2012-02-09 18:01:49

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

This patch set aimed to provide additional functionality for all IPC objects,
which is required for migration these objects by user-space checkpoint/restore
utils.
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.

The following series consists of:

---

Stanislav Kinsbursky (5):
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
ipc: add new SEM_SET command for sys_semctl() call


include/linux/ipc.h | 1 +
include/linux/msg.h | 1 +
include/linux/sem.h | 1 +
include/linux/shm.h | 1 +
ipc/compat.c | 9 +++++++
ipc/msg.c | 14 +++++++++-
ipc/sem.c | 11 +++++++-
ipc/shm.c | 14 +++++++++-
ipc/util.c | 59 +++++++++++++++++++++++++++++++++++++++++---
ipc/util.h | 3 ++
security/selinux/hooks.c | 3 ++
security/smack/smack_lsm.c | 3 ++
12 files changed, 110 insertions(+), 10 deletions(-)


2012-02-09 18:01:51

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 2/5] ipc: segment key change helper introduced

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 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 <[email protected]>

---
ipc/compat.c | 6 ++++++
ipc/util.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
ipc/util.h | 2 ++
3 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/ipc/compat.c b/ipc/compat.c
index 845a287..43f3596 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -138,6 +138,9 @@ static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
err = __get_user(p64->uid, &up64->uid);
err |= __get_user(p64->gid, &up64->gid);
err |= __get_user(p64->mode, &up64->mode);
+ err |= __get_user(p64->cuid, &up64->cuid);
+ err |= __get_user(p64->cgid, &up64->cgid);
+ err |= __get_user(p64->key, &up64->key);
return err;
}

@@ -149,6 +152,9 @@ static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
err = __get_user(p->uid, &up->uid);
err |= __get_user(p->gid, &up->gid);
err |= __get_user(p->mode, &up->mode);
+ err |= __get_user(p->cuid, &up->cuid);
+ err |= __get_user(p->cgid, &up->cgid);
+ err |= __get_user(p->key, &up->key);
return err;
}

diff --git a/ipc/util.c b/ipc/util.c
index ac9c6a9..7b1a2d8 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -173,7 +173,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
* @key: The key to find
*
* Requires ipc_ids.rw_mutex locked.
- * Returns the LOCKED pointer to the ipc structure if found or NULL
+ * Returns the UNLOCKED pointer to the ipc structure if found or NULL
* if not.
* If key is found ipc points to the owning ipc structure
*/
@@ -195,7 +195,6 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
continue;
}

- ipc_lock_by_ptr(ipc);
return ipc;
}

@@ -203,6 +202,27 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
}

/**
+ * ipc_findkey_locked - find and lock a key in an ipc identifier set
+ * @ids: Identifier set
+ * @key: The key to find
+ *
+ * Requires ipc_ids.rw_mutex locked.
+ * Returns the LOCKED pointer to the ipc structure if found or NULL
+ * if not.
+ * If key is found ipc points to the owning ipc structure
+ */
+
+static struct kern_ipc_perm *ipc_findkey_locked(struct ipc_ids *ids, key_t key)
+{
+ struct kern_ipc_perm *ipc;
+
+ ipc = ipc_findkey(ids, key);
+ if (ipc)
+ ipc_lock_by_ptr(ipc);
+ return ipc;
+}
+
+/**
* ipc_get_maxid - get the last assigned id
* @ids: IPC identifier set
*
@@ -382,7 +402,7 @@ retry:
* a new entry + read locks are not "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))
@@ -749,6 +769,31 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
}

/**
+ * ipc_update_key - update the key of an IPC.
+ * @in: the permission given as input.
+ * @out: the permission of the ipc to set.
+ *
+ * Common routine called by sys_shmctl(), sys_semctl(). sys_msgctl().
+ */
+int ipc_update_key(struct ipc_ids *ids, struct ipc64_perm *in,
+ struct kern_ipc_perm *out)
+{
+
+ if (out->key != in->key) {
+ /*
+ * Check for existent segment with the same key.
+ * Note: ipc_ids.rw_mutex is taken for write already.
+ */
+ if (ipc_findkey(ids, in->key))
+ return -EEXIST;
+ }
+ out->cuid = in->cuid;
+ out->cgid = in->cgid;
+ out->key = in->key;
+ return 0;
+}
+
+/**
* ipc_update_perm - update the permissions of an IPC.
* @in: the permission given as input.
* @out: the permission of the ipc to set.
diff --git a/ipc/util.h b/ipc/util.h
index 5f04b02..2bc6a9a 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -126,6 +126,8 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);

void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
+int ipc_update_key(struct ipc_ids *ids, struct ipc64_perm *in,
+ struct kern_ipc_perm *out);
void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
struct ipc_ids *ids, int id, int cmd,

2012-02-09 18:01:58

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 3/5] ipc: add new SHM_SET command for sys_shmctl() call

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 <[email protected]>

---
include/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(-)

diff --git a/include/linux/shm.h b/include/linux/shm.h
index 92808b8..6fc5447 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -63,6 +63,7 @@ struct shmid_ds {
/* ipcs ctl commands */
#define SHM_STAT 13
#define SHM_INFO 14
+#define SHM_SET 15

