Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[sfrench/cifs-2.6.git] / fs / binfmt_flat.c
index ae8595d498569a72c6be2f4ce45d956326d33a9a..861141b4f6d6f4cbbfcd96366074db8e4adbeaf3 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;