Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'modules-for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux

Pull modules updates from Jessica Yu:
"The main bulk of this pull request introduces a new exported symbol
namespaces feature. The number of exported symbols is increasingly
growing with each release (we're at about 31k exports as of 5.3-rc7)
and we currently have no way of visualizing how these symbols are
"clustered" or making sense of this huge export surface.

Namespacing exported symbols allows kernel developers to more
explicitly partition and categorize exported symbols, as well as more
easily limiting the availability of namespaced symbols to other parts
of the kernel. For starters, we have introduced the USB_STORAGE
namespace to demonstrate the API's usage. I have briefly summarized
the feature and its main motivations in the tag below.

Summary:

- Introduce exported symbol namespaces.

This new feature allows subsystem maintainers to partition and
categorize their exported symbols into explicit namespaces. Module
authors are now required to import the namespaces they need.

Some of the main motivations of this feature include: allowing
kernel developers to better manage the export surface, allow
subsystem maintainers to explicitly state that usage of some
exported symbols should only be limited to certain users (think:
inter-module or inter-driver symbols, debugging symbols, etc), as
well as more easily limiting the availability of namespaced symbols
to other parts of the kernel.

With the module import requirement, it is also easier to spot the
misuse of exported symbols during patch review.

Two new macros are introduced: EXPORT_SYMBOL_NS() and
EXPORT_SYMBOL_NS_GPL(). The API is thoroughly documented in
Documentation/kbuild/namespaces.rst.

- Some small code and kbuild cleanups here and there"

* tag 'modules-for-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux:
module: Remove leftover '#undef' from export header
module: remove unneeded casts in cmp_name()
module: move CONFIG_UNUSED_SYMBOLS to the sub-menu of MODULES
module: remove redundant 'depends on MODULES'
module: Fix link failure due to invalid relocation on namespace offset
usb-storage: export symbols in USB_STORAGE namespace
usb-storage: remove single-use define for debugging
docs: Add documentation for Symbol Namespaces
scripts: Coccinelle script for namespace dependencies.
modpost: add support for generating namespace dependencies
export: allow definition default namespaces in Makefiles or sources
module: add config option MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
modpost: add support for symbol namespaces
module: add support for symbol namespaces.
export: explicitly align struct kernel_symbol
module: support reading multiple values per modinfo tag

+615 -70
+1
.gitignore
··· 32 32 *.lzo 33 33 *.mod 34 34 *.mod.c 35 + *.ns_deps 35 36 *.o 36 37 *.o.* 37 38 *.patch
+5 -2
Documentation/kbuild/modules.rst
··· 470 470 471 471 The syntax of the Module.symvers file is:: 472 472 473 - <CRC> <Symbol> <module> 473 + <CRC> <Symbol> <Namespace> <Module> <Export Type> 474 474 475 - 0x2d036834 scsi_remove_host drivers/scsi/scsi_mod 475 + 0xe1cc2a05 usb_stor_suspend USB_STORAGE drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL 476 + 477 + The fields are separated by tabs and values may be empty (e.g. 478 + if no namespace is defined for an exported symbol). 476 479 477 480 For a kernel build without CONFIG_MODVERSIONS enabled, the CRC 478 481 would read 0x00000000.
+154
Documentation/kbuild/namespaces.rst
··· 1 + ================= 2 + Symbol Namespaces 3 + ================= 4 + 5 + The following document describes how to use Symbol Namespaces to structure the 6 + export surface of in-kernel symbols exported through the family of 7 + EXPORT_SYMBOL() macros. 8 + 9 + .. Table of Contents 10 + 11 + === 1 Introduction 12 + === 2 How to define Symbol Namespaces 13 + --- 2.1 Using the EXPORT_SYMBOL macros 14 + --- 2.2 Using the DEFAULT_SYMBOL_NAMESPACE define 15 + === 3 How to use Symbols exported in Namespaces 16 + === 4 Loading Modules that use namespaced Symbols 17 + === 5 Automatically creating MODULE_IMPORT_NS statements 18 + 19 + 1. Introduction 20 + =============== 21 + 22 + Symbol Namespaces have been introduced as a means to structure the export 23 + surface of the in-kernel API. It allows subsystem maintainers to partition 24 + their exported symbols into separate namespaces. That is useful for 25 + documentation purposes (think of the SUBSYSTEM_DEBUG namespace) as well as for 26 + limiting the availability of a set of symbols for use in other parts of the 27 + kernel. As of today, modules that make use of symbols exported into namespaces, 28 + are required to import the namespace. Otherwise the kernel will, depending on 29 + its configuration, reject loading the module or warn about a missing import. 30 + 31 + 2. How to define Symbol Namespaces 32 + ================================== 33 + 34 + Symbols can be exported into namespace using different methods. All of them are 35 + changing the way EXPORT_SYMBOL and friends are instrumented to create ksymtab 36 + entries. 37 + 38 + 2.1 Using the EXPORT_SYMBOL macros 39 + ================================== 40 + 41 + In addition to the macros EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(), that allow 42 + exporting of kernel symbols to the kernel symbol table, variants of these are 43 + available to export symbols into a certain namespace: EXPORT_SYMBOL_NS() and 44 + EXPORT_SYMBOL_NS_GPL(). They take one additional argument: the namespace. 45 + Please note that due to macro expansion that argument needs to be a 46 + preprocessor symbol. E.g. to export the symbol `usb_stor_suspend` into the 47 + namespace `USB_STORAGE`, use:: 48 + 49 + EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE); 50 + 51 + The corresponding ksymtab entry struct `kernel_symbol` will have the member 52 + `namespace` set accordingly. A symbol that is exported without a namespace will 53 + refer to `NULL`. There is no default namespace if none is defined. `modpost` 54 + and kernel/module.c make use the namespace at build time or module load time, 55 + respectively. 56 + 57 + 2.2 Using the DEFAULT_SYMBOL_NAMESPACE define 58 + ============================================= 59 + 60 + Defining namespaces for all symbols of a subsystem can be very verbose and may 61 + become hard to maintain. Therefore a default define (DEFAULT_SYMBOL_NAMESPACE) 62 + is been provided, that, if set, will become the default for all EXPORT_SYMBOL() 63 + and EXPORT_SYMBOL_GPL() macro expansions that do not specify a namespace. 64 + 65 + There are multiple ways of specifying this define and it depends on the 66 + subsystem and the maintainer's preference, which one to use. The first option 67 + is to define the default namespace in the `Makefile` of the subsystem. E.g. to 68 + export all symbols defined in usb-common into the namespace USB_COMMON, add a 69 + line like this to drivers/usb/common/Makefile:: 70 + 71 + ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON 72 + 73 + That will affect all EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() statements. A 74 + symbol exported with EXPORT_SYMBOL_NS() while this definition is present, will 75 + still be exported into the namespace that is passed as the namespace argument 76 + as this argument has preference over a default symbol namespace. 77 + 78 + A second option to define the default namespace is directly in the compilation 79 + unit as preprocessor statement. The above example would then read:: 80 + 81 + #undef DEFAULT_SYMBOL_NAMESPACE 82 + #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON 83 + 84 + within the corresponding compilation unit before any EXPORT_SYMBOL macro is 85 + used. 86 + 87 + 3. How to use Symbols exported in Namespaces 88 + ============================================ 89 + 90 + In order to use symbols that are exported into namespaces, kernel modules need 91 + to explicitly import these namespaces. Otherwise the kernel might reject to 92 + load the module. The module code is required to use the macro MODULE_IMPORT_NS 93 + for the namespaces it uses symbols from. E.g. a module using the 94 + usb_stor_suspend symbol from above, needs to import the namespace USB_STORAGE 95 + using a statement like:: 96 + 97 + MODULE_IMPORT_NS(USB_STORAGE); 98 + 99 + This will create a `modinfo` tag in the module for each imported namespace. 100 + This has the side effect, that the imported namespaces of a module can be 101 + inspected with modinfo:: 102 + 103 + $ modinfo drivers/usb/storage/ums-karma.ko 104 + [...] 105 + import_ns: USB_STORAGE 106 + [...] 107 + 108 + 109 + It is advisable to add the MODULE_IMPORT_NS() statement close to other module 110 + metadata definitions like MODULE_AUTHOR() or MODULE_LICENSE(). Refer to section 111 + 5. for a way to create missing import statements automatically. 112 + 113 + 4. Loading Modules that use namespaced Symbols 114 + ============================================== 115 + 116 + At module loading time (e.g. `insmod`), the kernel will check each symbol 117 + referenced from the module for its availability and whether the namespace it 118 + might be exported to has been imported by the module. The default behaviour of 119 + the kernel is to reject loading modules that don't specify sufficient imports. 120 + An error will be logged and loading will be failed with EINVAL. In order to 121 + allow loading of modules that don't satisfy this precondition, a configuration 122 + option is available: Setting MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y will 123 + enable loading regardless, but will emit a warning. 124 + 125 + 5. Automatically creating MODULE_IMPORT_NS statements 126 + ===================================================== 127 + 128 + Missing namespaces imports can easily be detected at build time. In fact, 129 + modpost will emit a warning if a module uses a symbol from a namespace 130 + without importing it. 131 + MODULE_IMPORT_NS() statements will usually be added at a definite location 132 + (along with other module meta data). To make the life of module authors (and 133 + subsystem maintainers) easier, a script and make target is available to fixup 134 + missing imports. Fixing missing imports can be done with:: 135 + 136 + $ make nsdeps 137 + 138 + A typical scenario for module authors would be:: 139 + 140 + - write code that depends on a symbol from a not imported namespace 141 + - `make` 142 + - notice the warning of modpost telling about a missing import 143 + - run `make nsdeps` to add the import to the correct code location 144 + 145 + For subsystem maintainers introducing a namespace, the steps are very similar. 146 + Again, `make nsdeps` will eventually add the missing namespace imports for 147 + in-tree modules:: 148 + 149 + - move or add symbols to a namespace (e.g. with EXPORT_SYMBOL_NS()) 150 + - `make` (preferably with an allmodconfig to cover all in-kernel 151 + modules) 152 + - notice the warning of modpost telling about a missing import 153 + - run `make nsdeps` to add the import to the correct code location 154 +
+18
Documentation/kernel-hacking/hacking.rst
··· 594 594 maintainers and developers may however require EXPORT_SYMBOL_GPL() 595 595 when adding any new APIs or functionality. 596 596 597 + :c:func:`EXPORT_SYMBOL_NS()` 598 + ---------------------------- 599 + 600 + Defined in ``include/linux/export.h`` 601 + 602 + This is the variant of `EXPORT_SYMBOL()` that allows specifying a symbol 603 + namespace. Symbol Namespaces are documented in 604 + ``Documentation/kbuild/namespaces.rst``. 605 + 606 + :c:func:`EXPORT_SYMBOL_NS_GPL()` 607 + -------------------------------- 608 + 609 + Defined in ``include/linux/export.h`` 610 + 611 + This is the variant of `EXPORT_SYMBOL_GPL()` that allows specifying a symbol 612 + namespace. Symbol Namespaces are documented in 613 + ``Documentation/kbuild/namespaces.rst``. 614 + 597 615 Routines and Conventions 598 616 ======================== 599 617
+5
MAINTAINERS
··· 11523 11523 T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git 11524 11524 F: tools/include/nolibc/ 11525 11525 11526 + NSDEPS 11527 + M: Matthias Maennich <maennich@google.com> 11528 + S: Maintained 11529 + F: scripts/nsdeps 11530 + 11526 11531 NTB AMD DRIVER 11527 11532 M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 11528 11533 L: linux-ntb@googlegroups.com
+13 -1
Makefile
··· 1498 1498 @echo ' headerdep - Detect inclusion cycles in headers' 1499 1499 @echo ' coccicheck - Check with Coccinelle' 1500 1500 @echo '' 1501 + @echo 'Tools:' 1502 + @echo ' nsdeps - Generate missing symbol namespace dependencies' 1503 + @echo '' 1501 1504 @echo 'Kernel selftest:' 1502 1505 @echo ' kselftest - Build and run kernel selftest (run as root)' 1503 1506 @echo ' Build, install, and boot kernel before' ··· 1682 1679 -o -name '*.ko.*' \ 1683 1680 -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ 1684 1681 -o -name '*.dwo' -o -name '*.lst' \ 1685 - -o -name '*.su' -o -name '*.mod' \ 1682 + -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ 1686 1683 -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ 1687 1684 -o -name '*.lex.c' -o -name '*.tab.[ch]' \ 1688 1685 -o -name '*.asn1.[ch]' \ ··· 1699 1696 1700 1697 tags TAGS cscope gtags: FORCE 1701 1698 $(call cmd,tags) 1699 + 1700 + # Script to generate missing namespace dependencies 1701 + # --------------------------------------------------------------------------- 1702 + 1703 + PHONY += nsdeps 1704 + 1705 + nsdeps: modules 1706 + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps 1707 + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ 1702 1708 1703 1709 # Scripts to check various things for consistency 1704 1710 # ---------------------------------------------------------------------------
-1
arch/m68k/include/asm/export.h
··· 1 - #define KSYM_ALIGN 2 2 1 #define KCRC_ALIGN 2 3 2 #include <asm-generic/export.h>
+2
drivers/usb/storage/Makefile
··· 8 8 9 9 ccflags-y := -I $(srctree)/drivers/scsi 10 10 11 + ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE 12 + 11 13 obj-$(CONFIG_USB_UAS) += uas.o 12 14 obj-$(CONFIG_USB_STORAGE) += usb-storage.o 13 15
+1
drivers/usb/storage/alauda.c
··· 36 36 MODULE_DESCRIPTION("Driver for Alauda-based card readers"); 37 37 MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>"); 38 38 MODULE_LICENSE("GPL"); 39 + MODULE_IMPORT_NS(USB_STORAGE); 39 40 40 41 /* 41 42 * Status bytes
+1
drivers/usb/storage/cypress_atacb.c
··· 22 22 MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB"); 23 23 MODULE_AUTHOR("Matthieu Castet <castet.matthieu@free.fr>"); 24 24 MODULE_LICENSE("GPL"); 25 + MODULE_IMPORT_NS(USB_STORAGE); 25 26 26 27 /* 27 28 * The table of devices
+1
drivers/usb/storage/datafab.c
··· 54 54 MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader"); 55 55 MODULE_AUTHOR("Jimmie Mayfield <mayfield+datafab@sackheads.org>"); 56 56 MODULE_LICENSE("GPL"); 57 + MODULE_IMPORT_NS(USB_STORAGE); 57 58 58 59 struct datafab_info { 59 60 unsigned long sectors; /* total sector count */
+1
drivers/usb/storage/ene_ub6250.c
··· 26 26 27 27 MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); 28 28 MODULE_LICENSE("GPL"); 29 + MODULE_IMPORT_NS(USB_STORAGE); 29 30 MODULE_FIRMWARE(SD_INIT1_FIRMWARE); 30 31 MODULE_FIRMWARE(SD_INIT2_FIRMWARE); 31 32 MODULE_FIRMWARE(SD_RW_FIRMWARE);
+1
drivers/usb/storage/freecom.c
··· 29 29 MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor"); 30 30 MODULE_AUTHOR("David Brown <usb-storage@davidb.org>"); 31 31 MODULE_LICENSE("GPL"); 32 + MODULE_IMPORT_NS(USB_STORAGE); 32 33 33 34 #ifdef CONFIG_USB_STORAGE_DEBUG 34 35 static void pdump(struct us_data *us, void *ibuffer, int length);
+1
drivers/usb/storage/isd200.c
··· 53 53 MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC"); 54 54 MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>"); 55 55 MODULE_LICENSE("GPL"); 56 + MODULE_IMPORT_NS(USB_STORAGE); 56 57 57 58 static int isd200_Initialization(struct us_data *us); 58 59
+1
drivers/usb/storage/jumpshot.c
··· 51 51 MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader"); 52 52 MODULE_AUTHOR("Jimmie Mayfield <mayfield+usb@sackheads.org>"); 53 53 MODULE_LICENSE("GPL"); 54 + MODULE_IMPORT_NS(USB_STORAGE); 54 55 55 56 /* 56 57 * The table of devices
+1
drivers/usb/storage/karma.c
··· 23 23 MODULE_DESCRIPTION("Driver for Rio Karma"); 24 24 MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>, Keith Bennett <keith@mcs.st-and.ac.uk>"); 25 25 MODULE_LICENSE("GPL"); 26 + MODULE_IMPORT_NS(USB_STORAGE); 26 27 27 28 #define RIO_PREFIX "RIOP\x00" 28 29 #define RIO_PREFIX_LEN 5
+1
drivers/usb/storage/onetouch.c
··· 25 25 MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver"); 26 26 MODULE_AUTHOR("Nick Sillik <n.sillik@temple.edu>"); 27 27 MODULE_LICENSE("GPL"); 28 + MODULE_IMPORT_NS(USB_STORAGE); 28 29 29 30 #define ONETOUCH_PKT_LEN 0x02 30 31 #define ONETOUCH_BUTTON KEY_PROG1
+1
drivers/usb/storage/realtek_cr.c
··· 35 35 MODULE_DESCRIPTION("Driver for Realtek USB Card Reader"); 36 36 MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>"); 37 37 MODULE_LICENSE("GPL"); 38 + MODULE_IMPORT_NS(USB_STORAGE); 38 39 39 40 static int auto_delink_en = 1; 40 41 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
+1
drivers/usb/storage/sddr09.c
··· 47 47 MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader"); 48 48 MODULE_AUTHOR("Andries Brouwer <aeb@cwi.nl>, Robert Baruch <autophile@starband.net>"); 49 49 MODULE_LICENSE("GPL"); 50 + MODULE_IMPORT_NS(USB_STORAGE); 50 51 51 52 static int usb_stor_sddr09_dpcm_init(struct us_data *us); 52 53 static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
+1
drivers/usb/storage/sddr55.c
··· 29 29 MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader"); 30 30 MODULE_AUTHOR("Simon Munton"); 31 31 MODULE_LICENSE("GPL"); 32 + MODULE_IMPORT_NS(USB_STORAGE); 32 33 33 34 /* 34 35 * The table of devices
+1
drivers/usb/storage/shuttle_usbat.c
··· 48 48 MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable"); 49 49 MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>, Robert Baruch <autophile@starband.net>"); 50 50 MODULE_LICENSE("GPL"); 51 + MODULE_IMPORT_NS(USB_STORAGE); 51 52 52 53 /* Supported device types */ 53 54 #define USBAT_DEV_HP8200 0x01
+1
drivers/usb/storage/uas.c
··· 1219 1219 module_usb_driver(uas_driver); 1220 1220 1221 1221 MODULE_LICENSE("GPL"); 1222 + MODULE_IMPORT_NS(USB_STORAGE); 1222 1223 MODULE_AUTHOR( 1223 1224 "Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp");
+8 -11
include/asm-generic/export.h
··· 4 4 #ifndef KSYM_FUNC 5 5 #define KSYM_FUNC(x) x 6 6 #endif 7 - #ifdef CONFIG_64BIT 8 - #ifndef KSYM_ALIGN 9 - #define KSYM_ALIGN 8 10 - #endif 11 - #else 12 - #ifndef KSYM_ALIGN 7 + #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS 13 8 #define KSYM_ALIGN 4 14 - #endif 9 + #elif defined(CONFIG_64BIT) 10 + #define KSYM_ALIGN 8 11 + #else 12 + #define KSYM_ALIGN 4 15 13 #endif 16 14 #ifndef KCRC_ALIGN 17 15 #define KCRC_ALIGN 4 ··· 17 19 18 20 .macro __put, val, name 19 21 #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS 20 - .long \val - ., \name - . 22 + .long \val - ., \name - ., 0 21 23 #elif defined(CONFIG_64BIT) 22 - .quad \val, \name 24 + .quad \val, \name, 0 23 25 #else 24 - .long \val, \name 26 + .long \val, \name, 0 25 27 #endif 26 28 .endm 27 29 ··· 55 57 #endif 56 58 #endif 57 59 .endm 58 - #undef __put 59 60 60 61 #if defined(CONFIG_TRIM_UNUSED_KSYMS) 61 62
+66 -10
include/linux/export.h
··· 18 18 #define THIS_MODULE ((struct module *)0) 19 19 #endif 20 20 21 + #define NS_SEPARATOR "." 22 + 21 23 #ifdef CONFIG_MODVERSIONS 22 24 /* Mark the CRC weak since genksyms apparently decides not to 23 25 * generate a checksums for some symbols */ ··· 28 26 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ 29 27 " .weak __crc_" #sym " \n" \ 30 28 " .long __crc_" #sym " - . \n" \ 31 - " .previous \n"); 29 + " .previous \n") 32 30 #else 33 31 #define __CRC_SYMBOL(sym, sec) \ 34 32 asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ 35 33 " .weak __crc_" #sym " \n" \ 36 34 " .long __crc_" #sym " \n" \ 37 - " .previous \n"); 35 + " .previous \n") 38 36 #endif 39 37 #else 40 38 #define __CRC_SYMBOL(sym, sec) ··· 48 46 * absolute relocations that require runtime processing on relocatable 49 47 * kernels. 50 48 */ 49 + #define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ 50 + __ADDRESSABLE(sym) \ 51 + asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ 52 + " .balign 4 \n" \ 53 + "__ksymtab_" #sym NS_SEPARATOR #ns ": \n" \ 54 + " .long " #sym "- . \n" \ 55 + " .long __kstrtab_" #sym "- . \n" \ 56 + " .long __kstrtab_ns_" #sym "- . \n" \ 57 + " .previous \n") 58 + 51 59 #define __KSYMTAB_ENTRY(sym, sec) \ 52 60 __ADDRESSABLE(sym) \ 53 61 asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ 54 - " .balign 8 \n" \ 62 + " .balign 4 \n" \ 55 63 "__ksymtab_" #sym ": \n" \ 56 64 " .long " #sym "- . \n" \ 57 65 " .long __kstrtab_" #sym "- . \n" \ 66 + " .long 0 \n" \ 58 67 " .previous \n") 59 68 60 69 struct kernel_symbol { 61 70 int value_offset; 62 71 int name_offset; 72 + int namespace_offset; 63 73 }; 64 74 #else 75 + #define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ 76 + static const struct kernel_symbol __ksymtab_##sym##__##ns \ 77 + asm("__ksymtab_" #sym NS_SEPARATOR #ns) \ 78 + __attribute__((section("___ksymtab" sec "+" #sym), used)) \ 79 + __aligned(sizeof(void *)) \ 80 + = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym } 81 + 65 82 #define __KSYMTAB_ENTRY(sym, sec) \ 66 83 static const struct kernel_symbol __ksymtab_##sym \ 84 + asm("__ksymtab_" #sym) \ 67 85 __attribute__((section("___ksymtab" sec "+" #sym), used)) \ 68 - = { (unsigned long)&sym, __kstrtab_##sym } 86 + __aligned(sizeof(void *)) \ 87 + = { (unsigned long)&sym, __kstrtab_##sym, NULL } 69 88 70 89 struct kernel_symbol { 71 90 unsigned long value; 72 91 const char *name; 92 + const char *namespace; 73 93 }; 74 94 #endif 75 95 76 96 #ifdef __GENKSYMS__ 77 97 78 - #define ___EXPORT_SYMBOL(sym, sec) __GENKSYMS_EXPORT_SYMBOL(sym) 98 + #define ___EXPORT_SYMBOL(sym,sec) __GENKSYMS_EXPORT_SYMBOL(sym) 99 + #define ___EXPORT_SYMBOL_NS(sym,sec,ns) __GENKSYMS_EXPORT_SYMBOL(sym) 79 100 80 101 #else 81 102 82 - /* For every exported symbol, place a struct in the __ksymtab section */ 83 - #define ___EXPORT_SYMBOL(sym, sec) \ 103 + #define ___export_symbol_common(sym, sec) \ 84 104 extern typeof(sym) sym; \ 85 - __CRC_SYMBOL(sym, sec) \ 105 + __CRC_SYMBOL(sym, sec); \ 86 106 static const char __kstrtab_##sym[] \ 87 107 __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ 88 - = #sym; \ 108 + = #sym \ 109 + 110 + /* For every exported symbol, place a struct in the __ksymtab section */ 111 + #define ___EXPORT_SYMBOL_NS(sym, sec, ns) \ 112 + ___export_symbol_common(sym, sec); \ 113 + static const char __kstrtab_ns_##sym[] \ 114 + __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ 115 + = #ns; \ 116 + __KSYMTAB_ENTRY_NS(sym, sec, ns) 117 + 118 + #define ___EXPORT_SYMBOL(sym, sec) \ 119 + ___export_symbol_common(sym, sec); \ 89 120 __KSYMTAB_ENTRY(sym, sec) 90 121 91 122 #endif ··· 130 95 * be reused in other execution contexts such as the UEFI stub or the 131 96 * decompressor. 132 97 */ 98 + #define __EXPORT_SYMBOL_NS(sym, sec, ns) 133 99 #define __EXPORT_SYMBOL(sym, sec) 134 100 135 101 #elif defined(CONFIG_TRIM_UNUSED_KSYMS) ··· 157 121 #define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec) 158 122 #define __cond_export_sym_0(sym, sec) /* nothing */ 159 123 124 + #define __EXPORT_SYMBOL_NS(sym, sec, ns) \ 125 + __ksym_marker(sym); \ 126 + __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) 127 + #define __cond_export_ns_sym(sym, sec, ns, conf) \ 128 + ___cond_export_ns_sym(sym, sec, ns, conf) 129 + #define ___cond_export_ns_sym(sym, sec, ns, enabled) \ 130 + __cond_export_ns_sym_##enabled(sym, sec, ns) 131 + #define __cond_export_ns_sym_1(sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns) 132 + #define __cond_export_ns_sym_0(sym, sec, ns) /* nothing */ 133 + 160 134 #else 161 135 162 - #define __EXPORT_SYMBOL(sym, sec) ___EXPORT_SYMBOL(sym, sec) 136 + #define __EXPORT_SYMBOL_NS(sym,sec,ns) ___EXPORT_SYMBOL_NS(sym,sec,ns) 137 + #define __EXPORT_SYMBOL(sym,sec) ___EXPORT_SYMBOL(sym,sec) 163 138 164 139 #endif /* CONFIG_MODULES */ 140 + 141 + #ifdef DEFAULT_SYMBOL_NAMESPACE 142 + #undef __EXPORT_SYMBOL 143 + #define __EXPORT_SYMBOL(sym, sec) \ 144 + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) 145 + #endif 165 146 166 147 #define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") 167 148 #define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") 168 149 #define EXPORT_SYMBOL_GPL_FUTURE(sym) __EXPORT_SYMBOL(sym, "_gpl_future") 150 + #define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns) 151 + #define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns) 152 + 169 153 #ifdef CONFIG_UNUSED_SYMBOLS 170 154 #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") 171 155 #define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl")
+2
include/linux/module.h
··· 280 280 281 281 #ifdef CONFIG_MODULES 282 282 283 + #define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, #ns) 284 + 283 285 extern int modules_disabled; /* for sysctl */ 284 286 /* Get/put a kernel symbol (calls must be symmetric) */ 285 287 void *__symbol_get(const char *symbol);
+30 -3
init/Kconfig
··· 2047 2047 2048 2048 config MODULE_SIG 2049 2049 bool "Module signature verification" 2050 - depends on MODULES 2051 2050 select SYSTEM_DATA_VERIFICATION 2052 2051 help 2053 2052 Check modules for valid signatures upon load: the signature ··· 2123 2124 2124 2125 config MODULE_COMPRESS 2125 2126 bool "Compress modules on installation" 2126 - depends on MODULES 2127 2127 help 2128 2128 2129 2129 Compresses kernel modules when 'make modules_install' is run; gzip or ··· 2158 2160 2159 2161 endchoice 2160 2162 2163 + config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS 2164 + bool "Allow loading of modules with missing namespace imports" 2165 + help 2166 + Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in 2167 + a namespace. A module that makes use of a symbol exported with such a 2168 + namespace is required to import the namespace via MODULE_IMPORT_NS(). 2169 + There is no technical reason to enforce correct namespace imports, 2170 + but it creates consistency between symbols defining namespaces and 2171 + users importing namespaces they make use of. This option relaxes this 2172 + requirement and lifts the enforcement when loading a module. 2173 + 2174 + If unsure, say N. 2175 + 2176 + config UNUSED_SYMBOLS 2177 + bool "Enable unused/obsolete exported symbols" 2178 + default y if X86 2179 + help 2180 + Unused but exported symbols make the kernel needlessly bigger. For 2181 + that reason most of these unused exports will soon be removed. This 2182 + option is provided temporarily to provide a transition period in case 2183 + some external kernel module needs one of these symbols anyway. If you 2184 + encounter such a case in your module, consider if you are actually 2185 + using the right API. (rationale: since nobody in the kernel is using 2186 + this in a module, there is a pretty good chance it's actually the 2187 + wrong interface to use). If you really need the symbol, please send a 2188 + mail to the linux kernel mailing list mentioning the symbol and why 2189 + you really need it, and what the merge plan to the mainline kernel for 2190 + your module is. 2191 + 2161 2192 config TRIM_UNUSED_KSYMS 2162 2193 bool "Trim unused exported kernel symbols" 2163 - depends on MODULES && !UNUSED_SYMBOLS 2194 + depends on !UNUSED_SYMBOLS 2164 2195 help 2165 2196 The kernel and some modules make many symbols available for 2166 2197 other modules to use via EXPORT_SYMBOL() and variants. Depending
+69 -7
kernel/module.c
··· 544 544 #endif 545 545 } 546 546 547 - static int cmp_name(const void *va, const void *vb) 547 + static const char *kernel_symbol_namespace(const struct kernel_symbol *sym) 548 548 { 549 - const char *a; 550 - const struct kernel_symbol *b; 551 - a = va; b = vb; 552 - return strcmp(a, kernel_symbol_name(b)); 549 + #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS 550 + if (!sym->namespace_offset) 551 + return NULL; 552 + return offset_to_ptr(&sym->namespace_offset); 553 + #else 554 + return sym->namespace; 555 + #endif 556 + } 557 + 558 + static int cmp_name(const void *name, const void *sym) 559 + { 560 + return strcmp(name, kernel_symbol_name(sym)); 553 561 } 554 562 555 563 static bool find_exported_symbol_in_section(const struct symsearch *syms, ··· 1387 1379 } 1388 1380 #endif /* CONFIG_MODVERSIONS */ 1389 1381 1382 + static char *get_modinfo(const struct load_info *info, const char *tag); 1383 + static char *get_next_modinfo(const struct load_info *info, const char *tag, 1384 + char *prev); 1385 + 1386 + static int verify_namespace_is_imported(const struct load_info *info, 1387 + const struct kernel_symbol *sym, 1388 + struct module *mod) 1389 + { 1390 + const char *namespace; 1391 + char *imported_namespace; 1392 + 1393 + namespace = kernel_symbol_namespace(sym); 1394 + if (namespace) { 1395 + imported_namespace = get_modinfo(info, "import_ns"); 1396 + while (imported_namespace) { 1397 + if (strcmp(namespace, imported_namespace) == 0) 1398 + return 0; 1399 + imported_namespace = get_next_modinfo( 1400 + info, "import_ns", imported_namespace); 1401 + } 1402 + #ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS 1403 + pr_warn( 1404 + #else 1405 + pr_err( 1406 + #endif 1407 + "%s: module uses symbol (%s) from namespace %s, but does not import it.\n", 1408 + mod->name, kernel_symbol_name(sym), namespace); 1409 + #ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS 1410 + return -EINVAL; 1411 + #endif 1412 + } 1413 + return 0; 1414 + } 1415 + 1416 + 1390 1417 /* Resolve a symbol for this module. I.e. if we find one, record usage. */ 1391 1418 static const struct kernel_symbol *resolve_symbol(struct module *mod, 1392 1419 const struct load_info *info, ··· 1447 1404 1448 1405 if (!check_version(info, name, mod, crc)) { 1449 1406 sym = ERR_PTR(-EINVAL); 1407 + goto getname; 1408 + } 1409 + 1410 + err = verify_namespace_is_imported(info, sym, mod); 1411 + if (err) { 1412 + sym = ERR_PTR(err); 1450 1413 goto getname; 1451 1414 } 1452 1415 ··· 2530 2481 return string; 2531 2482 } 2532 2483 2533 - static char *get_modinfo(struct load_info *info, const char *tag) 2484 + static char *get_next_modinfo(const struct load_info *info, const char *tag, 2485 + char *prev) 2534 2486 { 2535 2487 char *p; 2536 2488 unsigned int taglen = strlen(tag); ··· 2542 2492 * get_modinfo() calls made before rewrite_section_headers() 2543 2493 * must use sh_offset, as sh_addr isn't set! 2544 2494 */ 2545 - for (p = (char *)info->hdr + infosec->sh_offset; p; p = next_string(p, &size)) { 2495 + char *modinfo = (char *)info->hdr + infosec->sh_offset; 2496 + 2497 + if (prev) { 2498 + size -= prev - modinfo; 2499 + modinfo = next_string(prev, &size); 2500 + } 2501 + 2502 + for (p = modinfo; p; p = next_string(p, &size)) { 2546 2503 if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') 2547 2504 return p + taglen + 1; 2548 2505 } 2549 2506 return NULL; 2507 + } 2508 + 2509 + static char *get_modinfo(const struct load_info *info, const char *tag) 2510 + { 2511 + return get_next_modinfo(info, tag, NULL); 2550 2512 } 2551 2513 2552 2514 static void setup_modinfo(struct module *mod, struct load_info *info)
-16
lib/Kconfig.debug
··· 277 277 to keep kernel developers who have to stare a lot at assembler listings 278 278 sane. 279 279 280 - config UNUSED_SYMBOLS 281 - bool "Enable unused/obsolete exported symbols" 282 - default y if X86 283 - help 284 - Unused but exported symbols make the kernel needlessly bigger. For 285 - that reason most of these unused exports will soon be removed. This 286 - option is provided temporarily to provide a transition period in case 287 - some external kernel module needs one of these symbols anyway. If you 288 - encounter such a case in your module, consider if you are actually 289 - using the right API. (rationale: since nobody in the kernel is using 290 - this in a module, there is a pretty good chance it's actually the 291 - wrong interface to use). If you really need the symbol, please send a 292 - mail to the linux kernel mailing list mentioning the symbol and why 293 - you really need it, and what the merge plan to the mainline kernel for 294 - your module is. 295 - 296 280 config DEBUG_FS 297 281 bool "Debug Filesystem" 298 282 help
+4 -1
scripts/Makefile.modpost
··· 54 54 $(if $(KBUILD_EXTMOD),$(addprefix -e ,$(KBUILD_EXTRA_SYMBOLS))) \ 55 55 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ 56 56 $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ 57 - $(if $(KBUILD_MODPOST_WARN),-w) 57 + $(if $(KBUILD_MODPOST_WARN),-w) \ 58 + $(if $(filter nsdeps,$(MAKECMDGOALS)),-d) 58 59 59 60 ifdef MODPOST_VMLINUX 60 61 ··· 95 94 ifneq ($(KBUILD_MODPOST_NOFINAL),1) 96 95 $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal 97 96 endif 97 + 98 + nsdeps: __modpost 98 99 99 100 endif 100 101
+23
scripts/coccinelle/misc/add_namespace.cocci
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // 3 + /// Adds missing MODULE_IMPORT_NS statements to source files 4 + /// 5 + /// This script is usually called from scripts/nsdeps with -D ns=<namespace> to 6 + /// add a missing namespace tag to a module source file. 7 + /// 8 + 9 + @has_ns_import@ 10 + declarer name MODULE_IMPORT_NS; 11 + identifier virtual.ns; 12 + @@ 13 + MODULE_IMPORT_NS(ns); 14 + 15 + // Add missing imports, but only adjacent to a MODULE_LICENSE statement. 16 + // That ensures we are adding it only to the main module source file. 17 + @do_import depends on !has_ns_import@ 18 + declarer name MODULE_LICENSE; 19 + expression license; 20 + identifier virtual.ns; 21 + @@ 22 + MODULE_LICENSE(license); 23 + + MODULE_IMPORT_NS(ns);
+1 -1
scripts/export_report.pl
··· 94 94 # 95 95 while ( <$module_symvers> ) { 96 96 chomp; 97 - my (undef, $symbol, $module, $gpl) = split; 97 + my (undef, $symbol, $namespace, $module, $gpl) = split('\t'); 98 98 $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; 99 99 } 100 100 close($module_symvers);
+133 -17
scripts/mod/modpost.c
··· 38 38 static int sec_mismatch_fatal = 0; 39 39 /* ignore missing files */ 40 40 static int ignore_missing_files; 41 + /* write namespace dependencies */ 42 + static int write_namespace_deps; 41 43 42 44 enum export { 43 45 export_plain, export_unused, export_gpl, ··· 166 164 struct module *module; 167 165 unsigned int crc; 168 166 int crc_valid; 167 + const char *namespace; 169 168 unsigned int weak:1; 170 169 unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ 171 170 unsigned int kernel:1; /* 1 if symbol is from kernel ··· 236 233 return s; 237 234 } 238 235 return NULL; 236 + } 237 + 238 + static bool contains_namespace(struct namespace_list *list, 239 + const char *namespace) 240 + { 241 + struct namespace_list *ns_entry; 242 + 243 + for (ns_entry = list; ns_entry != NULL; ns_entry = ns_entry->next) 244 + if (strcmp(ns_entry->namespace, namespace) == 0) 245 + return true; 246 + 247 + return false; 248 + } 249 + 250 + static void add_namespace(struct namespace_list **list, const char *namespace) 251 + { 252 + struct namespace_list *ns_entry; 253 + 254 + if (!contains_namespace(*list, namespace)) { 255 + ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) + 256 + strlen(namespace) + 1)); 257 + strcpy(ns_entry->namespace, namespace); 258 + ns_entry->next = *list; 259 + *list = ns_entry; 260 + } 261 + } 262 + 263 + static bool module_imports_namespace(struct module *module, 264 + const char *namespace) 265 + { 266 + return contains_namespace(module->imported_namespaces, namespace); 239 267 } 240 268 241 269 static const struct { ··· 348 314 return export_unknown; 349 315 } 350 316 317 + static const char *sym_extract_namespace(const char **symname) 318 + { 319 + size_t n; 320 + char *dupsymname; 321 + 322 + n = strcspn(*symname, "."); 323 + if (n < strlen(*symname) - 1) { 324 + dupsymname = NOFAIL(strdup(*symname)); 325 + dupsymname[n] = '\0'; 326 + *symname = dupsymname; 327 + return dupsymname + n + 1; 328 + } 329 + 330 + return NULL; 331 + } 332 + 351 333 /** 352 334 * Add an exported symbol - it may have already been added without a 353 335 * CRC, in this case just update the CRC 354 336 **/ 355 - static struct symbol *sym_add_exported(const char *name, struct module *mod, 356 - enum export export) 337 + static struct symbol *sym_add_exported(const char *name, const char *namespace, 338 + struct module *mod, enum export export) 357 339 { 358 340 struct symbol *s = find_symbol(name); 359 341 360 342 if (!s) { 361 343 s = new_symbol(name, mod, export); 344 + s->namespace = namespace; 362 345 } else { 363 346 if (!s->preloaded) { 364 - warn("%s: '%s' exported twice. Previous export " 365 - "was in %s%s\n", mod->name, name, 366 - s->module->name, 367 - is_vmlinux(s->module->name) ?"":".ko"); 347 + warn("%s: '%s' exported twice. Previous export was in %s%s\n", 348 + mod->name, name, s->module->name, 349 + is_vmlinux(s->module->name) ? "" : ".ko"); 368 350 } else { 369 351 /* In case Module.symvers was out of date */ 370 352 s->module = mod; ··· 672 622 unsigned int crc; 673 623 enum export export; 674 624 bool is_crc = false; 625 + const char *name, *namespace; 675 626 676 627 if ((!is_vmlinux(mod->name) || mod->is_dot_o) && 677 628 strstarts(symname, "__ksymtab")) ··· 744 693 default: 745 694 /* All exported symbols */ 746 695 if (strstarts(symname, "__ksymtab_")) { 747 - sym_add_exported(symname + strlen("__ksymtab_"), mod, 748 - export); 696 + name = symname + strlen("__ksymtab_"); 697 + namespace = sym_extract_namespace(&name); 698 + sym_add_exported(name, namespace, mod, export); 749 699 } 750 700 if (strcmp(symname, "init_module") == 0) 751 701 mod->has_init = 1; ··· 1997 1945 const char *symname; 1998 1946 char *version; 1999 1947 char *license; 1948 + char *namespace; 2000 1949 struct module *mod; 2001 1950 struct elf_info info = { }; 2002 1951 Elf_Sym *sym; ··· 2027 1974 break; 2028 1975 } 2029 1976 license = get_next_modinfo(&info, "license", license); 1977 + } 1978 + 1979 + namespace = get_modinfo(&info, "import_ns"); 1980 + while (namespace) { 1981 + add_namespace(&mod->imported_namespaces, namespace); 1982 + namespace = get_next_modinfo(&info, "import_ns", namespace); 2030 1983 } 2031 1984 2032 1985 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { ··· 2194 2135 basename++; 2195 2136 else 2196 2137 basename = mod->name; 2138 + 2139 + if (exp->namespace) { 2140 + add_namespace(&mod->required_namespaces, 2141 + exp->namespace); 2142 + 2143 + if (!write_namespace_deps && 2144 + !module_imports_namespace(mod, exp->namespace)) { 2145 + warn("module %s uses symbol %s from namespace %s, but does not import it.\n", 2146 + basename, exp->name, exp->namespace); 2147 + } 2148 + } 2149 + 2197 2150 if (!mod->gpl_compatible) 2198 2151 check_for_gpl_usage(exp->export, basename, exp->name); 2199 2152 check_for_unused(exp->export, basename, exp->name); ··· 2425 2354 return; 2426 2355 2427 2356 while ((line = get_next_line(&pos, file, size))) { 2428 - char *symname, *modname, *d, *export, *end; 2357 + char *symname, *namespace, *modname, *d, *export, *end; 2429 2358 unsigned int crc; 2430 2359 struct module *mod; 2431 2360 struct symbol *s; ··· 2433 2362 if (!(symname = strchr(line, '\t'))) 2434 2363 goto fail; 2435 2364 *symname++ = '\0'; 2436 - if (!(modname = strchr(symname, '\t'))) 2365 + if (!(namespace = strchr(symname, '\t'))) 2366 + goto fail; 2367 + *namespace++ = '\0'; 2368 + if (!(modname = strchr(namespace, '\t'))) 2437 2369 goto fail; 2438 2370 *modname++ = '\0'; 2439 2371 if ((export = strchr(modname, '\t')) != NULL) ··· 2453 2379 mod = new_module(modname); 2454 2380 mod->skip = 1; 2455 2381 } 2456 - s = sym_add_exported(symname, mod, export_no(export)); 2382 + s = sym_add_exported(symname, namespace, mod, 2383 + export_no(export)); 2457 2384 s->kernel = kernel; 2458 2385 s->preloaded = 1; 2459 2386 s->is_static = 0; ··· 2484 2409 { 2485 2410 struct buffer buf = { }; 2486 2411 struct symbol *symbol; 2412 + const char *namespace; 2487 2413 int n; 2488 2414 2489 2415 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { 2490 2416 symbol = symbolhash[n]; 2491 2417 while (symbol) { 2492 - if (dump_sym(symbol)) 2493 - buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", 2494 - symbol->crc, symbol->name, 2495 - symbol->module->name, 2496 - export_str(symbol->export)); 2418 + if (dump_sym(symbol)) { 2419 + namespace = symbol->namespace; 2420 + buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", 2421 + symbol->crc, symbol->name, 2422 + namespace ? namespace : "", 2423 + symbol->module->name, 2424 + export_str(symbol->export)); 2425 + } 2497 2426 symbol = symbol->next; 2498 2427 } 2499 2428 } 2500 2429 write_if_changed(&buf, fname); 2501 2430 free(buf.p); 2431 + } 2432 + 2433 + static void write_namespace_deps_files(void) 2434 + { 2435 + struct module *mod; 2436 + struct namespace_list *ns; 2437 + struct buffer ns_deps_buf = {}; 2438 + 2439 + for (mod = modules; mod; mod = mod->next) { 2440 + char fname[PATH_MAX]; 2441 + 2442 + if (mod->skip) 2443 + continue; 2444 + 2445 + ns_deps_buf.pos = 0; 2446 + 2447 + for (ns = mod->required_namespaces; ns; ns = ns->next) 2448 + buf_printf(&ns_deps_buf, "%s\n", ns->namespace); 2449 + 2450 + if (ns_deps_buf.pos == 0) 2451 + continue; 2452 + 2453 + sprintf(fname, "%s.ns_deps", mod->name); 2454 + write_if_changed(&ns_deps_buf, fname); 2455 + } 2502 2456 } 2503 2457 2504 2458 struct ext_sym_list { ··· 2547 2443 struct ext_sym_list *extsym_iter; 2548 2444 struct ext_sym_list *extsym_start = NULL; 2549 2445 2550 - while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awE")) != -1) { 2446 + while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) { 2551 2447 switch (opt) { 2552 2448 case 'i': 2553 2449 kernel_read = optarg; ··· 2588 2484 case 'E': 2589 2485 sec_mismatch_fatal = 1; 2590 2486 break; 2487 + case 'd': 2488 + write_namespace_deps = 1; 2489 + break; 2591 2490 default: 2592 2491 exit(1); 2593 2492 } ··· 2625 2518 2626 2519 err |= check_modname_len(mod); 2627 2520 err |= check_exports(mod); 2521 + if (write_namespace_deps) 2522 + continue; 2523 + 2628 2524 add_header(&buf, mod); 2629 2525 add_intree_flag(&buf, !external_module); 2630 2526 add_retpoline(&buf); ··· 2640 2530 sprintf(fname, "%s.mod.c", mod->name); 2641 2531 write_if_changed(&buf, fname); 2642 2532 } 2533 + 2534 + if (write_namespace_deps) { 2535 + write_namespace_deps_files(); 2536 + return 0; 2537 + } 2538 + 2643 2539 if (dump_write) 2644 2540 write_dump(dump_write); 2645 2541 if (sec_mismatch_count && sec_mismatch_fatal)
+9
scripts/mod/modpost.h
··· 109 109 void 110 110 buf_write(struct buffer *buf, const char *s, int len); 111 111 112 + struct namespace_list { 113 + struct namespace_list *next; 114 + char namespace[0]; 115 + }; 116 + 112 117 struct module { 113 118 struct module *next; 114 119 const char *name; ··· 126 121 struct buffer dev_table_buf; 127 122 char srcversion[25]; 128 123 int is_dot_o; 124 + // Required namespace dependencies 125 + struct namespace_list *required_namespaces; 126 + // Actual imported namespaces 127 + struct namespace_list *imported_namespaces; 129 128 }; 130 129 131 130 struct elf_info {
+58
scripts/nsdeps
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Linux kernel symbol namespace import generator 4 + # 5 + # This script requires a minimum spatch version. 6 + SPATCH_REQ_VERSION="1.0.4" 7 + 8 + DIR="$(dirname $(readlink -f $0))/.." 9 + SPATCH="`which ${SPATCH:=spatch}`" 10 + if [ ! -x "$SPATCH" ]; then 11 + echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/' 12 + exit 1 13 + fi 14 + 15 + SPATCH_REQ_VERSION_NUM=$(echo $SPATCH_REQ_VERSION | ${DIR}/scripts/ld-version.sh) 16 + SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}') 17 + SPATCH_VERSION_NUM=$(echo $SPATCH_VERSION | ${DIR}/scripts/ld-version.sh) 18 + 19 + if [ "$SPATCH_VERSION_NUM" -lt "$SPATCH_REQ_VERSION_NUM" ] ; then 20 + echo "spatch needs to be version $SPATCH_REQ_VERSION or higher" 21 + exit 1 22 + fi 23 + 24 + generate_deps_for_ns() { 25 + $SPATCH --very-quiet --in-place --sp-file \ 26 + $srctree/scripts/coccinelle/misc/add_namespace.cocci -D ns=$1 $2 27 + } 28 + 29 + generate_deps() { 30 + local mod_name=`basename $@ .ko` 31 + local mod_file=`echo $@ | sed -e 's/\.ko/\.mod/'` 32 + local ns_deps_file=`echo $@ | sed -e 's/\.ko/\.ns_deps/'` 33 + if [ ! -f "$ns_deps_file" ]; then return; fi 34 + local mod_source_files=`cat $mod_file | sed -n 1p \ 35 + | sed -e 's/\.o/\.c/g' \ 36 + | sed "s/[^ ]* */${srctree}\/&/g"` 37 + for ns in `cat $ns_deps_file`; do 38 + echo "Adding namespace $ns to module $mod_name (if needed)." 39 + generate_deps_for_ns $ns $mod_source_files 40 + # sort the imports 41 + for source_file in $mod_source_files; do 42 + sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp 43 + offset=$(wc -l ${source_file}.tmp | awk '{print $1;}') 44 + cat $source_file | grep MODULE_IMPORT_NS | sort -u >> ${source_file}.tmp 45 + tail -n +$((offset +1)) ${source_file} | grep -v MODULE_IMPORT_NS >> ${source_file}.tmp 46 + if ! diff -q ${source_file} ${source_file}.tmp; then 47 + mv ${source_file}.tmp ${source_file} 48 + else 49 + rm ${source_file}.tmp 50 + fi 51 + done 52 + done 53 + } 54 + 55 + for f in `cat $objtree/modules.order`; do 56 + generate_deps $f 57 + done 58 +