mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Farid Zakaria <farid.m.zakaria@gmail.com>
To: kees@kernel.org, brauner@kernel.org, viro@zeniv.linux.org.uk
Cc: jack@suse.cz, shuah@kernel.org, linux-fsdevel@vger.kernel.org,
	linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Farid Zakaria <farid.m.zakaria@gmail.com>
Subject: [PATCH 2/2] selftests/exec: add test suites for $ORIGIN interpreter resolution
Date: Sun, 21 Jun 2026 21:39:34 -0700	[thread overview]
Message-ID: <20260622043934.179879-3-farid.m.zakaria@gmail.com> (raw)
In-Reply-To: <20260622043934.179879-1-farid.m.zakaria@gmail.com>

Add verification suites to test the kernel VFS and ELF loader $ORIGIN
interpreter resolution.

1. Add a KUnit unit test 'exec_test_resolve_elf_interpreter()' verifying
   path resolution format logic.
2. Add a kselftests integration test containing:
   - A nolibc-based statically linked mock interpreter that prints a
     success message and returns 42. nolibc is used to bypass glibc's
     static startup code which segfaults when loaded as an interpreter
     due to AT_PHDR mismatches.
   - A dynamic test program configured to look for the interpreter at
     $ORIGIN/mock_interp.
   - A shell script harness checking for a PASS result.

Assisted-by: Antigravity:Gemini-Pro
Signed-off-by: Farid Zakaria <farid.m.zakaria@gmail.com>
---
 fs/tests/exec_kunit.c                         | 26 +++++++++++++++++++
 tools/testing/selftests/exec/Makefile         | 12 ++++++---
 tools/testing/selftests/exec/mock_interp.c    |  6 +++++
 tools/testing/selftests/exec/origin_interp.sh | 16 ++++++++++++
 tools/testing/selftests/exec/test_prog.c      |  5 ++++
 5 files changed, 62 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/exec/mock_interp.c
 create mode 100755 tools/testing/selftests/exec/origin_interp.sh
 create mode 100644 tools/testing/selftests/exec/test_prog.c

diff --git a/fs/tests/exec_kunit.c b/fs/tests/exec_kunit.c
index 1c32cac09..991b9abad 100644
--- a/fs/tests/exec_kunit.c
+++ b/fs/tests/exec_kunit.c
@@ -119,8 +119,34 @@ static void exec_test_bprm_stack_limits(struct kunit *test)
 	}
 }
 
+static void exec_test_resolve_elf_interpreter(struct kunit *test)
+{
+	struct linux_binprm bprm = { .file = NULL };
+	struct file *f;
+	char *resolved;
+
+	// Test 1: Non-$ORIGIN interpreter path should just be duplicated
+	resolved = resolve_elf_interpreter(&bprm, "/lib64/ld-linux-x86-64.so.2");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, resolved);
+	KUNIT_EXPECT_STREQ(test, resolved, "/lib64/ld-linux-x86-64.so.2");
+	kfree(resolved);
+
+	// Test 2: $ORIGIN interpreter path
+	f = filp_open("/", O_RDONLY, 0);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, f);
+	bprm.file = f;
+
+	resolved = resolve_elf_interpreter(&bprm, "$ORIGIN/../lib/ld.so");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, resolved);
+	KUNIT_EXPECT_STREQ(test, resolved, "//../lib/ld.so");
+	kfree(resolved);
+
+	filp_close(f, NULL);
+}
+
 static struct kunit_case exec_test_cases[] = {
 	KUNIT_CASE(exec_test_bprm_stack_limits),
+	KUNIT_CASE(exec_test_resolve_elf_interpreter),
 	{},
 };
 
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index 45a3cfc43..5e2e305cb 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -10,9 +10,9 @@ ALIGN_PIES        := $(patsubst %,load_address.%,$(ALIGNS))
 ALIGN_STATIC_PIES := $(patsubst %,load_address.static.%,$(ALIGNS))
 ALIGNMENT_TESTS   := $(ALIGN_PIES) $(ALIGN_STATIC_PIES)
 
-TEST_PROGS := binfmt_script.py check-exec-tests.sh
-TEST_GEN_PROGS := execveat non-regular $(ALIGNMENT_TESTS)
-TEST_GEN_PROGS_EXTENDED := false inc set-exec script-exec.inc script-noexec.inc
+TEST_PROGS := binfmt_script.py check-exec-tests.sh origin_interp.sh
+TEST_GEN_PROGS := execveat non-regular $(ALIGNMENT_TESTS) test_prog
+TEST_GEN_PROGS_EXTENDED := false inc set-exec script-exec.inc script-noexec.inc mock_interp
 TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir
 # Makefile is a run-time dependency, since it's accessed by the execveat test
 TEST_FILES := Makefile
