Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

exec: Move exec_mmap right after de_thread in flush_old_exec

I have read through the code in exec_mmap and I do not see anything
that depends on sighand or the sighand lock, or on signals in anyway
so this should be safe.

This rearrangement of code has two significant benefits. It makes
the determination of passing the point of no return by testing bprm->mm
accurate. All failures prior to that point in flush_old_exec are
either truly recoverable or they are fatal.

Further this consolidates all of the possible indefinite waits for
userspace together at the top of flush_old_exec. The possible wait
for a ptracer on PTRACE_EVENT_EXIT, the possible wait for a page fault
to be resolved in clear_child_tid, and the possible wait for a page
fault in exit_robust_list.

This consolidation allows the creation of a mutex to replace
cred_guard_mutex that is not held over possible indefinite userspace
waits. Which will allow removing deadlock scenarios from the kernel.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

+12 -12
+12 -12
fs/exec.c
··· 1272 1272 if (retval) 1273 1273 goto out; 1274 1274 1275 - #ifdef CONFIG_POSIX_TIMERS 1276 - exit_itimers(me->signal); 1277 - flush_itimer_signals(); 1278 - #endif 1279 - 1280 - /* 1281 - * Make the signal table private. 1282 - */ 1283 - retval = unshare_sighand(me); 1284 - if (retval) 1285 - goto out; 1286 - 1287 1275 /* 1288 1276 * Must be called _before_ exec_mmap() as bprm->mm is 1289 1277 * not visibile until then. This also enables the update ··· 1294 1306 * in search_binary_handler() will SEGV current. 1295 1307 */ 1296 1308 bprm->mm = NULL; 1309 + 1310 + #ifdef CONFIG_POSIX_TIMERS 1311 + exit_itimers(me->signal); 1312 + flush_itimer_signals(); 1313 + #endif 1314 + 1315 + /* 1316 + * Make the signal table private. 1317 + */ 1318 + retval = unshare_sighand(me); 1319 + if (retval) 1320 + goto out; 1297 1321 1298 1322 set_fs(USER_DS); 1299 1323 me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |