mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
fs/binfmt_elf.c: extract elf_read() function
ELF reads done by the kernel have very complicated error detection code which better live in one place. Link: http://lkml.kernel.org/r/20191005165215.GB26927@avx2 Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
81696d5d54
commit
658c033565
@ -404,6 +404,17 @@ static unsigned long total_mapping_size(const struct elf_phdr *cmds, int nr)
|
|||||||
ELF_PAGESTART(cmds[first_idx].p_vaddr);
|
ELF_PAGESTART(cmds[first_idx].p_vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int elf_read(struct file *file, void *buf, size_t len, loff_t pos)
|
||||||
|
{
|
||||||
|
ssize_t rv;
|
||||||
|
|
||||||
|
rv = kernel_read(file, buf, len, &pos);
|
||||||
|
if (unlikely(rv != len)) {
|
||||||
|
return (rv < 0) ? rv : -EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load_elf_phdrs() - load ELF program headers
|
* load_elf_phdrs() - load ELF program headers
|
||||||
* @elf_ex: ELF header of the binary whose program headers should be loaded
|
* @elf_ex: ELF header of the binary whose program headers should be loaded
|
||||||
@ -418,7 +429,6 @@ static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
|
|||||||
{
|
{
|
||||||
struct elf_phdr *elf_phdata = NULL;
|
struct elf_phdr *elf_phdata = NULL;
|
||||||
int retval, err = -1;
|
int retval, err = -1;
|
||||||
loff_t pos = elf_ex->e_phoff;
|
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -439,9 +449,9 @@ static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Read in the program headers */
|
/* Read in the program headers */
|
||||||
retval = kernel_read(elf_file, elf_phdata, size, &pos);
|
retval = elf_read(elf_file, elf_phdata, size, elf_ex->e_phoff);
|
||||||
if (retval != size) {
|
if (retval < 0) {
|
||||||
err = (retval < 0) ? retval : -EIO;
|
err = retval;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,7 +730,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
elf_ppnt = elf_phdata;
|
elf_ppnt = elf_phdata;
|
||||||
for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
|
for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
|
||||||
char *elf_interpreter;
|
char *elf_interpreter;
|
||||||
loff_t pos;
|
|
||||||
|
|
||||||
if (elf_ppnt->p_type != PT_INTERP)
|
if (elf_ppnt->p_type != PT_INTERP)
|
||||||
continue;
|
continue;
|
||||||
@ -738,14 +747,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
if (!elf_interpreter)
|
if (!elf_interpreter)
|
||||||
goto out_free_ph;
|
goto out_free_ph;
|
||||||
|
|
||||||
pos = elf_ppnt->p_offset;
|
retval = elf_read(bprm->file, elf_interpreter, elf_ppnt->p_filesz,
|
||||||
retval = kernel_read(bprm->file, elf_interpreter,
|
elf_ppnt->p_offset);
|
||||||
elf_ppnt->p_filesz, &pos);
|
if (retval < 0)
|
||||||
if (retval != elf_ppnt->p_filesz) {
|
|
||||||
if (retval >= 0)
|
|
||||||
retval = -EIO;
|
|
||||||
goto out_free_interp;
|
goto out_free_interp;
|
||||||
}
|
|
||||||
/* make sure path is NULL terminated */
|
/* make sure path is NULL terminated */
|
||||||
retval = -ENOEXEC;
|
retval = -ENOEXEC;
|
||||||
if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
|
if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
|
||||||
@ -764,14 +769,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
would_dump(bprm, interpreter);
|
would_dump(bprm, interpreter);
|
||||||
|
|
||||||
/* Get the exec headers */
|
/* Get the exec headers */
|
||||||
pos = 0;
|
retval = elf_read(interpreter, &loc->interp_elf_ex,
|
||||||
retval = kernel_read(interpreter, &loc->interp_elf_ex,
|
sizeof(loc->interp_elf_ex), 0);
|
||||||
sizeof(loc->interp_elf_ex), &pos);
|
if (retval < 0)
|
||||||
if (retval != sizeof(loc->interp_elf_ex)) {
|
|
||||||
if (retval >= 0)
|
|
||||||
retval = -EIO;
|
|
||||||
goto out_free_dentry;
|
goto out_free_dentry;
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1174,11 +1175,10 @@ static int load_elf_library(struct file *file)
|
|||||||
unsigned long elf_bss, bss, len;
|
unsigned long elf_bss, bss, len;
|
||||||
int retval, error, i, j;
|
int retval, error, i, j;
|
||||||
struct elfhdr elf_ex;
|
struct elfhdr elf_ex;
|
||||||
loff_t pos = 0;
|
|
||||||
|
|
||||||
error = -ENOEXEC;
|
error = -ENOEXEC;
|
||||||
retval = kernel_read(file, &elf_ex, sizeof(elf_ex), &pos);
|
retval = elf_read(file, &elf_ex, sizeof(elf_ex), 0);
|
||||||
if (retval != sizeof(elf_ex))
|
if (retval < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
|
if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
|
||||||
@ -1203,9 +1203,8 @@ static int load_elf_library(struct file *file)
|
|||||||
|
|
||||||
eppnt = elf_phdata;
|
eppnt = elf_phdata;
|
||||||
error = -ENOEXEC;
|
error = -ENOEXEC;
|
||||||
pos = elf_ex.e_phoff;
|
retval = elf_read(file, eppnt, j, elf_ex.e_phoff);
|
||||||
retval = kernel_read(file, eppnt, j, &pos);
|
if (retval < 0)
|
||||||
if (retval != j)
|
|
||||||
goto out_free_ph;
|
goto out_free_ph;
|
||||||
|
|
||||||
for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
|
for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user