uid-range: optionally load outside view of UID range from uid_map procfs file
authorLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 16:51:03 +0000 (18:51 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 6 Apr 2024 14:08:23 +0000 (16:08 +0200)
src/basic/uid-range.c
src/basic/uid-range.h
src/core/manager.c
src/libsystemd/sd-device/device-monitor.c
src/test/test-uid-range.c
src/userdb/userdbctl.c

index 65504b899ae59ae3175c0b9bfa72399a02a06863..4c35df5ea882c1ce61a3308863eb0c44cda94bd5 100644 (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;
         }
index acfb7191e99253f341a49f5763509eee39d4c84b..d6b62f23651f2ed880c9a22c3cc9e5aafdeadb2d 100644 (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);
index 0103c582b520d1722a032c724e8dd16740c4a69e..b333be9afd8186e9f5d97544b82a36c702e5c91a 100644 (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)
index 018a68d1dbbe490345962889aa6ab6794004f7ca..408cd1758186de071c007c5f2ad2e7161be12073 100644 (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");
         }
index e8799e78100d498c8670b6d757b052406df5565f..b908cdaf1159a170636d254e527037382c2123fe 100644 (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));
index ecbdcb0f41fe19ed49f63ae2675e2a4c94abd7e2..c16e44d6b64248f1c3d8c95a9e4d20e2aa732194 100644 (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");