From nobody Sat Sep 26 18:16:28 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hsbP91d03z6tRZS for ; Sat, 26 Sep 2026 18:16:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hsbP86s6dz4JGg for ; Sat, 26 Sep 2026 18:16:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790446589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=514o8hs4vTPbs1ERxr9xSy/f6kfNdw+MDczf6zR8xWk=; b=qB+3VcZ/yF/1U79b+Qi1yCJwAB5yWafhUrPX86wbvD9IvXkkH+WWO1Lm+Tntv34WAYY+1n 0c7JHvKCpRcZvMdcWj9xtsmombx9hUldCEcTtJjpZc0PBiVhgy+ETjrq1F/VjOsSKhQ01P 6Xyz90ZKNA/YZ/KxG4Y8Cdml+3EMaqGiwI5qVuA0b8ZaR1zyV5SbzZ5CCnv0L/jNL05/4/ sKtCXGgUEGHq/8n/4Q9Gq84LRC5KYote/UDt5irxAHtdorcDjPx3bh669vR/l30sTRijrw es4gIn+47Alvmm4XZF7VqRewLP/6EJU7Tv97Pwm//P2o/TXlHEDwb0qqZHtsiQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790446589; b=a0pxs/Hry+NLDjpZ6Z2h2j+BN6+MTWx+pPjrg5E+jfzhhUP11jtewjoX/s+RsEt0IS49BU 36vvFpBNQZIRWJSnUb7JkNg9rXvDvcR1clYI6Fi2bSA6sd3zfJhQ4SKHv2J7BQ+Rq5fVJC CiFGvG6dhqtdYnkgw6Sy4m4NYG1g/E2PNf2uwV68AJ+JxyecCoAvykOuFGGiSRYt8ezyLQ m9DNmnwbZUlIil1bNpP46PWLI7Z742LFmTcjaTVM0s6I2z/t6LMCa9zpaWJQMmuzXr3J5Z uF53N+aHftw4R+xTAGhN1iWr6zAO3sBz2q6CZvO8scgq8l+saz2zUvnD5FWA0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790446589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=514o8hs4vTPbs1ERxr9xSy/f6kfNdw+MDczf6zR8xWk=; b=Usxu186ms6GG9S94iLtOBqtti69fTqGbeZYS423tAIR8HW/c3iG4FitoHJJljoFoFrnTWU 3SIQgK6MTafGwHnZ2EjmDFE3qe1lx9o2BWIXuOB3rPdF6PHpxwUJwJVeSucoSqV3RWxMRH zl3GJdP97DWh6INxm7kMERHW0UOjhgO5EQQh+0GbL8/NxktRAhrWd7OQoZCHT7o5eYju6u m5V+/sUQOIUptH3bt8R57Lgyk/H7hT4Vedrg6S91sIUoZfpLGMnKgY//sERlMewiFYSVq3 kc8h5SmexQ5L2bbyMjOwXRu5V5IwIwIEz44osmIOvTMeiSbQbzD9jP0FEALZDQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hsbP85NmLz15b0 for ; Sat, 26 Sep 2026 18:16:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 268ac by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 26 Sep 2026 18:16:28 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Devin Teske Subject: git: b98d169d1f91 - main - tests/sys/vfs: add ABI-root absolute symlink tests List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dteske X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: b98d169d1f910e0b28c7ea2f26fcc09f83614ec9 Auto-Submitted: auto-generated Date: Sat, 26 Sep 2026 18:16:28 +0000 Message-Id: <6ab80bfc.268ac.459a2395@gitrepo.freebsd.org> The branch main has been updated by dteske: URL: https://cgit.FreeBSD.org/src/commit/?id=b98d169d1f910e0b28c7ea2f26fcc09f83614ec9 commit b98d169d1f910e0b28c7ea2f26fcc09f83614ec9 Author: Devin Teske AuthorDate: 2026-09-26 18:12:33 +0000 Commit: Devin Teske CommitDate: 2026-09-26 18:12:33 +0000 tests/sys/vfs: add ABI-root absolute symlink tests Pin the overlay namei(9) uses for Linux ABI processes: a target under the ABI root wins (PR 289739), a native-only target should retry from the native root (PR 297426), an ENOENT past a resolved ABI target is not retried, and the plain no-symlink native fallback is unchanged. Skip without a Linux userland so CI stays green. The two native-only cases use atf_expect_fail until the retry lands. PR: 297426 Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D59990 --- tests/sys/vfs/Makefile | 2 + tests/sys/vfs/abi_root_symlink.sh | 279 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) diff --git a/tests/sys/vfs/Makefile b/tests/sys/vfs/Makefile index e25282b2c70a..f34616e22ebf 100644 --- a/tests/sys/vfs/Makefile +++ b/tests/sys/vfs/Makefile @@ -5,6 +5,8 @@ TESTSDIR= ${TESTSBASE}/sys/vfs ATF_TESTS_C+= lookup_cap_dotdot CFLAGS.lookup_cap_dotdot.c+= -I${SRCTOP}/tests +ATF_TESTS_SH+= abi_root_symlink + #ATF_TESTS_SH+= lookup_test TAP_TESTS_SH+= trailing_slash diff --git a/tests/sys/vfs/abi_root_symlink.sh b/tests/sys/vfs/abi_root_symlink.sh new file mode 100644 index 000000000000..18f7b5915a28 --- /dev/null +++ b/tests/sys/vfs/abi_root_symlink.sh @@ -0,0 +1,279 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2026 Devin Teske +# +# Regression tests for absolute symlink resolution under an ABI root +# (compat.linux.emul_path). namei(9) resolves paths for Linux ABI +# processes by trying the ABI root first and falling back to the +# native root. Absolute symlink targets receive the same treatment: +# a target is first resolved under the ABI root (so self-contained +# Linux userlands keep working, PR 289739); when the target itself +# does not resolve there, the walk restarts once from the native +# root using the expansion (so symlinks pointing at host paths, and +# linprocfs' /proc//exe, keep working, PR 297426). An ENOENT +# past a target that did resolve under the ABI root falls back to +# the original path like any other lookup. +# +# These tests require the Linux ABI (linux_enable=YES) and a Linux +# userland (e.g. emulators/linux_base-rl9) providing ${emul_path}/bin/sh. +# Without that, they skip, so CI jobs that lack a Linux base do not +# fail. The two native-only cases still fail on CURRENT namei(9) and +# use atf_expect_fail until the native-root retry lands (PR 297426). +# Each case comments the fixture so it can be rebuilt by hand. +# $wd is any empty directory (the ATF work directory when kyua +# runs). $emul is compat.linux.emul_path, usually /compat/linux. +# $emul$wd means the same path names created under that ABI root. +# + +require_linux() +{ + emul=$(sysctl -n compat.linux.emul_path 2>/dev/null) + [ "$emul" ] || atf_skip "Linux ABI not present (compat.linux.emul_path)" + kldstat -q -m linux64 || kldstat -q -m linux || + atf_skip "linux(4) not loaded" + lsh="$emul/bin/sh" + [ -x "$lsh" ] || atf_skip "Linux userland not installed ($lsh)" + # Mirror of the ATF work directory under the ABI root. + wd=$(pwd) + abiwd="$emul$wd" + atf_check mkdir -p "$abiwd" +} + +cleanup_linux() +{ + emul=$(sysctl -n compat.linux.emul_path 2>/dev/null) + [ "$emul" ] || return 0 + rm -rf "$emul$(pwd)" 2>/dev/null + # Remove now-empty parents mirrored under the ABI root. + rmdir -p "$emul$(dirname "$(pwd)")" 2>/dev/null + return 0 +} + +atf_test_case symlink_target_in_abi_root cleanup +symlink_target_in_abi_root_head() +{ + atf_set "descr" "Absolute symlink target under the ABI root wins" \ + "over an identically named native file (PR 289739)" + atf_set "require.user" "root" +} +symlink_target_in_abi_root_body() +{ + # + # Recreate by hand. $wd is any empty directory. $emul is + # compat.linux.emul_path (usually /compat/linux). + # + # Native: + # $wd/f-both + # Regular file containing the word "native". + # + # ABI (the same path names created under $emul): + # $emul$wd/f-both + # Regular file containing the word "abi". + # $emul$wd/link-both + # Absolute symlink whose target is $wd/f-both. + # + # A Linux process opens $wd/link-both. namei tries that path + # under the ABI root first ($emul$wd/link-both), follows the + # symlink to $wd/f-both, and stays on the ABI pass, so the + # file that is read is $emul$wd/f-both. + # + # Expected result: the read returns "abi". + # + require_linux + printf native > "$wd/f-both" + printf abi > "$abiwd/f-both" + atf_check ln -s "$wd/f-both" "$abiwd/link-both" + atf_check -o inline:"abi" "$lsh" -c "cat $wd/link-both" +} +symlink_target_in_abi_root_cleanup() +{ + cleanup_linux +} + +atf_test_case symlink_target_native_only cleanup +symlink_target_native_only_head() +{ + atf_set "descr" "Absolute symlink under the ABI root pointing at" \ + "a native-only file falls back to the native root (PR 297426)" + atf_set "require.user" "root" +} +symlink_target_native_only_body() +{ + # + # Recreate by hand. $wd is any empty directory. $emul is + # compat.linux.emul_path (usually /compat/linux). + # + # Native: + # $wd/f-native + # Regular file containing the word "native". + # + # ABI (the same path names created under $emul): + # $emul$wd/link-native + # Absolute symlink whose target is $wd/f-native. + # There is no $emul$wd/f-native. + # + # A Linux process opens $wd/link-native. namei tries that + # path under the ABI root first ($emul$wd/link-native) and + # follows the symlink to $wd/f-native. That target does not + # exist under the ABI root, so the walk should restart once + # from the native root using the expansion and read + # $wd/f-native. + # + # Expected result: the read returns "native". + # On CURRENT namei this is ENOENT (atf_expect_fail; PR 297426). + # + require_linux + printf native > "$wd/f-native" + atf_check ln -s "$wd/f-native" "$abiwd/link-native" + atf_expect_fail \ + "PR 297426: abs symlink to native-only target fails under ABI root" + atf_check -o inline:"native" "$lsh" -c "cat $wd/link-native" +} +symlink_target_native_only_cleanup() +{ + cleanup_linux +} + +atf_test_case symlink_target_native_only_midpath cleanup +symlink_target_native_only_midpath_head() +{ + atf_set "descr" "Absolute directory symlink under the ABI root" \ + "pointing at a native-only directory falls back to the native" \ + "root for lookups through it (PR 297426), as with" \ + "linux-rl9-fontconfig's /etc/fonts -> /usr/local/etc/fonts" + atf_set "require.user" "root" +} +symlink_target_native_only_midpath_body() +{ + # + # Recreate by hand. $wd is any empty directory. $emul is + # compat.linux.emul_path (usually /compat/linux). + # + # Native: + # $wd/ndir/ + # Directory. + # $wd/ndir/f + # Regular file containing the word "native". + # + # ABI (the same path names created under $emul): + # $emul$wd/dirlink + # Absolute symlink whose target is $wd/ndir. + # There is no $emul$wd/ndir. + # + # A Linux process opens $wd/dirlink/f. namei tries that path + # under the ABI root first ($emul$wd/dirlink/f), follows + # dirlink to $wd/ndir, and then wants $wd/ndir/f. The + # directory does not exist under the ABI root, so the walk + # should restart once from the native root using the + # expansion and read $wd/ndir/f. This is the + # linux-rl9-fontconfig case (/etc/fonts -> + # /usr/local/etc/fonts). + # + # Expected result: the read returns "native". + # On CURRENT namei this is ENOENT (atf_expect_fail; PR 297426). + # + require_linux + atf_check mkdir "$wd/ndir" + printf native > "$wd/ndir/f" + atf_check ln -s "$wd/ndir" "$abiwd/dirlink" + atf_expect_fail \ + "PR 297426: abs dir symlink to native-only target fails under ABI root" + atf_check -o inline:"native" "$lsh" -c "cat $wd/dirlink/f" +} +symlink_target_native_only_midpath_cleanup() +{ + cleanup_linux +} + +atf_test_case symlink_target_resolved_suffix cleanup +symlink_target_resolved_suffix_head() +{ + atf_set "descr" "ENOENT past an absolute symlink target that" \ + "resolved under the ABI root is not retried from the native" \ + "root, even when the missing suffix exists natively" + atf_set "require.user" "root" +} +symlink_target_resolved_suffix_body() +{ + # + # Recreate by hand. $wd is any empty directory. $emul is + # compat.linux.emul_path (usually /compat/linux). + # + # Native: + # $wd/tdir/ + # Directory. + # $wd/tdir/f + # Regular file containing the word "native". + # + # ABI (the same path names created under $emul): + # $emul$wd/tdir/ + # Empty directory (no file named f). + # $emul$wd/reslink + # Absolute symlink whose target is $wd/tdir. + # + # A Linux process opens $wd/reslink/f. namei tries that path + # under the ABI root first ($emul$wd/reslink/f), follows + # reslink to $wd/tdir, and finds $emul$wd/tdir on the ABI + # pass. The leftover component f is missing there. Because + # the symlink target already resolved under the ABI root, + # the native restart must not walk the expansion (that would + # incorrectly find $wd/tdir/f). It restarts the original + # path and still gets ENOENT. + # + # Expected result: ENOENT. + # + require_linux + atf_check mkdir "$abiwd/tdir" + atf_check mkdir "$wd/tdir" + printf native > "$wd/tdir/f" + atf_check ln -s "$wd/tdir" "$abiwd/reslink" + atf_check -s not-exit:0 -e ignore "$lsh" -c "cat $wd/reslink/f" +} +symlink_target_resolved_suffix_cleanup() +{ + cleanup_linux +} + +atf_test_case plain_native_fallback cleanup +plain_native_fallback_head() +{ + atf_set "descr" "Plain path (no symlink) absent under the ABI root" \ + "still falls back to the native root" + atf_set "require.user" "root" +} +plain_native_fallback_body() +{ + # + # Recreate by hand. $wd is any empty directory. $emul is + # compat.linux.emul_path (usually /compat/linux). + # + # Native: + # $wd/f-plain + # Regular file containing the word "native". + # + # ABI (the same path names created under $emul): + # There is no $emul$wd/f-plain, and no symlink. + # + # A Linux process opens $wd/f-plain. namei tries that path + # under the ABI root first, gets ENOENT, and restarts the + # original path from the native root. + # + # Expected result: the read returns "native". + # + require_linux + printf native > "$wd/f-plain" + atf_check -o inline:"native" "$lsh" -c "cat $wd/f-plain" +} +plain_native_fallback_cleanup() +{ + cleanup_linux +} + +atf_init_test_cases() +{ + atf_add_test_case symlink_target_in_abi_root + atf_add_test_case symlink_target_native_only + atf_add_test_case symlink_target_native_only_midpath + atf_add_test_case symlink_target_resolved_suffix + atf_add_test_case plain_native_fallback +}