summaryrefslogtreecommitdiff
path: root/src/shared/mount-util.c
diff options
context:
space:
mode:
authorQuentin Deslandes <qdeslandes@naccy.de>2022-09-04 20:30:58 +0200
committerQuentin Deslandes <qd@naccy.de>2022-09-05 17:23:28 +0100
commit2b2777eda96af054817f00b88a7ba80ab2578d47 (patch)
tree036c41ca85cc3bff57afedf8b0dea0e11e343ca2 /src/shared/mount-util.c
parent1aa18710aff992832cf901c943a21715ee5e65e6 (diff)
downloadsystemd-2b2777eda96af054817f00b88a7ba80ab2578d47.tar.gz
nspawn: add support for rootidmap bind option
rootidmap bind option will map the root user from the container to the owner of the mounted directory on the filesystem. This will ensure files and directories created by the root user in the container will be owned by the directory owner on the filesystem. All other user will remain unmapped.
Diffstat (limited to 'src/shared/mount-util.c')
-rw-r--r--src/shared/mount-util.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c
index ab1acfc2e5..d646634138 100644
--- a/src/shared/mount-util.c
+++ b/src/shared/mount-util.c
@@ -1053,32 +1053,43 @@ int make_mount_point(const char *path) {
return 1;
}
-static int make_userns(uid_t uid_shift, uid_t uid_range, RemountIdmapping idmapping) {
+static int make_userns(uid_t uid_shift, uid_t uid_range, uid_t owner, RemountIdmapping idmapping) {
_cleanup_close_ int userns_fd = -1;
_cleanup_free_ char *line = NULL;
/* Allocates a userns file descriptor with the mapping we need. For this we'll fork off a child
* process whose only purpose is to give us a new user namespace. It's killed when we got it. */
- if (asprintf(&line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0u, uid_shift, uid_range) < 0)
- return log_oom_debug();
-
- /* If requested we'll include an entry in the mapping so that the host root user can make changes to
- * the uidmapped mount like it normally would. Specifically, we'll map the user with UID_HOST_ROOT on
- * the backing fs to UID 0. This is useful, since nspawn code wants to create various missing inodes
- * in the OS tree before booting into it, and this becomes very easy and straightforward to do if it
- * can just do it under its own regular UID. Note that in that case the container's runtime uidmap
- * (i.e. the one the container payload processes run in) will leave this UID unmapped, i.e. if we
- * accidentally leave files owned by host root in the already uidmapped tree around they'll show up
- * as owned by 'nobody', which is safe. (Of course, we shouldn't leave such inodes around, but always
- * chown() them to the container's own UID range, but it's good to have a safety net, in case we
- * forget it.) */
- if (idmapping == REMOUNT_IDMAPPING_HOST_ROOT)
- if (strextendf(&line,
- UID_FMT " " UID_FMT " " UID_FMT "\n",
- UID_MAPPED_ROOT, 0u, 1u) < 0)
+ if (IN_SET(idmapping, REMOUNT_IDMAPPING_NONE, REMOUNT_IDMAPPING_HOST_ROOT)) {
+ if (asprintf(&line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0u, uid_shift, uid_range) < 0)
return log_oom_debug();
+ /* If requested we'll include an entry in the mapping so that the host root user can make
+ * changes to the uidmapped mount like it normally would. Specifically, we'll map the user
+ * with UID_MAPPED_ROOT on the backing fs to UID 0. This is useful, since nspawn code wants
+ * to create various missing inodes in the OS tree before booting into it, and this becomes
+ * very easy and straightforward to do if it can just do it under its own regular UID. Note
+ * that in that case the container's runtime uidmap (i.e. the one the container payload
+ * processes run in) will leave this UID unmapped, i.e. if we accidentally leave files owned
+ * by host root in the already uidmapped tree around they'll show up as owned by 'nobody',
+ * which is safe. (Of course, we shouldn't leave such inodes around, but always chown() them
+ * to the container's own UID range, but it's good to have a safety net, in case we
+ * forget it.) */
+ if (idmapping == REMOUNT_IDMAPPING_HOST_ROOT)
+ if (strextendf(&line,
+ UID_FMT " " UID_FMT " " UID_FMT "\n",
+ UID_MAPPED_ROOT, 0u, 1u) < 0)
+ return log_oom_debug();
+ }
+
+ if (idmapping == REMOUNT_IDMAPPING_HOST_OWNER) {
+ /* Remap the owner of the bind mounted directory to the root user within the container. This
+ * way every file written by root within the container to the bind-mounted directory will
+ * be owned by the original user. All other user will remain unmapped. */
+ if (asprintf(&line, UID_FMT " " UID_FMT " " UID_FMT "\n", owner, uid_shift, 1u) < 0)
+ return log_oom_debug();
+ }
+
/* We always assign the same UID and GID ranges */
userns_fd = userns_acquire(line, line);
if (userns_fd < 0)
@@ -1091,6 +1102,7 @@ int remount_idmap(
const char *p,
uid_t uid_shift,
uid_t uid_range,
+ uid_t owner,
RemountIdmapping idmapping) {
_cleanup_close_ int mount_fd = -1, userns_fd = -1;
@@ -1107,7 +1119,7 @@ int remount_idmap(
return log_debug_errno(errno, "Failed to open tree of mounted filesystem '%s': %m", p);
/* Create a user namespace mapping */
- userns_fd = make_userns(uid_shift, uid_range, idmapping);
+ userns_fd = make_userns(uid_shift, uid_range, owner, idmapping);
if (userns_fd < 0)
return userns_fd;