|
@@ -820,29 +820,24 @@ out_up:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
|
|
+static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
|
|
|
+ int cmd, int version, void __user *buf)
|
|
|
{
|
|
|
+ int err;
|
|
|
struct shmid_kernel *shp;
|
|
|
- int err, version;
|
|
|
- struct ipc_namespace *ns;
|
|
|
|
|
|
- if (cmd < 0 || shmid < 0) {
|
|
|
- err = -EINVAL;
|
|
|
- goto out;
|
|
|
+ /* preliminary security checks for *_INFO */
|
|
|
+ if (cmd == IPC_INFO || cmd == SHM_INFO) {
|
|
|
+ err = security_shm_shmctl(NULL, cmd);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
- version = ipc_parse_version(&cmd);
|
|
|
- ns = current->nsproxy->ipc_ns;
|
|
|
-
|
|
|
- switch (cmd) { /* replace with proc interface ? */
|
|
|
+ switch (cmd) {
|
|
|
case IPC_INFO:
|
|
|
{
|
|
|
struct shminfo64 shminfo;
|
|
|
|
|
|
- err = security_shm_shmctl(NULL, cmd);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
memset(&shminfo, 0, sizeof(shminfo));
|
|
|
shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
|
|
|
shminfo.shmmax = ns->shm_ctlmax;
|
|
@@ -864,10 +859,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
|
|
{
|
|
|
struct shm_info shm_info;
|
|
|
|
|
|
- err = security_shm_shmctl(NULL, cmd);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
memset(&shm_info, 0, sizeof(shm_info));
|
|
|
down_read(&shm_ids(ns).rw_mutex);
|
|
|
shm_info.used_ids = shm_ids(ns).in_use;
|
|
@@ -928,6 +919,36 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
|
|
err = result;
|
|
|
goto out;
|
|
|
}
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+out_unlock:
|
|
|
+ shm_unlock(shp);
|
|
|
+out:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
|
|
|
+{
|
|
|
+ struct shmid_kernel *shp;
|
|
|
+ int err, version;
|
|
|
+ struct ipc_namespace *ns;
|
|
|
+
|
|
|
+ if (cmd < 0 || shmid < 0) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ version = ipc_parse_version(&cmd);
|
|
|
+ ns = current->nsproxy->ipc_ns;
|
|
|
+
|
|
|
+ switch (cmd) {
|
|
|
+ case IPC_INFO:
|
|
|
+ case SHM_INFO:
|
|
|
+ case SHM_STAT:
|
|
|
+ case IPC_STAT:
|
|
|
+ return shmctl_nolock(ns, shmid, cmd, version, buf);
|
|
|
case SHM_LOCK:
|
|
|
case SHM_UNLOCK:
|
|
|
{
|