gpu/drm: Fix lock held when returning to user space.
[platform/kernel/linux-exynos.git] / kernel / module.c
index 40f983c..94528b8 100644 (file)
@@ -1201,8 +1201,10 @@ static ssize_t store_uevent(struct module_attribute *mattr,
                            struct module_kobject *mk,
                            const char *buffer, size_t count)
 {
-       kobject_synth_uevent(&mk->kobj, buffer, count);
-       return count;
+       int rc;
+
+       rc = kobject_synth_uevent(&mk->kobj, buffer, count);
+       return rc ? rc : count;
 }
 
 struct module_attribute module_uevent =
@@ -2707,21 +2709,21 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
 }
 #endif /* CONFIG_KALLSYMS */
 
-static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)
+static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num)
 {
        if (!debug)
                return;
 #ifdef CONFIG_DYNAMIC_DEBUG
-       if (ddebug_add_module(debug, num, debug->modname))
+       if (ddebug_add_module(debug, num, mod->name))
                pr_err("dynamic debug error adding module: %s\n",
                        debug->modname);
 #endif
 }
 
-static void dynamic_debug_remove(struct _ddebug *debug)
+static void dynamic_debug_remove(struct module *mod, struct _ddebug *debug)
 {
        if (debug)
-               ddebug_remove_module(debug->modname);
+               ddebug_remove_module(mod->name);
 }
 
 void * __weak module_alloc(unsigned long size)
@@ -2855,6 +2857,15 @@ static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
 }
 #endif /* CONFIG_LIVEPATCH */
 
+static void check_modinfo_retpoline(struct module *mod, struct load_info *info)
+{
+       if (retpoline_module_ok(get_modinfo(info, "retpoline")))
+               return;
+
+       pr_warn("%s: loading module not compiled with retpoline compiler.\n",
+               mod->name);
+}
+
 /* Sets info->hdr and info->len. */
 static int copy_module_from_user(const void __user *umod, unsigned long len,
                                  struct load_info *info)
@@ -3021,6 +3032,8 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
                add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
        }
 
+       check_modinfo_retpoline(mod, info);
+
        if (get_modinfo(info, "staging")) {
                add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
                pr_warn("%s: module is from the staging directory, the quality "
@@ -3495,6 +3508,11 @@ static noinline int do_init_module(struct module *mod)
         * walking this with preempt disabled.  In all the failure paths, we
         * call synchronize_sched(), but we don't want to slow down the success
         * path, so use actual RCU here.
+        * Note that module_alloc() on most architectures creates W+X page
+        * mappings which won't be cleaned up until do_free_init() runs.  Any
+        * code such as mark_rodata_ro() which depends on those mappings to
+        * be cleaned up needs to sync with the queued work - ie
+        * rcu_barrier_sched()
         */
        call_rcu_sched(&freeinit->rcu, do_free_init);
        mutex_unlock(&module_mutex);
@@ -3715,7 +3733,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
                goto free_arch_cleanup;
        }
 
-       dynamic_debug_setup(info->debug, info->num_debug);
+       dynamic_debug_setup(mod, info->debug, info->num_debug);
 
        /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
        ftrace_module_init(mod);
@@ -3779,7 +3797,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
        module_disable_nx(mod);
 
  ddebug_cleanup:
-       dynamic_debug_remove(info->debug);
+       dynamic_debug_remove(mod, info->debug);
        synchronize_sched();
        kfree(mod->args);
  free_arch_cleanup:
@@ -4042,7 +4060,7 @@ static unsigned long mod_find_symname(struct module *mod, const char *name)
 
        for (i = 0; i < kallsyms->num_symtab; i++)
                if (strcmp(name, symname(kallsyms, i)) == 0 &&
-                   kallsyms->symtab[i].st_info != 'U')
+                   kallsyms->symtab[i].st_shndx != SHN_UNDEF)
                        return kallsyms->symtab[i].st_value;
        return 0;
 }
@@ -4088,6 +4106,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
                if (mod->state == MODULE_STATE_UNFORMED)
                        continue;
                for (i = 0; i < kallsyms->num_symtab; i++) {
+
+                       if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
+                               continue;
+
                        ret = fn(data, symname(kallsyms, i),
                                 mod, kallsyms->symtab[i].st_value);
                        if (ret != 0)