[PATCH] bpf: say why a module BTF mismatch keeps the module from loading

From: Paul Menzel

Date: Wed Sep 02 2026 - 19:08:07 EST


With CONFIG_MODULE_ALLOW_BTF_MISMATCH=n – the default, and what Debian
ships – btf_module_notify() turns a split BTF mismatch into a fatal
-EINVAL at MODULE_STATE_COMING, so the module does not load at all.
All the user is told is:

typec_displayport: module verification failed: signature and/or required key missing - tainting kernel
BPF: [124962] TYPEDEF
BPF: type_id=124988
BPF:
BPF: Invalid name
BPF:
failed to validate module [typec_displayport] BTF: -22
BPF: [124944] ENUM (anon)
BPF: size=4 vlen=32
BPF:
BPF: Invalid name
BPF:
failed to validate module [usb_storage] BTF: -22
BPF: [125157] TYPEDEF
BPF: type_id=125185
BPF:
BPF: Invalid name
BPF:
failed to validate module [usbhid] BTF: -22

That message names neither the consequence nor the cause. The report this
comes from is a Dell XPS 13 9370 on Debian experimental where an apt run
replaced /lib/modules/7.2-amd64/ underneath the running 7.2~rc7 kernel;
experimental carries no ABI number, so the new build overwrites the tree
of the running one. usbhid then refused to load and the keyboard and
mouse behind a USB-C hub stayed dead, which reads as a USB regression
rather than as stale modules. mii failing takes r8152 with it, and
usb_storage takes USB mass storage, widening the confusion.

Note, the debug info is all that is stale here: nothing about the module
code is wrong, and dropping the BTF would have let the machine carry on.
Say so, and point at the escape hatch.

State the consequence on the per-module line, and add a once-only
explanation naming the likely cause and CONFIG_MODULE_ALLOW_BTF_MISMATCH.
Restrict the explanation to -EINVAL so that an -ENOMEM from
btf_parse_module() is not blamed on stale modules. Keep it a
pr_warn_once() because a single hotplug event produced 28 of these lines.

Assisted-by: claude-opus-5 (Claude Code)
Signed-off-by: Paul Menzel <pmenzel@xxxxxxxxxxxxx>
---
kernel/bpf/btf.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index da36d4b9d31ab..720c56e8ae498 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -8525,9 +8525,11 @@ static int btf_module_notify(struct notifier_block *nb, unsigned long op,
if (IS_ERR(btf)) {
kfree(btf_mod);
if (!IS_ENABLED(CONFIG_MODULE_ALLOW_BTF_MISMATCH)) {
- pr_warn("failed to validate module [%s] BTF: %ld\n",
- mod->name, PTR_ERR(btf));
err = PTR_ERR(btf);
+ pr_warn("failed to validate module [%s] BTF: %d; refusing to load it\n",
+ mod->name, err);
+ if (err == -EINVAL)
+ pr_warn_once("module BTF does not match this kernel build; the modules on disk are most likely from a different build than the running kernel (kernel package upgraded without rebooting?). Build with CONFIG_MODULE_ALLOW_BTF_MISMATCH=y to load such modules without their BTF.\n");
} else {
pr_warn_once("Kernel module BTF mismatch detected, BTF debug info may be unavailable for some modules\n");
}
--
2.54.0