From: sashiko-bot@kernel.org
To: "Oliver Hartkopp" <socketcan@hartkopp.net>
Cc: "Marc Kleine-Budde" <mkl@pengutronix.de>,
"Vincent Mailhol" <mailhol@kernel.org>,
linux-can@vger.kernel.org,
"Oliver Hartkopp" <socketcan@hartkopp.net>,
"Oleksij Rempel" <o.rempel@pengutronix.de>
Subject: Re: [PATCH v10 3/3] can: isotp: serialize TX state transitions under so->rx_lock
Date: Sun, 12 Jul 2026 18:11:55 +0000 [thread overview]
Message-ID: <20260712181155.B42EA1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260712-isotp-fixes-v10-3-793a1b1ce17f@hartkopp.net>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Lockless state transition in the timeout handler creates a race condition that causes timeout errors to be silently dropped or misattributed, leading sendmsg() to erroneously return success for timed-out transfers.
--
--- Patch [3]: [PATCH v10 3/3] can: isotp: serialize TX state transitions under so->rx_lock ---
commit e21ce85bab56b1b57ffd11ce2b23b760bfb72c21
Author: Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: serialize TX state transitions under so->rx_lock
This commit serializes CAN ISOTP TX state transitions and timer cancellations
under so->rx_lock to prevent concurrent modifications. It also changes the
timeout handlers to locklessly cancel transfers by checking and updating
so->tx_gen and so->tx.state.
Link: https://lore.kernel.org/linux-can/20260710142146.BDAE61F000E9@smtp.kernel.org/
> diff --git a/net/can/isotp.c b/net/can/isotp.c
> index 44c044eb83e12..54becaf6898f1 100644
> --- a/net/can/isotp.c
> +++ b/net/can/isotp.c
[ ... ]
> @@ -893,53 +927,83 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
[ ... ]
> +static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so)
> {
> - struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
> - txtimer);
> struct sock *sk = &so->sk;
> + u32 gen = READ_ONCE(so->tx_gen);
> + u32 old_state = READ_ONCE(so->tx.state);
>
> /* don't handle timeouts in IDLE or SHUTDOWN state */
> - if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
> + if (old_state == ISOTP_IDLE || old_state == ISOTP_SHUTDOWN)
> + return HRTIMER_NORESTART;
> +
> + /* only claim the timeout if the state is still unchanged */
> + if (cmpxchg(&so->tx.state, old_state, ISOTP_IDLE) != old_state)
> return HRTIMER_NORESTART;
>
> /* we did not get any flow control or echo frame in time */
>
> - /* report 'communication error on send' */
> - sk->sk_err = ECOMM;
> - if (!sock_flag(sk, SOCK_DEAD))
> - sk_error_report(sk);
> + if (READ_ONCE(so->tx_gen) == gen) {
> + /* report 'communication error on send' */
> + sk->sk_err = ECOMM;
> + if (!sock_flag(sk, SOCK_DEAD))
> + sk_error_report(sk);
> + }
[Severity: High]
Does this lockless state transition create a race window where timeout
errors are lost?
By setting so->tx.state to ISOTP_IDLE before setting sk->sk_err = ECOMM,
a thread waiting in isotp_sendmsg() for wait_tx_done might wake up, observe
ISOTP_IDLE, and read sock_error() before the error is set, falsely returning
success.
Additionally, could another concurrent sendmsg() see the IDLE state,
claim the socket, and increment tx_gen before the error is set?
If this happens, the check if (READ_ONCE(so->tx_gen) == gen) will fail,
and the error will never be reported to the original waiting thread.
[ ... ]
> @@ -960,13 +1024,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
[ ... ]
> + /* new transfer: bump so->tx_gen and drain the old one's timers,
> + * still under the so->rx_lock we just claimed the socket with
> + */
> + WRITE_ONCE(so->tx.state, ISOTP_SENDING);
> + WRITE_ONCE(so->tx_gen, READ_ONCE(so->tx_gen) + 1);
> + hrtimer_cancel(&so->txtimer);
> + hrtimer_cancel(&so->echotimer);
[Severity: High]
When this tx_gen increment occurs concurrently with isotp_tx_timeout()
after the timeout has already transitioned the state to ISOTP_IDLE, doesn't it
cause the timeout handler to suppress the error for the previous transfer?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260712-isotp-fixes-v10-0-793a1b1ce17f@hartkopp.net?part=3
next prev parent reply other threads:[~2026-07-12 18:11 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-12 17:59 [PATCH v10 0/3] net: can: isotp-fixes Oliver Hartkopp via B4 Relay
2026-07-12 17:59 ` Oliver Hartkopp
2026-07-12 17:59 ` [PATCH v10 1/3] can: isotp: use unconditional synchronize_rcu() in isotp_release() Oliver Hartkopp via B4 Relay
2026-07-12 17:59 ` Oliver Hartkopp
2026-07-12 18:15 ` sashiko-bot
2026-07-12 17:59 ` [PATCH v10 2/3] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER Oliver Hartkopp via B4 Relay
2026-07-12 17:59 ` Oliver Hartkopp
2026-07-12 17:59 ` [PATCH v10 3/3] can: isotp: serialize TX state transitions under so->rx_lock Oliver Hartkopp via B4 Relay
2026-07-12 17:59 ` Oliver Hartkopp
2026-07-12 18:11 ` sashiko-bot [this message]
2026-07-12 20:10 ` 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=20260712181155.B42EA1F000E9@smtp.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 \
/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.