]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/sys.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[linux.git] / kernel / sys.c
index d1b2b8d934bb7c660674583b5bd09d28c9f22167..38509dc1f77b0916cc7633f6814d86549ea62a40 100644 (file)
@@ -2018,7 +2018,11 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
                        return error;
        }
 
-       down_write(&mm->mmap_sem);
+       /*
+        * arg_lock protects concurent updates but we still need mmap_sem for
+        * read to exclude races with sys_brk.
+        */
+       down_read(&mm->mmap_sem);
 
        /*
         * We don't validate if these members are pointing to
@@ -2032,6 +2036,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
         *    to any problem in kernel itself
         */
 
+       spin_lock(&mm->arg_lock);
        mm->start_code  = prctl_map.start_code;
        mm->end_code    = prctl_map.end_code;
        mm->start_data  = prctl_map.start_data;
@@ -2043,6 +2048,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
        mm->arg_end     = prctl_map.arg_end;
        mm->env_start   = prctl_map.env_start;
        mm->env_end     = prctl_map.env_end;
+       spin_unlock(&mm->arg_lock);
 
        /*
         * Note this update of @saved_auxv is lockless thus
@@ -2055,7 +2061,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
        if (prctl_map.auxv_size)
                memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
 
-       up_write(&mm->mmap_sem);
+       up_read(&mm->mmap_sem);
        return 0;
 }
 #endif /* CONFIG_CHECKPOINT_RESTORE */