/* Obsolete, used only for backwards compatibility */
struct shminfo {
diff --git a/ipc/compat.c b/ipc/compat.c
index 43f3596..fc378d9 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -630,6 +630,7 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)


case IPC_SET:
+ case SHM_SET:
if (version == IPC_64) {
err = get_compat_shmid64_ds(&s64, uptr);
} else {
diff --git a/ipc/shm.c b/ipc/shm.c
index 67ed2e2..20fe8f5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -623,6 +623,9 @@ copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
out->shm_perm.uid = tbuf_old.shm_perm.uid;
out->shm_perm.gid = tbuf_old.shm_perm.gid;
out->shm_perm.mode = tbuf_old.shm_perm.mode;
+ out->shm_perm.cuid = tbuf_old.shm_perm.cuid;
+ out->shm_perm.cgid = tbuf_old.shm_perm.cgid;
+ out->shm_perm.key = tbuf_old.shm_perm.key;

return 0;
}
@@ -727,12 +730,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
struct shmid_kernel *shp;
int err;

- 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) ? : IPC_SET,
&shmid64.shm_perm, 0);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -746,6 +750,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;
case IPC_SET:
ipc_update_perm(&shmid64.shm_perm, ipcp);
shp->shm_ctim = get_seconds();
@@ -923,6 +931,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
}
case IPC_RMID:
case IPC_SET:
+ case SHM_SET:
err = shmctl_down(ns, shmid, cmd, buf, version);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6a3683e..1728a5e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4991,6 +4991,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
perms = SHM__GETATTR | SHM__ASSOCIATE;
break;
case IPC_SET:
+ case SHM_SET:
perms = SHM__SETATTR;
break;
case SHM_LOCK:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e8af5b0b..4765659 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2197,6 +2197,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
may = MAY_READ;
break;
case IPC_SET:
+ case SHM_SET:
case SHM_LOCK:
case SHM_UNLOCK:
case IPC_RMID:

2012-02-09 18:02:12

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 5/5] ipc: add new SEM_SET command for sys_semctl() call

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 <[email protected]>

---
include/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(-)

diff --git a/include/linux/sem.h b/include/linux/sem.h
index 10d6b22..c74b9b5 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -18,6 +18,7 @@
/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_INFO 19
+#define SEM_SET 20

/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct semid_ds {
diff --git a/ipc/compat.c b/ipc/compat.c
index 20d639e..b828244 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -289,6 +289,7 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
break;

case IPC_SET:
+ case SEM_SET:
if (version == IPC_64) {
err = get_compat_semid64_ds(&s64, compat_ptr(pad));
} else {
diff --git a/ipc/sem.c b/ipc/sem.c
index 845c912..d9024d5 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1084,12 +1084,13 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
struct semid64_ds semid64;
struct kern_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) ? : IPC_SET,
&semid64.sem_perm, 0);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -1104,6 +1105,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
case IPC_RMID:
freeary(ns, ipcp);
goto out_up;
+ case SEM_SET:
+ err = ipc_update_key(&sem_ids(ns), &semid64.sem_perm, ipcp);
+ if (err)
+ break;
case IPC_SET:
ipc_update_perm(&semid64.sem_perm, ipcp);
sma->sem_ctime = get_seconds();
@@ -1149,6 +1154,7 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
return err;
case IPC_RMID:
case IPC_SET:
+ case SEM_SET:
err = semctl_down(ns, semid, cmd, version, arg);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1428f8d..3bea7e3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5097,6 +5097,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
perms = SEM__DESTROY;
break;
case IPC_SET:
+ case SEM_SET:
perms = SEM__SETATTR;
break;
case IPC_STAT:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 143c053..a4a5d0c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2329,6 +2329,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
case SETALL:
case IPC_RMID:
case IPC_SET:
+ case SEM_SET:
may = MAY_READWRITE;
break;
case IPC_INFO:

