shm: handle separate PID namespaces case
[~shefty/rdma-dev.git] / ipc / shm.c
index 3f5b14365f33e54408c5e89d3b15aacbc2c1435b..fdaf8be65b759369482bb5aaa477346bed8741af 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -239,7 +239,23 @@ static int shm_try_destroy_current(int id, void *p, void *data)
        if (IS_ERR(shp))
                return 0;
 
-       if (shp->shm_cprid != task_tgid_vnr(current)) {
+       if (shp->shm_creator != current) {
+               shm_unlock(shp);
+               return 0;
+       }
+
+       /*
+        * Mark it as orphaned to destroy the segment when
+        * kernel.shm_rmid_forced is changed.
+        * It is noop if the following shm_may_destroy() returns true.
+        */
+       shp->shm_creator = NULL;
+
+       /*
+        * Don't even try to destroy it.  If shm_rmid_forced=0 and IPC_RMID
+        * is not set, it shouldn't be deleted here.
+        */
+       if (!ns->shm_rmid_forced) {
                shm_unlock(shp);
                return 0;
        }
@@ -255,7 +271,6 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data)
 {
        struct ipc_namespace *ns = data;
        struct shmid_kernel *shp = shm_lock(ns, id);
-       struct task_struct *task;
 
        if (IS_ERR(shp))
                return 0;
@@ -263,11 +278,8 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data)
        /*
         * We want to destroy segments without users and with already
         * exit'ed originating process.
-        *
-        * XXX: the originating process may exist in another pid namespace.
         */
-       task = find_task_by_vpid(shp->shm_cprid);
-       if (task != NULL) {
+       if (shp->shm_creator != NULL) {
                shm_unlock(shp);
                return 0;
        }
@@ -295,7 +307,7 @@ void exit_shm(struct task_struct *task)
        if (!nsp)
                return;
        ns = nsp->ipc_ns;
-       if (!ns || !ns->shm_rmid_forced)
+       if (!ns)
                return;
 
        /* Destroy all already created segments, but not mapped yet */
@@ -494,6 +506,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_segsz = size;
        shp->shm_nattch = 0;
        shp->shm_file = file;
+       shp->shm_creator = current;
        /*
         * shmid gets reported as "inode#" in /proc/pid/maps.
         * proc-ps tools use this. Changing this will break them.