uid-range: optionally load outside view of UID range from uid_map procfs file

This commit is contained in:
Lennart Poettering
2023-04-20 18:51:03 +02:00
parent 5bff40e719
commit 6ebb53d945
6 changed files with 25 additions and 10 deletions

View File

@@ -204,7 +204,7 @@ int uid_map_read_one(FILE *f, uid_t *ret_base, uid_t *ret_shift, uid_t *ret_rang
return 0;
}
int uid_range_load_userns(UIDRange **ret, const char *path) {
int uid_range_load_userns(UIDRange **ret, const char *path, UIDRangeUsernsMode mode) {
_cleanup_(uid_range_freep) UIDRange *range = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -216,9 +216,11 @@ int uid_range_load_userns(UIDRange **ret, const char *path) {
* To simplify things this will modify the passed array in case of later failure. */
assert(ret);
assert(mode >= 0);
assert(mode < _UID_RANGE_USERNS_MODE_MAX);
if (!path)
path = "/proc/self/uid_map";
path = IN_SET(mode, UID_RANGE_USERNS_INSIDE, UID_RANGE_USERNS_OUTSIDE) ? "/proc/self/uid_map" : "/proc/self/gid_map";
f = fopen(path, "re");
if (!f) {
@@ -243,7 +245,11 @@ int uid_range_load_userns(UIDRange **ret, const char *path) {
if (r < 0)
return r;
r = uid_range_add_internal(&range, uid_base, uid_range, /* coalesce = */ false);
r = uid_range_add_internal(
&range,
IN_SET(mode, UID_RANGE_USERNS_INSIDE, GID_RANGE_USERNS_INSIDE) ? uid_base : uid_shift,
uid_range,
/* coalesce = */ false);
if (r < 0)
return r;
}

View File

@@ -33,6 +33,15 @@ static inline bool uid_range_contains(const UIDRange *range, uid_t uid) {
int uid_map_read_one(FILE *f, uid_t *ret_base, uid_t *ret_shift, uid_t *ret_range);
int uid_range_load_userns(UIDRange **ret, const char *path);
typedef enum UIDRangeUsernsMode {
UID_RANGE_USERNS_INSIDE,
UID_RANGE_USERNS_OUTSIDE,
GID_RANGE_USERNS_INSIDE,
GID_RANGE_USERNS_OUTSIDE,
_UID_RANGE_USERNS_MODE_MAX,
_UID_RANGE_USERNS_MODE_INVALID = -EINVAL,
} UIDRangeUsernsMode;
int uid_range_load_userns(UIDRange **ret, const char *path, UIDRangeUsernsMode mode);
bool uid_range_overlaps(const UIDRange *range, uid_t start, uid_t nr);

View File

@@ -4805,7 +4805,7 @@ static int short_uid_range(const char *path) {
/* Taint systemd if we the UID range assigned to this environment doesn't at least cover 0…65534,
* i.e. from root to nobody. */
r = uid_range_load_userns(&p, path);
r = uid_range_load_userns(&p, path, UID_RANGE_USERNS_INSIDE);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return false;
if (r < 0)

View File

@@ -473,7 +473,7 @@ static bool check_sender_uid(sd_device_monitor *m, uid_t uid) {
return true;
if (!m->mapped_userns_uid_range) {
r = uid_range_load_userns(&m->mapped_userns_uid_range, NULL);
r = uid_range_load_userns(&m->mapped_userns_uid_range, NULL, UID_RANGE_USERNS_INSIDE);
if (r < 0)
log_monitor_errno(m, r, "Failed to load UID ranges mapped to the current user namespace, ignoring: %m");
}

View File

@@ -100,7 +100,7 @@ TEST(load_userns) {
_cleanup_fclose_ FILE *f = NULL;
int r;
r = uid_range_load_userns(&p, NULL);
r = uid_range_load_userns(&p, NULL, UID_RANGE_USERNS_INSIDE);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return;
@@ -123,7 +123,7 @@ TEST(load_userns) {
p = uid_range_free(p);
assert_se(uid_range_load_userns(&p, fn) >= 0);
assert_se(uid_range_load_userns(&p, fn, UID_RANGE_USERNS_INSIDE) >= 0);
assert_se(uid_range_contains(p, 0));
assert_se(uid_range_contains(p, 19));

View File

@@ -428,7 +428,7 @@ static int display_user(int argc, char *argv[], void *userdata) {
_cleanup_(uid_range_freep) UIDRange *uid_range = NULL;
int boundary_lines, uid_map_lines;
r = uid_range_load_userns(&uid_range, "/proc/self/uid_map");
r = uid_range_load_userns(&uid_range, "/proc/self/uid_map", UID_RANGE_USERNS_INSIDE);
if (r < 0)
log_debug_errno(r, "Failed to load /proc/self/uid_map, ignoring: %m");
@@ -731,7 +731,7 @@ static int display_group(int argc, char *argv[], void *userdata) {
_cleanup_(uid_range_freep) UIDRange *gid_range = NULL;
int boundary_lines, gid_map_lines;
r = uid_range_load_userns(&gid_range, "/proc/self/gid_map");
r = uid_range_load_userns(&gid_range, "/proc/self/gid_map", UID_RANGE_USERNS_INSIDE);
if (r < 0)
log_debug_errno(r, "Failed to load /proc/self/gid_map, ignoring: %m");