Appendix 3.C Audit Event Schemas

KACS emits its audit records through KMES with origin class 2 (§2.2). Each event's payload is a msgpack map whose field paths follow PGSS §6.4: access.requested is the key requested inside the map under access, never a key containing a dot, and a value the emitter does not have is absent rather than nil. The shared subject group — the effective token's subject.token.*, the PIP state in subject.pip.*, and the calling process as emitter.process.{pid,name,executable} — is attached at emission time from the resolved call context rather than by the evaluation pipeline (§3.8.9). A process with no executable, such as a kernel thread, has executable left out; the record is still written.

This appendix covers which events KACS emits and from where. The field-by-field payload schemas are in the Peios Events Index, which is canonical for them, and evman <event-type> prints each one.

3.C.1 Event families #

Event typeEmitted by
kacs.audit.access.checkedThe SACL walk, and token audit-policy forcing.
kacs.audit.handle.usedEnforcement points, per operation, against a handle's continuous audit mask.
kacs.audit.privilege.usedPrivilege-use auditing, for the five AccessCheck-influencing privileges in an access check, and at a Linux capability or volume gate (§3.4.1).
kacs.audit.descriptor.changedA change to the descriptor of a file, token, process or System V IPC object (below).
kacs.impersonation.started, kacs.impersonation.revertedAn impersonation attempt, and the end of an impersonation (§3.5.3).
kacs.caap.sacl.skipped, kacs.caap.staging.divergedA CAAP rule SACL that could not be parsed or evaluated; a staged result that differs from the effective one.
kacs.session.destroyedLogonSession teardown (§3.2.7).
kacs.descriptor.rejectedA descriptor xattr that exists but fails structural validation (§3.9.5).
kacs.caap.policy.changedkacs_set_caap installing, replacing or removing a central access policy (§3.8.8).
kacs.mount.policy.changedkacs_set_mount_policy (§3.9.5).
kacs.config.value.rejectedA port reservation table refused whole (§3.12.1).
stratafs.file.copied-upStrataFS copy-up lifecycle and failure (§3.9.7).
stratafs.mutation.refusedA StrataFS arrangement refusal.

kacs.descriptor.rejected carries object.kind file and outcome.reason corrupt. It does not name the file by path: the descriptor is read through internal path anchors whose mount cannot always be resolved to an absolute path, so object.file.path is absent. It names the file by object.file.inode and object.file.device (the filesystem's st_dev) instead, carries the stored attribute's length as object.sd.length, and carries the subject whose access made KACS read the descriptor.

KACS also writes kacs.signature.crypto.failed once at boot when the signature transform is unavailable (§3.6), carrying signature.crypto-stage boot-probe and the negative outcome.errno.

The privilege.name field of a kacs.audit.privilege.used event carries a canonical name. A record of an access check (operation.name access-check) names one of five — SeSecurityPrivilege, SeTakeOwnershipPrivilege, SeBackupPrivilege, SeRestorePrivilege and SeRelabelPrivilege — the only privileges an access check consults. A record of a capability or volume gate (linux-cap, volume-mount) names whichever privilege the gate spent (§3.4.1). The encoder names every defined privilege, and a bit with no name fails it closed rather than emitting an unnamed privilege; a token holding only privileges an access check does not consult produces no access-check record at all.

kacs.audit.handle.used carries an operation.name naming the enforcement point: file.access, file.mmap, file.mprotect, file.permission, file.write, file.ioctl, file.lock, file.fcntl, file.truncate and file.fallocate. It never carries a caller-supplied audit context: its object.kind is always file, with the handle's absolute path in object.file.path (absent only if the path cannot be resolved), and it never sets fields.attestation.userspace.

3.C.2 Descriptor changes #

kacs.audit.descriptor.changed records a change to the descriptor of a file, a token, a process or a System V IPC object by a caller authorised to make it, whether or not the change then applied. A change that includes the SACL is always recorded, whatever either descriptor says — so removing a file's SACL, which leaves nothing to audit the removal itself, is still recorded. Any other change is recorded when the rights it needed overlap the alarm mask on the handle it was made through. Only a file handle opened through FACS carries such a mask, so a change made through a path, or to a token, a process or an IPC object, is recorded only when it includes the SACL.

The record names the object by object.kind and its identity — object.file.path where it can be resolved, object.token.id and .guid, object.process.guid, or object.ipc.type and .id — and describes the change in object.sd: the parts set as components, and the length, SHA-256 digest and owner of the descriptor written (length, digest, owner) and of the one replaced (length-previous, digest-previous, owner-previous; absent where there was no stored descriptor). access.requested is the rights the change needed, with the handle's access.granted, access.audit-mask and the overlap as access.matched — zero when only the SACL made the record exist — for a change made through one. Registry keys have the same record as lcs.audit.key.descriptor.changed.

3.C.3 Delivery #

Audit and privilege-use events are delivered before any result is written back to the caller, and a delivery failure fails the syscall with EIO or EOPNOTSUPP. An audit event cannot be suppressed by handing the call a bad output pointer.

Three emissions are best-effort by contrast, and drop silently rather than failing the operation that caused them:

  • kacs.session.destroyed where the authentication package name is not valid UTF-8.
  • The two StrataFS events on an over-long operation string or path.
  • Any self-emitted payload that would exceed its encoding buffer.

A StrataFS record is not lost for want of memory. When the allocation for the full record fails, a reduced record is written from a fixed buffer instead: the same type with the stratum indices, the operation and the outcome, and without the paths — object.file.path-relative and each stratum.path — whose absence marks it as reduced.

The transport itself — ring buffer delivery, buffering and drop accounting — is KMES's (§2.5, §2.7).

Edit this page