summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/sem.c38
1 files changed, 16 insertions, 22 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 84c701fe5004..7836edb0cf96 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -617,8 +617,8 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
}
}
-static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
- int cmd, int version, union semun arg)
+static int semctl_nolock(struct ipc_namespace *ns, int semid,
+ int cmd, int version, union semun arg)
{
int err = -EINVAL;
struct sem_array *sma;
@@ -657,14 +657,23 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
return -EFAULT;
return (max_id < 0) ? 0: max_id;
}
+ case IPC_STAT:
case SEM_STAT:
{
struct semid64_ds tbuf;
int id;
- sma = sem_lock(ns, semid);
- if (IS_ERR(sma))
- return PTR_ERR(sma);
+ if (cmd == SEM_STAT) {
+ sma = sem_lock(ns, semid);
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
+ id = sma->sem_perm.id;
+ } else {
+ sma = sem_lock_check(ns, semid);
+ if (IS_ERR(sma))
+ return PTR_ERR(sma);
+ id = 0;
+ }
err = -EACCES;
if (ipcperms (&sma->sem_perm, S_IRUGO))
@@ -674,8 +683,6 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
if (err)
goto out_unlock;
- id = sma->sem_perm.id;
-
memset(&tbuf, 0, sizeof(tbuf));
kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
@@ -810,19 +817,6 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
err = 0;
goto out_unlock;
}
- case IPC_STAT:
- {
- struct semid64_ds tbuf;
- memset(&tbuf,0,sizeof(tbuf));
- kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
- tbuf.sem_otime = sma->sem_otime;
- tbuf.sem_ctime = sma->sem_ctime;
- tbuf.sem_nsems = sma->sem_nsems;
- sem_unlock(sma);
- if (copy_semid_to_user (arg.buf, &tbuf, version))
- return -EFAULT;
- return 0;
- }
/* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */
}
err = -EINVAL;
@@ -989,15 +983,15 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
switch(cmd) {
case IPC_INFO:
case SEM_INFO:
+ case IPC_STAT:
case SEM_STAT:
- err = semctl_nolock(ns,semid,semnum,cmd,version,arg);
+ err = semctl_nolock(ns, semid, cmd, version, arg);
return err;
case GETALL:
case GETVAL:
case GETPID:
case GETNCNT:
case GETZCNT:
- case IPC_STAT:
case SETVAL:
case SETALL:
err = semctl_main(ns,semid,semnum,cmd,version,arg);