mountfsd: Relax user namespace checks
- Allow foreign UID range - Allow delegated UID ranges Both of these can now be mapped by nsresourced into user namespaces and hence should be accepted by mountfsd.
This commit is contained in:
+41
-11
@@ -1208,30 +1208,60 @@ static int vl_method_mount_directory(
|
||||
uid_t start;
|
||||
|
||||
if (userns_fd >= 0) {
|
||||
/* Load ranges without coalescing to preserve the 1:1 correspondence
|
||||
* between inside and outside entries */
|
||||
_cleanup_(uid_range_freep) UIDRange *uid_range_outside = NULL, *uid_range_inside = NULL, *gid_range_outside = NULL, *gid_range_inside = NULL;
|
||||
r = uid_range_load_userns_by_fd(userns_fd, UID_RANGE_USERNS_OUTSIDE, &uid_range_outside);
|
||||
r = uid_range_load_userns_by_fd_full(userns_fd, UID_RANGE_USERNS_OUTSIDE, /* coalesce= */ false, &uid_range_outside);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load outside UID range of provided userns: %m");
|
||||
r = uid_range_load_userns_by_fd(userns_fd, UID_RANGE_USERNS_INSIDE, &uid_range_inside);
|
||||
|
||||
r = uid_range_load_userns_by_fd_full(userns_fd, UID_RANGE_USERNS_INSIDE, /* coalesce= */ false, &uid_range_inside);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load inside UID range of provided userns: %m");
|
||||
r = uid_range_load_userns_by_fd(userns_fd, GID_RANGE_USERNS_OUTSIDE, &gid_range_outside);
|
||||
|
||||
r = uid_range_load_userns_by_fd_full(userns_fd, GID_RANGE_USERNS_OUTSIDE, /* coalesce= */ false, &gid_range_outside);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load outside GID range of provided userns: %m");
|
||||
r = uid_range_load_userns_by_fd(userns_fd, GID_RANGE_USERNS_INSIDE, &gid_range_inside);
|
||||
|
||||
r = uid_range_load_userns_by_fd_full(userns_fd, GID_RANGE_USERNS_INSIDE, /* coalesce= */ false, &gid_range_inside);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load inside GID range of provided userns: %m");
|
||||
|
||||
/* Be very strict for now */
|
||||
/* UID and GID mappings must match */
|
||||
if (!uid_range_equal(uid_range_outside, gid_range_outside) ||
|
||||
!uid_range_equal(uid_range_inside, gid_range_inside) ||
|
||||
uid_range_outside->n_entries != 1 ||
|
||||
uid_range_outside->entries[0].nr != 0x10000 ||
|
||||
uid_range_inside->n_entries != 1 ||
|
||||
uid_range_inside->entries[0].start != 0 ||
|
||||
uid_range_inside->entries[0].nr != 0x10000)
|
||||
!uid_range_equal(uid_range_inside, gid_range_inside))
|
||||
return sd_varlink_error_invalid_parameter_name(link, "userNamespaceFileDescriptor");
|
||||
|
||||
/* Must have at least one entry, and inside/outside must have matching entry counts */
|
||||
if (uid_range_is_empty(uid_range_outside) ||
|
||||
uid_range_outside->n_entries != uid_range_inside->n_entries)
|
||||
return sd_varlink_error_invalid_parameter_name(link, "userNamespaceFileDescriptor");
|
||||
|
||||
/* The first range must be a root UID in the transient range (i.e. aligned
|
||||
* to a 64K boundary) and mapped to 0 inside the user namespace (size 65536) */
|
||||
if (!uid_is_transient(uid_range_outside->entries[0].start) ||
|
||||
(uid_range_outside->entries[0].start & 0xFFFFU) != 0 ||
|
||||
uid_range_outside->entries[0].nr != NSRESOURCE_UIDS_64K ||
|
||||
uid_range_inside->entries[0].start != 0 ||
|
||||
uid_range_inside->entries[0].nr != NSRESOURCE_UIDS_64K)
|
||||
return sd_varlink_error_invalid_parameter_name(link, "userNamespaceFileDescriptor");
|
||||
|
||||
/* All remaining entries must also be root UIDs in the transient range and
|
||||
* mapped 1:1, which identifies them as delegated ranges. The last entry
|
||||
* may also be the root UID in the foreign UID range. */
|
||||
for (size_t i = 1; i < uid_range_outside->n_entries; i++) {
|
||||
bool is_last = i + 1 == uid_range_outside->n_entries;
|
||||
uid_t entry_start = uid_range_outside->entries[i].start;
|
||||
|
||||
if (!(uid_is_transient(entry_start) ||
|
||||
(is_last && uid_is_foreign(entry_start))) ||
|
||||
(entry_start & 0xFFFFU) != 0 ||
|
||||
uid_range_outside->entries[i].nr != NSRESOURCE_UIDS_64K ||
|
||||
uid_range_outside->entries[i].start != uid_range_inside->entries[i].start ||
|
||||
uid_range_outside->entries[i].nr != uid_range_inside->entries[i].nr)
|
||||
return sd_varlink_error_invalid_parameter_name(link, "userNamespaceFileDescriptor");
|
||||
}
|
||||
|
||||
start = uid_range_outside->entries[0].start;
|
||||
} else
|
||||
start = 0;
|
||||
|
||||
Reference in New Issue
Block a user