diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 299 |
1 files changed, 171 insertions, 128 deletions
diff --git a/kernel/module.c b/kernel/module.c index 29f2d7b33dd..c268a771595 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -68,7 +68,8 @@ | |||
| 68 | 68 | ||
| 69 | /* List of modules, protected by module_mutex or preempt_disable | 69 | /* List of modules, protected by module_mutex or preempt_disable |
| 70 | * (delete uses stop_machine/add uses RCU list operations). */ | 70 | * (delete uses stop_machine/add uses RCU list operations). */ |
| 71 | static DEFINE_MUTEX(module_mutex); | 71 | DEFINE_MUTEX(module_mutex); |
| 72 | EXPORT_SYMBOL_GPL(module_mutex); | ||
| 72 | static LIST_HEAD(modules); | 73 | static LIST_HEAD(modules); |
| 73 | 74 | ||
| 74 | /* Waiting for a module to finish initializing? */ | 75 | /* Waiting for a module to finish initializing? */ |
| @@ -76,7 +77,7 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq); | |||
| 76 | 77 | ||
| 77 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 78 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
| 78 | 79 | ||
| 79 | /* Bounds of module allocation, for speeding __module_text_address */ | 80 | /* Bounds of module allocation, for speeding __module_address */ |
| 80 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; | 81 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
| 81 | 82 | ||
| 82 | int register_module_notifier(struct notifier_block * nb) | 83 | int register_module_notifier(struct notifier_block * nb) |
| @@ -186,17 +187,6 @@ extern const unsigned long __start___kcrctab_unused_gpl[]; | |||
| 186 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) | 187 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) |
| 187 | #endif | 188 | #endif |
| 188 | 189 | ||
| 189 | struct symsearch { | ||
| 190 | const struct kernel_symbol *start, *stop; | ||
| 191 | const unsigned long *crcs; | ||
| 192 | enum { | ||
| 193 | NOT_GPL_ONLY, | ||
| 194 | GPL_ONLY, | ||
| 195 | WILL_BE_GPL_ONLY, | ||
| 196 | } licence; | ||
| 197 | bool unused; | ||
| 198 | }; | ||
| 199 | |||
| 200 | static bool each_symbol_in_section(const struct symsearch *arr, | 190 | static bool each_symbol_in_section(const struct symsearch *arr, |
| 201 | unsigned int arrsize, | 191 | unsigned int arrsize, |
| 202 | struct module *owner, | 192 | struct module *owner, |
| @@ -217,10 +207,8 @@ static bool each_symbol_in_section(const struct symsearch *arr, | |||
| 217 | } | 207 | } |
| 218 | 208 | ||
| 219 | /* Returns true as soon as fn returns true, otherwise false. */ | 209 | /* Returns true as soon as fn returns true, otherwise false. */ |
| 220 | static bool each_symbol(bool (*fn)(const struct symsearch *arr, | 210 | bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, |
| 221 | struct module *owner, | 211 | unsigned int symnum, void *data), void *data) |
| 222 | unsigned int symnum, void *data), | ||
| 223 | void *data) | ||
| 224 | { | 212 | { |
| 225 | struct module *mod; | 213 | struct module *mod; |
| 226 | const struct symsearch arr[] = { | 214 | const struct symsearch arr[] = { |
| @@ -273,6 +261,7 @@ static bool each_symbol(bool (*fn)(const struct symsearch *arr, | |||
| 273 | } | 261 | } |
| 274 | return false; | 262 | return false; |
| 275 | } | 263 | } |
| 264 | EXPORT_SYMBOL_GPL(each_symbol); | ||
| 276 | 265 | ||
| 277 | struct find_symbol_arg { | 266 | struct find_symbol_arg { |
| 278 | /* Input */ | 267 | /* Input */ |
| @@ -283,7 +272,7 @@ struct find_symbol_arg { | |||
| 283 | /* Output */ | 272 | /* Output */ |
| 284 | struct module *owner; | 273 | struct module *owner; |
| 285 | const unsigned long *crc; | 274 | const unsigned long *crc; |
| 286 | unsigned long value; | 275 | const struct kernel_symbol *sym; |
| 287 | }; | 276 | }; |
| 288 | 277 | ||
| 289 | static bool find_symbol_in_section(const struct symsearch *syms, | 278 | static bool find_symbol_in_section(const struct symsearch *syms, |
| @@ -324,17 +313,17 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
| 324 | 313 | ||
| 325 | fsa->owner = owner; | 314 | fsa->owner = owner; |
| 326 | fsa->crc = symversion(syms->crcs, symnum); | 315 | fsa->crc = symversion(syms->crcs, symnum); |
| 327 | fsa->value = syms->start[symnum].value; | 316 | fsa->sym = &syms->start[symnum]; |
| 328 | return true; | 317 | return true; |
| 329 | } | 318 | } |
| 330 | 319 | ||
| 331 | /* Find a symbol, return value, (optional) crc and (optional) module | 320 | /* Find a symbol and return it, along with, (optional) crc and |
| 332 | * which owns it */ | 321 | * (optional) module which owns it */ |
| 333 | static unsigned long find_symbol(const char *name, | 322 | const struct kernel_symbol *find_symbol(const char *name, |
| 334 | struct module **owner, | 323 | struct module **owner, |
| 335 | const unsigned long **crc, | 324 | const unsigned long **crc, |
| 336 | bool gplok, | 325 | bool gplok, |
| 337 | bool warn) | 326 | bool warn) |
| 338 | { | 327 | { |
| 339 | struct find_symbol_arg fsa; | 328 | struct find_symbol_arg fsa; |
| 340 | 329 | ||
| @@ -347,15 +336,16 @@ static unsigned long find_symbol(const char *name, | |||
| 347 | *owner = fsa.owner; | 336 | *owner = fsa.owner; |
| 348 | if (crc) | 337 | if (crc) |
| 349 | *crc = fsa.crc; | 338 | *crc = fsa.crc; |
| 350 | return fsa.value; | 339 | return fsa.sym; |
| 351 | } | 340 | } |
| 352 | 341 | ||
| 353 | DEBUGP("Failed to find symbol %s\n", name); | 342 | DEBUGP("Failed to find symbol %s\n", name); |
| 354 | return -ENOENT; | 343 | return NULL; |
| 355 | } | 344 | } |
| 345 | EXPORT_SYMBOL_GPL(find_symbol); | ||
| 356 | 346 | ||
| 357 | /* Search for module by name: must hold module_mutex. */ | 347 | /* Search for module by name: must hold module_mutex. */ |
| 358 | static struct module *find_module(const char *name) | 348 | struct module *find_module(const char *name) |
| 359 | { | 349 | { |
| 360 | struct module *mod; | 350 | struct module *mod; |
| 361 | 351 | ||
| @@ -365,6 +355,7 @@ static struct module *find_module(const char *name) | |||
| 365 | } | 355 | } |
| 366 | return NULL; | 356 | return NULL; |
| 367 | } | 357 | } |
| 358 | EXPORT_SYMBOL_GPL(find_module); | ||
| 368 | 359 | ||
| 369 | #ifdef CONFIG_SMP | 360 | #ifdef CONFIG_SMP |
| 370 | 361 | ||
| @@ -641,7 +632,7 @@ static int already_uses(struct module *a, struct module *b) | |||
| 641 | } | 632 | } |
| 642 | 633 | ||
| 643 | /* Module a uses b */ | 634 | /* Module a uses b */ |
| 644 | static int use_module(struct module *a, struct module *b) | 635 | int use_module(struct module *a, struct module *b) |
| 645 | { | 636 | { |
| 646 | struct module_use *use; | 637 | struct module_use *use; |
| 647 | int no_warn, err; | 638 | int no_warn, err; |
| @@ -674,6 +665,7 @@ static int use_module(struct module *a, struct module *b) | |||
| 674 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); | 665 | no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); |
| 675 | return 1; | 666 | return 1; |
| 676 | } | 667 | } |
| 668 | EXPORT_SYMBOL_GPL(use_module); | ||
| 677 | 669 | ||
| 678 | /* Clear the unload stuff of the module. */ | 670 | /* Clear the unload stuff of the module. */ |
| 679 | static void module_unload_free(struct module *mod) | 671 | static void module_unload_free(struct module *mod) |
| @@ -856,7 +848,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, | |||
| 856 | mutex_lock(&module_mutex); | 848 | mutex_lock(&module_mutex); |
| 857 | /* Store the name of the last unloaded module for diagnostic purposes */ | 849 | /* Store the name of the last unloaded module for diagnostic purposes */ |
| 858 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); | 850 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
| 859 | unregister_dynamic_debug_module(mod->name); | 851 | ddebug_remove_module(mod->name); |
| 860 | free_module(mod); | 852 | free_module(mod); |
| 861 | 853 | ||
| 862 | out: | 854 | out: |
| @@ -894,7 +886,7 @@ void __symbol_put(const char *symbol) | |||
| 894 | struct module *owner; | 886 | struct module *owner; |
| 895 | 887 | ||
| 896 | preempt_disable(); | 888 | preempt_disable(); |
| 897 | if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false))) | 889 | if (!find_symbol(symbol, &owner, NULL, true, false)) |
| 898 | BUG(); | 890 | BUG(); |
| 899 | module_put(owner); | 891 | module_put(owner); |
| 900 | preempt_enable(); | 892 | preempt_enable(); |
| @@ -908,8 +900,10 @@ void symbol_put_addr(void *addr) | |||
| 908 | if (core_kernel_text((unsigned long)addr)) | 900 | if (core_kernel_text((unsigned long)addr)) |
| 909 | return; | 901 | return; |
| 910 | 902 | ||
| 911 | if (!(modaddr = module_text_address((unsigned long)addr))) | 903 | /* module_text_address is safe here: we're supposed to have reference |
| 912 | BUG(); | 904 | * to module from symbol_get, so it can't go away. */ |
| 905 | modaddr = __module_text_address((unsigned long)addr); | ||
| 906 | BUG_ON(!modaddr); | ||
| 913 | module_put(modaddr); | 907 | module_put(modaddr); |
| 914 | } | 908 | } |
| 915 | EXPORT_SYMBOL_GPL(symbol_put_addr); | 909 | EXPORT_SYMBOL_GPL(symbol_put_addr); |
| @@ -949,10 +943,11 @@ static inline void module_unload_free(struct module *mod) | |||
| 949 | { | 943 | { |
| 950 | } | 944 | } |
| 951 | 945 | ||
| 952 | static inline int use_module(struct module *a, struct module *b) | 946 | int use_module(struct module *a, struct module *b) |
| 953 | { | 947 | { |
| 954 | return strong_try_module_get(b) == 0; | 948 | return strong_try_module_get(b) == 0; |
| 955 | } | 949 | } |
| 950 | EXPORT_SYMBOL_GPL(use_module); | ||
| 956 | 951 | ||
| 957 | static inline void module_unload_init(struct module *mod) | 952 | static inline void module_unl |
