Skip to content

Commit

Permalink
ipc: unify the syscalls code
Browse files Browse the repository at this point in the history
This patch introduces a change into the sys_msgget(), sys_semget() and
sys_shmget() routines: they now share a common code, which is better for
maintainability.

Signed-off-by: Nadia Derbey <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Nadia Derbey authored and Linus Torvalds committed Oct 19, 2007
1 parent 7ca7e56 commit 7748dbf
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 139 deletions.
61 changes: 17 additions & 44 deletions ipc/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static struct ipc_ids init_msg_ids;
ipc_buildid(&msg_ids(ns), id, seq)

static void freeque(struct ipc_namespace *, struct msg_queue *);
static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
static int newque(struct ipc_namespace *, struct ipc_params *);
#ifdef CONFIG_PROC_FS
static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
#endif
Expand Down Expand Up @@ -144,10 +144,12 @@ static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
ipc_rmid(&msg_ids(ns), &s->q_perm);
}

static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
static int newque(struct ipc_namespace *ns, struct ipc_params *params)
{
struct msg_queue *msq;
int id, retval;
key_t key = params->key;
int msgflg = params->flg;

msq = ipc_rcu_alloc(sizeof(*msq));
if (!msq)
Expand Down Expand Up @@ -264,56 +266,27 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq)
ipc_rcu_putref(msq);
}

static inline int msg_security(void *msq, int msgflg)
{
return security_msg_queue_associate((struct msg_queue *) msq, msgflg);
}

asmlinkage long sys_msgget(key_t key, int msgflg)
{
struct msg_queue *msq;
int ret;
struct ipc_namespace *ns;
struct ipc_ops msg_ops;
struct ipc_params msg_params;

ns = current->nsproxy->ipc_ns;

ret = idr_pre_get(&msg_ids(ns).ipcs_idr, GFP_KERNEL);
msg_ops.getnew = newque;
msg_ops.associate = msg_security;
msg_ops.more_checks = NULL;

if (key == IPC_PRIVATE) {
if (!ret)
ret = -ENOMEM;
else {
mutex_lock(&msg_ids(ns).mutex);
ret = newque(ns, key, msgflg);
mutex_unlock(&msg_ids(ns).mutex);
}
} else {
mutex_lock(&msg_ids(ns).mutex);
msq = (struct msg_queue *) ipc_findkey(&msg_ids(ns), key);
if (msq == NULL) {
/* key not used */
if (!(msgflg & IPC_CREAT))
ret = -ENOENT;
else if (!ret)
ret = -ENOMEM;
else
ret = newque(ns, key, msgflg);
} else {
/* msq has been locked by ipc_findkey() */

if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)
ret = -EEXIST;
else {
if (ipcperms(&msq->q_perm, msgflg))
ret = -EACCES;
else {
ret = security_msg_queue_associate(
msq, msgflg);
if (!ret)
ret = msq->q_perm.id;
}
}
msg_unlock(msq);
}
mutex_unlock(&msg_ids(ns).mutex);
}
msg_params.key = key;
msg_params.flg = msgflg;

return ret;
return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
}

static inline unsigned long
Expand Down
76 changes: 29 additions & 47 deletions ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@

static struct ipc_ids init_sem_ids;

static int newary(struct ipc_namespace *, key_t, int, int);
static int newary(struct ipc_namespace *, struct ipc_params *);
static void freeary(struct ipc_namespace *, struct sem_array *);
#ifdef CONFIG_PROC_FS
static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
Expand Down Expand Up @@ -214,12 +214,15 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
*/
#define IN_WAKEUP 1

static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
static int newary(struct ipc_namespace *ns, struct ipc_params *params)
{
int id;
int retval;
struct sem_array *sma;
int size;
key_t key = params->key;
int nsems = params->u.nsems;
int semflg = params->flg;

if (!nsems)
return -EINVAL;
Expand Down Expand Up @@ -263,61 +266,40 @@ static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
return sma->sem_perm.id;
}

asmlinkage long sys_semget (key_t key, int nsems, int semflg)

static inline int sem_security(void *sma, int semflg)
{
return security_sem_associate((struct sem_array *) sma, semflg);
}

static inline int sem_more_checks(void *sma, struct ipc_params *params)
{
if (params->u.nsems > ((struct sem_array *)sma)->sem_nsems)
return -EINVAL;

return 0;
}

