diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 6067e429f281..068ffe007529 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -381,14 +381,13 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | |||
381 | mm->ioctx_list = NULL; | 381 | mm->ioctx_list = NULL; |
382 | mm->free_area_cache = TASK_UNMAPPED_BASE; | 382 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
383 | mm->cached_hole_size = ~0UL; | 383 | mm->cached_hole_size = ~0UL; |
384 | mm_init_cgroup(mm, p); | 384 | mm_init_owner(mm, p); |
385 | 385 | ||
386 | if (likely(!mm_alloc_pgd(mm))) { | 386 | if (likely(!mm_alloc_pgd(mm))) { |
387 | mm->def_flags = 0; | 387 | mm->def_flags = 0; |
388 | return mm; | 388 | return mm; |
389 | } | 389 | } |
390 | 390 | ||
391 | mm_free_cgroup(mm); | ||
392 | free_mm(mm); | 391 | free_mm(mm); |
393 | return NULL; | 392 | return NULL; |
394 | } | 393 | } |
@@ -432,13 +431,13 @@ void mmput(struct mm_struct *mm) | |||
432 | if (atomic_dec_and_test(&mm->mm_users)) { | 431 | if (atomic_dec_and_test(&mm->mm_users)) { |
433 | exit_aio(mm); | 432 | exit_aio(mm); |
434 | exit_mmap(mm); | 433 | exit_mmap(mm); |
434 | set_mm_exe_file(mm, NULL); | ||
435 | if (!list_empty(&mm->mmlist)) { | 435 | if (!list_empty(&mm->mmlist)) { |
436 | spin_lock(&mmlist_lock); | 436 | spin_lock(&mmlist_lock); |
437 | list_del(&mm->mmlist); | 437 | list_del(&mm->mmlist); |
438 | spin_unlock(&mmlist_lock); | 438 | spin_unlock(&mmlist_lock); |
439 | } | 439 | } |
440 | put_swap_token(mm); | 440 | put_swap_token(mm); |
441 | mm_free_cgroup(mm); | ||
442 | mmdrop(mm); | 441 | mmdrop(mm); |
443 | } | 442 | } |
444 | } | 443 | } |
@@ -545,6 +544,8 @@ struct mm_struct *dup_mm(struct task_struct *tsk) | |||
545 | if (init_new_context(tsk, mm)) | 544 | if (init_new_context(tsk, mm)) |
546 | goto fail_nocontext; | 545 | goto fail_nocontext; |
547 | 546 | ||
547 | dup_mm_exe_file(oldmm, mm); | ||
548 | |||
548 | err = dup_mmap(mm, oldmm); | 549 | err = dup_mmap(mm, oldmm); |
549 | if (err) | 550 | if (err) |
550 | goto free_pt; | 551 | goto free_pt; |
@@ -982,6 +983,13 @@ static void rt_mutex_init_task(struct task_struct *p) | |||
982 | #endif | 983 | #endif |
983 | } | 984 | } |
984 | 985 | ||
986 | #ifdef CONFIG_MM_OWNER | ||
987 | void mm_init_owner(struct mm_struct *mm, struct task_struct *p) | ||
988 | { | ||
989 | mm->owner = p; | ||
990 | } | ||
991 | #endif /* CONFIG_MM_OWNER */ | ||
992 | |||
985 | /* | 993 | /* |
986 | * This creates a new process as a copy of the old one, | 994 | * This creates a new process as a copy of the old one, |
987 | * but does not actually start it yet. | 995 | * but does not actually start it yet. |
@@ -1664,18 +1672,6 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp | |||
1664 | } | 1672 | } |
1665 | 1673 | ||
1666 | /* | 1674 | /* |
1667 | * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not | ||
1668 | * supported yet | ||
1669 | */ | ||
1670 | static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp) | ||
1671 | { | ||
1672 | if (unshare_flags & CLONE_SYSVSEM) | ||
1673 | return -EINVAL; | ||
1674 | |||
1675 | return 0; | ||
1676 | } | ||
1677 | |||
1678 | /* | ||
1679 | * unshare allows a process to 'unshare' part of the process | 1675 | * unshare allows a process to 'unshare' part of the process |
1680 | * context which was originally shared using clone. copy_* | 1676 | * context which was originally shared using clone. copy_* |
1681 | * functions used by do_fork() cannot be used here directly | 1677 | * functions used by do_fork() cannot be used here directly |
@@ -1690,8 +1686,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1690 | struct sighand_struct *new_sigh = NULL; | 1686 | struct sighand_struct *new_sigh = NULL; |
1691 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; | 1687 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; |
1692 | struct files_struct *fd, *new_fd = NULL; | 1688 | struct files_struct *fd, *new_fd = NULL; |
1693 | struct sem_undo_list *new_ulist = NULL; | ||
1694 | struct nsproxy *new_nsproxy = NULL; | 1689 | struct nsproxy *new_nsproxy = NULL; |
1690 | int do_sysvsem = 0; | ||
1695 | 1691 | ||
1696 | check_unshare_flags(&unshare_flags); | 1692 | check_unshare_flags(&unshare_flags); |
1697 | 1693 | ||
@@ -1703,6 +1699,13 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1703 | CLONE_NEWNET)) | 1699 | CLONE_NEWNET)) |
1704 | goto bad_unshare_out; | 1700 | goto bad_unshare_out; |
1705 | 1701 | ||
1702 | /* | ||
1703 | * CLONE_NEWIPC must also detach from the undolist: after switching | ||
1704 | * to a new ipc namespace, the semaphore arrays from the old | ||
1705 | * namespace are unreachable. | ||
1706 | */ | ||
1707 | if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM)) | ||
1708 | do_sysvsem = 1; | ||
1706 | if ((err = unshare_thread(unshare_flags))) | 1709 | if ((err = unshare_thread(unshare_flags))) |
1707 | goto bad_unshare_out; | 1710 | goto bad_unshare_out; |
1708 | if ((err = unshare_fs(unshare_flags, &new_fs))) | 1711 | if ((err = unshare_fs(unshare_flags, &new_fs))) |
@@ -1713,13 +1716,17 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1713 | goto bad_unshare_cleanup_sigh; | 1716 | goto bad_unshare_cleanup_sigh; |
1714 | if ((err = unshare_fd(unshare_flags, &new_fd))) | 1717 | if ((err = unshare_fd(unshare_flags, &new_fd))) |
1715 | goto bad_unshare_cleanup_vm; | 1718 | goto bad_unshare_cleanup_vm; |
1716 | if ((err = unshare_semundo(unshare_flags, &new_ulist))) | ||
1717 | goto bad_unshare_cleanup_fd; | ||
1718 | if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, | 1719 | if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, |
1719 | new_fs))) | 1720 | new_fs))) |
1720 | goto bad_unshare_cleanup_semundo; | 1721 | goto bad_unshare_cleanup_fd; |
1721 | 1722 | ||
1722 | if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) { | 1723 | if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) { |
1724 | if (do_sysvsem) { | ||
1725 | /* | ||
1726 | * CLONE_SYSVSEM is equivalent to sys_exit(). | ||
1727 | */ | ||
1728 | exit_sem(current); | ||
1729 | } | ||
1723 | 1730 | ||
1724 | if (new_nsproxy) { | 1731 | if (new_nsproxy) { |
1725 | switch_task_namespaces(current, new_nsproxy); | 1732 | switch_task_namespaces(current, new_nsproxy); |
@@ -1755,7 +1762,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1755 | if (new_nsproxy) | 1762 | if (new_nsproxy) |
1756 | put_nsproxy(new_nsproxy); | 1763 | put_nsproxy(new_nsproxy); |
1757 | 1764 | ||
1758 | bad_unshare_cleanup_semundo: | ||
1759 | bad_unshare_cleanup_fd: | 1765 | bad_unshare_cleanup_fd: |
1760 | if (new_fd) | 1766 | if (new_fd) |
1761 | put_files_struct(new_fd); | 1767 | put_files_struct(new_fd); |