]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/dynamic-user.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / core / dynamic-user.c
index c627027aaeae5d996a1685e7b467efb5adde24fe..7b00ee4bda0bd7bed5641807601310ed91e89ee8 100644 (file)
 #include "fileio.h"
 #include "fs-util.h"
 #include "io-util.h"
+#include "nscd-flush.h"
 #include "parse-util.h"
 #include "random-util.h"
+#include "serialize.h"
 #include "socket-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -33,7 +35,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) {
         return mfree(d);
 }
 
-static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) {
+static int dynamic_user_add(Manager *m, const char *name, int storage_socket[static 2], DynamicUser **ret) {
         DynamicUser *d;
         int r;
 
@@ -177,7 +179,7 @@ static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) {
          *
          * 1. Initially, we try to read the UID of a number of specified paths. If any of these UIDs works, we use
          *    them. We use in order to increase the chance of UID reuse, if StateDirectory=, CacheDirectory= or
-         *    LogDirectory= are used, as reusing the UID these directories are owned by saves us from having to
+         *    LogsDirectory= are used, as reusing the UID these directories are owned by saves us from having to
          *    recursively chown() them to new users.
          *
          * 2. If that didn't yield a currently unused UID, we hash the user name, and try to use that. This should be
@@ -382,6 +384,7 @@ static int dynamic_user_realize(
         _cleanup_close_ int etc_passwd_lock_fd = -1;
         uid_t num = UID_INVALID; /* a uid if is_user, and a gid otherwise */
         gid_t gid = GID_INVALID; /* a gid if is_user, ignored otherwise */
+        bool flush_cache = false;
         int r;
 
         assert(d);
@@ -470,6 +473,7 @@ static int dynamic_user_realize(
                         }
 
                         /* Great! Nothing is stored here, still. Store our newly acquired data. */
+                        flush_cache = true;
                 } else {
                         /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we
                          * acquired, and use what's stored now. */
@@ -499,6 +503,14 @@ static int dynamic_user_realize(
         if (r < 0)
                 return r;
 
+        if (flush_cache) {
+                /* If we allocated a new dynamic UID, refresh nscd, so that it forgets about potentially cached
+                 * negative entries. But let's do so after we release the /etc/passwd lock, so that there's no
+                 * potential for nscd wanting to lock that for completing the invalidation. */
+                etc_passwd_lock_fd = safe_close(etc_passwd_lock_fd);
+                (void) nscd_flush_cache(STRV_MAKE("passwd", "group"));
+        }
+
         if (is_user) {
                 *ret_uid = num;
                 *ret_gid = gid != GID_INVALID ? gid : num;
@@ -571,6 +583,8 @@ static int dynamic_user_close(DynamicUser *d) {
 
         /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */
         unlink_uid_lock(lock_fd, uid, d->name);
+
+        (void) nscd_flush_cache(STRV_MAKE("passwd", "group"));
         return 1;
 }
 
@@ -607,13 +621,13 @@ int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) {
 
                 copy0 = fdset_put_dup(fds, d->storage_socket[0]);
                 if (copy0 < 0)
-                        return copy0;
+                        return log_error_errno(copy0, "Failed to add dynamic user storage fd to serialization: %m");
 
                 copy1 = fdset_put_dup(fds, d->storage_socket[1]);
                 if (copy1 < 0)
-                        return copy1;
+                        return log_error_errno(copy1, "Failed to add dynamic user storage fd to serialization: %m");
 
-                fprintf(f, "dynamic-user=%s %i %i\n", d->name, copy0, copy1);
+                (void) serialize_item_format(f, "dynamic-user", "%s %i %i", d->name, copy0, copy1);
         }
 
         return 0;
@@ -693,7 +707,7 @@ int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret) {
 
         xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid);
         r = read_one_line_file(lock_path, &user);
-        if (r == -ENOENT)
+        if (IN_SET(r, -ENOENT, 0))
                 return -ESRCH;
         if (r < 0)
                 return r;