diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 987b28a1f01b..6e6a1c11b3e5 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1121,6 +1121,12 @@ static void posix_cpu_timers_init(struct task_struct *tsk) | |||
| 1121 | INIT_LIST_HEAD(&tsk->cpu_timers[2]); | 1121 | INIT_LIST_HEAD(&tsk->cpu_timers[2]); |
| 1122 | } | 1122 | } |
| 1123 | 1123 | ||
| 1124 | static inline void | ||
| 1125 | init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) | ||
| 1126 | { | ||
| 1127 | task->pids[type].pid = pid; | ||
| 1128 | } | ||
| 1129 | |||
| 1124 | /* | 1130 | /* |
| 1125 | * This creates a new process as a copy of the old one, | 1131 | * This creates a new process as a copy of the old one, |
| 1126 | * but does not actually start it yet. | 1132 | * but does not actually start it yet. |
| @@ -1199,8 +1205,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1199 | retval = -EAGAIN; | 1205 | retval = -EAGAIN; |
| 1200 | if (atomic_read(&p->real_cred->user->processes) >= | 1206 | if (atomic_read(&p->real_cred->user->processes) >= |
| 1201 | task_rlimit(p, RLIMIT_NPROC)) { | 1207 | task_rlimit(p, RLIMIT_NPROC)) { |
| 1202 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && | 1208 | if (p->real_cred->user != INIT_USER && |
| 1203 | p->real_cred->user != INIT_USER) | 1209 | !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) |
| 1204 | goto bad_fork_free; | 1210 | goto bad_fork_free; |
| 1205 | } | 1211 | } |
| 1206 | current->flags &= ~PF_NPROC_EXCEEDED; | 1212 | current->flags &= ~PF_NPROC_EXCEEDED; |
| @@ -1354,11 +1360,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1354 | goto bad_fork_cleanup_io; | 1360 | goto bad_fork_cleanup_io; |
| 1355 | } | 1361 | } |
| 1356 | 1362 | ||
| 1357 | p->pid = pid_nr(pid); | ||
| 1358 | p->tgid = p->pid; | ||
| 1359 | if (clone_flags & CLONE_THREAD) | ||
| 1360 | p->tgid = current->tgid; | ||
| 1361 | |||
| 1362 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; | 1363 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
| 1363 | /* | 1364 | /* |
| 1364 | * Clear TID on mm_release()? | 1365 | * Clear TID on mm_release()? |
| @@ -1394,12 +1395,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1394 | clear_all_latency_tracing(p); | 1395 | clear_all_latency_tracing(p); |
| 1395 | 1396 | ||
| 1396 | /* ok, now we should be set up.. */ | 1397 | /* ok, now we should be set up.. */ |
| 1397 | if (clone_flags & CLONE_THREAD) | 1398 | p->pid = pid_nr(pid); |
| 1399 | if (clone_flags & CLONE_THREAD) { | ||
| 1398 | p->exit_signal = -1; | 1400 | p->exit_signal = -1; |
| 1399 | else if (clone_flags & CLONE_PARENT) | 1401 | p->group_leader = current->group_leader; |
| 1400 | p->exit_signal = current->group_leader->exit_signal; | 1402 | p->tgid = current->tgid; |
| 1401 | else | 1403 | } else { |
| 1402 | p->exit_signal = (clone_flags & CSIGNAL); | 1404 | if (clone_flags & CLONE_PARENT) |
| 1405 | p->exit_signal = current->group_leader->exit_signal; | ||
| 1406 | else | ||
| 1407 | p->exit_signal = (clone_flags & CSIGNAL); | ||
| 1408 | p->group_leader = p; | ||
| 1409 | p->tgid = p->pid; | ||
| 1410 | } | ||
| 1403 | 1411 | ||
| 1404 | p->pdeath_signal = 0; | 1412 | p->pdeath_signal = 0; |
| 1405 | p->exit_state = 0; | 1413 | p->exit_state = 0; |
| @@ -1408,15 +1416,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1408 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); | 1416 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); |
| 1409 | p->dirty_paused_when = 0; | 1417 | p->dirty_paused_when = 0; |
| 1410 | 1418 | ||
| 1411 | /* | ||
| 1412 | * Ok, make it visible to the rest of the system. | ||
| 1413 | * We dont wake it up yet. | ||
| 1414 | */ | ||
| 1415 | p->group_leader = p; | ||
| 1416 | INIT_LIST_HEAD(&p->thread_group); | 1419 | INIT_LIST_HEAD(&p->thread_group); |
| 1417 | p->task_works = NULL; | 1420 | p->task_works = NULL; |
| 1418 | 1421 | ||
| 1419 | /* Need tasklist lock for parent etc handling! */ | 1422 | /* |
| 1423 | * Make it visible to the rest of the system, but dont wake it up yet. | ||
| 1424 | * Need tasklist lock for parent etc handling! | ||
| 1425 | */ | ||
| 1420 | write_lock_irq(&tasklist_lock); | 1426 | write_lock_irq(&tasklist_lock); |
| 1421 | 1427 | ||
| 1422 | /* CLONE_PARENT re-uses the old parent */ | 1428 | /* CLONE_PARENT re-uses the old parent */ |
| @@ -1446,18 +1452,14 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1446 | goto bad_fork_free_pid; | 1452 | goto bad_fork_free_pid; |
| 1447 | } | 1453 | } |
| 1448 | 1454 | ||
| 1449 | if (clone_flags & CLONE_THREAD) { | ||
| 1450 | current->signal->nr_threads++; | ||
| 1451 | atomic_inc(¤t->signal->live); | ||
| 1452 | atomic_inc(¤t->signal->sigcnt); | ||
| 1453 | p->group_leader = current->group_leader; | ||
| 1454 | list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | if (likely(p->pid)) { | 1455 | if (likely(p->pid)) { |
| 1458 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); | 1456 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); |
| 1459 | 1457 | ||
| 1458 | init_task_pid(p, PIDTYPE_PID, pid); | ||
| 1460 | if (thread_group_leader(p)) { | 1459 | if (thread_group_leader(p)) { |
| 1460 | init_task_pid(p, PIDTYPE_PGID, task_pgrp(current)); | ||
| 1461 | init_task_pid(p, PIDTYPE_SID, task_session(current)); | ||
| 1462 | |||
| 1461 | if (is_child_reaper(pid)) { | 1463 | if (is_child_reaper(pid)) { |
| 1462 | ns_of_pid(pid)->child_reaper = p; | 1464 | ns_of_pid(pid)->child_reaper = p; |
| 1463 | p->signal->flags |= SIGNAL_UNKILLABLE; | 1465 | p->signal->flags |= SIGNAL_UNKILLABLE; |
| @@ -1465,13 +1467,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1465 | 1467 | ||
| 1466 | p->signal->leader_pid = pid; | 1468 | p->signal->leader_pid = pid; |
| 1467 | p->signal->tty = tty_kref_get(current->signal->tty); | 1469 | p->signal->tty = tty_kref_get(current->signal->tty); |
| 1468 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); | ||
| 1469 | attach_pid(p, PIDTYPE_SID, task_session(current)); | ||
| 1470 | list_add_tail(&p->sibling, &p->real_parent->children); | 1470 | list_add_tail(&p->sibling, &p->real_parent->children); |
| 1471 | list_add_tail_rcu(&p->tasks, &init_task.tasks); | 1471 | list_add_tail_rcu(&p->tasks, &init_task.tasks); |
| 1472 | attach_pid(p, PIDTYPE_PGID); | ||
| 1473 | attach_pid(p, PIDTYPE_SID); | ||
| 1472 | __this_cpu_inc(process_counts); | 1474 | __this_cpu_inc(process_counts); |
| 1475 | } else { | ||
| 1476 | current->signal->nr_threads++; | ||
| 1477 | atomic_inc(¤t->signal->live); | ||
| 1478 | atomic_inc(¤t->signal->sigcnt); | ||
| 1479 | list_add_tail_rcu(&p->thread_group, | ||
| 1480 | &p->group_leader->thread_group); | ||
| 1473 | } | 1481 | } |
| 1474 | attach_pid(p, PIDTYPE_PID, pid); | 1482 | attach_pid(p, PIDTYPE_PID); |
| 1475 | nr_threads++; | 1483 | nr_threads++; |
| 1476 | } | 1484 | } |
| 1477 | 1485 | ||
