diff options
-rw-r--r-- | include/linux/module.h | 20 | ||||
-rw-r--r-- | kernel/module.c | 76 |
2 files changed, 73 insertions, 23 deletions
diff --git a/include/linux/module.h b/include/linux/module.h index 08e5e75d6122..fd1241e1416f 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -365,7 +365,9 @@ static inline int module_is_live(struct module *mod) | |||
365 | /* Is this address in a module? (second is with no locks, for oops) */ | 365 | /* Is this address in a module? (second is with no locks, for oops) */ |
366 | struct module *module_text_address(unsigned long addr); | 366 | struct module *module_text_address(unsigned long addr); |
367 | struct module *__module_text_address(unsigned long addr); | 367 | struct module *__module_text_address(unsigned long addr); |
368 | int is_module_address(unsigned long addr); | 368 | struct module *__module_address(unsigned long addr); |
369 | bool is_module_address(unsigned long addr); | ||
370 | bool is_module_text_address(unsigned long addr); | ||
369 | 371 | ||
370 | static inline int within_module_core(unsigned long addr, struct module *mod) | 372 | static inline int within_module_core(unsigned long addr, struct module *mod) |
371 | { | 373 | { |
@@ -494,21 +496,29 @@ search_module_extables(unsigned long addr) | |||
494 | return NULL; | 496 | return NULL; |
495 | } | 497 | } |
496 | 498 | ||
497 | /* Is this address in a module? */ | ||
498 | static inline struct module *module_text_address(unsigned long addr) | 499 | static inline struct module *module_text_address(unsigned long addr) |
499 | { | 500 | { |
500 | return NULL; | 501 | return NULL; |
501 | } | 502 | } |
502 | 503 | ||
503 | /* Is this address in a module? (don't take a lock, we're oopsing) */ | 504 | static inline struct module *__module_address(unsigned long addr) |
505 | { | ||
506 | return NULL; | ||
507 | } | ||
508 | |||
504 | static inline struct module *__module_text_address(unsigned long addr) | 509 | static inline struct module *__module_text_address(unsigned long addr) |
505 | { | 510 | { |
506 | return NULL; | 511 | return NULL; |
507 | } | 512 | } |
508 | 513 | ||
509 | static inline int is_module_address(unsigned long addr) | 514 | static inline bool is_module_address(unsigned long addr) |
510 | { | 515 | { |
511 | return 0; | 516 | return false; |
517 | } | ||
518 | |||
519 | static inline bool is_module_text_address(unsigned long addr) | ||
520 | { | ||
521 | return false; | ||
512 | } | 522 | } |
513 | 523 | ||
514 | /* Get/put a kernel symbol (calls should be symmetric) */ | 524 | /* Get/put a kernel symbol (calls should be symmetric) */ |
diff --git a/kernel/module.c b/kernel/module.c index 2f0fddf3c114..bd15a94f91c1 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -76,7 +76,7 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq); | |||
76 | 76 | ||
77 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 77 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
78 | 78 | ||
79 | /* Bounds of module allocation, for speeding __module_text_address */ | 79 | /* Bounds of module allocation, for speeding __module_address */ |
80 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; | 80 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
81 | 81 | ||
82 | int register_module_notifier(struct notifier_block * nb) | 82 | int register_module_notifier(struct notifier_block * nb) |
@@ -2745,29 +2745,31 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) | |||
2745 | } | 2745 | } |
2746 | 2746 | ||
2747 | /* | 2747 | /* |
2748 | * Is this a valid module address? | 2748 | * is_module_address - is this address inside a module? |
2749 | * @addr: the address to check. | ||
2750 | * | ||
2751 | * See is_module_text_address() if you simply want to see if the address | ||
2752 | * is code (not data). | ||
2749 | */ | 2753 | */ |
2750 | int is_module_address(unsigned long addr) | 2754 | bool is_module_address(unsigned long addr) |
2751 | { | 2755 | { |
2752 | struct module *mod; | 2756 | bool ret; |
2753 | 2757 | ||
2754 | preempt_disable(); | 2758 | preempt_disable(); |
2755 | 2759 | ret = __module_address(addr) != NULL; | |
2756 | list_for_each_entry_rcu(mod, &modules, list) { | ||
2757 | if (within_module_core(addr, mod)) { | ||
2758 | preempt_enable(); | ||
2759 | return 1; | ||
2760 | } | ||
2761 | } | ||
2762 | |||
2763 | preempt_enable(); | 2760 | preempt_enable(); |
2764 | 2761 | ||
2765 | return 0; | 2762 | return ret; |
2766 | } | 2763 | } |
2767 | 2764 | ||
2768 | 2765 | /* | |
2769 | /* Is this a valid kernel address? */ | 2766 | * __module_address - get the module which contains an address. |
2770 | __notrace_funcgraph struct module *__module_text_address(unsigned long addr) | 2767 | * @addr: the address. |
2768 | * | ||
2769 | * Must be called with preempt disabled or module mutex held so that | ||
2770 | * module doesn't get freed during this. | ||
2771 | */ | ||
2772 | __notrace_funcgraph struct module *__module_address(unsigned long addr) | ||
2771 | { | 2773 | { |
2772 | struct module *mod; | 2774 | struct module *mod; |
2773 | 2775 | ||
@@ -2775,12 +2777,50 @@ __notrace_funcgraph struct module *__module_text_address(unsigned long addr) | |||
2775 | return NULL; | 2777 | return NULL; |
2776 | 2778 | ||
2777 | list_for_each_entry_rcu(mod, &modules, list) | 2779 | list_for_each_entry_rcu(mod, &modules, list) |
2778 | if (within(addr, mod->module_init, mod->init_text_size) | 2780 | if (within_module_core(addr, mod) |
2779 | || within(addr, mod->module_core, mod->core_text_size)) | 2781 | || within_module_init(addr, mod)) |
2780 | return mod; | 2782 | return mod; |
2781 | return NULL; | 2783 | return NULL; |
2782 | } | 2784 | } |
2783 | 2785 | ||
2786 | /* | ||
2787 | * is_module_text_address - is this address inside module code? | ||
2788 | * @addr: the address to check. | ||
2789 | * | ||
2790 | * See is_module_address() if you simply want to see if the address is | ||
2791 | * anywhere in a module. See kernel_text_address() for testing if an | ||
2792 | * address corresponds to kernel or module code. | ||
2793 | */ | ||
2794 | bool is_module_text_address(unsigned long addr) | ||
2795 | { | ||
2796 | bool ret; | ||
2797 | |||
2798 | preempt_disable(); | ||
2799 | ret = __module_text_address(addr) != NULL; | ||
2800 | preempt_enable(); | ||
2801 | |||
2802 | return ret; | ||
2803 | } | ||
2804 | |||
2805 | /* | ||
2806 | * __module_text_address - get the module whose code contains an address. | ||
2807 | * @addr: the address. | ||
2808 | * | ||
2809 | * Must be called with preempt disabled or module mutex held so that | ||
2810 | * module doesn't get freed during this. | ||
2811 | */ | ||
2812 | struct module *__module_text_address(unsigned long addr) | ||
2813 | { | ||
2814 | struct module *mod = __module_address(addr); | ||
2815 | if (mod) { | ||
2816 | /* Make sure it's within the text section. */ | ||
2817 | if (!within(addr, mod->module_init, mod->init_text_size) | ||
2818 | && !within(addr, mod->module_core, mod->core_text_size)) | ||
2819 | mod = NULL; | ||
2820 | } | ||
2821 | return mod; | ||
2822 | } | ||
2823 | |||
2784 | struct module *module_text_address(unsigned long addr) | 2824 | struct module *module_text_address(unsigned long addr) |
2785 | { | 2825 | { |
2786 | struct module *mod; | 2826 | struct module *mod; |