* [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
@ 2025-01-16 23:14 Askar Safin
2025-01-17 6:37 ` Rich Felker
0 siblings, 1 reply; 13+ messages in thread
From: Askar Safin @ 2025-01-16 23:14 UTC (permalink / raw)
To: musl
I found a bug both in glibc and musl.
If a process does posix_spawn+waitpid, then attempting to pause it using Ctrl-Z
sometimes doesn't work and, worse, makes the process unkillable by usual Ctrl-Z or Ctrl-C.
The bug is described in full in this glibc issue: https://sourceware.org/bugzilla/show_bug.cgi?id=32565 .
It is reproducible with musl on the same system I used to reproduce it with glibc (see the link).
I compiled the code using "x86_64-linux-musl-gcc" wrapper provided by Debian.
Please, CC me when replying.
Output of some commands:
# dpkg -l musl
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-============-============-=================================
ii musl:amd64 1.2.5-1.1 amd64 standard C library
# /lib/x86_64-linux-musl/libc.so
musl libc (x86_64)
Version 1.2.5
Dynamic Program Loader
Usage: /lib/x86_64-linux-musl/libc.so [options] [--] pathname [args]
--
Askar Safin
https://types.pl/@safinaskar
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-16 23:14 [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill Askar Safin
@ 2025-01-17 6:37 ` Rich Felker
2025-01-17 6:46 ` Rich Felker
2025-01-17 17:55 ` Askar Safin
0 siblings, 2 replies; 13+ messages in thread
From: Rich Felker @ 2025-01-17 6:37 UTC (permalink / raw)
To: Askar Safin; +Cc: musl
On Fri, Jan 17, 2025 at 03:14:03AM +0400, Askar Safin wrote:
> I found a bug both in glibc and musl.
>
> If a process does posix_spawn+waitpid, then attempting to pause it using Ctrl-Z
> sometimes doesn't work and, worse, makes the process unkillable by usual Ctrl-Z or Ctrl-C.
>
> The bug is described in full in this glibc issue: https://sourceware.org/bugzilla/show_bug.cgi?id=32565 .
>
> It is reproducible with musl on the same system I used to reproduce it with glibc (see the link).
>
> I compiled the code using "x86_64-linux-musl-gcc" wrapper provided by Debian.
>
> Please, CC me when replying.
OK, I think this should be fixable by, if SIGTSTP is to be SIG_DFL in
the spawned child, setting it to a no-op handler instead of SIG_DFL.
It might actually make sense to just do this for all signals.
Note that SIGSTOP, which is not blockable interceptible or ignorable,
can't be handled this way, but the pid has not yet leaked to anything
at this point, so the only way SIGSTOP can be generated is by a badly
behaved program signaling random pids, which is not a case that needs
to be handled gracefully.
In theory SIGTTIN and SIGTTOU might be hazards too, but I don't think
it's possible for a process to generate them without attempting to
perform io, which the pre-exec child doesn't do. Still handling them
might be a good safety measure in case I'm wrong.
I'll prepare one or more versions of a proposed patch.
Rich
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-17 6:37 ` Rich Felker
@ 2025-01-17 6:46 ` Rich Felker
2025-01-17 17:55 ` Askar Safin
1 sibling, 0 replies; 13+ messages in thread
From: Rich Felker @ 2025-01-17 6:46 UTC (permalink / raw)
To: Askar Safin; +Cc: musl
On Fri, Jan 17, 2025 at 01:37:09AM -0500, Rich Felker wrote:
> On Fri, Jan 17, 2025 at 03:14:03AM +0400, Askar Safin wrote:
> > I found a bug both in glibc and musl.
> >
> > If a process does posix_spawn+waitpid, then attempting to pause it using Ctrl-Z
> > sometimes doesn't work and, worse, makes the process unkillable by usual Ctrl-Z or Ctrl-C.
> >
> > The bug is described in full in this glibc issue: https://sourceware.org/bugzilla/show_bug.cgi?id=32565 .
> >
> > It is reproducible with musl on the same system I used to reproduce it with glibc (see the link).
> >
> > I compiled the code using "x86_64-linux-musl-gcc" wrapper provided by Debian.
> >
> > Please, CC me when replying.
>
> OK, I think this should be fixable by, if SIGTSTP is to be SIG_DFL in
> the spawned child, setting it to a no-op handler instead of SIG_DFL.
> It might actually make sense to just do this for all signals.
>
> Note that SIGSTOP, which is not blockable interceptible or ignorable,
> can't be handled this way, but the pid has not yet leaked to anything
> at this point, so the only way SIGSTOP can be generated is by a badly
> behaved program signaling random pids, which is not a case that needs
> to be handled gracefully.
>
> In theory SIGTTIN and SIGTTOU might be hazards too, but I don't think
> it's possible for a process to generate them without attempting to
> perform io, which the pre-exec child doesn't do. Still handling them
> might be a good safety measure in case I'm wrong.
>
> I'll prepare one or more versions of a proposed patch.
One complication I'll need to address: the pre-exec child does not
have enough stack to execute (even a no-op) signal handler. So the
parent is going to need to handle checking the runtime-variable min
signal stack and ensuring it provides enough. And the no-op signal
handler will need to be installed to run with all signals blocked so
that recursive signals can't overflow a limit that only suffices for
one signal.
With those changes I think this approach works.
I think applying it to all signals is probably a bad idea in that it
would introduce a lot more syscall cost at spawn time. Just doing the
signals we need (and probably omitting SITTTIN/TTOU unless there's
good reason to believe they can happen) seems like the smart approach
not to make the fix annoyingly costly to users.
Rich
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-17 6:37 ` Rich Felker
2025-01-17 6:46 ` Rich Felker
@ 2025-01-17 17:55 ` Askar Safin
2025-01-18 9:51 ` Florian Weimer
2025-01-18 11:17 ` Rich Felker
1 sibling, 2 replies; 13+ messages in thread
From: Askar Safin @ 2025-01-17 17:55 UTC (permalink / raw)
To: Rich Felker; +Cc: musl
Thanks a lot for answer!
---- On Fri, 17 Jan 2025 10:37:09 +0400 Rich Felker wrote ---
> Note that SIGSTOP, which is not blockable interceptible or ignorable,
> can't be handled this way, but the pid has not yet leaked to anything
> at this point, so the only way SIGSTOP can be generated is by a badly
> behaved program signaling random pids, which is not a case that needs
> to be handled gracefully.
But what if somebody sends SIGSTOP to whole process group using kill(2)?
The bug is not reproducible with fork. Maybe this is kernel bug and should be
forwarded there instead?
--
Askar Safin
https://types.pl/@safinaskar
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-17 17:55 ` Askar Safin
@ 2025-01-18 9:51 ` Florian Weimer
2025-01-18 10:23 ` Rich Felker
2025-01-18 11:17 ` Rich Felker
1 sibling, 1 reply; 13+ messages in thread
From: Florian Weimer @ 2025-01-18 9:51 UTC (permalink / raw)
To: Askar Safin; +Cc: Rich Felker, musl
* Askar Safin:
> Thanks a lot for answer!
>
> ---- On Fri, 17 Jan 2025 10:37:09 +0400 Rich Felker wrote ---
> > Note that SIGSTOP, which is not blockable interceptible or ignorable,
> > can't be handled this way, but the pid has not yet leaked to anything
> > at this point, so the only way SIGSTOP can be generated is by a badly
> > behaved program signaling random pids, which is not a case that needs
> > to be handled gracefully.
>
> But what if somebody sends SIGSTOP to whole process group using kill(2)?
I would expect that they send SIGCONT afterwards to the same process
group, to resume execution of all processes. Doesn't this avoid the
issue?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 9:51 ` Florian Weimer
@ 2025-01-18 10:23 ` Rich Felker
2025-01-18 11:13 ` Florian Weimer
0 siblings, 1 reply; 13+ messages in thread
From: Rich Felker @ 2025-01-18 10:23 UTC (permalink / raw)
To: Florian Weimer; +Cc: Askar Safin, musl
On Sat, Jan 18, 2025 at 10:51:01AM +0100, Florian Weimer wrote:
> * Askar Safin:
>
> > Thanks a lot for answer!
> >
> > ---- On Fri, 17 Jan 2025 10:37:09 +0400 Rich Felker wrote ---
> > > Note that SIGSTOP, which is not blockable interceptible or ignorable,
> > > can't be handled this way, but the pid has not yet leaked to anything
> > > at this point, so the only way SIGSTOP can be generated is by a badly
> > > behaved program signaling random pids, which is not a case that needs
> > > to be handled gracefully.
> >
> > But what if somebody sends SIGSTOP to whole process group using kill(2)?
>
> I would expect that they send SIGCONT afterwards to the same process
> group, to resume execution of all processes. Doesn't this avoid the
> issue?
I mean if you just want a heuristic fix.. I guess?
But certainly they could send SIGSTOP to the group then SIGCONT only
to the single known process.
Rich
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 10:23 ` Rich Felker
@ 2025-01-18 11:13 ` Florian Weimer
2025-01-18 20:58 ` Askar Safin
0 siblings, 1 reply; 13+ messages in thread
From: Florian Weimer @ 2025-01-18 11:13 UTC (permalink / raw)
To: Rich Felker; +Cc: musl, Askar Safin
* Rich Felker:
> On Sat, Jan 18, 2025 at 10:51:01AM +0100, Florian Weimer wrote:
>> * Askar Safin:
>>
>> > Thanks a lot for answer!
>> >
>> > ---- On Fri, 17 Jan 2025 10:37:09 +0400 Rich Felker wrote ---
>> > > Note that SIGSTOP, which is not blockable interceptible or ignorable,
>> > > can't be handled this way, but the pid has not yet leaked to anything
>> > > at this point, so the only way SIGSTOP can be generated is by a badly
>> > > behaved program signaling random pids, which is not a case that needs
>> > > to be handled gracefully.
>> >
>> > But what if somebody sends SIGSTOP to whole process group using kill(2)?
>>
>> I would expect that they send SIGCONT afterwards to the same process
>> group, to resume execution of all processes. Doesn't this avoid the
>> issue?
>
> I mean if you just want a heuristic fix.. I guess?
>
> But certainly they could send SIGSTOP to the group then SIGCONT only
> to the single known process.
It seems this may be the hard-to-kill scenario with SIGTSTP, too.
After the problematic ^Z, the desired signal is only delivered after
typing “fg” or equivalent in the shell, which triggers that SIGCONT.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-17 17:55 ` Askar Safin
2025-01-18 9:51 ` Florian Weimer
@ 2025-01-18 11:17 ` Rich Felker
2025-01-18 20:16 ` Markus Wichmann
` (2 more replies)
1 sibling, 3 replies; 13+ messages in thread
From: Rich Felker @ 2025-01-18 11:17 UTC (permalink / raw)
To: Askar Safin; +Cc: musl
On Fri, Jan 17, 2025 at 09:55:50PM +0400, Askar Safin wrote:
> Thanks a lot for answer!
>
> ---- On Fri, 17 Jan 2025 10:37:09 +0400 Rich Felker wrote ---
> > Note that SIGSTOP, which is not blockable interceptible or ignorable,
> > can't be handled this way, but the pid has not yet leaked to anything
> > at this point, so the only way SIGSTOP can be generated is by a badly
> > behaved program signaling random pids, which is not a case that needs
> > to be handled gracefully.
>
> But what if somebody sends SIGSTOP to whole process group using kill(2)?
>
> The bug is not reproducible with fork. Maybe this is kernel bug and should be
> forwarded there instead?
I don't understand what you think the kernel bug is. AFAICT it's
behaving exactly as it should. The spawn impl just isn't using the
kernel primitives exactly right.
Since SIGSTOP is an issue, I don't think my previous idea of using
no-op signal handlers makes sense. We'll have to handle an unblockable
stop situation anyway so might as well use the same for blockable
stops.
So, I think the parent, while waiting for the fd close event from the
child, also needs to watch for child status change to stopped, and if
this happens, send SIGCONT. This is unfortunately gratuitously
difficult, since we don't have a primitive to wait for
fd-activity-or-pid-activity short of depending on pidf (if this even
works; does pidfd poll readable for transition to stopped state?).
If there is a working pidfd approach, I guess we should use that, and
fallback to polling with short timeout and doing a waitpid/WNOHANG
between polls if pidfd isn't obtainable.
Rich
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 11:17 ` Rich Felker
@ 2025-01-18 20:16 ` Markus Wichmann
2025-01-19 3:18 ` Rich Felker
2025-01-18 20:52 ` Askar Safin
2025-01-22 21:45 ` Askar Safin
2 siblings, 1 reply; 13+ messages in thread
From: Markus Wichmann @ 2025-01-18 20:16 UTC (permalink / raw)
To: musl
Hi all,
here is my understanding of the bug first.
1. Foreground process calls posix_spawn without the POSIX_SPAWN_SETSID
or POSIX_SPAWN_SETPGROUP flags (either of those prevent the bug).
2. User presses terminal suspend character between the parent process
masking signals and the child process execing the target program.
3. Kernel sends SIGTSTP to foreground process group.
4. SIGTSTP is blocked in parent process, so parent process does not
stop. Parent process is blocked in trying to read the pipe to the child,
though.
5. Child process unblocks signals before calling exec(), thereby
unblocking SIGTSTP and stopping.
6. User has an issue mainly because parent process never acts on SIGTSTP
and stops (which is why the shell's wait() call never returns).
Looking at the ingredients of the problem, it seems that unblocking
signals before reading the pipe would be the simplest way out of this
pickle. We cannot avoid blocking signals before calling clone() to spawn
the child with blocked signals, and they cannot be unblocked in exec(),
because all exec() functions pass on the signal mask, but the parent
could read the pipe with unblocked signals.
The code for reading the pipe and waiting for the child process
obviously would need to account for the possibility of EINTR, and there
is a possibility the pipe FD would escape to fork-without-exec in a
signal handler. That could be helped with FD_CLOFORK emulation in libc,
though (keep track of CLOFORK FDs in an FD set and close them all in
_Fork()), since FD_CLOFORK is not in the kernel, sadly.
Or else you could tell applications that weird things happen if you fork
in a signal handler without execing (that's weird usage, anyway).
Ciao,
Markus
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 11:17 ` Rich Felker
2025-01-18 20:16 ` Markus Wichmann
@ 2025-01-18 20:52 ` Askar Safin
2025-01-22 21:45 ` Askar Safin
2 siblings, 0 replies; 13+ messages in thread
From: Askar Safin @ 2025-01-18 20:52 UTC (permalink / raw)
To: Rich Felker; +Cc: musl, fw
---- On Sat, 18 Jan 2025 15:17:02 +0400 Rich Felker wrote ---
> Since SIGSTOP is an issue, I don't think my previous idea of using
> no-op signal handlers makes sense. We'll have to handle an unblockable
> stop situation anyway so might as well use the same for blockable
> stops.
When I mentioned SIGSTOP, this was just thinking out loud. I. e. purely theoretical
concern. I didn't even test it. The original bug report was about Ctrl-Z, i. e. SIGTSTP.
--
Askar Safin
https://types.pl/@safinaskar
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 11:13 ` Florian Weimer
@ 2025-01-18 20:58 ` Askar Safin
0 siblings, 0 replies; 13+ messages in thread
From: Askar Safin @ 2025-01-18 20:58 UTC (permalink / raw)
To: Florian Weimer; +Cc: Rich Felker, musl
---- On Sat, 18 Jan 2025 15:13:57 +0400 Florian Weimer wrote ---
> It seems this may be the hard-to-kill scenario with SIGTSTP, too.
> After the problematic ^Z, the desired signal is only delivered after
> typing “fg” or equivalent in the shell, which triggers that SIGCONT.
I don't understand what you mean here. Original issue was so:
the user presses ^Z, then (from UI point of view) stopping doesn't
happen. I. e. bash prompt doesn't appear, and thus user cannot
enter "fg"
--
Askar Safin
https://types.pl/@safinaskar
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 20:16 ` Markus Wichmann
@ 2025-01-19 3:18 ` Rich Felker
0 siblings, 0 replies; 13+ messages in thread
From: Rich Felker @ 2025-01-19 3:18 UTC (permalink / raw)
To: Markus Wichmann; +Cc: musl
On Sat, Jan 18, 2025 at 09:16:58PM +0100, Markus Wichmann wrote:
> Hi all,
>
> here is my understanding of the bug first.
>
> 1. Foreground process calls posix_spawn without the POSIX_SPAWN_SETSID
> or POSIX_SPAWN_SETPGROUP flags (either of those prevent the bug).
> 2. User presses terminal suspend character between the parent process
> masking signals and the child process execing the target program.
> 3. Kernel sends SIGTSTP to foreground process group.
> 4. SIGTSTP is blocked in parent process, so parent process does not
> stop. Parent process is blocked in trying to read the pipe to the child,
> though.
> 5. Child process unblocks signals before calling exec(), thereby
> unblocking SIGTSTP and stopping.
> 6. User has an issue mainly because parent process never acts on SIGTSTP
> and stops (which is why the shell's wait() call never returns).
>
> Looking at the ingredients of the problem, it seems that unblocking
> signals before reading the pipe would be the simplest way out of this
> pickle. We cannot avoid blocking signals before calling clone() to spawn
> the child with blocked signals, and they cannot be unblocked in exec(),
> because all exec() functions pass on the signal mask, but the parent
> could read the pipe with unblocked signals.
I think this is a misunderstanding of the bug. My understanding is
that, due to signals sent from a controlling terminal or to a process
group, it's posssible for a process which logically does not exist yet
to enter a stopped state.
If the parent also stopped, most likely they would get resumed
together, but there is no requirement that this happen. In a worst
case, the child stop may be queued before the child changes to a new
process group; in that case, it's acted upon after the process group
has already changed (because that necessarily happens before signals
are unblocked), and sending SIGCONT to the parent process group (like
a shell would do) will not resume it.
This cannot happen in the case of a hard SIGSTOP though, only SIGTSTP.
So one could argue that my original fix for SIGTSTP suffices, if
you're willing to assume something sending hard SIGSTOP to a process
group will send the SIGCONT to the process group as well.
> The code for reading the pipe and waiting for the child process
> obviously would need to account for the possibility of EINTR, and there
> is a possibility the pipe FD would escape to fork-without-exec in a
> signal handler. That could be helped with FD_CLOFORK emulation in libc,
> though (keep track of CLOFORK FDs in an FD set and close them all in
> _Fork()), since FD_CLOFORK is not in the kernel, sadly.
This doesn't matter. It's always expected that libc-internal fds can
escape this way, and in this case it's completely harmless except for
the resource leak. If you _Fork from a signal handler you're in a
permanent AS context, and can't really do much except exec or _exit.
So the resource usage really doesn't matter. It does not block forward
progress of anything.
> Or else you could tell applications that weird things happen if you fork
> in a signal handler without execing (that's weird usage, anyway).
This is basically what the standard already does.
I'm not really convinced that unblocking signals in the parent is
relevant to fixing this bug, but it might be a better behavior, since
posix_spawn can block forward progress indefinitely if the child file
actions do stupid things like opening a file type that blocks in open.
While the implementation may of course block signals internally where
needed, generally this should follow the as-if rule whereby the
application can't see that they were blocked except by timing
differences. Blocking forward progress that can only occur by a signal
being handled seems like at least bad QoI if not nonconforming.
Rich
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill
2025-01-18 11:17 ` Rich Felker
2025-01-18 20:16 ` Markus Wichmann
2025-01-18 20:52 ` Askar Safin
@ 2025-01-22 21:45 ` Askar Safin
2 siblings, 0 replies; 13+ messages in thread
From: Askar Safin @ 2025-01-22 21:45 UTC (permalink / raw)
To: dalias; +Cc: musl, fw
---- On Sat, 18 Jan 2025 15:17:02 +0400 Rich Felker wrote ---
> I don't understand what you think the kernel bug is.
Recently I got a suggestion to use CLONE_VM on io-uring@vger.kernel.org
( https://lore.kernel.org/io-uring/9ee30fc7-0329-4a69-b686-3131ce323c97@gmail.com/ )
So I tried CLONE_VM and it worked! I. e. this Ctrl-Z bug was not reproduced.
Also I compared various methods for spawning. And my testing shows that all
methods based on vfork or CLONE_VFORK or posix_spawn (as well as I understand it
is based on vfork, too) are buggy, and all others are not.
For all methods I wrote in comments whether the bug is reproducible on glibc
and musl.
In the end of this letter you will find full source.
So it may be good idea to replace vfork with CLONE_VM in musl and glibc.
Also, my CLONE_VM-based implementation is essentially reimplementation of vfork, but
in userspace. And it works. I. e. actual kernel implementation of vfork doesn't work,
and its userspace emulation works. This is strong argument for point of view, that
vfork is buggy in kernel.
--
Askar Safin
https://types.pl/@safinaskar
Source:
#define _GNU_SOURCE
#include <spawn.h>
#include <err.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/wait.h>
char *args[] = {"/bin/true", NULL};
char *env[] = {"HOME=/", NULL};
// repro glibc
// repro musl
pid_t
spawn_via_posix_spawn (void)
{
pid_t pid;
if (posix_spawn (&pid, "/bin/true", NULL, NULL, args, env) != 0)
{
errx (1, "posix_spawn");
}
return pid;
}
// not repro glibc
// not repro musl
pid_t
spawn_via_fork (void)
{
pid_t pid = fork ();
if (pid == -1)
{
err (1, "fork");
}
if (pid == 0)
{
execve ("/bin/true", args, env);
err (1, "execve");
}
return pid;
}
// repro glibc
// repro musl
pid_t
spawn_via_vfork (void)
{
pid_t pid = vfork ();
if (pid == -1)
{
err (1, "vfork");
}
if (pid == 0)
{
execve ("/bin/true", args, env);
err (1, "execve");
}
return pid;
}
/* Okay, so below we will emulate vfork using CLONE_VM. We will do so using O_CLOEXEC pipe.
* We will heavily rely on one important property: during execve Linux first destroys old memory,
* and then closes all O_CLOEXEC fds. This is actually true, as we can see in Linux source:
* https://elixir.bootlin.com/linux/v6.13-rc3/source/fs/exec.c#L1274
* https://elixir.bootlin.com/linux/v6.13-rc3/source/fs/exec.c#L1312
* As you can see, do_close_on_exec is called after exec_mmap
*/
int pipe_fd[2];
int
helper (void *a)
{
if (syscall (SYS_close, pipe_fd[0]) != 0)
{
syscall (SYS_write, 2, "clo", 3);
syscall (SYS_exit_group, 1);
}
syscall (SYS_execve, "/bin/true", args, env);
syscall (SYS_write, 2, "exe", 3);
syscall (SYS_exit_group, 1);
}
// not repro glibc
// not repro musl
pid_t
spawn_via_clone_vm (void)
{
if (pipe2 (pipe_fd, O_CLOEXEC) == -1)
{
err (1, "pipe2");
}
// Begin of code, copied from "man 2 clone"
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
char *stack; /* Start of stack buffer */
char *stackTop; /* End of stack buffer */
/* Allocate memory to be used for the stack of the child. */
stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED)
{
err (1, "mmap");
}
stackTop = stack + STACK_SIZE; /* Assume stack grows downward */
pid_t pid = clone (helper, stackTop, CLONE_VM | SIGCHLD, NULL);
if (pid == -1)
{
err (1, "clone");
}
// End of code, copied from "man 2 clone"
// Okay, so now we should wait for "execve". We will do this using that pipe
// We will use "syscall" to avoid messing with libc's state
// We cannot even rely on errno, because it is probably shared now
if (syscall (SYS_close, pipe_fd[1]) != 0)
{
syscall (SYS_write, 2, "clo", 3);
syscall (SYS_exit_group, 1);
}
char buf[1];
if (syscall (SYS_read, pipe_fd[0], buf, 1) != 0)
{
syscall (SYS_write, 2, "rea", 3);
syscall (SYS_exit_group, 1);
}
// Okay, so the child did "execve", now we can continue running normally
if (close (pipe_fd[0]) != 0)
{
err (1, "close");
}
return pid;
}
int
helper_clone_vfork (void *a)
{
execve ("/bin/true", args, env);
err (1, "execve");
}
// repro glibc
// repro musl
pid_t
spawn_via_clone_vfork (void)
{
// Begin of code, copied from "man 2 clone"
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
char *stack; /* Start of stack buffer */
char *stackTop; /* End of stack buffer */
/* Allocate memory to be used for the stack of the child. */
stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED)
{
err (1, "mmap");
}
stackTop = stack + STACK_SIZE; /* Assume stack grows downward */
pid_t pid = clone (helper, stackTop, CLONE_VFORK | SIGCHLD, NULL);
if (pid == -1)
{
err (1, "clone");
}
// End of code, copied from "man 2 clone"
return pid;
}
int
main (void)
{
for (;;)
{
pid_t pid = spawn_via_clone_vfork (); // You can replace this line with some other "spawn_via_..." function
if (waitpid (pid, NULL, 0) != pid)
{
err(1, "waitpid");
}
}
}
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-01-22 21:45 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-16 23:14 [musl] [bug] Ctrl-Z when process is doing posix_spawn makes the process hard to kill Askar Safin
2025-01-17 6:37 ` Rich Felker
2025-01-17 6:46 ` Rich Felker
2025-01-17 17:55 ` Askar Safin
2025-01-18 9:51 ` Florian Weimer
2025-01-18 10:23 ` Rich Felker
2025-01-18 11:13 ` Florian Weimer
2025-01-18 20:58 ` Askar Safin
2025-01-18 11:17 ` Rich Felker
2025-01-18 20:16 ` Markus Wichmann
2025-01-19 3:18 ` Rich Felker
2025-01-18 20:52 ` Askar Safin
2025-01-22 21:45 ` Askar Safin
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).