diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-04-30 03:54:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:49 -0400 |
commit | 12a3de0a965826096d8adc593bcf4392a7d5b459 (patch) | |
tree | 764d69c2973e67cb3ae58bec02e29cd616c40f90 /kernel/sys.c | |
parent | 1dd768c0815334d2319d6377f0750ace075b6142 (diff) |
pids: sys_getpgid: fix unsafe *pid usage, s/tasklist/rcu/
1. sys_getpgid() needs rcu_read_lock() to derive the pgrp _nr, even if
the task is current, otherwise we can race with another thread which
does sys_setpgid().
2. Use rcu_read_lock() instead of tasklist_lock when pid != 0, make sure
that we don't use the NULL pid if the task exits right after successful
find_task_by_vpid().
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/sys.c')
-rw-r--r-- | kernel/sys.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index ddd28e261f3a..895d2d4c9493 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -991,31 +991,37 @@ out: | |||
991 | 991 | ||
992 | asmlinkage long sys_getpgid(pid_t pid) | 992 | asmlinkage long sys_getpgid(pid_t pid) |
993 | { | 993 | { |
994 | struct task_struct *p; | ||
995 | struct pid *grp; | ||
996 | int retval; | ||
997 | |||
998 | rcu_read_lock(); | ||
994 | if (!pid) | 999 | if (!pid) |
995 | return task_pgrp_vnr(current); | 1000 | grp = task_pgrp(current); |
996 | else { | 1001 | else { |
997 | int retval; | ||
998 | struct task_struct *p; | ||
999 | |||
1000 | read_lock(&tasklist_lock); | ||
1001 | p = find_task_by_vpid(pid); | ||
1002 | retval = -ESRCH; | 1002 | retval = -ESRCH; |
1003 | if (p) { | 1003 | p = find_task_by_vpid(pid); |
1004 | retval = security_task_getpgid(p); | 1004 | if (!p) |
1005 | if (!retval) | 1005 | goto out; |
1006 | retval = task_pgrp_vnr(p); | 1006 | grp = task_pgrp(p); |
1007 | } | 1007 | if (!grp) |
1008 | read_unlock(&tasklist_lock); | 1008 | goto out; |
1009 | return retval; | 1009 | |
1010 | retval = security_task_getpgid(p); | ||
1011 | if (retval) | ||
1012 | goto out; | ||
1010 | } | 1013 | } |
1014 | retval = pid_vnr(grp); | ||
1015 | out: | ||
1016 | rcu_read_unlock(); | ||
1017 | return retval; | ||
1011 | } | 1018 | } |
1012 | 1019 | ||
1013 | #ifdef __ARCH_WANT_SYS_GETPGRP | 1020 | #ifdef __ARCH_WANT_SYS_GETPGRP |
1014 | 1021 | ||
1015 | asmlinkage long sys_getpgrp(void) | 1022 | asmlinkage long sys_getpgrp(void) |
1016 | { | 1023 | { |
1017 | /* SMP - assuming writes are word atomic this is fine */ | 1024 | return sys_getpgid(0); |
1018 | return task_pgrp_vnr(current); | ||
1019 | } | 1025 | } |
1020 | 1026 | ||
1021 | #endif | 1027 | #endif |