Linux Test Project
 help / color / mirror / Atom feed
* [LTP] [PATCH] binfmt_misc02.sh: Fix interpreter with uutils/coreutils
@ 2026-10-21  2:47 Kuan-Ying Lee via ltp
  2026-10-22 13:35 ` [LTP] " linuxtestproject.agent
  2026-10-22 13:57 ` [LTP] [PATCH] " Cyril Hrubis
  0 siblings, 2 replies; 4+ messages in thread
From: Kuan-Ying Lee via ltp @ 2026-10-21  2:47 UTC (permalink / raw)
  To: ltp; +Cc: po-hsu.lin, kuan-ying.lee

The test registers the system 'cat' directly as a binfmt_misc
interpreter and expects executing the data files to echo their content
back.

This breaks on distributions shipping the Rust uutils/coreutils
implementation (e.g. Ubuntu "Resolute"), where 'cat' is a hardlink to a
single multi-call 'coreutils' binary:

  $ readlink -f /usr/bin/cat
  /usr/lib/cargo/bin/coreutils/cat
  $ cat --version
  cat (uutils coreutils) 0.8.0

Such a binary has to work out which applet to run, and uutils does so
from AT_EXECFN, i.e. the path the kernel actually exec'd, rather than
from argv[0]. binfmt_misc sets argv[0] to the interpreter, but AT_EXECFN
keeps naming the file passed to the original execve(), so the applet
name is derived from the data file rather than from 'cat'. Renaming the
very same data file to "cat.extension" makes it work, which confirms
where the applet name comes from.

Hence the exec fails (exit 1) and subtests 1-4 report:

  binfmt_misc02 1 TFAIL: Fail to recognise a binary type

Subtests 5-6 pass because they expect no recognition and never run the
interpreter.

Fix it by registering a small wrapper script as the interpreter. The
shell execs cat itself, so argv[0] and AT_EXECFN name cat again and the
right applet is picked.

The interpreter path ends up in the binfmt_misc registration string,
whose delimiter is ':', '.' or ',' depending on the subtest, so the
path must contain none of them. That rules out $TST_TMPDIR, which
carries a '.', hence create the wrapper in a directory of our own
under $TMPDIR.

Signed-off-by: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
---
 .../kernel/fs/binfmt_misc/binfmt_misc02.sh    | 44 +++++++++++++++----
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh b/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
index 37c9b9e0f4e2..0d71f6a30ce9 100755
--- a/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
+++ b/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
@@ -18,8 +18,10 @@
 # We use various delimiteris to register a new binary type.
 
 TST_CNT=6
+TST_SETUP=binfmt_misc02_setup
+TST_CLEANUP=binfmt_misc02_cleanup
 TST_TESTFUNC=do_test
-TST_NEEDS_CMDS="cat head"
+TST_NEEDS_CMDS="cat chmod head mktemp"
 
 
 recognised_unrecognised()
@@ -85,22 +87,46 @@ verify_binfmt_misc()
 	remove_binary_type "$mntpoint/$name"
 }
 
-do_test()
+binfmt_misc02_setup()
 {
-	local cat="$(command -v cat)"
+	# The interpreter path becomes a field of the registration string,
+	# which is written with ':', '.' and ',' as delimiters below, so it
+	# must not contain any of them.
+	case "$TMPDIR" in
+	*[:.,]*) tst_brk TCONF "TMPDIR '$TMPDIR' contains ':', '.' or ','";;
+	esac
+
+	binfmt_misc_setup
+
+	interp_dir=$(mktemp -d "$TMPDIR/ltp_binfmt_miscXXXXXX")
+	[ -d "$interp_dir" ] || tst_brk TBROK "Failed to create interpreter dir"
+
+	interp="$interp_dir/interp"
+	printf '#!/bin/sh\nexec %s "$1"\n' "$(command -v cat)" > "$interp" ||
+		tst_brk TBROK "Failed to write $interp"
+	ROD chmod +x "$interp"
+}
 
+binfmt_misc02_cleanup()
+{
+	[ -n "$interp_dir" ] && rm -rf "$interp_dir"
+	binfmt_misc_cleanup
+}
+
+do_test()
+{
 	case $1 in
-	1) verify_binfmt_misc ":textension:E::extension::$cat:" \
+	1) verify_binfmt_misc ":textension:E::extension::$interp:" \
 			      "$TST_DATAROOT/file.extension" "1";;
-	2) verify_binfmt_misc ":tmagic:M:1:This::$cat:" \
+	2) verify_binfmt_misc ":tmagic:M:1:This::$interp:" \
 			      "$TST_DATAROOT/file.magic" "1";;
-	3) verify_binfmt_misc ".textension.E..extension..$cat." \
+	3) verify_binfmt_misc ".textension.E..extension..$interp." \
 			      "$TST_DATAROOT/file.extension" "1";;
-	4) verify_binfmt_misc ",tmagic,M,1,This,,$cat," \
+	4) verify_binfmt_misc ",tmagic,M,1,This,,$interp," \
 			      "$TST_DATAROOT/file.magic" "1";;
-	5) verify_binfmt_misc ":textension:E::ltp::$cat:" \
+	5) verify_binfmt_misc ":textension:E::ltp::$interp:" \
 			      "$TST_DATAROOT/file.extension" "0";;
-	6) verify_binfmt_misc ":tmagic:M:0:This::$cat:" \
+	6) verify_binfmt_misc ":tmagic:M:0:This::$interp:" \
 			      "$TST_DATAROOT/file.magic" "0";;
 	esac
 }
-- 
2.43.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 4+ messages in thread
* [LTP] [PATCH] binfmt_misc02.sh: Fix interpreter with uutils/coreutils
@ 2026-10-12  6:03 Kuan-Ying Lee via ltp
  0 siblings, 0 replies; 4+ messages in thread
