Commit e610499e2656e61975affd0af56b26eb73964c84
1 parent
414fd31b25
Exists in
master
and in
20 other branches
module: __module_address
Impact: New API, cleanup ksplice wants to know the bounds of a module, not just the module text. It makes sense to have __module_address. We then implement is_module_address and __module_text_address in terms of this (and change is_module_text_address() to bool while we're at it). Also, add proper kerneldoc for them all. Cc: Anders Kaseorg <andersk@mit.edu> Cc: Jeff Arnold <jbarnold@mit.edu> Cc: Tim Abbott <tabbott@mit.edu> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Showing 2 changed files with 73 additions and 23 deletions Side-by-side Diff
include/linux/module.h
... | ... | @@ -365,7 +365,9 @@ |
365 | 365 | /* Is this address in a module? (second is with no locks, for oops) */ |
366 | 366 | struct module *module_text_address(unsigned long addr); |
367 | 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 | 372 | static inline int within_module_core(unsigned long addr, struct module *mod) |
371 | 373 | { |
372 | 374 | |
373 | 375 | |
374 | 376 | |
... | ... | @@ -494,21 +496,29 @@ |
494 | 496 | return NULL; |
495 | 497 | } |
496 | 498 | |
497 | -/* Is this address in a module? */ | |
498 | 499 | static inline struct module *module_text_address(unsigned long addr) |
499 | 500 | { |
500 | 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 | 509 | static inline struct module *__module_text_address(unsigned long addr) |
505 | 510 | { |
506 | 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 | 524 | /* Get/put a kernel symbol (calls should be symmetric) */ |
kernel/module.c
... | ... | @@ -76,7 +76,7 @@ |
76 | 76 | |
77 | 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 | 80 | static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
81 | 81 | |
82 | 82 | int register_module_notifier(struct notifier_block * nb) |
83 | 83 | |
84 | 84 | |
85 | 85 | |
86 | 86 | |
87 | 87 | |
... | ... | @@ -2745,29 +2745,31 @@ |
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 | 2758 | preempt_disable(); |
2755 | - | |
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 | - | |
2759 | + ret = __module_address(addr) != NULL; | |
2763 | 2760 | preempt_enable(); |
2764 | 2761 | |
2765 | - return 0; | |
2762 | + return ret; | |
2766 | 2763 | } |
2767 | 2764 | |
2768 | - | |
2769 | -/* Is this a valid kernel address? */ | |
2770 | -__notrace_funcgraph struct module *__module_text_address(unsigned long addr) | |
2765 | +/* | |
2766 | + * __module_address - get the module which contains an address. | |
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 | 2774 | struct module *mod; |
2773 | 2775 | |
2774 | 2776 | |
... | ... | @@ -2775,10 +2777,48 @@ |
2775 | 2777 | return NULL; |
2776 | 2778 | |
2777 | 2779 | list_for_each_entry_rcu(mod, &modules, list) |
2778 | - if (within(addr, mod->module_init, mod->init_text_size) | |
2779 | - || within(addr, mod->module_core, mod->core_text_size)) | |
2780 | + if (within_module_core(addr, mod) | |
2781 | + || within_module_init(addr, mod)) | |
2780 | 2782 | return mod; |
2781 | 2783 | return NULL; |
2784 | +} | |
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; | |
2782 | 2822 | } |
2783 | 2823 | |
2784 | 2824 | struct module *module_text_address(unsigned long addr) |