diff options
| author | Matthias Maennich <maennich@google.com> | 2019-09-06 06:32:27 -0400 |
|---|---|---|
| committer | Jessica Yu <jeyu@kernel.org> | 2019-09-10 04:30:17 -0400 |
| commit | 8651ec01daedad26290f76beeb4736f9d2da4b87 (patch) | |
| tree | addd8a0c1a51b5000c96218a1b349fde30ff4f29 /include/linux | |
| parent | ed13fc33f763035a7c290f11c7111877c3a5daab (diff) | |
module: add support for symbol namespaces.
The EXPORT_SYMBOL_NS() and EXPORT_SYMBOL_NS_GPL() macros can be used to
export a symbol to a specific namespace. There are no _GPL_FUTURE and
_UNUSED variants because these are currently unused, and I'm not sure
they are necessary.
I didn't add EXPORT_SYMBOL_NS() for ASM exports; this patch sets the
namespace of ASM exports to NULL by default. In case of relative
references, it will be relocatable to NULL. If there's a need, this
should be pretty easy to add.
A module that wants to use a symbol exported to a namespace must add a
MODULE_IMPORT_NS() statement to their module code; otherwise, modpost
will complain when building the module, and the kernel module loader
will emit an error and fail when loading the module.
MODULE_IMPORT_NS() adds a modinfo tag 'import_ns' to the module. That
tag can be observed by the modinfo command, modpost and kernel/module.c
at the time of loading the module.
The ELF symbols are renamed to include the namespace with an asm label;
for example, symbol 'usb_stor_suspend' in namespace USB_STORAGE becomes
'usb_stor_suspend.USB_STORAGE'. This allows modpost to do namespace
checking, without having to go through all the effort of parsing ELF and
relocation records just to get to the struct kernel_symbols.
On x86_64 I saw no difference in binary size (compression), but at
runtime this will require a word of memory per export to hold the
namespace. An alternative could be to store namespaced symbols in their
own section and use a separate 'struct namespaced_kernel_symbol' for
that section, at the cost of making the module loader more complex.
Co-developed-by: Martijn Coenen <maco@android.com>
Signed-off-by: Martijn Coenen <maco@android.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/export.h | 91 | ||||
| -rw-r--r-- | include/linux/module.h | 2 |
2 files changed, 77 insertions, 16 deletions
diff --git a/include/linux/export.h b/include/linux/export.h index 28a4d2150689..d59461e71478 100644 --- a/include/linux/export.h +++ b/include/linux/export.h | |||
| @@ -20,6 +20,8 @@ extern struct module __this_module; | |||
| 20 | 20 | ||
| 21 | #ifdef CONFIG_MODULES | 21 | #ifdef CONFIG_MODULES |
| 22 | 22 | ||
| 23 | #define NS_SEPARATOR "." | ||
| 24 | |||
| 23 | #if defined(__KERNEL__) && !defined(__GENKSYMS__) | 25 | #if defined(__KERNEL__) && !defined(__GENKSYMS__) |
| 24 | #ifdef CONFIG_MODVERSIONS | 26 | #ifdef CONFIG_MODVERSIONS |
| 25 | /* Mark the CRC weak since genksyms apparently decides not to | 27 | /* Mark the CRC weak since genksyms apparently decides not to |
| @@ -29,13 +31,13 @@ extern struct module __this_module; | |||
| 29 | asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ | 31 | asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ |
| 30 | " .weak __crc_" #sym " \n" \ | 32 | " .weak __crc_" #sym " \n" \ |
| 31 | " .long __crc_" #sym " - . \n" \ | 33 | " .long __crc_" #sym " - . \n" \ |
| 32 | " .previous \n"); | 34 | " .previous \n") |
| 33 | #else | 35 | #else |
| 34 | #define __CRC_SYMBOL(sym, sec) \ | 36 | #define __CRC_SYMBOL(sym, sec) \ |
| 35 | asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ | 37 | asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ |
| 36 | " .weak __crc_" #sym " \n" \ | 38 | " .weak __crc_" #sym " \n" \ |
| 37 | " .long __crc_" #sym " \n" \ | 39 | " .long __crc_" #sym " \n" \ |
| 38 | " .previous \n"); | 40 | " .previous \n") |
| 39 | #endif | 41 | #endif |
| 40 | #else | 42 | #else |
| 41 | #define __CRC_SYMBOL(sym, sec) | 43 | #define __CRC_SYMBOL(sym, sec) |
| @@ -49,6 +51,16 @@ extern struct module __this_module; | |||
| 49 | * absolute relocations that require runtime processing on relocatable | 51 | * absolute relocations that require runtime processing on relocatable |
| 50 | * kernels. | 52 | * kernels. |
| 51 | */ | 53 | */ |
| 54 | #define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ | ||
| 55 | __ADDRESSABLE(sym) \ | ||
| 56 | asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ | ||
| 57 | " .balign 4 \n" \ | ||
| 58 | "__ksymtab_" #sym NS_SEPARATOR #ns ": \n" \ | ||
| 59 | " .long " #sym "- . \n" \ | ||
| 60 | " .long __kstrtab_" #sym "- . \n" \ | ||
| 61 | " .long __kstrtab_ns_" #sym "- . \n" \ | ||
| 62 | " .previous \n") | ||
| 63 | |||
| 52 | #define __KSYMTAB_ENTRY(sym, sec) \ | 64 | #define __KSYMTAB_ENTRY(sym, sec) \ |
| 53 | __ADDRESSABLE(sym) \ | 65 | __ADDRESSABLE(sym) \ |
| 54 | asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ | 66 | asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ |
| @@ -56,32 +68,53 @@ extern struct module __this_module; | |||
| 56 | "__ksymtab_" #sym ": \n" \ | 68 | "__ksymtab_" #sym ": \n" \ |
| 57 | " .long " #sym "- . \n" \ | 69 | " .long " #sym "- . \n" \ |
| 58 | " .long __kstrtab_" #sym "- . \n" \ | 70 | " .long __kstrtab_" #sym "- . \n" \ |
| 71 | " .long 0 - . \n" \ | ||
| 59 | " .previous \n") | 72 | " .previous \n") |
| 60 | 73 | ||
| 61 | struct kernel_symbol { | 74 | struct kernel_symbol { |
| 62 | int value_offset; | 75 | int value_offset; |
| 63 | int name_offset; | 76 | int name_offset; |
| 77 | int namespace_offset; | ||
| 64 | }; | 78 | }; |
| 65 | #else | 79 | #else |
| 80 | #define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ | ||
| 81 | static const struct kernel_symbol __ksymtab_##sym##__##ns \ | ||
| 82 | asm("__ksymtab_" #sym NS_SEPARATOR #ns) \ | ||
| 83 | __attribute__((section("___ksymtab" sec "+" #sym), used)) \ | ||
| 84 | __aligned(sizeof(void *)) \ | ||
| 85 | = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym } | ||
| 86 | |||
| 66 | #define __KSYMTAB_ENTRY(sym, sec) \ | 87 | #define __KSYMTAB_ENTRY(sym, sec) \ |
| 67 | static const struct kernel_symbol __ksymtab_##sym \ | 88 | static const struct kernel_symbol __ksymtab_##sym \ |
| 89 | asm("__ksymtab_" #sym) \ | ||
| 68 | __attribute__((section("___ksymtab" sec "+" #sym), used)) \ | 90 | __attribute__((section("___ksymtab" sec "+" #sym), used)) \ |
| 69 | __aligned(sizeof(void *)) \ | 91 | __aligned(sizeof(void *)) \ |
| 70 | = { (unsigned long)&sym, __kstrtab_##sym } | 92 | = { (unsigned long)&sym, __kstrtab_##sym, NULL } |
| 71 | 93 | ||
| 72 | struct kernel_symbol { | 94 | struct kernel_symbol { |
| 73 | unsigned long value; | 95 | unsigned long value; |
| 74 | const char *name; | 96 | const char *name; |
| 97 | const char *namespace; | ||
| 75 | }; | 98 | }; |
| 76 | #endif | 99 | #endif |
| 77 | 100 | ||
| 78 | /* For every exported symbol, place a struct in the __ksymtab section */ | 101 | #define ___export_symbol_common(sym, sec) \ |
| 79 | #define ___EXPORT_SYMBOL(sym, sec) \ | ||
| 80 | extern typeof(sym) sym; \ | 102 | extern typeof(sym) sym; \ |
| 81 | __CRC_SYMBOL(sym, sec) \ | 103 | __CRC_SYMBOL(sym, sec); \ |
| 82 | static const char __kstrtab_##sym[] \ | 104 | static const char __kstrtab_##sym[] \ |
| 83 | __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ | 105 | __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ |
| 84 | = #sym; \ | 106 | = #sym \ |
| 107 | |||
| 108 | /* For every exported symbol, place a struct in the __ksymtab section */ | ||
| 109 | #define ___EXPORT_SYMBOL_NS(sym, sec, ns) \ | ||
| 110 | ___export_symbol_common(sym, sec); \ | ||
| 111 | static const char __kstrtab_ns_##sym[] \ | ||
| 112 | __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ | ||
| 113 | = #ns; \ | ||
| 114 | __KSYMTAB_ENTRY_NS(sym, sec, ns) | ||
| 115 | |||
| 116 | #define ___EXPORT_SYMBOL(sym, sec) \ | ||
| 117 | ___export_symbol_common(sym, sec); \ | ||
| 85 | __KSYMTAB_ENTRY(sym, sec) | 118 | __KSYMTAB_ENTRY(sym, sec) |
| 86 | 119 | ||
| 87 | #if defined(__DISABLE_EXPORTS) | 120 | #if defined(__DISABLE_EXPORTS) |
| @@ -91,6 +124,7 @@ struct kernel_symbol { | |||
| 91 | * be reused in other execution contexts such as the UEFI stub or the | 124 | * be reused in other execution contexts such as the UEFI stub or the |
| 92 | * decompressor. | 125 | * decompressor. |
| 93 | */ | 126 | */ |
| 127 | #define __EXPORT_SYMBOL_NS(sym, sec, ns) | ||
| 94 | #define __EXPORT_SYMBOL(sym, sec) | 128 | #define __EXPORT_SYMBOL(sym, sec) |
| 95 | 129 | ||
| 96 | #elif defined(CONFIG_TRIM_UNUSED_KSYMS) | 130 | #elif defined(CONFIG_TRIM_UNUSED_KSYMS) |
| @@ -117,18 +151,26 @@ struct kernel_symbol { | |||
| 117 | #define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec) | 151 | #define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec) |
| 118 | #define __cond_export_sym_0(sym, sec) /* nothing */ | 152 | #define __cond_export_sym_0(sym, sec) /* nothing */ |
| 119 | 153 | ||
| 154 | #define __EXPORT_SYMBOL_NS(sym, sec, ns) \ | ||
| 155 | __ksym_marker(sym); \ | ||
| 156 | __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) | ||
| 157 | #define __cond_export_ns_sym(sym, sec, ns, conf) \ | ||
| 158 | ___cond_export_ns_sym(sym, sec, ns, conf) | ||
| 159 | #define ___cond_export_ns_sym(sym, sec, ns, enabled) \ | ||
| 160 | __cond_export_ns_sym_##enabled(sym, sec, ns) | ||
| 161 | #define __cond_export_ns_sym_1(sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns) | ||
| 162 | #define __cond_export_ns_sym_0(sym, sec, ns) /* nothing */ | ||
| 163 | |||
| 120 | #else | 164 | #else |
| 165 | #define __EXPORT_SYMBOL_NS ___EXPORT_SYMBOL_NS | ||
| 121 | #define __EXPORT_SYMBOL ___EXPORT_SYMBOL | 166 | #define __EXPORT_SYMBOL ___EXPORT_SYMBOL |
| 122 | #endif | 167 | #endif |
| 123 | 168 | ||
| 124 | #define EXPORT_SYMBOL(sym) \ | 169 | #define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") |
| 125 | __EXPORT_SYMBOL(sym, "") | 170 | #define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") |
| 126 | 171 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) __EXPORT_SYMBOL(sym, "_gpl_future") | |
| 127 | #define EXPORT_SYMBOL_GPL(sym) \ | 172 | #define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns) |
| 128 | __EXPORT_SYMBOL(sym, "_gpl") | 173 | #define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns) |
| 129 | |||
| 130 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) \ | ||
| 131 | __EXPORT_SYMBOL(sym, "_gpl_future") | ||
| 132 | 174 | ||
| 133 | #ifdef CONFIG_UNUSED_SYMBOLS | 175 | #ifdef CONFIG_UNUSED_SYMBOLS |
| 134 | #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") | 176 | #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") |
| @@ -138,11 +180,28 @@ struct kernel_symbol { | |||
| 138 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | 180 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) |
| 139 | #endif | 181 | #endif |
| 140 | 182 | ||
| 141 | #endif /* __GENKSYMS__ */ | 183 | #endif /* __KERNEL__ && !__GENKSYMS__ */ |
| 184 | |||
| 185 | #if defined(__GENKSYMS__) | ||
| 186 | /* | ||
| 187 | * When we're running genksyms, ignore the namespace and make the _NS | ||
| 188 | * variants look like the normal ones. There are two reasons for this: | ||
| 189 | * 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro | ||
| 190 | * argument is itself not expanded because it's always tokenized or | ||
| 191 | * concatenated; but when running genksyms, a blank definition of the | ||
| 192 | * macro does allow the argument to be expanded; if a namespace | ||
| 193 | * happens to collide with a #define, this can cause issues. | ||
| 194 | * 2) There's no need to modify genksyms to deal with the _NS variants | ||
| 195 | */ | ||
| 196 | #define EXPORT_SYMBOL_NS(sym, ns) EXPORT_SYMBOL(sym) | ||
| 197 | #define EXPORT_SYMBOL_NS_GPL(sym, ns) EXPORT_SYMBOL_GPL(sym) | ||
| 198 | #endif | ||
| 142 | 199 | ||
| 143 | #else /* !CONFIG_MODULES... */ | 200 | #else /* !CONFIG_MODULES... */ |
| 144 | 201 | ||
| 145 | #define EXPORT_SYMBOL(sym) | 202 | #define EXPORT_SYMBOL(sym) |
| 203 | #define EXPORT_SYMBOL_NS(sym, ns) | ||
| 204 | #define EXPORT_SYMBOL_NS_GPL(sym, ns) | ||
| 146 | #define EXPORT_SYMBOL_GPL(sym) | 205 | #define EXPORT_SYMBOL_GPL(sym) |
| 147 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) | 206 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) |
| 148 | #define EXPORT_UNUSED_SYMBOL(sym) | 207 | #define EXPORT_UNUSED_SYMBOL(sym) |
diff --git a/include/linux/module.h b/include/linux/module.h index 1455812dd325..b3611e749f72 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
| @@ -280,6 +280,8 @@ struct notifier_block; | |||
| 280 | 280 | ||
| 281 | #ifdef CONFIG_MODULES | 281 | #ifdef CONFIG_MODULES |
| 282 | 282 | ||
| 283 | #define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, #ns) | ||
| 284 | |||
| 283 | extern int modules_disabled; /* for sysctl */ | 285 | extern int modules_disabled; /* for sysctl */ |
| 284 | /* Get/put a kernel symbol (calls must be symmetric) */ | 286 | /* Get/put a kernel symbol (calls must be symmetric) */ |
| 285 | void *__symbol_get(const char *symbol); | 287 | void *__symbol_get(const char *symbol); |
