]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/uid-range: add uid_map_read_one helper
authorMike Yuan <me@yhndnzj.com>
Thu, 14 Dec 2023 15:55:43 +0000 (23:55 +0800)
committerMike Yuan <me@yhndnzj.com>
Fri, 15 Dec 2023 13:22:51 +0000 (21:22 +0800)
src/basic/uid-range.c
src/basic/uid-range.h
src/basic/virt.c
src/machine/machine.c

index 846359927612a22532f9435dedc902b4b2ddada0..d933d9fa5c1faf0c3e377423f1e6eb3c37c4edea 100644 (file)
@@ -180,6 +180,30 @@ bool uid_range_covers(const UidRange *range, uid_t start, uid_t nr) {
         return false;
 }
 
+int uid_map_read_one(FILE *f, uid_t *ret_base, uid_t *ret_shift, uid_t *ret_range) {
+        uid_t uid_base, uid_shift, uid_range;
+        int r;
+
+        assert(f);
+        assert(ret_base);
+        assert(ret_shift);
+        assert(ret_range);
+
+        errno = 0;
+        r = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
+        if (r == EOF)
+                return errno_or_else(ENOMSG);
+        assert(r >= 0);
+        if (r != 3)
+                return -EBADMSG;
+
+        *ret_base = uid_base;
+        *ret_shift = uid_shift;
+        *ret_range = uid_range;
+
+        return 0;
+}
+
 int uid_range_load_userns(UidRange **ret, const char *path) {
         _cleanup_(uid_range_freep) UidRange *range = NULL;
         _cleanup_fclose_ FILE *f = NULL;
@@ -212,18 +236,12 @@ int uid_range_load_userns(UidRange **ret, const char *path) {
 
         for (;;) {
                 uid_t uid_base, uid_shift, uid_range;
-                int k;
-
-                errno = 0;
-                k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
-                if (k == EOF) {
-                        if (ferror(f))
-                                return errno_or_else(EIO);
 
+                r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+                if (r == -ENOMSG)
                         break;
-                }
-                if (k != 3)
-                        return -EBADMSG;
+                if (r < 0)
+                        return r;
 
                 r = uid_range_add_internal(&range, uid_base, uid_range, /* coalesce = */ false);
                 if (r < 0)
index 461a5117373bbe2c12c4d2c78122af7d9b81a8a9..bfe78926698c150cb8b4b0d554c956783c4e51d5 100644 (file)
@@ -31,4 +31,6 @@ static inline bool uid_range_contains(const UidRange *range, uid_t uid) {
         return uid_range_covers(range, uid, 1);
 }
 
+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);
index a0b6fbcd658c230c49930186a7c6683c70d34f42..09aebabcd5e35a4d3fc503eb202a531dd86d60d9 100644 (file)
@@ -21,6 +21,7 @@
 #include "stat-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "uid-range.h"
 #include "virt.h"
 
 enum {
@@ -814,7 +815,7 @@ Virtualization detect_virtualization(void) {
 
 static int userns_has_mapping(const char *name) {
         _cleanup_fclose_ FILE *f = NULL;
-        uid_t a, b, c;
+        uid_t base, shift, range;
         int r;
 
         f = fopen(name, "re");
@@ -823,26 +824,22 @@ static int userns_has_mapping(const char *name) {
                 return errno == ENOENT ? false : -errno;
         }
 
-        errno = 0;
-        r = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &a, &b, &c);
-        if (r == EOF) {
-                if (ferror(f))
-                        return log_debug_errno(errno_or_else(EIO), "Failed to read %s: %m", name);
-
-                log_debug("%s is empty, we're in an uninitialized user namespace", name);
+        r = uid_map_read_one(f, &base, &shift, &range);
+        if (r == -ENOMSG) {
+                log_debug("%s is empty, we're in an uninitialized user namespace.", name);
                 return true;
         }
-        if (r != 3)
-                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse %s: %m", name);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to read %s: %m", name);
 
-        if (a == 0 && b == 0 && c == UINT32_MAX) {
+        if (base == 0 && shift == 0 && range == UINT32_MAX) {
                 /* The kernel calls mappings_overlap() and does not allow overlaps */
                 log_debug("%s has a full 1:1 mapping", name);
                 return false;
         }
 
         /* Anything else implies that we are in a user namespace */
-        log_debug("Mapping found in %s, we're in a user namespace", name);
+        log_debug("Mapping found in %s, we're in a user namespace.", name);
         return true;
 }
 
index 44ff5c190bb479d2b4179bebc28bdb52f59e2959..1939843b643bd2e1ac5c824fa30966a9034c5521 100644 (file)
@@ -32,6 +32,7 @@
 #include "string-table.h"
 #include "terminal-util.h"
 #include "tmpfile-util.h"
+#include "uid-range.h"
 #include "unit-name.h"
 #include "user-util.h"
 
@@ -690,14 +691,9 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
         }
 
         /* Read the first line. There's at least one. */
-        errno = 0;
-        k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
-        if (k != 3) {
-                if (ferror(f))
-                        return errno_or_else(EIO);
-
-                return -EBADMSG;
-        }
+        r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+        if (r < 0)
+                return r;
 
         /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */
         if (uid_base != 0)
@@ -757,6 +753,7 @@ static int machine_owns_uid_internal(
 
         _cleanup_fclose_ FILE *f = NULL;
         const char *p;
+        int r;
 
         /* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
         assert_cc(sizeof(uid_t) == sizeof(gid_t));
@@ -778,18 +775,12 @@ static int machine_owns_uid_internal(
 
         for (;;) {
                 uid_t uid_base, uid_shift, uid_range, converted;
-                int k;
 
-                errno = 0;
-                k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
-                if (k < 0 && feof(f))
+                r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+                if (r == -ENOMSG)
                         break;
-                if (k != 3) {
-                        if (ferror(f))
-                                return errno_or_else(EIO);
-
-                        return -EIO;
-                }
+                if (r < 0)
+                        return r;
 
                 /* The private user namespace is disabled, ignoring. */
                 if (uid_shift == 0)
@@ -831,6 +822,7 @@ static int machine_translate_uid_internal(
 
         _cleanup_fclose_ FILE *f = NULL;
         const char *p;
+        int r;
 
         /* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
         assert_cc(sizeof(uid_t) == sizeof(gid_t));
@@ -850,18 +842,12 @@ static int machine_translate_uid_internal(
 
         for (;;) {
                 uid_t uid_base, uid_shift, uid_range, converted;
-                int k;
 
-                errno = 0;
-                k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
-                if (k < 0 && feof(f))
+                r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+                if (r == -ENOMSG)
                         break;
-                if (k != 3) {
-                        if (ferror(f))
-                                return errno_or_else(EIO);
-
-                        return -EIO;
-                }
+                if (r < 0)
+                        return r;
 
                 if (uid < uid_base || uid >= uid_base + uid_range)
                         continue;
@@ -872,6 +858,7 @@ static int machine_translate_uid_internal(
 
                 if (ret_host_uid)
                         *ret_host_uid = converted;
+
                 return 0;
         }