The reproducer below uses time namespaces to easily trigger clone() failure (requires Linux >= 5.6). $ cat test.c #include <stdio.h> #include <spawn.h> #include <stdio.h> #include <string.h> #include <spawn.h> int main(int argc, char *argv[], char *envp[]) { if (argc <= 1) return 1; int err = posix_spawn(0, argv[1], 0, 0, argv + 1, envp); if (err) { printf("posix_spawn: %d (%s)\n", err, strerror(err)); return 127; } return 0; } $ gcc test.c $ strace -e clone,clone3 unshare -UrT ./a.out /bin/true clone3({flags=CLONE_VM|CLONE_VFORK, exit_signal=SIGCHLD, stack=0x7f322965f000, stack_size=0x9000}, 88) = -1 EINVAL (Invalid argument) posix_spawn: 1 (Operation not permitted) +++ exited with 127 +++ The bug is that while __clone_internal() reports errors via errno, __spawnix() treats it as a raw syscall[1], simply negating its return value (which is always -1 on error). [1] https://sourceware.org/git?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/spawni.c;h=d703485e3fb898dc65986d3e1cd9c1e7b8593abe;hb=glibc-2.35#l412
I think the best option here is to make __clone_internal not change errno and just return the error as negative errno.
> I think the best option here is to make __clone_internal not change errno and just return the error as negative errno. FWIW, all current code in glibc seems to use __clone_internal as a typical C function, i.e. expecting it return -1 and set errno on error. It's not clear to me why changing that would be the best option (compared to just fixing posix_spawn() to use errno instead of negating the return value).
Yes(In reply to Alexey Izbyshev from comment #2) > > I think the best option here is to make __clone_internal not change errno and just return the error as negative errno. > > FWIW, all current code in glibc seems to use __clone_internal as a typical C > function, i.e. expecting it return -1 and set errno on error. It's not clear > to me why changing that would be the best option (compared to just fixing > posix_spawn() to use errno instead of negating the return value). The only another usage is on pthread_create, but just using errno seems the simplest solution indeed.
Fixed on 2.36.
The release/2.35/master branch has been updated by Adhemerval Zanella <azanella@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=bbb017a2bb2983de297f3d443c59221fbff92e30 commit bbb017a2bb2983de297f3d443c59221fbff92e30 Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> Date: Fri May 6 11:34:18 2022 -0300 NEWS: Add a bug fix entry for BZ #29109