From 675174d4ba255383b213437e29b617d8f55dbc69 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Mon, 11 Oct 2021 12:01:31 +0200 Subject: conf, tap: Split netlink and pasta functions, allow interface configuration Move netlink routines to their own file, and use netlink to configure or fetch all the information we need, except for the TUNSETIFF ioctl. Move pasta-specific functions to their own file as well, add parameters and calls to configure the tap interface in the namespace. Signed-off-by: Stefano Brivio --- passt.c | 183 +--------------------------------------------------------------- 1 file changed, 2 insertions(+), 181 deletions(-) (limited to 'passt.c') diff --git a/passt.c b/passt.c index e0519f6..b411657 100644 --- a/passt.c +++ b/passt.c @@ -62,6 +62,7 @@ #include "pcap.h" #include "tap.h" #include "conf.h" +#include "pasta.h" #define EPOLL_EVENTS 8 @@ -156,178 +157,6 @@ void proto_update_l2_buf(unsigned char *eth_d, unsigned char *eth_s, udp_update_l2_buf(eth_d, eth_s, ip_da); } -static int pasta_child_pid; -static char pasta_child_ns[PATH_MAX]; - -/** - * pasta_ns_cleanup() - Look for processes in namespace, terminate them - */ -static void pasta_ns_cleanup(void) -{ - char proc_path[PATH_MAX], ns_link[PATH_MAX]; - int recheck = 0, found = 0, waited = 0; - struct dirent *dp; - DIR *dirp; - - if (!*pasta_child_ns) - return; - -loop: - if (!(dirp = opendir("/proc"))) - return; - - while ((dp = readdir(dirp))) { - pid_t pid; - - errno = 0; - pid = strtol(dp->d_name, NULL, 0); - if (!pid || errno) - continue; - - snprintf(proc_path, PATH_MAX, "/proc/%i/ns/net", pid); - if (readlink(proc_path, ns_link, PATH_MAX) < 0) - continue; - - if (!strncmp(ns_link, pasta_child_ns, PATH_MAX)) { - found = 1; - if (waited) - kill(pid, SIGKILL); - else - kill(pid, SIGQUIT); - } - } - - closedir(dirp); - - if (!found) - return; - - if (waited) { - if (recheck) { - info("Some processes in namespace didn't quit"); - } else { - found = 0; - recheck = 1; - goto loop; - } - return; - } - - info("Waiting for all processes in namespace to terminate"); - sleep(1); - waited = 1; - goto loop; -} - -/** - * pasta_child_handler() - Exit once shell spawned by pasta_start_ns() exits - * @signal: Unused, handler deals with SIGCHLD only - */ -static void pasta_child_handler(int signal) -{ - siginfo_t infop; - - (void)signal; - - if (pasta_child_pid && - !waitid(P_PID, pasta_child_pid, &infop, WEXITED | WNOHANG)) { - if (infop.si_pid == pasta_child_pid) { - pasta_ns_cleanup(); - exit(EXIT_SUCCESS); - } - } - - waitid(P_ALL, 0, NULL, WEXITED | WNOHANG); - waitid(P_ALL, 0, NULL, WEXITED | WNOHANG); -} - -/** - * pasta_wait_for_ns() - Busy loop until we can enter the target namespace - * @arg: Execution context - * - * Return: 0 - */ -static int pasta_wait_for_ns(void *arg) -{ - struct ctx *c = (struct ctx *)arg; - char ns[PATH_MAX]; - - if (c->netns_only) - goto netns; - - snprintf(ns, PATH_MAX, "/proc/%i/ns/user", pasta_child_pid); - do - while ((c->pasta_userns_fd = open(ns, O_RDONLY)) < 0); - while (setns(c->pasta_userns_fd, 0) && !close(c->pasta_userns_fd)); - -netns: - snprintf(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid); - do - while ((c->pasta_netns_fd = open(ns, O_RDONLY)) < 0); - while (setns(c->pasta_netns_fd, 0) && !close(c->pasta_netns_fd)); - - return 0; -} - -/** - * pasta_start_ns() - Fork shell in new namespace if target ns is not given - * @c: Execution context - */ -static void pasta_start_ns(struct ctx *c) -{ - char buf[BUFSIZ], *shell; - int euid = geteuid(); - int fd; - - c->foreground = 1; - if (!c->debug) - c->quiet = 1; - - if ((pasta_child_pid = fork()) == -1) { - perror("fork"); - exit(EXIT_FAILURE); - } - - if (pasta_child_pid) { - NS_CALL(pasta_wait_for_ns, c); - return; - } - - if (unshare(CLONE_NEWNET | (c->netns_only ? 0 : CLONE_NEWUSER))) { - perror("unshare"); - exit(EXIT_FAILURE); - } - - if (!c->netns_only) { - snprintf(buf, BUFSIZ, "%u %u %u", 0, euid, 1); - - fd = open("/proc/self/uid_map", O_WRONLY); - write(fd, buf, strlen(buf)); - close(fd); - - fd = open("/proc/self/setgroups", O_WRONLY); - write(fd, "deny", sizeof("deny")); - close(fd); - - fd = open("/proc/self/gid_map", O_WRONLY); - write(fd, buf, strlen(buf)); - close(fd); - } - - fd = open("/proc/sys/net/ipv4/ping_group_range", O_WRONLY); - write(fd, "0 0", strlen("0 0")); - close(fd); - - shell = getenv("SHELL") ? getenv("SHELL") : "/bin/sh"; - if (strstr(shell, "/bash")) - execve(shell, ((char *[]) { shell, "-l", NULL }), environ); - else - execve(shell, ((char *[]) { shell, NULL }), environ); - - perror("execve"); - exit(EXIT_FAILURE); -} - /** * main() - Entry point and main loop * @argc: Argument count @@ -366,20 +195,12 @@ int main(int argc, char **argv) openlog(log_name, 0, LOG_DAEMON); setlogmask(LOG_MASK(LOG_EMERG)); + conf(&c, argc, argv); if (!c.debug && (c.stderr || isatty(fileno(stdout)))) openlog(log_name, LOG_PERROR, LOG_DAEMON); - if (c.mode == MODE_PASTA && !c.pasta_netns_fd) { - char proc_path[PATH_MAX]; - - pasta_start_ns(&c); - snprintf(proc_path, PATH_MAX, "/proc/%i/ns/net", - pasta_child_pid); - readlink(proc_path, pasta_child_ns, PATH_MAX); - } - c.epollfd = epoll_create1(0); if (c.epollfd == -1) { perror("epoll_create1"); -- cgit v1.2.3