aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-03-31 05:31:33 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-31 15:18:59 -0500
commit390e2ff07712468ce6600a43aa91e897b056ce12 (patch)
treefb92d3c2218fa3e41078d1b5e103892ac7e95117
parent9741ef964dc8bfeb6520825df9fed8f538c3336e (diff)
[PATCH] Make setsid() more robust
The core problem: setsid fails if it is called by init. The effect in 2.6.16 and the earlier kernels that have this problem is that if you do a "ps -j 1 or ps -ej 1" you will see that init and several of it's children have process group and session == 0. Instead of process group == session == 1. Despite init calling setsid. The reason it fails is that daemonize calls set_special_pids(1,1) on kernel threads that are launched before /sbin/init is called. The only remaining effect in that current->signal->leader == 0 for init instead of 1. And the setsid call fails. No one has noticed because /sbin/init does not check the return value of setsid. In 2.4 where we don't have the pidhash table, and daemonize doesn't exist setsid actually works for init. I care a lot about pid == 1 not being a special case that we leave broken, because of the container/jail work that I am doing. - Carefully allow init (pid == 1) to call setsid despite the kernel using its session. - Use find_task_by_pid instead of find_pid because find_pid taking a pidtype is going away. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--kernel/sys.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 7ef7f6054c28..0b6ec0e7936f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1372,18 +1372,29 @@ asmlinkage long sys_getsid(pid_t pid)
1372asmlinkage long sys_setsid(void) 1372asmlinkage long sys_setsid(void)
1373{ 1373{
1374 struct task_struct *group_leader = current->group_leader; 1374 struct task_struct *group_leader = current->group_leader;
1375 struct pid *pid; 1375 pid_t session;
1376 int err = -EPERM; 1376 int err = -EPERM;
1377 1377
1378 mutex_lock(&tty_mutex); 1378 mutex_lock(&tty_mutex);
1379 write_lock_irq(&tasklist_lock); 1379 write_lock_irq(&tasklist_lock);
1380 1380
1381 pid = find_pid(PIDTYPE_PGID, group_leader->pid); 1381 /* Fail if I am already a session leader */
1382 if (pid) 1382 if (group_leader->signal->leader)
1383 goto out;
1384
1385 session = group_leader->pid;
1386 /* Fail if a process group id already exists that equals the
1387 * proposed session id.
1388 *
1389 * Don't check if session id == 1 because kernel threads use this
1390 * session id and so the check will always fail and make it so
1391 * init cannot successfully call setsid.
1392 */
1393 if (session > 1 && find_task_by_pid_type(PIDTYPE_PGID, session))
1383 goto out; 1394 goto out;
1384 1395
1385 group_leader->signal->leader = 1; 1396 group_leader->signal->leader = 1;
1386 __set_special_pids(group_leader->pid, group_leader->pid); 1397 __set_special_pids(session, session);
1387 group_leader->signal->tty = NULL; 1398 group_leader->signal->tty = NULL;
1388 group_leader->signal->tty_old_pgrp = 0; 1399 group_leader->signal->tty_old_pgrp = 0;
1389 err = process_group(group_leader); 1400 err = process_group(group_leader);