Linux CAN drivers development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tristan Madani" <tristmd@gmail.com>
Cc: linux-can@vger.kernel.org,
	"Marc Kleine-Budde" <mkl@pengutronix.de>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>,
	"Vincent Mailhol" <mailhol@kernel.org>,
	"Oleksij Rempel" <o.rempel@pengutronix.de>
Subject: Re: [PATCH net] can: j1939: fix skb refcount underflow in session teardown paths
Date: Mon, 02 Nov 2026 16:01:47 +0000	[thread overview]
Message-ID: <sashiko-outbox-193720@kernel.org> (raw)
In-Reply-To: <20261102155345.1267524-1-tristan@talencesecurity.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] can: j1939: skb and sock leak in j1939_session_destroy() and j1939_session_skb_drop_old()
--

commit 48d3734ee23304ec7eb1426db9d761018f0ff9d3
Author: Tristan Madani <tristmd@gmail.com>

can: j1939: fix skb refcount underflow in session teardown paths

This commit removes the explicit skb_unref() calls before kfree_skb() in
j1939_session_destroy() and j1939_session_skb_drop_old() to avoid a
refcount underflow.

> diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
> index 8fcfd13e5e6f8..3173936bd6f6e 100644
> --- a/net/can/j1939/transport.c
> +++ b/net/can/j1939/transport.c
> @@ -277,11 +277,8 @@ static void j1939_session_destroy(struct j1939_session *session)
>  	WARN_ON_ONCE(!list_empty(&session->sk_session_queue_entry));
>  	WARN_ON_ONCE(!list_empty(&session->active_session_list_entry));
>  
> -	while ((skb = skb_dequeue(&session->skb_queue)) != NULL) {
> -		/* drop ref taken in j1939_session_skb_queue() */
> -		skb_unref(skb);
> +	while ((skb = skb_dequeue(&session->skb_queue)) != NULL)
>  		kfree_skb(skb);
> -	}
>  	__j1939_session_drop(session);
>  	netdev_put(session->priv->ndev, &session->priv_dev_tracker);
>  	j1939_priv_put(session->priv);
> @@ -342,8 +339,6 @@ static void j1939_session_skb_drop_old(struct j1939_session *session)
>  
>  	if ((do_skcb->offset + do_skb->len) < offset_start) {
>  		__skb_unlink(do_skb, &session->skb_queue);
> -		/* drop ref taken in j1939_session_skb_queue() */
> -		skb_unref(do_skb);
>  		spin_unlock_irqrestore(&session->skb_queue.lock, flags);
>  
>  		kfree_skb(do_skb);

[Severity: High]
Does removing skb_unref() in j1939_session_destroy() and
j1939_session_skb_drop_old() leak every session-queued sk_buff and its
associated socket reference?

Every sk_buff queued into session->skb_queue starts with skb->users set to 1
from allocation (via alloc_skb() in j1939_session_fresh_new() for RX
sessions, or j1939_sk_alloc_skb() in j1939_sk_send_loop() for TX sessions).

When the initial skb is queued in j1939_session_new(), it takes a second
reference while callers do not drop the initial allocation reference on
success:

net/can/j1939/transport.c:j1939_session_new() {
	...
	skb_queue_head_init(&session->skb_queue);
	skb_queue_tail(&session->skb_queue, skb_get(skb));
	...
}

net/can/j1939/transport.c:j1939_session_fresh_new() {
	...
	skb = alloc_skb(size + sizeof(struct can_skb_priv), GFP_ATOMIC);
	...
	session = j1939_session_new(priv, skb, size);
	if (!session) {
		kfree_skb(skb);
		return NULL;
	}

	/* alloc data area */
	skb_put_zero(skb, size);
	/* skb is recounted in j1939_session_new() */
	return session;
}

Similarly, in net/can/j1939/socket.c, j1939_sk_send_loop() allocates each TX
segment skb with skb->users == 1 and passes it to j1939_tp_send() ->
j1939_session_new() or to j1939_session_skb_queue(), which also increments
skb->users to 2 without the caller dropping the initial reference:

net/can/j1939/transport.c:j1939_session_skb_queue() {
	...
	skb_get(skb);
	skb_queue_tail(&session->skb_queue, skb);
	...
}

Because transient users of the queued skbs (such as j1939_session_tx_dat(),
j1939_simple_txnext(), j1939_session_completed(), and
j1939_xtp_rx_dat_one()) acquire their own reference via
j1939_session_skb_get_by_offset() or j1939_session_skb_get() and balance it
with consume_skb() or kfree_skb(), every skb resting in session->skb_queue
has a refcount of 2.

Without the skb_unref() calls in j1939_session_destroy() and
j1939_session_skb_drop_old() (or alternatively removing the extra skb_get()
in j1939_session_new() and j1939_session_skb_queue()), won't kfree_skb()
only decrement skb->users from 2 to 1, leaking the sk_buff and preventing
sock_wfree() from ever releasing sk->sk_wmem_alloc and the struct sock
reference on TX sessions?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102155345.1267524-1-tristan@talencesecurity.com?part=1

  reply	other threads:[~2026-11-02 16:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 15:53 [PATCH net] can: j1939: fix skb refcount underflow in session teardown paths Tristan Madani
2026-11-02 16:01 ` sashiko-bot [this message]
2026-11-04  4:50 ` netdev-bot+sashiko
2026-11-04 13:01   ` Tristan Madani

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=sashiko-outbox-193720@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-can@vger.kernel.org \
    --cc=mailhol@kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=o.rempel@pengutronix.de \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=socketcan@hartkopp.net \
    --cc=tristmd@gmail.com \
    /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