]> err.no Git - linux-2.6/commitdiff
[PATCH] proc: optimize proc_check_dentry_visible
authorEric W. Biederman <ebiederm@xmission.com>
Mon, 26 Jun 2006 07:25:57 +0000 (00:25 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 26 Jun 2006 16:58:26 +0000 (09:58 -0700)
The code doesn't need to sleep to when making this check so I can just do the
comparison and not worry about the reference counts.

TODO: While looking at this I realized that my original cleanup did not push
the permission check far enough down into the stack.  The call of
proc_check_dentry_visible needs to move out of the generic proc
readlink/follow link code and into the individual get_link instances.
Otherwise the shared resources checks are not quite correct (shared
files_struct does not require a shared fs_struct), and there are races with
unshare.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/proc/base.c

index c7f855441573b907484ac33edf4d6703e86c7f66..f0db7f616ac3993bf6c594e2c1b9b301635d8822 100644 (file)
@@ -1074,24 +1074,27 @@ static int proc_check_dentry_visible(struct inode *inode,
         * namespace, or are simply process local (like pipes).
         */
        struct task_struct *task;
-       struct files_struct *task_files, *files;
        int error = -EACCES;
 
        /* See if the the two tasks share a commone set of
         * file descriptors.  If so everything is visible.
         */
-       task = get_proc_task(inode);
-       if (!task)
-               goto out;
-       files = get_files_struct(current);
-       task_files = get_files_struct(task);
-       if (files && task_files && (files == task_files))
-               error = 0;
-       if (task_files)
-               put_files_struct(task_files);
-       if (files)
-               put_files_struct(files);
-       put_task_struct(task);
+       rcu_read_lock();
+       task = tref_task(proc_tref(inode));
+       if (task) {
+               struct files_struct *task_files, *files;
+               /* This test answeres the question:
+                * Is there a point in time since we looked up the
+                * file descriptor where the two tasks share the
+                * same files struct?
+                */
+               rmb();
+               files = current->files;
+               task_files = task->files;
+               if (files && (files == task_files))
+                       error = 0;
+       }
+       rcu_read_unlock();
        if (!error)
                goto out;