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>
This commit is contained in:
Родитель
5cf4a36382
Коммит
cc338010a2
|
@ -687,7 +687,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
struct file *interpreter = NULL; /* to shut gcc up */
|
struct file *interpreter = NULL; /* to shut gcc up */
|
||||||
unsigned long load_addr = 0, load_bias = 0;
|
unsigned long load_addr = 0, load_bias = 0;
|
||||||
int load_addr_set = 0;
|
int load_addr_set = 0;
|
||||||
char * elf_interpreter = NULL;
|
|
||||||
unsigned long error;
|
unsigned long error;
|
||||||
struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
|
struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
|
||||||
unsigned long elf_bss, elf_brk;
|
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++) {
|
for (i = 0; i < loc->elf_ex.e_phnum; i++) {
|
||||||
if (elf_ppnt->p_type == PT_INTERP) {
|
if (elf_ppnt->p_type == PT_INTERP) {
|
||||||
|
char *elf_interpreter;
|
||||||
loff_t pos;
|
loff_t pos;
|
||||||
|
|
||||||
/* This is the program interpreter used for
|
/* This is the program interpreter used for
|
||||||
|
@ -774,9 +774,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
goto out_free_interp;
|
goto out_free_interp;
|
||||||
|
|
||||||
interpreter = open_exec(elf_interpreter);
|
interpreter = open_exec(elf_interpreter);
|
||||||
|
kfree(elf_interpreter);
|
||||||
retval = PTR_ERR(interpreter);
|
retval = PTR_ERR(interpreter);
|
||||||
if (IS_ERR(interpreter))
|
if (IS_ERR(interpreter))
|
||||||
goto out_free_interp;
|
goto out_free_ph;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the binary is not readable then enforce
|
* If the binary is not readable then enforce
|
||||||
|
@ -796,6 +797,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
out_free_interp:
|
||||||
|
kfree(elf_interpreter);
|
||||||
|
goto out_free_ph;
|
||||||
}
|
}
|
||||||
elf_ppnt++;
|
elf_ppnt++;
|
||||||
}
|
}
|
||||||
|
@ -820,7 +825,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some simple consistency checks for the interpreter */
|
/* Some simple consistency checks for the interpreter */
|
||||||
if (elf_interpreter) {
|
if (interpreter) {
|
||||||
retval = -ELIBBAD;
|
retval = -ELIBBAD;
|
||||||
/* Not an ELF interpreter */
|
/* Not an ELF interpreter */
|
||||||
if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
|
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
|
* independently randomized mmap region (0 load_bias
|
||||||
* without MAP_FIXED).
|
* without MAP_FIXED).
|
||||||
*/
|
*/
|
||||||
if (elf_interpreter) {
|
if (interpreter) {
|
||||||
load_bias = ELF_ET_DYN_BASE;
|
load_bias = ELF_ET_DYN_BASE;
|
||||||
if (current->flags & PF_RANDOMIZE)
|
if (current->flags & PF_RANDOMIZE)
|
||||||
load_bias += arch_mmap_rnd();
|
load_bias += arch_mmap_rnd();
|
||||||
|
@ -1075,7 +1080,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
goto out_free_dentry;
|
goto out_free_dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_interpreter) {
|
if (interpreter) {
|
||||||
unsigned long interp_map_addr = 0;
|
unsigned long interp_map_addr = 0;
|
||||||
|
|
||||||
elf_entry = load_elf_interp(&loc->interp_elf_ex,
|
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);
|
allow_write_access(interpreter);
|
||||||
fput(interpreter);
|
fput(interpreter);
|
||||||
kfree(elf_interpreter);
|
|
||||||
} else {
|
} else {
|
||||||
elf_entry = loc->elf_ex.e_entry;
|
elf_entry = loc->elf_ex.e_entry;
|
||||||
if (BAD_ADDR(elf_entry)) {
|
if (BAD_ADDR(elf_entry)) {
|
||||||
|
@ -1114,7 +1118,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||||
set_binfmt(&elf_format);
|
set_binfmt(&elf_format);
|
||||||
|
|
||||||
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||||
retval = arch_setup_additional_pages(bprm, !!elf_interpreter);
|
retval = arch_setup_additional_pages(bprm, !!interpreter);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto out;
|
goto out;
|
||||||
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
|
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
|
||||||
|
@ -1175,8 +1179,6 @@ out_free_dentry:
|
||||||
allow_write_access(interpreter);
|
allow_write_access(interpreter);
|
||||||
if (interpreter)
|
if (interpreter)
|
||||||
fput(interpreter);
|
fput(interpreter);
|
||||||
out_free_interp:
|
|
||||||
kfree(elf_interpreter);
|
|
||||||
out_free_ph:
|
out_free_ph:
|
||||||
kfree(elf_phdata);
|
kfree(elf_phdata);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче