Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[pandora-kernel.git] / fs / binfmt_flat.c
index ae8595d..fcb3405 100644 (file)
@@ -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,17 +540,25 @@ static int load_flat_file(struct linux_binprm * bprm,
                        goto err;
                }
 
+               len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
                down_write(&current->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(&current->mm->mmap_sem);
 
                if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
                        if (!realdatastart)
                                realdatastart = (unsigned long) -ENOMEM;
                        printk("Unable to allocate RAM for process data, errno %d\n",
-                                       (int)-datapos);
+                                       (int)-realdatastart);
                        do_munmap(current->mm, textpos, text_len);
                        ret = realdatastart;
                        goto err;
@@ -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(&current->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(&current->mm->mmap_sem);
+
                if (!textpos  || textpos >= (unsigned long) -4096) {
                        if (!textpos)
                                textpos = (unsigned long) -ENOMEM;
@@ -725,6 +742,7 @@ static int load_flat_file(struct linux_binprm * bprm,
         * __start to address 4 so that is okay).
         */
        if (rev > OLD_FLAT_VERSION) {
+               unsigned long persistent = 0;
                for (i=0; i < relocs; i++) {
                        unsigned long addr, relval;
 
@@ -732,6 +750,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                           relocated (of course, the address has to be
                           relocated first).  */
                        relval = ntohl(reloc[i]);
+                       if (flat_set_persistent (relval, &persistent))
+                               continue;
                        addr = flat_get_relocate_addr(relval);
                        rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
                        if (rp == (unsigned long *)RELOC_FAILED) {
@@ -740,7 +760,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                        }
 
                        /* Get the pointer's value.  */
-                       addr = flat_get_addr_from_rp(rp, relval, flags);
+                       addr = flat_get_addr_from_rp(rp, relval, flags,
+                                                       &persistent);
                        if (addr != 0) {
                                /*
                                 * Do the relocation.  PIC relocs in the data section are