diff options
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r-- | fs/binfmt_flat.c | 34 |
1 files changed, 11 insertions, 23 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 7bbd5c6b3725..5cebf0b37798 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -417,8 +417,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
417 | unsigned long textpos = 0, datapos = 0, result; | 417 | unsigned long textpos = 0, datapos = 0, result; |
418 | unsigned long realdatastart = 0; | 418 | unsigned long realdatastart = 0; |
419 | unsigned long text_len, data_len, bss_len, stack_len, flags; | 419 | unsigned long text_len, data_len, bss_len, stack_len, flags; |
420 | unsigned long len, reallen, memp = 0; | 420 | unsigned long len, memp = 0; |
421 | unsigned long extra, rlim; | 421 | unsigned long memp_size, extra, rlim; |
422 | unsigned long *reloc = 0, *rp; | 422 | unsigned long *reloc = 0, *rp; |
423 | struct inode *inode; | 423 | struct inode *inode; |
424 | int i, rev, relocs = 0; | 424 | int i, rev, relocs = 0; |
@@ -543,17 +543,10 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
543 | } | 543 | } |
544 | 544 | ||
545 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 545 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
546 | len = PAGE_ALIGN(len); | ||
546 | down_write(¤t->mm->mmap_sem); | 547 | down_write(¤t->mm->mmap_sem); |
547 | realdatastart = do_mmap(0, 0, len, | 548 | realdatastart = do_mmap(0, 0, len, |
548 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 549 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
549 | /* Remap to use all availabe slack region space */ | ||
550 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { | ||
551 | reallen = kobjsize((void *)realdatastart); | ||
552 | if (reallen > len) { | ||
553 | realdatastart = do_mremap(realdatastart, len, | ||
554 | reallen, MREMAP_FIXED, realdatastart); | ||
555 | } | ||
556 | } | ||
557 | up_write(¤t->mm->mmap_sem); | 550 | up_write(¤t->mm->mmap_sem); |
558 | 551 | ||
559 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 552 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
@@ -591,21 +584,14 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
591 | 584 | ||
592 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); | 585 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); |
593 | memp = realdatastart; | 586 | memp = realdatastart; |
594 | 587 | memp_size = len; | |
595 | } else { | 588 | } else { |
596 | 589 | ||
597 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 590 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
591 | len = PAGE_ALIGN(len); | ||
598 | down_write(¤t->mm->mmap_sem); | 592 | down_write(¤t->mm->mmap_sem); |
599 | textpos = do_mmap(0, 0, len, | 593 | textpos = do_mmap(0, 0, len, |
600 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 594 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
601 | /* Remap to use all availabe slack region space */ | ||
602 | if (textpos && (textpos < (unsigned long) -4096)) { | ||
603 | reallen = kobjsize((void *)textpos); | ||
604 | if (reallen > len) { | ||
605 | textpos = do_mremap(textpos, len, reallen, | ||
606 | MREMAP_FIXED, textpos); | ||
607 | } | ||
608 | } | ||
609 | up_write(¤t->mm->mmap_sem); | 595 | up_write(¤t->mm->mmap_sem); |
610 | 596 | ||
611 | if (!textpos || textpos >= (unsigned long) -4096) { | 597 | if (!textpos || textpos >= (unsigned long) -4096) { |
@@ -622,7 +608,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
622 | reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + | 608 | reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + |
623 | MAX_SHARED_LIBS * sizeof(unsigned long)); | 609 | MAX_SHARED_LIBS * sizeof(unsigned long)); |
624 | memp = textpos; | 610 | memp = textpos; |
625 | 611 | memp_size = len; | |
626 | #ifdef CONFIG_BINFMT_ZFLAT | 612 | #ifdef CONFIG_BINFMT_ZFLAT |
627 | /* | 613 | /* |
628 | * load it all in and treat it like a RAM load from now on | 614 | * load it all in and treat it like a RAM load from now on |
@@ -680,10 +666,12 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
680 | * set up the brk stuff, uses any slack left in data/bss/stack | 666 | * set up the brk stuff, uses any slack left in data/bss/stack |
681 | * allocation. We put the brk after the bss (between the bss | 667 | * allocation. We put the brk after the bss (between the bss |
682 | * and stack) like other platforms. | 668 | * and stack) like other platforms. |
669 | * Userspace code relies on the stack pointer starting out at | ||
670 | * an address right at the end of a page. | ||
683 | */ | 671 | */ |
684 | current->mm->start_brk = datapos + data_len + bss_len; | 672 | current->mm->start_brk = datapos + data_len + bss_len; |
685 | current->mm->brk = (current->mm->start_brk + 3) & ~3; | 673 | current->mm->brk = (current->mm->start_brk + 3) & ~3; |
686 | current->mm->context.end_brk = memp + kobjsize((void *) memp) - stack_len; | 674 | current->mm->context.end_brk = memp + memp_size - stack_len; |
687 | } | 675 | } |
688 | 676 | ||
689 | if (flags & FLAT_FLAG_KTRACE) | 677 | if (flags & FLAT_FLAG_KTRACE) |
@@ -790,8 +778,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
790 | 778 | ||
791 | /* zero the BSS, BRK and stack areas */ | 779 | /* zero the BSS, BRK and stack areas */ |
792 | memset((void*)(datapos + data_len), 0, bss_len + | 780 | memset((void*)(datapos + data_len), 0, bss_len + |
793 | (memp + kobjsize((void *) memp) - stack_len - /* end brk */ | 781 | (memp + memp_size - stack_len - /* end brk */ |
794 | libinfo->lib_list[id].start_brk) + /* start brk */ | 782 | libinfo->lib_list[id].start_brk) + /* start brk */ |
795 | stack_len); | 783 | stack_len); |
796 | 784 | ||
797 | return 0; | 785 | return 0; |