diff -ur linux-2.4.28-gentoo-r4/arch/mips/kernel/irixelf.c linux-2.4.28-gentoo-r5/arch/mips/kernel/irixelf.c --- linux-2.4.28-gentoo-r4/arch/mips/kernel/irixelf.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/arch/mips/kernel/irixelf.c 2005-01-07 20:20:32.000000000 +0000 @@ -130,7 +130,7 @@ end = PAGE_ALIGN(end); if (end <= start) return; - do_brk(start, end - start); + do_brk_locked(start, end - start); } @@ -379,7 +379,7 @@ /* Map the last of the bss segment */ if (last_bss > len) { - do_brk(len, (last_bss - len)); + do_brk_locked(len, (last_bss - len)); } kfree(elf_phdata); @@ -567,7 +567,7 @@ unsigned long v; struct prda *pp; - v = do_brk (PRDA_ADDRESS, PAGE_SIZE); + v = do_brk_locked (PRDA_ADDRESS, PAGE_SIZE); if (v < 0) return; @@ -859,7 +859,7 @@ len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; if (bss > len) - do_brk(len, bss-len); + do_brk_locked(len, bss-len); kfree(elf_phdata); return 0; } diff -ur linux-2.4.28-gentoo-r4/arch/sparc64/kernel/binfmt_aout32.c linux-2.4.28-gentoo-r5/arch/sparc64/kernel/binfmt_aout32.c --- linux-2.4.28-gentoo-r4/arch/sparc64/kernel/binfmt_aout32.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/arch/sparc64/kernel/binfmt_aout32.c 2005-01-07 20:20:32.000000000 +0000 @@ -49,7 +49,7 @@ end = PAGE_ALIGN(end); if (end <= start) return; - do_brk(start, end - start); + do_brk_locked(start, end - start); } /* @@ -246,10 +246,10 @@ if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* Fuck me plenty... */ - error = do_brk(N_TXTADDR(ex), ex.a_text); + error = do_brk_locked(N_TXTADDR(ex), ex.a_text); bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), ex.a_text, &pos); - error = do_brk(N_DATADDR(ex), ex.a_data); + error = do_brk_locked(N_DATADDR(ex), ex.a_data); bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -257,7 +257,7 @@ if (N_MAGIC(ex) == OMAGIC) { loff_t pos = fd_offset; - do_brk(N_TXTADDR(ex) & PAGE_MASK, + do_brk_locked(N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1); bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -272,7 +272,7 @@ if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; - do_brk(0, ex.a_text+ex.a_data); + do_brk_locked(0, ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); goto beyond_if; @@ -388,7 +388,7 @@ len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_brk(start_addr + len, bss - len); + error = do_brk_locked(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff -ur linux-2.4.28-gentoo-r4/fs/binfmt_aout.c linux-2.4.28-gentoo-r5/fs/binfmt_aout.c --- linux-2.4.28-gentoo-r4/fs/binfmt_aout.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/fs/binfmt_aout.c 2005-01-07 20:20:32.000000000 +0000 @@ -46,7 +46,7 @@ start = PAGE_ALIGN(start); end = PAGE_ALIGN(end); if (end > start) { - unsigned long addr = do_brk(start, end - start); + unsigned long addr = do_brk_locked(start, end - start); if (BAD_ADDR(addr)) return addr; } @@ -341,10 +341,10 @@ loff_t pos = fd_offset; /* Fuck me plenty... */ /* */ - error = do_brk(N_TXTADDR(ex), ex.a_text); + error = do_brk_locked(N_TXTADDR(ex), ex.a_text); bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), ex.a_text, &pos); - error = do_brk(N_DATADDR(ex), ex.a_data); + error = do_brk_locked(N_DATADDR(ex), ex.a_data); bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -365,7 +365,7 @@ map_size = ex.a_text+ex.a_data; #endif - error = do_brk(text_addr & PAGE_MASK, map_size); + error = do_brk_locked(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -399,7 +399,7 @@ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; - do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); + do_brk_locked(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); flush_icache_range((unsigned long) N_TXTADDR(ex), @@ -500,7 +500,7 @@ error_time = jiffies; } - do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); + do_brk_locked(start_addr, ex.a_text + ex.a_data + ex.a_bss); file->f_op->read(file, (char *)start_addr, ex.a_text + ex.a_data, &pos); @@ -524,7 +524,7 @@ len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_brk(start_addr + len, bss - len); + error = do_brk_locked(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; diff -ur linux-2.4.28-gentoo-r4/fs/binfmt_elf.c linux-2.4.28-gentoo-r5/fs/binfmt_elf.c --- linux-2.4.28-gentoo-r4/fs/binfmt_elf.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/fs/binfmt_elf.c 2005-01-07 20:20:46.000000000 +0000 @@ -88,6 +88,7 @@ static void set_brk(unsigned long start, end = ELF_PAGEALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); #ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC @@ -95,6 +96,7 @@ static void set_brk(unsigned long start, __do_mmap_pgoff(NULL, ELF_PAGEALIGN(start + current->mm->delta_exec), 0UL, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, start); #endif + up_write(¤t->mm->mmap_sem); } @@ -295,7 +297,9 @@ 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 */ @@ -370,7 +370,7 @@ /* Map the last of the bss segment */ if (last_bss > elf_bss) - do_brk(elf_bss, last_bss - elf_bss); + do_brk_locked(elf_bss, last_bss - elf_bss); *interp_load_addr = load_addr; error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; @@ -407,7 +407,7 @@ goto out; } - do_brk(0, text_data); + do_brk_locked(0, text_data); if (!interpreter->f_op || !interpreter->f_op->read) goto out; if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) @@ -415,7 +415,7 @@ flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); - do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), + do_brk_locked(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), interp_ex->a_bss); elf_entry = interp_ex->a_entry; @@ -1271,7 +1271,7 @@ 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); + do_brk_locked(len, bss - len); error = 0; out_free_ph: diff -ur linux-2.4.28-gentoo-r4/include/linux/mm.h linux-2.4.28-gentoo-r5/include/linux/mm.h --- linux-2.4.28-gentoo-r4/include/linux/mm.h 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/include/linux/mm.h 2005-01-07 20:20:32.000000000 +0000 @@ -601,6 +601,7 @@ extern int do_munmap(struct mm_struct *, unsigned long, size_t); extern unsigned long do_brk(unsigned long, unsigned long); +extern unsigned long do_brk_locked(unsigned long, unsigned long); static inline void __vma_unlink(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct * prev) { diff -ur linux-2.4.28-gentoo-r4/kernel/ksyms.c linux-2.4.28-gentoo-r5/kernel/ksyms.c --- linux-2.4.28-gentoo-r4/kernel/ksyms.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/kernel/ksyms.c 2005-01-07 20:20:32.000000000 +0000 @@ -90,6 +90,7 @@ EXPORT_SYMBOL(__do_mmap_pgoff); EXPORT_SYMBOL(do_munmap); EXPORT_SYMBOL(do_brk); +EXPORT_SYMBOL(do_brk_locked); EXPORT_SYMBOL(exit_mm); EXPORT_SYMBOL(exit_files); EXPORT_SYMBOL(exit_fs); diff -ur linux-2.4.28-gentoo-r4/mm/mmap.c linux-2.4.28-gentoo-r5/mm/mmap.c --- linux-2.4.28-gentoo-r4/mm/mmap.c 2005-01-07 20:33:12.000000000 +0000 +++ linux-2.4.28-gentoo-r5/mm/mmap.c 2005-01-07 20:20:32.000000000 +0000 @@ -1401,6 +1401,21 @@ return addr; } +/* locking version of do_brk. */ +unsigned long do_brk_locked(unsigned long addr, unsigned long len) +{ + unsigned long ret; + + down_write(¤t->mm->mmap_sem); + ret = do_brk(addr, len); + up_write(¤t->mm->mmap_sem); + + return ret; +} + + + + /* Build the RB tree corresponding to the VMA list. */ void build_mmap_rb(struct mm_struct * mm) {