[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/<pid>/cmdline, since the args
are pretty much always at the top of the data/bss/stack region.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Greg Ungerer 2007-02-07 12:03:08 +10:00 коммит произвёл Linus Torvalds
Родитель c051b01129
Коммит 72613e5f44
1 изменённых файлов: 24 добавлений и 7 удалений

Просмотреть файл

@ -419,7 +419,7 @@ static int load_flat_file(struct linux_binprm * bprm,
unsigned long textpos = 0, datapos = 0, result; unsigned long textpos = 0, datapos = 0, result;
unsigned long realdatastart = 0; unsigned long realdatastart = 0;
unsigned long text_len, data_len, bss_len, stack_len, flags; 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 extra, rlim;
unsigned long *reloc = 0, *rp; unsigned long *reloc = 0, *rp;
struct inode *inode; struct inode *inode;
@ -540,10 +540,18 @@ static int load_flat_file(struct linux_binprm * bprm,
goto err; goto err;
} }
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
realdatastart = do_mmap(0, 0, data_len + extra + realdatastart = do_mmap(0, 0, len,
MAX_SHARED_LIBS * sizeof(unsigned long), PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
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(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@ -584,11 +592,20 @@ static int load_flat_file(struct linux_binprm * bprm,
} else { } else {
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
textpos = do_mmap(0, 0, text_len + data_len + extra + textpos = do_mmap(0, 0, len,
MAX_SHARED_LIBS * sizeof(unsigned long), PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
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(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos) if (!textpos)
textpos = (unsigned long) -ENOMEM; textpos = (unsigned long) -ENOMEM;