diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 8ae205b65e..a08683bcea 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -67,9 +67,9 @@ int take_etc_passwd_lock(const char *root); #define UID_NOBODY ((uid_t) 65534U) #define GID_NOBODY ((gid_t) 65534U) -/* If REMOUNT_IDMAP_HOST_ROOT is set for remount_idmap() we'll include a mapping here that maps the host root - * user accessing the idmapped mount to the this user ID on the backing fs. This is the last valid UID in the - * *signed* 32bit range. You might wonder why precisely use this specific UID for this purpose? Well, we +/* If REMOUNT_IDMAPPING_HOST_ROOT is set for remount_idmap() we'll include a mapping here that maps the host + * root user accessing the idmapped mount to the this user ID on the backing fs. This is the last valid UID in + * the *signed* 32bit range. You might wonder why precisely use this specific UID for this purpose? Well, we * definitely cannot use the first 0…65536 UIDs for that, since in most cases that's precisely the file range * we intend to map to some high UID range, and since UID mappings have to be bijective we thus cannot use * them at all. Furthermore the UID range beyond INT32_MAX (i.e. the range above the signed 32bit range) is diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index d5af73a3cd..5d37204f6c 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -708,10 +708,10 @@ int mount_all(const char *dest, return 0; } -static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts, bool *idmapped) { +static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts, RemountIdmapping *idmapping) { unsigned long flags = *mount_flags; char *opts = NULL; - bool flag_idmapped = *idmapped; + RemountIdmapping new_idmapping = *idmapping; int r; assert(options); @@ -730,16 +730,16 @@ static int parse_mount_bind_options(const char *options, unsigned long *mount_fl else if (streq(word, "norbind")) flags &= ~MS_REC; else if (streq(word, "idmap")) - flag_idmapped = true; + new_idmapping = REMOUNT_IDMAPPING_HOST_ROOT; else if (streq(word, "noidmap")) - flag_idmapped = false; + new_idmapping = REMOUNT_IDMAPPING_NONE; else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid bind mount option: %s", word); } *mount_flags = flags; - *idmapped = flag_idmapped; + *idmapping = new_idmapping; /* in the future mount_opts will hold string options for mount(2) */ *mount_opts = opts; @@ -751,13 +751,13 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u unsigned long mount_flags = MS_BIND | MS_REC; struct stat source_st, dest_st; int r; - bool idmapped = false; + RemountIdmapping idmapping = REMOUNT_IDMAPPING_NONE; assert(dest); assert(m); if (m->options) { - r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts, &idmapped); + r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts, &idmapping); if (r < 0) return r; } @@ -815,8 +815,8 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u return log_error_errno(r, "Read-only bind mount failed: %m"); } - if (idmapped) { - r = remount_idmap(where, uid_shift, uid_range, REMOUNT_IDMAP_HOST_ROOT); + if (idmapping != REMOUNT_IDMAPPING_NONE) { + r = remount_idmap(where, uid_shift, uid_range, idmapping); if (r < 0) return log_error_errno(r, "Failed to map ids for bind mount %s: %m", where); } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ca87bffd0b..6316c03916 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3806,7 +3806,7 @@ static int outer_child( IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_AUTO) && arg_uid_shift != 0) { - r = remount_idmap(directory, arg_uid_shift, arg_uid_range, REMOUNT_IDMAP_HOST_ROOT); + r = remount_idmap(directory, arg_uid_shift, arg_uid_range, REMOUNT_IDMAPPING_HOST_ROOT); if (r == -EINVAL || ERRNO_IS_NOT_SUPPORTED(r)) { /* This might fail because the kernel or file system doesn't support idmapping. We * can't really distinguish this nicely, nor do we have any guarantees about the diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index ba0bdbbfb6..b976d92c15 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1380,7 +1380,7 @@ static int mount_partition( (void) fs_grow(node, p); if (remap_uid_gid) { - r = remount_idmap(p, uid_shift, uid_range, REMOUNT_IDMAP_HOST_ROOT); + r = remount_idmap(p, uid_shift, uid_range, REMOUNT_IDMAPPING_HOST_ROOT); if (r < 0) return r; } diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 2dd73b508d..ab1acfc2e5 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -1053,7 +1053,7 @@ int make_mount_point(const char *path) { return 1; } -static int make_userns(uid_t uid_shift, uid_t uid_range, RemountIdmapFlags flags) { +static int make_userns(uid_t uid_shift, uid_t uid_range, RemountIdmapping idmapping) { _cleanup_close_ int userns_fd = -1; _cleanup_free_ char *line = NULL; @@ -1073,7 +1073,7 @@ static int make_userns(uid_t uid_shift, uid_t uid_range, RemountIdmapFlags flags * 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 (flags & REMOUNT_IDMAP_HOST_ROOT) + if (idmapping == REMOUNT_IDMAPPING_HOST_ROOT) if (strextendf(&line, UID_FMT " " UID_FMT " " UID_FMT "\n", UID_MAPPED_ROOT, 0u, 1u) < 0) @@ -1091,7 +1091,7 @@ int remount_idmap( const char *p, uid_t uid_shift, uid_t uid_range, - RemountIdmapFlags flags) { + RemountIdmapping idmapping) { _cleanup_close_ int mount_fd = -1, userns_fd = -1; int r; @@ -1107,7 +1107,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, flags); + userns_fd = make_userns(uid_shift, uid_range, idmapping); if (userns_fd < 0) return userns_fd; diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index 1797b8803c..b40687a99c 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -118,7 +118,8 @@ int mount_image_in_namespace(pid_t target, const char *propagate_path, const cha int make_mount_point(const char *path); -typedef enum RemountIdmapFlags { +typedef enum RemountIdmapping { + REMOUNT_IDMAPPING_NONE, /* Include a mapping from UID_MAPPED_ROOT (i.e. UID 2^31-2) on the backing fs to UID 0 on the * uidmapped fs. This is useful to ensure that the host root user can safely add inodes to the * uidmapped fs (which otherwise wouldn't work as the host root user is not defined on the uidmapped @@ -126,10 +127,12 @@ typedef enum RemountIdmapFlags { * these inodes are quickly re-chown()ed to more suitable UIDs/GIDs. Any code that intends to be able * to add inodes to file systems mapped this way should set this flag, but given it comes with * certain security implications defaults to off, and requires explicit opt-in. */ - REMOUNT_IDMAP_HOST_ROOT = 1 << 0, -} RemountIdmapFlags; + REMOUNT_IDMAPPING_HOST_ROOT, + _REMOUNT_IDMAPPING_MAX, + _REMOUNT_IDMAPPING_INVALID = -EINVAL, +} RemountIdmapping; -int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range, RemountIdmapFlags flags); +int remount_idmap(const char *p, uid_t uid_shift, uid_t uid_range, RemountIdmapping idmapping); /* Creates a mount point (not parents) based on the source path or stat - ie, a file or a directory */ int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode);