Skip to content

Commit 27e68f0

Browse files
committed
exec: Trivial cleanups for exec
This is a continuation of my work to clean up exec so it's more difficult problems are approachable. The changes correct some comments, and moves the point_of_no_return variable up to when the point_of_no_return actually occurs. Eric W. Biederman (5): exec: Move the comment from above de_thread to above unshare_sighand exec: Fix spelling of search_binary_handler in a comment exec: Run sync_mm_rss before taking exec_update_mutex exec: Move handling of the point of no return to the top level exec: Set the point of no return sooner fs/exec.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: "Eric W. Biederman" <[email protected]>
2 parents b213c2d + 6834e0b commit 27e68f0

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

fs/exec.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,13 +1051,14 @@ static int exec_mmap(struct mm_struct *mm)
10511051
tsk = current;
10521052
old_mm = current->mm;
10531053
exec_mm_release(tsk, old_mm);
1054+
if (old_mm)
1055+
sync_mm_rss(old_mm);
10541056

10551057
ret = mutex_lock_killable(&tsk->signal->exec_update_mutex);
10561058
if (ret)
10571059
return ret;
10581060

10591061
if (old_mm) {
1060-
sync_mm_rss(old_mm);
10611062
/*
10621063
* Make sure that if there is a core dump in progress
10631064
* for the old mm, we get out and die instead of going
@@ -1093,12 +1094,6 @@ static int exec_mmap(struct mm_struct *mm)
10931094
return 0;
10941095
}
10951096

1096-
/*
1097-
* This function makes sure the current process has its own signal table,
1098-
* so that flush_signal_handlers can later reset the handlers without
1099-
* disturbing other processes. (Other processes might share the signal
1100-
* table via the CLONE_SIGHAND option to clone().)
1101-
*/
11021097
static int de_thread(struct task_struct *tsk)
11031098
{
11041099
struct signal_struct *sig = tsk->signal;
@@ -1240,6 +1235,12 @@ static int de_thread(struct task_struct *tsk)
12401235
}
12411236

12421237

1238+
/*
1239+
* This function makes sure the current process has its own signal table,
1240+
* so that flush_signal_handlers can later reset the handlers without
1241+
* disturbing other processes. (Other processes might share the signal
1242+
* table via the CLONE_SIGHAND option to clone().)
1243+
*/
12431244
static int unshare_sighand(struct task_struct *me)
12441245
{
12451246
struct sighand_struct *oldsighand = me->sighand;
@@ -1296,13 +1297,18 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
12961297
* Calling this is the point of no return. None of the failures will be
12971298
* seen by userspace since either the process is already taking a fatal
12981299
* signal (via de_thread() or coredump), or will have SEGV raised
1299-
* (after exec_mmap()) by search_binary_handlers (see below).
1300+
* (after exec_mmap()) by search_binary_handler (see below).
13001301
*/
13011302
int begin_new_exec(struct linux_binprm * bprm)
13021303
{
13031304
struct task_struct *me = current;
13041305
int retval;
13051306

1307+
/*
1308+
* Ensure all future errors are fatal.
1309+
*/
1310+
bprm->point_of_no_return = true;
1311+
13061312
/*
13071313
* Make this the only thread in the thread group.
13081314
*/
@@ -1325,13 +1331,6 @@ int begin_new_exec(struct linux_binprm * bprm)
13251331
if (retval)
13261332
goto out;
13271333

1328-
/*
1329-
* With the new mm installed it is completely impossible to
1330-
* fail and return to the original process. If anything from
1331-
* here on returns an error, the check in
1332-
* search_binary_handler() will SEGV current.
1333-
*/
1334-
bprm->point_of_no_return = true;
13351334
bprm->mm = NULL;
13361335

13371336
#ifdef CONFIG_POSIX_TIMERS
@@ -1720,13 +1719,8 @@ int search_binary_handler(struct linux_binprm *bprm)
17201719

17211720
read_lock(&binfmt_lock);
17221721
put_binfmt(fmt);
1723-
if (retval < 0 && bprm->point_of_no_return) {
1724-
/* we got to flush_old_exec() and failed after it */
1725-
read_unlock(&binfmt_lock);
1726-
force_sigsegv(SIGSEGV);
1727-
return retval;
1728-
}
1729-
if (retval != -ENOEXEC || !bprm->file) {
1722+
if (bprm->point_of_no_return || !bprm->file ||
1723+
(retval != -ENOEXEC)) {
17301724
read_unlock(&binfmt_lock);
17311725
return retval;
17321726
}
@@ -1897,6 +1891,14 @@ static int __do_execve_file(int fd, struct filename *filename,
18971891
return retval;
18981892

18991893
out:
1894+
/*
1895+
* If past the point of no return ensure the the code never
1896+
* returns to the userspace process. Use an existing fatal
1897+
* signal if present otherwise terminate the process with
1898+
* SIGSEGV.
1899+
*/
1900+
if (bprm->point_of_no_return && !fatal_signal_pending(current))
1901+
force_sigsegv(SIGSEGV);
19001902
if (bprm->mm) {
19011903
acct_arg_size(bprm, 0);
19021904
mmput(bprm->mm);

0 commit comments

Comments
 (0)