diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2019-05-14 15:43:39 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-14 19:52:50 -0700 |
commit | cc338010a233c0817276b1348692376db4b4b093 (patch) | |
tree | 83b178c1f5c1f49713ff372cb043d7244afe3e63 | |
parent | 5cf4a36382588e601454f2f1dba91a78d385e2c3 (diff) | |
download | linux-cc338010a233c0817276b1348692376db4b4b093.tar.bz2 |
fs/binfmt_elf.c: free PT_INTERP filename ASAP
There is no reason for PT_INTERP filename to linger till the end of the
whole loading process.
Link: http://lkml.kernel.org/r/20190314204953.GD18143@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Nikitas Angelinas <nikitas.angelinas@gmail.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Mukesh Ojha <mojha@codeaurora.org>
[nikitas.angelinas@gmail.com: fix GPF when dereferencing invalid interpreter]
Link: http://lkml.kernel.org/r/20190330140032.GA1527@vostro
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/binfmt_elf.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index ce276a46fa12..7402cbd92046 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -687,7 +687,6 @@ static int load_elf_binary(struct linux_binprm *bprm) struct file *interpreter = NULL; /* to shut gcc up */ unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; - char * elf_interpreter = NULL; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; unsigned long elf_bss, elf_brk; @@ -743,6 +742,7 @@ static int load_elf_binary(struct linux_binprm *bprm) for (i = 0; i < loc->elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { + char *elf_interpreter; loff_t pos; /* This is the program interpreter used for @@ -774,9 +774,10 @@ static int load_elf_binary(struct linux_binprm *bprm) goto out_free_interp; interpreter = open_exec(elf_interpreter); + kfree(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) - goto out_free_interp; + goto out_free_ph; /* * If the binary is not readable then enforce @@ -796,6 +797,10 @@ static int load_elf_binary(struct linux_binprm *bprm) } break; + +out_free_interp: + kfree(elf_interpreter); + goto out_free_ph; } elf_ppnt++; } @@ -820,7 +825,7 @@ static int load_elf_binary(struct linux_binprm *bprm) } /* Some simple consistency checks for the interpreter */ - if (elf_interpreter) { + if (interpreter) { retval = -ELIBBAD; /* Not an ELF interpreter */ if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) @@ -977,7 +982,7 @@ static int load_elf_binary(struct linux_binprm *bprm) * independently randomized mmap region (0 load_bias * without MAP_FIXED). */ - if (elf_interpreter) { + if (interpreter) { load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); @@ -1075,7 +1080,7 @@ static int load_elf_binary(struct linux_binprm *bprm) goto out_free_dentry; } - if (elf_interpreter) { + if (interpreter) { unsigned long interp_map_addr = 0; elf_entry = load_elf_interp(&loc->interp_elf_ex, @@ -1099,7 +1104,6 @@ static int load_elf_binary(struct linux_binprm *bprm) allow_write_access(interpreter); fput(interpreter); - kfree(elf_interpreter); } else { elf_entry = loc->elf_ex.e_entry; if (BAD_ADDR(elf_entry)) { @@ -1114,7 +1118,7 @@ static int load_elf_binary(struct linux_binprm *bprm) set_binfmt(&elf_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES - retval = arch_setup_additional_pages(bprm, !!elf_interpreter); + retval = arch_setup_additional_pages(bprm, !!interpreter); if (retval < 0) goto out; #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ @@ -1175,8 +1179,6 @@ out_free_dentry: allow_write_access(interpreter); if (interpreter) fput(interpreter); -out_free_interp: - kfree(elf_interpreter); out_free_ph: kfree(elf_phdata); goto out; |