7.6 The Write Path
The three write paths establish provenance differently because their inputs come from different places.
7.6.1 Events #
Emission is KMES's business. kmes_emit and kmes_emit_batch require
SeAuditPrivilege, and eventd is not in the admission path — it consumes
what KMES delivers (§2.2).
The identity stamps on an event are the kernel's, captured from kernel
state at the write. An emitting process cannot set, influence or
suppress them.
That is what makes an event's emitter.process.guid evidence, and why
a payload value at that path never shadows it (PSPU §3.22).
7.6.2 Logs use peinit as a broker #
Service processes do not reach the log socket.
eventd replaces the
inherited DACL on LogSocketPath with this protected DACL before
its first receive:
D:P(D;;0x2;;;SU)(A;;GA;;;SY)(A;;GA;;;OW)
It sets the DACL alone. The socket stays owned by the service SID of
eventd's own virtual Service identity, which created it, and the OW
allow lets that owner manage it; making SYSTEM the owner would need a
privilege the long-running daemon deliberately does not hold.
SU is the Service logon group, S-1-5-6. Every phase-2 service token,
including a SYSTEM service token, carries it. peinit's bootstrap SYSTEM
token does not. The deny is evaluated before the SYSTEM allow, so a
service cannot write merely because its user SID is SYSTEM; peinit can.
peinit determines origin from the output pipe it is draining and may
batch records from several origins in one datagram.
eventd
therefore
does not request or check a KACS token for each log datagram.
The socket
admission attests the broker and the broker attests the origin, without
token-fd churn or an AccessCheck on the log hot path.
A log origin proves which service context peinit associated with the line. It does not prove that the line's message is truthful.
7.6.3 Metrics carry the producer token #
Every authenticated caller may send to the metric socket: eventd replaces
the descriptor it would inherit from its closed runtime directory with
D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)(A;;FW;;;AU).
Who may publish what is decided below, per metric name, against the
token each datagram carries, so a socket that admitted fewer callers
would only leave a grant of EVENTD_PUBLISH to anyone else unusable.
The cost of an open socket is that anyone signed in can send datagrams,
and the socket is lossy (§9.1): a caller sending in bulk can crowd out
other producers' samples, though none of its own unauthorized records
is stored. An operator who wants the socket narrower sets another
descriptor on it after eventd starts, for example with sd set. eventd
sets its own again each time it starts.
A metric producer enables KACS_SO_PASS_TOKEN once on its persistent
sending socket. KACS attaches the producer's effective identity to each
datagram as KACS_SCM_TOKEN. eventd uses recvmsg with room for exactly
one token and no ordinary file descriptors.
eventd discards the whole datagram before MessagePack parsing when:
- no token arrived
- the data was truncated
- the ancillary data was truncated
- querying the token or resolving policy failed
For a valid datagram, eventd resolves each record's metric name through
the ordinary hierarchical Metrics descriptor namespace (§7.2) and runs
AccessCheck against the conveyed token for EVENTD_PUBLISH.
A denied
record is discarded; authorized sibling records in the same datagram
continue.
The wildcard Metrics descriptor grants EVENTD_PUBLISH to SYSTEM and
Administrators, not Authenticated Users. A package that owns a metric
prefix installs a more-specific descriptor granting its service SID
that right. Existing wildcard descriptors that exactly match eventd's
old read-only default are upgraded in place; administrator-modified
descriptors are never rewritten.
Authorization covers the metric name, not its labels or value. An authorized producer can create arbitrarily many valid label sets under that name (§5.3).
7.6.4 The publication cache #
A full AccessCheck is not performed per sample or per datagram. The metric ingestion thread owns a bounded verdict cache keyed by:
(token_id, modified_id, concrete metric name)
KACS reuses the captured token object while a persistent sender socket keeps the same effective identity, so ordinary traffic repeatedly hits the same entry. A hit performs no allocation and no AccessCheck.
MetricAuthorizationCacheSize bounds the total entry count.
When full,
eventd clears the cache rather than maintaining an LRU list on the write
path.
This makes churn expensive for the producer causing it without
adding pointer updates to every successful lookup.
The descriptor cache carries a generation. Any security-registry change advances it and clears all local publication verdicts before they are reused. The cache stores denials as well as grants, so repeatedly sending an unauthorized name does not repeatedly invoke KACS.
7.6.5 Rejected input #
Missing identity, truncation, denied records and policy errors increment
in-memory diagnostic counters.
Policy errors may produce rate-limited
standard-error text.
None produces a durable event or log record of eventd's own: doing
work proportional to hostile input would create an amplification path
(PSPU §3.4).
The one record a denial can cause is KACS's: under a descriptor whose
SACL audits failure, as every default does (§7.2), the publication check
that denies a name writes a kacs.audit.access.checked record. Denials
are cached like grants, so that is one record per token and name until
the cache is cleared, not one per datagram.