Merge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof...
[sfrench/cifs-2.6.git] / kernel / module.c
index 1038c013d8b22d8dc39d31595d5078953295794d..24dab046e16cb73d2c684efa9f29371622affd48 100644 (file)
@@ -958,7 +958,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
                }
        }
 
-       /* Stop the machine so refcounts can't move and disable module. */
        ret = try_stop_module(mod, flags, &forced);
        if (ret != 0)
                goto out;
@@ -2884,12 +2883,13 @@ static int module_sig_check(struct load_info *info, int flags)
        const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
        const char *reason;
        const void *mod = info->hdr;
-
+       bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS |
+                                      MODULE_INIT_IGNORE_VERMAGIC);
        /*
-        * Require flags == 0, as a module with version information
-        * removed is no longer the module that was signed
+        * Do not allow mangled modules as a module with version information
+        * removed is no longer the module that was signed.
         */
-       if (flags == 0 &&
+       if (!mangled_module &&
            info->len > markerlen &&
            memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
                /* We truncate the module to discard the signature */
@@ -3174,9 +3174,12 @@ out:
        return err;
 }
 
-static void free_copy(struct load_info *info)
+static void free_copy(struct load_info *info, int flags)
 {
-       vfree(info->hdr);
+       if (flags & MODULE_INIT_COMPRESSED_FILE)
+               module_decompress_cleanup(info);
+       else
+               vfree(info->hdr);
 }
 
 static int rewrite_section_headers(struct load_info *info, int flags)
@@ -4125,7 +4128,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        }
 
        /* Get rid of temporary copy. */
-       free_copy(info);
+       free_copy(info, flags);
 
        /* Done! */
        trace_module_load(mod);
@@ -4174,7 +4177,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        module_deallocate(mod, info);
  free_copy:
-       free_copy(info);
+       free_copy(info, flags);
        return err;
 }
 
@@ -4201,7 +4204,8 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
 SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
 {
        struct load_info info = { };
-       void *hdr = NULL;
+       void *buf = NULL;
+       int len;
        int err;
 
        err = may_init_module();
@@ -4211,15 +4215,24 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
        pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);
 
        if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
-                     |MODULE_INIT_IGNORE_VERMAGIC))
+                     |MODULE_INIT_IGNORE_VERMAGIC
+                     |MODULE_INIT_COMPRESSED_FILE))
                return -EINVAL;
 
-       err = kernel_read_file_from_fd(fd, 0, &hdr, INT_MAX, NULL,
+       len = kernel_read_file_from_fd(fd, 0, &buf, INT_MAX, NULL,
                                       READING_MODULE);
-       if (err < 0)
-               return err;
-       info.hdr = hdr;
-       info.len = err;
+       if (len < 0)
+               return len;
+
+       if (flags & MODULE_INIT_COMPRESSED_FILE) {
+               err = module_decompress(&info, buf, len);
+               vfree(buf); /* compressed data is no longer needed */
+               if (err)
+                       return err;
+       } else {
+               info.hdr = buf;
+               info.len = len;
+       }
 
        return load_module(&info, uargs, flags);
 }