mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: musl@lists.openwall.com
Subject: posix_spawn topics [was: Re: [musl] musl 1.1.17 released]
Date: Thu, 19 Oct 2017 21:17:16 -0400	[thread overview]
Message-ID: <20171020011716.GS1627@brightrain.aerifal.cx> (raw)
In-Reply-To: <CAHy7VY5r_9XzvPOx__n-2k91yXYCHvpjy2emuq=wH8VmmFpy8A@mail.gmail.com>

On Fri, Oct 20, 2017 at 02:11:35AM +0200, Petr Skocik wrote:
> Hi.
> Since posix_spawn is being discussed, I'd like to report a what I think is
> a bug in the current implementation:
> Since the child is unmasking its signals only after it's performed its file
> actions, the process may get blocked indefinitely (e.g., on a FIFO
> open) while being unresponsive to signals.
> 
> Example program (with close to no error checking):
> 
> 
> #define _GNU_SOURCE
> #include <unistd.h>
> #include <spawn.h>
> #include <stdlib.h>
> #include <fcntl.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sys/wait.h>
> int main()
> {
> pid_t pid;
> mkfifo("fifo", 0640);
> posix_spawn_file_actions_t fa;
> posix_spawn_file_actions_init(&fa);
> posix_spawn_file_actions_addopen(&fa, 0, "fifo", O_RDONLY, 0);
> posix_spawnp(&pid, "tr", &fa, 0, (char *const[]){ "tr", "a-z", "A-Z", 0},
> environ);
> 
>         //will get stuck here
> 
> }
> 
> 
> It  think the pthread_mask call should be moved above the file actions,
> which fixes this problem.

It's actually rather ugly that this happens at all. Your "fix" is
presumably that ^C now works, which of course helps. But short of
terminals signals there's no legitimate way to kill the hung process
because its pid has not been returned yet.

I'm not really sure what should happen here; it may call for an
interpretation request.

> Additionally, as far as extensions to the current POSIX standard are
> concerned, adding the herein (http://austingroupbugs.net/view.php?id=411)
> proposed change to *adddup2 semantics (clearing the FD_CLOEXEC flag on the
>  (given target in dup2 file actions where the source and target
> filedescriptor are identical) would be super nice (the reasoning for it
> should be in the link).

I wasn't aware of that part of #411; I agree it should be adopted now
without waiting for a new standard.

> Finally, I noticed the error passing code can be reduced to a simple write
> to a volatile int made from the child (purely cosmetic).

The pipe is there for a very important reason, and the reason is not
passing the error. It just happens that, since we already have to read
from it in the parent anyway, it makes a convenient channel to pass
the error on. Your modified version has serious memory corruption
because the parent continues running (and may return from posix_spawn)
after args->ret is set but before the child exits, thereby ending the
lifetime of the child's stack. Atomicity of closing of the
close-on-exec pipe with respect to exec is the property we're using
here to detect when exec has taken effect and memory is no longer
shared.

An argument can be made that CLONE_VFORK mandates the schedudler
prevent this, but historically it did not always do this correctly,
especially when traced (and I believe it's still possible when tracing
to manually resume the parent while the child is still sharing
memory), and the intent is to be compatible with kernels where
CLONE_VFORK is a nop. The main reason CLONE_VFORK is used is actually
as a hint to qemu-userlevel to get it to emulate things right.

> Attached are patches for these 3 things in case you wanted them. (I hope
> I'm not doing something stupid.)

Otherwise no, not "stupid", but the patches are a lot larger/more
invasive than they need to be and don't follow coding style.

> @@ -97,14 +108,14 @@ static int child(void *args_vp)
>  				__syscall(SYS_close, op->fd);
>  				break;
>  			case FDOP_DUP2:
> -				if ((ret=__sys_dup2(op->srcfd, op->fd))<0)
> +				if ((ret=dup3_or_set_cloexec(op->srcfd, op->fd, 0))<0)
>  					goto fail;
>  				break;
>  			case FDOP_OPEN:
>  				fd = __sys_open(op->path, op->oflag, op->mode);
>  				if ((ret=fd) < 0) goto fail;
>  				if (fd != op->fd) {
> -					if ((ret=__sys_dup2(fd, op->fd))<0)
> +					if ((ret=dup3_or_set_cloexec(fd, op->fd, 0))<0)

This (FDOP_OPEN) is not a case covered by the POSIX interpretation,
and using it here would actually be wrong if it were reachable, but
you're already inside "if (fd != op->fd)" and thus there's no way
fd==op->fd can be true. So the change in this line is just spurious.
There's then just one place where dup3_or_set_cloexec is called (the
previous case), and it doesn't make sense to have a function; rather
the conditional should just be inline in that case.

Rich


  reply	other threads:[~2017-10-20  1:17 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-19 20:13 musl 1.1.17 released Rich Felker
2017-10-20  0:11 ` Petr Skocik
2017-10-20  1:17   ` Rich Felker [this message]
2017-10-20  9:02     ` posix_spawn topics [was: Re: [musl] musl 1.1.17 released] Petr Skocik
2017-10-20  9:09       ` Petr Skočík

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171020011716.GS1627@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).