diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2021-09-29 16:11:06 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-10-07 04:05:15 +0200 |
commit | 9a175cc2cea75b98fc3c20381f58dcabf24ef529 (patch) | |
tree | 44e40e4dff717ec2e4d12402a47bcf33a6f4f92b /passt.c | |
parent | ab3283802206d19ea8509f5471b5c0928ca5835f (diff) | |
download | passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar.gz passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar.bz2 passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar.lz passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar.xz passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.tar.zst passt-9a175cc2cea75b98fc3c20381f58dcabf24ef529.zip |
pasta: Allow specifying paths and names of namespaces
Based on a patch from Giuseppe Scrivano, this adds the ability to:
- specify paths and names of target namespaces to join, instead of
a PID, also for user namespaces, with --userns
- request to join or create a network namespace only, without
entering or creating a user namespace, with --netns-only
- specify the base directory for netns mountpoints, with --nsrun-dir
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
[sbrivio: reworked logic to actually join the given namespaces when
they're not created, implemented --netns-only and --nsrun-dir,
updated pasta demo script and man page]
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'passt.c')
-rw-r--r-- | passt.c | 59 |
1 files changed, 39 insertions, 20 deletions
@@ -242,18 +242,34 @@ static void pasta_child_handler(int signal) /** * pasta_wait_for_ns() - Busy loop until we can enter the target namespace - * @target_pid: PID of process associated with target namespace + * @arg: Execution context * * Return: 0 */ -static int pasta_wait_for_ns(void *target_pid) +static int pasta_wait_for_ns(void *arg) { - while (ns_enter(*(int *)target_pid)); + 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 PID is not given + * 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) @@ -266,34 +282,36 @@ static void pasta_start_ns(struct ctx *c) if (!c->debug) c->quiet = 1; - if ((c->pasta_pid = fork()) == -1) { + if ((pasta_child_pid = fork()) == -1) { perror("fork"); exit(EXIT_FAILURE); } - if ((pasta_child_pid = c->pasta_pid)) { - NS_CALL(pasta_wait_for_ns, &pasta_child_pid); + if (pasta_child_pid) { + NS_CALL(pasta_wait_for_ns, c); return; } - if (unshare(CLONE_NEWNET | CLONE_NEWUSER)) { + if (unshare(CLONE_NEWNET | (c->netns_only ? 0 : CLONE_NEWUSER))) { perror("unshare"); exit(EXIT_FAILURE); } - snprintf(buf, BUFSIZ, "%u %u %u", 0, euid, 1); + 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/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/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/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")); @@ -352,11 +370,12 @@ int main(int argc, char **argv) if (!c.debug && (c.stderr || isatty(fileno(stdout)))) openlog(log_name, LOG_PERROR, LOG_DAEMON); - if (c.mode == MODE_PASTA && !c.pasta_pid) { + 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", c.pasta_pid); + snprintf(proc_path, PATH_MAX, "/proc/%i/ns/net", + pasta_child_pid); readlink(proc_path, pasta_child_ns, PATH_MAX); } |