public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: passt-dev@passt.top, Paul Holzinger <pholzing@redhat.com>
Subject: Re: [PATCH] pasta: Wait for tap to be set up before spawning command
Date: Mon, 13 Feb 2023 13:33:45 +1100	[thread overview]
Message-ID: <Y+mhibaq143eo6p5@yekko> (raw)
In-Reply-To: <20230213011319.1198880-1-sbrivio@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 4326 bytes --]

On Mon, Feb 13, 2023 at 02:13:19AM +0100, Stefano Brivio wrote:
> Adapted from a patch by Paul Holzinger: when pasta spawns a command,
> operating without a pre-existing user and network namespace, it needs
> to wait for the tap device to be configured and its handler ready,
> before the command is actually executed.
> 
> Otherwise, something like:
>   pasta --config-net nslookup passt.top
> 
> usually fails as the nslookup command is issued before the network
> interface is ready.
> 
> We can't adopt a simpler approach based on SIGSTOP and SIGCONT here:
> the child runs in a separate PID namespace, so it can't send SIGSTOP
> to itself as the kernel sees the child as init process and blocks
> the delivery of the signal.
> 
> We could send SIGSTOP from the parent, but this wouldn't avoid the
> possible condition where the child isn't ready to wait for it when
> the parent sends it, also raised by Paul -- and SIGSTOP can't be
> blocked, so it can never be pending.
> 
> Use SIGUSR1 instead: mask it before clone(), so that the child starts
> with it blocked, and can safely wait for it. Once the parent is
> ready, it sends SIGUSR1 to the child. If SIGUSR1 is sent before the
> child is waiting for it, the kernel will queue it for us, because
> it's blocked.
> 
> Reported-by: Paul Holzinger <pholzing@redhat.com>
> Fixes: 1392bc5ca002 ("Allow pasta to take a command to execute")
> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
> I just applied this, to keep things simpler for myself and for
> tests, given that Paul already had a look. I'm posting it anyway
> for reviews.
> 
>  passt.c |  3 +++
>  pasta.c | 14 +++++++++++++-
>  pasta.h |  2 ++
>  3 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/passt.c b/passt.c
> index 8b2c50d..d957e14 100644
> --- a/passt.c
> +++ b/passt.c
> @@ -301,6 +301,9 @@ int main(int argc, char **argv)
>  	else
>  		write_pidfile(pidfile_fd, getpid());
>  
> +	if (pasta_child_pid)
> +		kill(pasta_child_pid, SIGUSR1);
> +
>  	isolate_postfork(&c);
>  
>  	timer_init(&c, &now);
> diff --git a/pasta.c b/pasta.c
> index 528f02a..9169913 100644
> --- a/pasta.c
> +++ b/pasta.c
> @@ -47,7 +47,7 @@
>  #include "log.h"
>  
>  /* PID of child, in case we created a namespace */
> -static int pasta_child_pid;
> +int pasta_child_pid;
>  
>  /**
>   * pasta_child_handler() - Exit once shell exits (if we started it), reap clones
> @@ -166,10 +166,16 @@ struct pasta_spawn_cmd_arg {
>  static int pasta_spawn_cmd(void *arg)
>  {
>  	const struct pasta_spawn_cmd_arg *a;
> +	sigset_t set;
>  
>  	if (write_file("/proc/sys/net/ipv4/ping_group_range", "0 0"))
>  		warn("Cannot set ping_group_range, ICMP requests might fail");
>  
> +	/* Wait for the parent to be ready: see main() */
> +	sigemptyset(&set);
> +	sigaddset(&set, SIGUSR1);
> +	sigwaitinfo(&set, NULL);
> +
>  	a = (const struct pasta_spawn_cmd_arg *)arg;
>  	execvp(a->exe, a->argv);
>  
> @@ -196,6 +202,7 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
>  	char ns_fn_stack[NS_FN_STACK_SIZE];
>  	char *sh_argv[] = { NULL, NULL };
>  	char sh_arg0[PATH_MAX + 1];
> +	sigset_t set;
>  
>  	c->foreground = 1;
>  	if (!c->debug)
> @@ -226,6 +233,11 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
>  		arg.argv = sh_argv;
>  	}
>  
> +	/* Block SIGUSR1 in child, we queue it in main() when we're ready */
> +	sigemptyset(&set);
> +	sigaddset(&set, SIGUSR1);
> +	sigprocmask(SIG_BLOCK, &set, NULL);
> +
>  	pasta_child_pid = do_clone(pasta_spawn_cmd, ns_fn_stack,
>  				   sizeof(ns_fn_stack),
>  				   CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET |
> diff --git a/pasta.h b/pasta.h
> index a8b9893..0ccb7e9 100644
> --- a/pasta.h
> +++ b/pasta.h
> @@ -6,6 +6,8 @@
>  #ifndef PASTA_H
>  #define PASTA_H
>  
> +extern int pasta_child_pid;
> +
>  void pasta_open_ns(struct ctx *c, const char *netns);
>  void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
>  		    int argc, char *argv[]);

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

      reply	other threads:[~2023-02-13  3:12 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-13  1:13 [PATCH] pasta: Wait for tap to be set up before spawning command Stefano Brivio
2023-02-13  2:33 ` David Gibson [this message]

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=Y+mhibaq143eo6p5@yekko \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=pholzing@redhat.com \
    --cc=sbrivio@redhat.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://passt.top/passt

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 IMAP folder(s).