On 10 August 2026 21:49:45 BST, Ricardo Robaina <[email protected]>
wrote:
>On Mon, Aug 10, 2026 at 1:28 PM Bradley Morgan <[email protected]> wrote:
>>
>> On 10 August 2026 16:19:10 BST, Ricardo Robaina <[email protected]>
>> wrote:
>> >On Mon, Aug 10, 2026 at 10:32 AM Bradley Morgan <[email protected]>
>wrote:
>> >>
>> >> Hi Ricardo,
>> >>
>> >> > -     nlh->nlmsg_len = skb->len;
>> >> > +     nlh->nlmsg_len = copy->len;
>> >>
>> >> Fine. skb_copy() does skb_put(n, skb->len) and nothing touches
>> >> copy->len in between, so the two are always identical.
>> >> Which is also why "safer" is a bit of a stretch, it prevents nothing.
>> >> Feel free to bikeshed the changelog wording on that.
>> >>
>> >
>> >Thanks for reviewing this patch, Bradley. I agree with you on the
>wording.
>> >
>>
>> np.
>>
>> >> If you ever want a more interesting cleanup here, the real quirk is
>> >> the line above: the unicast path sets nlmsg_len to skb->len minus
>> >> NLMSG_HDRLEN, this one uses the full length.
>> >
>> >That's interesting, maybe moving the nlmsg_len fixup out of
>> >__audit_log_end() would be better. I'll look into it.
>> >
>>
>> Hmmm.. perhaps it will. I will suggest a fix:
>>
>> From 776375d625cd9cb138f7a6f876861bf428ae1e6c Mon Sep 17 00:00:00 2001
>> From: Bradley Morgan <[email protected]>
>> Date: Mon, 10 Aug 2026 16:26:06 +0000
>> Subject: [PATCH] audit: move the nlmsg_len fixup from __audit_log_end()
>to
>>  send time
>>
>> The auditd breakage (nlmsg_len set to the payload length instead of
>> the full message length) is applied in __audit_log_end() when the
>> record is queued. That forces kauditd_send_multicast_skb() to deep
>> copy every record and undo the length on the copy, so the multicast
>> group still sees a standard netlink message.
>>
>> Instead, finalize the header with the standard full length at queue
>> time and apply the auditd length right before the unicast send in
>> kauditd_send_queue(). Records stay standard netlink messages while
>> they sit in the queues, and the multicast copy no longer needs its
>> own fixup. The deep copy itself stays, since the auditd length
>> rewrite lands in the shared data region after the copy is already
>> handed to the listeners.
>>
>> auditd sees the same bytes as before. The fixup is computed from
>> skb->len, which does not change between queueing and sending, so
>> records that come back through the retry and hold queues get the same
>> value again. Reply and rule list skbs are built with nlmsg_put() and
>> sent on other paths, none of those are touched.
>>
>> This came out of the "use copied skb length" thread, where moving the
>> fixup was suggested as the more interesting cleanup.
>>
>> Signed-off-by: Bradley Morgan <[email protected]>
>> ---
>>  kernel/audit.c | 38 ++++++++++++++++++++++----------------
>>  1 file changed, 22 insertions(+), 16 deletions(-)
>>
>> diff --git a/kernel/audit.c b/kernel/audit.c
>> index 9412af9144bc..5b6528fc6eb5 100644
>> --- a/kernel/audit.c
>> +++ b/kernel/audit.c
>> @@ -802,6 +802,15 @@ static int kauditd_send_queue(struct sock *sk, u32
>portid,
>>                 if (skb_hook)
>>                         (*skb_hook)(skb);
>>
>> +               /*
>> +                * auditd expects nlmsg_len to be the payload length
>rather
>> +                * than the full message length.  Apply the breakage
>here at
>> +                * send time so the record stays a standard netlink
>message
>> +                * while queued and while it is copied for the multicast
>> +                * group above.
>> +                */
>> +               nlmsg_hdr(skb)->nlmsg_len = skb->len - NLMSG_HDRLEN;
>> +
>>                 /* can we send to anyone via unicast? */
>>                 if (!sk) {
>>                         if (err_hook)
>> @@ -849,7 +858,6 @@ static void kauditd_send_multicast_skb(struct
>sk_buff *skb)
>>  {
>>         struct sk_buff *copy;
>>         struct sock *sock = audit_get_sk(&init_net);
>> -       struct nlmsghdr *nlh;
>>
>>         /* NOTE: we are not taking an additional reference for init_net
>since
>>          *       we don't have to worry about it going away */
>> @@ -859,19 +867,15 @@ static void kauditd_send_multicast_skb(struct
>sk_buff *skb)
>>
>>         /*
>>          * The seemingly wasteful skb_copy() rather than bumping the
>refcount
>> -        * using skb_get() is necessary because non-standard mods are
>made to
>> -        * the skb by the original kaudit unicast socket send routine. 
>The
>> -        * existing auditd daemon assumes this breakage.  Fixing this
>would
>> -        * require co-ordinating a change in the established protocol
>between
>> -        * the kaudit kernel subsystem and the auditd userspace code. 
>There is
>> -        * no reason for new multicast clients to continue with this
>> -        * non-compliance.
>> +        * using skb_get() is necessary because the unicast send in
>> +        * kauditd_send_queue() rewrites nlmsg_len to the payload only
>length
>> +        * that auditd expects.  The copy shields the multicast
>listeners from
>> +        * that historical breakage, there is no reason for them to
>continue
>> +        * with this non compliance.
>>          */
>>         copy = skb_copy(skb, GFP_KERNEL);
>>         if (!copy)
>>                 return;
>> -       nlh = nlmsg_hdr(copy);
>> -       nlh->nlmsg_len = skb->len;
>>
>>         nlmsg_multicast(sock, copy, 0, AUDIT_NLGRP_READLOG, GFP_KERNEL);
>>  }
>> @@ -2785,13 +2789,15 @@ int audit_signal_info(int sig, struct
>task_struct *t)
>>   */
>>  static void __audit_log_end(struct sk_buff *skb)
>>  {
>> -       struct nlmsghdr *nlh;
>> -
>>         if (audit_rate_check()) {
>> -               /* setup the netlink header, see the comments in
>> -                * kauditd_send_multicast_skb() for length quirks */
>> -               nlh = nlmsg_hdr(skb);
>> -               nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
>> +               /*
>> +                * The record was built by appending data after
>nlmsg_put()
>> +                * without keeping nlmsg_len up to date, so finalize the
>> +                * header here with the standard full message length. 
>The
>> +                * payload only length that auditd expects is applied at
>> +                * send time in kauditd_send_queue().
>> +                */
>> +               nlmsg_end(skb, nlmsg_hdr(skb));
>>
>>                 /* queue the netlink packet */
>>                 skb_queue_tail(&audit_queue, skb);
>> --
>> 2.47.3
>>
>>
>>
>>
>> >>
>> >> Well, why not, please add:
>> >>
>> >> Reviewed-by: Bradley Morgan <[email protected]>
>> >> Thanks!
>> >>
>> >
>> >-Ricardo
>> >
>> >
>>
>> Thanks!
>>
>
>It looks good to me. I've built a kernel to test it and verified that
>it passes the audit testsuite.
>
># uname -r
>7.2.0-rc6+
>
># make test
>make -C tests test
>chmod +x */test
>Running as   user    root
>        with context unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
>        on   system  Fedora
>
>amcast_joinpart/test ................. ok
>backlog_wait_time_actual_reset/test .. ok
>bpf/test ............................. ok
>coredump/test ........................ ok
>exec_execve/test ..................... ok
>exec_name/test ....................... ok
>fanotify/test ........................ ok
>field_compare/test ................... ok
>file_create/test ..................... ok
>file_delete/test ..................... ok
>file_permission/test ................. ok
>file_rename/test ..................... ok
>filter_device/test ................... ok
>filter_exclude/test .................. ok
>filter_exit/test ..................... ok
>filter_inode/test .................... ok
>filter_saddr_fam/test ................ ok
>filter_sessionid/test ................ ok
>io_uring/test ........................ ok
>login_tty/test ....................... ok
>lost_reset/test ...................... ok
>netfilter_pkt/test ................... ok
>signal/test .......................... ok
>syscalls_file/test ................... ok
>syscall_module/test .................. ok
>syscall_socketcall/test .............. ok
>time_change/test ..................... ok
>user_msg/test ........................ ok
>All tests successful.
>Files=28, Tests=303, 46 wallclock secs ( 0.08 usr  0.03 sys + 14.50
>cusr  1.56 csys = 16.17 CPU)
>Result: PASS
>
>Reviewed-by: Ricardo Robaina <[email protected]>
>Tested-by: Ricardo Robaina <[email protected]>
>
>-Ricardo
>
>

woah, thanks for the review too. so do I like post or will Paul take it

Thanks!

Reply via email to