From: Kuan-Ying Lee via ltp @ 2026-10-12  6:03 UTC (permalink / raw)
  To: ltp; +Cc: po-hsu.lin, kuan-ying.lee

The test registers the system 'cat' directly as a binfmt_misc
interpreter and expects executing the data files to echo their content
back.

This breaks on distributions shipping the Rust uutils/coreutils
implementation (e.g. Ubuntu "Resolute"), where 'cat' is a hardlink to a
single multi-call 'coreutils' binary:

  $ readlink -f /usr/bin/cat
  /usr/lib/cargo/bin/coreutils/cat
  $ cat --version
  cat (uutils coreutils) 0.8.0

Such a binary has to work out which applet to run, and uutils does so
from AT_EXECFN, i.e. the path the kernel actually exec'd, rather than
from argv[0]. binfmt_misc sets argv[0] to the interpreter, but AT_EXECFN
keeps naming the file passed to the original execve(), so the applet
name is derived from the data file rather than from 'cat'. Renaming the
very same data file to "cat.extension" makes it work, which confirms
where the applet name comes from.

Hence the exec fails (exit 1) and subtests 1-4 report:

  binfmt_misc02 1 TFAIL: Fail to recognise a binary type

Subtests 5-6 pass because they expect no recognition and never run the
interpreter.

Fix it by registering a small wrapper script as the interpreter. The
shell execs cat itself, so argv[0] and AT_EXECFN name cat again and the
right applet is picked.

The interpreter path ends up in the binfmt_misc registration string,
whose delimiter is ':', '.' or ',' depending on the subtest, so the
path must contain none of them. That rules out $TST_TMPDIR, which
carries a '.', hence create the wrapper in a directory of our own
under $TMPDIR.

Signed-off-by: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
---
 .../kernel/fs/binfmt_misc/binfmt_misc02.sh    | 44 +++++++++++++++----
 1 file changed, 35 insertions(+), 9 deletions(-)

diff --git a/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh b/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
index 37c9b9e0f4e2..0d71f6a30ce9 100755
--- a/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
+++ b/testcases/kernel/fs/binfmt_misc/binfmt_misc02.sh
@@ -18,8 +18,10 @@
 # We use various delimiteris to register a new binary type.
 
 TST_CNT=6
+TST_SETUP=binfmt_misc02_setup
+TST_CLEANUP=binfmt_misc02_cleanup
 TST_TESTFUNC=do_test
-TST_NEEDS_CMDS="cat head"
+TST_NEEDS_CMDS="cat chmod head mktemp"
 
 
 recognised_unrecognised()
@@ -85,22 +87,46 @@ verify_binfmt_misc()
 	remove_binary_type "$mntpoint/$name"
 }
 
-do_test()
+binfmt_misc02_setup()
 {
-	local cat="$(command -v cat)"
+	# The interpreter path becomes a field of the registration string,
+	# which is written with ':', '.' and ',' as delimiters below, so it
+	# must not contain any of them.
+	case "$TMPDIR" in
+	*[:.,]*) tst_brk TCONF "TMPDIR '$TMPDIR' contains ':', '.' or ','";;
+	esac
+
+	binfmt_misc_setup
+
+	interp_dir=$(mktemp -d "$TMPDIR/ltp_binfmt_miscXXXXXX")
+	[ -d "$interp_dir" ] || tst_brk TBROK "Failed to create interpreter dir"
+
+	interp="$interp_dir/interp"
+	printf '#!/bin/sh\nexec %s "$1"\n' "$(command -v cat)" > "$interp" ||
+		tst_brk TBROK "Failed to write $interp"
+	ROD chmod +x "$interp"
+}
 
+binfmt_misc02_cleanup()
+{
+	[ -n "$interp_dir" ] && rm -rf "$interp_dir"
+	binfmt_misc_cleanup
+}
+
+do_test()
+{
 	case $1 in
-	1) verify_binfmt_misc ":textension:E::extension::$cat:" \
+	1) verify_binfmt_misc ":textension:E::extension::$interp:" \
 			      "$TST_DATAROOT/file.extension" "1";;
-	2) verify_binfmt_misc ":tmagic:M:1:This::$cat:" \
+	2) verify_binfmt_misc ":tmagic:M:1:This::$interp:" \
 			      "$TST_DATAROOT/file.magic" "1";;
-	3) verify_binfmt_misc ".textension.E..extension..$cat." \
+	3) verify_binfmt_misc ".textension.E..extension..$interp." \
 			      "$TST_DATAROOT/file.extension" "1";;
-	4) verify_binfmt_misc ",tmagic,M,1,This,,$cat," \
+	4) verify_binfmt_misc ",tmagic,M,1,This,,$interp," \
 			      "$TST_DATAROOT/file.magic" "1";;
-	5) verify_binfmt_misc ":textension:E::ltp::$cat:" \
+	5) verify_binfmt_misc ":textension:E::ltp::$interp:" \
 			      "$TST_DATAROOT/file.extension" "0";;
-	6) verify_binfmt_misc ":tmagic:M:0:This::$cat:" \
+	6) verify_binfmt_misc ":tmagic:M:0:This::$interp:" \
 			      "$TST_DATAROOT/file.magic" "0";;
 	esac
 }
-- 
2.43.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-22 13:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21  2:47 [LTP] [PATCH] binfmt_misc02.sh: Fix interpreter with uutils/coreutils Kuan-Ying Lee via ltp
2026-10-22 13:35 ` [LTP] " linuxtestproject.agent
2026-10-22 13:57 ` [LTP] [PATCH] " Cyril Hrubis
  -- strict thread matches above, loose matches on Subject: below --
2026-10-12  6:03 Kuan-Ying Lee via ltp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox