aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>2005-01-11 16:12:09 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 16:12:09 -0800
commit6a424edaddfcd5b68be2e1e641962764b57d7680 (patch)
tree4b2a8197472ae861ea6595a781c2521dff9087c1 /arch
parentfa6e49a2497cb4298d81c0d384c1ade8bcf1f0a3 (diff)
downloadhistory-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.c11
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c12
-rw-r--r--arch/x86_64/ia32/ia32_aout.c12
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(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(len, (last_bss - len));
+ up_write(&current->mm->mmap_sem);
}
kfree(elf_phdata);
@@ -562,7 +566,9 @@ void irix_map_prda_page (void)
unsigned long v;
struct prda *pp;
+ down_write(&current->mm->mmap_sem);
v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(len, bss-len);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->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(&current->mm->mmap_sem);
error = do_brk(N_TXTADDR(ex), ex.a_text);
+ up_write(&current->mm->mmap_sem);
bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
ex.a_text, &pos);
+ down_write(&current->mm->mmap_sem);
error = do_brk(N_DATADDR(ex), ex.a_data);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex) & PAGE_MASK,
ex.a_text+ex.a_data + PAGE_SIZE - 1);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(0, ex.a_text+ex.a_data);
+ up_write(&current->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(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(start, end - start);
+ up_write(&current->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(&current->mm->mmap_sem);
error = do_brk(text_addr & PAGE_MASK, map_size);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+ up_write(&current->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(&current->mm->mmap_sem);
do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+ up_write(&current->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(&current->mm->mmap_sem);
error = do_brk(start_addr + len, bss - len);
+ up_write(&current->mm->mmap_sem);
retval = error;
if (error != start_addr + len)
goto out;