diff options
-rw-r--r-- | include/linux/module.h | 28 | ||||
-rw-r--r-- | kernel/module.c | 43 |
2 files changed, 47 insertions, 24 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index c3d3fc4ffb18..d246da0b0f8c 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -354,6 +354,8 @@ struct module | |||
354 | #define MODULE_ARCH_INIT {} | 354 | #define MODULE_ARCH_INIT {} |
355 | #endif | 355 | #endif |
356 | 356 | ||
357 | extern struct mutex module_mutex; | ||
358 | |||
357 | /* FIXME: It'd be nice to isolate modules during init, too, so they | 359 | /* FIXME: It'd be nice to isolate modules during init, too, so they |
358 | aren't used before they (may) fail. But presently too much code | 360 | aren't used before they (may) fail. But presently too much code |
359 | (IDE & SCSI) require entry into the module during init.*/ | 361 | (IDE & SCSI) require entry into the module during init.*/ |
@@ -379,6 +381,31 @@ static inline int within_module_init(unsigned long addr, struct module *mod) | |||
379 | addr < (unsigned long)mod->module_init + mod->init_size; | 381 | addr < (unsigned long)mod->module_init + mod->init_size; |
380 | } | 382 | } |
381 | 383 | ||
384 | /* Search for module by name: must hold module_mutex. */ | ||
385 | struct module *find_module(const char *name); | ||
386 | |||
387 | struct symsearch { | ||
388 | const struct kernel_symbol *start, *stop; | ||
389 | const unsigned long *crcs; | ||
390 | enum { | ||
391 | NOT_GPL_ONLY, | ||
392 | GPL_ONLY, | ||
393 | WILL_BE_GPL_ONLY, | ||
394 | } licence; | ||
395 | bool unused; | ||
396 | }; | ||
397 | |||
398 | /* Search for an exported symbol by name. */ | ||
399 | const struct kernel_symbol *find_symbol(const char *name, | ||
400 | struct module **owner, | ||
401 | const unsigned long **crc, | ||
402 | bool gplok, | ||
403 | bool warn); | ||
404 | |||
405 | /* Walk the exported symbol table */ | ||
406 | bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, | ||
407 | unsigned int symnum, void *data), void *data); | ||
408 | |||
382 | /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if | 409 | /* Returns 0 and fills in value, defined and namebuf, or -ERANGE if |
383 | symnum out of range. */ | 410 | symnum out of range. */ |
384 | int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | 411 | int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, |
@@ -452,6 +479,7 @@ static inline void __module_get(struct module *module) | |||
452 | #define symbol_put_addr(p) do { } while(0) | 479 | #define symbol_put_addr(p) do { } while(0) |
453 | 480 | ||
454 | #endif /* CONFIG_MODULE_UNLOAD */ | 481 | #endif /* CONFIG_MODULE_UNLOAD */ |
482 | int use_module(struct module *a, struct module *b); | ||
455 | 483 | ||
456 | /* This is a #define so the string doesn't get put in every .o file */ | 484 | /* This is a #define so the string doesn't get put in every .o file */ |
457 | #define module_name(mod) \ | 485 | #define module_name(mod) \ |
diff --git a/kernel/module.c b/kernel/module.c index dd4389be9152..5fd00766a4dc 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? */ |
@@ -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 */ |
@@ -330,11 +319,11 @@ static bool find_symbol_in_section(const struct symsearch *syms, | |||
330 | 319 | ||
331 | /* Find a symbol and return it, along with, (optional) crc and | 320 | /* Find a symbol and return it, along with, (optional) crc and |
332 | * (optional) module which owns it */ | 321 | * (optional) module which owns it */ |
333 | static const struct kernel_symbol *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 | ||
@@ -353,9 +342,10 @@ static const struct kernel_symbol *find_symbol(const char *name, | |||
353 | DEBUGP("Failed to find symbol %s\n", name); | 342 | DEBUGP("Failed to find symbol %s\n", name); |
354 | return NULL; | 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) |
@@ -951,10 +943,11 @@ static inline void module_unload_free(struct module *mod) | |||
951 | { | 943 | { |
952 | } | 944 | } |
953 | 945 | ||
954 | static inline int use_module(struct module *a, struct module *b) | 946 | int use_module(struct module *a, struct module *b) |
955 | { | 947 | { |
956 | return strong_try_module_get(b) == 0; | 948 | return strong_try_module_get(b) == 0; |
957 | } | 949 | } |
950 | EXPORT_SYMBOL_GPL(use_module); | ||
958 | 951 | ||
959 | static inline void module_unload_init(struct module *mod) | 952 | static inline void module_unload_init(struct module *mod) |
960 | { | 953 | { |
@@ -2803,6 +2796,7 @@ __notrace_funcgraph struct module *__module_address(unsigned long addr) | |||
2803 | return mod; | 2796 | return mod; |
2804 | return NULL; | 2797 | return NULL; |
2805 | } | 2798 | } |
2799 | EXPORT_SYMBOL_GPL(__module_address); | ||
2806 | 2800 | ||
2807 | /* | 2801 | /* |
2808 | * is_module_text_address - is this address inside module code? | 2802 | * is_module_text_address - is this address inside module code? |
@@ -2841,6 +2835,7 @@ struct module *__module_text_address(unsigned long addr) | |||
2841 | } | 2835 | } |
2842 | return mod; | 2836 | return mod; |
2843 | } | 2837 | } |
2838 | EXPORT_SYMBOL_GPL(__module_text_address); | ||
2844 | 2839 | ||
2845 | /* Don't grab lock, we're oopsing. */ | 2840 | /* Don't grab lock, we're oopsing. */ |
2846 | void print_modules(void) | 2841 | void print_modules(void) |