[Bug libc/25715] New: system() returns wrong errors when posix_spawn fails

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] New: system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

            Bug ID: 25715
           Summary: system() returns wrong errors when posix_spawn fails
           Product: glibc
           Version: 2.30
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libc
          Assignee: unassigned at sourceware dot org
          Reporter: pokogiv215 at sweatmail dot com
                CC: drepper.fsp at gmail dot com
  Target Milestone: ---

On linux, I observe a call to system() claiming it's killed by sigbus when
really the underlying execv failed with E2BIG. See reproduction in [1].

What I expected to see is system() returning with exit code 127, as per `man
system`:
       *  If a shell could not be executed in the child process, then the
return value is as though the child shell terminated by calling _exit(2) with
the status 127.

Less important, but what I also expected is for posix_spawn to return 0 in this
case and to fill in the pid, but instead it returns E2BIG and doesn't fill in
the pid, which is not the behavior described by posix_spawn's man page:
       The posix_spawn() and posix_spawnp() functions fail only in the case
where the underlying fork(2) or vfork(2) call fails;  in these cases, these
functions return an error number,  which  will
       be one of the errors described for fork(2) or vfork(2).

The bad return value from system() was introduced in
5fb7fc96350575c9adb1316833e48ca11553be49, which returns posix_spawn's result
(an errno) from system (which returns a wait status).

The posix_spawn handling of errors in the child seems to have changed
unintentionally in 4b4d4056bb154603f36c6f8845757c1012758158 (because ec didn't
use to be set).


[1]

$ cat a.c
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <spawn.h>

int main(int argc, char* argv[], char** env) {
  char cmd[150000];
  memset(cmd, 'a', sizeof(cmd));
  cmd[sizeof(cmd) - 1] = 0;
  int ret = posix_spawn(NULL, "/bin/sh", 0, NULL,
                        (char *[]){"sh", "-c", (char *)cmd, 0}, env);
  printf("posix_spawn returns: %d = %s\n", ret, strerror(ret));
  int wstatus = system(cmd);
  if (WIFEXITED(wstatus)) {
    printf("exited, status=%d\n", WEXITSTATUS(wstatus));
  } else if (WIFSIGNALED(wstatus)) {
    printf("killed by signal %d = %s\n", WTERMSIG(wstatus),
strsignal(WTERMSIG(wstatus)));
  } else if (WIFSTOPPED(wstatus)) {
    printf("stopped by signal %d\n", WSTOPSIG(wstatus));
  } else if (WIFCONTINUED(wstatus)) {
    printf("continued\n");
  }
  return 0;
}
$ gcc a.c && ./a.out
posix_spawn returns: 7 = Argument list too long
killed by signal 7 = Bus error

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

Adhemerval Zanella <adhemerval.zanella at linaro dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
                 CC|                            |adhemerval.zanella at linaro dot o
                   |                            |rg
             Status|UNCONFIRMED                 |NEW
   Target Milestone|---                         |2.32
   Last reconfirmed|                            |2020-03-23
           Assignee|unassigned at sourceware dot org   |adhemerval.zanella at linaro dot o
                   |                            |rg

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
In reply to this post by Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

--- Comment #1 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
(In reply to pokogiv215 from comment #0)
> On linux, I observe a call to system() claiming it's killed by sigbus when
> really the underlying execv failed with E2BIG. See reproduction in [1].
>
> What I expected to see is system() returning with exit code 127, as per `man
> system`:
>        *  If a shell could not be executed in the child process, then the
> return value is as though the child shell terminated by calling _exit(2)
> with the status 127.

Yes, this is an issue introduced by 5fb7fc9635057. I am currently preparing a
patch to fix it.

>
> Less important, but what I also expected is for posix_spawn to return 0 in
> this case and to fill in the pid, but instead it returns E2BIG and doesn't
> fill in the pid, which is not the behavior described by posix_spawn's man
> page:
>        The posix_spawn() and posix_spawnp() functions fail only in the case
> where the underlying fork(2) or vfork(2) call fails;  in these cases, these
> functions return an error number,  which  will
>        be one of the errors described for fork(2) or vfork(2).

POSIX [1] and man-pages (which is not the canonical documentation of glibc) [2]
documents that if there is an error before or during the fork(2) (which in
glibc
Linux implementation of posix_spawn is done by a clone call with CLONE_VFORK),
then no child  is created, the contents of *pid are unspecified, and these
functions return an error number. And this is what is happening since what is
throwing the error is the execve syscall (using your example):

  $ strace -f ./elf/ld-linux-x86-64.so.2 [...] ./bz25715
  [...]
  [pid 16313] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
  pid 16313] execve("/bin/sh", ["sh", "-c",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...], 0x7ffcf2800f60 /* 78 vars */) = -1
