fix a struct file leak in do_mmap_pgoff()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 1 Dec 2009 01:12:03 +0000 (20:12 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 11 Dec 2009 11:44:57 +0000 (06:44 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
mm/mmap.c
mm/util.c

index 292ddc3..5076775 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -948,24 +948,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
        if (mm->map_count > sysctl_max_map_count)
                return -ENOMEM;
 
-       if (flags & MAP_HUGETLB) {
-               struct user_struct *user = NULL;
-               if (file)
-                       return -EINVAL;
-
-               /*
-                * VM_NORESERVE is used because the reservations will be
-                * taken when vm_ops->mmap() is called
-                * A dummy user value is used because we are not locking
-                * memory so no accounting is necessary
-                */
-               len = ALIGN(len, huge_page_size(&default_hstate));
-               file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
-                                               &user, HUGETLB_ANONHUGE_INODE);
-               if (IS_ERR(file))
-                       return PTR_ERR(file);
-       }
-
        /* Obtain the address to map to. we verify (or select) it and ensure
         * that it represents a valid section of the address space.
         */
index 3bf81b2..b377ce4 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -280,9 +280,24 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
        unsigned long retval = -EBADF;
 
        if (!(flags & MAP_ANONYMOUS)) {
+               if (unlikely(flags & MAP_HUGETLB))
+                       return -EINVAL;
                file = fget(fd);
                if (!file)
                        goto out;
+       } else if (flags & MAP_HUGETLB) {
+               struct user_struct *user = NULL;
+               /*
+                * VM_NORESERVE is used because the reservations will be
+                * taken when vm_ops->mmap() is called
+                * A dummy user value is used because we are not locking
+                * memory so no accounting is necessary
+                */
+               len = ALIGN(len, huge_page_size(&default_hstate));
+               file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
+                                               &user, HUGETLB_ANONHUGE_INODE);
+               if (IS_ERR(file))
+                       return PTR_ERR(file);
        }
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);