diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-01-08 04:03:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:14:01 -0500 |
commit | ee0acf90d320c29916ba8c5c1b2e908d81f5057d (patch) | |
tree | def952e2e3ebf2b5ba10585055f12ef0cbed17f2 /kernel/sys.c | |
parent | 9a5d3023e626a0baf86ac6b892c983b3db13f22b (diff) |
[PATCH] setpgid: should work for sub-threads
setpgid(0, pgid) or setpgid(forked_child_pid, pgid) does not work unless
the calling process is a thread_group_leader().
'man setpgid' does not tell anything about that, so I consider this
behaviour is a bug.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Oren Laadan <orenl@cs.columbia.edu>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index d8e49e659027..43e557211d8d 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1090,10 +1090,11 @@ asmlinkage long sys_times(struct tms __user * tbuf) | |||
1090 | asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | 1090 | asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) |
1091 | { | 1091 | { |
1092 | struct task_struct *p; | 1092 | struct task_struct *p; |
1093 | struct task_struct *group_leader = current->group_leader; | ||
1093 | int err = -EINVAL; | 1094 | int err = -EINVAL; |
1094 | 1095 | ||
1095 | if (!pid) | 1096 | if (!pid) |
1096 | pid = current->pid; | 1097 | pid = group_leader->pid; |
1097 | if (!pgid) | 1098 | if (!pgid) |
1098 | pgid = pid; | 1099 | pgid = pid; |
1099 | if (pgid < 0) | 1100 | if (pgid < 0) |
@@ -1113,16 +1114,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | |||
1113 | if (!thread_group_leader(p)) | 1114 | if (!thread_group_leader(p)) |
1114 | goto out; | 1115 | goto out; |
1115 | 1116 | ||
1116 | if (p->parent == current || p->real_parent == current) { | 1117 | if (p->parent == current || p->real_parent == group_leader) { |
1117 | err = -EPERM; | 1118 | err = -EPERM; |
1118 | if (p->signal->session != current->signal->session) | 1119 | if (p->signal->session != group_leader->signal->session) |
1119 | goto out; | 1120 | goto out; |
1120 | err = -EACCES; | 1121 | err = -EACCES; |
1121 | if (p->did_exec) | 1122 | if (p->did_exec) |
1122 | goto out; | 1123 | goto out; |
1123 | } else { | 1124 | } else { |
1124 | err = -ESRCH; | 1125 | err = -ESRCH; |
1125 | if (p != current) | 1126 | if (p != group_leader) |
1126 | goto out; | 1127 | goto out; |
1127 | } | 1128 | } |
1128 | 1129 | ||
@@ -1134,7 +1135,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | |||
1134 | struct task_struct *p; | 1135 | struct task_struct *p; |
1135 | 1136 | ||
1136 | do_each_task_pid(pgid, PIDTYPE_PGID, p) { | 1137 | do_each_task_pid(pgid, PIDTYPE_PGID, p) { |
1137 | if (p->signal->session == current->signal->session) | 1138 | if (p->signal->session == group_leader->signal->session) |
1138 | goto ok_pgid; | 1139 | goto ok_pgid; |
1139 | } while_each_task_pid(pgid, PIDTYPE_PGID, p); | 1140 | } while_each_task_pid(pgid, PIDTYPE_PGID, p); |
1140 | goto out; | 1141 | goto out; |