public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: passt-dev@passt.top, David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 09/10] isolation: Only configure UID/GID mappings in userns when spawning shell
Date: Tue, 11 Oct 2022 16:40:17 +1100	[thread overview]
Message-ID: <20221011054018.1449506-10-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20221011054018.1449506-1-david@gibson.dropbear.id.au>

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>
---
 conf.c      |  3 ++-
 isolation.c | 13 -------------
 pasta.c     | 16 ++++++++++++++--
 pasta.h     |  3 ++-
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/conf.c b/conf.c
index 1537dbf..b7661b6 100644
--- a/conf.c
+++ b/conf.c
@@ -1478,7 +1478,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 e1a024d..b94226d 100644
--- a/isolation.c
+++ b/isolation.c
@@ -207,9 +207,6 @@ void isolate_initial(void)
  */
 void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns)
 {
-	char uidmap[BUFSIZ];
-	char gidmap[BUFSIZ];
-
 	/* First set our UID & GID in the original namespace */
 	if (setgroups(0, NULL)) {
 		/* If we don't have CAP_SETGID, this will EPERM */
@@ -261,16 +258,6 @@ void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns)
 		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");
-	}
 }
 
 /**
diff --git a/pasta.c b/pasta.c
index 0ab2fe4..9666fed 100644
--- a/pasta.c
+++ b/pasta.c
@@ -166,7 +166,6 @@ static int pasta_setup_ns(void *arg)
 {
 	const struct pasta_setup_ns_arg *a
 		= (const struct pasta_setup_ns_arg *)arg;
-
 	if (write_file("/proc/sys/net/ipv4/ping_group_range", "0 0"))
 		warn("Cannot set ping_group_range, ICMP requests might fail");
 
@@ -179,16 +178,20 @@ 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 *sh_argv[] = { NULL, NULL };
+	char uidmap[BUFSIZ], gidmap[BUFSIZ];
 	char ns_fn_stack[NS_FN_STACK_SIZE];
 	char sh_arg0[PATH_MAX + 1];
 
@@ -196,7 +199,16 @@ 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");
 		if (!arg.exe)
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);
-- 
@@ -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);
-- 
2.37.3


  parent reply	other threads:[~2022-10-11  5:40 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-11  5:40 [PATCH 00/10] Fixes and cleanups for capability handling David Gibson
2022-10-11  5:40 ` [PATCH 01/10] test: Move slower tests to end of test run David Gibson
2022-10-11  5:40 ` [PATCH 02/10] pasta: More general way of starting spawned shell as a login shell David Gibson
2022-10-13  2:16   ` Stefano Brivio
2022-10-13  8:22     ` David Gibson
2022-10-13  9:48       ` Stefano Brivio
2022-10-13 23:24         ` David Gibson
2022-10-11  5:40 ` [PATCH 03/10] pasta_start_ns() always ends in parent context David Gibson
2022-10-11  5:40 ` [PATCH 04/10] Remove unhelpful drop_caps() call in pasta_start_ns() David Gibson
2022-10-11  5:40 ` [PATCH 05/10] Clarify various self-isolation steps David Gibson
2022-10-13  2:17   ` Stefano Brivio
2022-10-13  8:31     ` David Gibson
2022-10-13 12:49   ` Stefano Brivio
2022-10-13 23:25     ` David Gibson
2022-10-11  5:40 ` [PATCH 06/10] Replace FWRITE with a function David Gibson
2022-10-13  2:17   ` Stefano Brivio
2022-10-13  8:51     ` David Gibson
2022-10-11  5:40 ` [PATCH 07/10] isolation: Replace drop_caps() with a version that actually does something David Gibson
2022-10-13  2:18   ` Stefano Brivio
2022-10-13  9:44     ` David Gibson
2022-10-13  4:01   ` Stefano Brivio
2022-10-13 13:08     ` Stefano Brivio
2022-10-13 16:37       ` Stefano Brivio
2022-10-13 23:42         ` David Gibson
2022-10-11  5:40 ` [PATCH 08/10] isolation: Prevent any child processes gaining capabilities David Gibson
2022-10-13  2:17   ` Stefano Brivio
2022-10-13  9:33     ` David Gibson
2022-10-13  9:50       ` Stefano Brivio
2022-10-11  5:40 ` David Gibson [this message]
2022-10-13  2:18   ` [PATCH 09/10] isolation: Only configure UID/GID mappings in userns when spawning shell Stefano Brivio
2022-10-13  9:36     ` David Gibson
2022-10-11  5:40 ` [PATCH 10/10] Rename pasta_setup_ns() to pasta_spawn_cmd() David Gibson
2022-10-13  2:44 ` [PATCH 00/10] Fixes and cleanups for capability handling Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221011054018.1449506-10-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).