[Devel] [PATCH vz10] selftests: build test modules against the kernel tree

Eva Kurchatova eva.kurchatova at virtuozzo.com
Sun Aug 9 21:18:13 MSK 2026


Selftests livepatch, cgroup and mm/page_frag build out-of-tree kernel
modules and default KDIR to /lib/modules/$(uname -r)/build, which is
the running kernel build tree on the currently building host.
That is wrong whenever the selftests are built as part of a kernel
package: `uname -r` is not the kernel being packaged, so the modules
either are not built at all (no source tree for the builders kernel)
or come out with the wrong vermagic and symbol layout.
Either way no usable test modules end up in the packaged test suite,
and a testing host may not have the kernel build tree to compile them
either, so the tests will fail.

Default KDIR to the kernel tree the tests are built from, or to its O=
build directory, whenever that tree is configured and built.
This is exactly what bpf/test_kmods has been already doing all along,
and its modules are packaged and loaded successfully today.
Testing for include/config/auto.conf and Module.symvers keeps the previous
behaviour for a bare source checkout, and for a source tree that was
mrpropered after the kernel had been built (packaging copies
Module.symvers back into such a tree), so nothing that builds today
starts failing.

Also test for $(KDIR)/Makefile rather than for $(KDIR) itself before
descending into the kernel tree: /lib/modules/$(uname -r)/build is
commonly a dangling symlink, which the previous test accepted before
failing in make -C. Same protection is applied to bpf/page_frag, as it
had no such check at all.

With this, `make kselftest TARGETS=livepatch` in a built kernel tree
builds the modules for that kernel and `make install` ships them, so an
installed testsuite runs against pre-built modules and needs no kernel
build tree at all.

Signed-off-by: Eva Kurchatova <eva.kurchatova at virtuozzo.com>

https://virtuozzo.atlassian.net/browse/VSTOR-139647
Feature: fix selftests
---
 .../selftests/cgroup/test_modules/Makefile    | 25 ++++++++++++++++---
 .../selftests/livepatch/test_modules/Makefile | 25 ++++++++++++++++---
 tools/testing/selftests/mm/Makefile           | 14 +++++++++++
 tools/testing/selftests/mm/page_frag/Makefile | 22 ++++++++++++++++
 4 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_modules/Makefile b/tools/testing/selftests/cgroup/test_modules/Makefile
index 3f39eeda3a92..a47af9b7f18a 100644
--- a/tools/testing/selftests/cgroup/test_modules/Makefile
+++ b/tools/testing/selftests/cgroup/test_modules/Makefile
@@ -1,17 +1,34 @@
 TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test modules against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: When the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting
+# modules would carry the wrong vermagic and symbol layout. Fall back to
+# the running kernel's build tree for standalone builds.
+KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(TESTMODS_DIR)/../../../../..))
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
 KDIR ?= /lib/modules/$(shell uname -r)/build
 
 obj-m += cg_freezer_hang.o \
 	cg_freezer_kthread.o
 
-# Ensure that KDIR exists, otherwise skip the compilation
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships pre-built modules and has no kernel tree above it.
 modules:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	$(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
 endif
 
-# Ensure that KDIR exists, otherwise skip the clean target
+# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
 clean:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	$(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
 endif
diff --git a/tools/testing/selftests/livepatch/test_modules/Makefile b/tools/testing/selftests/livepatch/test_modules/Makefile
index 939230e571f5..7dc026fd42f7 100644
--- a/tools/testing/selftests/livepatch/test_modules/Makefile
+++ b/tools/testing/selftests/livepatch/test_modules/Makefile
@@ -1,4 +1,18 @@
 TESTMODS_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test modules against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting
+# modules would carry the wrong vermagic and symbol CRCs. Fall back to
+# the running kernel's build tree for standalone builds.
+KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(TESTMODS_DIR)/../../../../..))
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
 KDIR ?= /lib/modules/$(shell uname -r)/build
 
 obj-m += test_klp_atomic_replace.o \
@@ -14,14 +28,17 @@ obj-m += test_klp_atomic_replace.o \
 	test_klp_state3.o \
 	test_klp_syscall.o
 
-# Ensure that KDIR exists, otherwise skip the compilation
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships pre-built modules and has no kernel tree above it.
 modules:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	$(Q)$(MAKE) -C $(KDIR) modules KBUILD_EXTMOD=$(TESTMODS_DIR)
 endif
 
-# Ensure that KDIR exists, otherwise skip the clean target
+# Ensure that KDIR is a kernel build tree, otherwise skip the clean target
 clean:
-ifneq ("$(wildcard $(KDIR))", "")
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	$(Q)$(MAKE) -C $(KDIR) clean KBUILD_EXTMOD=$(TESTMODS_DIR)
 endif
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index 3de23ea4663f..3e643834d3a2 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -36,6 +36,20 @@ MAKEFLAGS += --no-builtin-rules
 CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
 LDLIBS = -lrt -lpthread -lm
 
+# Kernel build tree to compile page_frag_test.ko against. Prefer the
+# kernel tree these tests are part of (or its O= build directory) when it
+# is configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting module
+# would carry the wrong vermagic and symbol CRCs. Fall back to the
+# running kernel's build tree for standalone builds. Keep this in sync
+# with page_frag/Makefile, which is invoked separately by lib.mk.
+KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(CURDIR)/../../../..))
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
 KDIR ?= /lib/modules/$(shell uname -r)/build
 ifneq (,$(wildcard $(KDIR)/Module.symvers))
 ifneq (,$(wildcard $(KDIR)/include/linux/page_frag_cache.h))
diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile
index 8c8bb39ffa28..2c2918bbe0eb 100644
--- a/tools/testing/selftests/mm/page_frag/Makefile
+++ b/tools/testing/selftests/mm/page_frag/Makefile
@@ -1,4 +1,18 @@
 PAGE_FRAG_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
+
+# Kernel build tree to compile the test module against. Prefer the kernel
+# tree this test is part of (or its O= build directory) when it is
+# configured and built, like bpf/test_kmods already does: when the
+# selftests are built as part of a kernel package, uname -r is the build
+# host's kernel and not the kernel being packaged, so the resulting module
+# would carry the wrong vermagic and symbol CRCs. Fall back to the
+# running kernel's build tree for standalone builds.
+KDIR_TREE := $(if $(O),$(abspath $(O)),$(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..))
+ifneq (,$(wildcard $(KDIR_TREE)/include/config/auto.conf))
+ifneq (,$(wildcard $(KDIR_TREE)/Module.symvers))
+KDIR ?= $(KDIR_TREE)
+endif
+endif
 KDIR ?= /lib/modules/$(shell uname -r)/build
 
 ifeq ($(V),1)
@@ -11,8 +25,16 @@ MODULES = page_frag_test.ko
 
 obj-m += page_frag_test.o
 
+# Ensure that KDIR is a kernel build tree, otherwise skip the compilation.
+# Testing for the Makefile rather than for the directory itself also covers
+# a dangling /lib/modules/$(uname -r)/build symlink, and an installed
+# testsuite, which ships a pre-built module and has no kernel tree above it.
 all:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	+$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) modules
+endif
 
 clean:
+ifneq ("$(wildcard $(KDIR)/Makefile)", "")
 	+$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) clean
+endif
-- 
2.55.0



More information about the Devel mailing list