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[]);