asmlinkage long sys_semget(key_t key, int nsems, int semflg)
{
int err;
struct sem_array *sma;
struct ipc_namespace *ns;
struct ipc_ops sem_ops;
struct ipc_params sem_params;

ns = current->nsproxy->ipc_ns;

if (nsems < 0 || nsems > ns->sc_semmsl)
return -EINVAL;

err = idr_pre_get(&sem_ids(ns).ipcs_idr, GFP_KERNEL);
sem_ops.getnew = newary;
sem_ops.associate = sem_security;
sem_ops.more_checks = sem_more_checks;

if (key == IPC_PRIVATE) {
if (!err)
err = -ENOMEM;
else {
mutex_lock(&sem_ids(ns).mutex);
err = newary(ns, key, nsems, semflg);
mutex_unlock(&sem_ids(ns).mutex);
}
} else {
mutex_lock(&sem_ids(ns).mutex);
sma = (struct sem_array *) ipc_findkey(&sem_ids(ns), key);
if (sma == NULL) {
/* key not used */
if (!(semflg & IPC_CREAT))
err = -ENOENT;
else if (!err)
err = -ENOMEM;
else
err = newary(ns, key, nsems, semflg);
} else {
/* sma has been locked by ipc_findkey() */

if (semflg & IPC_CREAT && semflg & IPC_EXCL)
err = -EEXIST;
else {
if (nsems > sma->sem_nsems)
err = -EINVAL;
else if (ipcperms(&sma->sem_perm, semflg))
err = -EACCES;
else {
err = security_sem_associate(sma,
semflg);
if (!err)
err = sma->sem_perm.id;
}
}
sem_unlock(sma);
}
mutex_unlock(&sem_ids(ns).mutex);
}
sem_params.key = key;
sem_params.flg = semflg;
sem_params.u.nsems = nsems;

return err;
return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
}

/* Manage the doubly linked list sma->sem_pending as a FIFO:
Expand Down
73 changes: 27 additions & 46 deletions ipc/shm.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ static struct ipc_ids init_shm_ids;
#define shm_buildid(ns, id, seq) \
ipc_buildid(&shm_ids(ns), id, seq)

static int newseg (struct ipc_namespace *ns, key_t key,
int shmflg, size_t size);
static int newseg(struct ipc_namespace *, struct ipc_params *);
static void shm_open(struct vm_area_struct *vma);
static void shm_close(struct vm_area_struct *vma);
static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
Expand Down Expand Up @@ -341,8 +340,11 @@ static struct vm_operations_struct shm_vm_ops = {
#endif
};

static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
{
key_t key = params->key;
int shmflg = params->flg;
size_t size = params->u.size;
int error;
struct shmid_kernel *shp;
int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
Expand Down Expand Up @@ -423,57 +425,36 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
return error;
}

static inline int shm_security(void *shp, int shmflg)
{
return security_shm_associate((struct shmid_kernel *) shp, shmflg);
}

static inline int shm_more_checks(void *shp, struct ipc_params *params)
{
if (((struct shmid_kernel *)shp)->shm_segsz < params->u.size)
return -EINVAL;

return 0;
}

asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
{
struct shmid_kernel *shp;
int err;
struct ipc_namespace *ns;
struct ipc_ops shm_ops;
struct ipc_params shm_params;

ns = current->nsproxy->ipc_ns;

err = idr_pre_get(&shm_ids(ns).ipcs_idr, GFP_KERNEL);
shm_ops.getnew = newseg;
shm_ops.associate = shm_security;
shm_ops.more_checks = shm_more_checks;

if (key == IPC_PRIVATE) {
if (!err)
err = -ENOMEM;
else {
mutex_lock(&shm_ids(ns).mutex);
err = newseg(ns, key, shmflg, size);
mutex_unlock(&shm_ids(ns).mutex);
}
} else {
mutex_lock(&shm_ids(ns).mutex);
shp = (struct shmid_kernel *) ipc_findkey(&shm_ids(ns), key);
if (shp == NULL) {
if (!(shmflg & IPC_CREAT))
err = -ENOENT;
else if (!err)
err = -ENOMEM;
else
err = newseg(ns, key, shmflg, size);
} else {
/* shp has been locked by ipc_findkey() */

if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL))
err = -EEXIST;
else {
if (shp->shm_segsz < size)
err = -EINVAL;
else if (ipcperms(&shp->shm_perm, shmflg))
err = -EACCES;
else {
err = security_shm_associate(shp,
shmflg);
if (!err)
err = shp->shm_perm.id;
}
}
shm_unlock(shp);
}
mutex_unlock(&shm_ids(ns).mutex);
}
shm_params.key = key;
shm_params.flg = shmflg;
shm_params.u.size = size;

return err;
return ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params);
}

static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
Expand Down
Loading

0 comments on commit 7748dbf

Please sign in to comment.