diff options
author | Marcelo Tosatti <marcelo.tosatti@cyclades.com> | 2005-01-11 16:12:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-11 16:12:09 -0800 |
commit | 6a424edaddfcd5b68be2e1e641962764b57d7680 (patch) | |
tree | 4b2a8197472ae861ea6595a781c2521dff9087c1 /arch | |
parent | fa6e49a2497cb4298d81c0d384c1ade8bcf1f0a3 (diff) | |
download | history-6a424edaddfcd5b68be2e1e641962764b57d7680.tar.gz |
[PATCH] do_brk() needs mmap_sem write-locked
It seems to be general consensus that its safer to require all do_brk() callers
to grab mmap_sem, and have do_brk to warn otherwise. This is what the following
patch does.
Similar version has been changed to in v2.4.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/irixelf.c | 11 | ||||
-rw-r--r-- | arch/sparc64/kernel/binfmt_aout32.c | 12 | ||||
-rw-r--r-- | arch/x86_64/ia32/ia32_aout.c | 12 |
3 files changed, 33 insertions, 2 deletions
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index aee1f399e15b95..43c254299e4a73 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -127,7 +127,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } @@ -375,7 +377,9 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, /* Map the last of the bss segment */ if (last_bss > len) { + down_write(¤t->mm->mmap_sem); do_brk(len, (last_bss - len)); + up_write(¤t->mm->mmap_sem); } kfree(elf_phdata); @@ -562,7 +566,9 @@ void irix_map_prda_page (void) unsigned long v; struct prda *pp; + down_write(¤t->mm->mmap_sem); v = do_brk (PRDA_ADDRESS, PAGE_SIZE); + up_write(¤t->mm->mmap_sem); if (v < 0) return; @@ -852,8 +858,11 @@ static int load_irix_library(struct file *file) len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; - if (bss > len) + if (bss > len) { + down_write(¤t->mm->mmap_sem); do_brk(len, bss-len); + up_write(¤t->mm->mmap_sem); + } kfree(elf_phdata); return 0; } diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index c54d806e13d273..1afe88f6abc082 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -49,7 +49,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } /* @@ -246,10 +248,14 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* Fuck me plenty... */ + down_write(¤t->mm->mmap_sem); error = do_brk(N_TXTADDR(ex), ex.a_text); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text, &pos); + down_write(¤t->mm->mmap_sem); error = do_brk(N_DATADDR(ex), ex.a_data); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; @@ -257,8 +263,10 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (N_MAGIC(ex) == OMAGIC) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); } else { @@ -272,7 +280,9 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(0, ex.a_text+ex.a_data); + up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); @@ -389,7 +399,9 @@ static int load_aout32_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { + down_write(¤t->mm->mmap_sem); error = do_brk(start_addr + len, bss - len); + up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr + len) goto out; diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index 6ac57fcf1340b4..2014f2113cd8ac 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c @@ -115,7 +115,9 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; + down_write(¤t->mm->mmap_sem); do_brk(start, end - start); + up_write(¤t->mm->mmap_sem); } #if CORE_DUMP @@ -325,7 +327,10 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) pos = 32; map_size = ex.a_text+ex.a_data; + down_write(¤t->mm->mmap_sem); error = do_brk(text_addr & PAGE_MASK, map_size); + up_write(¤t->mm->mmap_sem); + if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; @@ -361,7 +366,9 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; + down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); + up_write(¤t->mm->mmap_sem); 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), @@ -469,8 +476,9 @@ static int load_aout_library(struct file *file) error_time = jiffies; } #endif - + down_write(¤t->mm->mmap_sem); do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); + up_write(¤t->mm->mmap_sem); file->f_op->read(file, (char *)start_addr, ex.a_text + ex.a_data, &pos); @@ -494,7 +502,9 @@ static int load_aout_library(struct file *file) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { + down_write(¤t->mm->mmap_sem); error = do_brk(start_addr + len, bss - len); + up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr + len) goto out; |