Merge tag 'modules-for-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu...
[sfrench/cifs-2.6.git] / kernel / module.c
index d7eb41d772c471ae358f85fab6ff78ad230dc168..40f983cbea81d1e3711955dfb2409659d89fd317 100644 (file)
@@ -49,9 +49,7 @@
 #include <linux/rculist.h>
 #include <linux/uaccess.h>
 #include <asm/cacheflush.h>
-#ifdef CONFIG_STRICT_MODULE_RWX
-#include <asm/set_memory.h>
-#endif
+#include <linux/set_memory.h>
 #include <asm/mmu_context.h>
 #include <linux/license.h>
 #include <asm/sections.h>
@@ -302,6 +300,7 @@ int unregister_module_notifier(struct notifier_block *nb)
 EXPORT_SYMBOL(unregister_module_notifier);
 
 struct load_info {
+       const char *name;
        Elf_Ehdr *hdr;
        unsigned long len;
        Elf_Shdr *sechdrs;
@@ -602,7 +601,7 @@ static struct module *find_module_all(const char *name, size_t len,
 
        module_assert_mutex_or_preempt();
 
-       list_for_each_entry(mod, &modules, list) {
+       list_for_each_entry_rcu(mod, &modules, list) {
                if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
                        continue;
                if (strlen(mod->name) == len && !memcmp(mod->name, name, len))
@@ -1275,12 +1274,13 @@ static u32 resolve_rel_crc(const s32 *crc)
        return *(u32 *)((void *)crc + *crc);
 }
 
-static int check_version(Elf_Shdr *sechdrs,
-                        unsigned int versindex,
+static int check_version(const struct load_info *info,
                         const char *symname,
                         struct module *mod,
                         const s32 *crc)
 {
+       Elf_Shdr *sechdrs = info->sechdrs;
+       unsigned int versindex = info->index.vers;
        unsigned int i, num_versions;
        struct modversion_info *versions;
 
@@ -1314,17 +1314,16 @@ static int check_version(Elf_Shdr *sechdrs,
        }
 
        /* Broken toolchain. Warn once, then let it go.. */
-       pr_warn_once("%s: no symbol version for %s\n", mod->name, symname);
+       pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
        return 1;
 
 bad_version:
        pr_warn("%s: disagrees about version of symbol %s\n",
-              mod->name, symname);
+              info->name, symname);
        return 0;
 }
 
-static inline int check_modstruct_version(Elf_Shdr *sechdrs,
-                                         unsigned int versindex,
+static inline int check_modstruct_version(const struct load_info *info,
                                          struct module *mod)
 {
        const s32 *crc;
@@ -1340,8 +1339,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
                BUG();
        }
        preempt_enable();
-       return check_version(sechdrs, versindex,
-                            VMLINUX_SYMBOL_STR(module_layout), mod, crc);
+       return check_version(info, VMLINUX_SYMBOL_STR(module_layout),
+                            mod, crc);
 }
 
 /* First part is kernel version, which we ignore if module has crcs. */
@@ -1355,8 +1354,7 @@ static inline int same_magic(const char *amagic, const char *bmagic,
        return strcmp(amagic, bmagic) == 0;
 }
 #else
-static inline int check_version(Elf_Shdr *sechdrs,
-                               unsigned int versindex,
+static inline int check_version(const struct load_info *info,
                                const char *symname,
                                struct module *mod,
                                const s32 *crc)
@@ -1364,8 +1362,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
        return 1;
 }
 
-static inline int check_modstruct_version(Elf_Shdr *sechdrs,
-                                         unsigned int versindex,
+static inline int check_modstruct_version(const struct load_info *info,
                                          struct module *mod)
 {
        return 1;
@@ -1401,7 +1398,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
        if (!sym)
                goto unlock;
 
-       if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
+       if (!check_version(info, name, mod, crc)) {
                sym = ERR_PTR(-EINVAL);
                goto getname;
        }
@@ -1664,31 +1661,36 @@ static inline void remove_notes_attrs(struct module *mod)
 }
 #endif /* CONFIG_KALLSYMS */
 
-static void add_usage_links(struct module *mod)
+static void del_usage_links(struct module *mod)
 {
 #ifdef CONFIG_MODULE_UNLOAD
        struct module_use *use;
-       int nowarn;
 
        mutex_lock(&module_mutex);
-       list_for_each_entry(use, &mod->target_list, target_list) {
-               nowarn = sysfs_create_link(use->target->holders_dir,
-                                          &mod->mkobj.kobj, mod->name);
-       }
+       list_for_each_entry(use, &mod->target_list, target_list)
+               sysfs_remove_link(use->target->holders_dir, mod->name);
        mutex_unlock(&module_mutex);
 #endif
 }
 
-static void del_usage_links(struct module *mod)
+static int add_usage_links(struct module *mod)
 {
+       int ret = 0;
 #ifdef CONFIG_MODULE_UNLOAD
        struct module_use *use;
 
        mutex_lock(&module_mutex);
-       list_for_each_entry(use, &mod->target_list, target_list)
-               sysfs_remove_link(use->target->holders_dir, mod->name);
+       list_for_each_entry(use, &mod->target_list, target_list) {
+               ret = sysfs_create_link(use->target->holders_dir,
+                                       &mod->mkobj.kobj, mod->name);
+               if (ret)
+                       break;
+       }
        mutex_unlock(&module_mutex);
+       if (ret)
+               del_usage_links(mod);
 #endif
+       return ret;
 }
 
 static int module_add_modinfo_attrs(struct module *mod)
@@ -1799,13 +1801,18 @@ static int mod_sysfs_setup(struct module *mod,
        if (err)
                goto out_unreg_param;
 
-       add_usage_links(mod);
+       err = add_usage_links(mod);
+       if (err)
+               goto out_unreg_modinfo_attrs;
+
        add_sect_attrs(mod, info);
        add_notes_attrs(mod, info);
 
        kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
        return 0;
 
+out_unreg_modinfo_attrs:
+       module_remove_modinfo_attrs(mod);
 out_unreg_param:
        module_param_sysfs_remove(mod);
 out_unreg_holders:
@@ -2912,9 +2919,15 @@ static int rewrite_section_headers(struct load_info *info, int flags)
                info->index.vers = 0; /* Pretend no __versions section! */
        else
                info->index.vers = find_sec(info, "__versions");
+       info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
+
        info->index.info = find_sec(info, ".modinfo");
+       if (!info->index.info)
+               info->name = "(missing .modinfo section)";
+       else
+               info->name = get_modinfo(info, "name");
        info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
-       info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
+
        return 0;
 }
 
@@ -2954,21 +2967,29 @@ static struct module *setup_load_info(struct load_info *info, int flags)
 
        info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
        if (!info->index.mod) {
-               pr_warn("No module found in object\n");
+               pr_warn("%s: No module found in object\n",
+                       info->name ?: "(missing .modinfo name field)");
                return ERR_PTR(-ENOEXEC);
        }
        /* This is temporary: point mod into copy of data. */
        mod = (void *)info->sechdrs[info->index.mod].sh_addr;
 
+       /*
+        * If we didn't load the .modinfo 'name' field, fall back to
+        * on-disk struct mod 'name' field.
+        */
+       if (!info->name)
+               info->name = mod->name;
+
        if (info->index.sym == 0) {
-               pr_warn("%s: module has no symbols (stripped?)\n", mod->name);
+               pr_warn("%s: module has no symbols (stripped?)\n", info->name);
                return ERR_PTR(-ENOEXEC);
        }
 
        info->index.pcpu = find_pcpusec(info);
 
        /* Check module struct version now, before we try to use module. */
-       if (!check_modstruct_version(info->sechdrs, info->index.vers, mod))
+       if (!check_modstruct_version(info, mod))
                return ERR_PTR(-ENOEXEC);
 
        return mod;
@@ -2989,7 +3010,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
                        return err;
        } else if (!same_magic(modmagic, vermagic, info->index.vers)) {
                pr_err("%s: version magic '%s' should be '%s'\n",
-                      mod->name, modmagic, vermagic);
+                      info->name, modmagic, vermagic);
                return -ENOEXEC;
        }
 
@@ -3074,9 +3095,9 @@ static int find_module_sections(struct module *mod, struct load_info *info)
        mod->trace_events = section_objs(info, "_ftrace_events",
                                         sizeof(*mod->trace_events),
                                         &mod->num_trace_events);
-       mod->trace_enums = section_objs(info, "_ftrace_enum_map",
-                                       sizeof(*mod->trace_enums),
-                                       &mod->num_trace_enums);
+       mod->trace_evals = section_objs(info, "_ftrace_eval_map",
+                                       sizeof(*mod->trace_evals),
+                                       &mod->num_trace_evals);
 #endif
 #ifdef CONFIG_TRACING
        mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt",
@@ -3239,7 +3260,7 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
 
 /* module_blacklist is a comma-separated list of module names */
 static char *module_blacklist;
-static bool blacklisted(char *module_name)
+static bool blacklisted(const char *module_name)
 {
        const char *p;
        size_t len;
@@ -3269,7 +3290,7 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        if (IS_ERR(mod))
                return mod;
 
-       if (blacklisted(mod->name))
+       if (blacklisted(info->name))
                return ERR_PTR(-EPERM);
 
        err = check_modinfo(mod, info, flags);
@@ -4198,7 +4219,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
                goto out;
 
        e = search_extable(mod->extable,
-                          mod->extable + mod->num_exentries - 1,
+                          mod->num_exentries,
                           addr);
 out:
        preempt_enable();