From: Marcelo Tosatti , Solar Designer The following patch changes the following on ELF parsing/loading code (fs/binfmt_elf): - Stronger validity checks on ELF files: treat e_phnum (program header count) < 1 as invalid treat p_filesz (file size) < 2 invalid on program header interp. case - Saner return error codes - Make sure SIGKILL is delivered on error handling Signed-off-by: Andrew Morton --- 25-akpm/fs/binfmt_elf.c | 21 +++++++++++++-------- 1 files changed, 13 insertions(+), 8 deletions(-) diff -puN fs/binfmt_elf.c~binfmt_elf-fix-return-error-codes-and-early-corrupt-binary-detection fs/binfmt_elf.c --- 25/fs/binfmt_elf.c~binfmt_elf-fix-return-error-codes-and-early-corrupt-binary-detection Thu Jan 6 15:40:29 2005 +++ 25-akpm/fs/binfmt_elf.c Thu Jan 6 15:40:29 2005 @@ -322,7 +322,8 @@ static unsigned long load_elf_interp(str */ if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) goto out; - if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) + if (interp_elf_ex->e_phnum < 1 || + interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr)) goto out; /* Now read in all of the header information */ @@ -524,12 +525,13 @@ static int load_elf_binary(struct linux_ /* Now read in all of the header information */ - retval = -ENOMEM; if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) goto out; - if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr)) + if (loc->elf_ex.e_phnum < 1 || + loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr)) goto out; size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); + retval = -ENOMEM; elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); if (!elf_phdata) goto out; @@ -575,10 +577,12 @@ static int load_elf_binary(struct linux_ * is an a.out format binary */ - retval = -ENOMEM; + retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || - elf_ppnt->p_filesz == 0) + elf_ppnt->p_filesz < 2) goto out_free_file; + + retval = -ENOMEM; elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) @@ -593,7 +597,7 @@ static int load_elf_binary(struct linux_ goto out_free_interp; } /* make sure path is NULL terminated */ - retval = -EINVAL; + retval = -ENOEXEC; if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') goto out_free_interp; @@ -868,8 +872,9 @@ static int load_elf_binary(struct linux_ interpreter, &interp_load_addr); if (BAD_ADDR(elf_entry)) { - printk(KERN_ERR "Unable to load interpreter\n"); - send_sig(SIGSEGV, current, 0); + printk(KERN_ERR "Unable to load interpreter %.128s\n", + elf_interpreter); + force_sig(SIGSEGV, current); retval = -ENOEXEC; /* Nobody gets to see this, but.. */ goto out_free_dentry; } _