* [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths
@ 2026-07-16 8:57 Jiangshan Yi
2026-07-16 9:09 ` sashiko-bot
2026-07-16 23:45 ` Ihor Solodrai
0 siblings, 2 replies; 4+ messages in thread
From: Jiangshan Yi @ 2026-07-16 8:57 UTC (permalink / raw)
To: ast, daniel, andrii, eddyz87, memxor
Cc: martin.lau, song, yonghong.song, jolsa, emil, ihor.solodrai,
paul.chaignon, bpf, linux-kernel, 13667453960, Jiangshan Yi
When building kselftest-all, the kselftest Makefile passes OUTPUT as a
command-line variable to each test directory:
tools/testing/selftests/Makefile:
$(MAKE) OUTPUT=$$BUILD/$$TARGET -C $$TARGET
GNU Make automatically exports command-line variables to all sub-makes.
This OUTPUT propagates through the entire build chain:
kselftest/mm (OUTPUT=.../selftests/mm)
-> gen_mods_dir -> page_frag (kernel module build)
-> tools/bpf/resolve_btfids (host tool dependency)
The resolve_btfids Makefile uses a conditional assignment:
OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
However, ?= cannot override a variable inherited from a parent build's
command line or environment. The inherited OUTPUT points to the wrong
directory (the mm selftest directory) and lacks a trailing slash.
The tools/build Makefile.build system concatenates $(OUTPUT) with
filenames without a separating slash in its pattern rules:
$(OUTPUT)%.o: %.c FORCE
When OUTPUT lacks a trailing '/', this produces corrupted paths such
as ".../selftests/mmmain.o" instead of ".../selftests/mm/main.o".
Meanwhile, the resolve_btfids Makefile itself uses $(OUTPUT)/filename
(with an explicit slash), so the HOSTLD step produces the file at a
different path than where the LINK step looks for it:
HOSTLD produces: .../selftests/mmresolve_btfids-in.o (no slash)
LINK looks for: .../selftests/mm/resolve_btfids-in.o (with slash)
This results in a linker error:
ld: cannot find .../resolve_btfids-in.o: No such file or directory
Fix this by checking the origin of OUTPUT. When it is "command line"
or "environment" (indicating leakage from a parent build such as
kselftest), use 'override' to reset it to the correct directory. When
built normally via the kernel build system, OUTPUT is set by
scripts/Makefile.include with origin "file" from the O= parameter,
which is correct and remains unaffected.
The fix can be reproduced and verified with:
make -C tools/bpf/resolve_btfids clean
# Before fix: fails with corrupted paths
make OUTPUT=/path/to/selftests/mm -C tools/bpf/resolve_btfids
# After fix: succeeds, artifacts in resolve_btfids directory
# Also test environment variable leakage:
OUTPUT=/path/to/selftests/mm make -C tools/bpf/resolve_btfids
Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
---
tools/bpf/resolve_btfids/Makefile | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile
index 7672208f65e4..eee88c73fd7a 100644
--- a/tools/bpf/resolve_btfids/Makefile
+++ b/tools/bpf/resolve_btfids/Makefile
@@ -26,6 +26,22 @@ HOSTAR ?= ar
HOSTPKG_CONFIG ?= pkg-config
CROSS_COMPILE =
+# If OUTPUT was inherited from a parent build's command line (e.g. from
+# kselftest), it points to the wrong directory and may lack a trailing
+# slash. The tools/build Makefile.build concatenates $(OUTPUT) with
+# filenames without a separating slash ($(OUTPUT)%.o), so a missing
+# trailing '/' produces corrupted paths such as "mmmain.o" instead of
+# "mm/main.o", and the linker cannot find resolve_btfids-in.o.
+#
+# When built via the kernel build system, OUTPUT is set by
+# scripts/Makefile.include (origin "file") from the O= parameter, which
+# is correct. Only a command-line origin indicates leakage from a
+# parent build and needs to be reset. Both "command line" and
+# "environment" origins indicate leakage; "file" (set by Makefile.include
+# from O=) and "undefined" are legitimate and must not be overridden.
+ifneq ($(filter command line environment,$(origin OUTPUT)),)
+override OUTPUT := $(srctree)/tools/bpf/resolve_btfids/
+endif
OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
LIBBPF_SRC := $(srctree)/tools/lib/bpf/
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths
2026-07-16 8:57 [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths Jiangshan Yi
@ 2026-07-16 9:09 ` sashiko-bot
2026-07-16 23:45 ` Ihor Solodrai
1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-07-16 9:09 UTC (permalink / raw)
To: Jiangshan Yi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The patch forcibly overrides the `OUTPUT` variable to the source tree directory if its origin is `command line` or `environment`. This breaks intentional out-of-tree builds for kernel tools and selftests (such as BPF and HID) which explicitly pass an `OUTPUT=` path on the command line. By overriding the requested path, the build writes artifacts into the source tree instead of the expected output directory, violating read-only source tree configurations and causing the selftest builds to fail because the `resolve_btfids` binary is missing from the required location.
--
--- Patch [1]: [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths ---
commit b49b49183f48428e27843ec3019b42192ca9ed12
Author: Jiangshan Yi <yijiangshan@kylinos.cn>
tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths
This commit addresses corrupted build paths caused by the OUTPUT variable
leaking from parent makes like kselftest. It attempts to fix this by checking
if OUTPUT comes from the command line or environment, and if so, overrides
it back to the source tree directory.
> diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile
> index 7672208f65e4b..eee88c73fd7a1 100644
> --- a/tools/bpf/resolve_btfids/Makefile
> +++ b/tools/bpf/resolve_btfids/Makefile
> @@ -26,6 +26,22 @@ HOSTAR ?= ar
> HOSTPKG_CONFIG ?= pkg-config
> CROSS_COMPILE =
>
> +# If OUTPUT was inherited from a parent build's command line (e.g. from
> +# kselftest), it points to the wrong directory and may lack a trailing
> +# slash. The tools/build Makefile.build concatenates $(OUTPUT) with
> +# filenames without a separating slash ($(OUTPUT)%.o), so a missing
> +# trailing '/' produces corrupted paths such as "mmmain.o" instead of
> +# "mm/main.o", and the linker cannot find resolve_btfids-in.o.
> +#
> +# When built via the kernel build system, OUTPUT is set by
> +# scripts/Makefile.include (origin "file") from the O= parameter, which
> +# is correct. Only a command-line origin indicates leakage from a
> +# parent build and needs to be reset. Both "command line" and
> +# "environment" origins indicate leakage; "file" (set by Makefile.include
> +# from O=) and "undefined" are legitimate and must not be overridden.
> +ifneq ($(filter command line environment,$(origin OUTPUT)),)
> +override OUTPUT := $(srctree)/tools/bpf/resolve_btfids/
> +endif
[Severity: Low]
Does this override break intentional out-of-tree builds?
When building BPF or HID selftests out-of-tree, the build system explicitly
passes an OUTPUT= path on the command line. Because the origin is evaluated as
"command line", this logic unconditionally overrides it, discarding the properly
requested out-of-tree path.
Won't this cause artifacts to be written directly into the source tree, violating
read-only source tree configurations and causing the build to fail when it looks
for the resolve_btfids binary in the expected output directory?
> OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
>
> LIBBPF_SRC := $(srctree)/tools/lib/bpf/
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260716085733.1761196-1-yijiangshan@kylinos.cn?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths
2026-07-16 8:57 [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths Jiangshan Yi
2026-07-16 9:09 ` sashiko-bot
@ 2026-07-16 23:45 ` Ihor Solodrai
2026-07-17 10:14 ` Jiangshan Yi
1 sibling, 1 reply; 4+ messages in thread
From: Ihor Solodrai @ 2026-07-16 23:45 UTC (permalink / raw)
To: Jiangshan Yi, ast, daniel, andrii, eddyz87, memxor
Cc: martin.lau, song, yonghong.song, jolsa, emil, paul.chaignon, bpf,
linux-kernel, 13667453960
On 7/16/26 1:57 AM, Jiangshan Yi wrote:
> When building kselftest-all, the kselftest Makefile passes OUTPUT as a
> command-line variable to each test directory:
>
> tools/testing/selftests/Makefile:
> $(MAKE) OUTPUT=$$BUILD/$$TARGET -C $$TARGET
>
> GNU Make automatically exports command-line variables to all sub-makes.
> This OUTPUT propagates through the entire build chain:
>
> kselftest/mm (OUTPUT=.../selftests/mm)
> -> gen_mods_dir -> page_frag (kernel module build)
> -> tools/bpf/resolve_btfids (host tool dependency)
>
> The resolve_btfids Makefile uses a conditional assignment:
>
> OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
>
> However, ?= cannot override a variable inherited from a parent build's
> command line or environment. The inherited OUTPUT points to the wrong
> directory (the mm selftest directory) and lacks a trailing slash.
>
> The tools/build Makefile.build system concatenates $(OUTPUT) with
> filenames without a separating slash in its pattern rules:
>
> $(OUTPUT)%.o: %.c FORCE
>
> When OUTPUT lacks a trailing '/', this produces corrupted paths such
> as ".../selftests/mmmain.o" instead of ".../selftests/mm/main.o".
> Meanwhile, the resolve_btfids Makefile itself uses $(OUTPUT)/filename
> (with an explicit slash), so the HOSTLD step produces the file at a
> different path than where the LINK step looks for it:
>
> HOSTLD produces: .../selftests/mmresolve_btfids-in.o (no slash)
> LINK looks for: .../selftests/mm/resolve_btfids-in.o (with slash)
>
> This results in a linker error:
>
> ld: cannot find .../resolve_btfids-in.o: No such file or directory
>
> Fix this by checking the origin of OUTPUT. When it is "command line"
> or "environment" (indicating leakage from a parent build such as
> kselftest), use 'override' to reset it to the correct directory. When
> built normally via the kernel build system, OUTPUT is set by
> scripts/Makefile.include with origin "file" from the O= parameter,
> which is correct and remains unaffected.
>
> The fix can be reproduced and verified with:
>
> make -C tools/bpf/resolve_btfids clean
> # Before fix: fails with corrupted paths
> make OUTPUT=/path/to/selftests/mm -C tools/bpf/resolve_btfids
> # After fix: succeeds, artifacts in resolve_btfids directory
>
> # Also test environment variable leakage:
> OUTPUT=/path/to/selftests/mm make -C tools/bpf/resolve_btfids
>
> Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
> ---
> tools/bpf/resolve_btfids/Makefile | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile
> index 7672208f65e4..eee88c73fd7a 100644
> --- a/tools/bpf/resolve_btfids/Makefile
> +++ b/tools/bpf/resolve_btfids/Makefile
> @@ -26,6 +26,22 @@ HOSTAR ?= ar
> HOSTPKG_CONFIG ?= pkg-config
> CROSS_COMPILE =
>
> +# If OUTPUT was inherited from a parent build's command line (e.g. from
> +# kselftest), it points to the wrong directory and may lack a trailing
> +# slash. The tools/build Makefile.build concatenates $(OUTPUT) with
> +# filenames without a separating slash ($(OUTPUT)%.o), so a missing
> +# trailing '/' produces corrupted paths such as "mmmain.o" instead of
> +# "mm/main.o", and the linker cannot find resolve_btfids-in.o.
> +#
> +# When built via the kernel build system, OUTPUT is set by
> +# scripts/Makefile.include (origin "file") from the O= parameter, which
> +# is correct. Only a command-line origin indicates leakage from a
> +# parent build and needs to be reset. Both "command line" and
> +# "environment" origins indicate leakage; "file" (set by Makefile.include
> +# from O=) and "undefined" are legitimate and must not be overridden.
> +ifneq ($(filter command line environment,$(origin OUTPUT)),)
> +override OUTPUT := $(srctree)/tools/bpf/resolve_btfids/
> +endif
> OUTPUT ?= $(srctree)/tools/bpf/resolve_btfids/
This seems to be a real bug, but the proposed diff is just wrong.
It doesn't even fix the case you target.
The `override` runs in the outer make, but the corruption happens in
the nested sub-make (resolve_btfids/Makefile:105):
$(BINARY_IN): fixdep FORCE prepare | $(OUTPUT)
$(Q)$(MAKE) $(build)=resolve_btfids
Try this:
$ cat parent.mk
ifneq ($(filter command line environment,$(origin OUTPUT)),)
override OUTPUT := /correct/
endif
export OUTPUT
all: ; @$(MAKE) --no-print-directory -f child.mk
$ cat child.mk
all: ; @echo "OUTPUT=[$(OUTPUT)] -> $(OUTPUT)main.o"
$ make -f parent.mk OUTPUT=/leaked/mm
OUTPUT=[/leaked/mm] -> /leaked/mmmain.o # override invisible; still broken
Your standalone repro probably only succeeds on a dirty tree.
Have you tried testing from clean?
Also bpf/Makefile:440 and hid/Makefile:159 deliberately pass
OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ on the command line.
And so the patch breaks those too:
$ mkdir -p /tmp/o/resolve_btfids && make -C tools/bpf/resolve_btfids clean \
&& make -C tools/bpf/resolve_btfids OUTPUT=/tmp/o/resolve_btfids/
...
make[1]: *** No rule to make target '.../resolve_btfids/fixdep'. Stop.
make: *** [.../tools/build/Makefile.include:15: fixdep] Error 2
I think a proper fix is to figure out a way to avoid generic OUTPUT to
fall through to resolve_btids (somewhere in selftests/lib.mk
probably).
Please make sure to test your change properly before submitting.
pw-bot: cr
>
> LIBBPF_SRC := $(srctree)/tools/lib/bpf/
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: Re: [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths
2026-07-16 23:45 ` Ihor Solodrai
@ 2026-07-17 10:14 ` Jiangshan Yi
0 siblings, 0 replies; 4+ messages in thread
From: Jiangshan Yi @ 2026-07-17 10:14 UTC (permalink / raw)
To: ihor.solodrai
Cc: 13667453960, andrii, ast, bpf, daniel, eddyz87, emil, jolsa,
linux-kernel, martin.lau, memxor, paul.chaignon, song,
yijiangshan, yonghong.song
Hi Ihor Solodrai,
Thanks for the review -- you are right on both counts, and v1 is dropped.
On the nested sub-make: the `override OUTPUT :=` only changes the
variable inside the outer resolve_btfids make; it does not touch
MAKEOVERRIDES, so the nested `$(MAKE) $(build)=resolve_btfids`
(resolve_btfids/Makefile:90) still inherits the original command-line
OUTPUT through MAKEFLAGS. The pattern rules that produce the corrupted
`$(OUTPUT)%.o` paths run in that nested sub-make, so they still see the
un-slashed value. Your parent.mk/child.mk repro captures this exactly.
On bpf/hid: selftests/bpf/Makefile:440 and selftests/hid/Makefile:159
build resolve_btfids directly with
`OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/` on the command line. An
origin check cannot tell those deliberate command-line assignments apart
from a leaked one, so v1 clobbered them -- exactly the breakage you
showed. The origin is simply the wrong place to make this decision.
v2 takes the approach you suggested: drop the generic kselftest OUTPUT
at the gen_mods_dir descent in selftests/lib.mk, so it never reaches the
kernel module build (and thus resolve_btfids) as a command-line
variable:
gen_mods_dir: MAKEOVERRIDES := $(filter-out OUTPUT=%,$(MAKEOVERRIDES))
gen_mods_dir:
$(Q)$(MAKE) -C $(TEST_GEN_MODS_DIR)
clean_mods_dir: MAKEOVERRIDES := $(filter-out OUTPUT=%,$(MAKEOVERRIDES))
clean_mods_dir:
$(Q)$(MAKE) -C $(TEST_GEN_MODS_DIR) clean
gen_mods_dir is the only path through which kselftest's per-test OUTPUT
leaks into a kernel build (the TEST_GEN_MODS_DIR module build, which can
the other selftest sub-makes -- and the test programs that rely on
OUTPUT -- are unaffected.
With the leaked command-line OUTPUT gone, resolve_btfids is reached with
only the O= that the kernel build passes on its tools/% descent, so the
`OUTPUT := $(ABSOLUTE_O)/...` assignment in scripts/Makefile.include (a
simple assignment) wins at every make level, including the nested
`$(build)=resolve_btfids` sub-make where the pattern rules run. bpf and
hid invoke resolve_btfids directly with their own OUTPUT= and do not go
through gen_mods_dir, so they are untouched.
Tested from a clean tree:
* kselftest build of a TEST_GEN_MODS_DIR test (mm/page_frag) with
CONFIG_DEBUG_INFO_BTF: resolve_btfids now builds into its
O=-derived directory; no more "mmmain.o" / missing
resolve_btfids-in.o.
* make -C tools/bpf/resolve_btfids
make -C tools/bpf/resolve_btfids OUTPUT=/tmp/o/resolve_btfids/
both still build (bpf/hid-style explicit OUTPUT= preserved).
* make OUTPUT=/tmp/build/kcmp -C tools/testing/selftests/kcmp still
honours OUTPUT for its own programs.
v2 posted as a separate thread.
Thanks,
Jiangshan
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-17 10:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 8:57 [PATCH] tools/resolve_btfids: fix OUTPUT leakage from kselftest causing corrupted build paths Jiangshan Yi
2026-07-16 9:09 ` sashiko-bot
2026-07-16 23:45 ` Ihor Solodrai
2026-07-17 10:14 ` Jiangshan Yi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox