nspawn: support foreign mappings also when nspawn doing the mapping itself
This adds a new "foreign" value to --private-users-ownership= which is a lot like "map", but maps from the host's foreign UID range rather than from the host's 0. (This has nothing much to do with making unprivileged directory-based containers work, it's just very handy that we can run privileged contains with such a mapping too, with an easy switch)
This commit is contained in:
@@ -930,10 +930,11 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(timezone_mode, TimezoneMode, TIMEZONE_AU
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_userns_ownership, user_namespace_ownership, UserNamespaceOwnership);
|
||||
|
||||
static const char *const user_namespace_ownership_table[_USER_NAMESPACE_OWNERSHIP_MAX] = {
|
||||
[USER_NAMESPACE_OWNERSHIP_OFF] = "off",
|
||||
[USER_NAMESPACE_OWNERSHIP_CHOWN] = "chown",
|
||||
[USER_NAMESPACE_OWNERSHIP_MAP] = "map",
|
||||
[USER_NAMESPACE_OWNERSHIP_AUTO] = "auto",
|
||||
[USER_NAMESPACE_OWNERSHIP_OFF] = "off",
|
||||
[USER_NAMESPACE_OWNERSHIP_CHOWN] = "chown",
|
||||
[USER_NAMESPACE_OWNERSHIP_MAP] = "map",
|
||||
[USER_NAMESPACE_OWNERSHIP_FOREIGN] = "foreign",
|
||||
[USER_NAMESPACE_OWNERSHIP_AUTO] = "auto",
|
||||
};
|
||||
|
||||
/* Note: while "yes" maps to "auto" here, we don't really document that, in order to make things clearer and less confusing to users. */
|
||||
|
||||
@@ -34,9 +34,10 @@ typedef enum UserNamespaceMode {
|
||||
} UserNamespaceMode;
|
||||
|
||||
typedef enum UserNamespaceOwnership {
|
||||
USER_NAMESPACE_OWNERSHIP_OFF,
|
||||
USER_NAMESPACE_OWNERSHIP_CHOWN,
|
||||
USER_NAMESPACE_OWNERSHIP_MAP,
|
||||
USER_NAMESPACE_OWNERSHIP_OFF, /* do not change ownership */
|
||||
USER_NAMESPACE_OWNERSHIP_CHOWN, /* chown to target range */
|
||||
USER_NAMESPACE_OWNERSHIP_MAP, /* map from 0x00000000…0x0000FFFF range to target range */
|
||||
USER_NAMESPACE_OWNERSHIP_FOREIGN, /* map from 0x7FFE0000…0x7FFEFFFF range to target range */
|
||||
USER_NAMESPACE_OWNERSHIP_AUTO,
|
||||
_USER_NAMESPACE_OWNERSHIP_MAX,
|
||||
_USER_NAMESPACE_OWNERSHIP_INVALID = -1,
|
||||
|
||||
+39
-2
@@ -107,6 +107,7 @@
|
||||
#include "sysctl-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "uid-classification.h"
|
||||
#include "umask-util.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
@@ -4137,9 +4138,39 @@ static int outer_child(
|
||||
return r;
|
||||
|
||||
if (arg_userns_mode != USER_NAMESPACE_NO &&
|
||||
IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_AUTO) &&
|
||||
IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_FOREIGN, USER_NAMESPACE_OWNERSHIP_AUTO) &&
|
||||
arg_uid_shift != 0) {
|
||||
_cleanup_strv_free_ char **dirs = NULL;
|
||||
RemountIdmapping mapping;
|
||||
|
||||
switch (arg_userns_ownership) {
|
||||
case USER_NAMESPACE_OWNERSHIP_MAP:
|
||||
mapping = REMOUNT_IDMAPPING_HOST_ROOT;
|
||||
break;
|
||||
|
||||
case USER_NAMESPACE_OWNERSHIP_FOREIGN:
|
||||
mapping = REMOUNT_IDMAPPING_FOREIGN_WITH_HOST_ROOT;
|
||||
break;
|
||||
|
||||
case USER_NAMESPACE_OWNERSHIP_AUTO: {
|
||||
struct stat st;
|
||||
|
||||
if (lstat(directory, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat() container root directory '%s': %m", directory);
|
||||
|
||||
r = stat_verify_directory(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Container root directory '%s' is not a directory: %m", directory);
|
||||
|
||||
mapping = uid_is_foreign(st.st_uid) ?
|
||||
REMOUNT_IDMAPPING_FOREIGN_WITH_HOST_ROOT :
|
||||
REMOUNT_IDMAPPING_HOST_ROOT;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (arg_volatile_mode != VOLATILE_YES) {
|
||||
r = strv_extend(&dirs, directory);
|
||||
@@ -4158,7 +4189,13 @@ static int outer_child(
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = remount_idmap(dirs, arg_uid_shift, arg_uid_range, UID_INVALID, UID_INVALID, REMOUNT_IDMAPPING_HOST_ROOT);
|
||||
r = remount_idmap(
|
||||
dirs,
|
||||
arg_uid_shift,
|
||||
arg_uid_range,
|
||||
/* host_owner= */ UID_INVALID,
|
||||
/* dest_owner= */ UID_INVALID,
|
||||
mapping);
|
||||
if (r == -EINVAL || ERRNO_IS_NEG_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
|
||||
|
||||
Reference in New Issue
Block a user