diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/kernel/module.c b/kernel/module.c index 215aaab09e91..46580edff0cb 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -55,6 +55,11 @@ | |||
| 55 | #include <linux/percpu.h> | 55 | #include <linux/percpu.h> |
| 56 | #include <linux/kmemleak.h> | 56 | #include <linux/kmemleak.h> |
| 57 | 57 | ||
| 58 | #define CREATE_TRACE_POINTS | ||
| 59 | #include <trace/events/module.h> | ||
| 60 | |||
| 61 | EXPORT_TRACEPOINT_SYMBOL(module_get); | ||
| 62 | |||
| 58 | #if 0 | 63 | #if 0 |
| 59 | #define DEBUGP printk | 64 | #define DEBUGP printk |
| 60 | #else | 65 | #else |
| @@ -909,16 +914,18 @@ void __symbol_put(const char *symbol) | |||
| 909 | } | 914 | } |
| 910 | EXPORT_SYMBOL(__symbol_put); | 915 | EXPORT_SYMBOL(__symbol_put); |
| 911 | 916 | ||
| 917 | /* Note this assumes addr is a function, which it currently always is. */ | ||
| 912 | void symbol_put_addr(void *addr) | 918 | void symbol_put_addr(void *addr) |
| 913 | { | 919 | { |
| 914 | struct module *modaddr; | 920 | struct module *modaddr; |
| 921 | unsigned long a = (unsigned long)dereference_function_descriptor(addr); | ||
| 915 | 922 | ||
| 916 | if (core_kernel_text((unsigned long)addr)) | 923 | if (core_kernel_text(a)) |
| 917 | return; | 924 | return; |
| 918 | 925 | ||
| 919 | /* module_text_address is safe here: we're supposed to have reference | 926 | /* module_text_address is safe here: we're supposed to have reference |
| 920 | * to module from symbol_get, so it can't go away. */ | 927 | * to module from symbol_get, so it can't go away. */ |
| 921 | modaddr = __module_text_address((unsigned long)addr); | 928 | modaddr = __module_text_address(a); |
| 922 | BUG_ON(!modaddr); | 929 | BUG_ON(!modaddr); |
| 923 | module_put(modaddr); | 930 | module_put(modaddr); |
| 924 | } | 931 | } |
| @@ -940,6 +947,8 @@ void module_put(struct module *module) | |||
| 940 | if (module) { | 947 | if (module) { |
| 941 | unsigned int cpu = get_cpu(); | 948 | unsigned int cpu = get_cpu(); |
| 942 | local_dec(__module_ref_addr(module, cpu)); | 949 | local_dec(__module_ref_addr(module, cpu)); |
| 950 | trace_module_put(module, _RET_IP_, | ||
| 951 | local_read(__module_ref_addr(module, cpu))); | ||
| 943 | /* Maybe they're waiting for us to drop reference? */ | 952 | /* Maybe they're waiting for us to drop reference? */ |
| 944 | if (unlikely(!module_is_live(module))) | 953 | if (unlikely(!module_is_live(module))) |
| 945 | wake_up_process(module->waiter); | 954 | wake_up_process(module->waiter); |
| @@ -1068,7 +1077,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs, | |||
| 1068 | { | 1077 | { |
| 1069 | const unsigned long *crc; | 1078 | const unsigned long *crc; |
| 1070 | 1079 | ||
| 1071 | if (!find_symbol("module_layout", NULL, &crc, true, false)) | 1080 | if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL, |
| 1081 | &crc, true, false)) | ||
| 1072 | BUG(); | 1082 | BUG(); |
| 1073 | return check_version(sechdrs, versindex, "module_layout", mod, crc); | 1083 | return check_version(sechdrs, versindex, "module_layout", mod, crc); |
| 1074 | } | 1084 | } |
| @@ -1271,6 +1281,10 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
| 1271 | struct module_notes_attrs *notes_attrs; | 1281 | struct module_notes_attrs *notes_attrs; |
| 1272 | struct bin_attribute *nattr; | 1282 | struct bin_attribute *nattr; |
| 1273 | 1283 | ||
| 1284 | /* failed to create section attributes, so can't create notes */ | ||
| 1285 | if (!mod->sect_attrs) | ||
| 1286 | return; | ||
| 1287 | |||
| 1274 | /* Count notes sections and allocate structures. */ | 1288 | /* Count notes sections and allocate structures. */ |
| 1275 | notes = 0; | 1289 | notes = 0; |
| 1276 | for (i = 0; i < nsect; i++) | 1290 | for (i = 0; i < nsect; i++) |
| @@ -1490,6 +1504,8 @@ static int __unlink_module(void *_mod) | |||
| 1490 | /* Free a module, remove from lists, etc (must hold module_mutex). */ | 1504 | /* Free a module, remove from lists, etc (must hold module_mutex). */ |
| 1491 | static void free_module(struct module *mod) | 1505 | static void free_module(struct module *mod) |
| 1492 | { | 1506 | { |
| 1507 | trace_module_free(mod); | ||
| 1508 | |||
| 1493 | /* Delete from various lists */ | 1509 | /* Delete from various lists */ |
| 1494 | stop_machine(__unlink_module, mod, NULL); | 1510 | stop_machine(__unlink_module, mod, NULL); |
| 1495 | remove_notes_attrs(mod); | 1511 | remove_notes_attrs(mod); |
| @@ -2216,6 +2232,10 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2216 | mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings, | 2232 | mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings, |
| 2217 | "__kcrctab_unused_gpl"); | 2233 | "__kcrctab_unused_gpl"); |
| 2218 | #endif | 2234 | #endif |
| 2235 | #ifdef CONFIG_CONSTRUCTORS | ||
| 2236 | mod->ctors = section_objs(hdr, sechdrs, secstrings, ".ctors", | ||
| 2237 | sizeof(*mod->ctors), &mod->num_ctors); | ||
| 2238 | #endif | ||
| 2219 | 2239 | ||
| 2220 | #ifdef CONFIG_MARKERS | 2240 | #ifdef CONFIG_MARKERS |
| 2221 | mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers", | 2241 | mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers", |
| @@ -2353,6 +2373,8 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2353 | /* Get rid of temporary copy */ | 2373 | /* Get rid of temporary copy */ |
| 2354 | vfree(hdr); | 2374 | vfree(hdr); |
| 2355 | 2375 | ||
| 2376 | trace_module_load(mod); | ||
| 2377 | |||
| 2356 | /* Done! */ | 2378 | /* Done! */ |
| 2357 | return mod; | 2379 | return mod; |
| 2358 | 2380 | ||
| @@ -2389,6 +2411,17 @@ static noinline struct module *load_module(void __user *umod, | |||
| 2389 | goto free_hdr; | 2411 | goto free_hdr; |
| 2390 | } | 2412 | } |
| 2391 | 2413 | ||
| 2414 | /* Call module constructors. */ | ||
| 2415 | static void do_mod_ctors(struct module *mod) | ||
| 2416 | { | ||
| 2417 | #ifdef CONFIG_CONSTRUCTORS | ||
| 2418 | unsigned long i; | ||
| 2419 | |||
| 2420 | for (i = 0; i < mod->num_ctors; i++) | ||
| 2421 | mod->ctors[i](); | ||
| 2422 | #endif | ||
| 2423 | } | ||
| 2424 | |||
| 2392 | /* This is where the real work happens */ | 2425 | /* This is where the real work happens */ |
| 2393 | SYSCALL_DEFINE3(init_module, void __user *, umod, | 2426 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
| 2394 | unsigned long, len, const char __user *, uargs) | 2427 | unsigned long, len, const char __user *, uargs) |
| @@ -2417,6 +2450,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2417 | blocking_notifier_call_chain(&module_notify_list, | 2450 | blocking_notifier_call_chain(&module_notify_list, |
| 2418 | MODULE_STATE_COMING, mod); | 2451 | MODULE_STATE_COMING, mod); |
| 2419 | 2452 | ||
| 2453 | do_mod_ctors(mod); | ||
| 2420 | /* Start the module */ | 2454 | /* Start the module */ |
| 2421 | if (mod->init != NULL) | 2455 | if (mod->init != NULL) |
| 2422 | ret = do_one_initcall(mod->init); | 2456 | ret = do_one_initcall(mod->init); |
| @@ -2435,9 +2469,9 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
| 2435 | return ret; | 2469 | return ret; |
| 2436 | } | 2470 | } |
| 2437 | if (ret > 0) { | 2471 | if (ret > 0) { |
| 2438 | printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, " | 2472 | printk(KERN_WARNING |
| 2439 | "it should follow 0/-E convention\n" | 2473 | "%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n" |
| 2440 | KERN_WARNING "%s: loading module anyway...\n", | 2474 | "%s: loading module anyway...\n", |
| 2441 | __func__, mod->name, ret, | 2475 | __func__, mod->name, ret, |
| 2442 | __func__); | 2476 | __func__); |
| 2443 | dump_stack(); | 2477 | dump_stack(); |
