aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorOren Laadan <orenl@cs.columbia.edu>2006-01-08 04:03:51 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:14:00 -0500
commit9a5d3023e626a0baf86ac6b892c983b3db13f22b (patch)
tree41d1be6513fc3a5367414654eeaf11bbb12d4814 /kernel/fork.c
parentfb86a35b9ded8a7e53a432cbf28df603cdd4849c (diff)
[PATCH] fork: fix race in setting child's pgrp and tty
In fork, child should recopy parent's pgrp/tty after it has tasklist_lock. Otherwise following a setpgid() on the parent, *after* copy_signal(), the child will own a stale pgrp (which may be reused); (eg. if copy_mm() sleeps a long while due to memory pressure). Similar issue for the tty. Signed-off-by: Oren Laadan <orenl@cs.columbia.edu> Cc: Oleg Nesterov <oleg@tv-sign.ru> 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/fork.c')
-rw-r--r--kernel/fork.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 7992ee759d89..4bc0bd8ef176 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -811,9 +811,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
811 sig->it_prof_expires = cputime_zero; 811 sig->it_prof_expires = cputime_zero;
812 sig->it_prof_incr = cputime_zero; 812 sig->it_prof_incr = cputime_zero;
813 813
814 sig->tty = current->signal->tty;
815 sig->pgrp = process_group(current);
816 sig->session = current->signal->session;
817 sig->leader = 0; /* session leadership doesn't inherit */ 814 sig->leader = 0; /* session leadership doesn't inherit */
818 sig->tty_old_pgrp = 0; 815 sig->tty_old_pgrp = 0;
819 816
@@ -1136,15 +1133,15 @@ static task_t *copy_process(unsigned long clone_flags,
1136 attach_pid(p, PIDTYPE_PID, p->pid); 1133 attach_pid(p, PIDTYPE_PID, p->pid);
1137 attach_pid(p, PIDTYPE_TGID, p->tgid); 1134 attach_pid(p, PIDTYPE_TGID, p->tgid);
1138 if (thread_group_leader(p)) { 1135 if (thread_group_leader(p)) {
1136 p->signal->tty = current->signal->tty;
1137 p->signal->pgrp = process_group(current);
1138 p->signal->session = current->signal->session;
1139 attach_pid(p, PIDTYPE_PGID, process_group(p)); 1139 attach_pid(p, PIDTYPE_PGID, process_group(p));
1140 attach_pid(p, PIDTYPE_SID, p->signal->session); 1140 attach_pid(p, PIDTYPE_SID, p->signal->session);
1141 if (p->pid) 1141 if (p->pid)
1142 __get_cpu_var(process_counts)++; 1142 __get_cpu_var(process_counts)++;
1143 } 1143 }
1144 1144
1145 if (!current->signal->tty && p->signal->tty)
1146 p->signal->tty = NULL;
1147
1148 nr_threads++; 1145 nr_threads++;
1149 total_forks++; 1146 total_forks++;
1150 write_unlock_irq(&tasklist_lock); 1147 write_unlock_irq(&tasklist_lock);