From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 16:00:11
v6:
1) rebased on 3.7-rc1
v5:
1) Several define-dependent compile bugs fixed
2) IPC message copy test updated
3) A couple of minor fixes.
4) Qlogic driver update: rename of its internal SEM_SET define into SEM_INIT
(compile error).
v4:
1) If MSG_COPY flag is specified, then "mtype" is not a type, but message
number to copy.
2) MSG_SET_COPY logic for sys_msgctl() was removed.
v3:
1) Copy messages to user-space under spinlock was replaced by allocation of
dummy message before queue lock and then copy of desired message to the dummy
one instead of unlinking it from queue list.
I.e. the message queue copy logic was changed: messages can be retrived one by
one (instead of receiving of the whole list at once).
This patch set is aimed to provide additional functionality for all IPC
objects,
which is required for migration of these objects by user-space
checkpoint/restore utils (CRIU).
The main problem here was impossibility to set up object id. This patch set
solves the problem in two steps:
1) Makes it possible to create new object (shared memory, semaphores set or
messages queue) with ID, equal to passed key.
2) Makes it possible to change existent object key.
Another problem was to peek messages from queues without deleting them.
This was achived by introducing of new MSG_COPY flag for sys_msgrcv(). If
MSG_COPY flag is set, then msgtyp is interpreted as message number.
The following series implements...
---
Stanislav Kinsbursky (10):
ipc: remove forced assignment of selected message
ipc: "use key as id" functionality for resource get system call introduced
ipc: segment key change helper introduced
ipc: add new SHM_SET command for sys_shmctl() call
ipc: add new MSG_SET command for sys_msgctl() call
glge driver: rename internal SEM_SET macro to SEM_INIT
ipc: add new SEM_SET command for sys_semctl() call
IPC: message queue receive cleanup
IPC: message queue copy feature introduced
test: IPC message queue copy feture test
drivers/net/ethernet/qlogic/qlge/qlge.h | 4
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 16 +-
include/linux/msg.h | 5 -
include/uapi/linux/ipc.h | 1
include/uapi/linux/msg.h | 2
include/uapi/linux/sem.h | 1
include/uapi/linux/shm.h | 1
ipc/compat.c | 45 +++--
ipc/msg.c | 116 +++++++++---
ipc/msgutil.c | 38 ++++
ipc/sem.c | 14 +
ipc/shm.c | 17 +-
ipc/util.c | 69 +++++++
ipc/util.h | 6 +
security/selinux/hooks.c | 3
security/smack/smack_lsm.c | 3
tools/testing/selftests/ipc/Makefile | 28 +++
tools/testing/selftests/ipc/msgque.c | 251 ++++++++++++++++++++++++++
18 files changed, 548 insertions(+), 72 deletions(-)
create mode 100644 tools/testing/selftests/ipc/Makefile
create mode 100644 tools/testing/selftests/ipc/msgque.c
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:58:23
This is a cleanup patch. The assignment is redundant.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
ipc/msg.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:58:26
This patch introduces existent segment key changing infrastructure.
New function ipc_update_key() can be used change segment key, cuid, cgid
values. It checks for that new key is not used (except IPC_PRIVATE) prior to
set it on existent.
To make this possible, added copying of this fields from user-space in
__get_compat_ipc_perm() and __get_compat_ipc64_perm() functions. Also segment
search by key and lock were splitted into different functions, because
ipc_update_key() doesn't need to lock the segment during check that new key is
not used.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
ipc/compat.c | 6 ++++++
ipc/util.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
ipc/util.h | 2 ++
3 files changed, 56 insertions(+), 3 deletions(-)
@@ -388,7 +408,7 @@ retry:*anewentry+readlocksarenot"upgradable"*/down_write(&ids->rw_mutex);-ipcp=ipc_findkey(ids,params->key);+ipcp=ipc_findkey_locked(ids,params->key);if(ipcp==NULL){/* key not used */if(!(flg&IPC_CREAT))
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:58:29
New MSG_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/uapi/linux/msg.h | 1 +
ipc/compat.c | 1 +
ipc/msg.c | 13 +++++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 15 insertions(+), 2 deletions(-)
@@ -418,12 +421,13 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,structmsg_queue*msq;interr;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==MSG_SET){if(copy_msqid_from_user(&msqid64,buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&msg_ids(ns),msqid,cmd,+ipcp=ipcctl_pre_down(ns,&msg_ids(ns),msqid,+(cmd!=MSG_SET)?cmd:IPC_SET,&msqid64.msg_perm,msqid64.msg_qbytes);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -439,6 +443,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,freeque(ns,ipcp);gotoout_up;caseIPC_SET:+caseMSG_SET:if(msqid64.msg_qbytes>ns->msg_ctlmnb&&!capable(CAP_SYS_RESOURCE)){err=-EPERM;
@@ -451,6 +456,9 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,msq->q_qbytes=msqid64.msg_qbytes;+if(cmd==MSG_SET)+ipc_update_key(&msg_ids(ns),&msqid64.msg_perm,ipcp);+msq->q_ctime=get_seconds();/* sleeping receivers might be excluded by*stricterpermissions.
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:59:12
This patch introduces new IPC resource get request flag IPC_PRESET, which
should be interpreted as a request to try to allocate IPC slot with number,
starting from value resented by key. IOW, kernel will try
allocate new segment in specified slot.
Note: if desired slot is not emply, then next free slot will be used.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/uapi/linux/ipc.h | 1 +
ipc/msg.c | 4 +++-
ipc/sem.c | 4 +++-
ipc/shm.c | 4 +++-
ipc/util.c | 18 +++++++++++++++---
ipc/util.h | 3 ++-
6 files changed, 27 insertions(+), 7 deletions(-)
@@ -24,6 +24,7 @@ struct ipc_perm#define IPC_CREAT 00001000 /* create if key is nonexistent */#define IPC_EXCL 00002000 /* fail if key exists */#define IPC_NOWAIT 00004000 /* return error on wait */+#define IPC_PRESET 00040000 /* use key as id *//* these fields are used by the DIPC package so the kernel as standardshouldavoidusingthemifpossible*/
@@ -92,9 +92,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header,#define IPC_SHM_IDS 2#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)+#define ipcid_to_seq(id) ((id) / SEQ_MULTIPLIER)/* must be called with ids->rw_mutex acquired for writing */-intipc_addid(structipc_ids*,structkern_ipc_perm*,int);+intipc_addid(structipc_ids*,structkern_ipc_perm*,int,int);/* must be called with ids->rw_mutex acquired for reading */intipc_get_maxid(structipc_ids*);
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:59:35
New SEM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/uapi/linux/sem.h | 1 +
ipc/compat.c | 1 +
ipc/sem.c | 10 ++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 12 insertions(+), 2 deletions(-)
@@ -290,6 +290,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)break;caseIPC_SET:+caseSEM_SET:if(version==IPC_64){err=get_compat_semid64_ds(&s64,compat_ptr(pad));}else{
@@ -1085,12 +1085,13 @@ static int semctl_down(struct ipc_namespace *ns, int semid,structsemid64_dssemid64;structkern_ipc_perm*ipcp;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==SEM_SET){if(copy_semid_from_user(&semid64,arg.buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&sem_ids(ns),semid,cmd,+ipcp=ipcctl_pre_down(ns,&sem_ids(ns),semid,+(cmd!=SEM_SET)?cmd:IPC_SET,&semid64.sem_perm,0);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -1105,6 +1106,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,caseIPC_RMID:freeary(ns,ipcp);gotoout_up;+caseSEM_SET:+err=ipc_update_key(&sem_ids(ns),&semid64.sem_perm,ipcp);+if(err)+break;caseIPC_SET:err=ipc_update_perm(&semid64.sem_perm,ipcp);if(err)
@@ -1152,6 +1157,7 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)returnerr;caseIPC_RMID:caseIPC_SET:+caseSEM_SET:err=semctl_down(ns,semid,cmd,version,arg);returnerr;default:
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 15:59:51
New SHM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/uapi/linux/shm.h | 1 +
ipc/compat.c | 1 +
ipc/shm.c | 13 +++++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 15 insertions(+), 2 deletions(-)
@@ -740,12 +743,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,structshmid_kernel*shp;interr;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==SHM_SET){if(copy_shmid_from_user(&shmid64,buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&shm_ids(ns),shmid,cmd,+ipcp=ipcctl_pre_down(ns,&shm_ids(ns),shmid,+(cmd!=SHM_SET)?cmd:IPC_SET,&shmid64.shm_perm,0);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -759,6 +763,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,caseIPC_RMID:do_shm_rmid(ns,ipcp);gotoout_up;+caseSHM_SET:+err=ipc_update_key(&shm_ids(ns),&shmid64.shm_perm,ipcp);+if(err)+break;caseIPC_SET:err=ipc_update_perm(&shmid64.shm_perm,ipcp);if(err)
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 16:00:21
This patch moves all message related manipulation into one function msg_fill().
Actually, two functions because of the compat one.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/linux/msg.h | 5 +++--
ipc/compat.c | 36 +++++++++++++++++++-----------------
ipc/msg.c | 44 +++++++++++++++++++++++---------------------
3 files changed, 45 insertions(+), 40 deletions(-)
@@ -341,13 +341,23 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)returndo_msgsnd(first,type,up->mtext,second,third);}+longcompat_do_msg_fill(void__user*dest,structmsg_msg*msg,size_tbufsz)+{+structcompat_msgbuf__user*msgp=dest;+size_tmsgsz;++if(put_user(msg->m_type,&msgp->mtype))+return-EFAULT;++msgsz=(bufsz>msg->m_ts)?msg->m_ts:bufsz;+if(store_msg(msgp->mtext,msg,msgsz))+return-EFAULT;+returnmsgsz;+}+longcompat_sys_msgrcv(intfirst,intsecond,intmsgtyp,intthird,intversion,void__user*uptr){-structcompat_msgbuf__user*up;-longtype;-interr;-if(first<0)return-EINVAL;if(second<0)
@@ -355,23 +365,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,if(!version){structcompat_ipc_kludgeipck;-err=-EINVAL;if(!uptr)-gotoout;-err=-EFAULT;+return-EINVAL;if(copy_from_user(&ipck,uptr,sizeof(ipck)))-gotoout;+return-EFAULT;uptr=compat_ptr(ipck.msgp);msgtyp=ipck.msgtyp;}-up=uptr;-err=do_msgrcv(first,&type,up->mtext,second,msgtyp,third);-if(err<0)-gotoout;-if(put_user(type,&up->mtype))-err=-EFAULT;-out:-returnerr;+returndo_msgrcv(first,uptr,second,msgtyp,third,compat_do_msg_fill);}#elselongcompat_sys_semctl(intsemid,intsemnum,intcmd,intarg)
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 16:00:48
This test can be used to check wheither kernel supports IPC message queue copy
and restore features (required by CRIU project).
---
tools/testing/selftests/ipc/Makefile | 28 ++++
tools/testing/selftests/ipc/msgque.c | 251 ++++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+), 0 deletions(-)
create mode 100644 tools/testing/selftests/ipc/Makefile
create mode 100644 tools/testing/selftests/ipc/msgque.c
@@ -0,0 +1,251 @@+#include<stdio.h>+#include<sys/types.h>+#include<sys/ipc.h>+#include<sys/msg.h>+#include<errno.h>+#include<string.h>+#include<stdlib.h>++#define MAX_MSG_SIZE 32++structmsg1{+intmsize;+longmtype;+charmtext[MAX_MSG_SIZE];+};++#define TEST_STRING "Test sysv5 msg"+#define MSG_TYPE 1++#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"+#define ANOTHER_MSG_TYPE 26538++#ifndef IPC_PRESET+#define IPC_PRESET 00040000+#endif++#ifndef MSG_COPY+#define MSG_COPY 040000+#endif++#ifndef MSG_SET+#define MSG_SET 13+#endif++#if defined (__GLIBC__) && __GLIBC__ >= 2+#define KEY __key+#else+#define KEY key+#endif++structmsgque_data{+intmsq_id;+intqbytes;+intkern_id;+intqnum;+intmode;+structmsg1*messages;+};++intrestore_queue(structmsgque_data*msgque)+{+structmsqid_dsds;+intid,i;++id=msgget(msgque->msq_id,+msgque->mode|IPC_CREAT|IPC_EXCL|IPC_PRESET);+if(id==-1){+printf("Failed to create queue\n");+return-errno;+}++if(id!=msgque->msq_id){+printf("Failed to preset id (%d instead of %d)\n",+id,msgque->msq_id);+return-EFAULT;+}++if(msgctl(id,MSG_STAT,&ds)<0){+printf("Failed to stat queue\n");+return-errno;+}++ds.msg_perm.KEY=msgque->msq_id;+ds.msg_qbytes=msgque->qbytes;+if(msgctl(id,MSG_SET,&ds)<0){+printf("Failed to update message key\n");+return-errno;+}++for(i=0;i<msgque->qnum;i++){+if(msgsnd(msgque->msq_id,&msgque->messages[i].mtype,msgque->messages[i].msize,IPC_NOWAIT)!=0){+printf("msgsnd failed (%m)\n");+return-errno;+};+}+return0;+}++intcheck_and_destroy_queue(structmsgque_data*msgque)+{+structmsg1message;+intcnt=0,ret;++while(1){+ret=msgrcv(msgque->msq_id,&message.mtype,MAX_MSG_SIZE,0,IPC_NOWAIT);+if(ret<0){+if(errno==ENOMSG)+break;+printf("Failed to read IPC message: %m\n");+ret=-errno;+gotoerr;+}+if(ret!=msgque->messages[cnt].msize){+printf("Wrong message size: %d (expected %d)\n",ret,msgque->messages[cnt].msize);+ret=-EINVAL;+gotoerr;+}+if(message.mtype!=msgque->messages[cnt].mtype){+printf("Wrong message type\n");+ret=-EINVAL;+gotoerr;+}+if(memcmp(message.mtext,msgque->messages[cnt].mtext,ret)){+printf("Wrong message content\n");+ret=-EINVAL;+gotoerr;+}+cnt++;+}++if(cnt!=msgque->qnum){+printf("Wrong message number\n");+ret=-EINVAL;+gotoerr;+}++ret=0;+err:+if(msgctl(msgque->msq_id,IPC_RMID,0)){+printf("Failed to destroy queue: %d\n",-errno);+return-errno;+}+returnret;+}++intdump_queue(structmsgque_data*msgque)+{+structmsqid_dsds;+inti,ret;++for(msgque->kern_id=0;msgque->kern_id<256;msgque->kern_id++){+ret=msgctl(msgque->kern_id,MSG_STAT,&ds);+if(ret<0){+if(errno==-EINVAL)+continue;+printf("Failed to get stats for IPC queue with id %d\n",msgque->kern_id);+return-errno;+}++if(ret==msgque->msq_id)+break;+}++msgque->messages=malloc(sizeof(structmsg1)*ds.msg_qnum);+if(msgque->messages==NULL){+printf("Failed to get stats for IPC queue\n");+return-ENOMEM;+}++msgque->qnum=ds.msg_qnum;+msgque->mode=ds.msg_perm.mode;+msgque->qbytes=ds.msg_qbytes;++for(i=0;i<msgque->qnum;i++){+ret=msgrcv(msgque->msq_id,&msgque->messages[i].mtype,MAX_MSG_SIZE,i,IPC_NOWAIT|MSG_COPY);+if(ret<0){+printf("Failed to copy IPC message: %m (%d)\n",errno);+return-errno;+}+msgque->messages[i].msize=ret;+}+return0;+}++intfill_msgque(structmsgque_data*msgque)+{+structmsg1msgbuf;++msgbuf.mtype=MSG_TYPE;+memcpy(msgbuf.mtext,TEST_STRING,sizeof(TEST_STRING));+if(msgsnd(msgque->msq_id,&msgbuf.mtype,sizeof(TEST_STRING),IPC_NOWAIT)!=0){+printf("First message send failed (%m)\n");+return-errno;+};++msgbuf.mtype=ANOTHER_MSG_TYPE;+memcpy(msgbuf.mtext,ANOTHER_TEST_STRING,sizeof(ANOTHER_TEST_STRING));+if(msgsnd(msgque->msq_id,&msgbuf.mtype,sizeof(ANOTHER_TEST_STRING),IPC_NOWAIT)!=0){+printf("Second message send failed (%m)\n");+return-errno;+};+return0;+}++intmain(intargc,char**argv)+{+key_tkey;+intmsg,pid,err;+structmsgque_datamsgque;++key=ftok(argv[0],822155650);+if(key==-1){+printf("Can't make key\n");+return-errno;+}++msgque.msq_id=msgget(key,IPC_CREAT|IPC_EXCL|0666);+if(msgque.msq_id==-1){+printf("Can't create queue\n");+gotoerr_out;+}++err=fill_msgque(&msgque);+if(err){+printf("Failed to fill queue\n");+gotoerr_destroy;+}++err=dump_queue(&msgque);+if(err){+printf("Failed to dump queue\n");+gotoerr_destroy;+}++err=check_and_destroy_queue(&msgque);+if(err){+printf("Failed to check and destroy queue\n");+gotoerr_out;+}++err=restore_queue(&msgque);+if(err){+printf("Failed to restore queue\n");+gotoerr_destroy;+}++err=check_and_destroy_queue(&msgque);+if(err){+printf("Failed to test queue\n");+gotoerr_out;+}+return0;++err_destroy:+if(msgctl(msgque.msq_id,IPC_RMID,0)){+printf("Failed to destroy queue: %d\n",-errno);+return-errno;+}+err_out:+returnerr;+}
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 16:01:46
This patch is required for checkpoint/restore in userspace.
IOW, c/r requires some way to get all pending IPC messages without deleting
them from the queue (checkpoint can fail and in this case tasks will be resumed,
so queue have to be valid).
To achive this, new operation flag MSG_COPY for sys_msgrcv() system call was
introduced. If this flag was specified, then mtype is interpreted as number of
the message to copy.
If MSG_COPY is set, then kernel will allocate dummy message with passed size,
and then use new copy_msg() helper function to copy desired message (instead of
unlinking it from the queue).
Notes:
1) Return -ENOSYS if MSG_COPY is specified, but CONFIG_CHECKPOINT_RESTORE is
not set.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/uapi/linux/msg.h | 1 +
ipc/msg.c | 50 ++++++++++++++++++++++++++++++++++++++++++++--
ipc/msgutil.c | 38 +++++++++++++++++++++++++++++++++++
ipc/util.h | 1 +
4 files changed, 88 insertions(+), 2 deletions(-)
@@ -11,6 +11,7 @@/* msgrcv options */#define MSG_NOERROR 010000 /* no error if message is too big */#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/+#define MSG_COPY 040000 /* copy (not remove) all queue messages *//* Obsolete, used only for backwards compatibility and libc5 compiles */structmsqid_ds{
From: Stanislav Kinsbursky <hidden> Date: 2012-10-15 16:02:05
The reason for shit patch is that SET_SET is desired to be a part of new part
of API of IPC sys_semctl() system call.
The name itself for IPC is quite natural, because all linux-specific commands
names for IPC system calls are originally created by replacing "IPC_" part by
"SEM_"("MSG_", "SHM_") part.
So, I'm hoping, that this change doesn't really matters for "QLogic qlge NIC
HBA Driver" developers, since it's just an internal define.
---
drivers/net/ethernet/qlogic/qlge/qlge.h | 4 ++--
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
From: Ben Hutchings <hidden> Date: 2012-10-15 18:28:21
On Mon, 2012-10-15 at 20:00 +0400, Stanislav Kinsbursky wrote:
The reason for shit patch is that SET_SET is desired to be a part of new part
of API of IPC sys_semctl() system call.
[...]
Two spelling errors above. :-)
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
From: Ben Hutchings <hidden> Date: 2012-10-15 19:00:36
On Mon, 2012-10-15 at 19:59 +0400, Stanislav Kinsbursky wrote:
New SHM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
[...]
quoted hunk
--- a/ipc/shm.c+++ b/ipc/shm.c
[...]
quoted hunk
@@ -759,6 +763,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, case IPC_RMID: do_shm_rmid(ns, ipcp); goto out_up;+ case SHM_SET:+ err = ipc_update_key(&shm_ids(ns), &shmid64.shm_perm, ipcp);+ if (err)+ break;
[...]
Please add /* fall through */ here, and in the similar cases in patches
5 and 7, to make clear that it's deliberate.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
From: Ben Hutchings <hidden> Date: 2012-10-15 20:03:32
On Mon, 2012-10-15 at 20:00 +0400, Stanislav Kinsbursky wrote:
quoted hunk
This patch moves all message related manipulation into one function msg_fill().
Actually, two functions because of the compat one.
Signed-off-by: Stanislav Kinsbursky <redacted>
---
include/linux/msg.h | 5 +++--
ipc/compat.c | 36 +++++++++++++++++++-----------------
ipc/msg.c | 44 +++++++++++++++++++++++---------------------
3 files changed, 45 insertions(+), 40 deletions(-)
[...]
That isn't even the right number of arguments now...
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
@@ -793,12 +793,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,msg=walk_msg;if(mode==SEARCH_LESSEQUAL&&walk_msg->m_type!=1){-msg=walk_msg;msgtyp=walk_msg->m_type-1;-}else{-msg=walk_msg;+}elsebreak;-}}tmp=tmp->next;}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
This patch introduces existent segment key changing infrastructure.
New function ipc_update_key() can be used change segment key, cuid, cgid
values. It checks for that new key is not used (except IPC_PRIVATE) prior to
set it on existent.
To make this possible, added copying of this fields from user-space in
__get_compat_ipc_perm() and __get_compat_ipc64_perm() functions. Also segment
search by key and lock were splitted into different functions, because
ipc_update_key() doesn't need to lock the segment during check that new key is
not used.
Signed-off-by: Stanislav Kinsbursky <redacted>
@@ -388,7 +408,7 @@ retry:*anewentry+readlocksarenot"upgradable"*/down_write(&ids->rw_mutex);-ipcp=ipc_findkey(ids,params->key);+ipcp=ipc_findkey_locked(ids,params->key);if(ipcp==NULL){/* key not used */if(!(flg&IPC_CREAT))
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
New SHM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
@@ -740,12 +743,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,structshmid_kernel*shp;interr;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==SHM_SET){if(copy_shmid_from_user(&shmid64,buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&shm_ids(ns),shmid,cmd,+ipcp=ipcctl_pre_down(ns,&shm_ids(ns),shmid,+(cmd!=SHM_SET)?cmd:IPC_SET,&shmid64.shm_perm,0);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -759,6 +763,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,caseIPC_RMID:do_shm_rmid(ns,ipcp);gotoout_up;+caseSHM_SET:+err=ipc_update_key(&shm_ids(ns),&shmid64.shm_perm,ipcp);+if(err)+break;caseIPC_SET:err=ipc_update_perm(&shmid64.shm_perm,ipcp);if(err)
@@ -2121,6 +2121,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)may=MAY_READ;break;caseIPC_SET:+caseSHM_SET:caseSHM_LOCK:caseSHM_UNLOCK:caseIPC_RMID:--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
New MSG_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
@@ -418,12 +421,13 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,structmsg_queue*msq;interr;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==MSG_SET){if(copy_msqid_from_user(&msqid64,buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&msg_ids(ns),msqid,cmd,+ipcp=ipcctl_pre_down(ns,&msg_ids(ns),msqid,+(cmd!=MSG_SET)?cmd:IPC_SET,&msqid64.msg_perm,msqid64.msg_qbytes);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -439,6 +443,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,freeque(ns,ipcp);gotoout_up;caseIPC_SET:+caseMSG_SET:if(msqid64.msg_qbytes>ns->msg_ctlmnb&&!capable(CAP_SYS_RESOURCE)){err=-EPERM;
@@ -451,6 +456,9 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,msq->q_qbytes=msqid64.msg_qbytes;+if(cmd==MSG_SET)+ipc_update_key(&msg_ids(ns),&msqid64.msg_perm,ipcp);+msq->q_ctime=get_seconds();/* sleeping receivers might be excluded by*stricterpermissions.
@@ -2374,6 +2374,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)may=MAY_READ;break;caseIPC_SET:+caseMSG_SET:caseIPC_RMID:may=MAY_READWRITE;break;--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
The reason for shit patch is that SET_SET is desired to be a part of new part
of API of IPC sys_semctl() system call.
The name itself for IPC is quite natural, because all linux-specific commands
names for IPC system calls are originally created by replacing "IPC_" part by
"SEM_"("MSG_", "SHM_") part.
So, I'm hoping, that this change doesn't really matters for "QLogic qlge NIC
Can't speak for the driver maintainer, but it does look sane.
Acked-by: Serge E. Hallyn <redacted>
quoted hunk
HBA Driver" developers, since it's just an internal define.
---
drivers/net/ethernet/qlogic/qlge/qlge.h | 4 ++--
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
New SEM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <redacted>
@@ -290,6 +290,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)break;caseIPC_SET:+caseSEM_SET:if(version==IPC_64){err=get_compat_semid64_ds(&s64,compat_ptr(pad));}else{
@@ -1085,12 +1085,13 @@ static int semctl_down(struct ipc_namespace *ns, int semid,structsemid64_dssemid64;structkern_ipc_perm*ipcp;-if(cmd==IPC_SET){+if(cmd==IPC_SET||cmd==SEM_SET){if(copy_semid_from_user(&semid64,arg.buf,version))return-EFAULT;}-ipcp=ipcctl_pre_down(ns,&sem_ids(ns),semid,cmd,+ipcp=ipcctl_pre_down(ns,&sem_ids(ns),semid,+(cmd!=SEM_SET)?cmd:IPC_SET,&semid64.sem_perm,0);if(IS_ERR(ipcp))returnPTR_ERR(ipcp);
@@ -1105,6 +1106,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,caseIPC_RMID:freeary(ns,ipcp);gotoout_up;+caseSEM_SET:+err=ipc_update_key(&sem_ids(ns),&semid64.sem_perm,ipcp);+if(err)+break;caseIPC_SET:err=ipc_update_perm(&semid64.sem_perm,ipcp);if(err)
@@ -1152,6 +1157,7 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)returnerr;caseIPC_RMID:caseIPC_SET:+caseSEM_SET:err=semctl_down(ns,semid,cmd,version,arg);returnerr;default:
@@ -2253,6 +2253,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)caseSETALL:caseIPC_RMID:caseIPC_SET:+caseSEM_SET:may=MAY_READWRITE;break;caseIPC_INFO:--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoting Stanislav Kinsbursky (skinsbursky@parallels.com):
This patch is required for checkpoint/restore in userspace.
IOW, c/r requires some way to get all pending IPC messages without deleting
them from the queue (checkpoint can fail and in this case tasks will be resumed,
so queue have to be valid).
To achive this, new operation flag MSG_COPY for sys_msgrcv() system call was
introduced. If this flag was specified, then mtype is interpreted as number of
the message to copy.
If MSG_COPY is set, then kernel will allocate dummy message with passed size,
and then use new copy_msg() helper function to copy desired message (instead of
unlinking it from the queue).
Notes:
1) Return -ENOSYS if MSG_COPY is specified, but CONFIG_CHECKPOINT_RESTORE is
not set.
How much could it clean things up if a new ipc/cr.c contained
#ifdef CONFIG_CHECKPOINT_RESTORE
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
...
}
#else
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
return -ENOSYS;
}
#endif
and you went on from there to try to remove all the new #ifdefs from the
existing files?
@@ -11,6 +11,7 @@/* msgrcv options */#define MSG_NOERROR 010000 /* no error if message is too big */#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/+#define MSG_COPY 040000 /* copy (not remove) all queue messages *//* Obsolete, used only for backwards compatibility and libc5 compiles */structmsqid_ds{
@@ -142,6 +142,7 @@ int ipc_parse_version (int *cmd);externvoidfree_msg(structmsg_msg*msg);externstructmsg_msg*load_msg(constvoid__user*src,intlen);+externstructmsg_msg*copy_msg(structmsg_msg*src,structmsg_msg*dst);externintstore_msg(void__user*dest,structmsg_msg*msg,intlen);externvoidrecompute_msgmni(structipc_namespace*);--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html