All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Zhenghang Xiao" <kipreyyy@gmail.com>
Cc: "Oleksij Rempel" <o.rempel@pengutronix.de>,
	linux-can@vger.kernel.org,
	"Marc Kleine-Budde" <mkl@pengutronix.de>,
	"Vincent Mailhol" <mailhol@kernel.org>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>
Subject: Re: [PATCH can] can: bcm: add synchronize_rcu() in bcm_delete_rx_op() to fix UAF
Date: Tue, 09 Jun 2026 18:52:57 +0000	[thread overview]
Message-ID: <20260609185258.4F3E41F00898@smtp.kernel.org> (raw)
In-Reply-To: <20260526102349.94074-1-kipreyyy@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] Skipping `bcm_rx_unreg()` when `dev_get_by_index()` returns NULL leaves the CAN receiver registered in the core, leading to a memory leak and Use-After-Free.
- [High] Incorrect list primitives used for RCU-traversed lists (`rx_ops` and `tx_ops`), leading to list corruption and crashes.
- [High] Concurrent modification of an existing RX operation in `bcm_rx_setup()` races with `bcm_rx_handler()`, allowing readers to see partially-written data.
--

commit 27083d45b99681b318907aa96e90787a12c08a58
Author: Zhenghang Xiao <kipreyyy@gmail.com>

can: bcm: add synchronize_rcu() in bcm_delete_rx_op() to fix UAF

This commit adds synchronize_rcu() in bcm_delete_rx_op() before
bcm_remove_op() to ensure all in-flight handlers complete before timers
are cancelled. This prevents a use-after-free where a timer could be
re-armed by a concurrent bcm_rx_handler after being cancelled.

Fixes: f1b4e32aca08 ("can: bcm: use call_rcu() instead of costly synchronize_rcu()")

> diff --git a/net/can/bcm.c b/net/can/bcm.c
> index a4bef2c48a559..ae083f59a9ef5 100644
> --- a/net/can/bcm.c
> +++ b/net/can/bcm.c
> @@ -870,6 +870,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
>  						  bcm_rx_handler, op);
>  
>  			list_del_rcu(&op->list);

[Severity: High]
This isn't a bug introduced by this patch, but looking at the code just
above this addition in bcm_delete_rx_op():

    dev = dev_get_by_index(sock_net(op->sk), op->ifindex);
    if (dev) {
            bcm_rx_unreg(dev, op);
            dev_put(dev);
    }

During device unregistration, unlist_netdevice() makes dev_get_by_index()
return NULL before the NETDEV_UNREGISTER notifier is dispatched.

If user space concurrently closes the socket in bcm_release() or deletes
the RX filter in bcm_delete_rx_op(), these functions check
dev_get_by_index(), see NULL, and bypass calling bcm_rx_unreg().

Does this leave the CAN receiver registered in the core, leaking the
struct receiver and causing a use-after-free when queued frames process
the already freed op pointer?

> +			synchronize_rcu();
>  			bcm_remove_op(op);
>  			return 1; /* done */
>  		}

[Severity: High]
This is a pre-existing issue, but I noticed a potential problem with the
list primitives used for rx_ops and tx_ops in net/can/bcm.c.

In bcm_rx_setup() and bcm_tx_setup(), the code uses list_add():

    list_add(&op->list, &bo->tx_ops);

However, in bcm_proc_show(), the tx_ops list is traversed locklessly:

    list_for_each_entry(op, &bo->tx_ops, list) {

Because list_add() lacks the smp_store_release() memory barriers of
list_add_rcu(), and the traversal doesn't use list_for_each_entry_rcu(),
could this result in readers seeing partially initialized list pointers
and dereferencing a NULL pointer on weakly ordered architectures?

[Severity: High]
This is another pre-existing issue, but there appears to be a race
condition between bcm_rx_setup() and bcm_rx_handler() in net/can/bcm.c.

When bcm_rx_setup() updates an existing RX operation under lock_sock(sk),
it modifies the frames locklessly:

    err = memcpy_from_msg(op->frames, msg, msg_head->nframes * op->cfsiz);
    if (err < 0)
            return err;
    memset(op->last_frames, 0, msg_head->nframes * op->cfsiz);
    op->nframes = msg_head->nframes;

Meanwhile, bcm_rx_handler() accesses these fields in softirq context:

    for (i = 1; i < op->nframes; i++) {
            if ((get_u64(op->frames, 0) & get_u64(rxframe, 0)) ==
                (get_u64(op->frames, 0) &
                 get_u64(op->frames + op->cfsiz * i, 0))) {

Since memcpy_from_msg() can sleep on page faults, could bcm_rx_handler()
read torn or partially overwritten CAN filters, leading to incorrect
message delivery or spurious timer scheduling?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260526102349.94074-1-kipreyyy@gmail.com?part=1

  parent reply	other threads:[~2026-06-09 18:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-26 10:23 [PATCH can] can: bcm: add synchronize_rcu() in bcm_delete_rx_op() to fix UAF Zhenghang Xiao
2026-05-26 10:59 ` Oliver Hartkopp
2026-06-09 18:52 ` sashiko-bot [this message]
2026-06-10  7:29   ` Oliver Hartkopp

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=20260609185258.4F3E41F00898@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=kipreyyy@gmail.com \
    --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 \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.