diff options
author | Oleg Nesterov <oleg@redhat.com> | 2010-05-26 17:44:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 12:12:52 -0400 |
commit | f106eee10038c2ee5b6056aaf3f6d5229be6dcdd (patch) | |
tree | de7ce930b7119a1be00f3c7604065896d31abc9c /kernel/fork.c | |
parent | f20011457f41c11edb5ea5038ad0c8ea9f392023 (diff) |
pids: fix fork_idle() to setup ->pids correctly
copy_process(pid => &init_struct_pid) doesn't do attach_pid/etc.
It shouldn't, but this means that the idle threads run with the wrong
pids copied from the caller's task_struct. In x86 case the caller is
either kernel_init() thread or keventd.
In particular, this means that after the series of cpu_up/cpu_down an
idle thread (which never exits) can run with .pid pointing to nowhere.
Change fork_idle() to initialize idle->pids[] correctly. We only set
.pid = &init_struct_pid but do not add .node to list, INIT_TASK() does
the same for the boot-cpu idle thread (swapper).
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Cedric Le Goater <clg@fr.ibm.com>
Cc: Dave Hansen <haveblue@us.ibm.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Herbert Poetzl <herbert@13thfloor.at>
Cc: Mathias Krause <Mathias.Krause@secunet.com>
Acked-by: Roland McGrath <roland@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index d32410bd4be7..bf9fef6d1bfe 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1338,6 +1338,16 @@ noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_re | |||
1338 | return regs; | 1338 | return regs; |
1339 | } | 1339 | } |
1340 | 1340 | ||
1341 | static inline void init_idle_pids(struct pid_link *links) | ||
1342 | { | ||
1343 | enum pid_type type; | ||
1344 | |||
1345 | for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) { | ||
1346 | INIT_HLIST_NODE(&links[type].node); /* not really needed */ | ||
1347 | links[type].pid = &init_struct_pid; | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1341 | struct task_struct * __cpuinit fork_idle(int cpu) | 1351 | struct task_struct * __cpuinit fork_idle(int cpu) |
1342 | { | 1352 | { |
1343 | struct task_struct *task; | 1353 | struct task_struct *task; |
@@ -1345,8 +1355,10 @@ struct task_struct * __cpuinit fork_idle(int cpu) | |||
1345 | 1355 | ||
1346 | task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, | 1356 | task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, |
1347 | &init_struct_pid, 0); | 1357 | &init_struct_pid, 0); |
1348 | if (!IS_ERR(task)) | 1358 | if (!IS_ERR(task)) { |
1359 | init_idle_pids(task->pids); | ||
1349 | init_idle(task, cpu); | 1360 | init_idle(task, cpu); |
1361 | } | ||
1350 | 1362 | ||
1351 | return task; | 1363 | return task; |
1352 | } | 1364 | } |