aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index c7c112391d79..be8aa5b98666 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1592,6 +1592,10 @@ static __latent_entropy struct task_struct *copy_process(
1592 int retval; 1592 int retval;
1593 struct task_struct *p; 1593 struct task_struct *p;
1594 1594
1595 /*
1596 * Don't allow sharing the root directory with processes in a different
1597 * namespace
1598 */
1595 if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) 1599 if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
1596 return ERR_PTR(-EINVAL); 1600 return ERR_PTR(-EINVAL);
1597 1601
@@ -2067,6 +2071,8 @@ long _do_fork(unsigned long clone_flags,
2067 int __user *child_tidptr, 2071 int __user *child_tidptr,
2068 unsigned long tls) 2072 unsigned long tls)
2069{ 2073{
2074 struct completion vfork;
2075 struct pid *pid;
2070 struct task_struct *p; 2076 struct task_struct *p;
2071 int trace = 0; 2077 int trace = 0;
2072 long nr; 2078 long nr;
@@ -2092,43 +2098,40 @@ long _do_fork(unsigned long clone_flags,
2092 p = copy_process(clone_flags, stack_start, stack_size, 2098 p = copy_process(clone_flags, stack_start, stack_size,
2093 child_tidptr, NULL, trace, tls, NUMA_NO_NODE); 2099 child_tidptr, NULL, trace, tls, NUMA_NO_NODE);
2094 add_latent_entropy(); 2100 add_latent_entropy();
2101
2102 if (IS_ERR(p))
2103 return PTR_ERR(p);
2104
2095 /* 2105 /*
2096 * Do this prior waking up the new thread - the thread pointer 2106 * Do this prior waking up the new thread - the thread pointer
2097 * might get invalid after that point, if the thread exits quickly. 2107 * might get invalid after that point, if the thread exits quickly.
2098 */ 2108 */
2099 if (!IS_ERR(p)) { 2109 trace_sched_process_fork(current, p);
2100 struct completion vfork;
2101 struct pid *pid;
2102
2103 trace_sched_process_fork(current, p);
2104 2110
2105 pid = get_task_pid(p, PIDTYPE_PID); 2111 pid = get_task_pid(p, PIDTYPE_PID);
2106 nr = pid_vnr(pid); 2112 nr = pid_vnr(pid);
2107 2113
2108 if (clone_flags & CLONE_PARENT_SETTID) 2114 if (clone_flags & CLONE_PARENT_SETTID)
2109 put_user(nr, parent_tidptr); 2115 put_user(nr, parent_tidptr);
2110 2116
2111 if (clone_flags & CLONE_VFORK) { 2117 if (clone_flags & CLONE_VFORK) {
2112 p->vfork_done = &vfork; 2118 p->vfork_done = &vfork;
2113 init_completion(&vfork); 2119 init_completion(&vfork);
2114 get_task_struct(p); 2120 get_task_struct(p);
2115 } 2121 }
2116
2117 wake_up_new_task(p);
2118 2122
2119 /* forking complete and child started to run, tell ptracer */ 2123 wake_up_new_task(p);
2120 if (unlikely(trace))
2121 ptrace_event_pid(trace, pid);
2122 2124
2123 if (clone_flags & CLONE_VFORK) { 2125 /* forking complete and child started to run, tell ptracer */
2124 if (!wait_for_vfork_done(p, &vfork)) 2126 if (unlikely(trace))
2125 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); 2127 ptrace_event_pid(trace, pid);
2126 }
2127 2128
2128 put_pid(pid); 2129 if (clone_flags & CLONE_VFORK) {
2129 } else { 2130 if (!wait_for_vfork_done(p, &vfork))
2130 nr = PTR_ERR(p); 2131 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
2131 } 2132 }
2133
2134 put_pid(pid);
2132 return nr; 2135 return nr;
2133} 2136}
2134 2137