drivers/input: eliminate INPUT_COMPAT_TEST macro
[linux-2.6-block.git] / kernel / module.c
index 794ebe8e878d55cf9a0b94a1ae7a994ac4dec80b..041200ca4a2db348287394777fab8efbae58b3f2 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/sections.h>
 #include <linux/tracepoint.h>
 #include <linux/ftrace.h>
+#include <linux/livepatch.h>
 #include <linux/async.h>
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
@@ -984,6 +985,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
                mod->exit();
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
+       klp_module_going(mod);
        ftrace_release_mod(mod);
 
        async_synchronize_full();
@@ -2675,7 +2677,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
        if (info->len < sizeof(*(info->hdr)))
                return -ENOEXEC;
 
-       err = security_kernel_module_from_file(NULL);
+       err = security_kernel_read_file(NULL, READING_MODULE);
        if (err)
                return err;
 
@@ -2693,63 +2695,6 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
        return 0;
 }
 
-/* Sets info->hdr and info->len. */
-static int copy_module_from_fd(int fd, struct load_info *info)
-{
-       struct fd f = fdget(fd);
-       int err;
-       struct kstat stat;
-       loff_t pos;
-       ssize_t bytes = 0;
-
-       if (!f.file)
-               return -ENOEXEC;
-
-       err = security_kernel_module_from_file(f.file);
-       if (err)
-               goto out;
-
-       err = vfs_getattr(&f.file->f_path, &stat);
-       if (err)
-               goto out;
-
-       if (stat.size > INT_MAX) {
-               err = -EFBIG;
-               goto out;
-       }
-
-       /* Don't hand 0 to vmalloc, it whines. */
-       if (stat.size == 0) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       info->hdr = vmalloc(stat.size);
-       if (!info->hdr) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       pos = 0;
-       while (pos < stat.size) {
-               bytes = kernel_read(f.file, pos, (char *)(info->hdr) + pos,
-                                   stat.size - pos);
-               if (bytes < 0) {
-                       vfree(info->hdr);
-                       err = bytes;
-                       goto out;
-               }
-               if (bytes == 0)
-                       break;
-               pos += bytes;
-       }
-       info->len = pos;
-
-out:
-       fdput(f);
-       return err;
-}
-
 static void free_copy(struct load_info *info)
 {
        vfree(info->hdr);
@@ -3315,6 +3260,7 @@ fail:
        module_put(mod);
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_GOING, mod);
+       klp_module_going(mod);
        ftrace_release_mod(mod);
        free_module(mod);
        wake_up_all(&module_wq);
@@ -3392,9 +3338,6 @@ static int complete_formation(struct module *mod, struct load_info *info)
        mod->state = MODULE_STATE_COMING;
        mutex_unlock(&module_mutex);
 
-       ftrace_module_enable(mod);
-       blocking_notifier_call_chain(&module_notify_list,
-                                    MODULE_STATE_COMING, mod);
        return 0;
 
 out:
@@ -3402,6 +3345,20 @@ out:
        return err;
 }
 
+static int prepare_coming_module(struct module *mod)
+{
+       int err;
+
+       ftrace_module_enable(mod);
+       err = klp_module_coming(mod);
+       if (err)
+               return err;
+
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_COMING, mod);
+       return 0;
+}
+
 static int unknown_module_param_cb(char *param, char *val, const char *modname,
                                   void *arg)
 {
@@ -3516,13 +3473,17 @@ static int load_module(struct load_info *info, const char __user *uargs,
        if (err)
                goto ddebug_cleanup;
 
+       err = prepare_coming_module(mod);
+       if (err)
+               goto bug_cleanup;
+
        /* Module is ready to execute: parsing args may do that. */
        after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
                                  -32768, 32767, mod,
                                  unknown_module_param_cb);
        if (IS_ERR(after_dashes)) {
                err = PTR_ERR(after_dashes);
-               goto bug_cleanup;
+               goto coming_cleanup;
        } else if (after_dashes) {
                pr_warn("%s: parameters '%s' after `--' ignored\n",
                       mod->name, after_dashes);
@@ -3531,7 +3492,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        /* Link in to syfs. */
        err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
-               goto bug_cleanup;
+               goto coming_cleanup;
 
        /* Get rid of temporary copy. */
        free_copy(info);
@@ -3541,15 +3502,17 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        return do_init_module(mod);
 
+ coming_cleanup:
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_GOING, mod);
+       klp_module_going(mod);
+
  bug_cleanup:
        /* module_bug_cleanup needs module_mutex protection */
        mutex_lock(&module_mutex);
        module_bug_cleanup(mod);
        mutex_unlock(&module_mutex);
 
-       blocking_notifier_call_chain(&module_notify_list,
-                                    MODULE_STATE_GOING, mod);
-
        /* we can't deallocate the module until we clear memory protection */
        module_disable_ro(mod);
        module_disable_nx(mod);
@@ -3611,8 +3574,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
 
 SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
 {
-       int err;
        struct load_info info = { };
+       loff_t size;
+       void *hdr;
+       int err;
 
        err = may_init_module();
        if (err)
@@ -3624,9 +3589,12 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
                      |MODULE_INIT_IGNORE_VERMAGIC))
                return -EINVAL;
 
-       err = copy_module_from_fd(fd, &info);
+       err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX,
+                                      READING_MODULE);
        if (err)
                return err;
+       info.hdr = hdr;
+       info.len = size;
 
        return load_module(&info, uargs, flags);
 }