diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-12 20:22:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-12 20:22:01 -0400 |
commit | 3a75ad1457d9cd84bc17d5b9cffb4d73b52be20b (patch) | |
tree | 8ca06468b1f9feffeefe04f700264ed7345d7803 /kernel/module.c | |
parent | 235b84fc862ae2637dc0dabada18d97f1bfc18e1 (diff) | |
parent | 96b5b19459b3c2aed2872bac42cbe19edfae710f (diff) |
Merge tag 'modules-for-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux
Pull modules updates from Jessica Yu:
"Summary of modules changes for the 4.13 merge window:
- Minor code cleanups
- Avoid accessing mod struct prior to checking module struct version,
from Kees
- Fix racy atomic inc/dec logic of kmod_concurrent_max in kmod, from
Luis"
* tag 'modules-for-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
module: make the modinfo name const
kmod: reduce atomic operations on kmod_concurrent and simplify
module: use list_for_each_entry_rcu() on find_module_all()
kernel/module.c: suppress warning about unused nowarn variable
module: Add module name to modinfo
module: Pass struct load_info into symbol checks
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/kernel/module.c b/kernel/module.c index b0f92a365140..40f983cbea81 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -300,6 +300,7 @@ int unregister_module_notifier(struct notifier_block *nb) | |||
300 | EXPORT_SYMBOL(unregister_module_notifier); | 300 | EXPORT_SYMBOL(unregister_module_notifier); |
301 | 301 | ||
302 | struct load_info { | 302 | struct load_info { |
303 | const char *name; | ||
303 | Elf_Ehdr *hdr; | 304 | Elf_Ehdr *hdr; |
304 | unsigned long len; | 305 | unsigned long len; |
305 | Elf_Shdr *sechdrs; | 306 | Elf_Shdr *sechdrs; |
@@ -600,7 +601,7 @@ static struct module *find_module_all(const char *name, size_t len, | |||
600 | 601 | ||
601 | module_assert_mutex_or_preempt(); | 602 | module_assert_mutex_or_preempt(); |
602 | 603 | ||
603 | list_for_each_entry(mod, &modules, list) { | 604 | list_for_each_entry_rcu(mod, &modules, list) { |
604 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | 605 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) |
605 | continue; | 606 | continue; |
606 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) | 607 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) |
@@ -1273,12 +1274,13 @@ static u32 resolve_rel_crc(const s32 *crc) | |||
1273 | return *(u32 *)((void *)crc + *crc); | 1274 | return *(u32 *)((void *)crc + *crc); |
1274 | } | 1275 | } |
1275 | 1276 | ||
1276 | static int check_version(Elf_Shdr *sechdrs, | 1277 | static int check_version(const struct load_info *info, |
1277 | unsigned int versindex, | ||
1278 | const char *symname, | 1278 | const char *symname, |
1279 | struct module *mod, | 1279 | struct module *mod, |
1280 | const s32 *crc) | 1280 | const s32 *crc) |
1281 | { | 1281 | { |
1282 | Elf_Shdr *sechdrs = info->sechdrs; | ||
1283 | unsigned int versindex = info->index.vers; | ||
1282 | unsigned int i, num_versions; | 1284 | unsigned int i, num_versions; |
1283 | struct modversion_info *versions; | 1285 | struct modversion_info *versions; |
1284 | 1286 | ||
@@ -1312,17 +1314,16 @@ static int check_version(Elf_Shdr *sechdrs, | |||
1312 | } | 1314 | } |
1313 | 1315 | ||
1314 | /* Broken toolchain. Warn once, then let it go.. */ | 1316 | /* Broken toolchain. Warn once, then let it go.. */ |
1315 | pr_warn_once("%s: no symbol version for %s\n", mod->name, symname); | 1317 | pr_warn_once("%s: no symbol version for %s\n", info->name, symname); |
1316 | return 1; | 1318 | return 1; |
1317 | 1319 | ||
1318 | bad_version: | 1320 | bad_version: |
1319 | pr_warn("%s: disagrees about version of symbol %s\n", | 1321 | pr_warn("%s: disagrees about version of symbol %s\n", |
1320 | mod->name, symname); | 1322 | info->name, symname); |
1321 | return 0; | 1323 | return 0; |
1322 | } | 1324 | } |
1323 | 1325 | ||
1324 | static inline int check_modstruct_version(Elf_Shdr *sechdrs, | 1326 | static inline int check_modstruct_version(const struct load_info *info, |
1325 | unsigned int versindex, | ||
1326 | struct module *mod) | 1327 | struct module *mod) |
1327 | { | 1328 | { |
1328 | const s32 *crc; | 1329 | const s32 *crc; |
@@ -1338,8 +1339,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
1338 | BUG(); | 1339 | BUG(); |
1339 | } | 1340 | } |
1340 | preempt_enable(); | 1341 | preempt_enable(); |
1341 | return check_version(sechdrs, versindex, | 1342 | return check_version(info, VMLINUX_SYMBOL_STR(module_layout), |
1342 | VMLINUX_SYMBOL_STR(module_layout), mod, crc); | 1343 | mod, crc); |
1343 | } | 1344 | } |
1344 | 1345 | ||
1345 | /* First part is kernel version, which we ignore if module has crcs. */ | 1346 | /* First part is kernel version, which we ignore if module has crcs. */ |
@@ -1353,8 +1354,7 @@ static inline int same_magic(const char *amagic, const char *bmagic, | |||
1353 | return strcmp(amagic, bmagic) == 0; | 1354 | return strcmp(amagic, bmagic) == 0; |
1354 | } | 1355 | } |
1355 | #else | 1356 | #else |
1356 | static inline int check_version(Elf_Shdr *sechdrs, | 1357 | static inline int check_version(const struct load_info *info, |
1357 | unsigned int versindex, | ||
1358 | const char *symname, | 1358 | const char *symname, |
1359 | struct module *mod, | 1359 | struct module *mod, |
1360 | const s32 *crc) | 1360 | const s32 *crc) |
@@ -1362,8 +1362,7 @@ static inline int check_version(Elf_Shdr *sechdrs, | |||
1362 | return 1; | 1362 | return 1; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | static inline int check_modstruct_version(Elf_Shdr *sechdrs, | 1365 | static inline int check_modstruct_version(const struct load_info *info, |
1366 | unsigned int versindex, | ||
1367 | struct module *mod) | 1366 | struct module *mod) |
1368 | { | 1367 | { |
1369 | return 1; | 1368 | return 1; |
@@ -1399,7 +1398,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, | |||
1399 | if (!sym) | 1398 | if (!sym) |
1400 | goto unlock; | 1399 | goto unlock; |
1401 | 1400 | ||
1402 | if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) { | 1401 | if (!check_version(info, name, mod, crc)) { |
1403 | sym = ERR_PTR(-EINVAL); | 1402 | sym = ERR_PTR(-EINVAL); |
1404 | goto getname; | 1403 | goto getname; |
1405 | } | 1404 | } |
@@ -1662,31 +1661,36 @@ static inline void remove_notes_attrs(struct module *mod) | |||
1662 | } | 1661 | } |
1663 | #endif /* CONFIG_KALLSYMS */ | 1662 | #endif /* CONFIG_KALLSYMS */ |
1664 | 1663 | ||
1665 | static void add_usage_links(struct module *mod) | 1664 | static void del_usage_links(struct module *mod) |
1666 | { | 1665 | { |
1667 | #ifdef CONFIG_MODULE_UNLOAD | 1666 | #ifdef CONFIG_MODULE_UNLOAD |
1668 | struct module_use *use; | 1667 | struct module_use *use; |
1669 | int nowarn; | ||
1670 | 1668 | ||
1671 | mutex_lock(&module_mutex); | 1669 | mutex_lock(&module_mutex); |
1672 | list_for_each_entry(use, &mod->target_list, target_list) { | 1670 | list_for_each_entry(use, &mod->target_list, target_list) |
1673 | nowarn = sysfs_create_link(use->target->holders_dir, | 1671 | sysfs_remove_link(use->target->holders_dir, mod->name); |
1674 | &mod->mkobj.kobj, mod->name); | ||
1675 | } | ||
1676 | mutex_unlock(&module_mutex); | 1672 | mutex_unlock(&module_mutex); |
1677 | #endif | 1673 | #endif |
1678 | } | 1674 | } |
1679 | 1675 | ||
1680 | static void del_usage_links(struct module *mod) | 1676 | static int add_usage_links(struct module *mod) |
1681 | { | 1677 | { |
1678 | int ret = 0; | ||
1682 | #ifdef CONFIG_MODULE_UNLOAD | 1679 | #ifdef CONFIG_MODULE_UNLOAD |
1683 | struct module_use *use; | 1680 | struct module_use *use; |
1684 | 1681 | ||
1685 | mutex_lock(&module_mutex); | 1682 | mutex_lock(&module_mutex); |
1686 | list_for_each_entry(use, &mod->target_list, target_list) | 1683 | list_for_each_entry(use, &mod->target_list, target_list) { |
1687 | sysfs_remove_link(use->target->holders_dir, mod->name); | 1684 | ret = sysfs_create_link(use->target->holders_dir, |
1685 | &mod->mkobj.kobj, mod->name); | ||
1686 | if (ret) | ||
1687 | break; | ||
1688 | } | ||
1688 | mutex_unlock(&module_mutex); | 1689 | mutex_unlock(&module_mutex); |
1690 | if (ret) | ||
1691 | del_usage_links(mod); | ||
1689 | #endif | 1692 | #endif |
1693 | return ret; | ||
1690 | } | 1694 | } |
1691 | 1695 | ||
1692 | static int module_add_modinfo_attrs(struct module *mod) | 1696 | static int module_add_modinfo_attrs(struct module *mod) |
@@ -1797,13 +1801,18 @@ static int mod_sysfs_setup(struct module *mod, | |||
1797 | if (err) | 1801 | if (err) |
1798 | goto out_unreg_param; | 1802 | goto out_unreg_param; |
1799 | 1803 | ||
1800 | add_usage_links(mod); | 1804 | err = add_usage_links(mod); |
1805 | if (err) | ||
1806 | goto out_unreg_modinfo_attrs; | ||
1807 | |||
1801 | add_sect_attrs(mod, info); | 1808 | add_sect_attrs(mod, info); |
1802 | add_notes_attrs(mod, info); | 1809 | add_notes_attrs(mod, info); |
1803 | 1810 | ||
1804 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); | 1811 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); |
1805 | return 0; | 1812 | return 0; |
1806 | 1813 | ||
1814 | out_unreg_modinfo_attrs: | ||
1815 | module_remove_modinfo_attrs(mod); | ||
1807 | out_unreg_param: | 1816 | out_unreg_param: |
1808 | module_param_sysfs_remove(mod); | 1817 | module_param_sysfs_remove(mod); |
1809 | out_unreg_holders: | 1818 | out_unreg_holders: |
@@ -2910,9 +2919,15 @@ static int rewrite_section_headers(struct load_info *info, int flags) | |||
2910 | info->index.vers = 0; /* Pretend no __versions section! */ | 2919 | info->index.vers = 0; /* Pretend no __versions section! */ |
2911 | else | 2920 | else |
2912 | info->index.vers = find_sec(info, "__versions"); | 2921 | info->index.vers = find_sec(info, "__versions"); |
2922 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | ||
2923 | |||
2913 | info->index.info = find_sec(info, ".modinfo"); | 2924 | info->index.info = find_sec(info, ".modinfo"); |
2925 | if (!info->index.info) | ||
2926 | info->name = "(missing .modinfo section)"; | ||
2927 | else | ||
2928 | info->name = get_modinfo(info, "name"); | ||
2914 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2929 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2915 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2930 | |
2916 | return 0; | 2931 | return 0; |
2917 | } | 2932 | } |
2918 | 2933 | ||
@@ -2952,21 +2967,29 @@ static struct module *setup_load_info(struct load_info *info, int flags) | |||
2952 | 2967 | ||
2953 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); | 2968 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); |
2954 | if (!info->index.mod) { | 2969 | if (!info->index.mod) { |
2955 | pr_warn("No module found in object\n"); | 2970 | pr_warn("%s: No module found in object\n", |
2971 | info->name ?: "(missing .modinfo name field)"); | ||
2956 | return ERR_PTR(-ENOEXEC); | 2972 | return ERR_PTR(-ENOEXEC); |
2957 | } | 2973 | } |
2958 | /* This is temporary: point mod into copy of data. */ | 2974 | /* This is temporary: point mod into copy of data. */ |
2959 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; | 2975 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; |
2960 | 2976 | ||
2977 | /* | ||
2978 | * If we didn't load the .modinfo 'name' field, fall back to | ||
2979 | * on-disk struct mod 'name' field. | ||
2980 | */ | ||
2981 | if (!info->name) | ||
2982 | info->name = mod->name; | ||
2983 | |||
2961 | if (info->index.sym == 0) { | 2984 | if (info->index.sym == 0) { |
2962 | pr_warn("%s: module has no symbols (stripped?)\n", mod->name); | 2985 | pr_warn("%s: module has no symbols (stripped?)\n", info->name); |
2963 | return ERR_PTR(-ENOEXEC); | 2986 | return ERR_PTR(-ENOEXEC); |
2964 | } | 2987 | } |
2965 | 2988 | ||
2966 | info->index.pcpu = find_pcpusec(info); | 2989 | info->index.pcpu = find_pcpusec(info); |
2967 | 2990 | ||
2968 | /* Check module struct version now, before we try to use module. */ | 2991 | /* Check module struct version now, before we try to use module. */ |
2969 | if (!check_modstruct_version(info->sechdrs, info->index.vers, mod)) | 2992 | if (!check_modstruct_version(info, mod)) |
2970 | return ERR_PTR(-ENOEXEC); | 2993 | return ERR_PTR(-ENOEXEC); |
2971 | 2994 | ||
2972 | return mod; | 2995 | return mod; |
@@ -2987,7 +3010,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) | |||
2987 | return err; | 3010 | return err; |
2988 | } else if (!same_magic(modmagic, vermagic, info->index.vers)) { | 3011 | } else if (!same_magic(modmagic, vermagic, info->index.vers)) { |
2989 | pr_err("%s: version magic '%s' should be '%s'\n", | 3012 | pr_err("%s: version magic '%s' should be '%s'\n", |
2990 | mod->name, modmagic, vermagic); | 3013 | info->name, modmagic, vermagic); |
2991 | return -ENOEXEC; | 3014 | return -ENOEXEC; |
2992 | } | 3015 | } |
2993 | 3016 | ||
@@ -3237,7 +3260,7 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, | |||
3237 | 3260 | ||
3238 | /* module_blacklist is a comma-separated list of module names */ | 3261 | /* module_blacklist is a comma-separated list of module names */ |
3239 | static char *module_blacklist; | 3262 | static char *module_blacklist; |
3240 | static bool blacklisted(char *module_name) | 3263 | static bool blacklisted(const char *module_name) |
3241 | { | 3264 | { |
3242 | const char *p; | 3265 | const char *p; |
3243 | size_t len; | 3266 | size_t len; |
@@ -3267,7 +3290,7 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
3267 | if (IS_ERR(mod)) | 3290 | if (IS_ERR(mod)) |
3268 | return mod; | 3291 | return mod; |
3269 | 3292 | ||
3270 | if (blacklisted(mod->name)) | 3293 | if (blacklisted(info->name)) |
3271 | return ERR_PTR(-EPERM); | 3294 | return ERR_PTR(-EPERM); |
3272 | 3295 | ||
3273 | err = check_modinfo(mod, info, flags); | 3296 | err = check_modinfo(mod, info, flags); |