proc: hold cred_guard_mutex in check_mem_permission()
authorStephen Wilson <wilsons@start.ca>
Sun, 13 Mar 2011 19:49:22 +0000 (15:49 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 23 Mar 2011 20:36:58 +0000 (16:36 -0400)
Avoid a potential race when task exec's and we get a new ->mm but check against
the old credentials in ptrace_may_access().

Holding of the mutex is implemented by factoring out the body of the code into a
helper function __check_mem_permission().  Performing this factorization now
simplifies upcoming changes and minimizes churn in the diff's.

Signed-off-by: Stephen Wilson <wilsons@start.ca>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/proc/base.c

index 9af49a3984f194effd876287f808ca349342d08f..013f116b3223a88a1b648a1857008c9466a612e5 100644 (file)
@@ -191,10 +191,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
        return result;
 }
 
-/*
- * Return zero if current may access user memory in @task, -error if not.
- */
-static int check_mem_permission(struct task_struct *task)
+static int __check_mem_permission(struct task_struct *task)
 {
        /*
         * A task can always look at itself, in case it chooses
@@ -222,6 +219,27 @@ static int check_mem_permission(struct task_struct *task)
        return -EPERM;
 }
 
+/*
+ * Return zero if current may access user memory in @task, -error if not.
+ */
+static int check_mem_permission(struct task_struct *task)
+{
+       int err;
+
+       /*
+        * Avoid racing if task exec's as we might get a new mm but validate
+        * against old credentials.
+        */
+       err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+       if (err)
+               return err;
+
+       err = __check_mem_permission(task);
+       mutex_unlock(&task->signal->cred_guard_mutex);
+
+       return err;
+}
+
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
        struct mm_struct *mm;