diff options
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r-- | fs/binfmt_flat.c | 31 |
1 files changed, 24 insertions, 7 deletions
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, | |||
419 | unsigned long textpos = 0, datapos = 0, result; | 419 | unsigned long textpos = 0, datapos = 0, result; |
420 | unsigned long realdatastart = 0; | 420 | unsigned long realdatastart = 0; |
421 | unsigned long text_len, data_len, bss_len, stack_len, flags; | 421 | unsigned long text_len, data_len, bss_len, stack_len, flags; |
422 | unsigned long memp = 0; /* for finding the brk area */ | 422 | unsigned long len, reallen, memp = 0; |
423 | unsigned long extra, rlim; | 423 | unsigned long extra, rlim; |
424 | unsigned long *reloc = 0, *rp; | 424 | unsigned long *reloc = 0, *rp; |
425 | struct inode *inode; | 425 | struct inode *inode; |
@@ -540,10 +540,18 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
540 | goto err; | 540 | goto err; |
541 | } | 541 | } |
542 | 542 | ||
543 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | ||
543 | down_write(¤t->mm->mmap_sem); | 544 | down_write(¤t->mm->mmap_sem); |
544 | realdatastart = do_mmap(0, 0, data_len + extra + | 545 | realdatastart = do_mmap(0, 0, len, |
545 | MAX_SHARED_LIBS * sizeof(unsigned long), | 546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 547 | /* Remap to use all availabe slack region space */ |
548 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { | ||
549 | reallen = ksize(realdatastart); | ||
550 | if (reallen > len) { | ||
551 | realdatastart = do_mremap(realdatastart, len, | ||
552 | reallen, MREMAP_FIXED, realdatastart); | ||
553 | } | ||
554 | } | ||
547 | up_write(¤t->mm->mmap_sem); | 555 | up_write(¤t->mm->mmap_sem); |
548 | 556 | ||
549 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 557 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
@@ -584,11 +592,20 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
584 | 592 | ||
585 | } else { | 593 | } else { |
586 | 594 | ||
595 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | ||
587 | down_write(¤t->mm->mmap_sem); | 596 | down_write(¤t->mm->mmap_sem); |
588 | textpos = do_mmap(0, 0, text_len + data_len + extra + | 597 | textpos = do_mmap(0, 0, len, |
589 | MAX_SHARED_LIBS * sizeof(unsigned long), | 598 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
590 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 599 | /* Remap to use all availabe slack region space */ |
600 | if (textpos && (textpos < (unsigned long) -4096)) { | ||
601 | reallen = ksize(textpos); | ||
602 | if (reallen > len) { | ||
603 | textpos = do_mremap(textpos, len, reallen, | ||
604 | MREMAP_FIXED, textpos); | ||
605 | } | ||
606 | } | ||
591 | up_write(¤t->mm->mmap_sem); | 607 | up_write(¤t->mm->mmap_sem); |
608 | |||
592 | if (!textpos || textpos >= (unsigned long) -4096) { | 609 | if (!textpos || textpos >= (unsigned long) -4096) { |
593 | if (!textpos) | 610 | if (!textpos) |
594 | textpos = (unsigned long) -ENOMEM; | 611 | textpos = (unsigned long) -ENOMEM; |