Laszlo Ersek
2023-Mar-22 16:53 UTC
[Libguestfs] [libnbd PATCH 0/3] reenable execvpe unit testing in Alpine Linux containers
These patches have been pushed (f5a065aa3a9c..9075f68ffc8b); I'm posting
them for visibility.
Laszlo
Laszlo Ersek (3):
lib/test-fork-safe-execvpe.sh: generalize "run" to "run0"
lib/test-fork-safe-execvpe.sh: cope with Alpine Linux / BusyBox
limitations
Revert "ci: skip "lib/test-fork-safe-execvpe.sh" on Alpine
Linux"
ci/skipped_tests | 10 ----
lib/test-fork-safe-execvpe.sh | 63 +++++++++++++-------
2 files changed, 42 insertions(+), 31 deletions(-)
Laszlo Ersek
2023-Mar-22 16:53 UTC
[Libguestfs] [libnbd PATCH 1/3] lib/test-fork-safe-execvpe.sh: generalize "run" to "run0"
It turns out that we'll need to put the generality of our
"test-fork-safe-execvpe" binary executable to use, in that it takes
separate "program-to-exec" and "argv0" (for the
program-to-exec)
arguments.
Currently, the "run" function duplicates $2 to both
"program-to-exec" and
"argv0", for "test-fork-safe-execvpe". Remove the
duplication (expect the
caller to provide separate $2 and $3 arguments, respectively) and rename
"run" to "run0". At the same time, reimplement
"run" as a simple wrapper
(i.e., with just the duplication) around "run0".
This patch is worth viewing with "git show --color-words" as well.
Signed-off-by: Laszlo Ersek <lersek at redhat.com>
---
lib/test-fork-safe-execvpe.sh | 28 +++++++++++++-------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/lib/test-fork-safe-execvpe.sh b/lib/test-fork-safe-execvpe.sh
index 5d2671946c66..f055f7b05814 100755
--- a/lib/test-fork-safe-execvpe.sh
+++ b/lib/test-fork-safe-execvpe.sh
@@ -32,42 +32,52 @@ execvpe=$(realpath -- "$dname/$bname")
# If $1 is "_", then the $execvpe helper binary is invoked with PATH
unset.
# Otherwise, the binary is invoked with PATH set to $1.
#
-# $2 and onward are passed to $execvpe; note that $2 becomes *both*
-# "program-to-exec" for the helper *and* argv[0] for the program
executed by the
-# helper.
+# $2 and onward are passed to $execvpe; $2 becomes "program-to-exec"
for the
+# helper and $3 becomes argv[0] for the program executed by the helper.
#
# The command itself (including the PATH setting) is written to "cmd"
(for error
# reporting purposes only); the standard output and error are saved in
"out" and
# "err" respectively; the exit status is written to
"status". This function
# should never fail; if it does, then that's a bug in this unit test
script, or
# the disk is full etc.
-run()
+run0()
{
local pathctl=$1
- local program=$2
local exit_status
shift 1
if test _ = "$pathctl"; then
- printf 'unset PATH; %s %s %s\n' "$execvpe"
"$program" "$*" >cmd
+ printf 'unset PATH; %s %s\n' "$execvpe"
"$*" >cmd
set +e
(
unset PATH
- "$execvpe" "$program" "$@" >out
2>err
+ "$execvpe" "$@" >out 2>err
)
exit_status=$?
set -e
else
- printf 'PATH=%s %s %s %s\n' "$pathctl"
"$execvpe" "$program" "$*" >cmd
+ printf 'PATH=%s %s %s\n' "$pathctl"
"$execvpe" "$*" >cmd
set +e
- PATH=$pathctl "$execvpe" "$program" "$@"
>out 2>err
+ PATH=$pathctl "$execvpe" "$@" >out 2>err
exit_status=$?
set -e
fi
printf '%d\n' $exit_status >status
}
+# Does the same as "run0", but $2 becomes *both*
"program-to-exec" for the the
+# $execvpe helper binary *and* argv[0] for the program executed by the helper.
+run()
+{
+ local pathctl=$1
+ local program=$2
+
+ shift 1
+
+ run0 "$pathctl" "$program" "$@"
+}
+
# After "run" returns, the following three functions can verify the
result.
#
# Check if the helper binary failed in nbd_internal_execvpe_init().
Laszlo Ersek
2023-Mar-22 16:53 UTC
[Libguestfs] [libnbd PATCH 2/3] lib/test-fork-safe-execvpe.sh: cope with Alpine Linux / BusyBox limitations
Whenever we expect our "bin/f" and "sh/f" files to execute (and to succeed), provide "expr" and "sh" as argv[0], respectively. This is to work around BusyBox, where the central busybox binary selects its behavior based on argv[0]. See e.g. <https://bugs.busybox.net/show_bug.cgi?id=15481>. Also cope with "realpath" (from BusyBox) not accepting the "--" end-of-options argument separator. See <https://bugs.busybox.net/show_bug.cgi?id=15466>. This patch is worth viewing with "git show --color-words" as well. Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- lib/test-fork-safe-execvpe.sh | 35 +++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/test-fork-safe-execvpe.sh b/lib/test-fork-safe-execvpe.sh index f055f7b05814..0e2dd942c9b7 100755 --- a/lib/test-fork-safe-execvpe.sh +++ b/lib/test-fork-safe-execvpe.sh @@ -24,7 +24,11 @@ set -e # utility is not in POSIX, but Linux, FreeBSD and OpenBSD all have it. bname=$(basename -- "$0" .sh) dname=$(dirname -- "$0") -execvpe=$(realpath -- "$dname/$bname") +if ! execvpe=$(realpath -- "$dname/$bname"); then + # Work around <https://bugs.busybox.net/show_bug.cgi?id=15466>. For example, + # Alpine Linux in the libnbd CI uses BusyBox. + execvpe=$(realpath "$dname/$bname") +fi # This is an elaborate way to control the PATH variable around the $execvpe # helper binary as narrowly as possible. @@ -35,6 +39,13 @@ execvpe=$(realpath -- "$dname/$bname") # $2 and onward are passed to $execvpe; $2 becomes "program-to-exec" for the # helper and $3 becomes argv[0] for the program executed by the helper. # +# (Outside of the "run" function below, "run0" should only ever be called for +# working around BusyBox. (Alpine Linux in the libnbd CI uses BusyBox.) +# BusyBox's utilities "expr", "sh" etc. are just symlinks to the central +# "busybox" binary executable, and that executable keys its behavior off the +# name under which it is invoked -- that is, $3 here. See +# <https://bugs.busybox.net/show_bug.cgi?id=15481>.) +# # The command itself (including the PATH setting) is written to "cmd" (for error # reporting purposes only); the standard output and error are saved in "out" and # "err" respectively; the exit status is written to "status". This function @@ -218,7 +229,7 @@ run "" nxregf/f/; execve_fail nxregf/f/ ENOTDIR run "" symlink/f; execve_fail symlink/f ELOOP # This runs "expr 1 + 1". -run "" bin/f 1 + 1; success bin/f,2 +run0 "" bin/f expr 1 + 1; success bin/f,2 # This triggers the ENOEXEC branch in nbd_internal_fork_safe_execvpe(). # nbd_internal_fork_safe_execvpe() will first try @@ -231,7 +242,7 @@ run "" bin/f 1 + 1; success bin/f,2 # # The shell script will get "sh/f" for $0 and "arg1" for $1, and print those # out. -run "" sh/f arg1; success sh/f,"sh/f arg1" +run0 "" sh/f sh arg1; success sh/f,"sh/f arg1" # In the tests below, the "file" parameter of execvpe() will not contain a # <slash> character. @@ -267,21 +278,21 @@ execve_fail empty/f,fifo/f,subdir/f,nxregf/f,symlink/f ELOOP # seen), and (b) that nbd_internal_fork_safe_execvpe() succeeds for the *last* # candidate. Repeat the test with "expr" (called "f" under "bin") and the shell # script (called "f" under "sh", triggering the ENOEXEC branch). -run bin f 1 + 1; success bin/f,2 -run sh f arg1; success sh/f,"sh/f arg1" +run0 bin f expr 1 + 1; success bin/f,2 +run0 sh f sh arg1; success sh/f,"sh/f arg1" # Demonstrate that the order of candidates matters. The first invocation finds # "expr" (called "f" under "bin"), the second invocation finds the shell script # under "sh" (triggering the ENOEXEC branch). -run empty:bin:sh f 1 + 1; success empty/f,bin/f,sh/f,2 -run empty:sh:bin f arg1; success empty/f,sh/f,bin/f,"sh/f arg1" +run0 empty:bin:sh f expr 1 + 1; success empty/f,bin/f,sh/f,2 +run0 empty:sh:bin f sh arg1; success empty/f,sh/f,bin/f,"sh/f arg1" # Check the expansion of zero-length prefixes in PATH to ".", plus the # (non-)insertion of the "/" separator. -run a/: f; execve_fail a/f,./f ENOENT -run :a/ f; execve_fail ./f,a/f ENOENT -run : f; execve_fail ./f,./f ENOENT +run a/: f; execve_fail a/f,./f ENOENT +run :a/ f; execve_fail ./f,a/f ENOENT +run : f; execve_fail ./f,./f ENOENT pushd bin -run : f 1 + 1; success ./f,./f,2 +run0 : f expr 1 + 1; success ./f,./f,2 popd -run :a/:::b/: f; execve_fail ./f,a/f,./f,./f,b/f,./f ENOENT +run :a/:::b/: f; execve_fail ./f,a/f,./f,./f,b/f,./f ENOENT
Laszlo Ersek
2023-Mar-22 16:53 UTC
[Libguestfs] [libnbd PATCH 3/3] Revert "ci: skip "lib/test-fork-safe-execvpe.sh" on Alpine Linux"
This reverts commit f5a065aa3a9cc71854d5f6143a6c4e0c6717cf28. "lib/test-fork-safe-execvpe.sh" now works around Alpine Linux / BusyBox limitations; reenable the test in the Alpine Linux containers. Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- ci/skipped_tests | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ci/skipped_tests b/ci/skipped_tests index 97158c0a17c2..0614a5c12201 100644 --- a/ci/skipped_tests +++ b/ci/skipped_tests @@ -6,13 +6,3 @@ # CentOS (stream) 8 probably has an older, buggy version of nbdkit and is not updated ^CentOS .*8$;info/info-uri.sh info/info-list-uris.sh interop/list-exports-nbdkit - -# Alpine Linux provides the "expr" utility (under pathname "/usr/bin/expr") in -# one of two forms: (1) as a symlink to the "/bin/busybox" binary executable, -# when the "coreutils" package is not installed, (2) as a symlink to the -# "coreutils" binary executable, otherwise. Both linked-to binary executables -# key their behavior off the name under which they are invoked (that is, argv0). -# Unfortunately, this breaks "lib/test-fork-safe-execvpe.sh": that test case -# copies the "expr" utility to a file called "bin/f", and actually expects -# "bin/f" to work. Both "busybox" and "coreutils" croak when invoked as "f". -^Alpine Linux-.*$;lib/test-fork-safe-execvpe.sh
Apparently Analagous Threads
- [libnbd PATCH v4 0/2] lib/utils: introduce async-signal-safe execvpe()
- [libnbd PATCH v4 0/2] lib/utils: introduce async-signal-safe execvpe()
- [libnbd PATCH v4 0/2] lib/utils: introduce async-signal-safe execvpe()
- [libnbd PATCH v4 0/2] lib/utils: introduce async-signal-safe execvpe()
- [libnbd PATCH v4 0/2] lib/utils: introduce async-signal-safe execvpe()