2012-02-09 18:02:09

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 4/5] ipc: add new MSG_SET command for sys_msgctl() call

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 <[email protected]>

---
include/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(-)

diff --git a/include/linux/msg.h b/include/linux/msg.h
index 56abf15..6689e73 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -6,6 +6,7 @@
/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_INFO 12
+#define MSG_SET 13

/* msgrcv options */
#define MSG_NOERROR 010000 /* no error if message is too big */
diff --git a/ipc/compat.c b/ipc/compat.c
index fc378d9..20d639e 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -439,6 +439,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
break;

case IPC_SET:
+ case MSG_SET:
if (version == IPC_64) {
err = get_compat_msqid64(&m64, uptr);
} else {
diff --git a/ipc/msg.c b/ipc/msg.c
index fc98723..303362b 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -391,6 +391,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
out->msg_perm.uid = tbuf_old.msg_perm.uid;
out->msg_perm.gid = tbuf_old.msg_perm.gid;
out->msg_perm.mode = tbuf_old.msg_perm.mode;
+ out->msg_perm.cuid = tbuf_old.msg_perm.cuid;
+ out->msg_perm.cgid = tbuf_old.msg_perm.cgid;
+ out->msg_perm.key = tbuf_old.msg_perm.key;

if (tbuf_old.msg_qbytes == 0)
out->msg_qbytes = tbuf_old.msg_lqbytes;
@@ -417,12 +420,13 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
struct msg_queue *msq;
int err;

- 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) ? : IPC_SET,
&msqid64.msg_perm, msqid64.msg_qbytes);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -438,6 +442,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
freeque(ns, ipcp);
goto out_up;
case IPC_SET:
+ case MSG_SET:
if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
!capable(CAP_SYS_RESOURCE)) {
err = -EPERM;
@@ -446,6 +451,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);
+
ipc_update_perm(&msqid64.msg_perm, ipcp);
msq->q_ctime = get_seconds();
/* sleeping receivers might be excluded by
@@ -565,6 +573,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
}
case IPC_SET:
case IPC_RMID:
+ case MSG_SET:
err = msgctl_down(ns, msqid, cmd, buf, version);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1728a5e..1428f8d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4849,6 +4849,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
break;
case IPC_SET:
+ case MSG_SET:
perms = MSGQ__SETATTR;
break;
case IPC_RMID:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 4765659..143c053 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2450,6 +2450,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
may = MAY_READ;
break;
case IPC_SET:
+ case MSG_SET:
case IPC_RMID:
may = MAY_READWRITE;
break;

2012-02-09 18:01:50

by Stanislav Kinsbursky

[permalink] [raw]
Subject: [PATCH 1/5] ipc: "use key as id" functionality for resource get system call introduced

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. If slot is not emply, them -EEXIST
returned.

Signed-off-by: Stanislav Kinsbursky <[email protected]>

---
include/linux/ipc.h | 1 +
ipc/msg.c | 1 +
ipc/sem.c | 1 +
ipc/shm.c | 1 +
ipc/util.c | 8 +++++++-
ipc/util.h | 1 +
6 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 30e8161..d7e5632 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -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 standard
should avoid using them if possible */
diff --git a/ipc/msg.c b/ipc/msg.c
index 7385de2..fc98723 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -190,6 +190,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)

msq->q_perm.mode = msgflg & S_IRWXUGO;
msq->q_perm.key = key;
+ msq->q_perm.id = (msgflg & IPC_PRESET) ? key : 0;

msq->q_perm.security = NULL;
retval = security_msg_queue_alloc(msq);
diff --git a/ipc/sem.c b/ipc/sem.c
index 5215a81..845c912 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -306,6 +306,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)

