From 72613e5f44adf2fe2684a5f1c1b62c2ee9984f40 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 7 Feb 2007 12:03:08 +1000 Subject: [PATCH] uclinux: correctly remap bin_fmtflat exe allocated mem regions remap() the region we get from mmap() to mark the fact that we are using all of the available slack space. Any slack space is used to form a simple brk region, and potentially more stack space than requested at load time. Any searches of the vma chain may well fail looking for stack (and especially arg) addresses if the remaping is not done. The simplest example is /proc//cmdline, since the args are pretty much always at the top of the data/bss/stack region. Signed-off-by: Greg Ungerer Signed-off-by: Linus Torvalds --- fs/binfmt_flat.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index ae8595d49856..7b0265d7f3a8 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -419,7 +419,7 @@ static int load_flat_file(struct linux_binprm * bprm, unsigned long textpos = 0, datapos = 0, result; unsigned long realdatastart = 0; unsigned long text_len, data_len, bss_len, stack_len, flags; - unsigned long memp = 0; /* for finding the brk area */ + unsigned long len, reallen, memp = 0; unsigned long extra, rlim; unsigned long *reloc = 0, *rp; struct inode *inode; @@ -540,10 +540,18 @@ static int load_flat_file(struct linux_binprm * bprm, goto err; } + len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); down_write(¤t->mm->mmap_sem); - realdatastart = do_mmap(0, 0, data_len + extra + - MAX_SHARED_LIBS * sizeof(unsigned long), - PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); + realdatastart = do_mmap(0, 0, len, + PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); + /* Remap to use all availabe slack region space */ + if (realdatastart && (realdatastart < (unsigned long)-4096)) { + reallen = ksize(realdatastart); + if (reallen > len) { + realdatastart = do_mremap(realdatastart, len, + reallen, MREMAP_FIXED, realdatastart); + } + } up_write(¤t->mm->mmap_sem); if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { @@ -584,11 +592,20 @@ static int load_flat_file(struct linux_binprm * bprm, } else { + len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); down_write(¤t->mm->mmap_sem); - textpos = do_mmap(0, 0, text_len + data_len + extra + - MAX_SHARED_LIBS * sizeof(unsigned long), - PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); + textpos = do_mmap(0, 0, len, + PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); + /* Remap to use all availabe slack region space */ + if (textpos && (textpos < (unsigned long) -4096)) { + reallen = ksize(textpos); + if (reallen > len) { + textpos = do_mremap(textpos, len, reallen, + MREMAP_FIXED, textpos); + } + } up_write(¤t->mm->mmap_sem); + if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos) textpos = (unsigned long) -ENOMEM; -- cgit v1.2.3-59-g8ed1b