aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@tv-sign.ru>2008-04-30 03:54:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:49 -0400
commit12a3de0a965826096d8adc593bcf4392a7d5b459 (patch)
tree764d69c2973e67cb3ae58bec02e29cd616c40f90 /kernel/sys.c
parent1dd768c0815334d2319d6377f0750ace075b6142 (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.c36
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
992asmlinkage long sys_getpgid(pid_t pid) 992asmlinkage 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);
1015out:
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
1015asmlinkage long sys_getpgrp(void) 1022asmlinkage 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