aboutgitcodebugslistschat
path: root/pasta.c
diff options
context:
space:
mode:
Diffstat (limited to 'pasta.c')
-rw-r--r--pasta.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/pasta.c b/pasta.c
index 674b554..bab945f 100644
--- a/pasta.c
+++ b/pasta.c
@@ -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);