diff options
author | Oren Laadan <orenl@cs.columbia.edu> | 2006-01-08 04:03:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-08 23:14:00 -0500 |
commit | 9a5d3023e626a0baf86ac6b892c983b3db13f22b (patch) | |
tree | 41d1be6513fc3a5367414654eeaf11bbb12d4814 /kernel | |
parent | fb86a35b9ded8a7e53a432cbf28df603cdd4849c (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')
-rw-r--r-- | kernel/fork.c | 9 |
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); |