#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
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);
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;
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;
}
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);
}
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
(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;
}
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;
* 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)
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;
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;
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
* 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);