diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-06-26 03:25:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:26 -0400 |
commit | 5b0c1dd38b66e2dd0cf655aa845e341b50b93ddd (patch) | |
tree | e8d3341591958d9c3e11400a2f16287a6dd00c46 /fs/proc | |
parent | 13b41b09491e5d75e8027dca1ee78f5e073bc4c0 (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/proc')
-rw-r--r-- | fs/proc/base.c | 29 |
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 | ||