Symbol Namespaces¶
The following document describes how to use Symbol Namespaces to structure theexport surface of in-kernel symbols exported through the family ofEXPORT_SYMBOL() macros.
Introduction¶
Symbol Namespaces have been introduced as a means to structure the exportsurface of the in-kernel API. It allows subsystem maintainers to partitiontheir exported symbols into separate namespaces. That is useful fordocumentation purposes (think of the SUBSYSTEM_DEBUG namespace) as well as forlimiting the availability of a set of symbols for use in other parts of thekernel. As of today, modules that make use of symbols exported into namespaces,are required to import the namespace. Otherwise the kernel will, depending onits configuration, reject loading the module or warn about a missing import.
Additionally, it is possible to put symbols into a module namespace, strictlylimiting which modules are allowed to use these symbols.
How to define Symbol Namespaces¶
Symbols can be exported into namespace using different methods. All of them arechanging the way EXPORT_SYMBOL and friends are instrumented to create ksymtabentries.
Using the EXPORT_SYMBOL macros¶
In addition to the macrosEXPORT_SYMBOL() andEXPORT_SYMBOL_GPL(), that allowexporting of kernel symbols to the kernel symbol table, variants of these areavailable to export symbols into a certain namespace:EXPORT_SYMBOL_NS() andEXPORT_SYMBOL_NS_GPL(). They take one additional argument: the namespace as astring constant. Note that this string must not contain whitespaces.E.g. to export the symbolusb_stor_suspend into thenamespaceUSB_STORAGE, use:
EXPORT_SYMBOL_NS(usb_stor_suspend, "USB_STORAGE");
The corresponding ksymtab entry structkernel_symbol will have the membernamespace set accordingly. A symbol that is exported without a namespace willrefer toNULL. There is no default namespace if none is defined.modpostand kernel/module/main.c make use the namespace at build time or module loadtime, respectively.
Using the DEFAULT_SYMBOL_NAMESPACE define¶
Defining namespaces for all symbols of a subsystem can be very verbose and maybecome hard to maintain. Therefore a default define (DEFAULT_SYMBOL_NAMESPACE)is been provided, that, if set, will become the default for allEXPORT_SYMBOL()andEXPORT_SYMBOL_GPL() macro expansions that do not specify a namespace.
There are multiple ways of specifying this define and it depends on thesubsystem and the maintainer’s preference, which one to use. The first optionis to define the default namespace in theMakefile of the subsystem. E.g. toexport all symbols defined in usb-common into the namespace USB_COMMON, add aline like this to drivers/usb/common/Makefile:
ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"USB_COMMON"'
That will affect allEXPORT_SYMBOL() andEXPORT_SYMBOL_GPL() statements. Asymbol exported withEXPORT_SYMBOL_NS() while this definition is present, willstill be exported into the namespace that is passed as the namespace argumentas this argument has preference over a default symbol namespace.
A second option to define the default namespace is directly in the compilationunit as preprocessor statement. The above example would then read:
#define DEFAULT_SYMBOL_NAMESPACE "USB_COMMON"
within the corresponding compilation unit before the #include for<linux/export.h>. Typically it’s placed before the first #include statement.
Using the EXPORT_SYMBOL_FOR_MODULES() macro¶
Symbols exported using this macro are put into a module namespace. Thisnamespace cannot be imported. These exports are GPL-only as they are onlyintended for in-tree modules.
The macro takes a comma separated list of module names, allowing only thosemodules to access this symbol. Simple tail-globs are supported.
For example:
EXPORT_SYMBOL_FOR_MODULES(preempt_notifier_inc, "kvm,kvm-*")
will limit usage of this symbol to modules whose name matches the givenpatterns.
How to use Symbols exported in Namespaces¶
In order to use symbols that are exported into namespaces, kernel modules needto explicitly import these namespaces. Otherwise the kernel might reject toload the module. The module code is required to use the macro MODULE_IMPORT_NSfor the namespaces it uses symbols from. E.g. a module using theusb_stor_suspend symbol from above, needs to import the namespace USB_STORAGEusing a statement like:
MODULE_IMPORT_NS("USB_STORAGE");This will create amodinfo tag in the module for each imported namespace.This has the side effect, that the imported namespaces of a module can beinspected with modinfo:
$ modinfo drivers/usb/storage/ums-karma.ko[...]import_ns: USB_STORAGE[...]
It is advisable to add theMODULE_IMPORT_NS() statement close to other modulemetadata definitions likeMODULE_AUTHOR() orMODULE_LICENSE().
Loading Modules that use namespaced Symbols¶
At module loading time (e.g.insmod), the kernel will check each symbolreferenced from the module for its availability and whether the namespace itmight be exported to has been imported by the module. The default behaviour ofthe 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 toallow loading of modules that don’t satisfy this precondition, a configurationoption is available: Setting MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y willenable loading regardless, but will emit a warning.
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 namespacewithout 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 (andsubsystem maintainers) easier, a script and make target is available to fixupmissing 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,makensdeps will eventually add the missing namespace imports forin-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
You can also run nsdeps for external module builds. A typical usage is:
$ make -C <path_to_kernel_src> M=$PWD nsdeps
Note: it will happily generate an import statement for the module namespace;which will not work and generates build and runtime failures.