[PATCH] vDSO, kbuild: Provide vDSO debug variants at runtime

From: Thomas Weißschuh

Date: Wed Jul 08 2026 - 10:02:00 EST


Finding the debug version of the vDSO is not trivial as there is no common
scheme where it is placed. That's especially problematic for CI testing.

The vDSO futex unlock mechanism requires for testing to have access to the
inner labels of the unlock assembly, which are only accessible via the
debug so.

Also for general debugging purposes it's convenient to have access to the
debug vDSO at a well defined place.

The files are placed in /sys/kernel/vdso_debug.tar.xz. They use the
regular 'make vdso_install' layout, including build-id symlinks to find
the correct file for each process.

The design is kept close to the ones of the similar IKCONFIG and IKHEADERS.

On x86 the x32 vDSO is derived from the x86_64 one, necessitating an
explicit dependency to avoid errors due to concurrent builds.

Suggested-by: Thomas Gleixner <tglx@xxxxxxxxxx>
Link: https://lore.kernel.org/lkml/20260602090536.045586688@xxxxxxxxxx/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>
---
Makefile | 33 ++++++++++++++++++++++++++++++++-
arch/x86/Makefile | 3 +++
init/Kconfig | 10 ++++++++++
kernel/Makefile | 1 +
kernel/vdso_debug.c | 43 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index b9c5792c79e0..8049f10c27b2 100644
--- a/Makefile
+++ b/Makefile
@@ -298,7 +298,7 @@ no-dot-config-targets := $(clean-targets) \
%asm-generic kernelversion %src-pkg dt_binding_check \
dt_style_selftest \
outputmakefile rustavailable rustfmt rustfmtcheck \
- run-command
+ run-command have-vdso-debug
no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \
image_name
single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %/
@@ -1539,6 +1539,37 @@ vdso_install: export INSTALL_FILES = $(vdso-install-y)
vdso_install:
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vdsoinst

+# ---------------------------------------------------------------------------
+# vDSO embedded debug symbols
+
+PHONY += vdso_prepare
+
+# Build the targets in $(vdso-install-y)
+# Some architectures may do this already through vdso_prepare,
+# so add a dependency to avoid race conditions
+$(vdso-install-y): vdso_prepare prepare0 FORCE
+ @$(MAKE) $(build)=$(patsubst %/,%,$(dir $@)) $@
+
+tar-opts := --mtime='1970-01-01 00:00:00' --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X
+
+quiet_cmd_vdso_debug_tar_xz = VDSODBG $@
+ cmd_vdso_debug_tar_xz = \
+ rm -rf $(tmp-target); mkdir -p $(tmp-target)/vdso/; \
+ $(MAKE) quiet=@ MODLIB=$(tmp-target) vdso_install; \
+ $(TAR) $(tar-opts) -a -c -f $@ -C $(tmp-target)/vdso/ .
+
+targets += vdso_debug.tar.xz
+vdso_debug.tar.xz: $(vdso-install-y) FORCE
+ $(call if_changed,vdso_debug_tar_xz)
+
+ifdef CONFIG_IVDSODEBUG
+prepare: vdso_debug.tar.xz
+endif
+
+PHONY += have-vdso-debug
+have-vdso-debug:
+ @echo $(if $(vdso-install-y)$(vdso-install-),y,n)
+
# ---------------------------------------------------------------------------
# Tools

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 598f178102ee..b762fddb620e 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -316,6 +316,9 @@ vdso-install-$(CONFIG_X86_64) += arch/x86/entry/vdso/vdso64/vdso64.so.dbg
vdso-install-$(CONFIG_X86_X32_ABI) += arch/x86/entry/vdso/vdso64/vdsox32.so.dbg
vdso-install-$(CONFIG_COMPAT_32) += arch/x86/entry/vdso/vdso32/vdso32.so.dbg

+# vdsox32.so.dbg is derived from vdso64.so.dbg. Avoid races with CONFIG_IVDSODEBUG
+arch/x86/entry/vdso/vdso64/vdsox32.so.dbg: arch/x86/entry/vdso/vdso64/vdso64.so.dbg
+
archprepare: checkbin
checkbin:
ifdef CONFIG_MITIGATION_RETPOLINE
diff --git a/init/Kconfig b/init/Kconfig
index 5230d4879b1c..f09132a44264 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -801,6 +801,16 @@ config IKHEADERS
or similar programs. If you build the headers as a module, a module called
kheaders.ko is built which can be loaded on-demand to get access to headers.

+config IVDSODEBUG
+ tristate "Enable vDSO debug information through /sys/kernel/vdso_debug.tar.xz"
+ depends on SYSFS
+ depends on "$(shell,make have-vdso-debug)"
+ help
+ This option enables access to the vDSO debug information. That can be
+ used to debug applications and test the vDSO implementation.
+
+ If configured as M the module will be called vdso_debug.ko.
+
config LOG_BUF_SHIFT
int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
range 12 25
diff --git a/kernel/Makefile b/kernel/Makefile
index 1e1a31673577..8adcc26ef859 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_USER_NS) += user_namespace.o
obj-$(CONFIG_PID_NS) += pid_namespace.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_IKHEADERS) += kheaders.o
+obj-$(CONFIG_IVDSODEBUG) += vdso_debug.o
obj-$(CONFIG_SMP) += stop_machine.o
obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o audit_fsnotify.o audit_tree.o
diff --git a/kernel/vdso_debug.c b/kernel/vdso_debug.c
new file mode 100644
index 000000000000..72d4f11327fc
--- /dev/null
+++ b/kernel/vdso_debug.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/cache.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/sysfs.h>
+
+asm (
+" .pushsection .rodata, \"a\" \n"
+" .global vdso_debug_data \n"
+"vdso_debug_data: \n"
+" .incbin \"vdso_debug.tar.xz\" \n"
+" .global vdso_debug_data_end \n"
+"vdso_debug_data_end: \n"
+" .popsection \n"
+);
+
+extern char vdso_debug_data[];
+extern char vdso_debug_data_end[];
+
+static struct bin_attribute vdso_debug_attr __ro_after_init =
+ __BIN_ATTR_SIMPLE_RO(vdso_debug.tar.xz, 0444);
+
+static int __init vdso_debug_init(void)
+{
+ vdso_debug_attr.private = vdso_debug_data;
+ vdso_debug_attr.size = vdso_debug_data_end - vdso_debug_data;
+
+ return sysfs_create_bin_file(kernel_kobj, &vdso_debug_attr);
+}
+
+static void __exit vdso_debug_exit(void)
+{
+ sysfs_remove_bin_file(kernel_kobj, &vdso_debug_attr);
+}
+
+module_init(vdso_debug_init);
+module_exit(vdso_debug_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>");
+MODULE_DESCRIPTION("Provide vDSO debug information at runtime");

---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260624-vdso-sysfs-abfd14fde5a7

Best regards,
--
Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>