diff options
Diffstat (limited to 'fs/binfmt_elf.c')
| -rw-r--r-- | fs/binfmt_elf.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 0ecc44fb0551..6eb6971bdee2 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -88,7 +88,10 @@ static int set_brk(unsigned long start, unsigned long end) start = ELF_PAGEALIGN(start); end = ELF_PAGEALIGN(end); if (end > start) { - unsigned long addr = do_brk(start, end - start); + unsigned long addr; + down_write(¤t->mm->mmap_sem); + addr = do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); if (BAD_ADDR(addr)) return addr; } @@ -322,7 +325,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, */ 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 */ @@ -408,7 +412,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, /* Map the last of the bss segment */ if (last_bss > elf_bss) { + down_write(¤t->mm->mmap_sem); error = do_brk(elf_bss, last_bss - elf_bss); + up_write(¤t->mm->mmap_sem); if (BAD_ADDR(error)) goto out_close; } @@ -448,7 +454,9 @@ static unsigned long load_aout_interp(struct exec * interp_ex, goto out; } + down_write(¤t->mm->mmap_sem); do_brk(0, text_data); + up_write(¤t->mm->mmap_sem); if (!interpreter->f_op || !interpreter->f_op->read) goto out; if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) @@ -456,8 +464,11 @@ static unsigned long load_aout_interp(struct exec * interp_ex, flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); + + down_write(¤t->mm->mmap_sem); do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), interp_ex->a_bss); + up_write(¤t->mm->mmap_sem); elf_entry = interp_ex->a_entry; out: @@ -524,12 +535,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) /* 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 +587,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) * 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 +607,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) 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 +882,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\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; } @@ -1215,16 +1230,16 @@ static void fill_prstatus(struct elf_prstatus *prstatus, * this and each other thread to finish dying after the * core dump synchronization phase. */ - jiffies_to_timeval(p->utime + p->signal->utime, + cputime_to_timeval(cputime_add(p->utime, p->signal->utime), &prstatus->pr_utime); - jiffies_to_timeval(p->stime + p->signal->stime, + cputime_to_timeval(cputime_add(p->stime, p->signal->stime), &prstatus->pr_stime); } else { - jiffies_to_timeval(p->utime, &prstatus->pr_utime); - jiffies_to_timeval(p->stime, &prstatus->pr_stime); + cputime_to_timeval(p->utime, &prstatus->pr_utime); + cputime_to_timeval(p->stime, &prstatus->pr_stime); } - jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime); - jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime); + cputime_to_timeval(p->signal->cutime, &prstatus->pr_cutime); + cputime_to_timeval(p->signal->cstime, &prstatus->pr_cstime); } static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, |
