diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-05-05 02:11:36 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-09 08:39:00 +0200 |
commit | 19d860a140beac48a1377f179e693abe86a9dac9 (patch) | |
tree | 4da809a162a3b9aea8575828f52e150b26ca6ff1 /fs/exec.c | |
parent | dcache.c: call ->d_prune() regardless of d_unhashed() (diff) | |
download | linux-19d860a140beac48a1377f179e693abe86a9dac9.tar.xz linux-19d860a140beac48a1377f179e693abe86a9dac9.zip |
handle suicide on late failure exits in execve() in search_binary_handler()
... rather than doing that in the guts of ->load_binary().
[updated to fix the bug spotted by Shentino - for SIGSEGV we really need
something stronger than send_sig_info(); again, better do that in one place]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/exec.c b/fs/exec.c index a2b42a98c743..7302b75a9820 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1372,18 +1372,23 @@ int search_binary_handler(struct linux_binprm *bprm) read_unlock(&binfmt_lock); bprm->recursion_depth++; retval = fmt->load_binary(bprm); + read_lock(&binfmt_lock); + put_binfmt(fmt); bprm->recursion_depth--; - if (retval >= 0 || retval != -ENOEXEC || - bprm->mm == NULL || bprm->file == NULL) { - put_binfmt(fmt); + if (retval < 0 && !bprm->mm) { + /* we got to flush_old_exec() and failed after it */ + read_unlock(&binfmt_lock); + force_sigsegv(SIGSEGV, current); + return retval; + } + if (retval != -ENOEXEC || !bprm->file) { + read_unlock(&binfmt_lock); return retval; } - read_lock(&binfmt_lock); - put_binfmt(fmt); } read_unlock(&binfmt_lock); - if (need_retry && retval == -ENOEXEC) { + if (need_retry) { if (printable(bprm->buf[0]) && printable(bprm->buf[1]) && printable(bprm->buf[2]) && printable(bprm->buf[3])) return retval; |