diff options
-rw-r--r-- | kernel/fork.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index fd65bca38a93..2deaf481efab 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1040,6 +1040,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1040 | if (p->binfmt && !try_module_get(p->binfmt->module)) | 1040 | if (p->binfmt && !try_module_get(p->binfmt->module)) |
1041 | goto bad_fork_cleanup_put_domain; | 1041 | goto bad_fork_cleanup_put_domain; |
1042 | 1042 | ||
1043 | if (pid != &init_struct_pid) { | ||
1044 | pid = alloc_pid(); | ||
1045 | if (!pid) | ||
1046 | goto bad_fork_put_binfmt_module; | ||
1047 | } | ||
1048 | |||
1043 | p->did_exec = 0; | 1049 | p->did_exec = 0; |
1044 | delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ | 1050 | delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ |
1045 | copy_flags(clone_flags, p); | 1051 | copy_flags(clone_flags, p); |
@@ -1331,6 +1337,9 @@ bad_fork_cleanup_cgroup: | |||
1331 | cgroup_exit(p, cgroup_callbacks_done); | 1337 | cgroup_exit(p, cgroup_callbacks_done); |
1332 | bad_fork_cleanup_delays_binfmt: | 1338 | bad_fork_cleanup_delays_binfmt: |
1333 | delayacct_tsk_free(p); | 1339 | delayacct_tsk_free(p); |
1340 | if (pid != &init_struct_pid) | ||
1341 | free_pid(pid); | ||
1342 | bad_fork_put_binfmt_module: | ||
1334 | if (p->binfmt) | 1343 | if (p->binfmt) |
1335 | module_put(p->binfmt->module); | 1344 | module_put(p->binfmt->module); |
1336 | bad_fork_cleanup_put_domain: | 1345 | bad_fork_cleanup_put_domain: |
@@ -1395,19 +1404,16 @@ long do_fork(unsigned long clone_flags, | |||
1395 | { | 1404 | { |
1396 | struct task_struct *p; | 1405 | struct task_struct *p; |
1397 | int trace = 0; | 1406 | int trace = 0; |
1398 | struct pid *pid = alloc_pid(); | ||
1399 | long nr; | 1407 | long nr; |
1400 | 1408 | ||
1401 | if (!pid) | ||
1402 | return -EAGAIN; | ||
1403 | nr = pid->nr; | ||
1404 | if (unlikely(current->ptrace)) { | 1409 | if (unlikely(current->ptrace)) { |
1405 | trace = fork_traceflag (clone_flags); | 1410 | trace = fork_traceflag (clone_flags); |
1406 | if (trace) | 1411 | if (trace) |
1407 | clone_flags |= CLONE_PTRACE; | 1412 | clone_flags |= CLONE_PTRACE; |
1408 | } | 1413 | } |
1409 | 1414 | ||
1410 | p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid); | 1415 | p = copy_process(clone_flags, stack_start, regs, stack_size, |
1416 | parent_tidptr, child_tidptr, NULL); | ||
1411 | /* | 1417 | /* |
1412 | * Do this prior waking up the new thread - the thread pointer | 1418 | * Do this prior waking up the new thread - the thread pointer |
1413 | * might get invalid after that point, if the thread exits quickly. | 1419 | * might get invalid after that point, if the thread exits quickly. |
@@ -1415,6 +1421,8 @@ long do_fork(unsigned long clone_flags, | |||
1415 | if (!IS_ERR(p)) { | 1421 | if (!IS_ERR(p)) { |
1416 | struct completion vfork; | 1422 | struct completion vfork; |
1417 | 1423 | ||
1424 | nr = pid_nr(task_pid(p)); | ||
1425 | |||
1418 | if (clone_flags & CLONE_VFORK) { | 1426 | if (clone_flags & CLONE_VFORK) { |
1419 | p->vfork_done = &vfork; | 1427 | p->vfork_done = &vfork; |
1420 | init_completion(&vfork); | 1428 | init_completion(&vfork); |
@@ -1448,7 +1456,6 @@ long do_fork(unsigned long clone_flags, | |||
1448 | } | 1456 | } |
1449 | } | 1457 | } |
1450 | } else { | 1458 | } else { |
1451 | free_pid(pid); | ||
1452 | nr = PTR_ERR(p); | 1459 | nr = PTR_ERR(p); |
1453 | } | 1460 | } |
1454 | return nr; | 1461 | return nr; |