@@ -55,3 +55,9 @@ $(OUTPUT)/script-exec.inc: $(CHECK_EXEC_SAMPLES)/script-exec.inc
 	cp $< $@
 $(OUTPUT)/script-noexec.inc: $(CHECK_EXEC_SAMPLES)/script-noexec.inc
 	cp $< $@
+
+$(OUTPUT)/mock_interp: mock_interp.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -static -nostdlib -include ../../../include/nolibc/nolibc.h $< -o $@
+
+$(OUTPUT)/test_prog: test_prog.c $(OUTPUT)/mock_interp
+	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-dynamic-linker,'$$ORIGIN/mock_interp' $< -o $@
diff --git a/tools/testing/selftests/exec/mock_interp.c b/tools/testing/selftests/exec/mock_interp.c
new file mode 100644
index 000000000..9c9ca1098
--- /dev/null
+++ b/tools/testing/selftests/exec/mock_interp.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+int main(void)
+{
+	write(1, "Hello from mock interpreter!\n", 29);
+	return 42;
+}
diff --git a/tools/testing/selftests/exec/origin_interp.sh b/tools/testing/selftests/exec/origin_interp.sh
new file mode 100755
index 000000000..635a40839
--- /dev/null
+++ b/tools/testing/selftests/exec/origin_interp.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+# Execute the test program which has its interpreter set to $ORIGIN/mock_interp
+# Note that mock_interp must be in the same directory.
+dir=$(dirname "$0")
+out=$("$dir"/test_prog 2>&1)
+exit_code=$?
+
+if [ $exit_code -eq 42 ] && [ "$out" = "Hello from mock interpreter!" ]; then
+	echo "origin_interp: PASS"
+	exit 0
+else
+	echo "origin_interp: FAIL (exit_code=$exit_code, output='$out')"
+	exit 1
+fi
diff --git a/tools/testing/selftests/exec/test_prog.c b/tools/testing/selftests/exec/test_prog.c
new file mode 100644
index 000000000..451614def
--- /dev/null
+++ b/tools/testing/selftests/exec/test_prog.c
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+int main(void)
+{
+	return 0; /* Should never be reached if interpreter is loaded instead */
+}
-- 
2.51.2


  parent reply	other threads:[~2026-06-22  4:39 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-22  4:39 [PATCH 0/2] fs: support $ORIGIN in ELF interpreter paths Farid Zakaria
2026-06-22  4:39 ` [PATCH 1/2] " Farid Zakaria
2026-06-22  9:53   ` Jori Koolstra
2026-06-23 20:14   ` Kees Cook
2026-06-23 20:35     ` Farid Zakaria
2026-06-22  4:39 ` Farid Zakaria [this message]
2026-06-22 10:39 ` [PATCH 0/2] " Jan Kara
2026-06-22 17:15   ` Farid Zakaria
2026-06-22 21:08     ` John Ericson
2026-06-25  8:50       ` Christian Brauner
2026-06-25 19:34         ` John Ericson
2026-06-26 12:39         ` Jann Horn
2026-06-26 13:26           ` David Laight
2026-06-26 13:34             ` Jann Horn
2026-06-26 16:28               ` David Laight
2026-06-28 12:36           ` Christian Brauner
2026-06-28 13:20             ` Christian Brauner
2026-06-28 18:44               ` David Laight
2026-06-30 16:58               ` Farid Zakaria
2026-07-02  6:47                 ` Christian Brauner
2026-06-30 17:59               ` David Laight
2026-07-02 21:42                 ` [RFC PATCH] fs: introduce pluggable ELF interpreter loader registry Farid Zakaria
2026-07-03  9:22                   ` Christian Brauner
2026-07-03 18:32                     ` Farid Zakaria
2026-07-04  8:15                       ` Christian Brauner
2026-07-04 21:14                         ` [RFC PATCH] fs: binfmt_misc: introduce eBPF-based matching and interpreter selection Farid Zakaria
2026-07-06 16:01                           ` Christian Brauner
2026-07-06 16:47                             ` Farid Zakaria
2026-07-07 11:34                               ` Christian Brauner
2026-07-07 19:45                                 ` Christian Brauner
2026-07-07 22:44                                   ` Farid Zakaria
2026-07-08  9:14                                     ` Christian Brauner
2026-07-08 16:47                                       ` Christian Brauner
2026-07-09  4:07                                         ` Farid Zakaria
2026-07-09  8:46                                           ` Christian Brauner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260622043934.179879-3-farid.m.zakaria@gmail.com \
    --to=farid.m.zakaria@gmail.com \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=kees@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=shuah@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome