The START_THREAD arch hook called in binfmt_elf is modified to return a value which the elf loader returns as the final result. This maintains similar behaviour as before but allows any arch specialising this macro to either 1. Abort execution of an elf binary from within start_thread() by returning a negative value or 2. Place a positive value in the first result register for the executing program to access by returning the positive value.
Signed-off-by: Sherwin da Cruz sherwin.dacruz@arm.com --- fs/binfmt_elf.c | 3 +-- fs/compat_binfmt_elf.c | 6 +++++- fs/exec.c | 4 ++-- include/linux/elf.h | 7 +++++-- 4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index dcbb2fc83f14..e7f87bf3ff13 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1441,8 +1441,7 @@ static int load_elf_binary(struct linux_binprm *bprm) #endif
finalize_exec(bprm); - START_THREAD(elf_ex, regs, elf_entry, bprm->p); - retval = 0; + retval = START_THREAD(elf_ex, regs, elf_entry, bprm); out: return retval;
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 413922b85be6..247b9ebd8fbb 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -127,7 +127,11 @@
#ifdef COMPAT_START_THREAD #undef START_THREAD -#define START_THREAD COMPAT_START_THREAD +#define START_THREAD(elf_ex, regs, elf_entry, bprm) \ +({ \ + COMPAT_START_THREAD(elf_ex, regs, elf_entry, bprm->p); \ + 0; /* binfmt_elf return value */ \ +}) #endif
#ifdef compat_arch_setup_additional_pages diff --git a/fs/exec.c b/fs/exec.c index c177f8cc3e00..3edd9601ae9a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1793,7 +1793,7 @@ static int exec_binprm(struct linux_binprm *bprm) trace_sched_process_exec(current, old_pid, bprm); ptrace_event(PTRACE_EVENT_EXEC, old_vpid); proc_exec_connector(current); - return 0; + return ret; }
/* @@ -2003,7 +2003,7 @@ int kernel_execve(const char *kernel_filename, free_bprm(bprm); out_ret: putname(filename); - return retval; + return retval < 0 ? retval : 0; }
static int do_execve(struct filename *filename, diff --git a/include/linux/elf.h b/include/linux/elf.h index 50ca9e34763c..039ad1867045 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -23,8 +23,11 @@ #endif
#ifndef START_THREAD -#define START_THREAD(elf_ex, regs, elf_entry, start_stack) \ - start_thread(regs, elf_entry, start_stack) +#define START_THREAD(elf_ex, regs, elf_entry, bprm) \ +({ \ + start_thread(regs, elf_entry, bprm->p); \ + 0; /* binfmt_elf return value */ \ +}) #endif
#if defined(ARCH_HAS_SETUP_ADDITIONAL_PAGES) && !defined(ARCH_SETUP_ADDITIONAL_PAGES)