Symbol namespaces
Subsystems (49)
cover Symbol namespaces
As of Linux 4.17, there are more than 30000 exported symbols in the kernel. There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree use
When module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "SUBSYSTEM_DEBUG" namespace.
Martijn Coenen (6):
export: explicitly align struct kernel_symbol.
module: add support for symbol namespaces.
modpost: add support for checking symbol namespaces.
modpost: add support for generating namespace dependencies.
scripts: Coccinelle script for namespace dependencies.
RFC: USB: storage: move symbols into USB_STORAGE namespace.
Makefile | 11 +++ arch/m68k/include/asm/export.h | 1 - arch/x86/include/asm/Kbuild | 1 + arch/x86/include/asm/export.h | 5 -- drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + drivers/usb/storage/usb.c | 20 ++--- include/asm-generic/export.h | 2 +- include/linux/export.h | 84 ++++++++++++++----- include/linux/module.h | 13 +++ kernel/module.c | 79 ++++++++++++++++++ scripts/Makefile.modpost | 4 +- scripts/add_namespace.cocci | 19 +++++ scripts/mod/modpost.c | 120 ++++++++++++++++++++++++++-- scripts/mod/modpost.h | 9 +++ scripts/nsdeps | 41 ++++++++++ 28 files changed, 379 insertions(+), 44 deletions(-) delete mode 100644 arch/x86/include/asm/export.h create mode 100644 scripts/add_namespace.cocci create mode 100644 scripts/nsdeps
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 1/6 export: explicitly align struct kernel_symbol.
This change allows growing struct kernel_symbol without wasting bytes to alignment.
struct kernel_symbol was already implicitly being aligned to the word size, except on x86_64 and m68k, where it is aligned to 16 and 2 bytes, respectively.
As far as I can tell there is no requirement for aligning struct kernel_symbol to 16 bytes on x86_64, but gcc aligns structs to their size, and the linker aligns the custom __ksymtab sections to the largest data type contained within, so setting KSYM_ALIGN to 16 was necessary to stay consistent with the code generated for non-ASM EXPORT_SYMBOL(). Now that non-ASM EXPORT_SYMBOL() explicitly aligns to word size (8), KSYM_ALIGN is no longer necessary.
As for m68k, struct kernel_symbol is aligned to 2 bytes even though the structure itself is 8 bytes; using a 4-byte alignment shouldn't hurt.
I manually verified the output of the __ksymtab sections didn't change on x86, x86_64, arm, arm64 and m68k. As expected, the section contents didn't change, and the ELF section alignment only changed on x86_64 and m68k. Feedback from other archs more than welcome.
--- arch/m68k/include/asm/export.h | 1 - arch/x86/include/asm/Kbuild | 1 + arch/x86/include/asm/export.h | 5 ----- include/linux/export.h | 1 + 4 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 arch/x86/include/asm/export.h
arch/m68k/include/asm/export.h +0 -1
@@ -1,3 +1,2 @@ -#define KSYM_ALIGN 2#define KCRC_ALIGN 2#include <asm-generic/export.h>
arch/x86/include/asm/Kbuild +1 -0
@@ -8,5 +8,6 @@ generated-y += xen-hypercalls.h generic-y += dma-contiguous.h generic-y += early_ioremap.h +generic-y += export.h generic-y += mcs_spinlock.h generic-y += mm-arch-hooks.h
arch/x86/include/asm/export.h deleted +0 -5
@@ -1,5 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifdef CONFIG_64BIT -#define KSYM_ALIGN 16 -#endif -#include <asm-generic/export.h>
include/linux/export.h +1 -0
@@ -64,6 +64,7 @@ extern struct module __this_module; static const struct kernel_symbol __ksymtab_##sym \ __used \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((aligned(sizeof(void *)))) \ = { (unsigned long)&sym, __kstrtab_##sym }#if defined(__KSYM_DEPS__)
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 2/6 module: add support for symbol namespaces.
In reply to Martijn CoenenThe 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. 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 warn when 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 reloction 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.
--- include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)
include/asm-generic/export.h +1 -1
@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN __ksymtab_\name: - __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0 .previous .section __ksymtab_strings,"a" __kstrtab_\name:
include/linux/export.h +63 -20
139 lines not on this page · raw message
include/linux/module.h +13 -0
@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;
@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;
kernel/module.c +79 -0
115 lines not on this page · raw message
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
+++ Martijn Coenen [16/07/18 14:21 +0200]:
Quoted 286 lines
The
EXPORT_SYMBOL_NS()andEXPORT_SYMBOL_NS_GPL()macros can be used to export a symbol to a specific namespace. There are no_GPL_FUTUREand_UNUSEDvariants 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. 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 warn when loading the module.The ELF symbols are renamed to include the namespace with an asm label; for example, symbol '
usb_stor_suspend' in namespaceUSB_STORAGEbecomes 'usb_stor_suspend.USB_STORAGE'. This allows modpost to do namespace checking, without having to go through all the effort of parsing ELF and reloction records just to get to the structkernel_symbols.On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Signed-off-by Martijn Coenen <[email protected]>---
include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)include/asm-generic/export.h +0
-0@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN__ksymtab_\name:
include/asm-generic/export.h +1
-1- __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0.previous
.section __ksymtab_strings,"a"
__kstrtab_\name:include/linux/export.h +63
-20@@ -22,6 +22,11 @@ struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; +}; + +struct namespace_import { +const char *namespace; };#ifdef MODULE @@ -54,18 +59,28 @@ extern struct module __this_module;#define __CRC_SYMBOL (sym, sec)#endif +#define NS_SEPARATOR "." + +#define MODULE_IMPORT_NS (ns) \ + static const struct namespace_import __knsimport_##ns \ + asm("__knsimport_" #ns) \ + __attribute__((section("__knsimport"), used)) \ + = { #ns } +/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ + static const char __kstrtab_##sym##nspost[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ + static const struct kernel_symbol __ksymtab_##sym##nspost \ + asm("__ksymtab_" #sym nspost2) \ __used \ - __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((section("___ksymtab" sec "+" #sym #nspost))) \ + __attribute__((used)) \ __attribute__((aligned(sizeof(void *)))) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym##nspost, ns }#if defined(__KSYM_DEPS__)@@ -76,52 +91,80 @@ extern struct module __this_module;* system filters out from the preprocessor output (see ksym_dep_filter * in scripts/Kbuild.include). */ -#define __EXPORT_SYMBOL (sym, sec) === __KSYM_##sym === +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) === __KSYM_##sym ===#elif defined(CONFIG_TRIM_UNUSED_KSYMS )#include <generated/autoksyms.h> -#define __EXPORT_SYMBOL (sym, sec) \ - __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym (sym, sec, conf) \ - ___cond_export_sym(sym, sec, conf) -#define ___cond_export_sym (sym, sec, enabled) \ - __cond_export_sym_##enabled(sym, sec) -#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec) -#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ + __cond_export_sym(sym, sec, ns, nspost, nspost2, \ + __is_defined(__KSYM_##sym)) +#define __cond_export_sym (sym, sec, ns, nspost, nspost2, conf) \ + ___cond_export_sym(sym, sec, ns, nspost, nspost2, conf) +#define ___cond_export_sym (sym, sec, ns, nspost, nspost2, enabled) \ + __cond_export_sym_##enabled(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_1 (sym, sec, ns, nspost, nspost2) \ + ___EXPORT_SYMBOL(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_0 (sym, sec, ns, nspost, nspost2)/* nothing */ #else #define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif #define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym, "", NULL, ,)#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "_gpl", NULL, ,)#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") + __EXPORT_SYMBOL(sym, "_gpl_future", NULL, ,) + +#define EXPORT_SYMBOL_NS (sym, ns) \ + __EXPORT_SYMBOL(sym, "", #ns, __##ns, NS_SEPARATOR #ns) + +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + __EXPORT_SYMBOL(sym, "_gpl", #ns, __##ns, NS_SEPARATOR #ns)#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused", , ,) +#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl", , ,)#else #define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) \ + EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym) +#define MODULE_IMPORT_NS (ns)#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ include/linux/module.h +13
-0@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;kernel/module.c +47
-0@@ -1166,6 +1166,51 @@ static inline int module_unload_init(struct module *mod) }#endif /* CONFIG_MODULE_UNLOAD */ +static bool module_has_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (strcmp (ns_dep->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static int add_module_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +if (module_has_ns_dependency (mod, ns)) +return 0 ; + + ns_dep =kmalloc (sizeof (*ns_dep),GFP_ATOMIC ); +if (!ns_dep) +return -ENOMEM ; + + ns_dep->namespace = ns; + +list_add (&ns_dep->ns_dep, &mod->ns_dependencies); + +return 0 ; +} + +static bool module_imports_ns (struct module *mod,const char *ns) +{ +size_t i; + +if (!ns) +return true; + +for (i =0 ; i < mod->num_ns_imports; ++i) { +if (!strcmp (mod->ns_imports[i].namespace, ns)) +return true; + } + +return false; +} +static size_t module_flags_taint (struct module *mod,char *buf) {size_t l =0 ;@@ -1415,6 +1460,18 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } +/* +* We can't yet verify that the module actually imports this
kernel/module.c static const struct kernel_symbol *resolve_symbol(struct module *mod, · line 1474
Quoted 10 lines
kernel/module.c +10
-0+* namespace, because the imports themselves are only available +* after processing the symbol table and doing relocation; so +* instead just record the dependency and check later. +*/ +if (sym->namespace) { + err =add_module_ns_dependency (mod, sym->namespace); +if (err) + sym =ERR_PTR (err); + } +
First, thanks a lot for the patchset. This is definitely something that will help distros as well to declutter the exported symbol space and provide a more cleanly defined kernel interface.
Hm, I'm wondering if we could avoid all this extra module-ns-dependency checking work if we just put the import stuff as a modinfo tag, like have MODULE_IMPORT_NS() insert an "import:" tag like we already do for module parameters, author, license, aliases, etc. Then we'd have that information pretty much from the start of load_module() and we don't need to wait for relocations to be applied to __knsimport. Then you could do the namespace checking right at resolve_symbol() instead of going through the extra step of building a dependency list to be verified later.
Also, this would get rid of the extra __knsimport section, the extra ns_dependencies field in struct module, and all those helper functions that manage it. In addition, having the modinfo tag may potentially help with debugging as we have the namespace imports clearly listed if we don't have the source code for a module. We'd probably need to modify get_modinfo() to handle multiple import: tags though. Luis [1] had written some code a while ago to handle multiple (of the same) modinfo tags.
Thoughts on this?
Thanks,
Jessica
Quoted 56 lines
getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);kernel/module.c +22
-0@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future", sizeof(*mod->gpl_future_syms),@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { +pr_warn ("%s: module uses symbols from namespace %s," +" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool finished_loading (const char *name) {@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err <0 ) goto free_modinfo; +verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ Signature · 1 line
2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
Hi Jessica,
Quoted 3 lines · Jessica Yu
First, thanks a lot for the patchset. This is definitely something that will help distros as well to declutter the exported symbol space and provide a more cleanly defined kernel interface.
Thanks, that's good to hear!
Quoted 9 lines
Hm, I'm wondering if we could avoid all this extra module-ns-dependency checking work if we just put the import stuff as a modinfo tag, like have
MODULE_IMPORT_NS()insert an "import:" tag like we already do for module parameters, author, license, aliases, etc. Then we'd have that information pretty much from the start ofload_module()and we don't need to wait for relocations to be applied to__knsimport. Then you could do the namespace checking right atresolve_symbol()instead of going through the extra step of building a dependency list to be verified later.
I believe I did consider modinfo when I started with this a while back, but don't recall right now why I didn't decide to use it; perhaps it was the lack of support for multiple identical tags. Since both modpost and the module loader have access to them, I don't see why it wouldn't work, and indeed I suspect it would make the module loader a bit simpler. I'll rework this and see what it looks like.
Thanks,
Martijn
Quoted 80 lines
Also, this would get rid of the extra
__knsimportsection, the extrans_dependenciesfield in struct module, and all those helper functions that manage it. In addition, having the modinfo tag may potentially help with debugging as we have the namespace imports clearly listed if we don't have the source code for a module. We'd probably need to modifyget_modinfo()to handle multiple import: tags though. Luis [1] had written some code a while ago to handle multiple (of the same) modinfo tags.Thoughts on this?
Thanks,
Jessica
[1] https://lkml.kernel.org/r/[email protected]
Quoted 61 lines
getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);kernel/module.c +5
-0@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future",sizeof(*mod->gpl_future_syms),kernel/module.c +7
-0@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { + pr_warn("%s: module uses symbols from namespace%s,"
kernel/module.c +6
-0+" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool
finished_loading(const char *name)
{kernel/module.c +2
-0@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs, if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {kernel/module.c +2
-0@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, constchar __user *uargs, if (err < 0) goto free_modinfo; +verify_namespace_dependencies (mod ); +flush_module_icache (mod);/* Now copy in args */--
2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
+++ Martijn Coenen [20/07/18 09:54 +0200]:
Quoted 20 lines
Hi Jessica,
Quoted 3 lines · Jessica Yu
First, thanks a lot for the patchset. This is definitely something that will help distros as well to declutter the exported symbol space and provide a more cleanly defined kernel interface.
Thanks, that's good to hear!
Quoted 9 lines
Hm, I'm wondering if we could avoid all this extra module-ns-dependency checking work if we just put the import stuff as a modinfo tag, like have
MODULE_IMPORT_NS()insert an "import:" tag like we already do for module parameters, author, license, aliases, etc. Then we'd have that information pretty much from the start ofload_module()and we don't need to wait for relocations to be applied to__knsimport. Then you could do the namespace checking right atresolve_symbol()instead of going through the extra step of building a dependency list to be verified later.
Quoted 6 lines
I believe I did consider modinfo when I started with this a while back, but don't recall right now why I didn't decide to use it; perhaps it was the lack of support for multiple identical tags. Since both modpost and the module loader have access to them, I don't see why it wouldn't work, and indeed I suspect it would make the module loader a bit simpler. I'll rework this and see what it looks like.
Thanks. Also, it looks like we're currently just warning (in both modpost and on module load) if a module uses symbols from a namespace it doesn't import. Are you also planning to eventually introduce namespace enforcement? It'd be trivial to fail the module build in modpost as well as reject the module on load if it uses an exported symbol belonging to a namespace it doesn't import. Although, I'd go with the warnings for a development cycle or two, to gently introduce the change in API and let other subsystems as well as out-of-tree module developers catch up.
Jessica
Quoted 79 lines
Quoted 79 lines
Also, this would get rid of the extra
__knsimportsection, the extrans_dependenciesfield in struct module, and all those helper functions that manage it. In addition, having the modinfo tag may potentially help with debugging as we have the namespace imports clearly listed if we don't have the source code for a module. We'd probably need to modifyget_modinfo()to handle multiple import: tags though. Luis [1] had written some code a while ago to handle multiple (of the same) modinfo tags.Thoughts on this?
Thanks,
Jessica
[1] https://lkml.kernel.org/r/[email protected]
Quoted 61 lines
getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);kernel/module.c +5
-0@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future",sizeof(*mod->gpl_future_syms),kernel/module.c +7
-0@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { + pr_warn("%s: module uses symbols from namespace%s,"
kernel/module.c +6
-0+" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool
finished_loading(const char *name)
{kernel/module.c +2
-0@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs, if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {kernel/module.c +2
-0@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, constchar __user *uargs, if (err < 0) goto free_modinfo; +verify_namespace_dependencies (mod ); +flush_module_icache (mod);/* Now copy in args */--
2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
Quoted 4 lines · Jessica Yu
Thanks. Also, it looks like we're currently just warning (in both modpost and on module load) if a module uses symbols from a namespace it doesn't import. Are you also planning to eventually introduce namespace enforcement?
This is something I've definitely been thinking about, and was curious what others would think. My main concern with enforcement is that it will start failing to load out-of-tree modules that use newly namespaced symbols. On the other hand, I think those modules will need to be rebuilt anyway to be able to load, because the changes to struct kernel_symbol make them incompatible with the current kernel. That could be another reason for having these symbols in a special section (with its own struct namespaced_kernel_symbol); but on the other hand, it would make the module loader more complex just to facilitate out-of-tree drivers, and I'm not sure where the trade-off between those two falls.
Quoted 6 lines
It'd be trivial to fail the module build in
modpost as well as reject the module on load if it uses an exported symbol belonging to a namespace it doesn't import. Although, I'd go with the warnings for a development cycle or two, to gently introduce the change in API and let other subsystems as well as out-of-tree module developers catch up.
An approach like that makes sense to me. Another alternative would be to make it a CONFIG_ option, and let distros/etc. decide what they are comfortable with.
Thanks,
Martijn
Quoted 93 lines
Jessica
Quoted 87 lines
Quoted 87 lines
Also, this would get rid of the extra
__knsimportsection, the extrans_dependenciesfield in struct module, and all those helper functions that
manage it. In addition, having the modinfo tag may potentially help with debugging as we have the namespace imports clearly listed if we don't have
the source code for a module. We'd probably need to modifyget_modinfo()to
handle multiple import: tags though. Luis [1] had written some code a while
ago to handle multiple (of the same) modinfo tags.Thoughts on this?
Thanks,
Jessica
[1] https://lkml.kernel.org/r/[email protected]
Quoted 65 lines
getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);kernel/module.c +5
-0@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info,"__ksymtab_gpl_future",
sizeof(*mod->gpl_future_syms),kernel/module.c +7
-0@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { + pr_warn("%s: module uses symbols from namespace%s,"
kernel/module.c +6
-0+" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool
finished_loading(const char *name)
{(quoted diff) +0
-0@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info,const
char__user*uargs,if (err) goto free_module;kernel/module.c +2
-0+INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok; if (!mod->sig_ok) {(quoted diff) +0
-0@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info,const
char__user*uargs,if (err < 0) goto free_modinfo;kernel/module.c +2
-1+verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ --2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
+++ Martijn Coenen [20/07/18 17:42 +0200]:
Quoted 6 lines · Jessica Yu
Quoted 4 lines
Thanks. Also, it looks like we're currently just warning (in both modpost and on module load) if a module uses symbols from a namespace it doesn't import. Are you also planning to eventually introduce namespace enforcement?
Quoted 11 lines
This is something I've definitely been thinking about, and was curious what others would think. My main concern with enforcement is that it will start failing to load out-of-tree modules that use newly namespaced symbols. On the other hand, I think those modules will need to be rebuilt anyway to be able to load, because the changes to struct
kernel_symbolmake them incompatible with the current kernel. That could be another reason for having these symbols in a special section (with its own structnamespaced_kernel_symbol); but on the other hand, it would make the module loader more complex just to facilitate out-of-tree drivers, and I'm not sure where the trade-off between those two falls.
IMO I don't think we should bend over backwards to accommodate out-of-tree modules - modifying the module loader to recognize even more special sections to accommodate these OOT modules would be where we'd draw the line I think.
Quoted 10 lines
Quoted 6 lines
It'd be trivial to fail the module build in
modpost as well as reject the module on load if it uses an exported symbol belonging to a namespace it doesn't import. Although, I'd go with the warnings for a development cycle or two, to gently introduce the change in API and let other subsystems as well as out-of-tree module developers catch up.An approach like that makes sense to me. Another alternative would be to make it a
CONFIG_option, and let distros/etc. decide what they are comfortable with.
I think going forward I would prefer to have export namespaces to be a normal and regular part of kernel API (as in, we shouldn't require a new option for it), and that the warnings for 1-2 cycles are courteous enough - but anyone with stronger opinions about this should speak up.
Thanks,
Jessica
Re: [PATCH 2/6] module: add support for symbol namespaces.
Quoted 4 lines · Jessica Yu
IMO I don't think we should bend over backwards to accommodate out-of-tree modules - modifying the module loader to recognize even more special sections to accommodate these OOT modules would be where we'd draw the line I think.
I agree with you, I really don't like making the module loader more complex (which is why I didn't opt to create separate sections in the first place), and in the end this change will in some ways benefit out-of-tree drivers too, even though it will be a bit painful now.
Quoted 4 lines
I think going forward I would prefer to have export namespaces to be a normal and regular part of kernel API (as in, we shouldn't require a new option for it), and that the warnings for 1-2 cycles are courteous enough - but anyone with stronger opinions about this should speak up.
That aligns with how I think about this; if we want this to be a standard thing in the kernel, we should at some point enforce it, because it's pretty easy to ignore the warning. The good thing is that it's not a big on/off switch, but subsystem maintainers can just introduce namespaces when it makes sense.
Thanks,
Martijn
Quoted 4 lines
Thanks,
Jessica
Re: [PATCH 2/6] module: add support for symbol namespaces.
In reply to Martijn CoenenI did find an issue with my approach:
Quoted 5 lines · Martijn Coenen
The ELF symbols are renamed to include the namespace with an asm label; for example, symbol '
usb_stor_suspend' in namespaceUSB_STORAGEbecomes 'usb_stor_suspend.USB_STORAGE'. This allows modpost to do namespace checking, without having to go through all the effort of parsing ELF and reloction records just to get to the structkernel_symbols.
depmod doesn't like this: if namespaced symbols are built-in to the kernel, they will appear as 'symbol.NS' in the symbol table, whereas modules using those symbols just depend on 'symbol'. This will cause depmod to warn about unknown symbols. I didn't find this previously because all the exports/imports I tested were done from modules themselves.
One way to deal with it is to change depmod, but it looks like it hasn't been changed in ages, and it would also introduce a dependency on userspaces to update it to avoid these warnings. So, we'd have to encode the symbol namespace information in another way for modpost to use. I could just write a separate post-processing tool (much like genksyms), or perhaps encode the information in a discardable section. Any other suggestions welcome.
Thanks,
Martijn
Quoted 333 lines
On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Signed-off-by Martijn Coenen <[email protected]>--- include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)include/asm-generic/export.h +1
-1@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN __ksymtab_\name: - __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0 .previous .section __ksymtab_strings,"a" __kstrtab_\name:include/linux/export.h +63
-20@@ -22,6 +22,11 @@ struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; +}; + +struct namespace_import { +const char *namespace; };#ifdef MODULE @@ -54,18 +59,28 @@ extern struct module __this_module;#define __CRC_SYMBOL (sym, sec)#endif +#define NS_SEPARATOR "." + +#define MODULE_IMPORT_NS (ns) \ + static const struct namespace_import __knsimport_##ns \ + asm("__knsimport_" #ns) \ + __attribute__((section("__knsimport"), used)) \ + = { #ns } +/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ + static const char __kstrtab_##sym##nspost[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ + static const struct kernel_symbol __ksymtab_##sym##nspost \ + asm("__ksymtab_" #sym nspost2) \ __used \ - __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((section("___ksymtab" sec "+" #sym #nspost))) \ + __attribute__((used)) \ __attribute__((aligned(sizeof(void *)))) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym##nspost, ns }#if defined(__KSYM_DEPS__)@@ -76,52 +91,80 @@ extern struct module __this_module;* system filters out from the preprocessor output (see ksym_dep_filter * in scripts/Kbuild.include). */ -#define __EXPORT_SYMBOL (sym, sec) === __KSYM_##sym === +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) === __KSYM_##sym ===#elif defined(CONFIG_TRIM_UNUSED_KSYMS )#include <generated/autoksyms.h> -#define __EXPORT_SYMBOL (sym, sec) \ - __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym (sym, sec, conf) \ - ___cond_export_sym(sym, sec, conf) -#define ___cond_export_sym (sym, sec, enabled) \ - __cond_export_sym_##enabled(sym, sec) -#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec) -#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ + __cond_export_sym(sym, sec, ns, nspost, nspost2, \ + __is_defined(__KSYM_##sym)) +#define __cond_export_sym (sym, sec, ns, nspost, nspost2, conf) \ + ___cond_export_sym(sym, sec, ns, nspost, nspost2, conf) +#define ___cond_export_sym (sym, sec, ns, nspost, nspost2, enabled) \ + __cond_export_sym_##enabled(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_1 (sym, sec, ns, nspost, nspost2) \ + ___EXPORT_SYMBOL(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_0 (sym, sec, ns, nspost, nspost2)/* nothing */ #else #define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif #define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym, "", NULL, ,)#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "_gpl", NULL, ,)#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") + __EXPORT_SYMBOL(sym, "_gpl_future", NULL, ,) + +#define EXPORT_SYMBOL_NS (sym, ns) \ + __EXPORT_SYMBOL(sym, "", #ns, __##ns, NS_SEPARATOR #ns) + +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + __EXPORT_SYMBOL(sym, "_gpl", #ns, __##ns, NS_SEPARATOR #ns)#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused", , ,) +#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl", , ,)#else #define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) \ + EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym) +#define MODULE_IMPORT_NS (ns)#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ include/linux/module.h +13
-0@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;kernel/module.c +79
-1@@ -1166,6 +1166,51 @@ static inline int module_unload_init(struct module *mod) }#endif /* CONFIG_MODULE_UNLOAD */ +static bool module_has_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (strcmp (ns_dep->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static int add_module_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +if (module_has_ns_dependency (mod, ns)) +return 0 ; + + ns_dep =kmalloc (sizeof (*ns_dep),GFP_ATOMIC ); +if (!ns_dep) +return -ENOMEM ; + + ns_dep->namespace = ns; + +list_add (&ns_dep->ns_dep, &mod->ns_dependencies); + +return 0 ; +} + +static bool module_imports_ns (struct module *mod,const char *ns) +{ +size_t i; + +if (!ns) +return true; + +for (i =0 ; i < mod->num_ns_imports; ++i) { +if (!strcmp (mod->ns_imports[i].namespace, ns)) +return true; + } + +return false; +} +static size_t module_flags_taint (struct module *mod,char *buf) {size_t l =0 ;@@ -1415,6 +1460,18 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } +/* +* We can't yet verify that the module actually imports this +* namespace, because the imports themselves are only available +* after processing the symbol table and doing relocation; so +* instead just record the dependency and check later. +*/ +if (sym->namespace) { + err =add_module_ns_dependency (mod, sym->namespace); +if (err) + sym =ERR_PTR (err); + } + getname:/* We must make copy under the lock if we failed to get ref. */ strncpy (ownername,module_name (owner),MODULE_NAME_LEN );@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future", sizeof(*mod->gpl_future_syms),@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { +pr_warn ("%s: module uses symbols from namespace %s," +" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool finished_loading (const char *name) {@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err <0 ) goto free_modinfo; +verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ --2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
+++ Martijn Coenen [24/07/18 09:56 +0200]:
Quoted 16 lines
I did find an issue with my approach:
Quoted 5 lines · Martijn Coenen
The ELF symbols are renamed to include the namespace with an asm label; for example, symbol '
usb_stor_suspend' in namespaceUSB_STORAGEbecomes 'usb_stor_suspend.USB_STORAGE'. This allows modpost to do namespace checking, without having to go through all the effort of parsing ELF and reloction records just to get to the structkernel_symbols.depmod doesn't like this: if namespaced symbols are built-in to the kernel, they will appear as 'symbol.NS' in the symbol table, whereas modules using those symbols just depend on 'symbol'. This will cause depmod to warn about unknown symbols. I didn't find this previously because all the exports/imports I tested were done from modules themselves.
Quoted 7 lines
One way to deal with it is to change depmod, but it looks like it hasn't been changed in ages, and it would also introduce a dependency on userspaces to update it to avoid these warnings. So, we'd have to encode the symbol namespace information in another way for modpost to use. I could just write a separate post-processing tool (much like genksyms), or perhaps encode the information in a discardable section. Any other suggestions welcome.
This seems to be because depmod uses System.map as a source for kernel symbols and scans for only the ones prefixed with "__ksymtab" to find the exported ones - and those happen to use the '.' to mark the namespace it belongs to. It strips that prefix and uses the remainder as the actual symbol name. To fix that it'd have to strip the namespace suffix in the symbol name as well.
Just scanning the depmod source code, it seems really trivial to just have depmod accommodate the new symbol name format. Adding Lucas (kmod maintainer) to CC.
Thanks,
Jessica
Quoted 334 lines
Quoted 334 lines
On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Signed-off-by Martijn Coenen <[email protected]>--- include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)include/asm-generic/export.h +1
-1@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN __ksymtab_\name: - __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0 .previous .section __ksymtab_strings,"a" __kstrtab_\name:include/linux/export.h +63
-20@@ -22,6 +22,11 @@ struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; +}; + +struct namespace_import { +const char *namespace; };#ifdef MODULE @@ -54,18 +59,28 @@ extern struct module __this_module;#define __CRC_SYMBOL (sym, sec)#endif +#define NS_SEPARATOR "." + +#define MODULE_IMPORT_NS (ns) \ + static const struct namespace_import __knsimport_##ns \ + asm("__knsimport_" #ns) \ + __attribute__((section("__knsimport"), used)) \ + = { #ns } +/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ + static const char __kstrtab_##sym##nspost[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ + static const struct kernel_symbol __ksymtab_##sym##nspost \ + asm("__ksymtab_" #sym nspost2) \ __used \ - __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((section("___ksymtab" sec "+" #sym #nspost))) \ + __attribute__((used)) \ __attribute__((aligned(sizeof(void *)))) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym##nspost, ns }#if defined(__KSYM_DEPS__)@@ -76,52 +91,80 @@ extern struct module __this_module;* system filters out from the preprocessor output (see ksym_dep_filter * in scripts/Kbuild.include). */ -#define __EXPORT_SYMBOL (sym, sec) === __KSYM_##sym === +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) === __KSYM_##sym ===#elif defined(CONFIG_TRIM_UNUSED_KSYMS )#include <generated/autoksyms.h> -#define __EXPORT_SYMBOL (sym, sec) \ - __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym (sym, sec, conf) \ - ___cond_export_sym(sym, sec, conf) -#define ___cond_export_sym (sym, sec, enabled) \ - __cond_export_sym_##enabled(sym, sec) -#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec) -#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ + __cond_export_sym(sym, sec, ns, nspost, nspost2, \ + __is_defined(__KSYM_##sym)) +#define __cond_export_sym (sym, sec, ns, nspost, nspost2, conf) \ + ___cond_export_sym(sym, sec, ns, nspost, nspost2, conf) +#define ___cond_export_sym (sym, sec, ns, nspost, nspost2, enabled) \ + __cond_export_sym_##enabled(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_1 (sym, sec, ns, nspost, nspost2) \ + ___EXPORT_SYMBOL(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_0 (sym, sec, ns, nspost, nspost2)/* nothing */ #else #define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif #define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym, "", NULL, ,)#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "_gpl", NULL, ,)#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") + __EXPORT_SYMBOL(sym, "_gpl_future", NULL, ,) + +#define EXPORT_SYMBOL_NS (sym, ns) \ + __EXPORT_SYMBOL(sym, "", #ns, __##ns, NS_SEPARATOR #ns) + +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + __EXPORT_SYMBOL(sym, "_gpl", #ns, __##ns, NS_SEPARATOR #ns)#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused", , ,) +#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl", , ,)#else #define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) \ + EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym) +#define MODULE_IMPORT_NS (ns)#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ include/linux/module.h +13
-0@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;kernel/module.c +79
-1@@ -1166,6 +1166,51 @@ static inline int module_unload_init(struct module *mod) }#endif /* CONFIG_MODULE_UNLOAD */ +static bool module_has_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (strcmp (ns_dep->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static int add_module_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +if (module_has_ns_dependency (mod, ns)) +return 0 ; + + ns_dep =kmalloc (sizeof (*ns_dep),GFP_ATOMIC ); +if (!ns_dep) +return -ENOMEM ; + + ns_dep->namespace = ns; + +list_add (&ns_dep->ns_dep, &mod->ns_dependencies); + +return 0 ; +} + +static bool module_imports_ns (struct module *mod,const char *ns) +{ +size_t i; + +if (!ns) +return true; + +for (i =0 ; i < mod->num_ns_imports; ++i) { +if (!strcmp (mod->ns_imports[i].namespace, ns)) +return true; + } + +return false; +} +static size_t module_flags_taint (struct module *mod,char *buf) {size_t l =0 ;@@ -1415,6 +1460,18 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } +/* +* We can't yet verify that the module actually imports this +* namespace, because the imports themselves are only available +* after processing the symbol table and doing relocation; so +* instead just record the dependency and check later. +*/ +if (sym->namespace) { + err =add_module_ns_dependency (mod, sym->namespace); +if (err) + sym =ERR_PTR (err); + } + getname:/* We must make copy under the lock if we failed to get ref. */ strncpy (ownername,module_name (owner),MODULE_NAME_LEN );@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future", sizeof(*mod->gpl_future_syms),@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { +pr_warn ("%s: module uses symbols from namespace %s," +" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool finished_loading (const char *name) {@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err <0 ) goto free_modinfo; +verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ --2.18.0.203.gfac676dfb9-goog
Re: [PATCH 2/6] module: add support for symbol namespaces.
Quoted 20 lines · Jessica Yu
+++ Martijn Coenen [24/07/18 09:56 +0200]:
Quoted 18 lines
I did find an issue with my approach:
Quoted 5 lines · Martijn Coenen
The ELF symbols are renamed to include the namespace with an asm label; for example, symbol '
usb_stor_suspend' in namespaceUSB_STORAGEbecomes 'usb_stor_suspend.USB_STORAGE'. This allows modpost to do namespace checking, without having to go through all the effort of parsing ELF and reloction records just to get to the structkernel_symbols.depmod doesn't like this: if namespaced symbols are built-in to the kernel, they will appear as 'symbol.NS' in the symbol table, whereas modules using those symbols just depend on 'symbol'. This will cause depmod to warn about unknown symbols. I didn't find this previously because all the exports/imports I tested were done from modules themselves.
One way to deal with it is to change depmod, but it looks like it hasn't been changed in ages, and it would also introduce a dependency
this might be because you are looking to the wrong project (module-init-tools) rather than kmod that replaced it some years ago?
Quoted 13 lines
Quoted 5 lines
on userspaces to update it to avoid these warnings. So, we'd have to encode the symbol namespace information in another way for modpost to use. I could just write a separate post-processing tool (much like genksyms), or perhaps encode the information in a discardable section. Any other suggestions welcome.
This seems to be because depmod uses System.map as a source for kernel symbols and scans for only the ones prefixed with "
__ksymtab" to find the exported ones - and those happen to use the '.' to mark the namespace it belongs to. It strips that prefix and uses the remainder as the actual symbol name. To fix that it'd have to strip the namespace suffix in the symbol name as well.
Quoted 3 lines
Just scanning the depmod source code, it seems really trivial to just have depmod accommodate the new symbol name format. Adding Lucas (kmod maintainer) to CC.
Yep, that would be easy and allow depmod to be backward compatible since we would do nothing if the symbol doesn't have the suffix. As for dependency on a new version, this seems trivial enough to be backported to previous releases used on distros so even if they are not rolling they would get a compatible depmod.
CC'ing [email protected] to keep track of this there
thanks
Lucas De Marchi
Quoted 339 lines
Thanks,
Jessica
Quoted 334 lines
Quoted 334 lines
On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Signed-off-by Martijn Coenen <[email protected]>--- include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)include/asm-generic/export.h +1
-1@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN __ksymtab_\name: - __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0 .previous .section __ksymtab_strings,"a" __kstrtab_\name:include/linux/export.h +63
-20@@ -22,6 +22,11 @@ struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; +}; + +struct namespace_import { +const char *namespace; };#ifdef MODULE @@ -54,18 +59,28 @@ extern struct module __this_module;#define __CRC_SYMBOL (sym, sec)#endif +#define NS_SEPARATOR "." + +#define MODULE_IMPORT_NS (ns) \ + static const struct namespace_import __knsimport_##ns \ + asm("__knsimport_" #ns) \ + __attribute__((section("__knsimport"), used)) \ + = { #ns } +/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ + static const char __kstrtab_##sym##nspost[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ + static const struct kernel_symbol __ksymtab_##sym##nspost \ + asm("__ksymtab_" #sym nspost2) \ __used \ - __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((section("___ksymtab" sec "+" #sym #nspost))) \ + __attribute__((used)) \ __attribute__((aligned(sizeof(void *)))) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym##nspost, ns }#if defined(__KSYM_DEPS__)@@ -76,52 +91,80 @@ extern struct module __this_module;* system filters out from the preprocessor output (see ksym_dep_filter * in scripts/Kbuild.include). */ -#define __EXPORT_SYMBOL (sym, sec) === __KSYM_##sym === +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) === __KSYM_##sym ===#elif defined(CONFIG_TRIM_UNUSED_KSYMS )#include <generated/autoksyms.h> -#define __EXPORT_SYMBOL (sym, sec) \ - __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym (sym, sec, conf) \ - ___cond_export_sym(sym, sec, conf) -#define ___cond_export_sym (sym, sec, enabled) \ - __cond_export_sym_##enabled(sym, sec) -#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec) -#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ + __cond_export_sym(sym, sec, ns, nspost, nspost2, \ + __is_defined(__KSYM_##sym)) +#define __cond_export_sym (sym, sec, ns, nspost, nspost2, conf) \ + ___cond_export_sym(sym, sec, ns, nspost, nspost2, conf) +#define ___cond_export_sym (sym, sec, ns, nspost, nspost2, enabled) \ + __cond_export_sym_##enabled(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_1 (sym, sec, ns, nspost, nspost2) \ + ___EXPORT_SYMBOL(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_0 (sym, sec, ns, nspost, nspost2)/* nothing */ #else #define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif #define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym, "", NULL, ,)#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "_gpl", NULL, ,)#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") + __EXPORT_SYMBOL(sym, "_gpl_future", NULL, ,) + +#define EXPORT_SYMBOL_NS (sym, ns) \ + __EXPORT_SYMBOL(sym, "", #ns, __##ns, NS_SEPARATOR #ns) + +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + __EXPORT_SYMBOL(sym, "_gpl", #ns, __##ns, NS_SEPARATOR #ns)#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused", , ,) +#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl", , ,)#else #define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) \ + EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym) +#define MODULE_IMPORT_NS (ns)#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ include/linux/module.h +13
-0@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;kernel/module.c +79
-1@@ -1166,6 +1166,51 @@ static inline int module_unload_init(struct module *mod) }#endif /* CONFIG_MODULE_UNLOAD */ +static bool module_has_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (strcmp (ns_dep->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static int add_module_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +if (module_has_ns_dependency (mod, ns)) +return 0 ; + + ns_dep =kmalloc (sizeof (*ns_dep),GFP_ATOMIC ); +if (!ns_dep) +return -ENOMEM ; + + ns_dep->namespace = ns; + +list_add (&ns_dep->ns_dep, &mod->ns_dependencies); + +return 0 ; +} + +static bool module_imports_ns (struct module *mod,const char *ns) +{ +size_t i; + +if (!ns) +return true; + +for (i =0 ; i < mod->num_ns_imports; ++i) { +if (!strcmp (mod->ns_imports[i].namespace, ns)) +return true; + } + +return false; +} +static size_t module_flags_taint (struct module *mod,char *buf) {size_t l =0 ;@@ -1415,6 +1460,18 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } +/* +* We can't yet verify that the module actually imports this +* namespace, because the imports themselves are only available +* after processing the symbol table and doing relocation; so +* instead just record the dependency and check later. +*/ +if (sym->namespace) { + err =add_module_ns_dependency (mod, sym->namespace); +if (err) + sym =ERR_PTR (err); + } + getname:/* We must make copy under the lock if we failed to get ref. */ strncpy (ownername,module_name (owner),MODULE_NAME_LEN );@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future", sizeof(*mod->gpl_future_syms),@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { +pr_warn ("%s: module uses symbols from namespace %s," +" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool finished_loading (const char *name) {@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err <0 ) goto free_modinfo; +verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ --2.18.0.203.gfac676dfb9-goog
Signature · 1 line
Lucas De Marchi
Re: [PATCH 2/6] module: add support for symbol namespaces.
Quoted 2 lines · Lucas De Marchi
this might be because you are looking to the wrong project (module-init-tools) rather than kmod that replaced it some years ago?
Oh yes indeed, thanks for pointing that out :-)
Quoted 9 lines
Quoted 3 lines
Just scanning the depmod source code, it seems really trivial to just have depmod accommodate the new symbol name format. Adding Lucas (kmod maintainer) to CC.
Yep, that would be easy and allow depmod to be backward compatible since we would do nothing if the symbol doesn't have the suffix. As for dependency on a new version, this seems trivial enough to be backported to previous releases used on distros so even if they are not rolling they would get a compatible depmod.
Thanks for the suggestion. I had also considered modifying the script that generates System.map to strip out the namespace; but that seems a bit hacky since it will then mismatch with the actual symbol table that's in the kernel image. The situation with depmod has gotten me a bit worried that perhaps there are more tools that look at System.map or the kernel's symbol table that won't be able to understand the new format. But of course those could be updated, too.
Another alternative I was considering is leaving the namespace out of the __ksymtab symbols, and instead for the symbols that have a namespace, have an entry in __ksymtab (without namespace) and an entry in a new section __ksymtab_ns (with namespace). We can then discard __ksymtab_ns when building the final executable/modules, since that information is not needed at runtime (it's encoded in struct kernel_symbol). What makes this a bit more complex is that modpost takes the fully linked version of vmlinux which would already have __ksymtab_ns stripped, so we'd need to use objcopy to copy out that section so modpost can use it to read vmlinux's namespaced symbols. Modules wouldn't have that problem, since modpost processes modules before their final linking step.
This last approach is more complex than just modifying depmod, but it does have the benefit that we won't be break userspace tools depending on the kernel __ksymtab section symbols. On the other hand, perhaps userspace tools would like to have the namespace information at some point.
For now I'll keep things as is and write up a patch for depmod, but if others prefer the __ksymtab_ns approach I described above I don't mind making that work.
Thanks,
Martijn
Quoted 351 lines
CC'ing [email protected] to keep track of this there
thanks
Lucas De MarchiQuoted 331 lines
Thanks,
Jessica
Quoted 326 lines
Quoted 326 lines
On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Signed-off-by Martijn Coenen <[email protected]>--- include/asm-generic/export.h | 2 +- include/linux/export.h | 83 +++++++++++++++++++++++++++--------- include/linux/module.h | 13 ++++++ kernel/module.c | 79 ++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-)include/asm-generic/export.h +1
-1@@ -29,7 +29,7 @@ .section ___ksymtab\sec+\name,"a" .balign KSYM_ALIGN __ksymtab_\name: - __put \val, __kstrtab_\name + __put \val, __kstrtab_\name, 0 .previous .section __ksymtab_strings,"a" __kstrtab_\name:include/linux/export.h +63
-20@@ -22,6 +22,11 @@ struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; +}; + +struct namespace_import { +const char *namespace; };#ifdef MODULE @@ -54,18 +59,28 @@ extern struct module __this_module;#define __CRC_SYMBOL (sym, sec)#endif +#define NS_SEPARATOR "." + +#define MODULE_IMPORT_NS (ns) \ + static const struct namespace_import __knsimport_##ns \ + asm("__knsimport_" #ns) \ + __attribute__((section("__knsimport"), used)) \ + = { #ns } +/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ + static const char __kstrtab_##sym##nspost[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ + static const struct kernel_symbol __ksymtab_##sym##nspost \ + asm("__ksymtab_" #sym nspost2) \ __used \ - __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __attribute__((section("___ksymtab" sec "+" #sym #nspost))) \ + __attribute__((used)) \ __attribute__((aligned(sizeof(void *)))) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym##nspost, ns }#if defined(__KSYM_DEPS__)@@ -76,52 +91,80 @@ extern struct module __this_module;* system filters out from the preprocessor output (see ksym_dep_filter * in scripts/Kbuild.include). */ -#define __EXPORT_SYMBOL (sym, sec) === __KSYM_##sym === +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) === __KSYM_##sym ===#elif defined(CONFIG_TRIM_UNUSED_KSYMS )#include <generated/autoksyms.h> -#define __EXPORT_SYMBOL (sym, sec) \ - __cond_export_sym(sym, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym (sym, sec, conf) \ - ___cond_export_sym(sym, sec, conf) -#define ___cond_export_sym (sym, sec, enabled) \ - __cond_export_sym_##enabled(sym, sec) -#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec) -#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL (sym, sec, ns, nspost, nspost2) \ + __cond_export_sym(sym, sec, ns, nspost, nspost2, \ + __is_defined(__KSYM_##sym)) +#define __cond_export_sym (sym, sec, ns, nspost, nspost2, conf) \ + ___cond_export_sym(sym, sec, ns, nspost, nspost2, conf) +#define ___cond_export_sym (sym, sec, ns, nspost, nspost2, enabled) \ + __cond_export_sym_##enabled(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_1 (sym, sec, ns, nspost, nspost2) \ + ___EXPORT_SYMBOL(sym, sec, ns, nspost, nspost2) +#define __cond_export_sym_0 (sym, sec, ns, nspost, nspost2)/* nothing */ #else #define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif #define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym, "", NULL, ,)#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") + __EXPORT_SYMBOL(sym, "_gpl", NULL, ,)#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") + __EXPORT_SYMBOL(sym, "_gpl_future", NULL, ,) + +#define EXPORT_SYMBOL_NS (sym, ns) \ + __EXPORT_SYMBOL(sym, "", #ns, __##ns, NS_SEPARATOR #ns) + +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + __EXPORT_SYMBOL(sym, "_gpl", #ns, __##ns, NS_SEPARATOR #ns)#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused", , ,) +#define EXPORT_UNUSED_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_unused_gpl", , ,)#else #define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) \ + EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) \ + EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)#define EXPORT_UNUSED_SYMBOL_GPL (sym) +#define MODULE_IMPORT_NS (ns)#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ include/linux/module.h +13
-0@@ -268,6 +268,12 @@ void *__symbol_get(const char *symbol);void *__symbol_get_gpl (const char *symbol);#define symbol_get (x) ((typeof(&x))(__symbol_get(VMLINUX_SYMBOL_STR(x)))) +/* namespace dependencies of the module */ +struct module_ns_dep { +struct list_head ns_dep; +const char *namespace; +}; +/* modules using other modules: kdb wants to see this. */ struct module_use {struct list_head source_list;@@ -359,6 +365,13 @@ struct module {const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs; +/* Namespace imports */ +unsigned int num_ns_imports; +const struct namespace_import *ns_imports; + +/* Namespace dependencies */ +struct list_head ns_dependencies; +#ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms;kernel/module.c +77
-0@@ -1166,6 +1166,51 @@ static inline int module_unload_init(struct module *mod) }#endif /* CONFIG_MODULE_UNLOAD */ +static bool module_has_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (strcmp (ns_dep->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static int add_module_ns_dependency (struct module *mod,const char *ns) +{ +struct module_ns_dep *ns_dep; + +if (module_has_ns_dependency (mod, ns)) +return 0 ; + + ns_dep =kmalloc (sizeof (*ns_dep),GFP_ATOMIC ); +if (!ns_dep) +return -ENOMEM ; + + ns_dep->namespace = ns; + +list_add (&ns_dep->ns_dep, &mod->ns_dependencies); + +return 0 ; +} + +static bool module_imports_ns (struct module *mod,const char *ns) +{ +size_t i; + +if (!ns) +return true; + +for (i =0 ; i < mod->num_ns_imports; ++i) { +if (!strcmp (mod->ns_imports[i].namespace, ns)) +return true; + } + +return false; +} +static size_t module_flags_taint (struct module *mod,char *buf) {size_t l =0 ;@@ -1415,6 +1460,18 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } +/* +* We can't yet verify that the module actually imports this +* namespace, because the imports themselves are only available +* after processing the symbol table and doing relocation; so +* instead just record the dependency and check later. +*/ +if (sym->namespace) { + err =add_module_ns_dependency (mod, sym->namespace); +if (err) + sym =ERR_PTR (err); + } + getname:/* We must make copy under the lock if we failed to get ref. */ strncpy (ownername,module_name (owner),MODULE_NAME_LEN );@@ -3061,6 +3118,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)sizeof (*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs =section_addr (info,"__kcrctab_gpl" ); + + mod->ns_imports =section_objs (info,"__knsimport" , +sizeof (*mod->ns_imports), + &mod->num_ns_imports); + mod->gpl_future_syms = section_objs(info, "__ksymtab_gpl_future", sizeof(*mod->gpl_future_syms),@@ -3381,6 +3443,19 @@ static int post_relocation(struct module *mod, const struct load_info *info)return module_finalize (info->hdr, info->sechdrs, mod); } +static void verify_namespace_dependencies (struct module *mod) +{ +struct module_ns_dep *ns_dep; + +list_for_each_entry (ns_dep, &mod->ns_dependencies, ns_dep) { +if (!module_imports_ns (mod, ns_dep->namespace)) { +pr_warn ("%s: module uses symbols from namespace %s," +" but does not import it.\n" , + mod->name, ns_dep->namespace); + } + } +} +/* Is this module of this name done loading? No locks held. */ static bool finished_loading (const char *name) {@@ -3682,6 +3757,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err) goto free_module; +INIT_LIST_HEAD (&mod->ns_dependencies); +#ifdef CONFIG_MODULE_SIG mod->sig_ok = info->sig_ok;if (!mod->sig_ok) {@@ -3730,6 +3807,8 @@ static int load_module(struct load_info *info, const char __user *uargs,if (err <0 ) goto free_modinfo;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
kernel/module.c +2
-1+verify_namespace_dependencies (mod); +flush_module_icache (mod);/* Now copy in args */ --2.18.0.203.gfac676dfb9-goog
--
Lucas De Marchi
PATCH 3/6 modpost: add support for checking symbol namespaces.
In reply to Martijn CoenenEmits a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in.
Example:
WARNING: module ums-usbat uses symbol usb_stor_resume from namespace USB_STORAGE_NS, but does not import it.
--- scripts/mod/modpost.c | 70 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 7 +++++ 2 files changed, 72 insertions(+), 5 deletions(-)
scripts/mod/modpost.c +65 -5
@@ -165,6 +165,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *ns;/* namespace */ unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel
@@ -234,6 +235,35 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list,const char *ns) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) { +if (strcmp (ns_entry->namespace, ns) ==0 ) +return true; + } + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *ns) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, ns)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ))); +strcpy (ns_entry->namespace, ns); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module,const char *ns) +{ +return contains_namespace (module->imported_namespaces, ns); +} + static const struct { const char *str; enum export export;
@@ -313,21 +343,40 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_ns (const char **symname) +{ +size_t n; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { +char *dupsymname =NOFAIL (strdup (*symname)); + + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + }else { +return NULL ; + } +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC **/ -static struct symbol *sym_add_exported (const char *name,struct module *mod, -enum export export) +static struct symbol *sym_add_exported (const char *name, +struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *extract_name = name; +const char *ns =sym_extract_ns (&extract_name); +struct symbol *s =find_symbol (extract_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (extract_name, mod, export); + s->ns = ns; }else {if (!s->preloaded) {warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, +"was in %s%s\n" , mod->name, extract_name, s->module->name,is_vmlinux (s->module->name) ?"" :".ko" ); }else {
@@ -697,6 +746,10 @@ static void handle_modversions(struct module *mod, struct elf_info *info, }if (strcmp (symname,"init_module" ) ==0 ) mod->has_init =1 ; +if (strstarts (symname,"__knsimport_" )) { +const char *name = symname +strlen ("__knsimport_" ); +add_namespace (&mod->imported_namespaces, name); + }if (strcmp (symname,"cleanup_module" ) ==0 ) mod->has_cleanup =1 ;break ;
@@ -2097,6 +2150,13 @@ static void check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->ns && !module_imports_namespace (mod, exp->ns)) { +warn ("module %s uses symbol %s from namespace %s, " +"but does not import it.\n" , + basename, exp->name, exp->ns); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);
scripts/mod/modpost.h +7 -0
@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void buf_write (struct buffer *buf,const char *s,int len); +struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module {struct module *next;const char *name;
@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 4/6 modpost: add support for generating namespace dependencies.
In reply to Martijn CoenenThis patch adds an option to modpost to generate a .ns_deps file per module, containing the namespace depedencies for that module.
This file can subsequently be used by other tools to automatically add newly introduced namespaces to the modules that require them, saving a lot of manual work.
--- scripts/mod/modpost.c | 58 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 2 ++ 2 files changed, 55 insertions(+), 5 deletions(-)
scripts/mod/modpost.c +53 -5
@@ -39,6 +39,8 @@ static int sec_mismatch_verbose = 1;static int sec_mismatch_fatal =0 ;/* ignore missing files */ static int ignore_missing_files; +/* Write namespace dependencies */ +static int write_ns_deps;enum export { export_plain, export_unused, export_gpl,
@@ -2151,10 +2153,15 @@ static void check_exports(struct module *mod)else basename = mod->name; -if (exp->ns && !module_imports_namespace (mod, exp->ns)) { -warn ("module %s uses symbol %s from namespace %s, " -"but does not import it.\n" , - basename, exp->name, exp->ns); +if (exp->ns) { +add_namespace (&mod->required_namespaces, exp->ns); + +if (!write_ns_deps && + !module_imports_namespace (mod, exp->ns)) { +warn ("module %s uses symbol %s from namespace " +"%s, but does not import it.\n" , + basename, exp->name, exp->ns); + } }if (!mod->gpl_compatible)
@@ -2457,6 +2464,38 @@ static void write_dump(const char *fname)free (buf.p); } +static void write_ns_deps_files (void ) +{ +struct module *mod; +struct namespace_list *ns; +struct buffer ns_deps_buf = { }; + +for (mod = modules; mod; mod = mod->next) { +char fname[PATH_MAX ]; +const char *basename; + +if (mod->skip) +continue ; + + ns_deps_buf.pos =0 ; + +for (ns = mod->required_namespaces; ns; ns = ns->next) +buf_printf (&ns_deps_buf,"%s\n" , ns->namespace); + +if (ns_deps_buf.pos ==0 ) +continue ; + + basename =strrchr (mod->name,'/' ); +if (basename) + basename++; +else + basename = mod->name; + +sprintf (fname,".tmp_versions/%s.ns_deps" , basename); +write_if_changed (&ns_deps_buf, fname); + } +} +struct ext_sym_list {struct ext_sym_list *next;const char *file;
@@ -2473,7 +2512,7 @@ int main(int argc, char **argv)struct ext_sym_list *extsym_iter;struct ext_sym_list *extsym_start =NULL ; -while ((opt =getopt (argc, argv,"i:I:e:mnsST:o:awM:K:E" )) !=-1 ) { +while ((opt =getopt (argc, argv,"i:I:e:mnsST:o:awM:K:Ed" )) !=-1 ) {switch (opt) {case 'i' : kernel_read = optarg;
@@ -2517,6 +2556,9 @@ int main(int argc, char **argv)case 'E' : sec_mismatch_fatal =1 ;break ; +case 'd' : + write_ns_deps =1 ; +break ;default :exit (1 ); }
@@ -2545,6 +2587,12 @@ int main(int argc, char **argv)check_exports (mod); } +if (write_ns_deps) { +/* Just write namespace dependencies and exit */ +write_ns_deps_files (); +return 0 ; + } + err =0 ;for (mod = modules; mod; mod = mod->next) {
scripts/mod/modpost.h +2 -0
@@ -126,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Required namespace dependencies +struct namespace_list *required_namespaces;// Actual imported namespaces struct namespace_list *imported_namespaces; };
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
Re: [PATCH 4/6] modpost: add support for generating namespace dependencies.
+++ Martijn Coenen [16/07/18 14:21 +0200]:
Quoted 8 lines
This patch adds an option to modpost to generate a .ns_deps file per module, containing the namespace depedencies for that module.
This file can subsequently be used by other tools to automatically add newly introduced namespaces to the modules that require them, saving a lot of manual work.
Signed-off-by Martijn Coenen <[email protected]>
Regarding modpost, I think it may also be helpful to additionally output the namespace an exported symbol belongs to (if any) in the Module.symvers file.
Quoted 125 lines
---
scripts/mod/modpost.c| 58 +++++++++++++++++++++++++++++++++++++++----scripts/mod/modpost.h| 2 ++2 files changed, 55 insertions(+), 5 deletions(-)scripts/mod/modpost.c +53
-5@@ -39,6 +39,8 @@ static int sec_mismatch_verbose = 1;static int sec_mismatch_fatal =0 ;/* ignore missing files */ static int ignore_missing_files; +/* Write namespace dependencies */ +static int write_ns_deps;enum export { export_plain, export_unused, export_gpl,@@ -2151,10 +2153,15 @@ static void check_exports(struct module *mod)else basename = mod->name; -if (exp->ns && !module_imports_namespace (mod, exp->ns)) { -warn ("module %s uses symbol %s from namespace %s, " -"but does not import it.\n" , - basename, exp->name, exp->ns); +if (exp->ns) { +add_namespace (&mod->required_namespaces, exp->ns); + +if (!write_ns_deps && + !module_imports_namespace (mod, exp->ns)) { +warn ("module %s uses symbol %s from namespace " +"%s, but does not import it.\n" , + basename, exp->name, exp->ns); + } }if (!mod->gpl_compatible)@@ -2457,6 +2464,38 @@ static void write_dump(const char *fname)free (buf.p); } +static void write_ns_deps_files (void ) +{ +struct module *mod; +struct namespace_list *ns; +struct buffer ns_deps_buf = { }; + +for (mod = modules; mod; mod = mod->next) { +char fname[PATH_MAX ]; +const char *basename; + +if (mod->skip) +continue ; + + ns_deps_buf.pos =0 ; + +for (ns = mod->required_namespaces; ns; ns = ns->next) +buf_printf (&ns_deps_buf,"%s\n" , ns->namespace); + +if (ns_deps_buf.pos ==0 ) +continue ; + + basename =strrchr (mod->name,'/' ); +if (basename) + basename++; +else + basename = mod->name; + +sprintf (fname,".tmp_versions/%s.ns_deps" , basename); +write_if_changed (&ns_deps_buf, fname); + } +} +struct ext_sym_list {struct ext_sym_list *next;const char *file;@@ -2473,7 +2512,7 @@ int main(int argc, char **argv)struct ext_sym_list *extsym_iter;struct ext_sym_list *extsym_start =NULL ; -while ((opt =getopt (argc, argv,"i:I:e:mnsST:o:awM:K:E" )) !=-1 ) { +while ((opt =getopt (argc, argv,"i:I:e:mnsST:o:awM:K:Ed" )) !=-1 ) {switch (opt) {case 'i' : kernel_read = optarg;@@ -2517,6 +2556,9 @@ int main(int argc, char **argv)case 'E' : sec_mismatch_fatal =1 ;break ; +case 'd' : + write_ns_deps =1 ; +break ;default :exit (1 ); }@@ -2545,6 +2587,12 @@ int main(int argc, char **argv)check_exports (mod); } +if (write_ns_deps) { +/* Just write namespace dependencies and exit */ +write_ns_deps_files (); +return 0 ; + } + err =0 ;for (mod = modules; mod; mod = mod->next) {scripts/mod/modpost.h +2
-0@@ -126,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Required namespace dependencies +struct namespace_list *required_namespaces;// Actual imported namespaces struct namespace_list *imported_namespaces; };Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 5/6 scripts: Coccinelle script for namespace dependencies.
In reply to Martijn CoenenA script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace with EXPORT_SYMBOL_NS()
2) Run 'make' (or 'make modules'), get warnings about modules not importing that namespace
3) Run 'make nsdeps' to automatically add required import statements to said modules
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
--- Makefile | 11 ++++++++++ scripts/Makefile.modpost | 4 +++- scripts/add_namespace.cocci | 19 +++++++++++++++++ scripts/nsdeps | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 scripts/add_namespace.cocci create mode 100644 scripts/nsdeps
Makefile +11 -0
@@ -1391,6 +1391,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'
@@ -1566,6 +1569,14 @@ quiet_cmd_tags = GEN $@ tags TAGS cscope gtags: FORCE $(call cmd,tags) +# Script to generate missing namespace dependencies + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + # Scripts to check various things for consistency # ---------------------------------------------------------------------------
scripts/Makefile.modpost +3 -1
@@ -79,7 +79,8 @@ modpost = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
@@ -130,6 +131,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: _modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------
scripts/add_namespace.cocci new file +19 -0
@@ -0,0 +1,19 @@ +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +@has_module_license@ +declarer name MODULE_LICENSE; +expression license; +@@ +MODULE_LICENSE(license); + +@do_import depends on has_module_license && !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);
scripts/nsdeps new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
PATCH 6/6 RFC: USB: storage: move symbols into USB_STORAGE namespace.
In reply to Martijn CoenenModules using these symbols must now import this namesapce explicitly.
--- drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + drivers/usb/storage/usb.c | 20 ++++++++++---------- 15 files changed, 24 insertions(+), 10 deletions(-)
drivers/usb/storage/alauda.c +1 -0
@@ -36,6 +36,7 @@MODULE_DESCRIPTION ("Driver for Alauda-based card readers" );MODULE_AUTHOR ("Daniel Drake <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * Status bytes
drivers/usb/storage/cypress_atacb.c +1 -0
@@ -22,6 +22,7 @@MODULE_DESCRIPTION ("SAT support for Cypress USB/ATA bridges with ATACB" );MODULE_AUTHOR ("Matthieu Castet <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/datafab.c +1 -0
@@ -54,6 +54,7 @@MODULE_DESCRIPTION ("Driver for Datafab USB Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );struct datafab_info {unsigned long sectors;/* total sector count */
drivers/usb/storage/ene_ub6250.c +1 -0
@@ -26,6 +26,7 @@MODULE_DESCRIPTION ("Driver for ENE UB6250 reader" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_FIRMWARE (SD_INIT1_FIRMWARE );MODULE_FIRMWARE (SD_INIT2_FIRMWARE );MODULE_FIRMWARE (SD_RW_FIRMWARE );
drivers/usb/storage/freecom.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for Freecom USB/IDE adaptor" );MODULE_AUTHOR ("David Brown <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (struct us_data *us,void *ibuffer,int length);
drivers/usb/storage/isd200.c +1 -0
@@ -53,6 +53,7 @@MODULE_DESCRIPTION ("Driver for In-System Design, Inc. ISD200 ASIC" );MODULE_AUTHOR ("Björn Stenberg <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int isd200_Initialization (struct us_data *us);
drivers/usb/storage/jumpshot.c +1 -0
@@ -51,6 +51,7 @@MODULE_DESCRIPTION ("Driver for Lexar \"Jumpshot\" Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/karma.c +1 -0
@@ -23,6 +23,7 @@MODULE_DESCRIPTION ("Driver for Rio Karma" );MODULE_AUTHOR ("Bob Copeland <[email protected]>, Keith Bennett <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define RIO_PREFIX "RIOP\x00"#define RIO_PREFIX_LEN 5
drivers/usb/storage/onetouch.c +1 -0
@@ -25,6 +25,7 @@MODULE_DESCRIPTION ("Maxtor USB OneTouch hard drive button driver" );MODULE_AUTHOR ("Nick Sillik <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define ONETOUCH_PKT_LEN 0x02#define ONETOUCH_BUTTON KEY_PROG1
drivers/usb/storage/realtek_cr.c +1 -0
@@ -35,6 +35,7 @@MODULE_DESCRIPTION ("Driver for Realtek USB Card Reader" );MODULE_AUTHOR ("wwang <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int auto_delink_en =1 ;module_param (auto_delink_en, int,S_IRUGO |S_IWUSR );
drivers/usb/storage/sddr09.c +1 -0
@@ -47,6 +47,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-09 SmartMedia reader" );MODULE_AUTHOR ("Andries Brouwer <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int usb_stor_sddr09_dpcm_init (struct us_data *us);static int sddr09_transport (struct scsi_cmnd *srb,struct us_data *us);
drivers/usb/storage/sddr55.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-55 SmartMedia reader" );MODULE_AUTHOR ("Simon Munton" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/shuttle_usbat.c +1 -0
@@ -48,6 +48,7 @@MODULE_DESCRIPTION ("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable" );MODULE_AUTHOR ("Daniel Drake <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* Supported device types */ #define USBAT_DEV_HP8200 0x01
drivers/usb/storage/uas.c +1 -0
@@ -1195,5 +1195,6 @@ static struct usb_driver uas_driver = {module_usb_driver (uas_driver);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_AUTHOR ("Hans de Goede <[email protected]>, Matthew Wilcox and Sarah Sharp" );
drivers/usb/storage/usb.c +10 -10
@@ -184,7 +184,7 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)mutex_unlock (&us->dev_mutex);return 0 ; } -EXPORT_SYMBOL_GPL (usb_stor_suspend); +EXPORT_SYMBOL_NS_GPL (usb_stor_suspend,USB_STORAGE );int usb_stor_resume (struct usb_interface *iface) {
@@ -198,7 +198,7 @@ int usb_stor_resume(struct usb_interface *iface)mutex_unlock (&us->dev_mutex);return 0 ; } -EXPORT_SYMBOL_GPL (usb_stor_resume); +EXPORT_SYMBOL_NS_GPL (usb_stor_resume,USB_STORAGE );int usb_stor_reset_resume (struct usb_interface *iface) {
@@ -213,7 +213,7 @@ int usb_stor_reset_resume(struct usb_interface *iface)*/ return 0; } -EXPORT_SYMBOL_GPL (usb_stor_reset_resume); +EXPORT_SYMBOL_NS_GPL (usb_stor_reset_resume,USB_STORAGE );#endif /* CONFIG_PM */
@@ -230,7 +230,7 @@ int usb_stor_pre_reset(struct usb_interface *iface)mutex_lock (&us->dev_mutex);return 0 ; } -EXPORT_SYMBOL_GPL (usb_stor_pre_reset); +EXPORT_SYMBOL_NS_GPL (usb_stor_pre_reset,USB_STORAGE );int usb_stor_post_reset (struct usb_interface *iface) {
@@ -247,7 +247,7 @@ int usb_stor_post_reset(struct usb_interface *iface)mutex_unlock (&us->dev_mutex);return 0 ; } -EXPORT_SYMBOL_GPL (usb_stor_post_reset); +EXPORT_SYMBOL_NS_GPL (usb_stor_post_reset,USB_STORAGE );/* * fill_inquiry_response takes an unsigned char array (which must
@@ -293,7 +293,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,usb_stor_set_xfer_buf (data, data_len, us->srb); } -EXPORT_SYMBOL_GPL (fill_inquiry_response); +EXPORT_SYMBOL_NS_GPL (fill_inquiry_response,USB_STORAGE );static int usb_stor_control_thread (void * __us) {
@@ -579,7 +579,7 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) } *fflags = (*fflags & ~mask) | f; } -EXPORT_SYMBOL_GPL (usb_stor_adjust_quirks); +EXPORT_SYMBOL_NS_GPL (usb_stor_adjust_quirks,USB_STORAGE );/* Get the unusual_devs entries and the string descriptors */ static int get_device_info(struct us_data *us, const struct usb_device_id *id,
@@ -990,7 +990,7 @@ int usb_stor_probe1(struct us_data **pus,release_everything (us);return result; } -EXPORT_SYMBOL_GPL (usb_stor_probe1); +EXPORT_SYMBOL_NS_GPL (usb_stor_probe1,USB_STORAGE );/* Second part of general USB mass-storage probing */ int usb_stor_probe2 (struct us_data *us)
@@ -1074,7 +1074,7 @@ int usb_stor_probe2(struct us_data *us)release_everything (us);return result; } -EXPORT_SYMBOL_GPL (usb_stor_probe2); +EXPORT_SYMBOL_NS_GPL (usb_stor_probe2,USB_STORAGE );/* Handle a USB mass-storage disconnect */ void usb_stor_disconnect (struct usb_interface *intf)
@@ -1084,7 +1084,7 @@ void usb_stor_disconnect(struct usb_interface *intf)quiesce_and_remove_host (us);release_everything (us); } -EXPORT_SYMBOL_GPL (usb_stor_disconnect); +EXPORT_SYMBOL_NS_GPL (usb_stor_disconnect,USB_STORAGE );static struct scsi_host_template usb_stor_host_template;
Signature · 1 line
2.18.0.203.gfac676dfb9-goog
Alan Stern
maintainerRe: [PATCH 6/6] RFC: USB: storage: move symbols into USB_STORAGE namespace.
Quoted 1 line · Martijn Coenen
Modules using these symbols must now import this namesapce explicitly.
Spelling error ("namesapce").
Quoted 11 lines
Signed-off-by Martijn Coenen <[email protected]>--- drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 +
Quoted 8 lines
drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + drivers/usb/storage/usb.c | 20 ++++++++++---------- 15 files changed, 24 insertions(+), 10 deletions(-)
This patch misses the various EXPORT_SYMBOL_GPL lines in debug.c, protocol.c, scsiglue.c, and transport.c. They should also be considered part of the USB_STORAGE namespace.
Alan Stern
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 6/6] RFC: USB: storage: move symbols into USB_STORAGE namespace.
Quoted 3 lines · Alan Stern
This patch misses the various
EXPORT_SYMBOL_GPLlines indebug.c,protocol.c,scsiglue.c, andtransport.c. They should also be considered part of theUSB_STORAGEnamespace.
Thanks! I'd been using the usb.c symbols as my test vehicle forever, and I forgot to check whether there were others. I'll make sure to include them in the next series.
Martijn
Quoted 3 lines
Alan Stern
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Greg Kroah-Hartman
maintainerQuoted 23 lines · Martijn Coenen
As of Linux 4.17, there are more than 30000 exported symbols in the kernel. There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree useWhen module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
Quoted 6 lines
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "
SUBSYSTEM_DEBUG" namespace.
To give people a bit more background here, this is something that both Andi Kleen and I talked about over a decade ago. Martijn based his work on Andi's original patches and made them all work well, something that I was unable to do :)
His addition of using the build system to automatically generate a patch for a subsystem based on the symbol namespace changes is frickin amazing.
Great work here, this is something that I have wanted for the kernel for a long time.
greg k-h
Arnd Bergmann
maintainerQuoted 23 lines · Martijn Coenen
As of Linux 4.17, there are more than 30000 exported symbols in the kernel. There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree useWhen module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
Quoted 6 lines
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "
SUBSYSTEM_DEBUG" namespace.
This looks nice. I don't want to overload you with additional requests, but it might be good to think about how this can be taken further, if we want to actually convert large parts of the kernel to it. I have two ideas:
- It would be nice to have a simple mechanism in Kconfig to put all symbols in a module into a namespace that is derived from KBUILD_MODNAME, to avoid having to annotate every symbol separately. This could be similar to how we ended up dealing with EXPORT_NO_SYMBOLS in the linux-2.4 days, with the goal of eventually having a namespace for each symbol. Similarly, we could pass a number of default namespaces through the Makefile, e.g. if we have a directory that has lots of drivers that all import the symbols from a common subsystem module.
- If this is possible to implement, it would be great to have a way to limit the globally visible symbols in a module to the ones that are explicitly exported even when a that module is built-in rather than loadable. Not sure how this is best done though. A couple of things can be done with objcopy, or possibly by reintroducing partial linking (which was removed not too long ago).
Arnd
Hi Arnd,
Quoted 4 lines · Arnd Bergmann
This looks nice. I don't want to overload you with additional requests, but it might be good to think about how this can be taken further, if we want to actually convert large parts of the kernel to it.
No worries about overloading, I'm happy with all feedback to make this better.
Quoted 12 lines
I have two ideas:
- It would be nice to have a simple mechanism in
Kconfigto put all symbols in a module into a namespace that is derived fromKBUILD_MODNAME, to avoid having to annotate every symbol separately. This could be similar to how we ended up dealing withEXPORT_NO_SYMBOLSin the linux-2.4 days, with the goal of eventually having a namespace for each symbol. Similarly, we could pass a number of default namespaces through theMakefile, e.g. if we have a directory that has lots of drivers that all import the symbols from a common subsystem module.
I'm hinging on two thoughts here; I really like it because it obviously reduces work and makes this easier to use. On the other hand, you now have to look in multiple places to see if a symbol is exported to a namespace/imported from a module. Perhaps it depends on how coarse-grained the namespaces end up being. Either way, I think it would be pretty easy to cook up patches for this.
Quoted 8 lines
- If this is possible to implement, it would be great to have a way to limit the globally visible symbols in a module to the ones that are explicitly exported even when a that module is built-in rather than loadable. Not sure how this is best done though. A couple of things can be done with objcopy, or possibly by reintroducing partial linking (which was removed not too long ago).
If I understand you correctly, this is orthogonal to symbol namespaces, right? Though I think there is value in doing the same thing for symbol namespaces: right now, the only way to find out if all modules correctly import a symbol exported to a namespace is to run an 'allmodconfig'; not having to do that would be a win. Being able to do the same thing for the exported symbols in the global namespace is very similar. So yeah, I think this is a good idea and will look into this more.
Do you think these things should be a part of these series, or can it be a follow-up?
Thanks,
Martijn
Quoted 2 lines
Arnd
Arnd Bergmann
maintainerQuoted 23 lines · Martijn Coenen
Hi Arnd,
Quoted 4 lines · Arnd Bergmann
This looks nice. I don't want to overload you with additional requests, but it might be good to think about how this can be taken further, if we want to actually convert large parts of the kernel to it.
No worries about overloading, I'm happy with all feedback to make this better.
Quoted 12 lines
I have two ideas:
- It would be nice to have a simple mechanism in
Kconfigto put all symbols in a module into a namespace that is derived fromKBUILD_MODNAME, to avoid having to annotate every symbol separately. This could be similar to how we ended up dealing withEXPORT_NO_SYMBOLSin the linux-2.4 days, with the goal of eventually having a namespace for each symbol. Similarly, we could pass a number of default namespaces through theMakefile, e.g. if we have a directory that has lots of drivers that all import the symbols from a common subsystem module.
Quoted 6 lines
I'm hinging on two thoughts here; I really like it because it obviously reduces work and makes this easier to use. On the other hand, you now have to look in multiple places to see if a symbol is exported to a namespace/imported from a module. Perhaps it depends on how coarse-grained the namespaces end up being. Either way, I think it would be pretty easy to cook up patches for this.
Ok, maybe try it and see where we get with it?
Quoted 10 lines
Quoted 7 lines
- If this is possible to implement, it would be great to have a way to limit the globally visible symbols in a module to the ones that are explicitly exported even when a that module is built-in rather than loadable. Not sure how this is best done though. A couple of things can be done with objcopy, or possibly by reintroducing partial linking (which was removed not too long ago).
If I understand you correctly, this is orthogonal to symbol namespaces, right?
Right, the only connection here is that both try to limit the scope of which symbols are available where. This can definitely be done without symbol namespaces. The implementation I had in mind with objcopy might end up using the same KBUILD_MODNAME as a prefix for internal symbols (which are not exported to modules), but that is a different problem.
Another related area is the question what happens to symbols that we want to share between two built-in parts of the kernel without exporting them to modules. E.g. if we might want to put all of vfs into one built-in module and make its symbols private to that module, while all of the mm subsystem is in a separate built-in module. The symbols that are needed for communicating between the two could simply be exported with EXPORT_SYMBOL_GPL(), but we that would open the surface to loadable modules that can't access them today. Using namespaces could solve that problem by limiting the scope in another way, or we could come up with a different method to annotate them, such as using the gcc visibility
attributes.
Quoted 2 lines
Do you think these things should be a part of these series, or can it be a follow-up?
If you think you can do the first thing easily, I'd say we should try to come up with an idea of where we want to take this in the long run. For limiting the scope of global symbols, that may well be a much bigger task to do upfront, so unless you have an idea for how to do that, maybe keep it in mind but let's not make it a dependency.
Arnd
Matthias Maennich
maintainerv2 cover Symbol namespaces - RFC
In reply to Martijn CoenenAs of Linux 5.3-rc4, there are 31203 [1] exported symbols in the kernel. That is a growth of almost 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree use
When module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "SUBSYSTEM_DEBUG" namespace.
I continued the work mainly done by Martijn Coenen. In this v2 the following changes have been introduced compared to v1 of this series:
- Rather than adding and evaluating separate sections __knsimport_NS, use modinfo tags to declare the namespaces a module introduces. Adjust modpost and the module loader accordingly.
- Also add support for reading multiple modinfo values for the same tag to allow list-like access to modinfo tags.
- The macros in export.h have been cleaned up to avoid redundancy in the macro parameters (ns, nspost, nspost2).
- The introduction of relative references in the ksymtab entries caused a rework of the macros to accommodate that configuration as well.
- Alignment of kernel_symbol in the ksymtab needed to be fixed to allow growing the kernel_symbol struct.
- Modpost does now also append the namespace suffix to the symbol entries in Module.symvers.
- The configuration option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS allows relaxing the enforcement of properly declared namespace imports at module loading time.
- Symbols can be collectively exported into a namespace by defining DEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile.
- The requirement for a very recent coccinelle spatch has been lifted by simplifying the script.
- nsdeps does now ensures MODULE_IMPORT_NS statements are sorted when patching the module source files.
- Some minor bugs have been addressed in nsdeps to allow it to work with modules that have more than one source file.
- The RFC for the usb-storage symbols has been simplified by using DEFAULT_SYMBOL_NAMESPACE=USB_STORAGE rather than explicitly exporting each and every symbol into that new namespace.
This patch series was developed against v5.3-rc4.
[1] git grep "^EXPORT_SYMBOL\w*(" v5.3-rc4 | wc -l
[2] git grep "^EXPORT_SYMBOL\w*(" v4.17 | wc -l
Matthias Maennich (10):
module: support reading multiple values per modinfo tag
export: explicitly align struct kernel_symbol
module: add support for symbol namespaces.
modpost: add support for symbol namespaces
module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
export: allow definition default namespaces in Makefiles or sources
modpost: add support for generating namespace dependencies
scripts: Coccinelle script for namespace dependencies.
usb-storage: remove single-use define for debugging
RFC: usb-storage: export symbols in USB_STORAGE namespace
MAINTAINERS | 5 + Makefile | 12 ++ arch/m68k/include/asm/export.h | 1 - drivers/usb/storage/Makefile | 2 + drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/debug.h | 2 - drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + include/asm-generic/export.h | 14 +- include/linux/export.h | 92 +++++++++++-- include/linux/module.h | 2 + init/Kconfig | 14 ++ kernel/module.c | 67 ++++++++- scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 ++++ scripts/mod/modpost.c | 144 ++++++++++++++++++-- scripts/mod/modpost.h | 9 ++ scripts/nsdeps | 54 ++++++++ 30 files changed, 421 insertions(+), 40 deletions(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v2 1/10 module: support reading multiple values per modinfo tag
Similar to modpost's get_next_modinfo(), introduce get_next_modinfo() in kernel/module.c to acquire any further values associated with the same modinfo tag name. That is useful for any tags that have multiple occurrences (such as 'alias'), but is in particular introduced here as part of the symbol namespaces patch series to read the (potentially) multiple namespaces a module is importing.
--- kernel/module.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
kernel/module.c +15 -2
@@ -2481,7 +2481,8 @@ static char *next_string(char *string, unsigned long *secsize)return string; } -static char *get_modinfo (struct load_info *info,const char *tag) +static char *get_next_modinfo (const struct load_info *info,const char *tag, +char *prev) {char *p;unsigned int taglen =strlen (tag);
@@ -2492,13 +2493,25 @@ static char *get_modinfo(struct load_info *info, const char *tag)* get_modinfo() calls made before rewrite_section_headers() * must use sh_offset, as sh_addr isn't set! */ -for (p = (char *)info->hdr + infosec->sh_offset; p; p =next_string (p, &size)) { +char *modinfo = (char *)info->hdr + infosec->sh_offset; + +if (prev) { + size -= prev - modinfo; + modinfo =next_string (prev, &size); + } + +for (p = modinfo; p; p =next_string (p, &size)) {if (strncmp (p, tag, taglen) ==0 && p[taglen] =='=' )return p + taglen +1 ; }return NULL ; } +static char *get_modinfo (const struct load_info *info,const char *tag) +{ +return get_next_modinfo (info, tag,NULL ); +} +static void setup_modinfo (struct module *mod,struct load_info *info) {struct module_attribute *attr;
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 01/10] module: support reading multiple values per modinfo tag
Quoted 10 lines · Matthias Maennich
Similar to modpost's
get_next_modinfo(), introduceget_next_modinfo()inkernel/module.cto acquire any further values associated with the same modinfo tag name. That is useful for any tags that have multiple occurrences (such as 'alias'), but is in particular introduced here as part of the symbol namespaces patch series to read the (potentially) multiple namespaces a module is importing.Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Matthias Maennich
maintainerPATCH v2 2/10 export: explicitly align struct kernel_symbol
In reply to Matthias MaennichThis change allows growing struct kernel_symbol without wasting bytes to alignment. It also concretized the alignment of ksymtab entries if relative references are used for ksymtab entries.
struct kernel_symbol was already implicitly being aligned to the word size, except on x86_64 and m68k, where it is aligned to 16 and 2 bytes, respectively.
As far as I can tell there is no requirement for aligning struct kernel_symbol to 16 bytes on x86_64, but gcc aligns structs to their size, and the linker aligns the custom __ksymtab sections to the largest data type contained within, so setting KSYM_ALIGN to 16 was necessary to stay consistent with the code generated for non-ASM EXPORT_SYMBOL(). Now that non-ASM EXPORT_SYMBOL() explicitly aligns to word size (8), KSYM_ALIGN is no longer necessary.
In case of relative references, the alignment has been changed accordingly to not waste space when adding new struct members.
As for m68k, struct kernel_symbol is aligned to 2 bytes even though the structure itself is 8 bytes; using a 4-byte alignment shouldn't hurt.
I manually verified the output of the __ksymtab sections didn't change on x86, x86_64, arm, arm64 and m68k. As expected, the section contents didn't change, and the ELF section alignment only changed on x86_64 and m68k. Feedback from other archs more than welcome.
--- arch/m68k/include/asm/export.h | 1 - include/asm-generic/export.h | 8 +++----- include/linux/export.h | 3 ++- 3 files changed, 5 insertions(+), 7 deletions(-)
arch/m68k/include/asm/export.h +0 -1
@@ -1,3 +1,2 @@ -#define KSYM_ALIGN 2#define KCRC_ALIGN 2#include <asm-generic/export.h>
include/asm-generic/export.h +3 -5
@@ -4,15 +4,13 @@#ifndef KSYM_FUNC #define KSYM_FUNC (x) x#endif -#ifdef CONFIG_64BIT -#ifndef KSYM_ALIGN +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +#define KSYM_ALIGN 4 +#elif defined(CONFIG_64BIT )#define KSYM_ALIGN 8 -#endif #else -#ifndef KSYM_ALIGN #define KSYM_ALIGN 4#endif -#endif #ifndef KCRC_ALIGN #define KCRC_ALIGN 4#endif
include/linux/export.h +2 -1
@@ -52,7 +52,7 @@ extern struct module __this_module;#define __KSYMTAB_ENTRY (sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ - " .balign 8 \n" \ + " .balign 4 \n" \ "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \
@@ -66,6 +66,7 @@ struct kernel_symbol {#define __KSYMTAB_ENTRY (sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ = { (unsigned long)&sym, __kstrtab_##sym }struct kernel_symbol {
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 02/10] export: explicitly align struct kernel_symbol
Quoted 22 lines · Matthias Maennich
This change allows growing struct
kernel_symbolwithout wasting bytes to alignment. It also concretized the alignment of ksymtab entries if relative references are used for ksymtab entries.struct
kernel_symbolwas already implicitly being aligned to the word size, except onx86_64and m68k, where it is aligned to 16 and 2 bytes, respectively.As far as I can tell there is no requirement for aligning struct
kernel_symbolto 16 bytes onx86_64, but gcc aligns structs to their size, and the linker aligns the custom__ksymtabsections to the largest data type contained within, so settingKSYM_ALIGNto 16 was necessary to stay consistent with the code generated for non-ASMEXPORT_SYMBOL(). Now that non-ASMEXPORT_SYMBOL()explicitly aligns to word size (8),KSYM_ALIGNis no longer necessary.In case of relative references, the alignment has been changed accordingly to not waste space when adding new struct members.
As for m68k, struct
kernel_symbolis aligned to 2 bytes even though the structure itself is 8 bytes; using a 4-byte alignment shouldn't hurt.
Quoted 8 lines
I manually verified the output of the
__ksymtabsections didn't change on x86,x86_64, arm, arm64 and m68k. As expected, the section contents didn't change, and the ELF section alignment only changed onx86_64and m68k. Feedback from other archs more than welcome.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Ick, messy, nice fix.
Matthias Maennich
maintainerPATCH v2 3/10 module: add support for symbol namespaces.
In reply to Matthias MaennichThe 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.
--- include/asm-generic/export.h | 6 +-- include/linux/export.h | 85 ++++++++++++++++++++++++++++++------ include/linux/module.h | 2 + kernel/module.c | 43 ++++++++++++++++++ 4 files changed, 120 insertions(+), 16 deletions(-)
include/asm-generic/export.h +3 -3
@@ -17,11 +17,11 @@ .macro __put, val, name#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - .long \val - ., \name - . + .long \val - ., \name - ., 0 - .#elif defined(CONFIG_64BIT ) - .quad \val, \name + .quad \val, \name, 0#else - .long \val, \name + .long \val, \name, 0#endif .endm
include/linux/export.h +72 -13
151 lines not on this page · raw message
include/linux/module.h +2 -0
@@ -280,6 +280,8 @@ struct notifier_block;#ifdef CONFIG_MODULES +#define MODULE_IMPORT_NS (ns) MODULE_INFO(import_ns, #ns) +extern int modules_disabled;/* for sysctl */ /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get (const char *symbol);
kernel/module.c +43 -0
61 lines not on this page · raw message
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 03/10] module: add support for symbol namespaces.
Quoted 31 lines · Matthias Maennich
The
EXPORT_SYMBOL_NS()andEXPORT_SYMBOL_NS_GPL()macros can be used to export a symbol to a specific namespace. There are no_GPL_FUTUREand_UNUSEDvariants 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 andkernel/module.cat 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 namespaceUSB_STORAGEbecomes '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 structkernel_symbols.On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.
Quoted 3 lines
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Matthias Maennich
maintainerPATCH v2 4/10 modpost: add support for symbol namespaces
In reply to Matthias MaennichAdd support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol usb_stor_resume from namespace USB_STORAGE, but does not import it.
--- scripts/mod/modpost.c | 91 +++++++++++++++++++++++++++++++++++++------ scripts/mod/modpost.h | 7 ++++ 2 files changed, 87 insertions(+), 11 deletions(-)
scripts/mod/modpost.c +80 -11
@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel
@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;
@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC
@@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;
@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;
@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);
@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);
@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol)) -buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; +buf_printf (&buf,"0x%08x\t%s%s%s\t%s\t%s\n" , + symbol->crc, symbol->name, + namespace ?"." :"" , + namespace ? namespace :"" , + symbol->module->name, +export_str (symbol->export)); + } symbol = symbol->next; } }
scripts/mod/modpost.h +7 -0
@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void buf_write (struct buffer *buf,const char *s,int len); +struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module {struct module *next;const char *name;
@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 04/10] modpost: add support for symbol namespaces
Quoted 12 lines · Matthias Maennich
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.
Quoted 8 lines
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- scripts/mod/modpost.c | 91 +++++++++++++++++++++++++++++++++++++------ scripts/mod/modpost.h | 7 ++++ 2 files changed, 87 insertions(+), 11 deletions(-)
Matthias Maennich
maintainerPATCH v2 5/10 module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
In reply to Matthias MaennichIf MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.
Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
--- init/Kconfig | 14 ++++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)
init/Kconfig +14 -0
@@ -2119,6 +2119,20 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + default n + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + This option relaxes this requirement when loading a module. While + technically there is no reason to enforce correct namespace imports, + it creates consistency between symbols defining namespaces and users + importing namespaces they make use of. + + If unsure, say N. + config TRIM_UNUSED_KSYMS bool "Trim unused exported kernel symbols" depends on MODULES && !UNUSED_SYMBOLS
kernel/module.c +9 -2
@@ -1408,9 +1408,16 @@ static int verify_namespace_is_imported(const struct load_info *info, imported_namespace =get_next_modinfo ( info,"import_ns" , imported_namespace); } -pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , - mod->name,kernel_symbol_name (sym), namespace); +#ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + pr_warn( +#else + pr_err( +#endif +"%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name, kernel_symbol_name(sym), namespace); +#ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS return -EINVAL ; +#endif }return 0 ; }
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 05/10] module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
Quoted 22 lines · Matthias Maennich
If
MODULE_ALLOW_MISSING_NAMESPACE_IMPORTSis enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- init/Kconfig | 14 ++++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)init/Kconfig +0
-0
init/Kconfig config MODULE_COMPRESS_XZ · line 2124
Quoted 6 lines
init/Kconfig +3
-0@@ -2119,6 +2119,20 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + default n
the default for config options is always N, no need to list it here.
Quoted 24 lines
init/Kconfig +11
-0+ help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + This option relaxes this requirement when loading a module. While + technically there is no reason to enforce correct namespace imports, + it creates consistency between symbols defining namespaces and users + importing namespaces they make use of. + + If unsure, say N. + config TRIM_UNUSED_KSYMS bool "Trim unused exported kernel symbols" depends on MODULES && !UNUSED_SYMBOLSkernel/module.c +0
-2@@ -1408,9 +1408,16 @@ static int verify_namespace_is_imported(const struct load_info *info, imported_namespace =get_next_modinfo ( info,"import_ns" , imported_namespace); } -pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , - mod->name,kernel_symbol_name (sym), namespace);
kernel/module.c static int verify_namespace_is_imported(const struct load_info *info, · line 1420
Quoted 10 lines
kernel/module.c +9
-0+#ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + pr_warn( +#else + pr_err( +#endif +"%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name, kernel_symbol_name(sym), namespace); +#ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS return -EINVAL ; +#endif
This #ifdef mess is a hack, but oh well :)
If you drop the above default line, feel free to add:
Re: [PATCH v2 05/10] module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
In reply to Matthias MaennichQuoted 36 lines · Matthias Maennich' via kernel-team
If
MODULE_ALLOW_MISSING_NAMESPACE_IMPORTSis enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- init/Kconfig | 14 ++++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)init/Kconfig +8
-0@@ -2119,6 +2119,20 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + default n + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + This option relaxes this requirement when loading a module.While
init/Kconfig config MODULE_COMPRESS_XZ · line 2132
Quoted 3 lines
init/Kconfig +3
-0+ technically there is no reason to enforce correct namespace imports, + it creates consistency between symbols defining namespaces and users + importing namespaces they make use of.
I'm confused by this sentence. It sounds like it's the opposite of what the config is doing? Can you please reword it for clarify?
-Saravana
Matthias Maennich
maintainerRe: [PATCH v2 05/10] module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
Quoted 37 lines · Saravana Kannan
Quoted 34 lines · Matthias Maennich' via kernel-team
If
MODULE_ALLOW_MISSING_NAMESPACE_IMPORTSis enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- init/Kconfig | 14 ++++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)init/Kconfig +8
-0@@ -2119,6 +2119,20 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + default n + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + This option relaxes this requirement when loading a module.
Quoted 7 lines
init/Kconfig config MODULE_COMPRESS_XZ · line 2132
Quoted 4 lines
While
init/Kconfig +3
-0+ technically there is no reason to enforce correct namespace imports, + it creates consistency between symbols defining namespaces and users + importing namespaces they make use of.I'm confused by this sentence. It sounds like it's the opposite of what the config is doing? Can you please reword it for clarify?
How about:
Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in a namespace. A module that makes use of a symbol exported with such a namespace is required to import the namespace via MODULE_IMPORT_NS(). There is no technical reason to enforce correct namespace imports, but it creates consistency between symbols defining namespaces and users importing namespaces they make use of. This option relaxes this requirement and lifts the enforcement when loading a module.
Signature · 2 lines
Cheers, Matthias
Re: [PATCH v2 05/10] module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
Quoted 49 lines · Matthias Maennich' via kernel-team
Quoted 37 lines · Saravana Kannan
Quoted 34 lines · Matthias Maennich' via kernel-team
If
MODULE_ALLOW_MISSING_NAMESPACE_IMPORTSis enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- init/Kconfig | 14 ++++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-)init/Kconfig +8
-0@@ -2119,6 +2119,20 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + default n + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + This option relaxes this requirement when loading a module.Quoted 7 lines
init/Kconfig config MODULE_COMPRESS_XZ · line 2132
Quoted 4 lines
While
init/Kconfig +3
-0+ technically there is no reason to enforce correct namespace imports, + it creates consistency between symbols defining namespaces and users + importing namespaces they make use of.I'm confused by this sentence. It sounds like it's the opposite of what the config is doing? Can you please reword it for clarify?
How about:
Quoted 7 lines
Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in a namespace. A module that makes use of a symbol exported with such a namespace is required to import the namespace via
MODULE_IMPORT_NS(). There is no technical reason to enforce correct namespace imports, but it creates consistency between symbols defining namespaces and users importing namespaces they make use of. This option relaxes this requirement and lifts the enforcement when loading a module.
That's a lot better. Especially moving the "This option relaxes..." to the bottom. Thanks.
-Saravana
Matthias Maennich
maintainerPATCH v2 6/10 export: allow definition default namespaces in Makefiles or sources
In reply to Matthias MaennichTo avoid excessive usage of EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), where MY_NAMESPACE will always be the namespace we are exporting to, allow exporting all definitions of EXPORT_SYMBOL() and friends by defining DEFAULT_SYMBOL_NAMESPACE.
For example, to export all symbols defined in usb-common into the namespace USB_COMMON, add a line like this to drivers/usb/common/Makefile:
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all EXPORT_SYMBOL(sym) definitions to EXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.
Another way of making use of this feature is to define the namespace within source or header files similar to how TRACE_SYSTEM defines are used:
#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
Please note that, as opposed to TRACE_SYSTEM, DEFAULT_SYMBOL_NAMESPACE has to be defined before including include/linux/export.h.
If DEFAULT_SYMBOL_NAMESPACE is defined, a symbol can still be exported to another namespace by using EXPORT_SYMBOL_NS() and friends with explicitly specifying the namespace.
--- include/linux/export.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/export.h +6 -0
@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Greg KH
maintainerRe: [PATCH v2 06/10] export: allow definition default namespaces in Makefiles or sources
Quoted 9 lines · Matthias Maennich
To avoid excessive usage of
EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), whereMY_NAMESPACEwill always be the namespace we are exporting to, allow exporting all definitions ofEXPORT_SYMBOL()and friends by definingDEFAULT_SYMBOL_NAMESPACE.For example, to export all symbols defined in usb-common into the namespace
USB_COMMON, add a line like this todrivers/usb/common/Makefile:ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
I thought we were trying to get away from cflags :(
Quoted 11 lines
That is equivalent to changing all
EXPORT_SYMBOL(sym)definitions toEXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.Another way of making use of this feature is to define the namespace within source or header files similar to how
TRACE_SYSTEMdefines are used:
#undefDEFAULT_SYMBOL_NAMESPACE
#defineDEFAULT_SYMBOL_NAMESPACEUSB_COMMON
Quoted 6 lines
Please note that, as opposed to
TRACE_SYSTEM,DEFAULT_SYMBOL_NAMESPACEhas to be defined before includinginclude/linux/export.h.If
DEFAULT_SYMBOL_NAMESPACEis defined, a symbol can still be exported to another namespace by usingEXPORT_SYMBOL_NS()and friends with explicitly specifying the namespace.
Ok, good, hopefully the cflags stuff will not be the default for people.
thanks,
greg k-h
Re: [PATCH v2 06/10] export: allow definition default namespaces in Makefiles or sources
In reply to Matthias MaennichQuoted 54 lines · Matthias Maennich
To avoid excessive usage of
EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), whereMY_NAMESPACEwill always be the namespace we are exporting to, allow exporting all definitions ofEXPORT_SYMBOL()and friends by definingDEFAULT_SYMBOL_NAMESPACE.For example, to export all symbols defined in usb-common into the namespace
USB_COMMON, add a line like this todrivers/usb/common/Makefile:ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all
EXPORT_SYMBOL(sym)definitions toEXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.Another way of making use of this feature is to define the namespace within source or header files similar to how
TRACE_SYSTEMdefines are used:
#undefDEFAULT_SYMBOL_NAMESPACE
#defineDEFAULT_SYMBOL_NAMESPACEUSB_COMMONPlease note that, as opposed to
TRACE_SYSTEM,DEFAULT_SYMBOL_NAMESPACEhas to be defined before includinginclude/linux/export.h.If
DEFAULT_SYMBOL_NAMESPACEis defined, a symbol can still be exported to another namespace by usingEXPORT_SYMBOL_NS()and friends with explicitly specifying the namespace.Suggested-by Arnd Bergmann <[email protected]>Reviewed-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- include/linux/export.h | 6 ++++++ 1 file changed, 6 insertions(+)include/linux/export.h +6
-0@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v2 7/10 modpost: add support for generating namespace dependencies
In reply to Matthias MaennichThis patch adds an option to modpost to generate a <module>.ns_deps file per module, containing the namespace dependencies for that module.
E.g. if the linked module my-module.ko would depend on the symbol myfunc.MY_NS in the namespace MY_NS, the my-module.ns_deps file created by modpost would contain the entry MY_NS to express the namespace dependency of my-module imposed by using the symbol myfunc.
These files can subsequently be used by static analysis tools (like coccinelle scripts) to address issues with missing namespace imports. A later patch of this series will introduce such a script 'nsdeps' and a corresponding make target to automatically add missing MODULE_IMPORT_NS() definitions to the module's sources. For that it uses the information provided in the generated .ns_deps files.
--- scripts/mod/modpost.c | 61 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 2 ++ 2 files changed, 58 insertions(+), 5 deletions(-)
scripts/mod/modpost.c +56 -5
@@ -38,6 +38,8 @@ static int sec_mismatch_count = 0;static int sec_mismatch_fatal =0 ;/* ignore missing files */ static int ignore_missing_files; +/* write namespace dependencies */ +static int write_namespace_deps;enum export { export_plain, export_unused, export_gpl,
@@ -2176,10 +2178,15 @@ static int check_exports(struct module *mod)else basename = mod->name; -if (exp->namespace && - !module_imports_namespace (mod, exp->namespace)) { -warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , - basename, exp->name, exp->namespace); +if (exp->namespace) { +add_namespace (&mod->required_namespaces, + exp->namespace); + +if (!write_namespace_deps && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } }if (!mod->gpl_compatible)
@@ -2481,6 +2488,38 @@ static void write_dump(const char *fname)free (buf.p); } +static void write_namespace_deps_files (void ) +{ +struct module *mod; +struct namespace_list *ns; +struct buffer ns_deps_buf = {}; + +for (mod = modules; mod; mod = mod->next) { +char fname[PATH_MAX ]; +const char *basename; + +if (mod->skip) +continue ; + + ns_deps_buf.pos =0 ; + +for (ns = mod->required_namespaces; ns; ns = ns->next) +buf_printf (&ns_deps_buf,"%s\n" , ns->namespace); + +if (ns_deps_buf.pos ==0 ) +continue ; + + basename =strrchr (mod->name,'/' ); +if (basename) + basename++; +else + basename = mod->name; + +sprintf (fname,".tmp_versions/%s.ns_deps" , basename); +write_if_changed (&ns_deps_buf, fname); + } +} +struct ext_sym_list {struct ext_sym_list *next;const char *file;
@@ -2497,7 +2536,7 @@ int main(int argc, char **argv)struct ext_sym_list *extsym_iter;struct ext_sym_list *extsym_start =NULL ; -while ((opt =getopt (argc, argv,"i:I:e:mnsT:o:awE" )) !=-1 ) { +while ((opt =getopt (argc, argv,"i:I:e:mnsT:o:awEd" )) !=-1 ) {switch (opt) {case 'i' : kernel_read = optarg;
@@ -2538,6 +2577,9 @@ int main(int argc, char **argv)case 'E' : sec_mismatch_fatal =1 ;break ; +case 'd' : + write_namespace_deps =1 ; +break ;default :exit (1 ); }
@@ -2572,6 +2614,9 @@ int main(int argc, char **argv) err |=check_modname_len (mod); err |=check_exports (mod); +if (write_namespace_deps) +continue ; +add_header (&buf, mod);add_intree_flag (&buf, !external_module);add_retpoline (&buf);
@@ -2584,6 +2629,12 @@ int main(int argc, char **argv)sprintf (fname,"%s.mod.c" , mod->name);write_if_changed (&buf, fname); } + +if (write_namespace_deps) { +write_namespace_deps_files (); +return 0 ; + } +if (dump_write)write_dump (dump_write);if (sec_mismatch_count && sec_mismatch_fatal)
scripts/mod/modpost.h +2 -0
@@ -126,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Required namespace dependencies +struct namespace_list *required_namespaces;// Actual imported namespaces struct namespace_list *imported_namespaces; };
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 07/10] modpost: add support for generating namespace dependencies
Quoted 15 lines · Matthias Maennich
This patch adds an option to modpost to generate a <module>.ns_deps file per module, containing the namespace dependencies for that module.
E.g. if the linked module my-module.ko would depend on the symbol myfunc.MY_NS in the namespace
MY_NS, the my-module.ns_deps file created by modpost would contain the entryMY_NSto express the namespace dependency of my-module imposed by using the symbol myfunc.These files can subsequently be used by static analysis tools (like coccinelle scripts) to address issues with missing namespace imports. A later patch of this series will introduce such a script 'nsdeps' and a corresponding make target to automatically add missing
MODULE_IMPORT_NS()definitions to the module's sources. For that it uses the information provided in the generated .ns_deps files.
Quoted 7 lines
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>--- scripts/mod/modpost.c | 61 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 2 ++ 2 files changed, 58 insertions(+), 5 deletions(-)
Matthias Maennich
maintainerPATCH v2 8/10 scripts: Coccinelle script for namespace dependencies.
In reply to Matthias MaennichA script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace with EXPORT_SYMBOL_NS() or define DEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
--- MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 54 +++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
MAINTAINERS +5 -0
@@ -11414,6 +11414,11 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git F: tools/include/nolibc/ +NSDEPS +M: Matthias Maennich <[email protected]> +S: Maintained +F: scripts/nsdeps + NTB AMD DRIVER M: Shyam Sundar S K <[email protected]> L: [email protected]
Makefile +12 -0
@@ -1500,6 +1500,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'
@@ -1687,6 +1690,15 @@ quiet_cmd_tags = GEN $@ tags TAGS cscope gtags: FORCE $(call cmd,tags) +# Script to generate missing namespace dependencies +# --------------------------------------------------------------------------- + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + # Scripts to check various things for consistency # ---------------------------------------------------------------------------
scripts/Makefile.modpost +3 -1
@@ -56,7 +56,8 @@ MODPOST = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) ifdef MODPOST_VMLINUX
@@ -134,6 +135,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: __modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------
scripts/coccinelle/misc/add_namespace.cocci new file +23 -0
@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +/// Adds missing MODULE_IMPORT_NS statements to source files +/// +/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to +/// add a missing namespace tag to a module source file. +/// + +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +// Add missing imports, but only adjacent to a MODULE_LICENSE statement. +// That ensures we are adding it only to the main module source file. +@do_import depends on !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);
scripts/nsdeps new file +54 -0
54 lines not on this page · raw message
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 08/10] scripts: Coccinelle script for namespace dependencies.
Quoted 12 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
Quoted 6 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Quoted 171 lines
--- MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 54 +++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdepsMAINTAINERS +5
-0@@ -11414,6 +11414,11 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git F: tools/include/nolibc/ +NSDEPS +M: Matthias Maennich <[email protected]> +S: Maintained +F: scripts/nsdeps + NTB AMD DRIVER M: Shyam Sundar S K <[email protected]> L: [email protected]Makefile +12
-0@@ -1500,6 +1500,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'@@ -1687,6 +1690,15 @@ quiet_cmd_tags = GEN $@ tags TAGS cscope gtags: FORCE $(call cmd,tags) +# Script to generate missing namespace dependencies +# --------------------------------------------------------------------------- + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + # Scripts to check various things for consistency # ---------------------------------------------------------------------------scripts/Makefile.modpost +3
-1@@ -56,7 +56,8 @@ MODPOST = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) ifdef MODPOST_VMLINUX@@ -134,6 +135,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: __modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------scripts/coccinelle/misc/add_namespace.cocci new file +23
-0@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +/// Adds missing MODULE_IMPORT_NS statements to source files +/// +/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to +/// add a missing namespace tag to a module source file. +/// + +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +// Add missing imports, but only adjacent to a MODULE_LICENSE statement. +// That ensures we are adding it only to the main module source file. +@do_import depends on !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);scripts/nsdeps new file +54
-1@@ -0,0 +1,54 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Linux kernel symbol namespace import generator +# +# This script requires at least spatch +# version 1.0.4. +SPATCH_REQ_VERSION="1.0.4" + +DIR="$(dirname $(readlink -f $0))/.." +SPATCH="`which ${SPATCH:=spatch}`" +if [ ! -x "$SPATCH" ]; then + echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' + exit 1 +fi + +SPATCH_REQ_VERSION_NUM=$(echo $SPATCH_REQ_VERSION | ${DIR}/scripts/ld-version.sh) +SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}') +SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh) + +if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then + echo 'spatch needs to be version 1.06 or higher' + exit 1 +fi + +generate_deps_for_ns() { + $SPATCH --very-quiet --in-place --sp-file \ + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 +} + +generate_deps() { + local mod_file=`echo $@ | sed -e 's/\.ns_deps/\.mod/'` + local mod_name=`cat $mod_file | sed -n 1p | sed -e 's/\/[^.]*$//'` + local mod_source_files=`cat $mod_file | sed -n 2p | sed -e 's/\.o/\.c/g'` + for ns in `cat $@`; do + echo "Adding namespace $ns to module $mod_name (if needed)." + generate_deps_for_ns $ns $mod_source_files + # sort the imports + for source_file in $mod_source_files; do + sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp + offset=$(wc -l ${source_file}.tmp | awk '{print $1;}') + cat $source_file | grep MODULE_IMPORT_NS | sort -u >> ${source_file}.tmp + tail -n +$((offset +1)) ${source_file} | grep -v MODULE_IMPORT_NS >> ${source_file}.tmp + if ! diff -q ${source_file} ${source_file}.tmp; then + mv ${source_file}.tmp ${source_file} + else + rm ${source_file}.tmp + fi + done + done +} + +for f in `find $srctree/.tmp_versions/ -name *.ns_deps`; do + generate_deps $f +done --2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v2 08/10] scripts: Coccinelle script for namespace dependencies.
In reply to Matthias MaennichQuoted 12 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
Quoted 7 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
I really can't express just how cool this patch is. I was amazed when I first saw it in action a long time ago, and still am.
Re: [Cocci] [PATCH v2 08/10] scripts: Coccinelle script for namespace dependencies.
In reply to Matthias MaennichQuoted 12 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
Quoted 7 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
[]
Quoted 8 lines
MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 54 +++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
[]
scripts/nsdeps line 21
Quoted 2 lines
scripts/nsdeps new file +2
-0+if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then + echo 'spatch needs to be version 1.06 or higher'
Nitpick: 1.0.6
Quoted 2 lines
(quoted diff) +2
-0+ exit 1 +fi
Signature · 4 lines
Himanshu Jha Undergraduate Student Department of Electronics & Communication Guru Tegh Bahadur Institute of Technology
Matthias Maennich
maintainerRe: [Cocci] [PATCH v2 08/10] scripts: Coccinelle script for namespace dependencies.
Quoted 32 lines · Himanshu Jha
Quoted 12 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' file generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.Quoted 7 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
[]
Quoted 8 lines
MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 54 +++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
Quoted 7 lines
[]
scripts/nsdeps line 21
Quoted 2 lines
scripts/nsdeps new file +2
-0+if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then + echo 'spatch needs to be version 1.06 or higher'Nitpick: 1.0.6
Good catch! Thanks!
Actually it needs to be even 1.0.4, so I will just use $SPATCH_REQ_VERSION from above.
Quoted 9 lines
Quoted 2 lines
(quoted diff) +2
-0+ exit 1 +fiSignature · 4 lines
Himanshu Jha Undergraduate Student Department of Electronics & Communication Guru Tegh Bahadur Institute of Technology
Re: [Cocci] [v2 08/10] scripts: Coccinelle script for namespace dependencies
In reply to Matthias Maennich+# This script requires at least spatch
+# version 1.0.4.
How do you think about to avoid the duplicate specification of this identification?
Regards,
Markus
Matthias Maennich
maintainerRe: [Cocci] [v2 08/10] scripts: Coccinelle script for namespace dependencies
Quoted 5 lines · Markus Elfring
scripts/nsdeps new file +2
-0+# This script requires at least spatch +# version 1.0.4.How do you think about to avoid the duplicate specification of this identification?
That is a good idea. I will reduce the patch to
+# This script requires a minimum spatch version.
+SPATCH_REQ_VERSION="1.0.4"
and use $SPATCH_REQ_VERSION when diagnosing this issue further down.
Cheers,
Matthias
Re: [v2 08/10] scripts: Coccinelle script for namespace dependencies
In reply to Matthias Maennichscripts/nsdeps line 28
Quoted 4 lines
scripts/nsdeps new file +4
-0+generate_deps_for_ns() { + $SPATCH --very-quiet --in-place --sp-file \ + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 +}
* Where will the variable “srctree” be set for the file “scripts/nsdeps”?
* Would you like to support a separate build directory for desired adjustments?
* How do you think about to check error handling around such commands?
Quoted 1 line
+generate_deps() {
…
scripts/nsdeps line 39
Quoted 2 lines
scripts/nsdeps new file +2
-0+ for source_file in $mod_source_files; do + sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp
…
I suggest to assign the name for the temporary file to a variable which should be used by subsequent commands.
Regards,
Markus
Matthias Maennich
maintainerRe: [v2 08/10] scripts: Coccinelle script for namespace dependencies
Quoted 7 lines · Markus Elfring
scripts/nsdeps line 28
Quoted 4 lines
scripts/nsdeps new file +4
-0+generate_deps_for_ns() { + $SPATCH --very-quiet --in-place --sp-file \ + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 +}* Where will the variable “srctree” be set for the file “scripts/nsdeps”?
$srctree is defined by kbuild in the toplevel Makefile.
Quoted 2 lines
* Would you like to support a separate build directory for desired adjustments?
No, as the purpose of this script is to directly patch the kernel sources where applicable.
Quoted 3 lines
* How do you think about to check error handling around such commands?
spatch emits a descriptive message on error. I will add a 'set -e' to the script so that it aborts on errors.
Quoted 8 lines
Quoted 1 line
+generate_deps() {
…
scripts/nsdeps line 39
Quoted 2 lines
scripts/nsdeps new file +2
-0+ for source_file in $mod_source_files; do + sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp…
I suggest to assign the name for the temporary file to a variable which should be used by subsequent commands.
I somehow don't agree that this is an improvement to the code as the variable would likely be something like ${source_file_tmp}. Sticking to ${source_file}.tmp does express the intent of a temporary file next to the original source file and the reader of the code does not need to reason about the value of ${source_file_tmp}.
Cheers,
Matthias
Re: [v2 08/10] scripts: Coccinelle script for namespace dependencies
Quoted 1 line
$srctree is defined by kbuild in the toplevel
Makefile.
How is this variable passed to the file “scripts/nsdeps”?
Quoted 4 lines
Quoted 1 line
* Would you like to support a separate build directory for desired adjustments?
No, as the purpose of this script is to directly patch the kernel sources where applicable.
Will there occasionally be a need to provide a generated patch (without in-place file modification)?
Quoted 5 lines
Quoted 2 lines
I suggest to assign the name for the temporary file to a variable which should be used by subsequent commands.
I somehow don't agree that this is an improvement to the code as the variable would likely be something like ${source_file_tmp}.
Would you dare to choose a shorter variable name?
Quoted 3 lines
${source_file}.tmp does express the intent of a temporary file next to the original source file and the reader of the code does not need to reason about the value of ${source_file_tmp}.
I would find a code variant with less suffix repetition nicer.
Regards,
Markus
Matthias Maennich
maintainerPATCH v2 9/10 usb-storage: remove single-use define for debugging
In reply to Matthias MaennichUSB_STORAGE was defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.
--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
drivers/usb/storage/debug.h +0 -2
@@ -29,8 +29,6 @@#include <linux/kernel.h> -#define USB_STORAGE "usb-storage: " -#ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command (const struct us_data *us,struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key,
drivers/usb/storage/scsiglue.c +1 -1
@@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,/* check for state-transition errors */ if (us->srb !=NULL ) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", +printk (KERN_ERR "usb-storage: Error in %s: us->srb = %p\n" , __func__, us->srb);return SCSI_MLQUEUE_HOST_BUSY ; }
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Greg KH
maintainerRe: [PATCH v2 09/10] usb-storage: remove single-use define for debugging
Quoted 10 lines · Matthias Maennich
USB_STORAGEwas defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.Signed-off-by Matthias Maennich <[email protected]>--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
I'll go take this today. The module really should just be using dev_err() there. It needs to be cleaned up :(
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v2 09/10] usb-storage: remove single-use define for debugging
Quoted 6 lines · Greg KH
Quoted 5 lines · Matthias Maennich
USB_STORAGEwas defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.
Quoted 8 lines
Quoted 5 lines
Signed-off-by Matthias Maennich <[email protected]>--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)I'll go take this today. The module really should just be using
dev_err()there. It needs to be cleaned up :(
Now applied to the usb git tree, thanks.
greg k-h
Matthias Maennich
maintainerPATCH v2 10/10 RFC: usb-storage: export symbols in USB_STORAGE namespace
In reply to Matthias MaennichModules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define DDEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Instead of a DEFAULT_SYMBOL_NAMESPACE definition, the EXPORT_SYMBOL_NS variants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respective EXPORT_SYMBOL macro expansion.
--- drivers/usb/storage/Makefile | 2 ++ drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + 15 files changed, 16 insertions(+)
drivers/usb/storage/Makefile +2 -0
@@ -8,6 +8,8 @@ ccflags-y := -I $(srctree)/drivers/scsi +ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE + obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o
drivers/usb/storage/alauda.c +1 -0
@@ -36,6 +36,7 @@MODULE_DESCRIPTION ("Driver for Alauda-based card readers" );MODULE_AUTHOR ("Daniel Drake <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * Status bytes
drivers/usb/storage/cypress_atacb.c +1 -0
@@ -22,6 +22,7 @@MODULE_DESCRIPTION ("SAT support for Cypress USB/ATA bridges with ATACB" );MODULE_AUTHOR ("Matthieu Castet <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/datafab.c +1 -0
@@ -54,6 +54,7 @@MODULE_DESCRIPTION ("Driver for Datafab USB Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );struct datafab_info {unsigned long sectors;/* total sector count */
drivers/usb/storage/ene_ub6250.c +1 -0
@@ -26,6 +26,7 @@MODULE_DESCRIPTION ("Driver for ENE UB6250 reader" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_FIRMWARE (SD_INIT1_FIRMWARE );MODULE_FIRMWARE (SD_INIT2_FIRMWARE );MODULE_FIRMWARE (SD_RW_FIRMWARE );
drivers/usb/storage/freecom.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for Freecom USB/IDE adaptor" );MODULE_AUTHOR ("David Brown <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (struct us_data *us,void *ibuffer,int length);
drivers/usb/storage/isd200.c +1 -0
@@ -53,6 +53,7 @@MODULE_DESCRIPTION ("Driver for In-System Design, Inc. ISD200 ASIC" );MODULE_AUTHOR ("Björn Stenberg <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int isd200_Initialization (struct us_data *us);
drivers/usb/storage/jumpshot.c +1 -0
@@ -51,6 +51,7 @@MODULE_DESCRIPTION ("Driver for Lexar \"Jumpshot\" Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/karma.c +1 -0
@@ -23,6 +23,7 @@MODULE_DESCRIPTION ("Driver for Rio Karma" );MODULE_AUTHOR ("Bob Copeland <[email protected]>, Keith Bennett <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define RIO_PREFIX "RIOP\x00"#define RIO_PREFIX_LEN 5
drivers/usb/storage/onetouch.c +1 -0
@@ -25,6 +25,7 @@MODULE_DESCRIPTION ("Maxtor USB OneTouch hard drive button driver" );MODULE_AUTHOR ("Nick Sillik <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define ONETOUCH_PKT_LEN 0x02#define ONETOUCH_BUTTON KEY_PROG1
drivers/usb/storage/realtek_cr.c +1 -0
@@ -35,6 +35,7 @@MODULE_DESCRIPTION ("Driver for Realtek USB Card Reader" );MODULE_AUTHOR ("wwang <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int auto_delink_en =1 ;module_param (auto_delink_en, int,S_IRUGO |S_IWUSR );
drivers/usb/storage/sddr09.c +1 -0
@@ -47,6 +47,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-09 SmartMedia reader" );MODULE_AUTHOR ("Andries Brouwer <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int usb_stor_sddr09_dpcm_init (struct us_data *us);static int sddr09_transport (struct scsi_cmnd *srb,struct us_data *us);
drivers/usb/storage/sddr55.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-55 SmartMedia reader" );MODULE_AUTHOR ("Simon Munton" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/shuttle_usbat.c +1 -0
@@ -48,6 +48,7 @@MODULE_DESCRIPTION ("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable" );MODULE_AUTHOR ("Daniel Drake <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* Supported device types */ #define USBAT_DEV_HP8200 0x01
drivers/usb/storage/uas.c +1 -0
@@ -1219,5 +1219,6 @@ static struct usb_driver uas_driver = {module_usb_driver (uas_driver);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_AUTHOR ("Hans de Goede <[email protected]>, Matthew Wilcox and Sarah Sharp" );
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Greg KH
maintainerRe: [PATCH v2 10/10] RFC: usb-storage: export symbols in USB_STORAGE namespace
Quoted 38 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DDEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdepsInstead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.Signed-off-by Matthias Maennich <[email protected]>--- drivers/usb/storage/Makefile | 2 ++ drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + 15 files changed, 16 insertions(+)drivers/usb/storage/Makefile +0
-0
drivers/usb/storage/Makefile line 11
Quoted 4 lines
drivers/usb/storage/Makefile +1
-0@@ -8,6 +8,8 @@ ccflags-y := -I $(srctree)/drivers/scsi +ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE
Wait, we have to do this for every subsystem? I thought there was a macro we could use in the code itself for this. What changed from earlier versions, or was this always here?
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH v2 10/10] RFC: usb-storage: export symbols in USB_STORAGE namespace
In reply to Matthias MaennichQuoted 8 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DDEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Quoted 5 lines
Instead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.
Ok, I can't read text, this answers my previous question.
But, as an example, shouldn't we also have some code here that uses the EXPORT_SYMBOL_NS() macro to ensure that it actually works?
thanks,
greg k-h
Matthias Maennich
maintainerRe: [PATCH v2 10/10] RFC: usb-storage: export symbols in USB_STORAGE namespace
Quoted 15 lines · Greg KH
Quoted 8 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DDEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdepsQuoted 5 lines
Instead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.
Quoted 5 lines
Ok, I can't read text, this answers my previous question.
But, as an example, shouldn't we also have some code here that uses the
EXPORT_SYMBOL_NS()macro to ensure that it actually works?
I will create another patch for a different subsystem where the use of the macros is more appropriate. Then we have both use cases covered.
Cheers,
Matthias
Matthias Maennich
maintainerv3 cover Symbol Namespaces
In reply to Matthias MaennichAs of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree use
When module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "SUBSYSTEM_DEBUG" namespace.
I continued the work mainly done by Martijn Coenen.
Changes in v2:
- Rather than adding and evaluating separate sections __knsimport_NS, use modinfo tags to declare the namespaces a module introduces. Adjust modpost and the module loader accordingly.
- Also add support for reading multiple modinfo values for the same tag to allow list-like access to modinfo tags.
- The macros in export.h have been cleaned up to avoid redundancy in the macro parameters (ns, nspost, nspost2).
- The introduction of relative references in the ksymtab entries caused a rework of the macros to accommodate that configuration as well.
- Alignment of kernel_symbol in the ksymtab needed to be fixed to allow growing the kernel_symbol struct.
- Modpost does now also append the namespace suffix to the symbol entries in Module.symvers.
- The configuration option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS allows relaxing the enforcement of properly declared namespace imports at module loading time.
- Symbols can be collectively exported into a namespace by defining DEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile.
- The requirement for a very recent coccinelle spatch has been lifted by simplifying the script.
- nsdeps does now ensures MODULE_IMPORT_NS statements are sorted when patching the module source files.
- Some minor bugs have been addressed in nsdeps to allow it to work with modules that have more than one source file.
- The RFC for the usb-storage symbols has been simplified by using DEFAULT_SYMBOL_NAMESPACE=USB_STORAGE rather than explicitly exporting each and every symbol into that new namespace.
Changes in v3:
- Reword the documentation for the MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS option for clarification.
- Fix printed required version of spatch in coccinelle script.
- Adopt kbuild changes for modpost: .mod files are no longer generated in .tmp_versions. Similarely, generate the .ns_deps files in the tree along with the .mod files. Also, nsdeps now uses modules.order as source for the list modules to consider.
- Add an RFC patch to introduce the namespace WATCHDOG_CORE for symbols exported in watchdog_core.c.
This patch series was developed against Linus' master (15d90b242290).
[1] git grep "^EXPORT_SYMBOL\w*(" v5.3-rc5 | wc -l
[2] git grep "^EXPORT_SYMBOL\w*(" v4.17 | wc -l
Matthias Maennich (11):
module: support reading multiple values per modinfo tag
export: explicitly align struct kernel_symbol
module: add support for symbol namespaces.
modpost: add support for symbol namespaces
module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
export: allow definition default namespaces in Makefiles or sources
modpost: add support for generating namespace dependencies
scripts: Coccinelle script for namespace dependencies.
usb-storage: remove single-use define for debugging
RFC: usb-storage: export symbols in USB_STORAGE namespace
RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
.gitignore | 1 + MAINTAINERS | 5 + Makefile | 14 +- arch/m68k/include/asm/export.h | 1 - drivers/hwmon/ftsteutates.c | 1 + drivers/hwmon/sch56xx-common.c | 1 + drivers/rtc/rtc-abx80x.c | 1 + drivers/usb/storage/Makefile | 2 + drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/debug.h | 2 - drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + drivers/watchdog/armada_37xx_wdt.c | 1 + drivers/watchdog/asm9260_wdt.c | 1 + drivers/watchdog/aspeed_wdt.c | 1 + drivers/watchdog/at91sam9_wdt.c | 1 + drivers/watchdog/atlas7_wdt.c | 1 + drivers/watchdog/bcm2835_wdt.c | 1 + drivers/watchdog/bcm47xx_wdt.c | 1 + drivers/watchdog/bcm7038_wdt.c | 1 + drivers/watchdog/bcm_kona_wdt.c | 1 + drivers/watchdog/bd70528_wdt.c | 1 + drivers/watchdog/cadence_wdt.c | 1 + drivers/watchdog/da9052_wdt.c | 1 + drivers/watchdog/da9055_wdt.c | 1 + drivers/watchdog/da9062_wdt.c | 1 + drivers/watchdog/da9063_wdt.c | 1 + drivers/watchdog/davinci_wdt.c | 1 + drivers/watchdog/digicolor_wdt.c | 1 + drivers/watchdog/dw_wdt.c | 1 + drivers/watchdog/ebc-c384_wdt.c | 1 + drivers/watchdog/ep93xx_wdt.c | 1 + drivers/watchdog/ftwdt010_wdt.c | 1 + drivers/watchdog/gpio_wdt.c | 1 + drivers/watchdog/hpwdt.c | 1 + drivers/watchdog/i6300esb.c | 1 + drivers/watchdog/iTCO_wdt.c | 1 + drivers/watchdog/ie6xx_wdt.c | 1 + drivers/watchdog/imgpdc_wdt.c | 1 + drivers/watchdog/imx2_wdt.c | 1 + drivers/watchdog/intel-mid_wdt.c | 1 + drivers/watchdog/it87_wdt.c | 1 + drivers/watchdog/kempld_wdt.c | 1 + drivers/watchdog/lpc18xx_wdt.c | 1 + drivers/watchdog/max63xx_wdt.c | 1 + drivers/watchdog/max77620_wdt.c | 1 + drivers/watchdog/mei_wdt.c | 1 + drivers/watchdog/mena21_wdt.c | 1 + drivers/watchdog/menf21bmc_wdt.c | 1 + drivers/watchdog/menz69_wdt.c | 1 + drivers/watchdog/meson_gxbb_wdt.c | 1 + drivers/watchdog/meson_wdt.c | 1 + drivers/watchdog/mlx_wdt.c | 1 + drivers/watchdog/moxart_wdt.c | 1 + drivers/watchdog/mtk_wdt.c | 1 + drivers/watchdog/ni903x_wdt.c | 1 + drivers/watchdog/nic7018_wdt.c | 1 + drivers/watchdog/npcm_wdt.c | 1 + drivers/watchdog/of_xilinx_wdt.c | 1 + drivers/watchdog/omap_wdt.c | 1 + drivers/watchdog/pm8916_wdt.c | 1 + drivers/watchdog/qcom-wdt.c | 1 + drivers/watchdog/rave-sp-wdt.c | 1 + drivers/watchdog/renesas_wdt.c | 1 + drivers/watchdog/retu_wdt.c | 1 + drivers/watchdog/rn5t618_wdt.c | 1 + drivers/watchdog/rza_wdt.c | 1 + drivers/watchdog/s3c2410_wdt.c | 1 + drivers/watchdog/sama5d4_wdt.c | 1 + drivers/watchdog/sirfsoc_wdt.c | 1 + drivers/watchdog/softdog.c | 1 + drivers/watchdog/sp5100_tco.c | 1 + drivers/watchdog/sprd_wdt.c | 1 + drivers/watchdog/st_lpc_wdt.c | 1 + drivers/watchdog/stmp3xxx_rtc_wdt.c | 1 + drivers/watchdog/stpmic1_wdt.c | 1 + drivers/watchdog/sunxi_wdt.c | 1 + drivers/watchdog/tangox_wdt.c | 1 + drivers/watchdog/tegra_wdt.c | 1 + drivers/watchdog/tqmx86_wdt.c | 1 + drivers/watchdog/ts4800_wdt.c | 1 + drivers/watchdog/ts72xx_wdt.c | 1 + drivers/watchdog/twl4030_wdt.c | 1 + drivers/watchdog/uniphier_wdt.c | 1 + drivers/watchdog/via_wdt.c | 1 + drivers/watchdog/w83627hf_wdt.c | 1 + drivers/watchdog/watchdog_core.c | 10 +- drivers/watchdog/wdat_wdt.c | 1 + drivers/watchdog/wm831x_wdt.c | 1 + drivers/watchdog/wm8350_wdt.c | 1 + drivers/watchdog/xen_wdt.c | 1 + drivers/watchdog/ziirave_wdt.c | 1 + include/asm-generic/export.h | 14 +- include/linux/export.h | 92 +++++++++++-- include/linux/module.h | 2 + init/Kconfig | 13 ++ kernel/module.c | 67 +++++++++- scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 ++++ scripts/mod/modpost.c | 137 ++++++++++++++++++-- scripts/mod/modpost.h | 9 ++ scripts/nsdeps | 56 ++++++++ 114 files changed, 504 insertions(+), 46 deletions(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 1/11 module: support reading multiple values per modinfo tag
Similar to modpost's get_next_modinfo(), introduce get_next_modinfo() in kernel/module.c to acquire any further values associated with the same modinfo tag name. That is useful for any tags that have multiple occurrences (such as 'alias'), but is in particular introduced here as part of the symbol namespaces patch series to read the (potentially) multiple namespaces a module is importing.
--- kernel/module.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
kernel/module.c +15 -2
@@ -2481,7 +2481,8 @@ static char *next_string(char *string, unsigned long *secsize)return string; } -static char *get_modinfo (struct load_info *info,const char *tag) +static char *get_next_modinfo (const struct load_info *info,const char *tag, +char *prev) {char *p;unsigned int taglen =strlen (tag);
@@ -2492,13 +2493,25 @@ static char *get_modinfo(struct load_info *info, const char *tag)* get_modinfo() calls made before rewrite_section_headers() * must use sh_offset, as sh_addr isn't set! */ -for (p = (char *)info->hdr + infosec->sh_offset; p; p =next_string (p, &size)) { +char *modinfo = (char *)info->hdr + infosec->sh_offset; + +if (prev) { + size -= prev - modinfo; + modinfo =next_string (prev, &size); + } + +for (p = modinfo; p; p =next_string (p, &size)) {if (strncmp (p, tag, taglen) ==0 && p[taglen] =='=' )return p + taglen +1 ; }return NULL ; } +static char *get_modinfo (const struct load_info *info,const char *tag) +{ +return get_next_modinfo (info, tag,NULL ); +} +static void setup_modinfo (struct module *mod,struct load_info *info) {struct module_attribute *attr;
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 2/11 export: explicitly align struct kernel_symbol
In reply to Matthias MaennichThis change allows growing struct kernel_symbol without wasting bytes to alignment. It also concretized the alignment of ksymtab entries if relative references are used for ksymtab entries.
struct kernel_symbol was already implicitly being aligned to the word size, except on x86_64 and m68k, where it is aligned to 16 and 2 bytes, respectively.
As far as I can tell there is no requirement for aligning struct kernel_symbol to 16 bytes on x86_64, but gcc aligns structs to their size, and the linker aligns the custom __ksymtab sections to the largest data type contained within, so setting KSYM_ALIGN to 16 was necessary to stay consistent with the code generated for non-ASM EXPORT_SYMBOL(). Now that non-ASM EXPORT_SYMBOL() explicitly aligns to word size (8), KSYM_ALIGN is no longer necessary.
In case of relative references, the alignment has been changed accordingly to not waste space when adding new struct members.
As for m68k, struct kernel_symbol is aligned to 2 bytes even though the structure itself is 8 bytes; using a 4-byte alignment shouldn't hurt.
I manually verified the output of the __ksymtab sections didn't change on x86, x86_64, arm, arm64 and m68k. As expected, the section contents didn't change, and the ELF section alignment only changed on x86_64 and m68k. Feedback from other archs more than welcome.
--- arch/m68k/include/asm/export.h | 1 - include/asm-generic/export.h | 8 +++----- include/linux/export.h | 3 ++- 3 files changed, 5 insertions(+), 7 deletions(-)
arch/m68k/include/asm/export.h +0 -1
@@ -1,3 +1,2 @@ -#define KSYM_ALIGN 2#define KCRC_ALIGN 2#include <asm-generic/export.h>
include/asm-generic/export.h +3 -5
@@ -4,15 +4,13 @@#ifndef KSYM_FUNC #define KSYM_FUNC (x) x#endif -#ifdef CONFIG_64BIT -#ifndef KSYM_ALIGN +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +#define KSYM_ALIGN 4 +#elif defined(CONFIG_64BIT )#define KSYM_ALIGN 8 -#endif #else -#ifndef KSYM_ALIGN #define KSYM_ALIGN 4#endif -#endif #ifndef KCRC_ALIGN #define KCRC_ALIGN 4#endif
include/linux/export.h +2 -1
@@ -52,7 +52,7 @@ extern struct module __this_module;#define __KSYMTAB_ENTRY (sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ - " .balign 8 \n" \ + " .balign 4 \n" \ "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \
@@ -66,6 +66,7 @@ struct kernel_symbol {#define __KSYMTAB_ENTRY (sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ = { (unsigned long)&sym, __kstrtab_##sym }struct kernel_symbol {
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 3/11 module: add support for symbol namespaces.
In reply to Matthias MaennichThe 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.
--- include/asm-generic/export.h | 6 +-- include/linux/export.h | 85 ++++++++++++++++++++++++++++++------ include/linux/module.h | 2 + kernel/module.c | 43 ++++++++++++++++++ 4 files changed, 120 insertions(+), 16 deletions(-)
include/asm-generic/export.h +3 -3
@@ -17,11 +17,11 @@ .macro __put, val, name#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - .long \val - ., \name - . + .long \val - ., \name - ., 0 - .#elif defined(CONFIG_64BIT ) - .quad \val, \name + .quad \val, \name, 0#else - .long \val, \name + .long \val, \name, 0#endif .endm
include/linux/export.h +72 -13
151 lines not on this page · raw message
include/linux/module.h +2 -0
@@ -280,6 +280,8 @@ struct notifier_block;#ifdef CONFIG_MODULES +#define MODULE_IMPORT_NS (ns) MODULE_INFO(import_ns, #ns) +extern int modules_disabled;/* for sysctl */ /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get (const char *symbol);
kernel/module.c +43 -0
61 lines not on this page · raw message
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 03/11] module: add support for symbol namespaces.
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 100 lines
The
EXPORT_SYMBOL_NS()andEXPORT_SYMBOL_NS_GPL()macros can be used to export a symbol to a specific namespace. There are no_GPL_FUTUREand_UNUSEDvariants 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 andkernel/module.cat 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 namespaceUSB_STORAGEbecomes '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 structkernel_symbols.On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
include/asm-generic/export.h | 6 +-- include/linux/export.h | 85 ++++++++++++++++++++++++++++++------ include/linux/module.h | 2 + kernel/module.c | 43 ++++++++++++++++++ 4 files changed, 120 insertions(+), 16 deletions(-)include/asm-generic/export.h +0
-0@@ -17,11 +17,11 @@.macro
__put, val, name
#ifdefCONFIG_HAVE_ARCH_PREL32_RELOCATIONSinclude/asm-generic/export.h +1
-1- .long \val - ., \name - . + .long \val - ., \name - ., 0 - .#elif
defined(CONFIG_64BIT)include/asm-generic/export.h +1
-1- .quad \val, \name + .quad \val, \name, 0#else
include/asm-generic/export.h +1
-1- .long \val, \name + .long \val, \name, 0#endif
.endminclude/linux/export.h +13
-0@@ -20,6 +20,8 @@ extern struct module __this_module;#ifdef CONFIG_MODULES +#define NS_SEPARATOR "." +#if defined(__KERNEL__) && !defined(__GENKSYMS__)#ifdef CONFIG_MODVERSIONS /* Mark the CRC weak since genksyms apparently decides not to @@ -49,6 +51,16 @@ extern struct module __this_module;* absolute relocations that require runtime processing on relocatable * kernels. */ +#define __KSYMTAB_ENTRY_NS (sym, sec, ns) \ + __ADDRESSABLE(sym) \ + asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ + " .balign 4 \n" \ + "__ksymtab_" #sym NS_SEPARATOR #ns ": \n" \ + " .long " #sym "- . \n" \ + " .long __kstrtab_" #sym "- . \n" \ + " .long __kstrtab_ns_" #sym "- . \n" \ + " .previous \n") +#define __KSYMTAB_ENTRY (sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \@@ -56,32 +68,53 @@ extern struct module __this_module; "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \ + " .long 0 - . \n" \ " .previous \n")struct kernel_symbol {int value_offset;
include/linux/export.h extern struct module __this_module; · line 85
Quoted 10 lines
include/linux/export.h +7
-0int name_offset; + int namespace_offset; };#else +#define __KSYMTAB_ENTRY_NS (sym, sec, ns) \ + static const struct kernel_symbol __ksymtab_##sym##__##ns \ + asm("__ksymtab_" #sym NS_SEPARATOR #ns) \ + __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ + = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym}
Style nit: missing space after __kstrtab_ns_##sym.
Quoted 15 lines
include/linux/export.h +4
-1+#define __KSYMTAB_ENTRY (sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ + asm("__ksymtab_" #sym) \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ __aligned(sizeof(void *)) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym, NULL }struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; };#endif
include/linux/export.h extern struct module __this_module; · line 106
Quoted 10 lines
include/linux/export.h +2
-3-/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___export_symbol_common (sym, sec) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ - = #sym; \ + = #sym \
Any particular reason for this change? Not that it's important, just noticing the inconsistent inclusion of the semicolon in some of the macros (e.g. __CRC_SYMBOL includes it but __export_symbol_common doesn't).
Quoted 156 lines
include/linux/export.h +46
-9+ +/* For every exported symbol, place a struct in the __ksymtab section */ +#define ___EXPORT_SYMBOL_NS (sym, sec, ns) \ + ___export_symbol_common(sym, sec); \ + static const char __kstrtab_ns_##sym[] \ + __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ + = #ns; \ + __KSYMTAB_ENTRY_NS(sym, sec, ns) + +#define ___EXPORT_SYMBOL (sym, sec) \ + ___export_symbol_common(sym, sec); \ __KSYMTAB_ENTRY(sym, sec)#if defined(__DISABLE_EXPORTS)@@ -91,6 +124,7 @@ struct kernel_symbol {* be reused in other execution contexts such as the UEFI stub or the * decompressor. */ +#define __EXPORT_SYMBOL_NS (sym, sec, ns)#define __EXPORT_SYMBOL (sym, sec)#elif defined(CONFIG_TRIM_UNUSED_KSYMS )@@ -117,18 +151,26 @@ struct kernel_symbol {#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec)#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL_NS (sym, sec, ns) \ + __ksym_marker(sym); \ + __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) +#define __cond_export_ns_sym (sym, sec, ns, conf) \ + ___cond_export_ns_sym(sym, sec, ns, conf) +#define ___cond_export_ns_sym (sym, sec, ns, enabled) \ + __cond_export_ns_sym_##enabled(sym, sec, ns) +#define __cond_export_ns_sym_1 (sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns) +#define __cond_export_ns_sym_0 (sym, sec, ns)/* nothing */ +#else +#define __EXPORT_SYMBOL_NS ___EXPORT_SYMBOL_NS#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif -#define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") - -#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") - -#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "") +#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future") +#define EXPORT_SYMBOL_NS (sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns)#ifdef CONFIG_UNUSED_SYMBOLS #define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused")@@ -138,11 +180,28 @@ struct kernel_symbol {#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)include/linux/module.h +2
-0@@ -280,6 +280,8 @@ struct notifier_block;#ifdef CONFIG_MODULES +#define MODULE_IMPORT_NS (ns) MODULE_INFO(import_ns, #ns) +extern int
modules_disabled; /* for sysctl */ /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get(const char *symbol);kernel/module.c +37
-0@@ -544,6 +544,15 @@ static const char *kernel_symbol_name(const struct kernel_symbol *sym)#endif } +static const char *kernel_symbol_namespace (const struct kernel_symbol *sym) +{ +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +return offset_to_ptr (&sym->namespace_offset); +#else +return sym->namespace; +#endif +} +static int cmp_name (const void *va,const void *vb) {const char *a;@@ -1379,6 +1388,34 @@ static inline int same_magic(const char *amagic, const char *bmagic, }#endif /* CONFIG_MODVERSIONS */ +static char *get_modinfo (const struct load_info *info,const char *tag); +static char *get_next_modinfo (const struct load_info *info,const char *tag, +char *prev); + +static int verify_namespace_is_imported (const struct load_info *info, +const struct kernel_symbol *sym, +struct module *mod) +{ +const char *namespace; +char *imported_namespace; + + namespace =kernel_symbol_namespace (sym); +if (namespace) { + imported_namespace =get_modinfo (info,"import_ns" ); +while (imported_namespace) { +if (strcmp (namespace, imported_namespace) ==0 ) +return 0 ; + imported_namespace =get_next_modinfo ( + info,"import_ns" , imported_namespace); + } +pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name,kernel_symbol_name (sym), namespace); +return -EINVAL ; + } +return 0 ; +} + +/* Resolve a symbol for this module. I.e. if we find one, record usage. */ static const struct kernel_symbol *resolve_symbol(struct module *mod, const struct load_info *info,
kernel/module.c static const struct kernel_symbol *resolve_symbol(struct module *mod, · line 1457
Quoted 8 lines
kernel/module.c +5
-0@@ -1413,6 +1450,12 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } + err =verify_namespace_is_imported (info, sym, mod); +if (err) { + sym =ERR_PTR (err); + goto getname; + }
I think we should verify the namespace before taking a reference to the owner module (just swap the verify_namespace_is_imported() and ref_module() calls here).
Other than that, this patch looks good. Thanks!
Quoted 7 lines
kernel/module.c +1
-0+getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerRe: [PATCH v3 03/11] module: add support for symbol namespaces.
Quoted 130 lines · Jessica Yu
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 100 lines
The
EXPORT_SYMBOL_NS()andEXPORT_SYMBOL_NS_GPL()macros can be used to export a symbol to a specific namespace. There are no_GPL_FUTUREand_UNUSEDvariants 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 andkernel/module.cat 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 namespaceUSB_STORAGEbecomes '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 structkernel_symbols.On
x86_64I 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 'structnamespaced_kernel_symbol' for that section, at the cost of making the module loader more complex.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
include/asm-generic/export.h | 6 +-- include/linux/export.h | 85 ++++++++++++++++++++++++++++++------ include/linux/module.h | 2 + kernel/module.c | 43 ++++++++++++++++++ 4 files changed, 120 insertions(+), 16 deletions(-)include/asm-generic/export.h +0
-0@@ -17,11 +17,11 @@.macro
__put, val, name
#ifdefCONFIG_HAVE_ARCH_PREL32_RELOCATIONSinclude/asm-generic/export.h +1
-1- .long \val - ., \name - . + .long \val - ., \name - ., 0 - .#elif
defined(CONFIG_64BIT)include/asm-generic/export.h +1
-1- .quad \val, \name + .quad \val, \name, 0#else
include/asm-generic/export.h +1
-1- .long \val, \name + .long \val, \name, 0#endif
.endminclude/linux/export.h +13
-0@@ -20,6 +20,8 @@ extern struct module __this_module;#ifdef CONFIG_MODULES +#define NS_SEPARATOR "." +#if defined(__KERNEL__) && !defined(__GENKSYMS__)#ifdef CONFIG_MODVERSIONS /* Mark the CRC weak since genksyms apparently decides not to @@ -49,6 +51,16 @@ extern struct module __this_module;* absolute relocations that require runtime processing on relocatable * kernels. */ +#define __KSYMTAB_ENTRY_NS (sym, sec, ns) \ + __ADDRESSABLE(sym) \ + asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ + " .balign 4 \n" \ + "__ksymtab_" #sym NS_SEPARATOR #ns ": \n" \ + " .long " #sym "- . \n" \ + " .long __kstrtab_" #sym "- . \n" \ + " .long __kstrtab_ns_" #sym "- . \n" \ + " .previous \n") +#define __KSYMTAB_ENTRY (sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \@@ -56,32 +68,53 @@ extern struct module __this_module; "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \ + " .long 0 - . \n" \ " .previous \n")struct kernel_symbol {int value_offset;include/linux/export.h extern struct module __this_module; · line 85
Quoted 10 lines
include/linux/export.h +7
-0int name_offset; + int namespace_offset; };#else +#define __KSYMTAB_ENTRY_NS (sym, sec, ns) \ + static const struct kernel_symbol __ksymtab_##sym##__##ns \ + asm("__ksymtab_" #sym NS_SEPARATOR #ns) \ + __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ + = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym}Style nit: missing space after __kstrtab_ns_##sym.
Quoted 16 lines
include/linux/export.h +4
-1+#define __KSYMTAB_ENTRY (sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ + asm("__ksymtab_" #sym) \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ __aligned(sizeof(void *)) \ - = { (unsigned long)&sym, __kstrtab_##sym } + = { (unsigned long)&sym, __kstrtab_##sym, NULL }struct kernel_symbol {unsigned long value;const char *name; +const char *namespace; };#endif
Quoted 14 lines
include/linux/export.h extern struct module __this_module; · line 106
Quoted 9 lines
include/linux/export.h +2
-3-/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL (sym, sec) \ +#define ___export_symbol_common (sym, sec) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ - = #sym; \ + = #sym \Any particular reason for this change? Not that it's important, just noticing the inconsistent inclusion of the semicolon in some of the macros (e.g.
__CRC_SYMBOLincludes it but__export_symbol_commondoesn't).
I tried to be consistent to let the macro "call site" provide the final semicolon. And you are right, I could have adjusted __CRC_SYMBOL as well. I will adjust this for the next version.
Quoted 169 lines
Quoted 156 lines
include/linux/export.h +46
-9+ +/* For every exported symbol, place a struct in the __ksymtab section */ +#define ___EXPORT_SYMBOL_NS (sym, sec, ns) \ + ___export_symbol_common(sym, sec); \ + static const char __kstrtab_ns_##sym[] \ + __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ + = #ns; \ + __KSYMTAB_ENTRY_NS(sym, sec, ns) + +#define ___EXPORT_SYMBOL (sym, sec) \ + ___export_symbol_common(sym, sec); \ __KSYMTAB_ENTRY(sym, sec)#if defined(__DISABLE_EXPORTS)@@ -91,6 +124,7 @@ struct kernel_symbol {* be reused in other execution contexts such as the UEFI stub or the * decompressor. */ +#define __EXPORT_SYMBOL_NS (sym, sec, ns)#define __EXPORT_SYMBOL (sym, sec)#elif defined(CONFIG_TRIM_UNUSED_KSYMS )@@ -117,18 +151,26 @@ struct kernel_symbol {#define __cond_export_sym_1 (sym, sec) ___EXPORT_SYMBOL(sym, sec)#define __cond_export_sym_0 (sym, sec)/* nothing */ +#define __EXPORT_SYMBOL_NS (sym, sec, ns) \ + __ksym_marker(sym); \ + __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) +#define __cond_export_ns_sym (sym, sec, ns, conf) \ + ___cond_export_ns_sym(sym, sec, ns, conf) +#define ___cond_export_ns_sym (sym, sec, ns, enabled) \ + __cond_export_ns_sym_##enabled(sym, sec, ns) +#define __cond_export_ns_sym_1 (sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns) +#define __cond_export_ns_sym_0 (sym, sec, ns)/* nothing */ +#else +#define __EXPORT_SYMBOL_NS ___EXPORT_SYMBOL_NS#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif -#define EXPORT_SYMBOL (sym) \ - __EXPORT_SYMBOL(sym, "") - -#define EXPORT_SYMBOL_GPL (sym) \ - __EXPORT_SYMBOL(sym, "_gpl") - -#define EXPORT_SYMBOL_GPL_FUTURE (sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "") +#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future") +#define EXPORT_SYMBOL_NS (sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns)#ifdef CONFIG_UNUSED_SYMBOLS #define EXPORT_UNUSED_SYMBOL (sym) __EXPORT_SYMBOL(sym, "_unused")@@ -138,11 +180,28 @@ struct kernel_symbol {#define EXPORT_UNUSED_SYMBOL_GPL (sym)#endif -#endif /* __GENKSYMS__ */ +#endif /* __KERNEL__ && !__GENKSYMS__ */ + +#if defined(__GENKSYMS__) +/* +* When we're running genksyms, ignore the namespace and make the _NS +* variants look like the normal ones. There are two reasons for this: +* 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro +* argument is itself not expanded because it's always tokenized or +* concatenated; but when running genksyms, a blank definition of the +* macro does allow the argument to be expanded; if a namespace +* happens to collide with a #define, this can cause issues. +* 2) There's no need to modify genksyms to deal with the _NS variants +*/ +#define EXPORT_SYMBOL_NS (sym, ns) EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_NS_GPL (sym, ns) EXPORT_SYMBOL_GPL(sym) +#endif #else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym) +#define EXPORT_SYMBOL_NS (sym, ns) +#define EXPORT_SYMBOL_NS_GPL (sym, ns)#define EXPORT_SYMBOL_GPL (sym)#define EXPORT_SYMBOL_GPL_FUTURE (sym)#define EXPORT_UNUSED_SYMBOL (sym)include/linux/module.h +2
-0@@ -280,6 +280,8 @@ struct notifier_block;#ifdef CONFIG_MODULES +#define MODULE_IMPORT_NS (ns) MODULE_INFO(import_ns, #ns) +extern int
modules_disabled; /* for sysctl */ /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get(const char *symbol);kernel/module.c +37
-0@@ -544,6 +544,15 @@ static const char *kernel_symbol_name(const struct kernel_symbol *sym)#endif } +static const char *kernel_symbol_namespace (const struct kernel_symbol *sym) +{ +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +return offset_to_ptr (&sym->namespace_offset); +#else +return sym->namespace; +#endif +} +static int cmp_name (const void *va,const void *vb) {const char *a;@@ -1379,6 +1388,34 @@ static inline int same_magic(const char *amagic, const char *bmagic, }#endif /* CONFIG_MODVERSIONS */ +static char *get_modinfo (const struct load_info *info,const char *tag); +static char *get_next_modinfo (const struct load_info *info,const char *tag, +char *prev); + +static int verify_namespace_is_imported (const struct load_info *info, +const struct kernel_symbol *sym, +struct module *mod) +{ +const char *namespace; +char *imported_namespace; + + namespace =kernel_symbol_namespace (sym); +if (namespace) { + imported_namespace =get_modinfo (info,"import_ns" ); +while (imported_namespace) { +if (strcmp (namespace, imported_namespace) ==0 ) +return 0 ; + imported_namespace =get_next_modinfo ( + info,"import_ns" , imported_namespace); + } +pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name,kernel_symbol_name (sym), namespace); +return -EINVAL ; + } +return 0 ; +} + +/* Resolve a symbol for this module. I.e. if we find one, record usage. */ static const struct kernel_symbol *resolve_symbol(struct module *mod, const struct load_info *info,kernel/module.c static const struct kernel_symbol *resolve_symbol(struct module *mod, · line 1457
Quoted 8 lines
kernel/module.c +5
-0@@ -1413,6 +1450,12 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, goto getname; } + err =verify_namespace_is_imported (info, sym, mod); +if (err) { + sym =ERR_PTR (err); + goto getname; + }I think we should verify the namespace before taking a reference to the owner module (just swap the
verify_namespace_is_imported()andref_module()calls here).
Quoted 2 lines
Other than that, this patch looks good. Thanks!
Thanks! I will address the points above.
Cheers,
Matthias
Quoted 7 lines
Quoted 7 lines
kernel/module.c +1
-0+getname:
/* We must make copy under the lock if we failed to get ref. */ strncpy(ownername, module_name(owner), MODULE_NAME_LEN);Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 4/11 modpost: add support for symbol namespaces
In reply to Matthias MaennichAdd support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol usb_stor_resume from namespace USB_STORAGE, but does not import it.
--- scripts/mod/modpost.c | 91 +++++++++++++++++++++++++++++++++++++------ scripts/mod/modpost.h | 7 ++++ 2 files changed, 87 insertions(+), 11 deletions(-)
scripts/mod/modpost.c +80 -11
@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel
@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;
@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC
@@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;
@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;
@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);
@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);
@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol)) -buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; +buf_printf (&buf,"0x%08x\t%s%s%s\t%s\t%s\n" , + symbol->crc, symbol->name, + namespace ?"." :"" , + namespace ? namespace :"" , + symbol->module->name, +export_str (symbol->export)); + } symbol = symbol->next; } }
scripts/mod/modpost.h +7 -0
@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void buf_write (struct buffer *buf,const char *s,int len); +struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module {struct module *next;const char *name;
@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 04/11] modpost: add support for symbol namespaces
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 166 lines
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
scripts/mod/modpost.c| 91 +++++++++++++++++++++++++++++++++++++------scripts/mod/modpost.h| 7 ++++2 files changed, 87 insertions(+), 11 deletions(-)scripts/mod/modpost.c +71
-7@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC @@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol))
scripts/mod/modpost.c static void write_dump(const char *fname) · line 2473
Quoted 10 lines
scripts/mod/modpost.c +6
-4-buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s%s%s\t%s\t%s\n", + symbol->crc, symbol->name, + namespace ? "." : "", + namespace ? namespace : "",
I think it might be cleaner to just have namespace be a separate field in Module.symvers, rather than appending a dot and the namespace at the end of a symbol name. Maybe something like
<crc> <symbol_name> <namespace> <module>
For symbols without a namespace, we could just have "", with all fields delimited by tabs. This is just a stylistic suggestion, what do you think?
Regardless of the chosen format, I think we need to document how namespaces are represented in Documentation/kbuild/modules.rst, where it describes the Module.symvers format.
Thanks!
Jessica
Quoted 34 lines
scripts/mod/modpost.c +3
-0+ symbol->module->name, + export_str(symbol->export)); + } symbol = symbol->next; } }scripts/mod/modpost.h +0
-0@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void
buf_write(struct buffer *buf, const char *s, int len);scripts/mod/modpost.h +5
-0+struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module { struct module *next; const char *name;scripts/mod/modpost.h +2
-0@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerRe: [PATCH v3 04/11] modpost: add support for symbol namespaces
Quoted 182 lines · Jessica Yu
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 166 lines
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
scripts/mod/modpost.c| 91 +++++++++++++++++++++++++++++++++++++------scripts/mod/modpost.h| 7 ++++2 files changed, 87 insertions(+), 11 deletions(-)scripts/mod/modpost.c +71
-7@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC @@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol))scripts/mod/modpost.c static void write_dump(const char *fname) · line 2473
Quoted 10 lines
scripts/mod/modpost.c +6
-4-buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s%s%s\t%s\t%s\n", + symbol->crc, symbol->name, + namespace ? "." : "", + namespace ? namespace : "",I think it might be cleaner to just have namespace be a separate field in Module.symvers, rather than appending a dot and the namespace at the end of a symbol name. Maybe something like
Quoted 5 lines
<crc> <
symbol_name> <namespace> <module>For symbols without a namespace, we could just have "", with all fields delimited by tabs. This is just a stylistic suggestion, what do you think?
I thought of something like that initially, but did not do it to not break users of this file. But as I am anyway breaking users by changing the symbol name into symbol.NS, I might as well do it as you suggested. Since read_dump() also knew already how to extract the namespaces from symbol.NS, it had already worked without a change to the reading code of modpost. Are there any other consumers of Module.symvers that we should be aware of?
Quoted 3 lines
Regardless of the chosen format, I think we need to document how namespaces are represented in
Documentation/kbuild/modules.rst, where it describes the Module.symvers format.
Agreed. I will update the documentation. It anyway needs an update.
Cheers,
Matthias
Quoted 34 lines
Quoted 34 lines
scripts/mod/modpost.c +3
-0+ symbol->module->name, + export_str(symbol->export)); + } symbol = symbol->next; } }scripts/mod/modpost.h +0
-0@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void
buf_write(struct buffer *buf, const char *s, int len);scripts/mod/modpost.h +5
-0+struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module { struct module *next; const char *name;scripts/mod/modpost.h +2
-0@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 04/11] modpost: add support for symbol namespaces
+++ Matthias Maennich [27/08/19 15:41 +0100]:
Quoted 189 lines · Jessica Yu
Quoted 182 lines
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 166 lines
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
scripts/mod/modpost.c| 91 +++++++++++++++++++++++++++++++++++++------scripts/mod/modpost.h| 7 ++++2 files changed, 87 insertions(+), 11 deletions(-)scripts/mod/modpost.c +71
-7@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC @@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol))scripts/mod/modpost.c static void write_dump(const char *fname) · line 2473
Quoted 10 lines
scripts/mod/modpost.c +6
-4-buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s%s%s\t%s\t%s\n", + symbol->crc, symbol->name, + namespace ? "." : "", + namespace ? namespace : "",I think it might be cleaner to just have namespace be a separate field in Module.symvers, rather than appending a dot and the namespace at the end of a symbol name. Maybe something like
Quoted 5 lines
<crc> <
symbol_name> <namespace> <module>For symbols without a namespace, we could just have "", with all fields delimited by tabs. This is just a stylistic suggestion, what do you think?
Quoted 7 lines
I thought of something like that initially, but did not do it to not break users of this file. But as I am anyway breaking users by changing the symbol name into symbol.NS, I might as well do it as you suggested. Since
read_dump()also knew already how to extract the namespaces from symbol.NS, it had already worked without a change to the reading code of modpost. Are there any other consumers of Module.symvers that we should be aware of?
Maybe we can ease any possible breakage caused by the new format by putting the namespace column last? Then the first 4 fields crc, symbol, module, export type will remain in the same order, with namespace last. In-tree, I think we would need to update scripts/export_report.pl.
kmod is likely to be affected too - Lucas, would the addition of a new field (in the order described above) in Module.symvers break any kmod tools?
Thanks,
Jessica
Matthias Maennich
maintainerRe: [PATCH v3 04/11] modpost: add support for symbol namespaces
Quoted 198 lines · Jessica Yu
+++ Matthias Maennich [27/08/19 15:41 +0100]:
Quoted 189 lines · Jessica Yu
Quoted 182 lines
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 166 lines
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
scripts/mod/modpost.c| 91 +++++++++++++++++++++++++++++++++++++------scripts/mod/modpost.h| 7 ++++2 files changed, 87 insertions(+), 11 deletions(-)scripts/mod/modpost.c +71
-7@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC @@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol))scripts/mod/modpost.c static void write_dump(const char *fname) · line 2473
Quoted 10 lines
scripts/mod/modpost.c +6
-4-buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s%s%s\t%s\t%s\n", + symbol->crc, symbol->name, + namespace ? "." : "", + namespace ? namespace : "",I think it might be cleaner to just have namespace be a separate field in Module.symvers, rather than appending a dot and the namespace at the end of a symbol name. Maybe something like
Quoted 5 lines
<crc> <
symbol_name> <namespace> <module>For symbols without a namespace, we could just have "", with all fields delimited by tabs. This is just a stylistic suggestion, what do you think?
Quoted 7 lines
I thought of something like that initially, but did not do it to not break users of this file. But as I am anyway breaking users by changing the symbol name into symbol.NS, I might as well do it as you suggested. Since
read_dump()also knew already how to extract the namespaces from symbol.NS, it had already worked without a change to the reading code of modpost. Are there any other consumers of Module.symvers that we should be aware of?
Quoted 9 lines
Maybe we can ease any possible breakage caused by the new format by putting the namespace column last? Then the first 4 fields crc, symbol, module, export type will remain in the same order, with namespace last. In-tree, I think we would need to update
scripts/export_report.pl.kmod is likely to be affected too - Lucas, would the addition of a new field (in the order described above) in Module.symvers break any kmod tools?
According to the comment right above read_dump() and having a look a the implementation of it, the format is
0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
So, independently of what 'something' is, also export seems to be optional. OTOH, write_dump() seems to consistently write
0x12345678<tab>symbol<tab>module<tab>export
Not sure if there is something modifying Module.symvers afterwards or whether this is something that historically needs to be supported, but if we could rule that out, I would prefer
0x12345678<tab>symbol<tab>namespace<tab>module<tab>export
as you initially suggested.
Cheers,
Matthias
Re: [PATCH v3 04/11] modpost: add support for symbol namespaces
+++ Matthias Maennich [28/08/19 10:55 +0100]:
Quoted 219 lines · Jessica Yu
Quoted 198 lines
+++ Matthias Maennich [27/08/19 15:41 +0100]:
Quoted 189 lines · Jessica Yu
Quoted 182 lines
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 166 lines
Add support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol
usb_stor_resumefrom namespaceUSB_STORAGE, but does not import it.Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Reviewed-by Joel Fernandes (Google) <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
scripts/mod/modpost.c| 91 +++++++++++++++++++++++++++++++++++++------scripts/mod/modpost.h| 7 ++++2 files changed, 87 insertions(+), 11 deletions(-)scripts/mod/modpost.c +71
-7@@ -164,6 +164,7 @@ struct symbol {struct module *module;unsigned int crc;int crc_valid; +const char *namespace; unsigned int weak:1; unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel@@ -233,6 +234,37 @@ static struct symbol *find_symbol(const char *name)return NULL ; } +static bool contains_namespace (struct namespace_list *list, +const char *namespace) +{ +struct namespace_list *ns_entry; + +for (ns_entry = list; ns_entry !=NULL ; ns_entry = ns_entry->next) +if (strcmp (ns_entry->namespace, namespace) ==0 ) +return true; + +return false; +} + +static void add_namespace (struct namespace_list **list,const char *namespace) +{ +struct namespace_list *ns_entry; + +if (!contains_namespace (*list, namespace)) { + ns_entry =NOFAIL (malloc (sizeof (struct namespace_list ) + +strlen (namespace) +1 )); +strcpy (ns_entry->namespace, namespace); + ns_entry->next = *list; + *list = ns_entry; + } +} + +static bool module_imports_namespace (struct module *module, +const char *namespace) +{ +return contains_namespace (module->imported_namespaces, namespace); +} + static const struct { const char *str; enum export export;@@ -312,6 +344,22 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)return export_unknown; } +static const char *sym_extract_namespace (const char **symname) +{ +size_t n; +char *dupsymname; + + n =strcspn (*symname,"." ); +if (n <strlen (*symname) -1 ) { + dupsymname =NOFAIL (strdup (*symname)); + dupsymname[n] ='\0' ; + *symname = dupsymname; +return dupsymname + n +1 ; + } + +return NULL ; +} +/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC @@ -319,16 +367,18 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)static struct symbol *sym_add_exported (const char *name,struct module *mod,enum export export) { -struct symbol *s =find_symbol (name); +const char *symbol_name = name; +const char *namespace =sym_extract_namespace (&symbol_name); +struct symbol *s =find_symbol (symbol_name);if (!s) { - s =new_symbol (name, mod, export); + s =new_symbol (symbol_name, mod, export); + s->namespace = namespace; }else {if (!s->preloaded) { -warn ("%s: '%s' exported twice. Previous export " -"was in %s%s\n" , mod->name, name, - s->module->name, -is_vmlinux (s->module->name) ?"" :".ko" ); +warn ("%s: '%s' exported twice. Previous export was in %s%s\n" , + mod->name, symbol_name, s->module->name, +is_vmlinux (s->module->name) ?"" :".ko" ); }else {/* In case Module.symvers was out of date */ s->module = mod;@@ -1943,6 +1993,7 @@ static void read_symbols(const char *modname)const char *symname;char *version;char *license; +char *namespace;struct module *mod;struct elf_info info = { };Elf_Sym *sym;@@ -1974,6 +2025,12 @@ static void read_symbols(const char *modname) license =get_next_modinfo (&info,"license" , license); } + namespace =get_modinfo (&info,"import_ns" ); +while (namespace) { +add_namespace (&mod->imported_namespaces, namespace); + namespace =get_next_modinfo (&info,"import_ns" , namespace); + } +for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname =remove_dot (info.strtab + sym->st_name);@@ -2118,6 +2175,13 @@ static int check_exports(struct module *mod) basename++; else basename = mod->name; + +if (exp->namespace && + !module_imports_namespace (mod, exp->namespace)) { +warn ("module %s uses symbol %s from namespace %s, but does not import it.\n" , + basename, exp->name, exp->namespace); + } +if (!mod->gpl_compatible)check_for_gpl_usage (exp->export, basename, exp->name);check_for_unused (exp->export, basename, exp->name);@@ -2395,16 +2459,21 @@ static void write_dump(const char *fname) {struct buffer buf = { };struct symbol *symbol; +const char *namespace;int n;for (n =0 ; n <SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n];while (symbol) { -if (dump_sym (symbol))scripts/mod/modpost.c static void write_dump(const char *fname) · line 2473
Quoted 10 lines
scripts/mod/modpost.c +6
-4-buf_printf (&buf,"0x%08x\t%s\t%s\t%s\n" , - symbol->crc, symbol->name, - symbol->module->name, -export_str (symbol->export)); +if (dump_sym (symbol)) { + namespace = symbol->namespace; + buf_printf(&buf, "0x%08x\t%s%s%s\t%s\t%s\n", + symbol->crc, symbol->name, + namespace ? "." : "", + namespace ? namespace : "",I think it might be cleaner to just have namespace be a separate field in Module.symvers, rather than appending a dot and the namespace at the end of a symbol name. Maybe something like
Quoted 5 lines
<crc> <
symbol_name> <namespace> <module>For symbols without a namespace, we could just have "", with all fields delimited by tabs. This is just a stylistic suggestion, what do you think?
Quoted 7 lines
I thought of something like that initially, but did not do it to not break users of this file. But as I am anyway breaking users by changing the symbol name into symbol.NS, I might as well do it as you suggested. Since
read_dump()also knew already how to extract the namespaces from symbol.NS, it had already worked without a change to the reading code of modpost. Are there any other consumers of Module.symvers that we should be aware of?Quoted 9 lines
Maybe we can ease any possible breakage caused by the new format by putting the namespace column last? Then the first 4 fields crc, symbol, module, export type will remain in the same order, with namespace last. In-tree, I think we would need to update
scripts/export_report.pl.kmod is likely to be affected too - Lucas, would the addition of a new field (in the order described above) in Module.symvers break any kmod tools?
According to the comment right above
read_dump()and having a look a the implementation of it, the format is0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something]
So, independently of what 'something' is, also export seems to be optional. OTOH,
write_dump()seems to consistently write0x12345678<tab>symbol<tab>module<tab>export
Quoted 7 lines
Not sure if there is something modifying Module.symvers afterwards or whether this is something that historically needs to be supported, but if we could rule that out, I would prefer
0x12345678<tab>symbol<tab>namespace<tab>module<tab>export
as you initially suggested.
I don't mind either format :-) As long as the kmod folks are OK with it.
Thanks,
Jessica
Matthias Maennich
maintainerPATCH v3 5/11 module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
In reply to Matthias MaennichIf MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.
Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
--- init/Kconfig | 13 +++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
init/Kconfig +13 -0
@@ -2119,6 +2119,19 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + There is no technical reason to enforce correct namespace imports, + but it creates consistency between symbols defining namespaces and + users importing namespaces they make use of. This option relaxes this + requirement and lifts the enforcement when loading a module. + + If unsure, say N. + config TRIM_UNUSED_KSYMS bool "Trim unused exported kernel symbols" depends on MODULES && !UNUSED_SYMBOLS
kernel/module.c +9 -2
@@ -1408,9 +1408,16 @@ static int verify_namespace_is_imported(const struct load_info *info, imported_namespace =get_next_modinfo ( info,"import_ns" , imported_namespace); } -pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , - mod->name,kernel_symbol_name (sym), namespace); +#ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + pr_warn( +#else + pr_err( +#endif +"%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name, kernel_symbol_name(sym), namespace); +#ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS return -EINVAL ; +#endif }return 0 ; }
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 6/11 export: allow definition default namespaces in Makefiles or sources
In reply to Matthias MaennichTo avoid excessive usage of EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), where MY_NAMESPACE will always be the namespace we are exporting to, allow exporting all definitions of EXPORT_SYMBOL() and friends by defining DEFAULT_SYMBOL_NAMESPACE.
For example, to export all symbols defined in usb-common into the namespace USB_COMMON, add a line like this to drivers/usb/common/Makefile:
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all EXPORT_SYMBOL(sym) definitions to EXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.
Another way of making use of this feature is to define the namespace within source or header files similar to how TRACE_SYSTEM defines are used:
#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
Please note that, as opposed to TRACE_SYSTEM, DEFAULT_SYMBOL_NAMESPACE has to be defined before including include/linux/export.h.
If DEFAULT_SYMBOL_NAMESPACE is defined, a symbol can still be exported to another namespace by using EXPORT_SYMBOL_NS() and friends with explicitly specifying the namespace.
--- include/linux/export.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/export.h +6 -0
@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 06/11] export: allow definition default namespaces in Makefiles or sources
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 20 lines
To avoid excessive usage of
EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), whereMY_NAMESPACEwill always be the namespace we are exporting to, allow exporting all definitions ofEXPORT_SYMBOL()and friends by definingDEFAULT_SYMBOL_NAMESPACE.For example, to export all symbols defined in usb-common into the namespace
USB_COMMON, add a line like this todrivers/usb/common/Makefile:ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all
EXPORT_SYMBOL(sym)definitions toEXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.Another way of making use of this feature is to define the namespace within source or header files similar to how
TRACE_SYSTEMdefines are used:
#undefDEFAULT_SYMBOL_NAMESPACE
#defineDEFAULT_SYMBOL_NAMESPACEUSB_COMMON
Quoted 6 lines
Please note that, as opposed to
TRACE_SYSTEM,DEFAULT_SYMBOL_NAMESPACEhas to be defined before includinginclude/linux/export.h.If
DEFAULT_SYMBOL_NAMESPACEis defined, a symbol can still be exported to another namespace by usingEXPORT_SYMBOL_NS()and friends with explicitly specifying the namespace.
This changelog provides a good summary of how to use DEFAULT_SYMBOL_NAMESPACE, I wonder if we should explicitly document its proper usage somewhere? (along with EXPORT_SYMBOL_NS*) The EXPORT_SYMBOL API is briefly documented in Documentation/kernel-hacking/hacking.rst - it might be slightly dated, but perhaps it'd fit there best?
Quoted 28 lines
Suggested-by Arnd Bergmann <[email protected]>Reviewed-by Martijn Coenen <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
include/linux/export.h| 6 ++++++1 file changed, 6 insertions(+)include/linux/export.h +6
-0@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerRe: [PATCH v3 06/11] export: allow definition default namespaces in Makefiles or sources
Quoted 28 lines · Jessica Yu
+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 20 lines
To avoid excessive usage of
EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), whereMY_NAMESPACEwill always be the namespace we are exporting to, allow exporting all definitions ofEXPORT_SYMBOL()and friends by definingDEFAULT_SYMBOL_NAMESPACE.For example, to export all symbols defined in usb-common into the namespace
USB_COMMON, add a line like this todrivers/usb/common/Makefile:ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all
EXPORT_SYMBOL(sym)definitions toEXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.Another way of making use of this feature is to define the namespace within source or header files similar to how
TRACE_SYSTEMdefines are used:
#undefDEFAULT_SYMBOL_NAMESPACE
#defineDEFAULT_SYMBOL_NAMESPACEUSB_COMMONQuoted 6 lines
Please note that, as opposed to
TRACE_SYSTEM,DEFAULT_SYMBOL_NAMESPACEhas to be defined before includinginclude/linux/export.h.If
DEFAULT_SYMBOL_NAMESPACEis defined, a symbol can still be exported to another namespace by usingEXPORT_SYMBOL_NS()and friends with explicitly specifying the namespace.
Quoted 6 lines
This changelog provides a good summary of how to use
DEFAULT_SYMBOL_NAMESPACE, I wonder if we should explicitly document its proper usage somewhere? (along with EXPORT_SYMBOL_NS*) TheEXPORT_SYMBOLAPI is briefly documented inDocumentation/kernel-hacking/hacking.rst- it might be slightly dated, but perhaps it'd fit there best?
I will add documentation along with the commits. Not only for the macros, but in general to describe the feature.
Quoted 28 lines
Quoted 28 lines
Suggested-by Arnd Bergmann <[email protected]>Reviewed-by Martijn Coenen <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
include/linux/export.h| 6 ++++++1 file changed, 6 insertions(+)include/linux/export.h +6
-0@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 7/11 modpost: add support for generating namespace dependencies
In reply to Matthias MaennichThis patch adds an option to modpost to generate a <module>.ns_deps file per module, containing the namespace dependencies for that module.
E.g. if the linked module my-module.ko would depend on the symbol myfunc.MY_NS in the namespace MY_NS, the my-module.ns_deps file created by modpost would contain the entry MY_NS to express the namespace dependency of my-module imposed by using the symbol myfunc.
These files can subsequently be used by static analysis tools (like coccinelle scripts) to address issues with missing namespace imports. A later patch of this series will introduce such a script 'nsdeps' and a corresponding make target to automatically add missing MODULE_IMPORT_NS() definitions to the module's sources. For that it uses the information provided in the generated .ns_deps files.
--- .gitignore | 1 + Makefile | 2 +- scripts/mod/modpost.c | 54 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 2 ++ 4 files changed, 53 insertions(+), 6 deletions(-)
.gitignore +1 -0
@@ -32,6 +32,7 @@ *.lzo *.mod *.mod.c +*.ns_deps *.o *.o.* *.order
Makefile +1 -1
@@ -1669,7 +1669,7 @@ clean: $(clean-dirs) -o -name '*.ko.*' \ -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ -o -name '*.dwo' -o -name '*.lst' \ - -o -name '*.su' -o -name '*.mod' \ + -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '*.lex.c' -o -name '*.tab.[ch]' \ -o -name '*.asn1.[ch]' \
scripts/mod/modpost.c +49 -5
96 lines not on this page · raw message
scripts/mod/modpost.h +2 -0
@@ -126,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Required namespace dependencies +struct namespace_list *required_namespaces;// Actual imported namespaces struct namespace_list *imported_namespaces; };
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Matthias Maennich
maintainerPATCH v3 8/11 scripts: Coccinelle script for namespace dependencies.
In reply to Matthias MaennichA script that uses the '<module>.ns_deps' files generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace with EXPORT_SYMBOL_NS() or define DEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
--- MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 56 +++++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
MAINTAINERS +5 -0
@@ -11428,6 +11428,11 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git F: tools/include/nolibc/ +NSDEPS +M: Matthias Maennich <[email protected]> +S: Maintained +F: scripts/nsdeps + NTB AMD DRIVER M: Shyam Sundar S K <[email protected]> L: [email protected]
Makefile +12 -0
@@ -1500,6 +1500,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'
@@ -1687,6 +1690,15 @@ quiet_cmd_tags = GEN $@ tags TAGS cscope gtags: FORCE $(call cmd,tags) +# Script to generate missing namespace dependencies +# --------------------------------------------------------------------------- + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + # Scripts to check various things for consistency # ---------------------------------------------------------------------------
scripts/Makefile.modpost +3 -1
@@ -56,7 +56,8 @@ MODPOST = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) ifdef MODPOST_VMLINUX
@@ -134,6 +135,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: __modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------
scripts/coccinelle/misc/add_namespace.cocci new file +23 -0
@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +/// Adds missing MODULE_IMPORT_NS statements to source files +/// +/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to +/// add a missing namespace tag to a module source file. +/// + +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +// Add missing imports, but only adjacent to a MODULE_LICENSE statement. +// That ensures we are adding it only to the main module source file. +@do_import depends on !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);
scripts/nsdeps new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [v3 08/11] scripts: Coccinelle script for namespace dependencies
scripts/nsdeps line 27
Quoted 4 lines
scripts/nsdeps new file +4
-0+generate_deps_for_ns() { + $SPATCH --very-quiet --in-place --sp-file \ + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 +}
I would appreciate more constructive answers for specific software development concerns.
https://lore.kernel.org/lkml/[email protected]/
https://lkml.org/lkml/2019/8/15/515
Regards,
Markus
Re: [PATCH v3 08/11] scripts: Coccinelle script for namespace dependencies.
In reply to Matthias Maennich+++ Matthias Maennich [21/08/19 12:49 +0100]:
Quoted 178 lines
A script that uses the '<module>.ns_deps' files generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Acked-by Julia Lawall <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>---
MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++++++++ scripts/nsdeps | 56 +++++++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-)create mode 100644
scripts/coccinelle/misc/add_namespace.coccicreate mode 100644scripts/nsdepsMAINTAINERS +0
-0@@ -11428,6 +11428,11 @@ S: MaintainedT: git
git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
F:tools/include/nolibc/MAINTAINERS +5
-0+NSDEPS +M: Matthias Maennich <[email protected]> +S: Maintained +F: scripts/nsdeps +NTB AMD DRIVER
M: Shyam Sundar S K <[email protected]>
L: [email protected]Makefile +3
-0@@ -1500,6 +1500,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'@@ -1687,6 +1690,15 @@ quiet_cmd_tags = GEN $@tags TAGS cscope gtags: FORCE
$(call cmd,tags)Makefile +9
-0+# Script to generate missing namespace dependencies +# --------------------------------------------------------------------------- + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ +# Scripts to check various things for consistency
# ---------------------------------------------------------------------------scripts/Makefile.modpost +2
-1@@ -56,7 +56,8 @@ MODPOST = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d)ifdef
MODPOST_VMLINUXscripts/Makefile.modpost +1
-0@@ -134,6 +135,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: __modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------scripts/coccinelle/misc/add_namespace.cocci new file +23
-0@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +/// Adds missing MODULE_IMPORT_NS statements to source files +/// +/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to +/// add a missing namespace tag to a module source file. +/// + +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +// Add missing imports, but only adjacent to a MODULE_LICENSE statement. +// That ensures we are adding it only to the main module source file. +@do_import depends on !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);scripts/nsdeps new file +45
-0@@ -0,0 +1,56 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Linux kernel symbol namespace import generator +# +# This script requires a minimum spatch version. +SPATCH_REQ_VERSION="1.0.4" + +DIR="$(dirname $(readlink -f $0))/.." +SPATCH="`which ${SPATCH:=spatch}`" +if [ ! -x "$SPATCH" ]; then + echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' + exit 1 +fi + +SPATCH_REQ_VERSION_NUM=$(echo $SPATCH_REQ_VERSION | ${DIR}/scripts/ld-version.sh) +SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}') +SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh) + +if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then + echo "spatch needs to be version $SPATCH_REQ_VERSION or higher" + exit 1 +fi + +generate_deps_for_ns() { + $SPATCH --very-quiet --in-place --sp-file \ + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 +} + +generate_deps() { + local mod_name=`basename $@ .ko` + local mod_file=`echo $@ | sed -e 's/\.ko/\.mod/'` + local ns_deps_file=`echo $@ | sed -e 's/\.ko/\.ns_deps/'` + if [ ! -f "$ns_deps_file" ]; then return; fi + local mod_source_files=`cat $mod_file | sed -n 1p | sed -e 's/\.o/\.c/g'` + for ns in `cat $ns_deps_file`; do + echo "Adding namespace $ns to module $mod_name (if needed)." + generate_deps_for_ns $ns $mod_source_files + # sort the imports + for source_file in $mod_source_files; do + sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp + offset=$(wc -l ${source_file}.tmp | awk '{print $1;}') + cat $source_file | grep MODULE_IMPORT_NS | sort -u >> ${source_file}.tmp + tail -n +$((offset +1)) ${source_file} | grep -v MODULE_IMPORT_NS >> ${source_file}.tmp + if ! diff -q ${source_file} ${source_file}.tmp; then + mv ${source_file}.tmp ${source_file}
scripts/nsdeps line 55
Quoted 10 lines
scripts/nsdeps new file +10
-0+ else + rm ${source_file}.tmp + fi + done + done +} + +for f in `cat $srctree/modules.order`; do + generate_deps $f +done
Hi Matthias!
I normally build outside of the source tree (make O=..) and I think that choked up the nsdeps script a bit. For example when I run 'make nsdeps O=/tmp/linux' I get:
cat: /home/jeyu/linux/modules.order: No such file or directory
I just changed $srctree/modules.order to $objtree/modules.order and that fixed it for me. Also, I had to prefix $source_file in the script with $srctree so that it'd find the right file to modify.
Thanks!
Jessica
Matthias Maennich
maintainerPATCH v3 9/11 usb-storage: remove single-use define for debugging
In reply to Matthias MaennichUSB_STORAGE was defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.
--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
drivers/usb/storage/debug.h +0 -2
@@ -29,8 +29,6 @@#include <linux/kernel.h> -#define USB_STORAGE "usb-storage: " -#ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command (const struct us_data *us,struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key,
drivers/usb/storage/scsiglue.c +1 -1
@@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,/* check for state-transition errors */ if (us->srb !=NULL ) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", +printk (KERN_ERR "usb-storage: Error in %s: us->srb = %p\n" , __func__, us->srb);return SCSI_MLQUEUE_HOST_BUSY ; }
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 09/11] usb-storage: remove single-use define for debugging
Quoted 6 lines · Matthias Maennich
USB_STORAGEwas defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.Signed-off-by Matthias Maennich <[email protected]>
As you know, this patch is already in the usb-next tree, and will be in the 5.4-rc1 merge.
But, as this series will end up going through a different tree than the usb tree, here's my reviewed-by so that it can be included with the rest of these patches:
Re: [PATCH v3 09/11] usb-storage: remove single-use define for debugging
In reply to Matthias MaennichQuoted 29 lines · Matthias Maennich
USB_STORAGEwas defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.Signed-off-by Matthias Maennich <[email protected]>--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)drivers/usb/storage/debug.h +0
-2@@ -29,8 +29,6 @@#include <linux/kernel.h> -#define USB_STORAGE "usb-storage: " -#ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command (const struct us_data *us,struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key,drivers/usb/storage/scsiglue.c +0
-0
drivers/usb/storage/scsiglue.c static int queuecommand_lck(struct scsi_cmnd *srb, · line 383
Quoted 6 lines
drivers/usb/storage/scsiglue.c +1
-1@@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,/* check for state-transition errors */ if (us->srb !=NULL ) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", +printk (KERN_ERR "usb-storage: Error in %s: us->srb = %p\n" , __func__, us->srb);
The proper fix for this is to use pr_fmt and convert the printk to pr_err().
Thanks,
tglx
Greg KH
maintainerRe: [PATCH v3 09/11] usb-storage: remove single-use define for debugging
Quoted 32 lines · Thomas Gleixner
Quoted 30 lines · Matthias Maennich
USB_STORAGEwas defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.Signed-off-by Matthias Maennich <[email protected]>--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)drivers/usb/storage/debug.h +0
-2@@ -29,8 +29,6 @@#include <linux/kernel.h> -#define USB_STORAGE "usb-storage: " -#ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command (const struct us_data *us,struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key,drivers/usb/storage/scsiglue.c +0
-0@@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
Quoted 7 lines
drivers/usb/storage/scsiglue.c static int queuecommand_lck(struct scsi_cmnd *srb, · line 383
Quoted 5 lines
drivers/usb/storage/scsiglue.c +1
-1/* check for state-transition errors */ if (us->srb !=NULL ) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", +printk (KERN_ERR "usb-storage: Error in %s: us->srb = %p\n" , __func__, us->srb);The proper fix for this is to use
pr_fmtand convert the printk topr_err().
Yeah, that's the correct long-term fix, I think someone already sent that in for the usb tree, where I have taken this patch already.
thanks,
greg k-h
Matthias Maennich
maintainerPATCH v3 10/11 RFC: usb-storage: export symbols in USB_STORAGE namespace
In reply to Matthias MaennichModules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define DEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Instead of a DEFAULT_SYMBOL_NAMESPACE definition, the EXPORT_SYMBOL_NS variants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respective EXPORT_SYMBOL macro expansion.
--- drivers/usb/storage/Makefile | 2 ++ drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + 15 files changed, 16 insertions(+)
drivers/usb/storage/Makefile +2 -0
@@ -8,6 +8,8 @@ ccflags-y := -I $(srctree)/drivers/scsi +ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE + obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o
drivers/usb/storage/alauda.c +1 -0
@@ -36,6 +36,7 @@MODULE_DESCRIPTION ("Driver for Alauda-based card readers" );MODULE_AUTHOR ("Daniel Drake <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * Status bytes
drivers/usb/storage/cypress_atacb.c +1 -0
@@ -22,6 +22,7 @@MODULE_DESCRIPTION ("SAT support for Cypress USB/ATA bridges with ATACB" );MODULE_AUTHOR ("Matthieu Castet <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/datafab.c +1 -0
@@ -54,6 +54,7 @@MODULE_DESCRIPTION ("Driver for Datafab USB Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );struct datafab_info {unsigned long sectors;/* total sector count */
drivers/usb/storage/ene_ub6250.c +1 -0
@@ -26,6 +26,7 @@MODULE_DESCRIPTION ("Driver for ENE UB6250 reader" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_FIRMWARE (SD_INIT1_FIRMWARE );MODULE_FIRMWARE (SD_INIT2_FIRMWARE );MODULE_FIRMWARE (SD_RW_FIRMWARE );
drivers/usb/storage/freecom.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for Freecom USB/IDE adaptor" );MODULE_AUTHOR ("David Brown <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (struct us_data *us,void *ibuffer,int length);
drivers/usb/storage/isd200.c +1 -0
@@ -53,6 +53,7 @@MODULE_DESCRIPTION ("Driver for In-System Design, Inc. ISD200 ASIC" );MODULE_AUTHOR ("Björn Stenberg <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int isd200_Initialization (struct us_data *us);
drivers/usb/storage/jumpshot.c +1 -0
@@ -51,6 +51,7 @@MODULE_DESCRIPTION ("Driver for Lexar \"Jumpshot\" Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/karma.c +1 -0
@@ -23,6 +23,7 @@MODULE_DESCRIPTION ("Driver for Rio Karma" );MODULE_AUTHOR ("Bob Copeland <[email protected]>, Keith Bennett <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define RIO_PREFIX "RIOP\x00"#define RIO_PREFIX_LEN 5
drivers/usb/storage/onetouch.c +1 -0
@@ -25,6 +25,7 @@MODULE_DESCRIPTION ("Maxtor USB OneTouch hard drive button driver" );MODULE_AUTHOR ("Nick Sillik <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define ONETOUCH_PKT_LEN 0x02#define ONETOUCH_BUTTON KEY_PROG1
drivers/usb/storage/realtek_cr.c +1 -0
@@ -35,6 +35,7 @@MODULE_DESCRIPTION ("Driver for Realtek USB Card Reader" );MODULE_AUTHOR ("wwang <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int auto_delink_en =1 ;module_param (auto_delink_en, int,S_IRUGO |S_IWUSR );
drivers/usb/storage/sddr09.c +1 -0
@@ -47,6 +47,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-09 SmartMedia reader" );MODULE_AUTHOR ("Andries Brouwer <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int usb_stor_sddr09_dpcm_init (struct us_data *us);static int sddr09_transport (struct scsi_cmnd *srb,struct us_data *us);
drivers/usb/storage/sddr55.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-55 SmartMedia reader" );MODULE_AUTHOR ("Simon Munton" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/shuttle_usbat.c +1 -0
@@ -48,6 +48,7 @@MODULE_DESCRIPTION ("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable" );MODULE_AUTHOR ("Daniel Drake <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* Supported device types */ #define USBAT_DEV_HP8200 0x01
drivers/usb/storage/uas.c +1 -0
@@ -1219,5 +1219,6 @@ static struct usb_driver uas_driver = {module_usb_driver (uas_driver);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_AUTHOR ("Hans de Goede <[email protected]>, Matthew Wilcox and Sarah Sharp" );
Signature · 1 line
2.23.0.rc1.153.gdeed80330f-goog
Re: [PATCH v3 10/11] RFC: usb-storage: export symbols in USB_STORAGE namespace
Quoted 8 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Quoted 7 lines
Instead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.Signed-off-by Matthias Maennich <[email protected]>
This looks good to me. This can be included with the rest of this series when/if it goes through the kbuild or module tree:
Actually, which tree will this be going through?
thanks,
greg k-h
Re: [PATCH v3 10/11] RFC: usb-storage: export symbols in USB_STORAGE namespace
+++ Greg KH [21/08/19 05:38 -0700]:
Quoted 15 lines · Matthias Maennich
Quoted 14 lines
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdepsInstead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.
Quoted 8 lines
Quoted 1 line
Signed-off-by Matthias Maennich <[email protected]>This looks good to me. This can be included with the rest of this series when/if it goes through the kbuild or module tree:
Reviewed-by Greg Kroah-Hartman <[email protected]>Actually, which tree will this be going through?
I would be happy to take the patchset through the modules tree once it collects the appropriate ack/reviewed-by's and once I get a chance to sit down and review/test it next week :)
Thanks!
Jessica
Re: [PATCH v3 10/11] RFC: usb-storage: export symbols in USB_STORAGE namespace
In reply to Matthias MaennichQuoted 8 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Quoted 5 lines
Instead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.
So what is USB_STORAGE here? It isn't a C string, so where does it come from? To me using a C string would seem like the nicer interface vs a random cpp symbol that gets injected somewhere.
Matthias Maennich
maintainerRe: [PATCH v3 10/11] RFC: usb-storage: export symbols in USB_STORAGE namespace
Quoted 15 lines · Christoph Hellwig
Quoted 8 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define
DEFAULT_SYMBOL_NAMESPACEin the correspondingMakefile
2) make (see warnings during modpost about missing imports)
3) make nsdepsQuoted 5 lines
Instead of a
DEFAULT_SYMBOL_NAMESPACEdefinition, theEXPORT_SYMBOL_NSvariants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respectiveEXPORT_SYMBOLmacro expansion.
Quoted 3 lines
So what is
USB_STORAGEhere? It isn't a C string, so where does it come from? To me using a C string would seem like the nicer interface vs a random cpp symbol that gets injected somewhere.
To be honest, I would also prefer an interface that uses C strings or literals for the new EXPORT_SYMBOLS* macros:
EXPORT_SYMBOL_NS(mysym, "USB_STORAGE");
or
const char USB_STORAGE_NS[] = "USB_STORAGE";
EXPORT_SYMBOL_NS(mysym, USB_STORAGE_NS);
The DEFAULT_SYMBOL_NAMESPACE define within Makefiles would get a bit more verbose in that case to express the literal:
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE="\"USB_STORAGE\""
The main reason against that, is, that in the expansion of EXPORT_SYMBOL_NS, we define the ksymtab entry, which name is constructed partly by the name of the namespace:
static const struct kernel_symbol __ksymtab_##sym##__##ns ...
^^^^
For that we depend on a cpp symbol to construct the name. I am not sure there is a reasonable way of getting rid of that without ending up constructing the ksymtab entries completely in asm as it is already done in case of PREL32_RELOCATIONS. But I am happy to be corrected.
For reference that is done in patch 03/11 of this series:
https://lore.kernel.org/lkml/[email protected]/
Cheers,
Matthias
Matthias Maennich
maintainerPATCH v3 11/11 RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
In reply to Matthias MaennichModules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Use EXPORT_SYMBOL_NS* macros instead of EXPORT_SYMBOL* for symbols in watchdog_core.c
2) make (see warnings during modpost about missing imports)
3) make nsdeps
I used 'allmodconfig' for the above steps to ensure all occurrences are patched.
Defining DEFAULT_SYMBOL_NAMESPACE in the Makefile is not trivial in this case as not only watchdog_core is defined in drivers/watchdog/Makefile. Hence this patch uses the variant of using the EXPORT_SYMBOL_NS* macros to export into a different namespace.
An alternative to this patch would be a single definition line before any use of EXPORT_SYMBOL*:
#define DEFAULT_SYMBOL_NAMESPACE WATCHDOG_CORE
--- drivers/hwmon/ftsteutates.c | 1 + drivers/hwmon/sch56xx-common.c | 1 + drivers/rtc/rtc-abx80x.c | 1 + drivers/watchdog/armada_37xx_wdt.c | 1 + drivers/watchdog/asm9260_wdt.c | 1 + drivers/watchdog/aspeed_wdt.c | 1 + drivers/watchdog/at91sam9_wdt.c | 1 + drivers/watchdog/atlas7_wdt.c | 1 + drivers/watchdog/bcm2835_wdt.c | 1 + drivers/watchdog/bcm47xx_wdt.c | 1 + drivers/watchdog/bcm7038_wdt.c | 1 + drivers/watchdog/bcm_kona_wdt.c | 1 + drivers/watchdog/bd70528_wdt.c | 1 + drivers/watchdog/cadence_wdt.c | 1 + drivers/watchdog/da9052_wdt.c | 1 + drivers/watchdog/da9055_wdt.c | 1 + drivers/watchdog/da9062_wdt.c | 1 + drivers/watchdog/da9063_wdt.c | 1 + drivers/watchdog/davinci_wdt.c | 1 + drivers/watchdog/digicolor_wdt.c | 1 + drivers/watchdog/dw_wdt.c | 1 + drivers/watchdog/ebc-c384_wdt.c | 1 + drivers/watchdog/ep93xx_wdt.c | 1 + drivers/watchdog/ftwdt010_wdt.c | 1 + drivers/watchdog/gpio_wdt.c | 1 + drivers/watchdog/hpwdt.c | 1 + drivers/watchdog/i6300esb.c | 1 + drivers/watchdog/iTCO_wdt.c | 1 + drivers/watchdog/ie6xx_wdt.c | 1 + drivers/watchdog/imgpdc_wdt.c | 1 + drivers/watchdog/imx2_wdt.c | 1 + drivers/watchdog/intel-mid_wdt.c | 1 + drivers/watchdog/it87_wdt.c | 1 + drivers/watchdog/kempld_wdt.c | 1 + drivers/watchdog/lpc18xx_wdt.c | 1 + drivers/watchdog/max63xx_wdt.c | 1 + drivers/watchdog/max77620_wdt.c | 1 + drivers/watchdog/mei_wdt.c | 1 + drivers/watchdog/mena21_wdt.c | 1 + drivers/watchdog/menf21bmc_wdt.c | 1 + drivers/watchdog/menz69_wdt.c | 1 + drivers/watchdog/meson_gxbb_wdt.c | 1 + drivers/watchdog/meson_wdt.c | 1 + drivers/watchdog/mlx_wdt.c | 1 + drivers/watchdog/moxart_wdt.c | 1 + drivers/watchdog/mtk_wdt.c | 1 + drivers/watchdog/ni903x_wdt.c | 1 + drivers/watchdog/nic7018_wdt.c | 1 + drivers/watchdog/npcm_wdt.c | 1 + drivers/watchdog/of_xilinx_wdt.c | 1 + drivers/watchdog/omap_wdt.c | 1 + drivers/watchdog/pm8916_wdt.c | 1 + drivers/watchdog/qcom-wdt.c | 1 + drivers/watchdog/rave-sp-wdt.c | 1 + drivers/watchdog/renesas_wdt.c | 1 + drivers/watchdog/retu_wdt.c | 1 + drivers/watchdog/rn5t618_wdt.c | 1 + drivers/watchdog/rza_wdt.c | 1 + drivers/watchdog/s3c2410_wdt.c | 1 + drivers/watchdog/sama5d4_wdt.c | 1 + drivers/watchdog/sirfsoc_wdt.c | 1 + drivers/watchdog/softdog.c | 1 + drivers/watchdog/sp5100_tco.c | 1 + drivers/watchdog/sprd_wdt.c | 1 + drivers/watchdog/st_lpc_wdt.c | 1 + drivers/watchdog/stmp3xxx_rtc_wdt.c | 1 + drivers/watchdog/stpmic1_wdt.c | 1 + drivers/watchdog/sunxi_wdt.c | 1 + drivers/watchdog/tangox_wdt.c | 1 + drivers/watchdog/tegra_wdt.c | 1 + drivers/watchdog/tqmx86_wdt.c | 1 + drivers/watchdog/ts4800_wdt.c | 1 + drivers/watchdog/ts72xx_wdt.c | 1 + drivers/watchdog/twl4030_wdt.c | 1 + drivers/watchdog/uniphier_wdt.c | 1 + drivers/watchdog/via_wdt.c | 1 + drivers/watchdog/w83627hf_wdt.c | 1 + drivers/watchdog/watchdog_core.c | 10 +++++----- drivers/watchdog/wdat_wdt.c | 1 + drivers/watchdog/wm831x_wdt.c | 1 + drivers/watchdog/wm8350_wdt.c | 1 + drivers/watchdog/xen_wdt.c | 1 + drivers/watchdog/ziirave_wdt.c | 1 + 83 files changed, 87 insertions(+), 5 deletions(-)
drivers/hwmon/ftsteutates.c +1 -0
@@ -830,3 +830,4 @@ module_i2c_driver(fts_driver);MODULE_AUTHOR ("Thilo Cestonaro <[email protected]>" );MODULE_DESCRIPTION ("FTS Teutates driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/hwmon/sch56xx-common.c +1 -0
@@ -571,6 +571,7 @@ static void __exit sch56xx_exit(void)MODULE_DESCRIPTION ("SMSC SCH56xx Hardware Monitoring Common Code" );MODULE_AUTHOR ("Hans de Goede <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );module_init (sch56xx_init);module_exit (sch56xx_exit);
drivers/rtc/rtc-abx80x.c +1 -0
@@ -880,3 +880,4 @@ MODULE_AUTHOR("Philippe De Muyter <[email protected]>");MODULE_AUTHOR ("Alexandre Belloni <[email protected]>" );MODULE_DESCRIPTION ("Abracon ABX80X RTC driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/armada_37xx_wdt.c +1 -0
@@ -370,4 +370,5 @@ MODULE_AUTHOR("Marek Behun <[email protected]>");MODULE_DESCRIPTION ("Armada 37xx CPU Watchdog" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:armada_37xx_wdt" );
drivers/watchdog/asm9260_wdt.c +1 -0
@@ -374,3 +374,4 @@ module_platform_driver(asm9260_wdt_driver);MODULE_DESCRIPTION ("asm9260 WatchDog Timer Driver" );MODULE_AUTHOR ("Oleksij Rempel <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/aspeed_wdt.c +1 -0
@@ -334,3 +334,4 @@ module_exit(aspeed_wdt_exit);MODULE_DESCRIPTION ("Aspeed Watchdog Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/at91sam9_wdt.c +1 -0
@@ -416,3 +416,4 @@ module_platform_driver_probe(at91wdt_driver, at91wdt_probe);MODULE_AUTHOR ("Renaud CERRATO <[email protected]>" );MODULE_DESCRIPTION ("Watchdog driver for Atmel AT91SAM9x processors" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/atlas7_wdt.c +1 -0
@@ -218,4 +218,5 @@ module_platform_driver(atlas7_wdt_driver);MODULE_DESCRIPTION ("CSRatlas7 watchdog driver" );MODULE_AUTHOR ("Guo Zeng <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:atlas7-wdt" );
drivers/watchdog/bcm2835_wdt.c +1 -0
@@ -242,3 +242,4 @@ MODULE_ALIAS("platform:bcm2835-wdt");MODULE_AUTHOR ("Lubomir Rintel <[email protected]>" );MODULE_DESCRIPTION ("Driver for Broadcom BCM2835 watchdog timer" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/bcm47xx_wdt.c +1 -0
@@ -241,3 +241,4 @@ MODULE_AUTHOR("Aleksandar Radovanovic");MODULE_AUTHOR ("Hauke Mehrtens <[email protected]>" );MODULE_DESCRIPTION ("Watchdog driver for Broadcom BCM47xx" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/bcm7038_wdt.c +1 -0
@@ -212,5 +212,6 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_DESCRIPTION ("Driver for Broadcom 7038 SoCs Watchdog" );MODULE_AUTHOR ("Justin Chen" );
drivers/watchdog/bcm_kona_wdt.c +1 -0
@@ -339,3 +339,4 @@ MODULE_ALIAS("platform:" BCM_KONA_WDT_NAME);MODULE_AUTHOR ("Markus Mayer <[email protected]>" );MODULE_DESCRIPTION ("Broadcom Kona Watchdog Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/bd70528_wdt.c +1 -0
@@ -288,3 +288,4 @@ module_platform_driver(bd70528_wdt);MODULE_AUTHOR ("Matti Vaittinen <[email protected]>" );MODULE_DESCRIPTION ("BD70528 watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/cadence_wdt.c +1 -0
@@ -438,3 +438,4 @@ module_platform_driver(cdns_wdt_driver);MODULE_AUTHOR ("Xilinx, Inc." );MODULE_DESCRIPTION ("Watchdog driver for Cadence WDT" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/da9052_wdt.c +1 -0
@@ -191,4 +191,5 @@ module_platform_driver(da9052_wdt_driver);MODULE_AUTHOR ("Anthony Olech <[email protected]>" );MODULE_DESCRIPTION ("DA9052 SM Device Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:da9052-watchdog" );
drivers/watchdog/da9055_wdt.c +1 -0
@@ -166,4 +166,5 @@ module_platform_driver(da9055_wdt_driver);MODULE_AUTHOR ("David Dajun Chen <[email protected]>" );MODULE_DESCRIPTION ("DA9055 watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:da9055-watchdog" );
drivers/watchdog/da9062_wdt.c +1 -0
@@ -232,4 +232,5 @@ module_platform_driver(da9062_wdt_driver);MODULE_AUTHOR ("S Twiss <[email protected]>" );MODULE_DESCRIPTION ("WDT device driver for Dialog DA9062 and DA9061" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:da9062-watchdog" );
drivers/watchdog/da9063_wdt.c +1 -0
@@ -239,4 +239,5 @@ module_platform_driver(da9063_wdt_driver);MODULE_AUTHOR ("Mariusz Wojtasik <[email protected]>" );MODULE_DESCRIPTION ("Watchdog driver for Dialog DA9063" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:" DA9063_DRVNAME_WATCHDOG );
drivers/watchdog/davinci_wdt.c +1 -0
@@ -274,4 +274,5 @@ MODULE_PARM_DESC(heartbeat, __MODULE_STRING(DEFAULT_HEARTBEAT));MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:davinci-wdt" );
drivers/watchdog/digicolor_wdt.c +1 -0
@@ -161,3 +161,4 @@ module_platform_driver(dc_wdt_driver);MODULE_AUTHOR ("Baruch Siach <[email protected]>" );MODULE_DESCRIPTION ("Driver for Conexant Digicolor watchdog timer" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/dw_wdt.c +1 -0
@@ -340,3 +340,4 @@ module_platform_driver(dw_wdt_driver);MODULE_AUTHOR ("Jamie Iles" );MODULE_DESCRIPTION ("Synopsys DesignWare Watchdog Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/ebc-c384_wdt.c +1 -0
@@ -139,4 +139,5 @@ module_exit(ebc_c384_wdt_exit);MODULE_AUTHOR ("William Breathitt Gray <[email protected]>" );MODULE_DESCRIPTION ("WinSystems EBC-C384 watchdog timer driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("isa:" MODULE_NAME );
drivers/watchdog/ep93xx_wdt.c +1 -0
@@ -144,3 +144,4 @@ MODULE_AUTHOR("Alessandro Zummo <[email protected]>");MODULE_AUTHOR ("H Hartley Sweeten <[email protected]>" );MODULE_DESCRIPTION ("EP93xx Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/ftwdt010_wdt.c +1 -0
@@ -227,3 +227,4 @@ module_platform_driver(ftwdt010_wdt_driver);MODULE_AUTHOR ("Linus Walleij" );MODULE_DESCRIPTION ("Watchdog driver for Faraday Technology FTWDT010" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/gpio_wdt.c +1 -0
@@ -194,3 +194,4 @@ module_platform_driver(gpio_wdt_driver);MODULE_AUTHOR ("Alexander Shiyan <[email protected]>" );MODULE_DESCRIPTION ("GPIO Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/hpwdt.c +1 -0
@@ -386,6 +386,7 @@ static struct pci_driver hpwdt_driver = {MODULE_AUTHOR ("Tom Mingarelli" );MODULE_DESCRIPTION ("hpe watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_VERSION (HPWDT_VERSION );module_param (soft_margin, int,0 );
drivers/watchdog/i6300esb.c +1 -0
@@ -351,3 +351,4 @@ module_pci_driver(esb_driver);MODULE_AUTHOR ("Ross Biro and David Härdeman" );MODULE_DESCRIPTION ("Watchdog driver for Intel 6300ESB chipsets" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/iTCO_wdt.c +1 -0
@@ -632,4 +632,5 @@ MODULE_AUTHOR("Wim Van Sebroeck <[email protected]>");MODULE_DESCRIPTION ("Intel TCO WatchDog Timer Driver" );MODULE_VERSION (DRV_VERSION );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:" DRV_NAME );
drivers/watchdog/ie6xx_wdt.c +1 -0
@@ -314,4 +314,5 @@ module_exit(ie6xx_wdt_exit);MODULE_AUTHOR ("Alexander Stein <[email protected]>" );MODULE_DESCRIPTION ("Intel Atom E6xx Watchdog Device Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:" DRIVER_NAME );
drivers/watchdog/imgpdc_wdt.c +1 -0
@@ -314,3 +314,4 @@ MODULE_AUTHOR("Jude Abraham <[email protected]>");MODULE_AUTHOR ("Naidu Tellapati <[email protected]>" );MODULE_DESCRIPTION ("Imagination Technologies PDC Watchdog Timer Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/imx2_wdt.c +1 -0
@@ -433,4 +433,5 @@ module_platform_driver_probe(imx2_wdt_driver, imx2_wdt_probe);MODULE_AUTHOR ("Wolfram Sang" );MODULE_DESCRIPTION ("Watchdog driver for IMX2 and later" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:" DRIVER_NAME );
drivers/watchdog/intel-mid_wdt.c +1 -0
@@ -181,3 +181,4 @@ module_platform_driver(mid_wdt_driver);MODULE_AUTHOR ("David Cohen <[email protected]>" );MODULE_DESCRIPTION ("Watchdog Driver for Intel MID platform" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/it87_wdt.c +1 -0
@@ -354,3 +354,4 @@ module_exit(it87_wdt_exit);MODULE_AUTHOR ("Oliver Schuster" );MODULE_DESCRIPTION ("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/kempld_wdt.c +1 -0
@@ -550,3 +550,4 @@ module_platform_driver(kempld_wdt_driver);MODULE_DESCRIPTION ("KEM PLD Watchdog Driver" );MODULE_AUTHOR ("Michael Brunner <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/lpc18xx_wdt.c +1 -0
@@ -316,3 +316,4 @@ module_platform_driver(lpc18xx_wdt_driver);MODULE_AUTHOR ("Ariel D'Alessandro <[email protected]>" );MODULE_DESCRIPTION ("NXP LPC18xx Watchdog Timer Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/max63xx_wdt.c +1 -0
@@ -284,3 +284,4 @@ MODULE_PARM_DESC(nodelay, "(max6373/74 only, default=0)");MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/max77620_wdt.c +1 -0
@@ -209,3 +209,4 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "MODULE_AUTHOR ("Laxman Dewangan <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/mei_wdt.c +1 -0
@@ -662,4 +662,5 @@ module_mei_cl_driver(mei_wdt_driver);MODULE_AUTHOR ("Intel Corporation" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_DESCRIPTION ("Device driver for Intel MEI iAMT watchdog" );
drivers/watchdog/mena21_wdt.c +1 -0
@@ -225,4 +225,5 @@ module_platform_driver(a21_wdt_driver);MODULE_AUTHOR ("MEN Mikro Elektronik" );MODULE_DESCRIPTION ("MEN A21 Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:a21-watchdog" );
drivers/watchdog/menf21bmc_wdt.c +1 -0
@@ -181,4 +181,5 @@ module_platform_driver(menf21bmc_wdt);MODULE_DESCRIPTION ("MEN 14F021P00 BMC Watchdog driver" );MODULE_AUTHOR ("Andreas Werner <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:menf21bmc_wdt" );
drivers/watchdog/menz69_wdt.c +1 -0
@@ -167,4 +167,5 @@ module_mcb_driver(men_z069_driver);MODULE_AUTHOR ("Johannes Thumshirn <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("mcb:16z069" );
drivers/watchdog/meson_gxbb_wdt.c +1 -0
@@ -204,3 +204,4 @@ module_platform_driver(meson_gxbb_wdt_driver);MODULE_AUTHOR ("Neil Armstrong <[email protected]>" );MODULE_DESCRIPTION ("Amlogic Meson GXBB Watchdog timer driver" );MODULE_LICENSE ("Dual BSD/GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/meson_wdt.c +1 -0
@@ -228,5 +228,6 @@ MODULE_PARM_DESC(nowayout, __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Carlo Caione <[email protected]>" );MODULE_DESCRIPTION ("Meson Watchdog Timer Driver" );
drivers/watchdog/mlx_wdt.c +1 -0
@@ -287,4 +287,5 @@ module_platform_driver(mlxreg_wdt_driver);MODULE_AUTHOR ("Michael Shych <[email protected]>" );MODULE_DESCRIPTION ("Mellanox watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:mlx-wdt" );
drivers/watchdog/moxart_wdt.c +1 -0
@@ -164,4 +164,5 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds");MODULE_DESCRIPTION ("MOXART watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Jonas Jensen <[email protected]>" );
drivers/watchdog/mtk_wdt.c +1 -0
@@ -247,6 +247,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Matthias Brugger <[email protected]>" );MODULE_DESCRIPTION ("Mediatek WatchDog Timer Driver" );MODULE_VERSION (DRV_VERSION );
drivers/watchdog/ni903x_wdt.c +1 -0
@@ -255,3 +255,4 @@ MODULE_DESCRIPTION("NI 903x Watchdog");MODULE_AUTHOR ("Jeff Westfahl <[email protected]>" );MODULE_AUTHOR ("Kyle Roeschley <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/nic7018_wdt.c +1 -0
@@ -250,3 +250,4 @@ module_platform_driver(watchdog_driver);MODULE_DESCRIPTION ("National Instruments NIC7018 Watchdog driver" );MODULE_AUTHOR ("Hui Chun Ong <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/npcm_wdt.c +1 -0
@@ -248,3 +248,4 @@ module_platform_driver(npcm_wdt_driver);MODULE_AUTHOR ("Joel Stanley" );MODULE_DESCRIPTION ("Watchdog driver for NPCM" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/of_xilinx_wdt.c +1 -0
@@ -308,3 +308,4 @@ module_platform_driver(xwdt_driver);MODULE_AUTHOR ("Alejandro Cabrera <[email protected]>" );MODULE_DESCRIPTION ("Xilinx Watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/omap_wdt.c +1 -0
@@ -375,4 +375,5 @@ module_platform_driver(omap_wdt_driver);MODULE_AUTHOR ("George G. Davis" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:omap_wdt" );
drivers/watchdog/pm8916_wdt.c +1 -0
@@ -210,3 +210,4 @@ module_platform_driver(pm8916_wdt_driver);MODULE_AUTHOR ("Loic Poulain <[email protected]>" );MODULE_DESCRIPTION ("Qualcomm pm8916 watchdog driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/qcom-wdt.c +1 -0
@@ -272,3 +272,4 @@ module_platform_driver(qcom_watchdog_driver);MODULE_DESCRIPTION ("QCOM KPSS Watchdog Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/rave-sp-wdt.c +1 -0
@@ -329,6 +329,7 @@ module_platform_driver(rave_sp_wdt_driver);MODULE_DEVICE_TABLE (of, rave_sp_wdt_of_match);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Andrey Vostrikov <[email protected]>" );MODULE_AUTHOR ("Nikita Yushchenko <[email protected]>" );MODULE_AUTHOR ("Andrey Smirnov <[email protected]>" );
drivers/watchdog/renesas_wdt.c +1 -0
@@ -315,4 +315,5 @@ module_platform_driver(rwdt_driver);MODULE_DESCRIPTION ("Renesas WDT Watchdog Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Wolfram Sang <[email protected]>" );
drivers/watchdog/retu_wdt.c +1 -0
@@ -168,3 +168,4 @@ MODULE_DESCRIPTION("Retu watchdog");MODULE_AUTHOR ("Amit Kucheria" );MODULE_AUTHOR ("Aaro Koskinen <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/rn5t618_wdt.c +1 -0
@@ -191,3 +191,4 @@ module_platform_driver(rn5t618_wdt_driver);MODULE_AUTHOR ("Beniamino Galvani <[email protected]>" );MODULE_DESCRIPTION ("RN5T618 watchdog driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/rza_wdt.c +1 -0
@@ -245,3 +245,4 @@ module_platform_driver(rza_wdt_driver);MODULE_DESCRIPTION ("Renesas RZ/A WDT Driver" );MODULE_AUTHOR ("Chris Brandt <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/s3c2410_wdt.c +1 -0
@@ -739,3 +739,4 @@ module_platform_driver(s3c2410wdt_driver);MODULE_AUTHOR ("Ben Dooks <[email protected]>, Dimitry Andric <[email protected]>" );MODULE_DESCRIPTION ("S3C2410 Watchdog Device Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/sama5d4_wdt.c +1 -0
@@ -321,3 +321,4 @@ module_platform_driver(sama5d4_wdt_driver);MODULE_AUTHOR ("Atmel Corporation" );MODULE_DESCRIPTION ("Atmel SAMA5D4 Watchdog Timer driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/sirfsoc_wdt.c +1 -0
@@ -213,4 +213,5 @@ module_platform_driver(sirfsoc_wdt_driver);MODULE_DESCRIPTION ("SiRF SoC watchdog driver" );MODULE_AUTHOR ("Xianglong Du <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:sirfsoc-wdt" );
drivers/watchdog/softdog.c +1 -0
@@ -165,3 +165,4 @@ module_exit(softdog_exit);MODULE_AUTHOR ("Alan Cox" );MODULE_DESCRIPTION ("Software Watchdog Device Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/sp5100_tco.c +1 -0
@@ -486,3 +486,4 @@ module_exit(sp5100_tco_exit);MODULE_AUTHOR ("Priyanka Gupta" );MODULE_DESCRIPTION ("TCO timer driver for SP5100/SB800 chipset" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/sprd_wdt.c +1 -0
@@ -384,3 +384,4 @@ module_platform_driver(sprd_watchdog_driver);MODULE_AUTHOR ("Eric Long <[email protected]>" );MODULE_DESCRIPTION ("Spreadtrum Watchdog Timer Controller Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/st_lpc_wdt.c +1 -0
@@ -305,3 +305,4 @@ module_platform_driver(st_wdog_driver);MODULE_AUTHOR ("David Paris <[email protected]>" );MODULE_DESCRIPTION ("ST LPC Watchdog Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/stmp3xxx_rtc_wdt.c +1 -0
@@ -150,4 +150,5 @@ module_platform_driver(stmp3xxx_wdt_driver);MODULE_DESCRIPTION ("STMP3XXX RTC Watchdog Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Wolfram Sang <[email protected]>" );
drivers/watchdog/stpmic1_wdt.c +1 -0
@@ -138,3 +138,4 @@ module_platform_driver(stpmic1_wdt_driver);MODULE_DESCRIPTION ("Watchdog driver for STPMIC1 device" );MODULE_AUTHOR ("Pascal Paillet <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/sunxi_wdt.c +1 -0
@@ -289,6 +289,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Carlo Caione <[email protected]>" );MODULE_AUTHOR ("Henrik Nordstrom <[email protected]>" );MODULE_DESCRIPTION ("sunxi WatchDog Timer Driver" );
drivers/watchdog/tangox_wdt.c +1 -0
@@ -207,3 +207,4 @@ module_platform_driver(tangox_wdt_driver);MODULE_AUTHOR ("Mans Rullgard <[email protected]>" );MODULE_DESCRIPTION ("SMP86xx/SMP87xx Watchdog driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/tegra_wdt.c +1 -0
@@ -276,3 +276,4 @@ module_platform_driver(tegra_wdt_driver);MODULE_AUTHOR ("NVIDIA Corporation" );MODULE_DESCRIPTION ("Tegra Watchdog Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/tqmx86_wdt.c +1 -0
@@ -124,3 +124,4 @@ MODULE_AUTHOR("Andrew Lunn <[email protected]>");MODULE_DESCRIPTION ("TQMx86 Watchdog" );MODULE_ALIAS ("platform:tqmx86-wdt" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/ts4800_wdt.c +1 -0
@@ -200,4 +200,5 @@ module_platform_driver(ts4800_wdt_driver);MODULE_AUTHOR ("Damien Riegel <[email protected]>" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:ts4800_wdt" );
drivers/watchdog/ts72xx_wdt.c +1 -0
@@ -174,4 +174,5 @@ module_platform_driver(ts72xx_wdt_driver);MODULE_AUTHOR ("Mika Westerberg <[email protected]>" );MODULE_DESCRIPTION ("TS-72xx SBC Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:ts72xx-wdt" );
drivers/watchdog/twl4030_wdt.c +1 -0
@@ -123,5 +123,6 @@ module_platform_driver(twl4030_wdt_driver);MODULE_AUTHOR ("Nokia Corporation" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:twl4030_wdt" );
drivers/watchdog/uniphier_wdt.c +1 -0
@@ -255,3 +255,4 @@ MODULE_PARM_DESC(nowayout,MODULE_AUTHOR ("Keiji Hayashibara <[email protected]>" );MODULE_DESCRIPTION ("UniPhier Watchdog Device Driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/via_wdt.c +1 -0
@@ -259,3 +259,4 @@ module_pci_driver(wdt_driver);MODULE_AUTHOR ("Marc Vertes" );MODULE_DESCRIPTION ("Driver for watchdog timer on VIA chipset" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/w83627hf_wdt.c +1 -0
@@ -528,5 +528,6 @@ module_init(wdt_init);module_exit (wdt_exit);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_AUTHOR ("Pádraig Brady <[email protected]>" );MODULE_DESCRIPTION ("w83627hf/thf WDT driver" );
drivers/watchdog/watchdog_core.c +5 -5
@@ -145,7 +145,7 @@ int watchdog_init_timeout(struct watchdog_device *wdd,return ret; } -EXPORT_SYMBOL_GPL (watchdog_init_timeout); +EXPORT_SYMBOL_NS_GPL (watchdog_init_timeout,WATCHDOG_CORE );static int watchdog_restart_notifier (struct notifier_block *nb,unsigned long action,void *data)
@@ -180,7 +180,7 @@ void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority) { wdd->restart_nb.priority = priority; } -EXPORT_SYMBOL_GPL (watchdog_set_restart_priority); +EXPORT_SYMBOL_NS_GPL (watchdog_set_restart_priority,WATCHDOG_CORE );static int __watchdog_register_device (struct watchdog_device *wdd) {
@@ -279,7 +279,7 @@ int watchdog_register_device(struct watchdog_device *wdd)return ret; } -EXPORT_SYMBOL_GPL (watchdog_register_device); +EXPORT_SYMBOL_NS_GPL (watchdog_register_device,WATCHDOG_CORE );static void __watchdog_unregister_device (struct watchdog_device *wdd) {
@@ -311,7 +311,7 @@ void watchdog_unregister_device(struct watchdog_device *wdd)mutex_unlock (&wtd_deferred_reg_mutex); } -EXPORT_SYMBOL_GPL (watchdog_unregister_device); +EXPORT_SYMBOL_NS_GPL (watchdog_unregister_device,WATCHDOG_CORE );static void devm_watchdog_unregister_device (struct device *dev,void *res) {
@@ -348,7 +348,7 @@ int devm_watchdog_register_device(struct device *dev,return ret; } -EXPORT_SYMBOL_GPL (devm_watchdog_register_device); +EXPORT_SYMBOL_NS_GPL (devm_watchdog_register_device,WATCHDOG_CORE );static int __init watchdog_deferred_registration (void ) {
drivers/watchdog/wdat_wdt.c +1 -0
@@ -523,4 +523,5 @@ module_platform_driver(wdat_wdt_driver);MODULE_AUTHOR ("Mika Westerberg <[email protected]>" );MODULE_DESCRIPTION ("ACPI Hardware Watchdog (WDAT) driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:wdat_wdt" );
drivers/watchdog/wm831x_wdt.c +1 -0
@@ -282,4 +282,5 @@ module_platform_driver(wm831x_wdt_driver);MODULE_AUTHOR ("Mark Brown" );MODULE_DESCRIPTION ("WM831x Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:wm831x-watchdog" );
drivers/watchdog/wm8350_wdt.c +1 -0
@@ -175,4 +175,5 @@ module_platform_driver(wm8350_wdt_driver);MODULE_AUTHOR ("Mark Brown" );MODULE_DESCRIPTION ("WM8350 Watchdog" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );MODULE_ALIAS ("platform:wm8350-wdt" );
drivers/watchdog/xen_wdt.c +1 -0
@@ -206,3 +206,4 @@ module_exit(xen_wdt_cleanup_module);MODULE_AUTHOR ("Jan Beulich <[email protected]>" );MODULE_DESCRIPTION ("Xen WatchDog Timer Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
drivers/watchdog/ziirave_wdt.c +1 -0
@@ -751,3 +751,4 @@ module_i2c_driver(ziirave_wdt_driver);MODULE_AUTHOR ("Martyn Welch <[email protected]" );MODULE_DESCRIPTION ("Zodiac Aerospace RAVE Switch Watchdog Processor Driver" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (WATCHDOG_CORE );
Signature · 7 lines
2.23.0.rc1.153.gdeed80330f-goog _______________________________________________ Linux-mediatek mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-mediatek
Re: [PATCH v3 11/11] RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
Quoted 17 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Use EXPORT_SYMBOL_NS* macros instead of EXPORT_SYMBOL* for symbols in
watchdog_core.c
2) make (see warnings during modpost about missing imports)
3) make nsdepsI used 'allmodconfig' for the above steps to ensure all occurrences are patched.
Defining
DEFAULT_SYMBOL_NAMESPACEin theMakefileis not trivial in this case as not onlywatchdog_coreis defined indrivers/watchdog/Makefile. Hence this patch uses the variant of using the EXPORT_SYMBOL_NS* macros to export into a different namespace.
Quoted 5 lines
An alternative to this patch would be a single definition line before any use of EXPORT_SYMBOL*:
#defineDEFAULT_SYMBOL_NAMESPACEWATCHDOG_CORESigned-off-by Matthias Maennich <[email protected]>
As we talked in chat, the cc: list for this patch was crazy :)
If you end up resending this (as odds are the mailing lists will trash it for too many recipients), feel free to add:
Great work,
greg k-h
Guenter Roeck
maintainerRe: [PATCH v3 11/11] RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
In reply to Matthias MaennichQuoted 9 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Use EXPORT_SYMBOL_NS* macros instead of EXPORT_SYMBOL* for symbols in
watchdog_core.c
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Quoted 8 lines
I used 'allmodconfig' for the above steps to ensure all occurrences are patched.
Defining
DEFAULT_SYMBOL_NAMESPACEin theMakefileis not trivial in this case as not onlywatchdog_coreis defined indrivers/watchdog/Makefile. Hence this patch uses the variant of using the EXPORT_SYMBOL_NS* macros to export into a different namespace.
I don't have the context, and thus I am missing the point of this patch set. Whatever it is supposed to accomplish, it seems extreme to me to require extra code in each driver for it.
Anyway, WATCHDOG_CORE would be the default namespace (if it is what I think it is) for watchdog drivers, even though not all watchdog drivers use it. As such, I am missing an explanation why defining it in Makefile is not trivial. "... as not only watchdog_core is defined in drivers/watchdog/Makefile" does not mean anything to me and is not a real explanation. Also, it is not immediately obvious to me why "select WATCHDOG_CORE" in Kconfig would not automatically imply that WATCHDOG_CORE is used by a given driver, and why it is impossible to use that information to avoid the per-driver changes.
I am also missing an explanation why WATCHDOG_CORE is going to be a separate namespace to start with. Maybe that discussion has happened, but I don't recall being advised or asked or told about it. Are we also going to have a new HWMON_CORE namespace ? And the same for each other subsystem in the kernel ?
Since this is being added to the watchdog API, it will have to be documented accordingly. Watchdog driver writers, both inside and outside the watchdog subsystem, will need to know that they now have to add an additional boilerplate declaration into their drivers.
Last but not least, combining patches affecting multiple subsystems in a single patch will make it difficult to apply and will likely result in conflicts. Personally I would prefer a split into one patch per affected subsystem. Also, please keep in mind that new pending watchdog drivers won't have the new boilerplate.
Thanks,
Guenter
Matthias Maennich
maintainerRe: [PATCH v3 11/11] RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
Hi Guenter!
Quoted 13 lines · Guenter Roeck
Quoted 12 lines · Matthias Maennich
Modules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Use EXPORT_SYMBOL_NS* macros instead of EXPORT_SYMBOL* for symbols in
watchdog_core.c
2) make (see warnings during modpost about missing imports)
3) make nsdepsI used 'allmodconfig' for the above steps to ensure all occurrences are patched.
Quoted 9 lines
Quoted 5 lines
Defining
DEFAULT_SYMBOL_NAMESPACEin theMakefileis not trivial in this case as not onlywatchdog_coreis defined indrivers/watchdog/Makefile. Hence this patch uses the variant of using the EXPORT_SYMBOL_NS* macros to export into a different namespace.I don't have the context, and thus I am missing the point of this patch set. Whatever it is supposed to accomplish, it seems extreme to me to require extra code in each driver for it.
Unfortunately, get_maintainer.pl has helped me too much and this series got blocked by some mailing lists due to the large amount of recipients. Following versions will be sent to the previous audience + the linux-watchdog list.
For context, the full series (including previous versions) can be found on lore at
https://lore.kernel.org/lkml/20180716122125.175792-1-maco-z5hGa2qSFaRBDgjK7y7TUQ@public.gmane.org/
and the cover letter for v3 has made it to linux-amlogic
https://lore.kernel.org/linux-amlogic/20190821114955.12788-1-maennich-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org/
Quoted 5 lines
Anyway,
WATCHDOG_COREwould be the default namespace (if it is what I think it is) for watchdog drivers, even though not all watchdog drivers use it. As such, I am missing an explanation why defining it inMakefileis not trivial. "... as not onlywatchdog_coreis defined indrivers/watchdog/Makefile" does not mean anything to me and is not a real
True, that is a bit out of context. Especially considering you did not receive any other messages of that series.
Defining a namespace a symbol should be exported to can be done in different ways. All of them effectively change the EXPORT_SYMBOL* macro's behaviour. The method I am referring to is using
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=WATCHDOG_CORE
directly in drivers/watchdog/Makefile. Since this would also apply the namespace to exports in non-core modules it would be incorrect. Thus I used the method of applying the namespace directly by changing the EXPORT_SYMBOL macro expansion.
Quoted 5 lines
explanation. Also, it is not immediately obvious to me why "select
WATCHDOG_CORE" inKconfigwould not automatically imply thatWATCHDOG_COREis used by a given driver, and why it is impossible to use that information to avoid the per-driver changes.
One intention of this patch series is to make exporting and using of namespaces explicit. As such, the subsystem exporting symbols is defining the namespace it exports to and the module using a namespace is supposed to explicitly declare its usage via import. In case of watchdog (and probably other cases) it might make sense to find a way to implicitly import the namespace for in-tree drivers in the same area.
Quoted 6 lines
I am also missing an explanation why
WATCHDOG_COREis going to be a separate namespace to start with. Maybe that discussion has happened, but I don't recall being advised or asked or told about it. Are we also going to have a newHWMON_COREnamespace ? And the same for each other subsystem in the kernel ?
This very patch is an RFC to demonstrate how Symbol Namespaces would be used based on the current implementation (the other RFC as part of this series is for the introduction of the namespace USB_STORAGE). WATCHDOG_CORE serves as one of two examples. I do not think the two RFC patches should be merged along with this series.
Quoted 5 lines
Since this is being added to the watchdog API, it will have to be documented accordingly. Watchdog driver writers, both inside and outside the watchdog subsystem, will need to know that they now have to add an additional boilerplate declaration into their drivers.
Completely agree. This is just an RFC that omits these details as it purely focuses on the introduction and consequences of such a namespace to demonstrate how the feature works.
Quoted 5 lines
Last but not least, combining patches affecting multiple subsystems in a single patch will make it difficult to apply and will likely result in conflicts. Personally I would prefer a split into one patch per affected subsystem. Also, please keep in mind that new pending watchdog drivers won't have the new boilerplate.
I understand the point. Especially as I am already now affected by the long list of recipients when sending this patch. The problem with single patches here is, that once a symbol is exported into a namespace, all modules using it have to declare that import to avoid a warning at compile time and module load time. Hence the all-in-one approach. Luckily, the patch series also provides a way to address such a warning (via make nsdeps) that creates the necessary source code fix as a single line per module and namespace right after MODULE_LICENSE(). That is how this patch was created in the first place.
Cheers,
Matthias
Re: [PATCH v3 00/11] Symbol Namespaces
In reply to Matthias MaennichQuoted 4 lines · Matthias Maennich
As of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
This is good work.
One solution for drastically reducing the effective export surface is to have CONFIG_TRIM_UNUSED_KSYMS=y. This is more extreme than symbol namespace, but might be worth mentioning nevertheless.
Nicolas
Greg KH
maintainerRe: [PATCH v3 00/11] Symbol Namespaces
Quoted 7 lines · Nicolas Pitre
Quoted 4 lines · Matthias Maennich
As of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Quoted 5 lines
This is good work.
One solution for drastically reducing the effective export surface is to have
CONFIG_TRIM_UNUSED_KSYMS=y. This is more extreme than symbol namespace, but might be worth mentioning nevertheless.
Oh that's amazing, I never noticed that feature. That is a nice thing, thanks for pointing it out.
greg k-h
Re: [PATCH v3 00/11] Symbol Namespaces
Quoted 8 lines · Greg KH
Quoted 3 lines · Nicolas Pitre
One solution for drastically reducing the effective export surface is to have
CONFIG_TRIM_UNUSED_KSYMS=y. This is more extreme than symbol namespace, but might be worth mentioning nevertheless.Oh that's amazing, I never noticed that feature. That is a nice thing, thanks for pointing it out.
For those interested, this feature was demonstrated with numbers here:
https://lwn.net/Articles/746780/
Nicolas
Re: [PATCH v3 00/11] Symbol Namespaces
In reply to Matthias MaennichQuoted 22 lines · Matthias Maennich
As of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree useWhen module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
Quoted 5 lines
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "
SUBSYSTEM_DEBUG" namespace.
I'm missing how one can prohibit these random out of tree modules from doing MODULE_IMPORT_NS().
That is; suppose I stick all the preempt_notifier symbols in a KVM namespace, how do I enforce no out-of-tree modules ever do MODULE_IMPORT_NS(KVM) and gain access?
(the above would basically break virtualbox, which I knows uses preempt notifiers too, but I don't give a rats arse about that)
Greg KH
maintainerRe: [PATCH v3 00/11] Symbol Namespaces
Quoted 23 lines · Peter Zijlstra
Quoted 22 lines · Matthias Maennich
As of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree useWhen module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
Quoted 8 lines
Quoted 5 lines
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "
SUBSYSTEM_DEBUG" namespace.I'm missing how one can prohibit these random out of tree modules from doing
MODULE_IMPORT_NS().
Nothing, but then they are explicitly being "bad" :)
Quoted 6 lines
That is; suppose I stick all the
preempt_notifiersymbols in a KVM namespace, how do I enforce no out-of-tree modules ever doMODULE_IMPORT_NS(KVM)and gain access?(the above would basically break virtualbox, which I knows uses preempt notifiers too, but I don't give a rats arse about that)
It's a huge red flag for anyone reviewing the code that this module is doing something it probably really should not be doing at all. It will make reviewing code easier, this isn't there to try to "prevent bad actors" at all, sorry.
thanks,
greg k-h
Matthias Maennich
maintainerRe: [PATCH v3 00/11] Symbol Namespaces
Quoted 30 lines · Greg Kroah-Hartman
Quoted 29 lines · Peter Zijlstra
Quoted 27 lines · Matthias Maennich
As of Linux 5.3-rc5, there are 31205 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree useWhen module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "
SUBSYSTEM_DEBUG" namespace.
Quoted 5 lines
Quoted 2 lines
I'm missing how one can prohibit these random out of tree modules from doing
MODULE_IMPORT_NS().Nothing, but then they are explicitly being "bad" :)
As a side effect of this implementation (namespace imports via modinfo tags), imports are very visible for (out-of-tree) modules, e.g.
$ modinfo drivers/usb/storage/ums-usbat.ko filename: drivers/usb/storage/ums-usbat.ko import_ns: USB_STORAGE license: GPL author: ... ...
Quoted 4 lines
Quoted 4 lines
That is; suppose I stick all the
preempt_notifiersymbols in a KVM namespace, how do I enforce no out-of-tree modules ever doMODULE_IMPORT_NS(KVM)and gain access?
That is actually a feature worth following up: Restricting the namespaces that can be imported by modules. I am afraid it is not part of this series, but should not be too hard once agreed how such a list will be defined.
Quoted 8 lines
Quoted 2 lines
(the above would basically break virtualbox, which I knows uses preempt notifiers too, but I don't give a rats arse about that)
It's a huge red flag for anyone reviewing the code that this module is doing something it probably really should not be doing at all. It will make reviewing code easier, this isn't there to try to "prevent bad actors" at all, sorry.
Cheers,
Matthias
Matthias Maennich
maintainerv4 cover Symbol Namespaces
In reply to Martijn CoenenAs of Linux 5.3-rc7, there are 31207 [1] exported symbols in the kernel. That is a growth of roughly 1000 symbols since 4.17 (30206 [2]). There seems to be some consensus amongst kernel devs that the export surface is too large, and hard to reason about.
Generally, these symbols fall in one of these categories:
1) Symbols actually meant for drivers
2) Symbols that are only exported because functionality is split over multiple modules, yet they really shouldn't be used by modules outside of their own subsystem
3) Symbols really only meant for in-tree use
When module developers try to upstream their code, it regularly turns out that they are using exported symbols that they really shouldn't be using. This problem is even bigger for drivers that are currently out-of-tree, which may be using many symbols that they shouldn't be using, and that break when those symbols are removed or modified.
This patch allows subsystem maintainers to partition their exported symbols into separate namespaces, and module authors to import such namespaces only when needed.
This allows subsystem maintainers to more easily limit availability of these namespaced symbols to other parts of the kernel. It can also be used to partition the set of exported symbols for documentation purposes; for example, a set of symbols that is really only used for debugging could be in a "SUBSYSTEM_DEBUG" namespace.
The series contains two RFC patches that do not need to be merged along with the rest of the series, but they serve as a reference for using the symbol namespaces. Especially, the watchdog subsystem might not be affected by the issues addressed by Symbol Namespaces. I left the patch in for reference anyway for demonstration purposes.
I continued the work mainly done by Martijn Coenen.
Changes in v2:
- Rather than adding and evaluating separate sections __knsimport_NS, use modinfo tags to declare the namespaces a module introduces. Adjust modpost and the module loader accordingly.
- Also add support for reading multiple modinfo values for the same tag to allow list-like access to modinfo tags.
- The macros in export.h have been cleaned up to avoid redundancy in the macro parameters (ns, nspost, nspost2).
- The introduction of relative references in the ksymtab entries caused a rework of the macros to accommodate that configuration as well.
- Alignment of kernel_symbol in the ksymtab needed to be fixed to allow growing the kernel_symbol struct.
- Modpost does now also append the namespace suffix to the symbol entries in Module.symvers.
- The configuration option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS allows relaxing the enforcement of properly declared namespace imports at module loading time.
- Symbols can be collectively exported into a namespace by defining DEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile.
- The requirement for a very recent coccinelle spatch has been lifted by simplifying the script.
- nsdeps does now ensures MODULE_IMPORT_NS statements are sorted when patching the module source files.
- Some minor bugs have been addressed in nsdeps to allow it to work with modules that have more than one source file.
- The RFC for the usb-storage symbols has been simplified by using DEFAULT_SYMBOL_NAMESPACE=USB_STORAGE rather than explicitly exporting each and every symbol into that new namespace.
Changes in v3:
- Reword the documentation for the MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS option for clarification.
- Fix printed required version of spatch in coccinelle script.
- Adopt kbuild changes for modpost: .mod files are no longer generated in .tmp_versions. Similarely, generate the .ns_deps files in the tree along with the .mod files. Also, nsdeps now uses modules.order as source for the list modules to consider.
- Add an RFC patch to introduce the namespace WATCHDOG_CORE for symbols exported in watchdog_core.c.
Changes in v4:
- scripts/nsdeps:
- exit on first error
- support out-of-tree builds O=...
- scripts/mod/modpost: make the namespace a separate field when exporting to Module.symvers (rather than symbol.NS)
- scripts/export_report.pl: update for new Module.symvers format
- include/linux/export.h: fixed style nits
- kernel/module.c: ensure namespaces are imported before taking a reference to the owner module
- Documentation: document the Symbol Namespace feature and update references to Module.symvers and EXPORT_SYMBOL*
This patch series was developed against v5.3-rc7.
[1] git grep "^EXPORT_SYMBOL\w*(" v5.3-rc7 | wc -l
[2] git grep "^EXPORT_SYMBOL\w*(" v4.17 | wc -l
Matthias Maennich (12):
module: support reading multiple values per modinfo tag
export: explicitly align struct kernel_symbol
module: add support for symbol namespaces.
modpost: add support for symbol namespaces
module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
export: allow definition default namespaces in Makefiles or sources
modpost: add support for generating namespace dependencies
scripts: Coccinelle script for namespace dependencies.
docs: Add documentation for Symbol Namespaces
usb-storage: remove single-use define for debugging
RFC: usb-storage: export symbols in USB_STORAGE namespace
RFC: watchdog: export core symbols in WATCHDOG_CORE namespace
.gitignore | 1 + Documentation/kbuild/modules.rst | 7 +- Documentation/kbuild/namespaces.rst | 154 ++++++++++++++++++++ Documentation/kernel-hacking/hacking.rst | 18 +++ MAINTAINERS | 5 + Makefile | 14 +- arch/m68k/include/asm/export.h | 1 - drivers/hwmon/ftsteutates.c | 1 + drivers/hwmon/sch56xx-common.c | 1 + drivers/rtc/rtc-abx80x.c | 1 + drivers/usb/storage/Makefile | 2 + drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/debug.h | 2 - drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + drivers/watchdog/armada_37xx_wdt.c | 1 + drivers/watchdog/asm9260_wdt.c | 1 + drivers/watchdog/aspeed_wdt.c | 1 + drivers/watchdog/at91sam9_wdt.c | 1 + drivers/watchdog/atlas7_wdt.c | 1 + drivers/watchdog/bcm2835_wdt.c | 1 + drivers/watchdog/bcm47xx_wdt.c | 1 + drivers/watchdog/bcm7038_wdt.c | 1 + drivers/watchdog/bcm_kona_wdt.c | 1 + drivers/watchdog/bd70528_wdt.c | 1 + drivers/watchdog/cadence_wdt.c | 1 + drivers/watchdog/da9052_wdt.c | 1 + drivers/watchdog/da9055_wdt.c | 1 + drivers/watchdog/da9062_wdt.c | 1 + drivers/watchdog/da9063_wdt.c | 1 + drivers/watchdog/davinci_wdt.c | 1 + drivers/watchdog/digicolor_wdt.c | 1 + drivers/watchdog/dw_wdt.c | 1 + drivers/watchdog/ebc-c384_wdt.c | 1 + drivers/watchdog/ep93xx_wdt.c | 1 + drivers/watchdog/ftwdt010_wdt.c | 1 + drivers/watchdog/gpio_wdt.c | 1 + drivers/watchdog/hpwdt.c | 1 + drivers/watchdog/i6300esb.c | 1 + drivers/watchdog/iTCO_wdt.c | 1 + drivers/watchdog/ie6xx_wdt.c | 1 + drivers/watchdog/imgpdc_wdt.c | 1 + drivers/watchdog/imx2_wdt.c | 1 + drivers/watchdog/intel-mid_wdt.c | 1 + drivers/watchdog/it87_wdt.c | 1 + drivers/watchdog/kempld_wdt.c | 1 + drivers/watchdog/lpc18xx_wdt.c | 1 + drivers/watchdog/max63xx_wdt.c | 1 + drivers/watchdog/max77620_wdt.c | 1 + drivers/watchdog/mei_wdt.c | 1 + drivers/watchdog/mena21_wdt.c | 1 + drivers/watchdog/menf21bmc_wdt.c | 1 + drivers/watchdog/menz69_wdt.c | 1 + drivers/watchdog/meson_gxbb_wdt.c | 1 + drivers/watchdog/meson_wdt.c | 1 + drivers/watchdog/mlx_wdt.c | 1 + drivers/watchdog/moxart_wdt.c | 1 + drivers/watchdog/mtk_wdt.c | 1 + drivers/watchdog/ni903x_wdt.c | 1 + drivers/watchdog/nic7018_wdt.c | 1 + drivers/watchdog/npcm_wdt.c | 1 + drivers/watchdog/of_xilinx_wdt.c | 1 + drivers/watchdog/omap_wdt.c | 1 + drivers/watchdog/pm8916_wdt.c | 1 + drivers/watchdog/qcom-wdt.c | 1 + drivers/watchdog/rave-sp-wdt.c | 1 + drivers/watchdog/renesas_wdt.c | 1 + drivers/watchdog/retu_wdt.c | 1 + drivers/watchdog/rn5t618_wdt.c | 1 + drivers/watchdog/rza_wdt.c | 1 + drivers/watchdog/s3c2410_wdt.c | 1 + drivers/watchdog/sama5d4_wdt.c | 1 + drivers/watchdog/sirfsoc_wdt.c | 1 + drivers/watchdog/softdog.c | 1 + drivers/watchdog/sp5100_tco.c | 1 + drivers/watchdog/sprd_wdt.c | 1 + drivers/watchdog/st_lpc_wdt.c | 1 + drivers/watchdog/stmp3xxx_rtc_wdt.c | 1 + drivers/watchdog/stpmic1_wdt.c | 1 + drivers/watchdog/sunxi_wdt.c | 1 + drivers/watchdog/tangox_wdt.c | 1 + drivers/watchdog/tegra_wdt.c | 1 + drivers/watchdog/tqmx86_wdt.c | 1 + drivers/watchdog/ts4800_wdt.c | 1 + drivers/watchdog/ts72xx_wdt.c | 1 + drivers/watchdog/twl4030_wdt.c | 1 + drivers/watchdog/uniphier_wdt.c | 1 + drivers/watchdog/via_wdt.c | 1 + drivers/watchdog/w83627hf_wdt.c | 1 + drivers/watchdog/watchdog_core.c | 10 +- drivers/watchdog/wdat_wdt.c | 1 + drivers/watchdog/wm831x_wdt.c | 1 + drivers/watchdog/wm8350_wdt.c | 1 + drivers/watchdog/xen_wdt.c | 1 + drivers/watchdog/ziirave_wdt.c | 1 + include/asm-generic/export.h | 14 +- include/linux/export.h | 98 +++++++++++-- include/linux/module.h | 2 + init/Kconfig | 13 ++ kernel/module.c | 67 ++++++++- scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 +++ scripts/export_report.pl | 2 +- scripts/mod/modpost.c | 150 ++++++++++++++++--- scripts/mod/modpost.h | 9 ++ scripts/nsdeps | 60 ++++++++ 118 files changed, 697 insertions(+), 57 deletions(-) create mode 100644 Documentation/kbuild/namespaces.rst create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 1/12 module: support reading multiple values per modinfo tag
Similar to modpost's get_next_modinfo(), introduce get_next_modinfo() in kernel/module.c to acquire any further values associated with the same modinfo tag name. That is useful for any tags that have multiple occurrences (such as 'alias'), but is in particular introduced here as part of the symbol namespaces patch series to read the (potentially) multiple namespaces a module is importing.
--- kernel/module.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
kernel/module.c +15 -2
@@ -2481,7 +2481,8 @@ static char *next_string(char *string, unsigned long *secsize)return string; } -static char *get_modinfo (struct load_info *info,const char *tag) +static char *get_next_modinfo (const struct load_info *info,const char *tag, +char *prev) {char *p;unsigned int taglen =strlen (tag);
@@ -2492,13 +2493,25 @@ static char *get_modinfo(struct load_info *info, const char *tag)* get_modinfo() calls made before rewrite_section_headers() * must use sh_offset, as sh_addr isn't set! */ -for (p = (char *)info->hdr + infosec->sh_offset; p; p =next_string (p, &size)) { +char *modinfo = (char *)info->hdr + infosec->sh_offset; + +if (prev) { + size -= prev - modinfo; + modinfo =next_string (prev, &size); + } + +for (p = modinfo; p; p =next_string (p, &size)) {if (strncmp (p, tag, taglen) ==0 && p[taglen] =='=' )return p + taglen +1 ; }return NULL ; } +static char *get_modinfo (const struct load_info *info,const char *tag) +{ +return get_next_modinfo (info, tag,NULL ); +} +static void setup_modinfo (struct module *mod,struct load_info *info) {struct module_attribute *attr;
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 2/12 export: explicitly align struct kernel_symbol
In reply to Matthias MaennichThis change allows growing struct kernel_symbol without wasting bytes to alignment. It also concretized the alignment of ksymtab entries if relative references are used for ksymtab entries.
struct kernel_symbol was already implicitly being aligned to the word size, except on x86_64 and m68k, where it is aligned to 16 and 2 bytes, respectively.
As far as I can tell there is no requirement for aligning struct kernel_symbol to 16 bytes on x86_64, but gcc aligns structs to their size, and the linker aligns the custom __ksymtab sections to the largest data type contained within, so setting KSYM_ALIGN to 16 was necessary to stay consistent with the code generated for non-ASM EXPORT_SYMBOL(). Now that non-ASM EXPORT_SYMBOL() explicitly aligns to word size (8), KSYM_ALIGN is no longer necessary.
In case of relative references, the alignment has been changed accordingly to not waste space when adding new struct members.
As for m68k, struct kernel_symbol is aligned to 2 bytes even though the structure itself is 8 bytes; using a 4-byte alignment shouldn't hurt.
I manually verified the output of the __ksymtab sections didn't change on x86, x86_64, arm, arm64 and m68k. As expected, the section contents didn't change, and the ELF section alignment only changed on x86_64 and m68k. Feedback from other archs more than welcome.
--- arch/m68k/include/asm/export.h | 1 - include/asm-generic/export.h | 8 +++----- include/linux/export.h | 3 ++- 3 files changed, 5 insertions(+), 7 deletions(-)
arch/m68k/include/asm/export.h +0 -1
@@ -1,3 +1,2 @@ -#define KSYM_ALIGN 2#define KCRC_ALIGN 2#include <asm-generic/export.h>
include/asm-generic/export.h +3 -5
@@ -4,15 +4,13 @@#ifndef KSYM_FUNC #define KSYM_FUNC (x) x#endif -#ifdef CONFIG_64BIT -#ifndef KSYM_ALIGN +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +#define KSYM_ALIGN 4 +#elif defined(CONFIG_64BIT )#define KSYM_ALIGN 8 -#endif #else -#ifndef KSYM_ALIGN #define KSYM_ALIGN 4#endif -#endif #ifndef KCRC_ALIGN #define KCRC_ALIGN 4#endif
include/linux/export.h +2 -1
@@ -52,7 +52,7 @@ extern struct module __this_module;#define __KSYMTAB_ENTRY (sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ - " .balign 8 \n" \ + " .balign 4 \n" \ "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \
@@ -66,6 +66,7 @@ struct kernel_symbol {#define __KSYMTAB_ENTRY (sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ = { (unsigned long)&sym, __kstrtab_##sym }struct kernel_symbol {
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 3/12 module: add support for symbol namespaces.
In reply to Matthias MaennichThe 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.
--- include/asm-generic/export.h | 6 +-- include/linux/export.h | 91 +++++++++++++++++++++++++++++------- include/linux/module.h | 2 + kernel/module.c | 43 +++++++++++++++++ 4 files changed, 123 insertions(+), 19 deletions(-)
include/asm-generic/export.h +3 -3
@@ -17,11 +17,11 @@ .macro __put, val, name#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS - .long \val - ., \name - . + .long \val - ., \name - ., 0 - .#elif defined(CONFIG_64BIT ) - .quad \val, \name + .quad \val, \name, 0#else - .long \val, \name + .long \val, \name, 0#endif .endm
include/linux/export.h +75 -16
167 lines not on this page · raw message
include/linux/module.h +2 -0
@@ -280,6 +280,8 @@ struct notifier_block;#ifdef CONFIG_MODULES +#define MODULE_IMPORT_NS (ns) MODULE_INFO(import_ns, #ns) +extern int modules_disabled;/* for sysctl */ /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get (const char *symbol);
kernel/module.c +43 -0
61 lines not on this page · raw message
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 4/12 modpost: add support for symbol namespaces
In reply to Matthias MaennichAdd support for symbols that are exported into namespaces. For that, extract any namespace suffix from the symbol name. In addition, emit a warning whenever a module refers to an exported symbol without explicitly importing the namespace that it is defined in. This patch consistently adds the namespace suffix to symbol names exported into Module.symvers.
Example warning emitted by modpost in case of the above violation:
WARNING: module ums-usbat uses symbol usb_stor_resume from namespace USB_STORAGE, but does not import it.
--- Documentation/kbuild/modules.rst | 7 ++- scripts/export_report.pl | 2 +- scripts/mod/modpost.c | 104 ++++++++++++++++++++++++++----- scripts/mod/modpost.h | 7 +++ 4 files changed, 101 insertions(+), 19 deletions(-)
Documentation/kbuild/modules.rst +5 -2
@@ -470,9 +470,12 @@ build. The syntax of the Module.symvers file is:: - <CRC> <Symbol> <module> + <CRC> <Symbol> <Namespace> <Module> <Export Type> - 0x2d036834 scsi_remove_host drivers/scsi/scsi_mod + 0xe1cc2a05 usb_stor_suspend USB_STORAGE drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL + + The fields are separated by tabs and values may be empty (e.g. + if no namespace is defined for an exported symbol). For a kernel build without CONFIG_MODVERSIONS enabled, the CRC would read 0x00000000.
scripts/export_report.pl +1 -1
@@ -94,7 +94,7 @@ if (defined $opt{'o'}) { # while ( <$module_symvers> ) { chomp; - my (undef, $symbol, $module, $gpl) = split; + my (undef, $symbol, $namespace, $module, $gpl) = split('\t'); $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; } close($module_symvers);
scripts/mod/modpost.c +88 -16
192 lines not on this page · raw message
scripts/mod/modpost.h +7 -0
@@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);void buf_write (struct buffer *buf,const char *s,int len); +struct namespace_list { +struct namespace_list *next; +char namespace[0 ]; +}; +struct module {struct module *next;const char *name;
@@ -121,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Actual imported namespaces +struct namespace_list *imported_namespaces; };struct elf_info {
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 5/12 module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
In reply to Matthias MaennichIf MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is enabled (default=n), the requirement for modules to import all namespaces that are used by the module is relaxed.
Enabling this option effectively allows (invalid) modules to be loaded while only a warning is emitted.
Disabling this option keeps the enforcement at module loading time and loading is denied if the module's imports are not satisfactory.
--- init/Kconfig | 13 +++++++++++++ kernel/module.c | 11 +++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
init/Kconfig +13 -0
@@ -2119,6 +2119,19 @@ config MODULE_COMPRESS_XZ endchoice +config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + bool "Allow loading of modules with missing namespace imports" + help + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in + a namespace. A module that makes use of a symbol exported with such a + namespace is required to import the namespace via MODULE_IMPORT_NS(). + There is no technical reason to enforce correct namespace imports, + but it creates consistency between symbols defining namespaces and + users importing namespaces they make use of. This option relaxes this + requirement and lifts the enforcement when loading a module. + + If unsure, say N. + config TRIM_UNUSED_KSYMS bool "Trim unused exported kernel symbols" depends on MODULES && !UNUSED_SYMBOLS
kernel/module.c +9 -2
@@ -1408,9 +1408,16 @@ static int verify_namespace_is_imported(const struct load_info *info, imported_namespace =get_next_modinfo ( info,"import_ns" , imported_namespace); } -pr_err ("%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , - mod->name,kernel_symbol_name (sym), namespace); +#ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS + pr_warn( +#else + pr_err( +#endif +"%s: module uses symbol (%s) from namespace %s, but does not import it.\n" , + mod->name, kernel_symbol_name(sym), namespace); +#ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS return -EINVAL ; +#endif }return 0 ; }
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 6/12 export: allow definition default namespaces in Makefiles or sources
In reply to Matthias MaennichTo avoid excessive usage of EXPORT_SYMBOL_NS(sym, MY_NAMESPACE), where MY_NAMESPACE will always be the namespace we are exporting to, allow exporting all definitions of EXPORT_SYMBOL() and friends by defining DEFAULT_SYMBOL_NAMESPACE.
For example, to export all symbols defined in usb-common into the namespace USB_COMMON, add a line like this to drivers/usb/common/Makefile:
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
That is equivalent to changing all EXPORT_SYMBOL(sym) definitions to EXPORT_SYMBOL_NS(sym, USB_COMMON). Subsequently all symbol namespaces functionality will apply.
Another way of making use of this feature is to define the namespace within source or header files similar to how TRACE_SYSTEM defines are used:
#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
Please note that, as opposed to TRACE_SYSTEM, DEFAULT_SYMBOL_NAMESPACE has to be defined before including include/linux/export.h.
If DEFAULT_SYMBOL_NAMESPACE is defined, a symbol can still be exported to another namespace by using EXPORT_SYMBOL_NS() and friends with explicitly specifying the namespace.
--- include/linux/export.h | 6 ++++++ 1 file changed, 6 insertions(+)
include/linux/export.h +6 -0
@@ -166,6 +166,12 @@ struct kernel_symbol {#define __EXPORT_SYMBOL ___EXPORT_SYMBOL#endif +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL (sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif +#define EXPORT_SYMBOL (sym) __EXPORT_SYMBOL(sym, "")#define EXPORT_SYMBOL_GPL (sym) __EXPORT_SYMBOL(sym, "_gpl")#define EXPORT_SYMBOL_GPL_FUTURE (sym) __EXPORT_SYMBOL(sym, "_gpl_future")
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 7/12 modpost: add support for generating namespace dependencies
In reply to Matthias MaennichThis patch adds an option to modpost to generate a <module>.ns_deps file per module, containing the namespace dependencies for that module.
E.g. if the linked module my-module.ko would depend on the symbol myfunc.MY_NS in the namespace MY_NS, the my-module.ns_deps file created by modpost would contain the entry MY_NS to express the namespace dependency of my-module imposed by using the symbol myfunc.
These files can subsequently be used by static analysis tools (like coccinelle scripts) to address issues with missing namespace imports. A later patch of this series will introduce such a script 'nsdeps' and a corresponding make target to automatically add missing MODULE_IMPORT_NS() definitions to the module's sources. For that it uses the information provided in the generated .ns_deps files.
--- .gitignore | 1 + Makefile | 2 +- scripts/mod/modpost.c | 54 +++++++++++++++++++++++++++++++++++++++---- scripts/mod/modpost.h | 2 ++ 4 files changed, 53 insertions(+), 6 deletions(-)
.gitignore +1 -0
@@ -32,6 +32,7 @@ *.lzo *.mod *.mod.c +*.ns_deps *.o *.o.* *.order
Makefile +1 -1
@@ -1669,7 +1669,7 @@ clean: $(clean-dirs) -o -name '*.ko.*' \ -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ -o -name '*.dwo' -o -name '*.lst' \ - -o -name '*.su' -o -name '*.mod' \ + -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ -o -name '*.lex.c' -o -name '*.tab.[ch]' \ -o -name '*.asn1.[ch]' \
scripts/mod/modpost.c +49 -5
96 lines not on this page · raw message
scripts/mod/modpost.h +2 -0
@@ -126,6 +126,8 @@ struct module {struct buffer dev_table_buf;char srcversion[25 ];int is_dot_o; +// Required namespace dependencies +struct namespace_list *required_namespaces;// Actual imported namespaces struct namespace_list *imported_namespaces; };
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 8/12 scripts: Coccinelle script for namespace dependencies.
In reply to Matthias MaennichA script that uses the '<module>.ns_deps' files generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace with EXPORT_SYMBOL_NS() or define DEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
--- MAINTAINERS | 5 ++ Makefile | 12 +++++ scripts/Makefile.modpost | 4 +- scripts/coccinelle/misc/add_namespace.cocci | 23 ++++++++ scripts/nsdeps | 60 +++++++++++++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 scripts/coccinelle/misc/add_namespace.cocci create mode 100644 scripts/nsdeps
MAINTAINERS +5 -0
@@ -11436,6 +11436,11 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git F: tools/include/nolibc/ +NSDEPS +M: Matthias Maennich <[email protected]> +S: Maintained +F: scripts/nsdeps + NTB AMD DRIVER M: Shyam Sundar S K <[email protected]> L: [email protected]
Makefile +12 -0
@@ -1500,6 +1500,9 @@ help: @echo ' headerdep - Detect inclusion cycles in headers' @echo ' coccicheck - Check with Coccinelle' @echo '' + @echo 'Tools:' + @echo ' nsdeps - Generate missing symbol namespace dependencies' + @echo '' @echo 'Kernel selftest:' @echo ' kselftest - Build and run kernel selftest (run as root)' @echo ' Build, install, and boot kernel before'
@@ -1687,6 +1690,15 @@ quiet_cmd_tags = GEN $@ tags TAGS cscope gtags: FORCE $(call cmd,tags) +# Script to generate missing namespace dependencies +# --------------------------------------------------------------------------- + +PHONY += nsdeps + +nsdeps: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + # Scripts to check various things for consistency # ---------------------------------------------------------------------------
scripts/Makefile.modpost +3 -1
@@ -56,7 +56,8 @@ MODPOST = scripts/mod/modpost \ $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ - $(if $(KBUILD_MODPOST_WARN),-w) + $(if $(KBUILD_MODPOST_WARN),-w) \ + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) ifdef MODPOST_VMLINUX
@@ -134,6 +135,7 @@ $(modules): %.ko :%.o %.mod.o FORCE targets += $(modules) +nsdeps: __modpost # Add FORCE to the prequisites of a target to force it to be always rebuilt. # ---------------------------------------------------------------------------
scripts/coccinelle/misc/add_namespace.cocci new file +23 -0
@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +/// Adds missing MODULE_IMPORT_NS statements to source files +/// +/// This script is usually called from scripts/nsdeps with -D ns=<namespace> to +/// add a missing namespace tag to a module source file. +/// + +@has_ns_import@ +declarer name MODULE_IMPORT_NS; +identifier virtual.ns; +@@ +MODULE_IMPORT_NS(ns); + +// Add missing imports, but only adjacent to a MODULE_LICENSE statement. +// That ensures we are adding it only to the main module source file. +@do_import depends on !has_ns_import@ +declarer name MODULE_LICENSE; +expression license; +identifier virtual.ns; +@@ +MODULE_LICENSE(license); ++ MODULE_IMPORT_NS(ns);
scripts/nsdeps new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Re: [PATCH v4 08/12] scripts: Coccinelle script for namespace dependencies.
Quoted 13 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' files generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.
Quoted 8 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Acked-by Julia Lawall <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Without any correct dependency,
this does not work.
$ make clean; make nsdeps cat: modules.order: No such file or directory cat: ./modules.order: No such file or directory
I do not see any point in the Makefile changes.
Signature · 2 lines
Best Regards Masahiro Yamada
Matthias Maennich
maintainerRe: [PATCH v4 08/12] scripts: Coccinelle script for namespace dependencies.
Quoted 24 lines · Masahiro Yamada
Quoted 13 lines · Matthias Maennich
A script that uses the '<module>.ns_deps' files generated by modpost to automatically add the required symbol namespace dependencies to each module.
Usage:
1) Move some symbols to a namespace withEXPORT_SYMBOL_NS()or defineDEFAULT_SYMBOL_NAMESPACE
2) Run 'make' (or 'make modules') and get warnings about modules not importing that namespace.
3) Run 'make nsdeps' to automatically add required import statements to said modules.Quoted 8 lines
This makes it easer for subsystem maintainers to introduce and maintain symbol namespaces into their codebase.
Co-developed-by Martijn Coenen <[email protected]>Signed-off-by Martijn Coenen <[email protected]>Acked-by Julia Lawall <[email protected]>Reviewed-by Greg Kroah-Hartman <[email protected]>Signed-off-by Matthias Maennich <[email protected]>
Quoted 2 lines
Without any correct dependency,
this does not work.
You are right, 'nsdeps' needs to depend on 'modules' to make that work. I will fix that in the next version.
Quoted 6 lines
$ make clean; make nsdeps cat: modules.order: No such file or directory cat: ./modules.order: No such file or directoryI do not see any point in the
Makefilechanges.
Matthias Maennich
maintainerPATCH v4 9/12 docs: Add documentation for Symbol Namespaces
In reply to Matthias MaennichDescribe using Symbol Namespaces from a perspective of a user. I.e. module authors or subsystem maintainers.
--- Documentation/kbuild/namespaces.rst | 154 +++++++++++++++++++++++ Documentation/kernel-hacking/hacking.rst | 18 +++ 2 files changed, 172 insertions(+) create mode 100644 Documentation/kbuild/namespaces.rst
Documentation/kbuild/namespaces.rst new file +154 -0
@@ -0,0 +1,154 @@ +================= +Symbol Namespaces +================= + +The following document describes how to use Symbol Namespaces to structure the +export surface of in-kernel symbols exported through the family of +EXPORT_SYMBOL() macros. + +.. Table of Contents + + === 1 Introduction + === 2 How to define Symbol Namespaces + --- 2.1 Using the EXPORT_SYMBOL macros + --- 2.2 Using the DEFAULT_SYMBOL_NAMESPACE define + === 3 How to use Symbols exported in Namespaces + === 4 Loading Modules that use namespaced Symbols + === 5 Automatically creating MODULE_IMPORT_NS statements + +1. Introduction +=============== + +Symbol Namespaces have been introduced as a means to structure the export +surface of the in-kernel API. It allows subsystem maintainers to partition +their exported symbols into separate namespaces. That is useful for +documentation purposes (think of the SUBSYSTEM_DEBUG namespace) as well as for +limiting the availability of a set of symbols for use in other parts of the +kernel. As of today, modules that make use of symbols exported into namespaces, +are required to import the namespace. Otherwise the kernel will, depending on +its configuration, reject loading the module or warn about a missing import. + +2. How to define Symbol Namespaces +================================== + +Symbols can be exported into namespace using different methods. All of them are +changing the way EXPORT_SYMBOL and friends are instrumented to create ksymtab +entries. + +2.1 Using the EXPORT_SYMBOL macros +================================== + +In addition to the macros EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(), that allow +exporting of kernel symbols to the kernel symbol table, variants of these are +available to export symbols into a certain namespace: EXPORT_SYMBOL_NS() and +EXPORT_SYMBOL_NS_GPL(). They take one additional argument: the namespace. +Please note that due to macro expansion that argument needs to be a +preprocessor symbol. E.g. to export the symbol `usb_stor_suspend` into the +namespace `USB_STORAGE`, use:: + + EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE); + +The corresponding ksymtab entry struct `kernel_symbol` will have the member +`namespace` set accordingly. A symbol that is exported without a namespace will +refer to `NULL`. There is no default namespace if none is defined. `modpost` +and kernel/module.c make use the namespace at build time or module load time, +respectively. + +2.2 Using the DEFAULT_SYMBOL_NAMESPACE define +============================================= + +Defining namespaces for all symbols of a subsystem can be very verbose and may +become hard to maintain. Therefore a default define (DEFAULT_SYMBOL_NAMESPACE) +is been provided, that, if set, will become the default for all EXPORT_SYMBOL() +and EXPORT_SYMBOL_GPL() macro expansions that do not specify a namespace. + +There are multiple ways of specifying this define and it depends on the +subsystem and the maintainer's preference, which one to use. The first option +is to define the default namespace in the `Makefile` of the subsystem. E.g. to +export all symbols defined in usb-common into the namespace USB_COMMON, add a +line like this to drivers/usb/common/Makefile:: + + ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON + +That will affect all EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() statements. A +symbol exported with EXPORT_SYMBOL_NS() while this definition is present, will +still be exported into the namespace that is passed as the namespace argument +as this argument has preference over a default symbol namespace. + +A second option to define the default namespace is directly in the compilation +unit as preprocessor statement. The above example would then read:: + + #undef DEFAULT_SYMBOL_NAMESPACE + #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON + +within the corresponding compilation unit before any EXPORT_SYMBOL macro is +used. + +3. How to use Symbols exported in Namespaces +============================================ + +In order to use symbols that are exported into namespaces, kernel modules need +to explicitly import these namespaces. Otherwise the kernel might reject to +load the module. The module code is required to use the macro MODULE_IMPORT_NS +for the namespaces it uses symbols from. E.g. a module using the +usb_stor_suspend symbol from above, needs to import the namespace USB_STORAGE +using a statement like:: + + MODULE_IMPORT_NS(USB_STORAGE); + +This will create a `modinfo` tag in the module for each imported namespace. +This has the side effect, that the imported namespaces of a module can be +inspected with modinfo:: + + $ modinfo drivers/usb/storage/ums-karma.ko + [...] + import_ns: USB_STORAGE + [...] + + +It is advisable to add the MODULE_IMPORT_NS() statement close to other module +metadata definitions like MODULE_AUTHOR() or MODULE_LICENSE(). Refer to section +5. for a way to create missing import statements automatically. + +4. Loading Modules that use namespaced Symbols +============================================== + +At module loading time (e.g. `insmod`), the kernel will check each symbol +referenced from the module for its availability and whether the namespace it +might be exported to has been imported by the module. The default behaviour of +the kernel is to reject loading modules that don't specify sufficient imports. +An error will be logged and loading will be failed with EINVAL. In order to +allow loading of modules that don't satisfy this precondition, a configuration +option is available: Setting MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y will +enable loading regardless, but will emit a warning. + +5. Automatically creating MODULE_IMPORT_NS statements +===================================================== + +Missing namespaces imports can easily be detected at build time. In fact, +modpost will emit a warning if a module uses a symbol from a namespace +without importing it. +MODULE_IMPORT_NS() statements will usually be added at a definite location +(along with other module meta data). To make the life of module authors (and +subsystem maintainers) easier, a script and make target is available to fixup +missing imports. Fixing missing imports can be done with:: + + $ make nsdeps + +A typical scenario for module authors would be:: + + - write code that depends on a symbol from a not imported namespace + - `make` + - notice the warning of modpost telling about a missing import + - run `make nsdeps` to add the import to the correct code location + +For subsystem maintainers introducing a namespace, the steps are very similar. +Again, `make nsdeps` will eventually add the missing namespace imports for +in-tree modules:: + + - move or add symbols to a namespace (e.g. with EXPORT_SYMBOL_NS()) + - `make` (preferably with an allmodconfig to cover all in-kernel + modules) + - notice the warning of modpost telling about a missing import + - run `make nsdeps` to add the import to the correct code location +
Documentation/kernel-hacking/hacking.rst +18 -0
@@ -594,6 +594,24 @@ internal implementation issue, and not really an interface. Some maintainers and developers may however require EXPORT_SYMBOL_GPL() when adding any new APIs or functionality. +:c:func:`EXPORT_SYMBOL_NS()` +---------------------------- + +Defined in ``include/linux/export.h`` + +This is the variant of `EXPORT_SYMBOL()` that allows specifying a symbol +namespace. Symbol Namespaces are documented in +``Documentation/kbuild/namespaces.rst``. + +:c:func:`EXPORT_SYMBOL_NS_GPL()` +-------------------------------- + +Defined in ``include/linux/export.h`` + +This is the variant of `EXPORT_SYMBOL_GPL()` that allows specifying a symbol +namespace. Symbol Namespaces are documented in +``Documentation/kbuild/namespaces.rst``. + Routines and Conventions ========================
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Re: [PATCH v4 09/12] docs: Add documentation for Symbol Namespaces
Quoted 4 lines · Matthias Maennich
Describe using Symbol Namespaces from a perspective of a user. I.e. module authors or subsystem maintainers.
Signed-off-by Matthias Maennich <[email protected]>
Nice, it's good to have stuff to point people at.
Matthias Maennich
maintainerPATCH v4 10/12 usb-storage: remove single-use define for debugging
In reply to Matthias MaennichUSB_STORAGE was defined as "usb-storage: " and used in a single location as argument to printk. In order to be able to use the name 'USB_STORAGE', drop the definition and use the string directly for the printk call.
--- drivers/usb/storage/debug.h | 2 -- drivers/usb/storage/scsiglue.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-)
drivers/usb/storage/debug.h +0 -2
@@ -29,8 +29,6 @@#include <linux/kernel.h> -#define USB_STORAGE "usb-storage: " -#ifdef CONFIG_USB_STORAGE_DEBUG void usb_stor_show_command (const struct us_data *us,struct scsi_cmnd *srb); void usb_stor_show_sense(const struct us_data *us, unsigned char key,
drivers/usb/storage/scsiglue.c +1 -1
@@ -379,7 +379,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,/* check for state-transition errors */ if (us->srb !=NULL ) { - printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n", +printk (KERN_ERR "usb-storage: Error in %s: us->srb = %p\n" , __func__, us->srb);return SCSI_MLQUEUE_HOST_BUSY ; }
Signature · 1 line
2.23.0.187.g17f5b7556c-goog
Matthias Maennich
maintainerPATCH v4 11/12 RFC: usb-storage: export symbols in USB_STORAGE namespace
In reply to Matthias MaennichModules using these symbols are required to explicitly import the namespace. This patch was generated with the following steps and serves as a reference to use the symbol namespace feature:
1) Define DEFAULT_SYMBOL_NAMESPACE in the corresponding Makefile
2) make (see warnings during modpost about missing imports)
3) make nsdeps
Instead of a DEFAULT_SYMBOL_NAMESPACE definition, the EXPORT_SYMBOL_NS variants can be used to explicitly specify the namespace. The advantage of the method used here is that newly added symbols are automatically exported and existing ones are exported without touching their respective EXPORT_SYMBOL macro expansion.
--- drivers/usb/storage/Makefile | 2 ++ drivers/usb/storage/alauda.c | 1 + drivers/usb/storage/cypress_atacb.c | 1 + drivers/usb/storage/datafab.c | 1 + drivers/usb/storage/ene_ub6250.c | 1 + drivers/usb/storage/freecom.c | 1 + drivers/usb/storage/isd200.c | 1 + drivers/usb/storage/jumpshot.c | 1 + drivers/usb/storage/karma.c | 1 + drivers/usb/storage/onetouch.c | 1 + drivers/usb/storage/realtek_cr.c | 1 + drivers/usb/storage/sddr09.c | 1 + drivers/usb/storage/sddr55.c | 1 + drivers/usb/storage/shuttle_usbat.c | 1 + drivers/usb/storage/uas.c | 1 + 15 files changed, 16 insertions(+)
drivers/usb/storage/Makefile +2 -0
@@ -8,6 +8,8 @@ ccflags-y := -I $(srctree)/drivers/scsi +ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE + obj-$(CONFIG_USB_UAS) += uas.o obj-$(CONFIG_USB_STORAGE) += usb-storage.o
drivers/usb/storage/alauda.c +1 -0
@@ -36,6 +36,7 @@MODULE_DESCRIPTION ("Driver for Alauda-based card readers" );MODULE_AUTHOR ("Daniel Drake <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * Status bytes
drivers/usb/storage/cypress_atacb.c +1 -0
@@ -22,6 +22,7 @@MODULE_DESCRIPTION ("SAT support for Cypress USB/ATA bridges with ATACB" );MODULE_AUTHOR ("Matthieu Castet <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/datafab.c +1 -0
@@ -54,6 +54,7 @@MODULE_DESCRIPTION ("Driver for Datafab USB Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );struct datafab_info {unsigned long sectors;/* total sector count */
drivers/usb/storage/ene_ub6250.c +1 -0
@@ -26,6 +26,7 @@MODULE_DESCRIPTION ("Driver for ENE UB6250 reader" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_FIRMWARE (SD_INIT1_FIRMWARE );MODULE_FIRMWARE (SD_INIT2_FIRMWARE );MODULE_FIRMWARE (SD_RW_FIRMWARE );
drivers/usb/storage/freecom.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for Freecom USB/IDE adaptor" );MODULE_AUTHOR ("David Brown <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (struct us_data *us,void *ibuffer,int length);
drivers/usb/storage/isd200.c +1 -0
@@ -53,6 +53,7 @@MODULE_DESCRIPTION ("Driver for In-System Design, Inc. ISD200 ASIC" );MODULE_AUTHOR ("Björn Stenberg <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int isd200_Initialization (struct us_data *us);
drivers/usb/storage/jumpshot.c +1 -0
@@ -51,6 +51,7 @@MODULE_DESCRIPTION ("Driver for Lexar \"Jumpshot\" Compact Flash reader" );MODULE_AUTHOR ("Jimmie Mayfield <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/karma.c +1 -0
@@ -23,6 +23,7 @@MODULE_DESCRIPTION ("Driver for Rio Karma" );MODULE_AUTHOR ("Bob Copeland <[email protected]>, Keith Bennett <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define RIO_PREFIX "RIOP\x00"#define RIO_PREFIX_LEN 5
drivers/usb/storage/onetouch.c +1 -0
@@ -25,6 +25,7 @@MODULE_DESCRIPTION ("Maxtor USB OneTouch hard drive button driver" );MODULE_AUTHOR ("Nick Sillik <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );#define ONETOUCH_PKT_LEN 0x02#define ONETOUCH_BUTTON KEY_PROG1
drivers/usb/storage/realtek_cr.c +1 -0
@@ -35,6 +35,7 @@MODULE_DESCRIPTION ("Driver for Realtek USB Card Reader" );MODULE_AUTHOR ("wwang <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int auto_delink_en =1 ;module_param (auto_delink_en, int,S_IRUGO |S_IWUSR );
drivers/usb/storage/sddr09.c +1 -0
@@ -47,6 +47,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-09 SmartMedia reader" );MODULE_AUTHOR ("Andries Brouwer <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );static int usb_stor_sddr09_dpcm_init (struct us_data *us);static int sddr09_transport (struct scsi_cmnd *srb,struct us_data *us);
drivers/usb/storage/sddr55.c +1 -0
@@ -29,6 +29,7 @@MODULE_DESCRIPTION ("Driver for SanDisk SDDR-55 SmartMedia reader" );MODULE_AUTHOR ("Simon Munton" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* * The table of devices
drivers/usb/storage/shuttle_usbat.c +1 -0
@@ -48,6 +48,7 @@MODULE_DESCRIPTION ("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable" );MODULE_AUTHOR ("Daniel Drake <[email protected]>, Robert Baruch <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );/* Supported device types */ #define USBAT_DEV_HP8200 0x01
drivers/usb/storage/uas.c +1 -0
@@ -1219,5 +1219,6 @@ static struct usb_driver uas_driver = {module_usb_driver (uas_driver);MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS (USB_STORAGE );MODULE_AUTHOR ("Hans de Goede <[email protected]>, Matthew Wilcox and Sarah Sharp" );
Signature · 1 line
2.23.0.187.g17f5b7556c-goog