diff options
| author | Paul Mackerras <paulus@samba.org> | 2008-05-09 06:12:06 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2008-05-09 06:12:06 -0400 |
| commit | 2a5f2e3e6cd1ce9fb3f8b186b6bc9aa1f1497a92 (patch) | |
| tree | b2306840f227972a7c9d4a2b75e516fe81358ce8 /kernel/fork.c | |
| parent | 02539d71fa98d5737bb668b02286c76241e4bac9 (diff) | |
| parent | 78be76476a34a77f0ea9db2f78ba46a2b0fd5ab5 (diff) | |
Merge branch 'for-2.6.26' of master.kernel.org:/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx into merge
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 51 |
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 | ||
| 988 | void 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 | */ | ||
| 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 | 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 | ||
| 1758 | bad_unshare_cleanup_semundo: | ||
| 1759 | bad_unshare_cleanup_fd: | 1766 | bad_unshare_cleanup_fd: |
| 1760 | if (new_fd) | 1767 | if (new_fd) |
| 1761 | put_files_struct(new_fd); | 1768 | put_files_struct(new_fd); |
