Trim unused exported kernel symbols (CONFIG_TRIM_UNUSED_KSYMS)
I'm tweaking my kernel config, when I ran across this option CONFIG_TRIM_UNUSED_KSYMS.
The title is Trim unused exported kernel symbols with a snippit of the description being:
This option allows for unused exported symbols to be dropped from the build.
In turn, this provides the compiler more opportunities (especially when using LTO) for optimizing the code and reducing binary size.
This might have some security advantages as well.
Anyone have any knowledge about the implications of this option?
Thanks!
the risk is that out-of-tree kernel modules, like wireguard and (formerly?) zfs won't be able to stop stripping of the symbols they need.
also any kernel modules you install as precompiled binaries are at risk of missing symbols, unless you have other modules that need the same symbols.
for most users I betthe main risk would be nvidia drivers. it would be interesting to see if they still work, and if not whether there are other drivers that could be built to preserve the right dependencies (nouveau?).
alternatively there may be a list used for stripping we could add needed symbols to.
On Fri, Oct 11, 2019, 05:43 Ellison Patterson [email protected] wrote:
I'm tweaking my kernel config, when I ran across this option CONFIG_TRIM_UNUSED_KSYMS.
The title is Trim unused exported kernel symbols with a snippit of the description being:
This option allows for unused exported symbols to be dropped from the build. In turn, this provides the compiler more opportunities (especially when using LTO) for optimizing the code and reducing binary size. This might have some security advantages as well.
Anyone have any knowledge about the implications of this option?
Thanks!
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/InBetweenNames/gentooLTO/issues/423?email_source=notifications&email_token=AAAHXYSO4W547YLURRLNRVLQOBYGVA5CNFSM4I7ZJIP2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HRGLILA, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAHXYQBYZ4UKPBNXVI7XQTQOBYGVANCNFSM4I7ZJIPQ .
That was sudden closure. Why close it all of a sudden @ellisonpatterson?
Also, I wonder if the option would affect VirtualBox's modules...
That was sudden closure. Why close it all of a sudden @ellisonpatterson?
Also, I wonder if the option would affect VirtualBox's modules...
It seems to affect various modules (ZFS for my build) and I'm not sure if it's worth pursuing since the feature itself could lead to issues.
CONFIG_TRIM_UNUSED_KSYMS will break all external modules.
If unsure, or if you need to build out-of-tree modules, say N.
You can patch in the module like this for example. The reason ZFS isn't an in-kernel option is due to GPL licensing. For something as small as ZFS it should be simple, I'm not sure not sure how difficult it would be for NVIDIA. Ofc you shouldn't redistribute it if you do decide to do it for yourself.
Hmm... I wonder if VirtualBox modules are affected. Those are the only modules I have, period. Yeah, I build everything in (instead of "M", I select "Y" in menuconfig).
Edit
I just realized that I already said that (regarding VB modules).
The mainline kernel (5.4-rc7) currently has CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
If 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.
It seems as if this option would you allow you to load external modules that are invalid due to their signatures/required symbols being stripped.
Edit: didn't work..for now
@ellisonpatterson Given that the discussion has sparked yet again, maybe you consider reopening the ticket?
@ellisonpatterson Given that the discussion has sparked yet again, maybe you consider reopening the ticket?
Sorry about that, I have reopened it for further discussion (thank you!)
The mainline kernel (5.4-rc7) currently has
CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTSIf 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.It seems as if this option would you allow you to load external modules that are invalid due to their signatures/required symbols being stripped.
Edit: didn't work..for now
That's an unrelated option. The kernel is cleaning up the module source interface and this option will break ones that haven't been updated. It won't help with external modules that depend on some symbol that got dropped from the kernel though.
Note that the LTO advantage isn't relevant unless you've got a patched kernel that you're compiling with LTO turned on.
I'm staring at initial changes for CONFIG_TRIM_UNUSED_KSYMS support, and from what I understand we just need to add required symbols into include/generated/autoksyms.h, which adjusting by the scripts/adjust_autoksyms.sh script during build. So I collected main work into separate script for external modules, and patched autoksyms.h generation logic a bit.
support-trim-unused-ksyms-for-external-modules.patch
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -19,6 +19,7 @@
cur_ksyms_file="include/generated/autoksyms.h"
new_ksyms_file="include/generated/autoksyms.h.tmpnew"
+ext_ksyms_file="include/generated/autoksyms.h.extern"
info() {
if [ "$quiet" != "silent_" ]; then
@@ -49,7 +50,11 @@
sed 's/ko$/mod/' modules.order |
xargs -n1 sed -n -e '2{s/ /\n/g;/^$/!p;}' -- |
sort -u |
-sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$new_ksyms_file"
+sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$new_ksyms_file".tmp
+
+# Merge external and new ksym files
+sort -u "$new_ksyms_file".tmp "$ext_ksyms_file" >> "$new_ksyms_file"
+rm -f "$new_ksyms_file".tmp
# Special case for modversions (see modpost.c)
if [ -n "$CONFIG_MODVERSIONS" ]; then
@@ -82,7 +87,8 @@
# Replace the old list with tne new one
old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true)
new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true)
- info "KSYMS" "symbols: before=$old, after=$new, changed=$changed"
+ ext=$(grep -c "^#define __KSYM_" "$ext_ksyms_file" || true)
+ info "KSYMS" "symbols: before=$old, after=$new, external=$ext, changed=$changed"
info "UPD" "$cur_ksyms_file"
mv -f "$new_ksyms_file" "$cur_ksyms_file"
# Then trigger a rebuild of affected source files
extern-ksym.sh
#!/bin/sh
#CUR_KERNEL_VER=5.4.8-gentoo
CUR_KERNEL_VER=$(uname -r)
. /usr/src/linux-${CUR_KERNEL_VER}/include/config/auto.conf
list_required_ksyms() {
nm $1 |
sed -n 's/^ \+U //p' |
sed -ns -e '{s/ /\n/g;/^$/!p;}' |
sort -u |
while read sym; do
if [ -n "$CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX" ]; then
sym="${sym#_}"
fi
echo "#define __KSYM_${sym} 1"
done
}
# Find all external modules
mod_dir_list=$(find /lib/modules/${CUR_KERNEL_VER} -mindepth 1 -maxdepth 1 -type d \! -name 'kernel' | xargs)
for mod_dir in $mod_dir_list; do
for ko in ${mod_dir}/*.ko; do
list_required_ksyms ${ko}
done
done | sort -u
Here should be a clean-up, because some symbols are defined in neighbour *.ko modules, but no big deal for now. This will propose kernel to include unknown symbols, like KSYM_nvUvmInterfaceRetainChannelResources, which I guess it don't care about.
Test
cd /usr/src/linux
sh /path/to/extern-ksym.sh > include/generated/autoksyms.h.extern
patch -p1 < /path/to/support-trim-unused-ksyms-for-external-modules.patch
make nconfig # enable CONFIG_TRIM_UNUSED_KSYMS
make
# check output:
# CHK include/generated/autoksyms.h
# KSYMS symbols: before=0, after=2965, external=563, changed=2965
# UPD include/generated/autoksyms.h
Result
| file | 5.4.8-gentoo | 5.4.8-gentoo.old |
|---|---|---|
| System.map | 2344152 | 2932044 |
| vmlinuz | 7062064 | 7164464 |
Note
- External modules should be built/updated BEFORE kernel update, this mean if you going to update both module and kernel, then you should
- update module for current kernel
- generate autoksyms.h.extern file
- switch to new kernel, build it and rebuild external modules again
- I guess
autoksyms.h.externshould be regenerated by every external module update, and put in an known place. - There is a guard currently for external kernel modules, which says "CONFIG_TRIM_UNUSED_KSYMS: should not be set. But it is." https://bugs.gentoo.org/591832 linux-mod.eclass:584
Status
- I'm currently looking for solution to easily override the guard w/o modification of eclass and ebuilds
- Then I'm going to rebuild all external modules and
prayreboot. - UPD: Hello from CONFIG_TRIM_UNUSED_KSYMS + (NVIDIA + Virtualbox + etc.) modules installed. :wink:
So, it's hard to fully automate process, but I already built several kernel versions with this, and in general I just copy generated autoksyms.h.extern list into installed kernel's include/generated/ directory, before build.
Some stats:
| Size | Version | Notes |
|---|---|---|
| 6959664 | vmlinuz-5.3.10-gentoo | |
| 6963760 | vmlinuz-5.3.11-gentoo | |
| 6992432 | vmlinuz-5.4.0-gentoo | |
| 6984240 | vmlinuz-5.4.1-gentoo | |
| 6984240 | vmlinuz-5.4.2-gentoo | |
| 6988336 | vmlinuz-5.4.3-gentoo | |
| 6988336 | vmlinuz-5.4.5-gentoo | |
| 6988336 | vmlinuz-5.4.6-gentoo | |
| 7160368 | vmlinuz-5.4.7-gentoo | BPF forced by in-kernel Gentoo systemd option (likely) |
| 7164464 | vmlinuz-5.4.8-gentoo.old | Normal build |
| 7062064 | vmlinuz-5.4.8-gentoo.old | Trimmed ksyms |
| 5898800 | vmlinuz-5.4.8-gentoo | Minor modules cleanup (unused VBox, etc.) |
| 5624368 | vmlinuz-5.4.10-gentoo | More cleanups (unused BPF, Perf, Debugfs,etc. are dropped) |
| 5624368 | vmlinuz-5.4.11-gentoo | |
| 5624368 | vmlinuz-5.4.12-gentoo | |
| 5628464 | vmlinuz-5.4.13-gentoo | |
| 5628464 | vmlinuz-5.4.14-gentoo |
Probably placebo effect: very fast content (re)draw in Firefox.
In what unit is the size?
hi i compiled the new kernel 5.5 today and i was not able to compile VirtualBox Modules and get here and i dont know why ????
is this
zcat /proc/config.gz | grep CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y
enabled by default ..... im recompiling now Thanks for the info.
nope i still cannot compile the modules even with CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS disabled
Thks, Little gentoo forum post on the subject: https://forums.gentoo.org/viewtopic-p-8437576.html#8437576 Thks 4 ur attention.
Calling script updated, cf above link. Thks 4 ur attention.
Calling script updated, cf above link. Hopefully near beta. Thks 4 ur attention.
Single script version, cf above link. Thks 4 ur attention.
@pchome
. /usr/src/linux-${CUR_KERNEL_VER}/include/config/auto.conf Sorry to disturb for a likely to be noob question: I'm wondering about the purpose of the above command. All I found it about it is that the file get displayed if set +x in bash script.
Is there any reason I'm missing?
Big up for your work, by the way ;) Thks 4 ur attention, interest & support.
CONFIG_UNUSED_KSYMS_WHITELIST Can also be a great alternative.
For example I use it to inform the kernel to keep the symbols used by the nvidia-dkms modules.
Indeed CONFIG_UNUSED_KSYMS_WHITELIST allows single pass kernel build once WHITELIST has been elaborated