mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bradley Morgan <brads@mainlining.org>
To: "Jérémy Jean" <Jeremy.Jean@oss.cyber.gouv.fr>,
	"Paul Moore" <paul@paul-moore.com>,
	"Eric Paris" <eparis@redhat.com>
Cc: audit@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH] audit: fix UAF in kauditd_send_queue()
Date: Sat, 31 Oct 2026 23:56:47 +0000	[thread overview]
Message-ID: <6F0EE0A0-10C3-4B96-AD77-A6952672CDB7@mainlining.org> (raw)
In-Reply-To: <20261031211258.1626829-2-Jeremy.Jean@oss.cyber.gouv.fr>

On 31 October 2026 21:12:59 GMT, "Jérémy Jean"
<Jeremy.Jean@oss.cyber.gouv.fr> wrote:
>kauditd_send_queue() grabs an extra reference to the skb header before
>netlink_unicast() since it may need to retry a failed send. If unicast
>delivery reuses that same header, the receive path stores the
>destination socket in skb->sk without taking a socket reference.
>Consequently, after the receiver consumes the skb and closes the
>socket, the extra reference taken on the skb header makes kauditd
>release a header whose skb->sk points to freed socket storage.
>
>KASAN reports a UAF as:
>
>  BUG: KASAN: slab-use-after-free in sock_rfree+0x44/0x140
>  Write of size 4 at addr ffff888004f94140 by task kauditd/31
>
>Clone the header before netlink_unicast(), then use the clone for
>delivery and keep the original skb only for retries. If cloning fails,
>handle it as -EAGAIN so the send can be retried.
>
>Fixes: f3d357b09295 ("Audit: save audit_backlog_limit audit messages in case auditd comes back")
>Cc: stable@vger.kernel.org

What I cant work out from the changelog is where netlink_trim() went.
With users == 2 it usually clones for you anyway (skb_shared() is just
users != 1) and then the receiver owns a different struct, so this
couldnt happen. Unless it took the early return:

	if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize)
		return skb;

Which one was it? If its the delta side then its the tightly filled
records that trip this, which explains 18 years of silence pretty well.
It also tells us what this costs, where trim would have cloned anyway
you just moved the clone, otherwise you pay one small slab alloc per
record.

>Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
>---
> kernel/audit.c | 11 +++++++----
> 1 file changed, 7 insertions(+), 4 deletions(-)
>
>diff --git a/kernel/audit.c b/kernel/audit.c
>index 9412af9144bc..5e739fa606be 100644
>--- a/kernel/audit.c
>+++ b/kernel/audit.c
>@@ -790,6 +790,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
> {
> 	int rc = 0;
> 	struct sk_buff *skb = NULL;
>+	struct sk_buff *skb_to_send;
> 	struct sk_buff *skb_tail;
> 	unsigned int failed = 0;
> 
>@@ -810,9 +811,11 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
> 		}
> 
> retry:
>-		/* grab an extra skb reference in case of error */
>-		skb_get(skb);
>-		rc = netlink_unicast(sk, skb, portid, 0);
>+		/* Keep the original header unowned for retries. */


A header isnt a skb, and the comment you deleted said skb. Also this
line is where the why belongs, since the why is the bug itself. e.g,

		/* netlink remembers the sock in skb->sk with no ref,
		 * so send a clone and keep the original clean
		 */


>+		skb_to_send = skb_clone(skb, GFP_KERNEL);
>+		/* Preserve the connection on a temporary allocation failure. */

Well, this one doesnt preserve the connection.. -EAGAIN falls into the
same bail branch which does sk = NULL and then squashes rc to 0, so
once the alloc failures hit retry_limit the connection is gone anyway.

It also eats a slot of ++failed for what is really just an ENOMEM and
not a send failure. Might be fine! but the comment says the opposite of
the code, can you make it match?

>+		rc = skb_to_send ?
>+			netlink_unicast(sk, skb_to_send, portid, 0) : -EAGAIN;
> 		if (rc < 0) {
> 			/* send failed - try a few times unless fatal error */
> 			if (++failed >= retry_limit ||
>@@ -827,7 +830,7 @@ retry:
> 			} else
> 				goto retry;
> 		} else {
>-			/* skb sent - drop the extra reference and continue */
>+			/* skb sent - consume the original and continue */
> 			consume_skb(skb);
> 			failed = 0;
> 		}
>

--- Thanks!

  reply	other threads:[~2026-10-31 23:57 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31 21:12 Jérémy Jean
2026-10-31 23:56 ` Bradley Morgan [this message]
2026-11-04 20:36 ` Paul Moore
2026-11-04 21:05   ` Bradley Morgan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6F0EE0A0-10C3-4B96-AD77-A6952672CDB7@mainlining.org \
    --to=brads@mainlining.org \
    --cc=Jeremy.Jean@oss.cyber.gouv.fr \
    --cc=audit@vger.kernel.org \
    --cc=eparis@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®