diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 987b28a1f01b..bf46287c91a4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -365,8 +365,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 365 | mm->locked_vm = 0; | 365 | mm->locked_vm = 0; |
| 366 | mm->mmap = NULL; | 366 | mm->mmap = NULL; |
| 367 | mm->mmap_cache = NULL; | 367 | mm->mmap_cache = NULL; |
| 368 | mm->free_area_cache = oldmm->mmap_base; | ||
| 369 | mm->cached_hole_size = ~0UL; | ||
| 370 | mm->map_count = 0; | 368 | mm->map_count = 0; |
| 371 | cpumask_clear(mm_cpumask(mm)); | 369 | cpumask_clear(mm_cpumask(mm)); |
| 372 | mm->mm_rb = RB_ROOT; | 370 | mm->mm_rb = RB_ROOT; |
| @@ -540,8 +538,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) | |||
| 540 | mm->nr_ptes = 0; | 538 | mm->nr_ptes = 0; |
| 541 | memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); | 539 | memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); |
| 542 | spin_lock_init(&mm->page_table_lock); | 540 | spin_lock_init(&mm->page_table_lock); |
| 543 | mm->free_area_cache = TASK_UNMAPPED_BASE; | ||
| 544 | mm->cached_hole_size = ~0UL; | ||
| 545 | mm_init_aio(mm); | 541 | mm_init_aio(mm); |
| 546 | mm_init_owner(mm, p); | 542 | mm_init_owner(mm, p); |
| 547 | 543 | ||
| @@ -1121,6 +1117,12 @@ static void posix_cpu_timers_init(struct task_struct *tsk) | |||
| 1121 | INIT_LIST_HEAD(&tsk->cpu_timers[2]); | 1117 | INIT_LIST_HEAD(&tsk->cpu_timers[2]); |
| 1122 | } | 1118 | } |
| 1123 | 1119 | ||
| 1120 | static inline void | ||
| 1121 | init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid) | ||
| 1122 | { | ||
| 1123 | task->pids[type].pid = pid; | ||
| 1124 | } | ||
| 1125 | |||
| 1124 | /* | 1126 | /* |
| 1125 | * This creates a new process as a copy of the old one, | 1127 | * This creates a new process as a copy of the old one, |
| 1126 | * but does not actually start it yet. | 1128 | * but does not actually start it yet. |
| @@ -1175,7 +1177,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1175 | * don't allow the creation of threads. | 1177 | * don't allow the creation of threads. |
| 1176 | */ | 1178 | */ |
| 1177 | if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) && | 1179 | if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) && |
| 1178 | (task_active_pid_ns(current) != current->nsproxy->pid_ns)) | 1180 | (task_active_pid_ns(current) != |
| 1181 | current->nsproxy->pid_ns_for_children)) | ||
| 1179 | return ERR_PTR(-EINVAL); | 1182 | return ERR_PTR(-EINVAL); |
| 1180 | 1183 | ||
| 1181 | retval = security_task_create(clone_flags); | 1184 | retval = security_task_create(clone_flags); |
| @@ -1199,8 +1202,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1199 | retval = -EAGAIN; | 1202 | retval = -EAGAIN; |
| 1200 | if (atomic_read(&p->real_cred->user->processes) >= | 1203 | if (atomic_read(&p->real_cred->user->processes) >= |
| 1201 | task_rlimit(p, RLIMIT_NPROC)) { | 1204 | task_rlimit(p, RLIMIT_NPROC)) { |
| 1202 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && | 1205 | if (p->real_cred->user != INIT_USER && |
| 1203 | p->real_cred->user != INIT_USER) | 1206 | !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) |
| 1204 | goto bad_fork_free; | 1207 | goto bad_fork_free; |
| 1205 | } | 1208 | } |
| 1206 | current->flags &= ~PF_NPROC_EXCEEDED; | 1209 | current->flags &= ~PF_NPROC_EXCEEDED; |
| @@ -1349,16 +1352,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1349 | 1352 | ||
| 1350 | if (pid != &init_struct_pid) { | 1353 | if (pid != &init_struct_pid) { |
| 1351 | retval = -ENOMEM; | 1354 | retval = -ENOMEM; |
| 1352 | pid = alloc_pid(p->nsproxy->pid_ns); | 1355 | pid = alloc_pid(p->nsproxy->pid_ns_for_children); |
| 1353 | if (!pid) | 1356 | if (!pid) |
| 1354 | goto bad_fork_cleanup_io; | 1357 | goto bad_fork_cleanup_io; |
| 1355 | } | 1358 | } |
| 1356 | 1359 | ||
| 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; | 1360 | p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
| 1363 | /* | 1361 | /* |
| 1364 | * Clear TID on mm_release()? | 1362 | * Clear TID on mm_release()? |
| @@ -1394,12 +1392,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1394 | clear_all_latency_tracing(p); | 1392 | clear_all_latency_tracing(p); |
| 1395 | 1393 | ||
| 1396 | /* ok, now we should be set up.. */ | 1394 | /* ok, now we should be set up.. */ |
| 1397 | if (clone_flags & CLONE_THREAD) | 1395 | p->pid = pid_nr(pid); |
| 1396 | if (clone_flags & CLONE_THREAD) { | ||
| 1398 | p->exit_signal = -1; | 1397 | p->exit_signal = -1; |
| 1399 | else if (clone_flags & CLONE_PARENT) | 1398 | p->group_leader = current->group_leader; |
| 1400 | p->exit_signal = current->group_leader->exit_signal; | 1399 | p->tgid = current->tgid; |
| 1401 | else | 1400 | } else { |
| 1402 | p->exit_signal = (clone_flags & CSIGNAL); | 1401 | if (clone_flags & CLONE_PARENT) |
| 1402 | p->exit_signal = current->group_leader->exit_signal; | ||
| 1403 | else | ||
| 1404 | p->exit_signal = (clone_flags & CSIGNAL); | ||
| 1405 | p->group_leader = p; | ||
| 1406 | p->tgid = p->pid; | ||
| 1407 | } | ||
| 1403 | 1408 | ||
| 1404 | p->pdeath_signal = 0; | 1409 | p->pdeath_signal = 0; |
| 1405 | p->exit_state = 0; | 1410 | p->exit_state = 0; |
| @@ -1408,15 +1413,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1408 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); | 1413 | p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10); |
| 1409 | p->dirty_paused_when = 0; | 1414 | p->dirty_paused_when = 0; |
| 1410 | 1415 | ||
| 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); | 1416 | INIT_LIST_HEAD(&p->thread_group); |
| 1417 | p->task_works = NULL; | 1417 | p->task_works = NULL; |
| 1418 | 1418 | ||
| 1419 | /* Need tasklist lock for parent etc handling! */ | 1419 | /* |
| 1420 | * Make it visible to the rest of the system, but dont wake it up yet. | ||
| 1421 | * Need tasklist lock for parent etc handling! | ||
| 1422 | */ | ||
| 1420 | write_lock_irq(&tasklist_lock); | 1423 | write_lock_irq(&tasklist_lock); |
| 1421 | 1424 | ||
| 1422 | /* CLONE_PARENT re-uses the old parent */ | 1425 | /* CLONE_PARENT re-uses the old parent */ |
| @@ -1446,18 +1449,14 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1446 | goto bad_fork_free_pid; | 1449 | goto bad_fork_free_pid; |
| 1447 | } | 1450 | } |
| 1448 | 1451 | ||
| 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)) { | 1452 | if (likely(p->pid)) { |
| 1458 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); | 1453 | ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); |
| 1459 | 1454 | ||
| 1455 | init_task_pid(p, PIDTYPE_PID, pid); | ||
| 1460 | if (thread_group_leader(p)) { | 1456 | if (thread_group_leader(p)) { |
| 1457 | init_task_pid(p, PIDTYPE_PGID, task_pgrp(current)); | ||
| 1458 | init_task_pid(p, PIDTYPE_SID, task_session(current)); | ||
| 1459 | |||
| 1461 | if (is_child_reaper(pid)) { | 1460 | if (is_child_reaper(pid)) { |
| 1462 | ns_of_pid(pid)->child_reaper = p; | 1461 | ns_of_pid(pid)->child_reaper = p; |
| 1463 | p->signal->flags |= SIGNAL_UNKILLABLE; | 1462 | p->signal->flags |= SIGNAL_UNKILLABLE; |
| @@ -1465,13 +1464,19 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1465 | 1464 | ||
| 1466 | p->signal->leader_pid = pid; | 1465 | p->signal->leader_pid = pid; |
| 1467 | p->signal->tty = tty_kref_get(current->signal->tty); | 1466 | 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); | 1467 | list_add_tail(&p->sibling, &p->real_parent->children); |
| 1471 | list_add_tail_rcu(&p->tasks, &init_task.tasks); | 1468 | list_add_tail_rcu(&p->tasks, &init_task.tasks); |
| 1469 | attach_pid(p, PIDTYPE_PGID); | ||
| 1470 | attach_pid(p, PIDTYPE_SID); | ||
| 1472 | __this_cpu_inc(process_counts); | 1471 | __this_cpu_inc(process_counts); |
| 1472 | } else { | ||
| 1473 | current->signal->nr_threads++; | ||
| 1474 | atomic_inc(¤t->signal->live); | ||
| 1475 | atomic_inc(¤t->signal->sigcnt); | ||
| 1476 | list_add_tail_rcu(&p->thread_group, | ||
| 1477 | &p->group_leader->thread_group); | ||
| 1473 | } | 1478 | } |
| 1474 | attach_pid(p, PIDTYPE_PID, pid); | 1479 | attach_pid(p, PIDTYPE_PID); |
| 1475 | nr_threads++; | 1480 | nr_threads++; |
| 1476 | } | 1481 | } |
| 1477 | 1482 | ||
| @@ -1542,7 +1547,7 @@ static inline void init_idle_pids(struct pid_link *links) | |||
| 1542 | } | 1547 | } |
| 1543 | } | 1548 | } |
| 1544 | 1549 | ||
| 1545 | struct task_struct * __cpuinit fork_idle(int cpu) | 1550 | struct task_struct *fork_idle(int cpu) |
| 1546 | { | 1551 | { |
| 1547 | struct task_struct *task; | 1552 | struct task_struct *task; |
| 1548 | task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0); | 1553 | task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0); |
| @@ -1675,6 +1680,12 @@ SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, | |||
| 1675 | int __user *, parent_tidptr, | 1680 | int __user *, parent_tidptr, |
| 1676 | int __user *, child_tidptr, | 1681 | int __user *, child_tidptr, |
| 1677 | int, tls_val) | 1682 | int, tls_val) |
| 1683 | #elif defined(CONFIG_CLONE_BACKWARDS3) | ||
| 1684 | SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, | ||
| 1685 | int, stack_size, | ||
| 1686 | int __user *, parent_tidptr, | ||
| 1687 | int __user *, child_tidptr, | ||
| 1688 | int, tls_val) | ||
| 1678 | #else | 1689 | #else |
| 1679 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | 1690 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, |
| 1680 | int __user *, parent_tidptr, | 1691 | int __user *, parent_tidptr, |
