auditd: fix V0 dispatch truncating last 16 bytes of events - #544
Merged
stevegrubb merged 1 commit intoAug 13, 2026
Merged
Conversation
When log_format=RAW and audisp-syslog is active, the last 16 characters of every kernel audit event were missing from syslog output. For example a USER event ending in "terminal=? res=success'" would appear as "termina" with the rest cut off. The problem was found by comparing the audit.log output (which was complete) with the syslog output (which was truncated). Tracing with strace showed that auditd's write to the plugin pipe was 16 bytes shorter than the write to the log file. Commit ba8ba4f subtracted NLMSG_HDRLEN (16) from nlmsg_len before copying the payload to the dispatcher, assuming nlmsg_len follows the standard netlink convention where it includes the 16-byte header. The kernel audit subsystem does not follow that convention. In audit_log_end() (kernel/audit.c) the kernel sets: nlh->nlmsg_len = skb->len - NLMSG_HDRLEN; This means nlmsg_len is already the payload size, not the total message size. Subtracting NLMSG_HDRLEN again removes 16 bytes of real event data. The kernel documents this as a non-standard choice. The multicast path (kauditd_send_multicast_skb) makes a copy and restores the standard nlmsg_len = skb->len for non-auditd listeners. A netlink probe confirmed this on kernel 6.12: for every event, recvfrom returns nlmsg_len + 16 bytes, meaning nlmsg_len equals the payload size and the extra 16 bytes are the header. Fix: use nlmsg_len directly as the payload size for both kernel and synthetic events, and keep a bounds check against the buffer size. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Cropi <alakatos@redhat.com>
sergio-correia
approved these changes
Aug 11, 2026
sergio-correia
left a comment
Contributor
There was a problem hiding this comment.
Nice catch! The kernel audit subsystem's non-standard nlmsg_len behavior makes this code deceptively tricky, as it is easy to assume standard netlink conventions apply, but
__audit_log_end() deliberately sets nlmsg_len = skb->len - NLMSG_HDRLEN on the unicast path. The old subtraction was a double-subtract bug.
Contributor
|
Thanks. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When log_format=RAW and any audisp plugin (e.g. audisp-syslog) is active,
the last 16 bytes of every kernel audit event are silently dropped before
reaching the plugin pipe. A USER record ending in
terminal=? res=success'shows up in syslog as
terminawith the rest gone.Root cause
Commit ba8ba4f introduced a branch for embedded netlink replies
(
rep->nlh == &rep->msg.nlh) that subtractedNLMSG_HDRLEN(16) fromnlmsg_lenbefore copying the payload, assuming the kernel follows thestandard netlink convention where
nlmsg_len = header + payload.The kernel audit subsystem doesn't follow that convention.
In
kernel/audit.c,__audit_log_end()sets:So
nlmsg_lenis already the payload size. SubtractingNLMSG_HDRLENagaincuts 16 real bytes off every kernel audit event.
The kernel documents this explicitly in
kauditd_send_multicast_skb():The multicast path fixes
nlmsg_lenback toskb->lenfor non-auditdreaders, but the unicast path that auditd reads doesn't.
Fix
Remove the
rep->nlh == &rep->msg.nlhbranch distinction. The kernel alwayssets
nlmsg_lento the payload size, so use it directly with no subtraction.Keep the bounds check against the buffer size.
Tests
test_netlink_payload_length: updated to use payload-onlynlmsg_len,matching how the kernel actually sets it
test_invalid_netlink_length: removed the now-impossible low-bound case(
< NLMSG_HDRLEN)test_realistic_user_event: new -- full USER record payload round-tripthrough V0 dispatch
test_v2_protocol_uses_rep_len: new -- VER2 path usesrep->len, notnlmsg_len; confirms no regression thereHow to reproduce
log_format=RAWand enable audisp-syslogauditctl -m "test message"audit.logvs syslog output -- syslog entries will be exactly16 bytes shorter every time