diff options
Diffstat (limited to 'pasta.c')
| -rw-r--r-- | pasta.c | 38 |
1 files changed, 32 insertions, 6 deletions
@@ -40,6 +40,7 @@ #include <arpa/inet.h> #include <netinet/in.h> #include <net/ethernet.h> +#include <sys/prctl.h> #include <sys/syscall.h> #include <linux/magic.h> @@ -70,15 +71,13 @@ void pasta_child_handler(int signal) if (pasta_child_pid && !waitid(P_PID, pasta_child_pid, &infop, WEXITED | WNOHANG)) { if (infop.si_pid == pasta_child_pid) { - fsync_pcap_and_log(); - if (infop.si_code == CLD_EXITED) - _exit(infop.si_status); + passt_exit(infop.si_status); /* If killed by a signal, si_status is the number. * Follow common shell convention of returning it + 128. */ - _exit(infop.si_status + 128); + passt_exit(infop.si_status + 128); /* Nothing to do, detached PID namespace going away */ } @@ -191,6 +190,10 @@ static int pasta_spawn_cmd(void *arg) size_t conf_hostname_len; sigset_t set; + /* If the parent dies with an error, so should we */ + if (prctl(PR_SET_PDEATHSIG, SIGKILL)) + die_perror("Couldn't set PR_SET_PDEATHSIG"); + /* We run in a detached PID and mount namespace: mount /proc over */ if (mount("", "/proc", "proc", 0, NULL)) warn_perror("Couldn't mount /proc"); @@ -217,6 +220,12 @@ static int pasta_spawn_cmd(void *arg) sigaddset(&set, SIGUSR1); sigwaitinfo(&set, NULL); + /* Once exec()ed this process is more valuable, and easier to see and + * clean up. Let us outlive our parent now. + */ + if (prctl(PR_SET_PDEATHSIG, 0)) + die_perror("Couldn't clear PR_SET_PDEATHSIG"); + execvp(a->exe, a->argv); die_perror("Failed to start command or shell"); @@ -307,6 +316,9 @@ void pasta_ns_conf(struct ctx *c) die("Couldn't bring up loopback interface in namespace: %s", strerror_(-rc)); + if (c->splice_only) + return; + /* Get or set MAC in target namespace */ if (MAC_IS_ZERO(c->guest_mac)) nl_link_get_mac(nl_sock_ns, c->pasta_ifi, c->guest_mac); @@ -339,6 +351,12 @@ void pasta_ns_conf(struct ctx *c) AF_INET); } + if (c->ifi4 == -1 && rc == -ENOTSUP) { + warn("IPv4 not supported, disabling"); + c->ifi4 = 0; + goto ipv4_done; + } + if (rc < 0) { die("Couldn't set IPv4 address(es) in namespace: %s", strerror_(-rc)); @@ -358,6 +376,7 @@ void pasta_ns_conf(struct ctx *c) strerror_(-rc)); } } +ipv4_done: if (c->ifi6) { rc = nl_addr_get_ll(nl_sock_ns, c->pasta_ifi, @@ -404,12 +423,19 @@ void pasta_ns_conf(struct ctx *c) AF_INET6); } + if (c->ifi6 == -1 && rc == -ENOTSUP) { + warn("IPv6 not supported, disabling"); + c->ifi6 = 0; + goto ipv6_done; + } + if (rc < 0) { die("Couldn't set IPv6 route(s) in guest: %s", strerror_(-rc)); } } } +ipv6_done: proto_update_l2_buf(c->guest_mac); } @@ -511,7 +537,7 @@ void pasta_netns_quit_inotify_handler(struct ctx *c, int inotify_fd) if (!strncmp(ev->name, c->netns_base, sizeof(c->netns_base))) { info("Namespace %s is gone, exiting", c->netns_base); - _exit(EXIT_SUCCESS); + passt_exit(EXIT_SUCCESS); } } } @@ -539,7 +565,7 @@ void pasta_netns_quit_timer_handler(struct ctx *c, union epoll_ref ref) return; info("Namespace %s is gone, exiting", c->netns_base); - _exit(EXIT_SUCCESS); + passt_exit(EXIT_SUCCESS); } close(fd); |
