mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 02:19:54 -04:00
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/87sgga6ze4.fsf@x220.int.ebiederm.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
46
fs/exec.c
46
fs/exec.c
@@ -1051,13 +1051,14 @@ static int exec_mmap(struct mm_struct *mm)
|
||||
tsk = current;
|
||||
old_mm = current->mm;
|
||||
exec_mm_release(tsk, old_mm);
|
||||
if (old_mm)
|
||||
sync_mm_rss(old_mm);
|
||||
|
||||
ret = mutex_lock_killable(&tsk->signal->exec_update_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (old_mm) {
|
||||
sync_mm_rss(old_mm);
|
||||
/*
|
||||
* Make sure that if there is a core dump in progress
|
||||
* for the old mm, we get out and die instead of going
|
||||
@@ -1093,12 +1094,6 @@ static int exec_mmap(struct mm_struct *mm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes sure the current process has its own signal table,
|
||||
* so that flush_signal_handlers can later reset the handlers without
|
||||
* disturbing other processes. (Other processes might share the signal
|
||||
* table via the CLONE_SIGHAND option to clone().)
|
||||
*/
|
||||
static int de_thread(struct task_struct *tsk)
|
||||
{
|
||||
struct signal_struct *sig = tsk->signal;
|
||||
@@ -1240,6 +1235,12 @@ static int de_thread(struct task_struct *tsk)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function makes sure the current process has its own signal table,
|
||||
* so that flush_signal_handlers can later reset the handlers without
|
||||
* disturbing other processes. (Other processes might share the signal
|
||||
* table via the CLONE_SIGHAND option to clone().)
|
||||
*/
|
||||
static int unshare_sighand(struct task_struct *me)
|
||||
{
|
||||
struct sighand_struct *oldsighand = me->sighand;
|
||||
@@ -1296,13 +1297,18 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
|
||||
* Calling this is the point of no return. None of the failures will be
|
||||
* seen by userspace since either the process is already taking a fatal
|
||||
* signal (via de_thread() or coredump), or will have SEGV raised
|
||||
* (after exec_mmap()) by search_binary_handlers (see below).
|
||||
* (after exec_mmap()) by search_binary_handler (see below).
|
||||
*/
|
||||
int begin_new_exec(struct linux_binprm * bprm)
|
||||
{
|
||||
struct task_struct *me = current;
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* Ensure all future errors are fatal.
|
||||
*/
|
||||
bprm->point_of_no_return = true;
|
||||
|
||||
/*
|
||||
* Make this the only thread in the thread group.
|
||||
*/
|
||||
@@ -1325,13 +1331,6 @@ int begin_new_exec(struct linux_binprm * bprm)
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* With the new mm installed it is completely impossible to
|
||||
* fail and return to the original process. If anything from
|
||||
* here on returns an error, the check in
|
||||
* search_binary_handler() will SEGV current.
|
||||
*/
|
||||
bprm->point_of_no_return = true;
|
||||
bprm->mm = NULL;
|
||||
|
||||
#ifdef CONFIG_POSIX_TIMERS
|
||||
@@ -1720,13 +1719,8 @@ int search_binary_handler(struct linux_binprm *bprm)
|
||||
|
||||
read_lock(&binfmt_lock);
|
||||
put_binfmt(fmt);
|
||||
if (retval < 0 && bprm->point_of_no_return) {
|
||||
/* we got to flush_old_exec() and failed after it */
|
||||
read_unlock(&binfmt_lock);
|
||||
force_sigsegv(SIGSEGV);
|
||||
return retval;
|
||||
}
|
||||
if (retval != -ENOEXEC || !bprm->file) {
|
||||
if (bprm->point_of_no_return || !bprm->file ||
|
||||
(retval != -ENOEXEC)) {
|
||||
read_unlock(&binfmt_lock);
|
||||
return retval;
|
||||
}
|
||||
@@ -1897,6 +1891,14 @@ static int __do_execve_file(int fd, struct filename *filename,
|
||||
return retval;
|
||||
|
||||
out:
|
||||
/*
|
||||
* If past the point of no return ensure the the code never
|
||||
* returns to the userspace process. Use an existing fatal
|
||||
* signal if present otherwise terminate the process with
|
||||
* SIGSEGV.
|
||||
*/
|
||||
if (bprm->point_of_no_return && !fatal_signal_pending(current))
|
||||
force_sigsegv(SIGSEGV);
|
||||
if (bprm->mm) {
|
||||
acct_arg_size(bprm, 0);
|
||||
mmput(bprm->mm);
|
||||
|
||||
Reference in New Issue
Block a user