diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-02-08 07:19:09 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 12:22:27 -0500 |
commit | e4cc0a9c876d4d4eadaef97a2bff4a199946d202 (patch) | |
tree | e25406d84ce842c54e3ac5438e4bcee32a75a964 /kernel | |
parent | 4e021306cff4277764a42065214fc73f2d26be4b (diff) |
fix setsid() for sub-namespace /sbin/init
sys_setsid() still deals with pid_t's from the global namespace. This means
that the "session > 1" check can't help for sub-namespace init, setsid() can't
succeed because copy_process(CLONE_NEWPID) populates PIDTYPE_PGID/SID links.
Remove the usage of task_struct->pid and convert the code to use "struct pid".
This also simplifies and speedups the code, saves one find_pid().
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Pavel Emelyanov <xemul@openvz.org>
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 | 22 |
1 files changed, 10 insertions, 12 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 42136dd453d1..e13bc518b444 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1045,35 +1045,33 @@ asmlinkage long sys_getsid(pid_t pid) | |||
1045 | asmlinkage long sys_setsid(void) | 1045 | asmlinkage long sys_setsid(void) |
1046 | { | 1046 | { |
1047 | struct task_struct *group_leader = current->group_leader; | 1047 | struct task_struct *group_leader = current->group_leader; |
1048 | pid_t session; | 1048 | struct pid *sid = task_pid(group_leader); |
1049 | pid_t session = pid_vnr(sid); | ||
1049 | int err = -EPERM; | 1050 | int err = -EPERM; |
1050 | 1051 | ||
1051 | write_lock_irq(&tasklist_lock); | 1052 | write_lock_irq(&tasklist_lock); |
1052 | |||
1053 | /* Fail if I am already a session leader */ | 1053 | /* Fail if I am already a session leader */ |
1054 | if (group_leader->signal->leader) | 1054 | if (group_leader->signal->leader) |
1055 | goto out; | 1055 | goto out; |
1056 | 1056 | ||
1057 | session = group_leader->pid; | 1057 | /* Fail if a process group id already exists that equals the proposed |
1058 | /* Fail if a process group id already exists that equals the | 1058 | * session id. |
1059 | * proposed session id. | ||
1060 | * | 1059 | * |
1061 | * Don't check if session id == 1 because kernel threads use this | 1060 | * Don't check if session == 1 because kernel threads and CLONE_NEWPID |
1062 | * session id and so the check will always fail and make it so | 1061 | * tasks use this session id and so the check will always fail and make |
1063 | * init cannot successfully call setsid. | 1062 | * it so init cannot successfully call setsid. |
1064 | */ | 1063 | */ |
1065 | if (session > 1 && find_task_by_pid_type_ns(PIDTYPE_PGID, | 1064 | if (session != 1 && pid_task(sid, PIDTYPE_PGID)) |
1066 | session, &init_pid_ns)) | ||
1067 | goto out; | 1065 | goto out; |
1068 | 1066 | ||
1069 | group_leader->signal->leader = 1; | 1067 | group_leader->signal->leader = 1; |
1070 | __set_special_pids(session, session); | 1068 | __set_special_pids(pid_nr(sid), pid_nr(sid)); |
1071 | 1069 | ||
1072 | spin_lock(&group_leader->sighand->siglock); | 1070 | spin_lock(&group_leader->sighand->siglock); |
1073 | group_leader->signal->tty = NULL; | 1071 | group_leader->signal->tty = NULL; |
1074 | spin_unlock(&group_leader->sighand->siglock); | 1072 | spin_unlock(&group_leader->sighand->siglock); |
1075 | 1073 | ||
1076 | err = task_pgrp_vnr(group_leader); | 1074 | err = session; |
1077 | out: | 1075 | out: |
1078 | write_unlock_irq(&tasklist_lock); | 1076 | write_unlock_irq(&tasklist_lock); |
1079 | return err; | 1077 | return err; |