From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eva Kurchatova Date: Wed, 12 Aug 2026 12:49:17 +0300 Subject: [Devel] [PATCH vz10 v2] selftests: build test modules against the kernel tree Message-ID: <20260812094921.162724-1-eva.kurchatova@virtuozzo.com> List-Id: 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 built and packaged that way today. Pick the build directory up from O= or KBUILD_OUTPUT, and resolve a relative one against the source tree, the way kbuild resolves it as well. 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. The same protection is applied to bpf/test_kmods and mm/page_frag, which had no such check at all. Give bpf/test_kmods the same treatment while at it, so that every in-tree test module picks KDIR the same way: it hardcoded the source tree with no regard for O=, and failed outright instead of falling back when that tree was not configured. In an O= build KDIR is the build directory, which carries the generated configuration but not the source headers. mm/Makefile decides whether to build page_frag_test.ko by looking for include/linux/page_frag_cache.h below KDIR, so look for that header through the "source" symlink that outputmakefile leaves in the build directory as well, otherwise an O= build skips the module and blames a too old kernel for it. Split kernel-devel packages that keep sources and build artifacts apart carry the same symlink. 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 https://virtuozzo.atlassian.net/browse/VSTOR-139647 Feature: fix selftests --- Changes since v1: - Look for page_frag_cache.h through the "source" symlink as well. v1 tested $(KDIR)/include/linux/page_frag_cache.h only, but in an O= build KDIR is the build directory, which carries the generated configuration and no source headers at all. mm/Makefile therefore left TEST_GEN_MODS_DIR unset, lib.mk never descended into page_frag/, page_frag_test.ko was neither built nor installed, and the build blamed a too old kernel for it. Before v1 that case built the module against /lib/modules/$(uname -r)/build, where the header is present, so v1 did regress it. - Resolve a relative O= against the source tree. v1 fed O= to $(abspath ...), which resolves against the directory of the Makefile being read, so make -C O=../../../../out placed the build directory several levels off and silently fell back to /lib/modules/$(uname -r)/build. Going through the top level selftests Makefile was unaffected, it hands an absolute path down. - Honour KBUILD_OUTPUT, not only O=, since kbuild treats the two the same and a suite Makefile invoked directly never sees the O= that the top level selftests Makefile derives from it. - Apply the same KDIR selection and the $(KDIR)/Makefile test to bpf/test_kmods, so that all in-tree test modules pick their kernel build tree the same way. It hardcoded the source tree, ignoring O=, and failed the build instead of falling back when that tree was not configured. - Derive the source tree in mm/Makefile from MAKEFILE_LIST rather than from $(CURDIR), to match the other four Makefiles and to not depend on make having been entered with -C. .../testing/selftests/bpf/test_kmods/Makefile | 30 ++++++++++++++++- .../selftests/cgroup/test_modules/Makefile | 33 ++++++++++++++++--- .../selftests/livepatch/test_modules/Makefile | 33 ++++++++++++++++--- tools/testing/selftests/mm/Makefile | 33 ++++++++++++++++++- tools/testing/selftests/mm/page_frag/Makefile | 30 +++++++++++++++++ 5 files changed, 149 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/bpf/test_kmods/Makefile b/tools/testing/selftests/bpf/test_kmods/Makefile index d4e50c4509c9..2353140505d6 100644 --- a/tools/testing/selftests/bpf/test_kmods/Makefile +++ b/tools/testing/selftests/bpf/test_kmods/Makefile @@ -1,5 +1,25 @@ TEST_KMOD_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) -KDIR ?= $(abspath $(TEST_KMOD_DIR)/../../../../..) + +# Kernel build tree to compile the test modules against. This already +# defaulted to the kernel tree these tests are part of; also honour its +# O= or KBUILD_OUTPUT build directory, and fall back to the running +# kernel's build tree when the tree is not configured and built, so that +# all in-tree test modules pick KDIR the same way. +KSRC_TREE := $(abspath $(TEST_KMOD_DIR)/../../../../..) +KOUT := $(or $(O),$(KBUILD_OUTPUT)) +ifeq ($(KOUT),) +KDIR_TREE := $(KSRC_TREE) +else ifneq (,$(filter /%,$(KOUT))) +KDIR_TREE := $(abspath $(KOUT)) +else +KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT)) +endif +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) Q = @@ -14,8 +34,16 @@ $(foreach m,$(MODULES),$(eval obj-m += $(m:.ko=.o))) CFLAGS_bpf_testmod.o = -I$(src) +# 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. all: +ifneq ("$(wildcard $(KDIR)/Makefile)", "") $(Q)$(MAKE) -C $(KDIR) M=$(TEST_KMOD_DIR) modules +endif +# Ensure that KDIR is a kernel build tree, otherwise skip the clean target clean: +ifneq ("$(wildcard $(KDIR)/Makefile)", "") $(Q)$(MAKE) -C $(KDIR) M=$(TEST_KMOD_DIR) clean +endif diff --git a/tools/testing/selftests/cgroup/test_modules/Makefile b/tools/testing/selftests/cgroup/test_modules/Makefile index 3f39eeda3a92..1dc531589b15 100644 --- a/tools/testing/selftests/cgroup/test_modules/Makefile +++ b/tools/testing/selftests/cgroup/test_modules/Makefile @@ -1,17 +1,42 @@ 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. +KSRC_TREE := $(abspath $(TESTMODS_DIR)/../../../../..) +KOUT := $(or $(O),$(KBUILD_OUTPUT)) +ifeq ($(KOUT),) +KDIR_TREE := $(KSRC_TREE) +else ifneq (,$(filter /%,$(KOUT))) +KDIR_TREE := $(abspath $(KOUT)) +else +KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT)) +endif +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..66dcbd842f71 100644 --- a/tools/testing/selftests/livepatch/test_modules/Makefile +++ b/tools/testing/selftests/livepatch/test_modules/Makefile @@ -1,4 +1,26 @@ 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. +KSRC_TREE := $(abspath $(TESTMODS_DIR)/../../../../..) +KOUT := $(or $(O),$(KBUILD_OUTPUT)) +ifeq ($(KOUT),) +KDIR_TREE := $(KSRC_TREE) +else ifneq (,$(filter /%,$(KOUT))) +KDIR_TREE := $(abspath $(KOUT)) +else +KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT)) +endif +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 +36,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..1d6bb5cf9e08 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -36,9 +36,40 @@ 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. +KSRC_TREE := $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../../..) +KOUT := $(or $(O),$(KBUILD_OUTPUT)) +ifeq ($(KOUT),) +KDIR_TREE := $(KSRC_TREE) +else ifneq (,$(filter /%,$(KOUT))) +KDIR_TREE := $(abspath $(KOUT)) +else +KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT)) +endif +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 + +# A build directory holds the generated configuration but no source +# headers, so look for the header through the "source" symlink that +# outputmakefile leaves in an O= build directory as well. Split +# kernel-devel packages carry the same symlink. +PAGE_FRAG_HDR := $(firstword $(wildcard \ + $(KDIR)/include/linux/page_frag_cache.h \ + $(KDIR)/source/include/linux/page_frag_cache.h)) + ifneq (,$(wildcard $(KDIR)/Module.symvers)) -ifneq (,$(wildcard $(KDIR)/include/linux/page_frag_cache.h)) +ifneq (,$(PAGE_FRAG_HDR)) TEST_GEN_MODS_DIR := page_frag else PAGE_FRAG_WARNING = "missing page_frag_cache.h, please use a newer kernel" diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile index 8c8bb39ffa28..f7bc03f5d914 100644 --- a/tools/testing/selftests/mm/page_frag/Makefile +++ b/tools/testing/selftests/mm/page_frag/Makefile @@ -1,4 +1,26 @@ 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. +KSRC_TREE := $(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..) +KOUT := $(or $(O),$(KBUILD_OUTPUT)) +ifeq ($(KOUT),) +KDIR_TREE := $(KSRC_TREE) +else ifneq (,$(filter /%,$(KOUT))) +KDIR_TREE := $(abspath $(KOUT)) +else +KDIR_TREE := $(abspath $(KSRC_TREE)/$(KOUT)) +endif +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 +33,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