]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journald: pin the sending client's context across native message dispatch
authorLuca Boccassi <luca.boccassi@gmail.com>
Tue, 7 Jul 2026 10:58:14 +0000 (11:58 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 7 Jul 2026 17:01:50 +0000 (18:01 +0100)
manager_process_native_message() looks up the sender's ClientContext with
client_context_get(), which does not pin it.

A native message may carry an OBJECT_PID=, which makes
manager_dispatch_message_real() perform a nested client_context_get() for that
PID. On a cache miss this runs client_context_try_shrink_to(), whose pid-flush
branch frees every unpinned cache entry whose PID has already been reaped,
including the borrowed sender context. manager_dispatch_message_real() then keeps
using it (it reads c->uid, and the built iovecs still alias the context's
fields).

Pin the sender context with client_context_acquire() for the duration of the
dispatch and release it afterwards, mirroring what the stdout stream path
already does.

Follow-up for 22e3a02b9d618bbebcf987bc1411acda367271ec

src/journal/journald-native.c

index 1c36ca9434fa43ac1ddb32c299d676d9aa852052..01e7d65453d6aa026f9a98272ce0780e9854bc81 100644 (file)
@@ -319,7 +319,10 @@ void manager_process_native_message(
         assert(buffer || buffer_size == 0);
 
         if (ucred && pid_is_valid(ucred->pid)) {
-                r = client_context_get(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
+                /* Pin the sender's context for the whole dispatch below, as processing an entry may look up
+                 * further contexts (e.g. for an OBJECT_PID=), which can flush already reaped entries from
+                 * the cache */
+                r = client_context_acquire(m, ucred->pid, ucred, label, /* unit_id= */ NULL, &context);
                 if (r < 0)
                         log_ratelimit_warning_errno(r, JOURNAL_LOG_RATELIMIT,
                                                     "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m",
@@ -331,6 +334,8 @@ void manager_process_native_message(
                                          (const uint8_t*) buffer + (buffer_size - remaining), &remaining,
                                          context, ucred, tv, label);
         } while (r == 0);
+
+        client_context_release(m, context);
 }
 
 static size_t entry_size_max_by_ucred(Manager *m, const struct ucred *ucred, const char *label) {