From: Siddharth Nayyar Date: Thu, 26 Mar 2026 21:25:03 +0000 (+0000) Subject: module: add kflagstab section to vmlinux and modules X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9743311b4535dc76ce81f46303da0f69bfaa5fd6;p=thirdparty%2Fkernel%2Flinux.git module: add kflagstab section to vmlinux and modules This patch introduces a __kflagstab section to store symbol flags in a dedicated data structure, similar to how CRCs are handled in the __kcrctab. The flags for a given symbol in __kflagstab will be located at the same index as the symbol's entry in __ksymtab and its CRC in __kcrctab. This design decouples the flags from the symbol table itself, allowing us to maintain a single, sorted __ksymtab. As a result, the symbol search remains an efficient, single lookup, regardless of the number of flags we add in the future. The motivation for this change comes from the Android kernel, which uses an additional symbol flag to restrict the use of certain exported symbols by unsigned modules, thereby enhancing kernel security. This __kflagstab can be implemented as a bitmap to efficiently manage which symbols are available for general use versus those restricted to signed modules only. This section will contain read-only data for values of kernel symbol flags in the form of an 8-bit bitsets for each kernel symbol. Each bit in the bitset represents a flag value defined by ksym_flags enumeration. Petr Pavlu ran a small test to get a better understanding of the different section sizes resulting from this patch series. He used v6.17-rc6 together with the openSUSE x86_64 config [1], which is fairly large. The resulting vmlinux.bin (no debuginfo) had an on-disk size of 58 MiB, and included 5937 + 6589 (GPL-only) exported symbols. The following table summarizes his measurements and calculations regarding the sizes of all sections related to exported symbols: | HAVE_ARCH_PREL32_RELOCATIONS | !HAVE_ARCH_PREL32_RELOCATIONS Section | Base [B] | Ext. [B] | Sep. [B] | Base [B] | Ext. [B] | Sep. [B] ---------------------------------------------------------------------------------------- __ksymtab | 71244 | 200416 | 150312 | 142488 | 400832 | 300624 __ksymtab_gpl | 79068 | NA | NA | 158136 | NA | NA __kcrctab | 23748 | 50104 | 50104 | 23748 | 50104 | 50104 __kcrctab_gpl | 26356 | NA | NA | 26356 | NA | NA __ksymtab_strings | 253628 | 253628 | 253628 | 253628 | 253628 | 253628 __kflagstab | NA | NA | 12526 | NA | NA | 12526 ---------------------------------------------------------------------------------------- Total | 454044 | 504148 | 466570 | 604356 | 704564 | 616882 Increase to base [%] | NA | 11.0 | 2.8 | NA | 16.6 | 2.1 The column "HAVE_ARCH_PREL32_RELOCATIONS -> Base" contains the measured numbers. The rest of the values are calculated. The "Ext." column represents an alternative approach of extending __ksymtab to include a bitset of symbol flags, and the "Sep." column represents the approach of having a separate __kflagstab. With HAVE_ARCH_PREL32_RELOCATIONS, each kernel_symbol is 12 B in size and is extended to 16 B. With !HAVE_ARCH_PREL32_RELOCATIONS, it is 24 B, extended to 32 B. Note that this does not include the metadata needed to relocate __ksymtab*, which is freed after the initial processing. Adding __kflagstab as a separate section has a negligible impact, as expected. When extending __ksymtab (kernel_symbol) instead, the worst case with !HAVE_ARCH_PREL32_RELOCATIONS increases the export data size by 16.6%. Note that the larger increase in size for the latter approach is due to 4-byte alignment of kernel_symbol data structure, instead of 1-byte alignment for the flags bitset in __kflagstab in the former approach. Based on the above, it was concluded that introducing __kflagstab makes sense, as the added complexity is minimal over extending kernel_symbol, and there is overall simplification of symbol finding logic in the module loader. Signed-off-by: Siddharth Nayyar Reviewed-by: Petr Pavlu [Sami: Updated commit message to include details from the cover letter.] Signed-off-by: Sami Tolvanen --- diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 1e1580febe4b..d64a475c468a 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -536,6 +536,13 @@ __stop___kcrctab_gpl = .; \ } \ \ + /* Kernel symbol flags table */ \ + __kflagstab : AT(ADDR(__kflagstab) - LOAD_OFFSET) { \ + __start___kflagstab = .; \ + KEEP(*(SORT(___kflagstab+*))) \ + __stop___kflagstab = .; \ + } \ + \ /* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \ diff --git a/scripts/module.lds.S b/scripts/module.lds.S index e1cab3cee3f7..3ecfb3ea1cc8 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -23,6 +23,7 @@ SECTIONS { __ksymtab_gpl 0 : ALIGN(8) { *(SORT(___ksymtab_gpl+*)) } __kcrctab 0 : ALIGN(4) { *(SORT(___kcrctab+*)) } __kcrctab_gpl 0 : ALIGN(4) { *(SORT(___kcrctab_gpl+*)) } + __kflagstab 0 : ALIGN(1) { *(SORT(___kflagstab+*)) } .ctors 0 : ALIGN(8) { *(SORT(.ctors.*)) *(.ctors) } .init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) }