Hello,
I've been running execveat (execveat.c) locally on v6.1 and next-20240228. It has flaky test case. There are some test cases which fail consistently. The comment (not very clear) on top of failing cases is as following:
/* * Execute as a long pathname relative to "/". If this is a script, * the interpreter will launch but fail to open the script because its * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. * * The failure code is usually 127 (POSIX: "If a command is not found, * the exit status shall be 127."), but some systems give 126 (POSIX: * "If the command name is found, but it is not an executable utility, * the exit status shall be 126."), so allow either. */ The file name is just less than PATH_MAX (4096) and we are expecting the execveat() to fail with particular 99 or 127/128 error code. But kernel is returning 1 error code. Snippet from full output:
# child 3493092 exited with 1 not 99 nor 99 # child 3493094 exited with 1 not 127 nor 126
I'm not sure if test is wrong or the kernel has changed the return error codes.
Full test run output: ./execveat TAP version 13 1..51 ok 1 Check success of execveat(3, '../execveat', 0)... ok 2 Check success of execveat(5, 'execveat', 0)... ok 3 Check success of execveat(7, 'execveat', 0)... ok 4 Check success of execveat(-100, '/home/usama/repos/ke...ftests/exec/execveat', 0)... ok 5 Check success of execveat(99, '/home/usama/repos/ke...ftests/exec/execveat', 0)... ok 6 Check success of execveat(9, '', 4096)... ok 7 Check success of execveat(18, '', 4096)... ok 8 Check success of execveat(10, '', 4096)... ok 9 Check success of execveat(15, '', 4096)... ok 10 Check success of execveat(15, '', 4096)... ok 11 Check success of execveat(16, '', 4096)... ok 12 Check failure of execveat(9, '', 0) with ENOENT ok 13 Check failure of execveat(9, '(null)', 4096) with EFAULT ok 14 Check success of execveat(5, 'execveat.symlink', 0)... ok 15 Check success of execveat(7, 'execveat.symlink', 0)... ok 16 Check success of execveat(-100, '/home/usama/repos/ke...xec/execveat.symlink', 0)... ok 17 Check success of execveat(11, '', 4096)... ok 18 Check success of execveat(11, '', 4352)... ok 19 Check failure of execveat(5, 'execveat.symlink', 256) with ELOOP ok 20 Check failure of execveat(7, 'execveat.symlink', 256) with ELOOP ok 21 Check failure of execveat(-100, '/home/usama/repos/kernel/linux_mainline/tools/testing/selftests/exec/execveat.symlink', 256) with ELOOP ok 22 Check failure of execveat(5, 'pipe', 0) with EACCES ok 23 Check success of execveat(3, '../script', 0)... ok 24 Check success of execveat(5, 'script', 0)... ok 25 Check success of execveat(7, 'script', 0)... ok 26 Check success of execveat(-100, '/home/usama/repos/ke...elftests/exec/script', 0)... ok 27 Check success of execveat(14, '', 4096)... ok 28 Check success of execveat(14, '', 4352)... ok 29 Check failure of execveat(19, '', 4096) with ENOENT ok 30 Check failure of execveat(8, 'script', 0) with ENOENT ok 31 Check success of execveat(17, '', 4096)... ok 32 Check success of execveat(17, '', 4096)... ok 33 Check success of execveat(4, '../script', 0)... ok 34 Check success of execveat(4, 'script', 0)... ok 35 Check success of execveat(4, '../script', 0)... ok 36 Check failure of execveat(4, 'script', 0) with ENOENT ok 37 Check failure of execveat(5, 'execveat', 65535) with EINVAL ok 38 Check failure of execveat(5, 'no-such-file', 0) with ENOENT ok 39 Check failure of execveat(7, 'no-such-file', 0) with ENOENT ok 40 Check failure of execveat(-100, 'no-such-file', 0) with ENOENT ok 41 Check failure of execveat(5, '', 4096) with EACCES ok 42 Check failure of execveat(5, 'Makefile', 0) with EACCES ok 43 Check failure of execveat(12, '', 4096) with EACCES ok 44 Check failure of execveat(13, '', 4096) with EACCES ok 45 Check failure of execveat(99, '', 4096) with EBADF ok 46 Check failure of execveat(99, 'execveat', 0) with EBADF ok 47 Check failure of execveat(9, 'execveat', 0) with ENOTDIR # Invoke copy of 'execveat' via filename of length 4094: ok 48 Check success of execveat(20, '', 4096)... # execveat() failed, rc=-1 errno=2 (No such file or directory) not ok 49 Check success of execveat(6, 'home/usama/repos/ker...yyyyyyyyyyyyyyyyyyyy', 0)... # child 3493092 exited with 1 not 99 nor 99 not ok 49 Check success of execveat(6, 'home/usama/repos/ker...yyyyyyyyyyyyyyyyyyyy', 0)... # Invoke copy of 'script' via filename of length 4094: ok 50 Check success of execveat(21, '', 4096)... # execveat() failed, rc=-1 errno=2 (No such file or directory) not ok 51 Check success of execveat(6, 'home/usama/repos/ker...yyyyyyyyyyyyyyyyyyyy', 0)... # child 3493094 exited with 1 not 127 nor 126 not ok 51 Check success of execveat(6, 'home/usama/repos/ker...yyyyyyyyyyyyyyyyyyyy', 0)... 2 tests failed # Totals: pass:49 fail:2 xfail:0 xpass:0 skip:0 error:0
On Tue, Mar 05, 2024 at 07:20:27PM +0500, Muhammad Usama Anjum wrote:
Hello,
I've been running execveat (execveat.c) locally on v6.1 and next-20240228. It has flaky test case. There are some test cases which fail consistently. The comment (not very clear) on top of failing cases is as following:
/*
- Execute as a long pathname relative to "/". If this is a script,
- the interpreter will launch but fail to open the script because its
- name ("/dev/fd/5/xxx....") is bigger than PATH_MAX.
- The failure code is usually 127 (POSIX: "If a command is not found,
- the exit status shall be 127."), but some systems give 126 (POSIX:
- "If the command name is found, but it is not an executable utility,
- the exit status shall be 126."), so allow either.
*/ The file name is just less than PATH_MAX (4096) and we are expecting the execveat() to fail with particular 99 or 127/128 error code. But kernel is returning 1 error code. Snippet from full output:
# child 3493092 exited with 1 not 99 nor 99 # child 3493094 exited with 1 not 127 nor 126
I'm not sure if test is wrong or the kernel has changed the return error codes.
The error code is actually coming from the script interpreter (in this case, "/bin/sh"). On my system, /bin/sh is /bin/dash, and I see the failure. If I manually change "script" to use "#!/bin/bash", the test passes for me.
Since lots of other selftests appears to depend on /bin/bash, I think the right fix is simply:
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c index bf79d664c8e6..0546ca24f2b2 100644 --- a/tools/testing/selftests/exec/execveat.c +++ b/tools/testing/selftests/exec/execveat.c @@ -393,7 +393,7 @@ static int run_tests(void) static void prerequisites(void) { int fd; - const char *script = "#!/bin/sh\nexit $*\n"; + const char *script = "#!/bin/bash\nexit $*\n";
/* Create ephemeral copies of files */ exe_cp("execveat", "execveat.ephemeral");
Can you test this and let me know if this fixes it for you?
Thanks for the report!
-Kees
On 3/6/24 2:00 AM, Kees Cook wrote:
On Tue, Mar 05, 2024 at 07:20:27PM +0500, Muhammad Usama Anjum wrote:
Hello,
I've been running execveat (execveat.c) locally on v6.1 and next-20240228. It has flaky test case. There are some test cases which fail consistently. The comment (not very clear) on top of failing cases is as following:
/*
- Execute as a long pathname relative to "/". If this is a script,
- the interpreter will launch but fail to open the script because its
- name ("/dev/fd/5/xxx....") is bigger than PATH_MAX.
- The failure code is usually 127 (POSIX: "If a command is not found,
- the exit status shall be 127."), but some systems give 126 (POSIX:
- "If the command name is found, but it is not an executable utility,
- the exit status shall be 126."), so allow either.
*/ The file name is just less than PATH_MAX (4096) and we are expecting the execveat() to fail with particular 99 or 127/128 error code. But kernel is returning 1 error code. Snippet from full output:
# child 3493092 exited with 1 not 99 nor 99 # child 3493094 exited with 1 not 127 nor 126
I'm not sure if test is wrong or the kernel has changed the return error codes.
The error code is actually coming from the script interpreter (in this case, "/bin/sh"). On my system, /bin/sh is /bin/dash, and I see the failure. If I manually change "script" to use "#!/bin/bash", the test passes for me.
Since lots of other selftests appears to depend on /bin/bash, I think the right fix is simply:
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c index bf79d664c8e6..0546ca24f2b2 100644 --- a/tools/testing/selftests/exec/execveat.c +++ b/tools/testing/selftests/exec/execveat.c @@ -393,7 +393,7 @@ static int run_tests(void) static void prerequisites(void) { int fd;
- const char *script = "#!/bin/sh\nexit $*\n";
- const char *script = "#!/bin/bash\nexit $*\n";
/* Create ephemeral copies of files */ exe_cp("execveat", "execveat.ephemeral");
Can you test this and let me know if this fixes it for you?
I've tested this patch. Still getting same failures.
Thanks for the report!
-Kees
On Thu, Mar 07, 2024 at 02:22:27PM +0500, Muhammad Usama Anjum wrote:
I've tested this patch. Still getting same failures.
Okay, thanks for testing!
What environment are you testing under? It would seem like some unexpected userspace conditions exist that the test isn't prepared for. (I was able to reproduce one error with /bin/dash, for example, but not the others, so something must be different in the set up.)
-Kees
On 3/8/24 1:39 AM, Kees Cook wrote:
On Thu, Mar 07, 2024 at 02:22:27PM +0500, Muhammad Usama Anjum wrote:
I've tested this patch. Still getting same failures.
Okay, thanks for testing!
What environment are you testing under? It would seem like some unexpected userspace conditions exist that the test isn't prepared for. (I was able to reproduce one error with /bin/dash, for example, but not the others, so something must be different in the set up.)
I'm testing on Debian Bookworm with v6.1, v6.7 and next-20240304 kernels. I've tested it on another VM which is also Debian Bookworm. The default shell is dash on Debian as well.
-Kees
On Mon, Mar 11, 2024 at 10:08:36PM +0500, Muhammad Usama Anjum wrote:
On 3/8/24 1:39 AM, Kees Cook wrote:
On Thu, Mar 07, 2024 at 02:22:27PM +0500, Muhammad Usama Anjum wrote:
I've tested this patch. Still getting same failures.
Okay, thanks for testing!
What environment are you testing under? It would seem like some unexpected userspace conditions exist that the test isn't prepared for. (I was able to reproduce one error with /bin/dash, for example, but not the others, so something must be different in the set up.)
I'm testing on Debian Bookworm with v6.1, v6.7 and next-20240304 kernels. I've tested it on another VM which is also Debian Bookworm. The default shell is dash on Debian as well.
Thanks! Okay, I can reproduce these failures now under a Bookworm install. I'll keep investigating...
On Mon, Mar 11, 2024 at 10:08:36PM +0500, Muhammad Usama Anjum wrote:
On 3/8/24 1:39 AM, Kees Cook wrote:
On Thu, Mar 07, 2024 at 02:22:27PM +0500, Muhammad Usama Anjum wrote:
I've tested this patch. Still getting same failures.
Okay, thanks for testing!
What environment are you testing under? It would seem like some unexpected userspace conditions exist that the test isn't prepared for. (I was able to reproduce one error with /bin/dash, for example, but not the others, so something must be different in the set up.)
I'm testing on Debian Bookworm with v6.1, v6.7 and next-20240304 kernels. I've tested it on another VM which is also Debian Bookworm. The default shell is dash on Debian as well.
Do you know which kernel version this _passes_ on? I haven't been able to find when this actually returned the expected values...
On 3/14/24 8:05 AM, Kees Cook wrote:
On Mon, Mar 11, 2024 at 10:08:36PM +0500, Muhammad Usama Anjum wrote:
On 3/8/24 1:39 AM, Kees Cook wrote:
On Thu, Mar 07, 2024 at 02:22:27PM +0500, Muhammad Usama Anjum wrote:
I've tested this patch. Still getting same failures.
Okay, thanks for testing!
What environment are you testing under? It would seem like some unexpected userspace conditions exist that the test isn't prepared for. (I was able to reproduce one error with /bin/dash, for example, but not the others, so something must be different in the set up.)
I'm testing on Debian Bookworm with v6.1, v6.7 and next-20240304 kernels. I've tested it on another VM which is also Debian Bookworm. The default shell is dash on Debian as well.
Do you know which kernel version this _passes_ on? I haven't been able to find when this actually returned the expected values...
I'd tried to find a kernel on which it used to pass i.e., I rewinded the kernel to the last change in this test. But still it was failing on that. Not sure if the test is wrong or the environment is making the test to output wrong values.
linux-kselftest-mirror@lists.linaro.org