From: sashiko-bot@kernel.org
To: "Dmitry Antipov" <dmantipov@yandex.ru>
Cc: linux-can@vger.kernel.org,
"Oleksij Rempel" <o.rempel@pengutronix.de>,
"Oliver Hartkopp" <socketcan@hartkopp.net>,
"Marc Kleine-Budde" <mkl@pengutronix.de>,
"Vincent Mailhol" <mailhol@kernel.org>
Subject: Re: [PATCH v3 1/2] can: j1939: make hrtimer callback lockless and free ECUs asyncronously
Date: Fri, 28 Aug 2026 07:08:24 +0000 [thread overview]
Message-ID: <20260828070825.559901F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260828064621.91364-1-dmantipov@yandex.ru>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Missing bottom-half disable in __j1939_ecu_work() causes a deadlock with softirq RX handlers.
- [High] Lockless read-modify-write of ent->nusers in j1939_ecu_map_atomic() causes lost updates and accounting corruption.
- [High] Asynchronous ECU removal work is not flushed on module unload, causing use-after-free panics.
- [High] Publish-before-initialize TOCTOU race in j1939_ecu_map_atomic() exposes the ECU pointer before taking a reference.
- [High] Delayed removal from the ECU list causes concurrent list traversals to encounter an ECU with a zero reference count.
--
commit ff05e907d647c94fe0051f49164f837f1fa99aa5
Author: Dmitry Antipov <dmantipov@yandex.ru>
can: j1939: make hrtimer callback lockless and free ECUs asyncronously
This patch removes the lock from j1939_ecu_timer_handler() and uses cmpxchg()
to map the device. It also defers removal to a workqueue to avoid concurrent
modification of the list.
> diff --git a/net/can/j1939/bus.c b/net/can/j1939/bus.c
> index cdc3c0a719379..a347594b8c1c5 100644
> --- a/net/can/j1939/bus.c
> +++ b/net/can/j1939/bus.c
> @@ -14,17 +14,27 @@
>
> #include "j1939-priv.h"
>
> -static void __j1939_ecu_release(struct kref *kref)
> +static void __j1939_ecu_work(struct work_struct *work)
> {
> - struct j1939_ecu *ecu = container_of(kref, struct j1939_ecu, kref);
> + struct j1939_ecu *ecu = container_of(work, struct j1939_ecu, work);
> struct j1939_priv *priv = ecu->priv;
>
> + write_lock(&priv->lock);
[Severity: High]
Does this code expose the lock to deadlocks with softirqs?
Because __j1939_ecu_work() runs in process context and uses write_lock(), a
network softirq could interrupt this and try to acquire the same priv->lock via
read_lock_bh() or write_lock_bh() during frame reception.
Should this use write_lock_bh() instead?
> list_del(&ecu->list);
> netdev_put(priv->ndev, &ecu->priv_dev_tracker);
> kfree(ecu);
> + write_unlock(&priv->lock);
> +
> j1939_priv_put(priv);
> }
>
> +static void __j1939_ecu_release(struct kref *kref)
> +{
> + struct j1939_ecu *ecu = container_of(kref, struct j1939_ecu, kref);
> +
> + schedule_work(&ecu->work);
[Severity: High]
Does scheduling the removal work leave the object on the priv->ecus list with a
zero reference count?
Concurrent network paths traversing the list under read_lock_bh() might
find this zero-refcount object and call j1939_ecu_get(), triggering a
kref_get() on a zero refcount and causing refcount saturation.
Should the object be removed from the list synchronously before scheduling the
work?
[Severity: High]
Does this deferral create a use-after-free regression during module unload?
If the last socket is closed, dropping references and scheduling this
work, and the module is immediately unloaded via rmmod, the workqueue might
execute __j1939_ecu_work() after the module's memory is freed.
Is there a missing flush of the scheduled work in the j1939_module_exit() path?
> +}
> +
> void j1939_ecu_put(struct j1939_ecu *ecu)
[ ... ]
> @@ -46,26 +56,23 @@ static bool j1939_ecu_is_mapped_locked(struct j1939_ecu *ecu)
>
> /* ECU device interface */
> /* map ECU to a bus address space */
> -static void j1939_ecu_map_locked(struct j1939_ecu *ecu)
> +static void j1939_ecu_map_atomic(struct j1939_ecu *ecu)
> {
> struct j1939_priv *priv = ecu->priv;
> struct j1939_addr_ent *ent;
>
> - lockdep_assert_held(&priv->lock);
> -
> if (!j1939_address_is_unicast(ecu->addr))
> return;
>
> ent = &priv->ents[ecu->addr];
>
> - if (ent->ecu) {
> + if (cmpxchg(&ent->ecu, NULL, ecu)) {
[Severity: High]
Does this cmpxchg expose the pointer to concurrent threads before its
reference count is incremented?
If another thread concurrently unmaps the object and calls j1939_ecu_put(), it
could drop a reference that this mapping thread has not yet acquired. If the
refcount drops to zero, the object would be queued for deletion, and the
subsequent j1939_ecu_get() here would increment a zero refcount.
Should j1939_ecu_get() be called before the cmpxchg?
> netdev_warn(priv->ndev, "Trying to map already mapped ECU, addr: 0x%02x, name: 0x%016llx. Skip it.\n",
> ecu->addr, ecu->name);
> return;
> }
>
> j1939_ecu_get(ecu);
> - ent->ecu = ecu;
> ent->nusers += ecu->nusers;
[Severity: High]
Does this unprotected arithmetic race with other threads?
Since the update to ent->nusers is no longer protected by priv->lock,
concurrent threads could perform read-modify-write operations on ent->nusers
simultaneously, causing lost updates to the user accounting.
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260828064621.91364-1-dmantipov@yandex.ru?part=1
prev parent reply other threads:[~2026-08-28 7:08 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 6:46 [PATCH v3 1/2] can: j1939: make hrtimer callback lockless and free ECUs asyncronously Dmitry Antipov
2026-08-28 6:46 ` [PATCH v3 2/2] can: j1939: cancel all pending ECUs on device stop Dmitry Antipov
2026-08-28 7:09 ` sashiko-bot
2026-08-28 7:08 ` sashiko-bot [this message]
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=20260828070825.559901F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmantipov@yandex.ru \
--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.