diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 55 |
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 | ||