sma->sem_perm.mode = (semflg & S_IRWXUGO);
sma->sem_perm.key = key;
+ sma->sem_perm.id = (semflg & IPC_PRESET) ? key : 0;

sma->sem_perm.security = NULL;
retval = security_sem_alloc(sma);
diff --git a/ipc/shm.c b/ipc/shm.c
index b76be5b..67ed2e2 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -468,6 +468,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)

shp->shm_perm.key = key;
shp->shm_perm.mode = (shmflg & S_IRWXUGO);
+ shp->shm_perm.id = (shmflg & IPC_PRESET) ? key : 0;
shp->mlock_user = NULL;

shp->shm_perm.security = NULL;
diff --git a/ipc/util.c b/ipc/util.c
index 75261a3..ac9c6a9 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -264,7 +264,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
rcu_read_lock();
spin_lock(&new->lock);

- err = idr_get_new(&ids->ipcs_idr, new, &id);
+ err = idr_get_new_above(&ids->ipcs_idr, new,
+ ipcid_to_idx(new->id), &id);
if (err) {
spin_unlock(&new->lock);
rcu_read_unlock();
@@ -277,6 +278,11 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
new->cuid = new->uid = euid;
new->gid = new->cgid = egid;

+ if (new->id && ipcid_to_idx(new->id) == id) {
+ new->seq = ipcid_to_seq(new->id);
+ return id;
+ }
+
new->seq = ids->seq++;
if(ids->seq > ids->seq_max)
ids->seq = 0;
diff --git a/ipc/util.h b/ipc/util.h
index 6f5c20b..5f04b02 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -92,6 +92,7 @@ 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 */
int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);

2012-02-10 18:29:19

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
> This patch set aimed to provide additional functionality for all IPC objects,
> which is required for migration these objects by user-space checkpoint/restore
> utils.
> 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.

Is there any chance you might include the LSM data as well?

>
> The following series consists of:
>
> ---
>
> Stanislav Kinsbursky (5):
> 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
> ipc: add new SEM_SET command for sys_semctl() call
>
>
> include/linux/ipc.h | 1 +
> include/linux/msg.h | 1 +
> include/linux/sem.h | 1 +
> include/linux/shm.h | 1 +
> ipc/compat.c | 9 +++++++
> ipc/msg.c | 14 +++++++++-
> ipc/sem.c | 11 +++++++-
> ipc/shm.c | 14 +++++++++-
> ipc/util.c | 59 +++++++++++++++++++++++++++++++++++++++++---
> ipc/util.h | 3 ++
> security/selinux/hooks.c | 3 ++
> security/smack/smack_lsm.c | 3 ++
> 12 files changed, 110 insertions(+), 10 deletions(-)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2012-02-13 11:04:37

by Stanislav Kinsbursky

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

10.02.2012 22:29, Casey Schaufler пишет:
> On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
>> This patch set aimed to provide additional functionality for all IPC objects,
>> which is required for migration these objects by user-space checkpoint/restore
>> utils.
>> 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.
>
> Is there any chance you might include the LSM data as well?
>

Sorry, but I don't understand your question.
What is this "LSM"? Linux Shared Memory? If yes, and you mean SYSV IPC SHM, then
where do you want to include it?

--
Best regards,
Stanislav Kinsbursky

2012-02-13 16:11:51

by Serge Hallyn

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

Quoting Stanislav Kinsbursky ([email protected]):
> 10.02.2012 22:29, Casey Schaufler пишет:
> >On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
> >>This patch set aimed to provide additional functionality for all IPC objects,
> >>which is required for migration these objects by user-space checkpoint/restore
> >>utils.
> >>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.
> >
> >Is there any chance you might include the LSM data as well?
> >
>
> Sorry, but I don't understand your question.
> What is this "LSM"? Linux Shared Memory? If yes, and you mean SYSV
> IPC SHM, then where do you want to include it?

He means linux security modules. (see include/linux/security.h)

2012-02-13 16:49:10

by Stanislav Kinsbursky

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

