diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-04-30 03:54:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:49 -0400 |
commit | 1dd768c0815334d2319d6377f0750ace075b6142 (patch) | |
tree | 13e3d42f3679ef1a50e276abdbeafccc9cfe1ed0 /kernel | |
parent | 7d8da0962eaee30b4a380ded177349bfbdd6ac46 (diff) |
pids: sys_getsid: fix unsafe *pid usage, fix possible 0 instead of -ESRCH
1. sys_getsid() needs rcu_read_lock() to derive the session _nr, even if
the task is current, otherwise we can race with another thread which
does sys_setsid().
2. The task can exit between find_task_by_vpid() and task_session_vnr(),
in that unlikely case sys_getsid() returns 0 instead of -ESRCH.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sys.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 5d0b44cd435c..ddd28e261f3a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1022,23 +1022,30 @@ asmlinkage long sys_getpgrp(void) | |||
1022 | 1022 | ||
1023 | asmlinkage long sys_getsid(pid_t pid) | 1023 | asmlinkage long sys_getsid(pid_t pid) |
1024 | { | 1024 | { |
1025 | struct task_struct *p; | ||
1026 | struct pid *sid; | ||
1027 | int retval; | ||
1028 | |||
1029 | rcu_read_lock(); | ||
1025 | if (!pid) | 1030 | if (!pid) |
1026 | return task_session_vnr(current); | 1031 | sid = task_session(current); |
1027 | else { | 1032 | else { |
1028 | int retval; | ||
1029 | struct task_struct *p; | ||
1030 | |||
1031 | rcu_read_lock(); | ||
1032 | p = find_task_by_vpid(pid); | ||
1033 | retval = -ESRCH; | 1033 | retval = -ESRCH; |
1034 | if (p) { | 1034 | p = find_task_by_vpid(pid); |
1035 | retval = security_task_getsid(p); | 1035 | if (!p) |
1036 | if (!retval) | 1036 | goto out; |
1037 | retval = task_session_vnr(p); | 1037 | sid = task_session(p); |
1038 | } | 1038 | if (!sid) |
1039 | rcu_read_unlock(); | 1039 | goto out; |
1040 | return retval; | 1040 | |
1041 | retval = security_task_getsid(p); | ||
1042 | if (retval) | ||
1043 | goto out; | ||
1041 | } | 1044 | } |
1045 | retval = pid_vnr(sid); | ||
1046 | out: | ||
1047 | rcu_read_unlock(); | ||
1048 | return retval; | ||
1042 | } | 1049 | } |
1043 | 1050 | ||
1044 | asmlinkage long sys_setsid(void) | 1051 | asmlinkage long sys_setsid(void) |