]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
userdb: introduce USERDB_SYNTHESIZE_NUMERIC flag
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 9 May 2025 02:18:02 +0000 (11:18 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 9 May 2025 03:10:28 +0000 (12:10 +0900)
When the flag is set, even if the specified UID/GID does not exist,
create a synthetic user record for the UID/GID.
Currently, only system UID/GID are supported.

src/shared/userdb.c
src/shared/userdb.h

index 5480caa4cf39c1d1fe8eef03e32e4fd7da1cf310..2972def56a3d18340c8e50a84f541319a1be99f5 100644 (file)
@@ -742,6 +742,31 @@ static int synthetic_foreign_user_build(uid_t foreign_uid, UserRecord **ret) {
                         SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("foreign")));
 }
 
+static int synthetic_numeric_user_build(uid_t uid, UserRecord **ret) {
+        assert(ret);
+
+        if (uid == 0) /* This should be handled by synthetic_root_user_build() */
+                return -ESRCH;
+
+        if (!uid_is_system(uid))
+                return -ESRCH;
+
+        _cleanup_free_ char *un = NULL;
+        if (asprintf(&un, "unknown-" UID_FMT, uid) < 0)
+                return -ENOMEM;
+
+        _cleanup_free_ char *rn = NULL;
+        if (asprintf(&rn, "Unknown System UID " UID_FMT, uid) < 0)
+                return -ENOMEM;
+
+        return user_record_buildo(
+                        ret,
+                        SD_JSON_BUILD_PAIR_STRING("userName", un),
+                        SD_JSON_BUILD_PAIR_STRING("realName", rn),
+                        SD_JSON_BUILD_PAIR_UNSIGNED("uid", uid),
+                        SD_JSON_BUILD_PAIR_STRING("disposition", "system"));
+}
+
 static int user_name_foreign_extract_uid(const char *name, uid_t *ret_uid) {
         int r;
 
@@ -963,6 +988,9 @@ static int userdb_by_uid_fallbacks(
         if (!FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE_FOREIGN) && uid_is_foreign(uid))
                 return synthetic_foreign_user_build(uid - FOREIGN_UID_BASE, ret);
 
+        if (FLAGS_SET(flags, USERDB_SYNTHESIZE_NUMERIC))
+                return synthetic_numeric_user_build(uid, ret);
+
         return -ESRCH;
 }
 
@@ -1232,6 +1260,31 @@ static int synthetic_foreign_group_build(gid_t foreign_gid, GroupRecord **ret) {
                         SD_JSON_BUILD_PAIR("disposition", JSON_BUILD_CONST_STRING("foreign")));
 }
 
+static int synthetic_numeric_group_build(gid_t gid, GroupRecord **ret) {
+        assert(ret);
+
+        if (gid == 0) /* This should be handled by synthetic_root_group_build() */
+                return -ESRCH;
+
+        if (!gid_is_system(gid))
+                return -ESRCH;
+
+        _cleanup_free_ char *gn = NULL;
+        if (asprintf(&gn, "unknown-" GID_FMT, gid) < 0)
+                return -ENOMEM;
+
+        _cleanup_free_ char *d = NULL;
+        if (asprintf(&d, "Unknown System GID " UID_FMT, gid) < 0)
+                return -ENOMEM;
+
+        return group_record_buildo(
+                        ret,
+                        SD_JSON_BUILD_PAIR_STRING("groupName", gn),
+                        SD_JSON_BUILD_PAIR_STRING("description", d),
+                        SD_JSON_BUILD_PAIR_UNSIGNED("gid", gid),
+                        SD_JSON_BUILD_PAIR_STRING("disposition", "system"));
+}
+
 static int query_append_gid_match(sd_json_variant **query, const UserDBMatch *match) {
         int r;
 
@@ -1387,6 +1440,9 @@ static int groupdb_by_gid_fallbacks(
         if (!FLAGS_SET(flags, USERDB_DONT_SYNTHESIZE_FOREIGN) && gid_is_foreign(gid))
                 return synthetic_foreign_group_build(gid - FOREIGN_UID_BASE, ret);
 
+        if (FLAGS_SET(flags, USERDB_SYNTHESIZE_NUMERIC))
+                return synthetic_numeric_group_build(gid, ret);
+
         return -ESRCH;
 }
 
index 783e39d59112ed28562a6e0a1bd1f6d324e2f0b1..683b94a6df44db65ba89186fec2e879ceff2cb8e 100644 (file)
@@ -32,6 +32,7 @@ typedef enum UserDBFlags {
         USERDB_DROPIN_ONLY = USERDB_EXCLUDE_NSS|USERDB_EXCLUDE_VARLINK|USERDB_DONT_SYNTHESIZE_INTRINSIC|USERDB_DONT_SYNTHESIZE_FOREIGN,
 
         USERDB_PARSE_NUMERIC             = 1 << 8,  /* if a numeric UID is specified as name, parse it and look up by UID/GID */
+        USERDB_SYNTHESIZE_NUMERIC        = 1 << 8,  /* synthesize system UID/GID even if it does not exist */
 } UserDBFlags;
 
 /* Well-known errors we'll return here: