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
--
BR,
Muhammad Usama Anjum
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
--
Kees Cook
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
>
--
BR,
Muhammad Usama Anjum
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
--
Kees Cook
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
>
--
BR,
Muhammad Usama Anjum
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...
--
Kees Cook
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...
--
Kees Cook
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.
>
--
BR,
Muhammad Usama Anjum