aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-06-26 03:25:57 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:26 -0400
commit5b0c1dd38b66e2dd0cf655aa845e341b50b93ddd (patch)
treee8d3341591958d9c3e11400a2f16287a6dd00c46 /fs
parent13b41b09491e5d75e8027dca1ee78f5e073bc4c0 (diff)
[PATCH] proc: optimize proc_check_dentry_visible
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/proc/base.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c7f855441573..f0db7f616ac3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1074,24 +1074,27 @@ static int proc_check_dentry_visible(struct inode *inode,
1074 * namespace, or are simply process local (like pipes). 1074 * namespace, or are simply process local (like pipes).
1075 */ 1075 */
1076 struct task_struct *task; 1076 struct task_struct *task;
1077 struct files_struct *task_files, *files;
1078 int error = -EACCES; 1077 int error = -EACCES;
1079 1078
1080 /* See if the the two tasks share a commone set of 1079 /* See if the the two tasks share a commone set of
1081 * file descriptors. If so everything is visible. 1080 * file descriptors. If so everything is visible.
1082 */ 1081 */
1083 task = get_proc_task(inode); 1082 rcu_read_lock();
1084 if (!task) 1083 task = tref_task(proc_tref(inode));
1085 goto out; 1084 if (task) {
1086 files = get_files_struct(current); 1085 struct files_struct *task_files, *files;
1087 task_files = get_files_struct(task); 1086 /* This test answeres the question:
1088 if (files && task_files && (files == task_files)) 1087 * Is there a point in time since we looked up the
1089 error = 0; 1088 * file descriptor where the two tasks share the
1090 if (task_files) 1089 * same files struct?
1091 put_files_struct(task_files); 1090 */
1092 if (files) 1091 rmb();
1093 put_files_struct(files); 1092 files = current->files;
1094 put_task_struct(task); 1093 task_files = task->files;
1094 if (files && (files == task_files))
1095 error = 0;
1096 }
1097 rcu_read_unlock();
1095 if (!error) 1098 if (!error)
1096 goto out; 1099 goto out;
1097 1100