diff --git a/include/uapi/linux/sem.h b/include/uapi/linux/sem.h
index 9c3e745b0656..fde93f635660 100644
--- a/include/uapi/linux/sem.h
+++ b/include/uapi/linux/sem.h
@@ -19,6 +19,7 @@
/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_INFO 19
+#define SEM_STAT_ALL 20
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct semid_ds {diff --git a/ipc/sem.c b/ipc/sem.c
index a4af04979fd2..cb2737c7f1d6 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1190,14 +1190,14 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
memset(semid64, 0, sizeof(*semid64));
rcu_read_lock();
- if (cmd == SEM_STAT) {
+ if (cmd == SEM_STAT || cmd == SEM_STAT_ALL) {
sma = sem_obtain_object(ns, semid);
if (IS_ERR(sma)) {
err = PTR_ERR(sma);
goto out_unlock;
}
id = sma->sem_perm.id;
- } else {
+ } else { /* IPC_STAT */
sma = sem_obtain_object_check(ns, semid);
if (IS_ERR(sma)) {
err = PTR_ERR(sma);@@ -1205,9 +1205,14 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
}
}
- err = -EACCES;
- if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
- goto out_unlock;
+ /* see comment for SHM_STAT_ALL */
+ if (cmd == SEM_STAT_ALL)
+ audit_ipc_obj(&sma->sem_perm);
+ else {
+ err = -EACCES;
+ if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
+ goto out_unlock;
+ }
err = security_sem_semctl(sma, cmd);
if (err)@@ -1596,6 +1601,7 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
return semctl_info(ns, semid, cmd, p);
case IPC_STAT:
case SEM_STAT:
+ case SEM_STAT_ALL:
err = semctl_stat(ns, semid, cmd, &semid64);
if (err < 0)
return err;
@@ -1697,6 +1703,7 @@ COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
return semctl_info(ns, semid, cmd, p);
case IPC_STAT:
case SEM_STAT:
+ case SEM_STAT_ALL:
err = semctl_stat(ns, semid, cmd, &semid64);
if (err < 0)
return err;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index dc2a9a0f6ddf..aa965742bba9 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5847,6 +5847,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
break;
case IPC_STAT:
case SEM_STAT:
+ case SEM_STAT_ALL:
perms = SEM__GETATTR | SEM__ASSOCIATE;
break;
default:
--
2.13.6