13.02.2012 20:11, Serge Hallyn пишет:
> Quoting Stanislav Kinsbursky ([email protected]):
>> 10.02.2012 22:29, Casey Schaufler пишет:
>>> On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
>>>> This patch set aimed to provide additional functionality for all IPC objects,
>>>> which is required for migration these objects by user-space checkpoint/restore
>>>> utils.
>>>> 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.
>>>
>>> Is there any chance you might include the LSM data as well?
>>>
>>
>> Sorry, but I don't understand your question.
>> What is this "LSM"? Linux Shared Memory? If yes, and you mean SYSV
>> IPC SHM, then where do you want to include it?
>
> He means linux security modules. (see include/linux/security.h)

Ok, thanks for explanation.
Casey, what exactly you are asking about? Am I going to implement
security_*_set() functions?

--
Best regards,
Stanislav Kinsbursky

2012-02-13 17:39:57

by Casey Schaufler

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

On 2/13/2012 8:48 AM, Stanislav Kinsbursky wrote:
> 13.02.2012 20:11, Serge Hallyn пишет:
>> Quoting Stanislav Kinsbursky ([email protected]):
>>> 10.02.2012 22:29, Casey Schaufler пишет:
>>>> On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
>>>>> This patch set aimed to provide additional functionality for all
>>>>> IPC objects,
>>>>> which is required for migration these objects by user-space
>>>>> checkpoint/restore
>>>>> utils.
>>>>> 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.
>>>>
>>>> Is there any chance you might include the LSM data as well?
>>>>
>>>
>>> Sorry, but I don't understand your question.
>>> What is this "LSM"? Linux Shared Memory? If yes, and you mean SYSV
>>> IPC SHM, then where do you want to include it?
>>
>> He means linux security modules. (see include/linux/security.h)
>
> Ok, thanks for explanation.
> Casey, what exactly you are asking about? Am I going to implement
> security_*_set() functions?
>

The IPC objects are queer beasts in that they are both
volatile and persistent. If you restart a process that
uses IPC objects they may have to be recreated, which is
what your code is doing. If the system is using an LSM
there may be information attached to the IPC object that
can not be derived from the process being restarted.

That's a roundabout way of saying yes, you may need to
implement security_sem_set and friends
security_{sem,shm,msg}_[ge]et(). The good news is that
I know of at least one other project that is looking
to implement those functions for unrelated reasons.

2012-02-14 11:34:06

by Stanislav Kinsbursky

[permalink] [raw]
Subject: Re: [PATCH 0/5] IPC: checkpoint/restore in userspace enhancements

13.02.2012 21:39, Casey Schaufler пишет:
> On 2/13/2012 8:48 AM, Stanislav Kinsbursky wrote:
>> 13.02.2012 20:11, Serge Hallyn пишет:
>>> Quoting Stanislav Kinsbursky ([email protected]):
>>>> 10.02.2012 22:29, Casey Schaufler пишет:
>>>>> On 2/9/2012 10:01 AM, Stanislav Kinsbursky wrote:
>>>>>> This patch set aimed to provide additional functionality for all
>>>>>> IPC objects,
>>>>>> which is required for migration these objects by user-space
>>>>>> checkpoint/restore
>>>>>> utils.
>>>>>> 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.
>>>>>
>>>>> Is there any chance you might include the LSM data as well?
>>>>>
>>>>
>>>> Sorry, but I don't understand your question.
>>>> What is this "LSM"? Linux Shared Memory? If yes, and you mean SYSV
>>>> IPC SHM, then where do you want to include it?
>>>
>>> He means linux security modules. (see include/linux/security.h)
>>
>> Ok, thanks for explanation.
>> Casey, what exactly you are asking about? Am I going to implement
>> security_*_set() functions?
>>
>
> The IPC objects are queer beasts in that they are both
> volatile and persistent. If you restart a process that
> uses IPC objects they may have to be recreated, which is
> what your code is doing. If the system is using an LSM
> there may be information attached to the IPC object that
> can not be derived from the process being restarted.
>

Hmmm. If I understood you right, you are taking about kernel_ipc_perm->security
data migration, which is not supported yet.
Am I right?
If yes, then, in general, it would be great to migrate security data some day.
It you feel, that new interfaces are not suitable for security migration and you
can give me an advice how to update them - then it would be great.

> That's a roundabout way of saying yes, you may need to
> implement security_sem_set and friends
> security_{sem,shm,msg}_[ge]et(). The good news is that
> I know of at least one other project that is looking
> to implement those functions for unrelated reasons.

What project?

--
Best regards,
Stanislav Kinsbursky