]> Pileus Git - ~andy/linux/blobdiff - ipc/shm.c
ipc: introduce ipc_valid_object() helper to sort out IPC_RMID races
[~andy/linux] / ipc / shm.c
index 7a51443a51d6421bd2a02a66ec18db98f6796dd3..1bc68f115842d562a336644df154d9b3b62adc71 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -975,6 +975,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
                        goto out_unlock1;
 
                ipc_lock_object(&shp->shm_perm);
+
+               /* check if shm_destroy() is tearing down shp */
+               if (!ipc_valid_object(&shp->shm_perm)) {
+                       err = -EIDRM;
+                       goto out_unlock0;
+               }
+
                if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
                        kuid_t euid = current_euid();
                        if (!uid_eq(euid, shp->shm_perm.uid) &&
@@ -989,13 +996,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
                }
 
                shm_file = shp->shm_file;
-
-               /* check if shm_destroy() is tearing down shp */
-               if (shm_file == NULL) {
-                       err = -EIDRM;
-                       goto out_unlock0;
-               }
-
                if (is_file_hugepages(shm_file))
                        goto out_unlock0;
 
@@ -1116,7 +1116,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
        ipc_lock_object(&shp->shm_perm);
 
        /* check if shm_destroy() is tearing down shp */
-       if (shp->shm_file == NULL) {
+       if (!ipc_valid_object(&shp->shm_perm)) {
                ipc_unlock_object(&shp->shm_perm);
                err = -EIDRM;
                goto out_unlock;