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 | ||