diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-04-27 18:03:31 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-05-07 22:44:13 +0200 |
commit | f61c7f88d0cd7e7901a384eb7749686e4ed633e5 (patch) | |
tree | 972fd1fbb8b9ec38903206d91e96b5e19a9fdda5 /src/nspawn/nspawn.c | |
parent | nspawn: drop an unnecessary local variable (diff) | |
download | systemd-f61c7f88d0cd7e7901a384eb7749686e4ed633e5.tar.xz systemd-f61c7f88d0cd7e7901a384eb7749686e4ed633e5.zip |
nspawn: introduce --private-users-ownership=map|auto
This adds a two new values to --private-users-ownership=: "map" and
"auto".
"map" exposes the kernel 5.12 idmap feature pretty much 1:1. It fails if
the kernel or used file system doesn't support ID mapping.
"auto" is a bit smarter: if we can make ID mapping work, we'll use it,
otherwise revert back to classic chown()ing. We'll also use chown()ing
if we detect that an image is already ID shifted, both to increase
compatibility with the status quo ante, and to simplify our codepaths,
since the mappings become a lot simpler if we only have to map from zero
to something else, instead of from anything to anything else.
The short -U switch, and --private-users=pick will now imply
--private-users-ownership=auto instead of
--private-users-ownership=chown, since the new logic should be the much
better choice.
Diffstat (limited to '')
-rw-r--r-- | src/nspawn/nspawn.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 72886a070b..4ef95bfa5a 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1733,7 +1733,7 @@ static int verify_arguments(void) { if (arg_userns_ownership < 0) arg_userns_ownership = - arg_userns_mode == USER_NAMESPACE_PICK ? USER_NAMESPACE_OWNERSHIP_CHOWN : + arg_userns_mode == USER_NAMESPACE_PICK ? USER_NAMESPACE_OWNERSHIP_AUTO : USER_NAMESPACE_OWNERSHIP_OFF; if (arg_start_mode == START_BOOT && arg_kill_signal <= 0) @@ -3065,6 +3065,18 @@ static int determine_uid_shift(const char *directory) { "UID and GID base of %s don't match.", directory); arg_uid_range = UINT32_C(0x10000); + + if (arg_uid_shift != 0) { + /* If the image is shifted already, then we'll fall back to classic chowning, for + * compatibility (and simplicity), or refuse if mapping is explicitly requested. */ + + if (arg_userns_ownership == USER_NAMESPACE_OWNERSHIP_AUTO) { + log_debug("UID base of %s is non-zero, not using UID mapping.", directory); + arg_userns_ownership = USER_NAMESPACE_OWNERSHIP_CHOWN; + } else if (arg_userns_ownership == USER_NAMESPACE_OWNERSHIP_MAP) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "UID base of %s is not zero, UID mapping not supported.", directory); + } } if (!userns_shift_range_valid(arg_uid_shift, arg_uid_range)) @@ -3558,6 +3570,7 @@ static int outer_child( _cleanup_strv_free_ char **os_release_pairs = NULL; _cleanup_close_ int fd = -1; + bool idmap = false; const char *p; pid_t pid; ssize_t l; @@ -3661,6 +3674,32 @@ static int outer_child( directory = "/run/systemd/nspawn-root"; } + if (arg_userns_mode != USER_NAMESPACE_NO && + IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_AUTO) && + arg_uid_shift != 0) { + r = make_mount_point(directory); + if (r < 0) + return r; + + r = remount_idmap(directory, arg_uid_shift, arg_uid_range); + 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 + * error codes we see, could be EOPNOTSUPP or EINVAL. */ + if (arg_userns_ownership != USER_NAMESPACE_OWNERSHIP_AUTO) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "ID mapped mounts are apparently not available, sorry."); + + log_debug("ID mapped mounts are apparently not available on this kernel or for the selected file system, reverting to recursive chown()ing."); + arg_userns_ownership = USER_NAMESPACE_OWNERSHIP_CHOWN; + } else if (r < 0) + return log_error_errno(r, "Failed to set up ID mapped mounts: %m"); + else { + log_debug("ID mapped mounts available, making use of them."); + idmap = true; + } + } + r = setup_pivot_root( directory, arg_pivot_root_new, @@ -3701,7 +3740,8 @@ static int outer_child( DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY| DISSECT_IMAGE_DISCARD_ON_LOOP| DISSECT_IMAGE_USR_NO_ROOT| - (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS)); + (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK|DISSECT_IMAGE_GROWFS)| + (idmap ? DISSECT_IMAGE_MOUNT_IDMAPPED : 0)); if (r == -EUCLEAN) return log_error_errno(r, "File system check for image failed: %m"); if (r < 0) |