E2BIG (Argument list too long)
  [pid 16313] exit_group(127)             = ?
  [pid 16311] <... clone resumed> child_stack=0x7f35d0eb1ff0,
flags=CLONE_VM|CLONE_VFORK|SIGCHLD) = 16313
  [pid 16313] +++ exited with 127 +++

Returning anything different than an error, in this case, does not make sense.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html

>
> The bad return value from system() was introduced in
> 5fb7fc96350575c9adb1316833e48ca11553be49, which returns posix_spawn's result
> (an errno) from system (which returns a wait status).
>
> The posix_spawn handling of errors in the child seems to have changed
> unintentionally in 4b4d4056bb154603f36c6f8845757c1012758158 (because ec
> didn't use to be set).
>
>
> [1]
>
> $ cat a.c
> #include <stdio.h>
> #include <string.h>
> #include <signal.h>
> #include <stdlib.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <spawn.h>
>
> int main(int argc, char* argv[], char** env) {
>   char cmd[150000];
>   memset(cmd, 'a', sizeof(cmd));
>   cmd[sizeof(cmd) - 1] = 0;
>   int ret = posix_spawn(NULL, "/bin/sh", 0, NULL,
> (char *[]){"sh", "-c", (char *)cmd, 0}, env);
>   printf("posix_spawn returns: %d = %s\n", ret, strerror(ret));
>   int wstatus = system(cmd);
>   if (WIFEXITED(wstatus)) {
>     printf("exited, status=%d\n", WEXITSTATUS(wstatus));
>   } else if (WIFSIGNALED(wstatus)) {
>     printf("killed by signal %d = %s\n", WTERMSIG(wstatus),
> strsignal(WTERMSIG(wstatus)));
>   } else if (WIFSTOPPED(wstatus)) {
>     printf("stopped by signal %d\n", WSTOPSIG(wstatus));
>   } else if (WIFCONTINUED(wstatus)) {
>     printf("continued\n");
>   }
>   return 0;
> }
> $ gcc a.c && ./a.out
> posix_spawn returns: 7 = Argument list too long
> killed by signal 7 = Bus error

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
In reply to this post by Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

--- Comment #2 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f09542c584b121da0322fde4b55306d512b85d93

commit f09542c584b121da0322fde4b55306d512b85d93
Author: Adhemerval Zanella <[hidden email]>
Date:   Mon Mar 23 15:23:20 2020 -0300

    posix: Fix system error return value [BZ #25715]

    It fixes 5fb7fc9635 when posix_spawn fails.

    Checked on x86_64-linux-gnu and i686-linux-gnu.

    Reviewed-by: Carlos O'Donell <[hidden email]>

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
In reply to this post by Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

Adhemerval Zanella <adhemerval.zanella at linaro dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #3 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
Fixed on 2.32.

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
In reply to this post by Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

--- Comment #4 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.30/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9cd774568999873bec34b3db228c2ee914692dbd

commit 9cd774568999873bec34b3db228c2ee914692dbd
Author: Adhemerval Zanella <[hidden email]>
Date:   Mon Mar 23 15:23:20 2020 -0300

    posix: Fix system error return value [BZ #25715]

    It fixes 5fb7fc9635 when posix_spawn fails.

    Checked on x86_64-linux-gnu and i686-linux-gnu.

    Reviewed-by: Carlos O'Donell <[hidden email]>

    (cherry picked from commit f09542c584b121da0322fde4b55306d512b85d93)

--
You are receiving this mail because:
You are on the CC list for the bug.
Reply | Threaded
Open this post in threaded view
|

[Bug libc/25715] system() returns wrong errors when posix_spawn fails

Sourceware - glibc-bugs mailing list
In reply to this post by Sourceware - glibc-bugs mailing list
https://sourceware.org/bugzilla/show_bug.cgi?id=25715

--- Comment #5 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The release/2.31/master branch has been updated by Adhemerval Zanella
<[hidden email]>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=46bbbd4622351528ae22c2d3397ab090f5099e82

commit 46bbbd4622351528ae22c2d3397ab090f5099e82
Author: Adhemerval Zanella <[hidden email]>
Date:   Mon Mar 23 15:23:20 2020 -0300

    posix: Fix system error return value [BZ #25715]

    It fixes 5fb7fc9635 when posix_spawn fails.

    Checked on x86_64-linux-gnu and i686-linux-gnu.

    Reviewed-by: Carlos O'Donell <[hidden email]>

    (cheery picked from commit f09542c584b121da0322fde4b55306d512b85d93)

--
You are receiving this mail because:
You are on the CC list for the bug.