aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2022-10-14 15:25:36 +1100
committerStefano Brivio <sbrivio@redhat.com>2022-10-15 02:10:36 +0200
commiteb3d03a588e8a246a30017add08c79527fa9a6a3 (patch)
tree0afa2ecef4f28800b931310caea62dbc841941c4
parentfb449b16bd8ccf8b751dfa5aee54cb7de0525706 (diff)
downloadpasst-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar.gz
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar.bz2
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar.lz
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar.xz
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.tar.zst
passt-eb3d03a588e8a246a30017add08c79527fa9a6a3.zip
isolation: Only configure UID/GID mappings in userns when spawning shell
When in passt mode, or pasta mode spawning a command, we create a userns for ourselves. This is used both to isolate the pasta/passt process itself and to run the spawned command, if any. Since eed17a47 "Handle userns isolation and dropping root at the same time" we've handled both cases the same, configuring the UID and GID mappings in the new userns to map whichever UID we're running as to root within the userns. This mapping is desirable when spawning a shell or other command, so that the user gets a root shell with reasonably clear abilities within the userns and netns. It's not necessarily essential, though. When not spawning a shell, it doesn't really have any purpose: passt itself doesn't need to be root and can operate fine with an unmapped user (using some of the capabilities we get when entering the userns instead). Configuring the uid_map can cause problems if passt is running with any capabilities in the initial namespace, such as CAP_NET_BIND_SERVICE to allow it to forward low ports. In this case the kernel makes files in /proc/pid owned by root rather than the starting user to prevent the user from interfering with the operation of the capability-enhanced process. This includes uid_map meaning we are not able to write to it. Whether this behaviour is correct in the kernel is debatable, but in any case we might as well avoid problems by only initializing the user mappings when we really want them. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--conf.c3
-rw-r--r--isolation.c13
-rw-r--r--pasta.c15
-rw-r--r--pasta.h3
4 files changed, 18 insertions, 16 deletions
diff --git a/conf.c b/conf.c
index 9f7df2c..35d037e 100644
--- a/conf.c
+++ b/conf.c
@@ -1556,7 +1556,8 @@ void conf(struct ctx *c, int argc, char **argv)
if (*netns) {
pasta_open_ns(c, netns);
} else {
- pasta_start_ns(c, argc - optind, argv + optind);
+ pasta_start_ns(c, uid, gid,
+ argc - optind, argv + optind);
}
}
diff --git a/isolation.c b/isolation.c
index 3a4ec9f..4e6637d 100644
--- a/isolation.c
+++ b/isolation.c
@@ -265,23 +265,10 @@ void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns,
close(ufd);
} else if (use_userns) { /* Create and join a new userns */
- char uidmap[BUFSIZ];
- char gidmap[BUFSIZ];
-
if (unshare(CLONE_NEWUSER) != 0) {
err("Couldn't create user namespace: %s", strerror(errno));
exit(EXIT_FAILURE);
}
-
- /* Configure user and group mappings */
- snprintf(uidmap, BUFSIZ, "0 %u 1", uid);
- snprintf(gidmap, BUFSIZ, "0 %u 1", gid);
-
- if (write_file("/proc/self/uid_map", uidmap) ||
- write_file("/proc/self/setgroups", "deny") ||
- write_file("/proc/self/gid_map", gidmap)) {
- warn("Couldn't configure user namespace");
- }
}
/* Joining a new userns gives us full capabilities; drop the
diff --git a/pasta.c b/pasta.c
index d135f1b..1824c6e 100644
--- a/pasta.c
+++ b/pasta.c
@@ -180,15 +180,19 @@ static int pasta_setup_ns(void *arg)
/**
* pasta_start_ns() - Fork command in new namespace if target ns is not given
* @c: Execution context
+ * @uid: UID we're running as in the init namespace
+ * @gid: GID we're running as in the init namespace
* @argc: Number of arguments for spawned command
* @argv: Command to spawn and arguments
*/
-void pasta_start_ns(struct ctx *c, int argc, char *argv[])
+void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
+ int argc, char *argv[])
{
struct pasta_setup_ns_arg arg = {
.exe = argv[0],
.argv = argv,
};
+ char uidmap[BUFSIZ], gidmap[BUFSIZ];
char ns_fn_stack[NS_FN_STACK_SIZE];
char *sh_argv[] = { NULL, NULL };
char sh_arg0[PATH_MAX + 1];
@@ -197,6 +201,15 @@ void pasta_start_ns(struct ctx *c, int argc, char *argv[])
if (!c->debug)
c->quiet = 1;
+ /* Configure user and group mappings */
+ snprintf(uidmap, BUFSIZ, "0 %u 1", uid);
+ snprintf(gidmap, BUFSIZ, "0 %u 1", gid);
+
+ if (write_file("/proc/self/uid_map", uidmap) ||
+ write_file("/proc/self/setgroups", "deny") ||
+ write_file("/proc/self/gid_map", gidmap)) {
+ warn("Couldn't configure user mappings");
+ }
if (argc == 0) {
arg.exe = getenv("SHELL");
diff --git a/pasta.h b/pasta.h
index 02df1f6..a8b9893 100644
--- a/pasta.h
+++ b/pasta.h
@@ -7,7 +7,8 @@
#define PASTA_H
void pasta_open_ns(struct ctx *c, const char *netns);
-void pasta_start_ns(struct ctx *c, int argc, char *argv[]);
+void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
+ int argc, char *argv[]);
void pasta_ns_conf(struct ctx *c);
void pasta_child_handler(int signal);
int pasta_netns_quit_init(struct ctx *c);