FAILED: patch "[PATCH] can: bcm: track a single source interface for ANYDEV" failed to apply to 6.18-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 2f5976f54a04e9f18b25283036ac3136be453b17
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072018-crouch-islamic-d0cb@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2f5976f54a04e9f18b25283036ac3136be453b17 Mon Sep 17 00:00:00 2001
From: Oliver Hartkopp <[email protected]>
Date: Tue, 14 Jul 2026 18:55:33 +0200
Subject: [PATCH] can: bcm: track a single source interface for ANYDEV
timeout/throttle ops
An ANYDEV rx op (ifindex == 0) with an active RX timeout and/or throttle timer has no defined semantics when matching frames arrive from several interfaces: bcm_rx_handler() can run concurrently for the same op on different CPUs, racing hrtimer_cancel()/ bcm_rx_starttimer() against bcm_rx_timeout_handler() and causing spurious RX_TIMEOUT notifications and last_frames corruption. The same concurrency lets throttled multiplex frames from different interfaces clobber the single rx_ifindex/rx_stamp fields shared by the op.
Add op->if_detected to track the first interface that delivers a matching frame while a timeout/throttle timer is configured, and reject frames from any other interface for that op. The claim is decided in bcm_rx_handler() before hrtimer_cancel() touches op->timer, so a rejected frame can never disturb the claimed interface's watchdog. RTR-mode ops are excluded via RX_RTR_FRAME, independent of kt_ival1/kt_ival2, since those may briefly hold a stale value from an earlier non-RTR configuration.
The claim is released in bcm_notify() on NETDEV_UNREGISTER and in bcm_rx_setup() when SETTIMER reconfigures the timer values.
A (re-)claim is only possible on CAN devices in NETREG_REGISTERED dev->reg_state to cover the release in bcm_notify() where reg_state becomes NETREG_UNREGISTERING until synchronize_net().
net/can/bcm.c +44 -5
@@ -117,6 +117,7 @@ struct bcm_op {struct hrtimer timer, thrtimer;ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;int rx_ifindex; +int if_detected;/* first received ifindex in ANYDEV rx_op mode */ int cfsiz;u32 count;u32 nframes;
@@ -797,6 +798,33 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)return ; } +/* An ANYDEV op with an active RX timeout and/or throttle timer +* tracks a single source interface: claim the first interface that +* delivers a matching frame and reject frames from any other one, +* before hrtimer_cancel() below can touch op->timer - this avoids +* racing bcm_rx_timeout_handler() across concurrent interfaces. +* RX_RTR_FRAME ops are excluded, as kt_ival1/kt_ival2 may briefly +* hold a stale value from an earlier non-RTR configuration. +*/ +if (!op->ifindex) { +spin_lock_bh (&op->bcm_rx_update_lock); + +if (!(op->flags &RX_RTR_FRAME ) && + (op->kt_ival1 || op->kt_ival2)) { +/* don't claim to vanishing interface */ +if (!op->if_detected && +READ_ONCE (skb->dev->reg_state) ==NETREG_REGISTERED ) + op->if_detected = skb->dev->ifindex; + +if (op->if_detected != skb->dev->ifindex) { +spin_unlock_bh (&op->bcm_rx_update_lock); +return ; + } + } + +spin_unlock_bh (&op->bcm_rx_update_lock); + } +/* disable timeout */ hrtimer_cancel (&op->timer);
@@ -831,10 +859,9 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) traffic_flags |=RX_OWN ; } -/* save rx timestamp and originator for recvfrom() under lock. -* For an op subscribed on all interfaces (ifindex == 0) -* bcm_rx_handler() can run concurrently on different CPUs so -* the CAN content and the meta data must be bundled correctly. +/* save rx timestamp and originator for recvfrom() under lock: an +* ANYDEV op without an active timer can still run concurrently on +* different CPUs, so content and meta data must be bundled here. */ op->rx_stamp = skb->tstamp; op->rx_ifindex = skb->dev->ifindex;
@@ -1369,6 +1396,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->kt_ival1 =bcm_timeval_to_ktime (msg_head->ival1); op->kt_ival2 =bcm_timeval_to_ktime (msg_head->ival2); op->kt_lastmsg =0 ; + op->if_detected =0 ;/* reclaim ifindex in ANYDEV mode */ }spin_unlock_bh (&op->bcm_rx_update_lock);
@@ -1775,10 +1803,21 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,lock_sock (sk);/* rx_ops: remove device specific receive entries */ -list_for_each_entry (op, &bo->rx_ops, list) +list_for_each_entry (op, &bo->rx_ops, list) {if (op->rx_reg_dev == dev)bcm_rx_unreg (dev, op); +/* release an ANYDEV op's claim (see bcm_rx_handler()) +* on this now confirmed-gone interface. +*/ +if (!op->ifindex) { +spin_lock_bh (&op->bcm_rx_update_lock); +if (op->if_detected == dev->ifindex) + op->if_detected =0 ; +spin_unlock_bh (&op->bcm_rx_update_lock); + } + } +/* tx_ops: stop device specific cyclic transmissions on the * vanishing ifindex. Cancelling the timer is enough to stop * cyclic bcm_can_tx() calls as there is no re-arming.
Oliver Hartkopp
maintainerPATCH 8/8 can: bcm: track a single source interface for ANYDEV timeout/throttle ops
commit 2f5976f54a04e9f18b25283036ac3136be453b17 upstream.
An ANYDEV rx op (ifindex == 0) with an active RX timeout and/or throttle timer has no defined semantics when matching frames arrive from several interfaces: bcm_rx_handler() can run concurrently for the same op on different CPUs, racing hrtimer_cancel()/ bcm_rx_starttimer() against bcm_rx_timeout_handler() and causing spurious RX_TIMEOUT notifications and last_frames corruption. The same concurrency lets throttled multiplex frames from different interfaces clobber the single rx_ifindex/rx_stamp fields shared by the op.
Add op->if_detected to track the first interface that delivers a matching frame while a timeout/throttle timer is configured, and reject frames from any other interface for that op. The claim is decided in bcm_rx_handler() before hrtimer_cancel() touches op->timer, so a rejected frame can never disturb the claimed interface's watchdog. RTR-mode ops are excluded via RX_RTR_FRAME, independent of kt_ival1/kt_ival2, since those may briefly hold a stale value from an earlier non-RTR configuration.
The claim is released in bcm_notify() on NETDEV_UNREGISTER and in bcm_rx_setup() when SETTIMER reconfigures the timer values.
A (re-)claim is only possible on CAN devices in NETREG_REGISTERED dev->reg_state to cover the release in bcm_notify() where reg_state becomes NETREG_UNREGISTERING until synchronize_net().
--- net/can/bcm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-)
net/can/bcm.c +44 -5
@@ -116,6 +116,7 @@ struct bcm_op {struct hrtimer timer, thrtimer;ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;int rx_ifindex; +int if_detected;/* first received ifindex in ANYDEV rx_op mode */ int cfsiz;u32 count;u32 nframes;
@@ -791,6 +792,33 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)return ; } +/* An ANYDEV op with an active RX timeout and/or throttle timer +* tracks a single source interface: claim the first interface that +* delivers a matching frame and reject frames from any other one, +* before hrtimer_cancel() below can touch op->timer - this avoids +* racing bcm_rx_timeout_handler() across concurrent interfaces. +* RX_RTR_FRAME ops are excluded, as kt_ival1/kt_ival2 may briefly +* hold a stale value from an earlier non-RTR configuration. +*/ +if (!op->ifindex) { +spin_lock_bh (&op->bcm_rx_update_lock); + +if (!(op->flags &RX_RTR_FRAME ) && + (op->kt_ival1 || op->kt_ival2)) { +/* don't claim to vanishing interface */ +if (!op->if_detected && + skb->dev->reg_state ==NETREG_REGISTERED ) + op->if_detected = skb->dev->ifindex; + +if (op->if_detected != skb->dev->ifindex) { +spin_unlock_bh (&op->bcm_rx_update_lock); +return ; + } + } + +spin_unlock_bh (&op->bcm_rx_update_lock); + } +/* disable timeout */ hrtimer_cancel (&op->timer);
@@ -825,10 +853,9 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) traffic_flags |=RX_OWN ; } -/* save rx timestamp and originator for recvfrom() under lock. -* For an op subscribed on all interfaces (ifindex == 0) -* bcm_rx_handler() can run concurrently on different CPUs so -* the CAN content and the meta data must be bundled correctly. +/* save rx timestamp and originator for recvfrom() under lock: an +* ANYDEV op without an active timer can still run concurrently on +* different CPUs, so content and meta data must be bundled here. */ op->rx_stamp = skb->tstamp; op->rx_ifindex = skb->dev->ifindex;
@@ -1363,6 +1390,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->kt_ival1 =bcm_timeval_to_ktime (msg_head->ival1); op->kt_ival2 =bcm_timeval_to_ktime (msg_head->ival2); op->kt_lastmsg =0 ; + op->if_detected =0 ;/* reclaim ifindex in ANYDEV mode */ }spin_unlock_bh (&op->bcm_rx_update_lock);
@@ -1763,10 +1791,21 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,lock_sock (sk);/* rx_ops: remove device specific receive entries */ -list_for_each_entry (op, &bo->rx_ops, list) +list_for_each_entry (op, &bo->rx_ops, list) {if (op->rx_reg_dev == dev)bcm_rx_unreg (dev, op); +/* release an ANYDEV op's claim (see bcm_rx_handler()) +* on this now confirmed-gone interface. +*/ +if (!op->ifindex) { +spin_lock_bh (&op->bcm_rx_update_lock); +if (op->if_detected == dev->ifindex) + op->if_detected =0 ; +spin_unlock_bh (&op->bcm_rx_update_lock); + } + } +/* tx_ops: stop device specific cyclic transmissions on the * vanishing ifindex. Cancelling the timer is enough to stop * cyclic bcm_can_tx() calls as there is no re-arming.
Signature · 1 line
2.43.0