Commit 658c0335 authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Linus Torvalds
Browse files

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: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 81696d5d
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -404,6 +404,17 @@ static unsigned long total_mapping_size(const struct elf_phdr *cmds, int nr)
				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
 * @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;
	int retval, err = -1;
	loff_t pos = elf_ex->e_phoff;
	unsigned int size;

	/*
@@ -439,9 +449,9 @@ static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
		goto out;

	/* Read in the program headers */
	retval = kernel_read(elf_file, elf_phdata, size, &pos);
	if (retval != size) {
		err = (retval < 0) ? retval : -EIO;
	retval = elf_read(elf_file, elf_phdata, size, elf_ex->e_phoff);
	if (retval < 0) {
		err = retval;
		goto out;
	}

@@ -720,7 +730,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
	elf_ppnt = elf_phdata;
	for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
		char *elf_interpreter;
		loff_t pos;

		if (elf_ppnt->p_type != PT_INTERP)
			continue;
@@ -738,14 +747,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
		if (!elf_interpreter)
			goto out_free_ph;

		pos = elf_ppnt->p_offset;
		retval = kernel_read(bprm->file, elf_interpreter,
				     elf_ppnt->p_filesz, &pos);
		if (retval != elf_ppnt->p_filesz) {
			if (retval >= 0)
				retval = -EIO;
		retval = elf_read(bprm->file, elf_interpreter, elf_ppnt->p_filesz,
				  elf_ppnt->p_offset);
		if (retval < 0)
			goto out_free_interp;
		}
		/* make sure path is NULL terminated */
		retval = -ENOEXEC;
		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);

		/* Get the exec headers */
		pos = 0;
		retval = kernel_read(interpreter, &loc->interp_elf_ex,
				     sizeof(loc->interp_elf_ex), &pos);
		if (retval != sizeof(loc->interp_elf_ex)) {
			if (retval >= 0)
				retval = -EIO;
		retval = elf_read(interpreter, &loc->interp_elf_ex,
				  sizeof(loc->interp_elf_ex), 0);
		if (retval < 0)
			goto out_free_dentry;
		}

		break;

@@ -1174,11 +1175,10 @@ static int load_elf_library(struct file *file)
	unsigned long elf_bss, bss, len;
	int retval, error, i, j;
	struct elfhdr elf_ex;
	loff_t pos = 0;

	error = -ENOEXEC;
	retval = kernel_read(file, &elf_ex, sizeof(elf_ex), &pos);
	if (retval != sizeof(elf_ex))
	retval = elf_read(file, &elf_ex, sizeof(elf_ex), 0);
	if (retval < 0)
		goto out;

	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
@@ -1203,9 +1203,8 @@ static int load_elf_library(struct file *file)

	eppnt = elf_phdata;
	error = -ENOEXEC;
	pos =  elf_ex.e_phoff;
	retval = kernel_read(file, eppnt, j, &pos);
	if (retval != j)
	retval = elf_read(file, eppnt, j, elf_ex.e_phoff);
	if (retval < 0)
		goto out_free_ph;

	for (j = 0, i = 0; i<elf_ex.e_phnum; i++)