journald: pin the sending client's context across native message dispatch

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 22e3a02b9d
This commit is contained in:
Luca Boccassi
2026-07-07 18:01:50 +01:00
parent a977bf4d06
commit 0b4a90765c
+6 -1
View 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) {