--- z/fs/binfmt_elf.c.orig Fri Sep 28 17:30:17 2001 +++ z/fs/binfmt_elf.c Thu Nov 22 03:09:32 2001 @@ -75,13 +75,15 @@ NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE }; -static void set_brk(unsigned long start, unsigned long end) +#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) + +static unsigned long set_brk(unsigned long start, unsigned long end) { start = ELF_PAGEALIGN(start); end = ELF_PAGEALIGN(end); if (end <= start) - return; - do_brk(start, end - start); + return 0; + return do_brk(start, end - start); } @@ -297,6 +299,9 @@ elf_type |= MAP_FIXED; map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type); + error = map_addr; + if (BAD_ADDR(map_addr)) + goto out_close; if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { load_addr = map_addr - ELF_PAGESTART(vaddr); @@ -333,8 +338,11 @@ elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ /* Map the last of the bss segment */ - if (last_bss > elf_bss) - do_brk(elf_bss, last_bss - elf_bss); + if (last_bss > elf_bss) { + error = do_brk(elf_bss, last_bss - elf_bss); + if (BAD_ADDR(error)) + goto out_close; + } *interp_load_addr = load_addr; error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; @@ -407,7 +415,6 @@ int load_addr_set = 0; char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; - mm_segment_t old_fs; unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; unsigned long elf_bss, k, elf_brk; @@ -582,8 +589,6 @@ the image should be loaded at fixed address, not at a variable address. */ - old_fs = get_fs(); - set_fs(get_ds()); for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags; unsigned long vaddr; @@ -591,6 +596,26 @@ if (elf_ppnt->p_type != PT_LOAD) continue; + if (elf_brk > elf_bss) { + unsigned long nbyte; + + /* There was a PT_LOAD segment with p_memsz > p_filesz + before this one. Map anonymous pages, if needed, + and clear the area. */ + error = set_brk (elf_bss + load_bias, elf_brk + load_bias); + /* here retval is zero */ + if (BAD_ADDR(error)) + goto out_free_dentry; + + nbyte = ELF_PAGEOFFSET(elf_bss); + if (nbyte) { + nbyte = ELF_MIN_ALIGN - nbyte; + if (nbyte > elf_brk - elf_bss) + nbyte = elf_brk - elf_bss; + clear_user((void *) elf_bss + load_bias, nbyte); + } + } + if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; @@ -608,6 +633,9 @@ } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); + /* here retval is zero */ + if (BAD_ADDR(error)) + goto out_free_dentry; if (!load_addr_set) { load_addr_set = 1; @@ -634,7 +662,6 @@ if (k > elf_brk) elf_brk = k; } - set_fs(old_fs); elf_entry += load_bias; elf_bss += load_bias; @@ -657,11 +684,10 @@ fput(interpreter); kfree(elf_interpreter); - if (elf_entry == ~0UL) { - printk(KERN_ERR "Unable to load interpreter\n"); - kfree(elf_phdata); - send_sig(SIGSEGV, current, 0); - return 0; + /* here retval is zero */ + if (BAD_ADDR(elf_entry)) { + printk(KERN_WARNING "Unable to load interpreter\n"); + goto out_free_ph; } } @@ -695,7 +721,10 @@ /* Calling set_brk effectively mmaps the pages that we need * for the bss and break sections */ - set_brk(elf_bss, elf_brk); + error = set_brk(elf_bss, elf_brk); + /* here retval is zero */ + if (BAD_ADDR(error)) + goto out; padzero(elf_bss); @@ -734,14 +763,15 @@ start_thread(regs, elf_entry, bprm->p); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); - retval = 0; + /* here retval is zero */ out: return retval; /* error cleanup */ out_free_dentry: allow_write_access(interpreter); - fput(interpreter); + if (interpreter) + fput(interpreter); out_free_interp: if (elf_interpreter) kfree(elf_interpreter); @@ -819,8 +849,11 @@ len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1); bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; - if (bss > len) - do_brk(len, bss - len); + if (bss > len) { + error = do_brk(len, bss - len); + if (BAD_ADDR(error)) + goto out_free_ph; + } error = 0; out_free_ph: