Commit e30c7c3b authored by Takuya Yoshikawa's avatar Takuya Yoshikawa Committed by Linus Torvalds

binfmt_elf_fdpic: Fix clear_user() error handling

clear_user() returns the number of bytes that could not be copied rather than
an error code.  So we should return -EFAULT rather than directly returning the
results.

Without this patch, positive values may be returned to elf_fdpic_map_file()
and the following error handlings do not function as expected.

1.
	ret = elf_fdpic_map_file_constdisp_on_uclinux(params, file, mm);
	if (ret < 0)
		return ret;
2.
	ret = elf_fdpic_map_file_by_direct_mmap(params, file, mm);
	if (ret < 0)
		return ret;
Signed-off-by: default avatarTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarMike Frysinger <vapier@gentoo.org>
CC: Alexander Viro <viro@zeniv.linux.org.uk>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Daisuke HATAYAMA <d.hatayama@jp.fujitsu.com>
CC: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 293a7cfe
...@@ -990,10 +990,9 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( ...@@ -990,10 +990,9 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
/* clear any space allocated but not loaded */ /* clear any space allocated but not loaded */
if (phdr->p_filesz < phdr->p_memsz) { if (phdr->p_filesz < phdr->p_memsz) {
ret = clear_user((void *) (seg->addr + phdr->p_filesz), if (clear_user((void *) (seg->addr + phdr->p_filesz),
phdr->p_memsz - phdr->p_filesz); phdr->p_memsz - phdr->p_filesz))
if (ret) return -EFAULT;
return ret;
} }
if (mm) { if (mm) {
...@@ -1027,7 +1026,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1027,7 +1026,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
struct elf32_fdpic_loadseg *seg; struct elf32_fdpic_loadseg *seg;
struct elf32_phdr *phdr; struct elf32_phdr *phdr;
unsigned long load_addr, delta_vaddr; unsigned long load_addr, delta_vaddr;
int loop, dvset, ret; int loop, dvset;
load_addr = params->load_addr; load_addr = params->load_addr;
delta_vaddr = 0; delta_vaddr = 0;
...@@ -1127,9 +1126,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1127,9 +1126,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
* PT_LOAD */ * PT_LOAD */
if (prot & PROT_WRITE && disp > 0) { if (prot & PROT_WRITE && disp > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
ret = clear_user((void __user *) maddr, disp); if (clear_user((void __user *) maddr, disp))
if (ret) return -EFAULT;
return ret;
maddr += disp; maddr += disp;
} }
...@@ -1164,19 +1162,17 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1164,19 +1162,17 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (prot & PROT_WRITE && excess1 > 0) { if (prot & PROT_WRITE && excess1 > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", kdebug("clear[%d] ad=%lx sz=%lx",
loop, maddr + phdr->p_filesz, excess1); loop, maddr + phdr->p_filesz, excess1);
ret = clear_user((void __user *) maddr + phdr->p_filesz, if (clear_user((void __user *) maddr + phdr->p_filesz,
excess1); excess1))
if (ret) return -EFAULT;
return ret;
} }
#else #else
if (excess > 0) { if (excess > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", kdebug("clear[%d] ad=%lx sz=%lx",
loop, maddr + phdr->p_filesz, excess); loop, maddr + phdr->p_filesz, excess);
ret = clear_user((void *) maddr + phdr->p_filesz, excess); if (clear_user((void *) maddr + phdr->p_filesz, excess))
if (ret) return -EFAULT;
return ret;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment