Summary: | system() returns wrong errors when posix_spawn fails | ||
---|---|---|---|
Product: | glibc | Reporter: | pokogiv215 |
Component: | libc | Assignee: | Adhemerval Zanella <adhemerval.zanella> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | adhemerval.zanella, drepper.fsp |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | 2.30 | ||
Target Milestone: | 2.32 | ||
Host: | Target: | ||
Build: | Last reconfirmed: | 2020-03-23 00:00:00 |
Description
pokogiv215
2020-03-23 13:48:17 UTC
(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 The master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f09542c584b121da0322fde4b55306d512b85d93 commit f09542c584b121da0322fde4b55306d512b85d93 Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> 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 <carlos@redhat.com> Fixed on 2.32. The release/2.30/master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9cd774568999873bec34b3db228c2ee914692dbd commit 9cd774568999873bec34b3db228c2ee914692dbd Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> 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 <carlos@redhat.com> (cherry picked from commit f09542c584b121da0322fde4b55306d512b85d93) The release/2.31/master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=46bbbd4622351528ae22c2d3397ab090f5099e82 commit 46bbbd4622351528ae22c2d3397ab090f5099e82 Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> 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 <carlos@redhat.com> (cheery picked from commit f09542c584b121da0322fde4b55306d512b85d93) |