mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
binfmt_elf: load interpreter program headers earlier
Load the program headers of an ELF interpreter early enough in load_elf_binary that they can be examined before it's too late to return an error from an exec syscall. This patch does not perform any such checking, it merely lays the groundwork for a further patch to do so. No functional change is intended. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7675/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
6a8d38945c
commit
a9d9ef133f
@ -447,9 +447,8 @@ out:
|
|||||||
|
|
||||||
static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
||||||
struct file *interpreter, unsigned long *interp_map_addr,
|
struct file *interpreter, unsigned long *interp_map_addr,
|
||||||
unsigned long no_base)
|
unsigned long no_base, struct elf_phdr *interp_elf_phdata)
|
||||||
{
|
{
|
||||||
struct elf_phdr *elf_phdata;
|
|
||||||
struct elf_phdr *eppnt;
|
struct elf_phdr *eppnt;
|
||||||
unsigned long load_addr = 0;
|
unsigned long load_addr = 0;
|
||||||
int load_addr_set = 0;
|
int load_addr_set = 0;
|
||||||
@ -467,17 +466,14 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|||||||
if (!interpreter->f_op->mmap)
|
if (!interpreter->f_op->mmap)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
elf_phdata = load_elf_phdrs(interp_elf_ex, interpreter);
|
total_size = total_mapping_size(interp_elf_phdata,
|
||||||
if (!elf_phdata)
|
interp_elf_ex->e_phnum);
|
||||||
goto out;
|
|
||||||
|
|
||||||
total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
|
|
||||||
if (!total_size) {
|
if (!total_size) {
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
goto out_close;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
eppnt = elf_phdata;
|
eppnt = interp_elf_phdata;
|
||||||
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
|
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
|
||||||
if (eppnt->p_type == PT_LOAD) {
|
if (eppnt->p_type == PT_LOAD) {
|
||||||
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
|
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
|
||||||
@ -504,7 +500,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|||||||
*interp_map_addr = map_addr;
|
*interp_map_addr = map_addr;
|
||||||
error = map_addr;
|
error = map_addr;
|
||||||
if (BAD_ADDR(map_addr))
|
if (BAD_ADDR(map_addr))
|
||||||
goto out_close;
|
goto out;
|
||||||
|
|
||||||
if (!load_addr_set &&
|
if (!load_addr_set &&
|
||||||
interp_elf_ex->e_type == ET_DYN) {
|
interp_elf_ex->e_type == ET_DYN) {
|
||||||
@ -523,7 +519,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|||||||
eppnt->p_memsz > TASK_SIZE ||
|
eppnt->p_memsz > TASK_SIZE ||
|
||||||
TASK_SIZE - eppnt->p_memsz < k) {
|
TASK_SIZE - eppnt->p_memsz < k) {
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
goto out_close;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -553,7 +549,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|||||||
*/
|
*/
|
||||||
if (padzero(elf_bss)) {
|
if (padzero(elf_bss)) {
|
||||||
error = -EFAULT;
|
error = -EFAULT;
|
||||||
goto out_close;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What we have mapped so far */
|
/* What we have mapped so far */
|
||||||
@ -562,13 +558,10 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|||||||
/* Map the last of the bss segment */
|
/* Map the last of the bss segment */
|
||||||
error = vm_brk(elf_bss, last_bss - elf_bss);
|
error = vm_brk(elf_bss, last_bss - elf_bss);
|
||||||
if (BAD_ADDR(error))
|
if (BAD_ADDR(error))
|
||||||
goto out_close;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = load_addr;
|
error = load_addr;
|
||||||
|
|
||||||
out_close:
|
|
||||||
kfree(elf_phdata);
|
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -605,7 +598,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
int load_addr_set = 0;
|
int load_addr_set = 0;
|
||||||
char * elf_interpreter = NULL;
|
char * elf_interpreter = NULL;
|
||||||
unsigned long error;
|
unsigned long error;
|
||||||
struct elf_phdr *elf_ppnt, *elf_phdata;
|
struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
|
||||||
unsigned long elf_bss, elf_brk;
|
unsigned long elf_bss, elf_brk;
|
||||||
int retval, i;
|
int retval, i;
|
||||||
unsigned long elf_entry;
|
unsigned long elf_entry;
|
||||||
@ -729,6 +722,12 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
/* Verify the interpreter has a valid arch */
|
/* Verify the interpreter has a valid arch */
|
||||||
if (!elf_check_arch(&loc->interp_elf_ex))
|
if (!elf_check_arch(&loc->interp_elf_ex))
|
||||||
goto out_free_dentry;
|
goto out_free_dentry;
|
||||||
|
|
||||||
|
/* Load the interpreter program headers */
|
||||||
|
interp_elf_phdata = load_elf_phdrs(&loc->interp_elf_ex,
|
||||||
|
interpreter);
|
||||||
|
if (!interp_elf_phdata)
|
||||||
|
goto out_free_dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush all traces of the currently running executable */
|
/* Flush all traces of the currently running executable */
|
||||||
@ -903,7 +902,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
elf_entry = load_elf_interp(&loc->interp_elf_ex,
|
elf_entry = load_elf_interp(&loc->interp_elf_ex,
|
||||||
interpreter,
|
interpreter,
|
||||||
&interp_map_addr,
|
&interp_map_addr,
|
||||||
load_bias);
|
load_bias, interp_elf_phdata);
|
||||||
if (!IS_ERR((void *)elf_entry)) {
|
if (!IS_ERR((void *)elf_entry)) {
|
||||||
/*
|
/*
|
||||||
* load_elf_interp() returns relocation
|
* load_elf_interp() returns relocation
|
||||||
@ -994,6 +993,7 @@ out_ret:
|
|||||||
|
|
||||||
/* error cleanup */
|
/* error cleanup */
|
||||||
out_free_dentry:
|
out_free_dentry:
|
||||||
|
kfree(interp_elf_phdata);
|
||||||
allow_write_access(interpreter);
|
allow_write_access(interpreter);
|
||||||
if (interpreter)
|
if (interpreter)
|
||||||
fput(interpreter);
|
fput(interpreter);
|
||||||
|
Loading…
Reference in New Issue
Block a user