diff options
Diffstat (limited to 'fs/binfmt_elf.c')
| -rw-r--r-- | fs/binfmt_elf.c | 15 | 
1 files changed, 7 insertions, 8 deletions
| diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d0434406eaeb..f42e64210ee5 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -84,7 +84,7 @@ static struct linux_binfmt elf_format = {  		.min_coredump	= ELF_EXEC_PAGESIZE  }; -#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) +#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)  static int set_brk(unsigned long start, unsigned long end)  { @@ -394,7 +394,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,  			 * <= p_memsize so it's only necessary to check p_memsz.  			 */  			k = load_addr + eppnt->p_vaddr; -			if (k > TASK_SIZE || +			if (BAD_ADDR(k) ||  			    eppnt->p_filesz > eppnt->p_memsz ||  			    eppnt->p_memsz > TASK_SIZE ||  			    TASK_SIZE - eppnt->p_memsz < k) { @@ -887,7 +887,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)  		 * allowed task size. Note that p_filesz must always be  		 * <= p_memsz so it is only necessary to check p_memsz.  		 */ -		if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || +		if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||  		    elf_ppnt->p_memsz > TASK_SIZE ||  		    TASK_SIZE - elf_ppnt->p_memsz < k) {  			/* set_brk can never work. Avoid overflows. */ @@ -941,10 +941,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)  						    interpreter,  						    &interp_load_addr);  		if (BAD_ADDR(elf_entry)) { -			printk(KERN_ERR "Unable to load interpreter %.128s\n", -				elf_interpreter);  			force_sig(SIGSEGV, current); -			retval = -ENOEXEC; /* Nobody gets to see this, but.. */ +			retval = IS_ERR((void *)elf_entry) ? +					(int)elf_entry : -EINVAL;  			goto out_free_dentry;  		}  		reloc_func_desc = interp_load_addr; @@ -955,8 +954,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)  	} else {  		elf_entry = loc->elf_ex.e_entry;  		if (BAD_ADDR(elf_entry)) { -			send_sig(SIGSEGV, current, 0); -			retval = -ENOEXEC; /* Nobody gets to see this, but.. */ +			force_sig(SIGSEGV, current); +			retval = -EINVAL;  			goto out_free_dentry;  		}  	} | 
