From a7ac20d9130556f286c0bd692bf5d0473c2daf37 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 18 Feb 2025 10:21:13 +0100 Subject: [PATCH] oci: report empty exec path as ENOENT unify the error codes returned by runc and crun. Fix the tests to work with both runtimes, as well as the https://github.com/containers/crun/pull/1672 changes in progress for crun. Follow-up for https://github.com/containers/podman/pull/25340 Closes: https://issues.redhat.com/browse/RHEL-85826 Signed-off-by: Giuseppe Scrivano (cherry picked from commit 4695564730abf8432102f8a07546afc9f87f855b) --- libpod/oci_util.go | 2 +- test/e2e/exec_test.go | 9 +++------ test/e2e/run_entrypoint_test.go | 7 ++++++- test/e2e/run_exit_test.go | 6 ++++-- test/system/030-run.bats | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libpod/oci_util.go b/libpod/oci_util.go index 5d30c8b8f7..292f59a117 100644 --- a/libpod/oci_util.go +++ b/libpod/oci_util.go @@ -152,7 +152,7 @@ func getOCIRuntimeError(name, runtimeMsg string) error { } return fmt.Errorf("%s: %s: %w", name, strings.Trim(errStr, "\n"), define.ErrOCIRuntimePermissionDenied) } - if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*").FindString(runtimeMsg); match != "" { + if match := regexp.MustCompile("(?i).*executable file not found in.*|.*no such file or directory.*|.*open executable.*").FindString(runtimeMsg); match != "" { errStr := match if includeFullOutput { errStr = runtimeMsg diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 8ab0d363b3..6c3acc4864 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -400,17 +400,14 @@ var _ = Describe("Podman exec", func() { setup.WaitWithDefaultTimeout() Expect(setup).Should(ExitCleanly()) - expect := "chdir to `/missing`: No such file or directory" - if podmanTest.OCIRuntime == "runc" { - expect = "chdir to cwd" - } + expect := ".*(chdir to cwd|chdir to `/missing`: No such file or directory).*" session := podmanTest.Podman([]string{"exec", "--workdir", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError(127, expect)) + Expect(session).To(ExitWithErrorRegex(127, expect)) session = podmanTest.Podman([]string{"exec", "-w", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError(127, expect)) + Expect(session).To(ExitWithErrorRegex(127, expect)) }) It("podman exec cannot be invoked", func() { diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index db7fbfec24..d4f8363bb6 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -18,7 +18,12 @@ CMD [] podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false") session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"}) session.WaitWithDefaultTimeout() - Expect(session).Should(ExitWithErrorRegex(126, ".*(open executable|executable path is empty): Operation not permitted: OCI permission denied.*")) + if session.ExitCode() == 126 { + // special case for crun <= 1.20, remove once a new version is out + Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied")) + return + } + Expect(session).Should(ExitWithErrorRegex(127, ".*(executable file not found in \\$PATH|cannot find `` in \\$PATH).*: OCI runtime attempted to invoke a command that was not found.*")) }) It("podman run entrypoint == [\"\"]", func() { diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index 900f2a21d5..618059b133 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -22,13 +22,15 @@ var _ = Describe("Podman run exit", func() { It("podman run exit ExecErrorCodeCannotInvoke", func() { result := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) result.WaitWithDefaultTimeout() - Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*")) + expected := ".*(exec: \"/etc\": is a directory|(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied).*" + Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, expected)) }) It("podman run exit ExecErrorCodeNotFound", func() { result := podmanTest.Podman([]string{"run", ALPINE, "foobar"}) result.WaitWithDefaultTimeout() - Expect(result).Should(ExitWithError(define.ExecErrorCodeNotFound, "executable file `foobar` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found")) + expected := ".*(executable file not found in \\$PATH|executable file `foobar` not found in \\$PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found).*" + Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeNotFound, expected)) }) It("podman run exit 0", func() { diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 1adb73ca3f..ee430d4b4c 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -1657,7 +1657,7 @@ search | $IMAGE | # runc and crun emit different diagnostics runtime=$(podman_runtime) case "$runtime" in - crun) expect='\(executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found\|executable path is empty\)' ;; + crun) expect='\(executable file `` not found in $PATH\|cannot find `` in $PATH\): No such file or directory: OCI runtime attempted to invoke a command that was not found' ;; runc) expect='runc: runc create failed: unable to start container process: exec: "": executable file not found in $PATH: OCI runtime attempted to invoke a command that was not found' ;; *) skip "Unknown runtime '$runtime'" ;; esac