aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-07 01:15:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-07 01:15:42 -0500
commita2e5790d841658485d642196dbb0927303d6c22f (patch)
treeb3d28c9bcb7da6880806146fd22a88a7ee7f733e /kernel/fork.c
parentab2d92ad881da11331280aedf612d82e61cb6d41 (diff)
parent60c3e026d73ccabb075fb70ba02f8512ab40cf2c (diff)
Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: - kasan updates - procfs - lib/bitmap updates - other lib/ updates - checkpatch tweaks - rapidio - ubsan - pipe fixes and cleanups - lots of other misc bits * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (114 commits) Documentation/sysctl/user.txt: fix typo MAINTAINERS: update ARM/QUALCOMM SUPPORT patterns MAINTAINERS: update various PALM patterns MAINTAINERS: update "ARM/OXNAS platform support" patterns MAINTAINERS: update Cortina/Gemini patterns MAINTAINERS: remove ARM/CLKDEV SUPPORT file pattern MAINTAINERS: remove ANDROID ION pattern mm: docs: add blank lines to silence sphinx "Unexpected indentation" errors mm: docs: fix parameter names mismatch mm: docs: fixup punctuation pipe: read buffer limits atomically pipe: simplify round_pipe_size() pipe: reject F_SETPIPE_SZ with size over UINT_MAX pipe: fix off-by-one error when checking buffer limits pipe: actually allow root to exceed the pipe buffer limits pipe, sysctl: remove pipe_proc_fn() pipe, sysctl: drop 'min' parameter from pipe-max-size converter kasan: rework Kconfig settings crash_dump: is_kdump_kernel can be boolean kernel/mutex: mutex_is_locked can be boolean ...
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