diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/kernel/module.c b/kernel/module.c index 4a3665f8f837..40f983cbea81 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -49,9 +49,7 @@ | |||
| 49 | #include <linux/rculist.h> | 49 | #include <linux/rculist.h> |
| 50 | #include <linux/uaccess.h> | 50 | #include <linux/uaccess.h> |
| 51 | #include <asm/cacheflush.h> | 51 | #include <asm/cacheflush.h> |
| 52 | #ifdef CONFIG_STRICT_MODULE_RWX | 52 | #include <linux/set_memory.h> |
| 53 | #include <asm/set_memory.h> | ||
| 54 | #endif | ||
| 55 | #include <asm/mmu_context.h> | 53 | #include <asm/mmu_context.h> |
| 56 | #include <linux/license.h> | 54 | #include <linux/license.h> |
| 57 | #include <asm/sections.h> | 55 | #include <asm/sections.h> |
| @@ -302,6 +300,7 @@ int unregister_module_notifier(struct notifier_block *nb) | |||
| 302 | EXPORT_SYMBOL(unregister_module_notifier); | 300 | EXPORT_SYMBOL(unregister_module_notifier); |
| 303 | 301 | ||
| 304 | struct load_info { | 302 | struct load_info { |
| 303 | const char *name; | ||
| 305 | Elf_Ehdr *hdr; | 304 | Elf_Ehdr *hdr; |
| 306 | unsigned long len; | 305 | unsigned long len; |
| 307 | Elf_Shdr *sechdrs; | 306 | Elf_Shdr *sechdrs; |
| @@ -602,7 +601,7 @@ static struct module *find_module_all(const char *name, size_t len, | |||
| 602 | 601 | ||
| 603 | module_assert_mutex_or_preempt(); | 602 | module_assert_mutex_or_preempt(); |
| 604 | 603 | ||
| 605 | list_for_each_entry(mod, &modules, list) { | 604 | list_for_each_entry_rcu(mod, &modules, list) { |
| 606 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | 605 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) |
| 607 | continue; | 606 | continue; |
| 608 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) | 607 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) |
| @@ -1202,10 +1201,7 @@ static ssize_t store_uevent(struct module_attribute *mattr, | |||
| 1202 | struct module_kobject *mk, | 1201 | struct module_kobject *mk, |
| 1203 | const char *buffer, size_t count) | 1202 | const char *buffer, size_t count) |
| 1204 | { | 1203 | { |
| 1205 | enum kobject_action action; | 1204 | kobject_synth_uevent(&mk->kobj, buffer, count); |
| 1206 | |||
| 1207 | if (kobject_action_type(buffer, count, &action) == 0) | ||
| 1208 | kobject_uevent(&mk->kobj, action); | ||
| 1209 | return count; | 1205 | return count; |
| 1210 | } | 1206 | } |
| 1211 | 1207 | ||
| @@ -1278,12 +1274,13 @@ static u32 resolve_rel_crc(const s32 *crc) | |||
| 1278 | return *(u32 *)((void *)crc + *crc); | 1274 | return *(u32 *)((void *)crc + *crc); |
| 1279 | } | 1275 | } |
| 1280 | 1276 | ||
| 1281 | static int check_version(Elf_Shdr *sechdrs, | 1277 | static int check_version(const struct load_info *info, |
| 1282 | unsigned int versindex, | ||
| 1283 | const char *symname, | 1278 | const char *symname, |
| 1284 | struct module *mod, | 1279 | struct module *mod, |
| 1285 | const s32 *crc) | 1280 | const s32 *crc) |
| 1286 | { | 1281 | { |
| 1282 | Elf_Shdr *sechdrs = info->sechdrs; | ||
| 1283 | unsigned int versindex = info->index.vers; | ||
| 1287 | unsigned int i, num_versions; | 1284 | unsigned int i, num_versions; |
| 1288 | struct modversion_info *versions; | 1285 | struct modversion_info *versions; |
| 1289 | 1286 | ||
| @@ -1317,17 +1314,16 @@ static int check_version(Elf_Shdr *sechdrs, | |||
| 1317 | } | 1314 | } |
| 1318 | 1315 | ||
| 1319 | /* Broken toolchain. Warn once, then let it go.. */ | 1316 | /* Broken toolchain. Warn once, then let it go.. */ |
| 1320 | 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); |
| 1321 | return 1; | 1318 | return 1; |
| 1322 | 1319 | ||
| 1323 | bad_version: | 1320 | bad_version: |
| 1324 | pr_warn("%s: disagrees about version of symbol %s\n", | 1321 | pr_warn("%s: disagrees about version of symbol %s\n", |
| 1325 | mod->name, symname); | 1322 | info->name, symname); |
| 1326 | return 0; | 1323 | return 0; |
| 1327 | } | 1324 | } |
| 1328 | 1325 | ||
| 1329 | static inline int check_modstruct_version(Elf_Shdr *sechdrs, | 1326 | static inline int check_modstruct_version(const struct load_info *info, |
| 1330 | unsigned int versindex, | ||
| 1331 | struct module *mod) | 1327 | struct module *mod) |
| 1332 | { | 1328 | { |
| 1333 | const s32 *crc; | 1329 | const s32 *crc; |
| @@ -1343,8 +1339,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
| 1343 | BUG(); | 1339 | BUG(); |
| 1344 | } | 1340 | } |
| 1345 | preempt_enable(); | 1341 | preempt_enable(); |
| 1346 | return check_version(sechdrs, versindex, | 1342 | return check_version(info, VMLINUX_SYMBOL_STR(module_layout), |
| 1347 | VMLINUX_SYMBOL_STR(module_layout), mod, crc); | 1343 | mod, crc); |
| 1348 | } | 1344 | } |
| 1349 | 1345 | ||
| 1350 | /* 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. */ |
| @@ -1358,8 +1354,7 @@ static inline int same_magic(const char *amagic, const char *bmagic, | |||
| 1358 | return strcmp(amagic, bmagic) == 0; | 1354 | return strcmp(amagic, bmagic) == 0; |
| 1359 | } | 1355 | } |
| 1360 | #else | 1356 | #else |
| 1361 | static inline int check_version(Elf_Shdr *sechdrs, | 1357 | static inline int check_version(const struct load_info *info, |
| 1362 | unsigned int versindex, | ||
| 1363 | const char *symname, | 1358 | const char *symname, |
| 1364 | struct module *mod, | 1359 | struct module *mod, |
| 1365 | const s32 *crc) | 1360 | const s32 *crc) |
| @@ -1367,8 +1362,7 @@ static inline int check_version(Elf_Shdr *sechdrs, | |||
| 1367 | return 1; | 1362 | return 1; |
| 1368 | } | 1363 | } |
| 1369 | 1364 | ||
| 1370 | static inline int check_modstruct_version(Elf_Shdr *sechdrs, | 1365 | static inline int check_modstruct_version(const struct load_info *info, |
| 1371 | unsigned int versindex, | ||
| 1372 | struct module *mod) | 1366 | struct module *mod) |
| 1373 | { | 1367 | { |
| 1374 | return 1; | 1368 | return 1; |
| @@ -1404,7 +1398,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, | |||
| 1404 | if (!sym) | 1398 | if (!sym) |
| 1405 | goto unlock; | 1399 | goto unlock; |
| 1406 | 1400 | ||
| 1407 | if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) { | 1401 | if (!check_version(info, name, mod, crc)) { |
| 1408 | sym = ERR_PTR(-EINVAL); | 1402 | sym = ERR_PTR(-EINVAL); |
| 1409 | goto getname; | 1403 | goto getname; |
| 1410 | } | 1404 | } |
| @@ -1667,31 +1661,36 @@ static inline void remove_notes_attrs(struct module *mod) | |||
| 1667 | } | 1661 | } |
| 1668 | #endif /* CONFIG_KALLSYMS */ | 1662 | #endif /* CONFIG_KALLSYMS */ |
| 1669 | 1663 | ||
| 1670 | static void add_usage_links(struct module *mod) | 1664 | static void del_usage_links(struct module *mod) |
| 1671 | { | 1665 | { |
| 1672 | #ifdef CONFIG_MODULE_UNLOAD | 1666 | #ifdef CONFIG_MODULE_UNLOAD |
| 1673 | struct module_use *use; | 1667 | struct module_use *use; |
| 1674 | int nowarn; | ||
| 1675 | 1668 | ||
| 1676 | mutex_lock(&module_mutex); | 1669 | mutex_lock(&module_mutex); |
| 1677 | list_for_each_entry(use, &mod->target_list, target_list) { | 1670 | list_for_each_entry(use, &mod->target_list, target_list) |
| 1678 | nowarn = sysfs_create_link(use->target->holders_dir, | 1671 | sysfs_remove_link(use->target->holders_dir, mod->name); |
| 1679 | &mod->mkobj.kobj, mod->name); | ||
| 1680 | } | ||
| 1681 | mutex_unlock(&module_mutex); | 1672 | mutex_unlock(&module_mutex); |
| 1682 | #endif | 1673 | #endif |
| 1683 | } | 1674 | } |
| 1684 | 1675 | ||
| 1685 | static void del_usage_links(struct module *mod) | 1676 | static int add_usage_links(struct module *mod) |
| 1686 | { | 1677 | { |
| 1678 | int ret = 0; | ||
| 1687 | #ifdef CONFIG_MODULE_UNLOAD | 1679 | #ifdef CONFIG_MODULE_UNLOAD |
| 1688 | struct module_use *use; | 1680 | struct module_use *use; |
| 1689 | 1681 | ||
| 1690 | mutex_lock(&module_mutex); | 1682 | mutex_lock(&module_mutex); |
| 1691 | list_for_each_entry(use, &mod->target_list, target_list) | 1683 | list_for_each_entry(use, &mod->target_list, target_list) { |
| 1692 | 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 | } | ||
| 1693 | mutex_unlock(&module_mutex); | 1689 | mutex_unlock(&module_mutex); |
| 1690 | if (ret) | ||
| 1691 | del_usage_links(mod); | ||
| 1694 | #endif | 1692 | #endif |
| 1693 | return ret; | ||
| 1695 | } | 1694 | } |
| 1696 | 1695 | ||
| 1697 | static int module_add_modinfo_attrs(struct module *mod) | 1696 | static int module_add_modinfo_attrs(struct module *mod) |
| @@ -1802,13 +1801,18 @@ static int mod_sysfs_setup(struct module *mod, | |||
| 1802 | if (err) | 1801 | if (err) |
| 1803 | goto out_unreg_param; | 1802 | goto out_unreg_param; |
| 1804 | 1803 | ||
| 1805 | add_usage_links(mod); | 1804 | err = add_usage_links(mod); |
| 1805 | if (err) | ||
| 1806 | goto out_unreg_modinfo_attrs; | ||
| 1807 | |||
| 1806 | add_sect_attrs(mod, info); | 1808 | add_sect_attrs(mod, info); |
| 1807 | add_notes_attrs(mod, info); | 1809 | add_notes_attrs(mod, info); |
| 1808 | 1810 | ||
| 1809 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); | 1811 | kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); |
| 1810 | return 0; | 1812 | return 0; |
| 1811 | 1813 | ||
| 1814 | out_unreg_modinfo_attrs: | ||
| 1815 | module_remove_modinfo_attrs(mod); | ||
| 1812 | out_unreg_param: | 1816 | out_unreg_param: |
| 1813 | module_param_sysfs_remove(mod); | 1817 | module_param_sysfs_remove(mod); |
| 1814 | out_unreg_holders: | 1818 | out_unreg_holders: |
| @@ -2915,9 +2919,15 @@ static int rewrite_section_headers(struct load_info *info, int flags) | |||
| 2915 | info->index.vers = 0; /* Pretend no __versions section! */ | 2919 | info->index.vers = 0; /* Pretend no __versions section! */ |
| 2916 | else | 2920 | else |
| 2917 | 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 | |||
| 2918 | 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"); | ||
| 2919 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2929 | info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; |
| 2920 | info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2930 | |
| 2921 | return 0; | 2931 | return 0; |
| 2922 | } | 2932 | } |
| 2923 | 2933 | ||
| @@ -2957,21 +2967,29 @@ static struct module *setup_load_info(struct load_info *info, int flags) | |||
| 2957 | 2967 | ||
| 2958 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); | 2968 | info->index.mod = find_sec(info, ".gnu.linkonce.this_module"); |
| 2959 | if (!info->index.mod) { | 2969 | if (!info->index.mod) { |
| 2960 | 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)"); | ||
| 2961 | return ERR_PTR(-ENOEXEC); | 2972 | return ERR_PTR(-ENOEXEC); |
| 2962 | } | 2973 | } |
| 2963 | /* This is temporary: point mod into copy of data. */ | 2974 | /* This is temporary: point mod into copy of data. */ |
| 2964 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; | 2975 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; |
| 2965 | 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 | |||
| 2966 | if (info->index.sym == 0) { | 2984 | if (info->index.sym == 0) { |
| 2967 | pr_warn("%s: module has no symbols (stripped?)\n", mod->name); | 2985 | pr_warn("%s: module has no symbols (stripped?)\n", info->name); |
| 2968 | return ERR_PTR(-ENOEXEC); | 2986 | return ERR_PTR(-ENOEXEC); |
| 2969 | } | 2987 | } |
| 2970 | 2988 | ||
| 2971 | info->index.pcpu = find_pcpusec(info); | 2989 | info->index.pcpu = find_pcpusec(info); |
| 2972 | 2990 | ||
| 2973 | /* Check module struct version now, before we try to use module. */ | 2991 | /* Check module struct version now, before we try to use module. */ |
| 2974 | if (!check_modstruct_version(info->sechdrs, info->index.vers, mod)) | 2992 | if (!check_modstruct_version(info, mod)) |
| 2975 | return ERR_PTR(-ENOEXEC); | 2993 | return ERR_PTR(-ENOEXEC); |
| 2976 | 2994 | ||
| 2977 | return mod; | 2995 | return mod; |
| @@ -2992,7 +3010,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) | |||
| 2992 | return err; | 3010 | return err; |
| 2993 | } else if (!same_magic(modmagic, vermagic, info->index.vers)) { | 3011 | } else if (!same_magic(modmagic, vermagic, info->index.vers)) { |
| 2994 | pr_err("%s: version magic '%s' should be '%s'\n", | 3012 | pr_err("%s: version magic '%s' should be '%s'\n", |
| 2995 | mod->name, modmagic, vermagic); | 3013 | info->name, modmagic, vermagic); |
| 2996 | return -ENOEXEC; | 3014 | return -ENOEXEC; |
| 2997 | } | 3015 | } |
| 2998 | 3016 | ||
| @@ -3077,9 +3095,9 @@ static int find_module_sections(struct module *mod, struct load_info *info) | |||
| 3077 | mod->trace_events = section_objs(info, "_ftrace_events", | 3095 | mod->trace_events = section_objs(info, "_ftrace_events", |
| 3078 | sizeof(*mod->trace_events), | 3096 | sizeof(*mod->trace_events), |
| 3079 | &mod->num_trace_events); | 3097 | &mod->num_trace_events); |
| 3080 | mod->trace_enums = section_objs(info, "_ftrace_enum_map", | 3098 | mod->trace_evals = section_objs(info, "_ftrace_eval_map", |
| 3081 | sizeof(*mod->trace_enums), | 3099 | sizeof(*mod->trace_evals), |
| 3082 | &mod->num_trace_enums); | 3100 | &mod->num_trace_evals); |
| 3083 | #endif | 3101 | #endif |
| 3084 | #ifdef CONFIG_TRACING | 3102 | #ifdef CONFIG_TRACING |
| 3085 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", | 3103 | mod->trace_bprintk_fmt_start = section_objs(info, "__trace_printk_fmt", |
| @@ -3242,7 +3260,7 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, | |||
| 3242 | 3260 | ||
| 3243 | /* module_blacklist is a comma-separated list of module names */ | 3261 | /* module_blacklist is a comma-separated list of module names */ |
| 3244 | static char *module_blacklist; | 3262 | static char *module_blacklist; |
| 3245 | static bool blacklisted(char *module_name) | 3263 | static bool blacklisted(const char *module_name) |
| 3246 | { | 3264 | { |
| 3247 | const char *p; | 3265 | const char *p; |
| 3248 | size_t len; | 3266 | size_t len; |
| @@ -3272,7 +3290,7 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
| 3272 | if (IS_ERR(mod)) | 3290 | if (IS_ERR(mod)) |
| 3273 | return mod; | 3291 | return mod; |
| 3274 | 3292 | ||
| 3275 | if (blacklisted(mod->name)) | 3293 | if (blacklisted(info->name)) |
| 3276 | return ERR_PTR(-EPERM); | 3294 | return ERR_PTR(-EPERM); |
| 3277 | 3295 | ||
| 3278 | err = check_modinfo(mod, info, flags); | 3296 | err = check_modinfo(mod, info, flags); |
| @@ -4201,7 +4219,7 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) | |||
| 4201 | goto out; | 4219 | goto out; |
| 4202 | 4220 | ||
| 4203 | e = search_extable(mod->extable, | 4221 | e = search_extable(mod->extable, |
| 4204 | mod->extable + mod->num_exentries - 1, | 4222 | mod->num_exentries, |
| 4205 | addr); | 4223 | addr); |
| 4206 | out: | 4224 | out: |
| 4207 | preempt_enable(); | 4225 | preempt_enable(); |
