From 6ebb53d945481b9dc1336b2708d0937a8ca6486f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2023 18:51:03 +0200 Subject: [PATCH] uid-range: optionally load outside view of UID range from uid_map procfs file --- src/basic/uid-range.c | 12 +++++++++--- src/basic/uid-range.h | 11 ++++++++++- src/core/manager.c | 2 +- src/libsystemd/sd-device/device-monitor.c | 2 +- src/test/test-uid-range.c | 4 ++-- src/userdb/userdbctl.c | 4 ++-- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/basic/uid-range.c b/src/basic/uid-range.c index 65504b899a..4c35df5ea8 100644 --- a/src/basic/uid-range.c +++ b/src/basic/uid-range.c @@ -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; } diff --git a/src/basic/uid-range.h b/src/basic/uid-range.h index acfb7191e9..d6b62f2365 100644 --- a/src/basic/uid-range.h +++ b/src/basic/uid-range.h @@ -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); diff --git a/src/core/manager.c b/src/core/manager.c index 0103c582b5..b333be9afd 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -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) diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index 018a68d1db..408cd17581 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -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"); } diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c index e8799e7810..b908cdaf11 100644 --- a/src/test/test-uid-range.c +++ b/src/test/test-uid-range.c @@ -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)); diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index ecbdcb0f41..c16e44d6b6 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -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"); -- 2.25.1