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