Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH AUTOSEL 7.0] dsa: tag_mxl862xx: set dsa_default_offload_fwd_mark()
From: Daniel Golle @ 2026-04-20 13:34 UTC (permalink / raw)
  To: Sasha Levin
  Cc: patches, stable, Jakub Kicinski, andrew, olteanv, davem, edumazet,
	pabeni, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-153-sashal@kernel.org>

On Mon, Apr 20, 2026 at 09:19:07AM -0400, Sasha Levin wrote:
> From: Daniel Golle <daniel@makrotopia.org>
> 
> [ Upstream commit 4250ff1640ea1ede99bfe02ca949acbcc6c0927f ]
> 
> The MxL862xx offloads bridge forwarding in hardware, so set
> dsa_default_offload_fwd_mark() to avoid duplicate forwarding of
> packets of (eg. flooded) frames arriving at the CPU port.
> 
> Link-local frames are directly trapped to the CPU port only, so don't
> set dsa_default_offload_fwd_mark() on those.
> 
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> Link: https://patch.msgid.link/e1161c90894ddc519c57dc0224b3a0f6bfa1d2d6.1775049897.git.daniel@makrotopia.org
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> 
> LLM Generated explanations, may be completely bogus:
> 
> Now I have all the information needed for a complete analysis.

This commit should NOT be backported, it only makes sense with bridge
offloading implemented, which only happened with commit 340bdf984613c
("net: dsa: mxl862xx: implement bridge offloading").

^ permalink raw reply

* [PATCH AUTOSEL 6.18] net: airoha: Fix memory leak in airoha_qdma_rx_process()
From: Sasha Levin @ 2026-04-20 13:22 UTC (permalink / raw)
  To: patches, stable
  Cc: Lorenzo Bianconi, Simon Horman, Jakub Kicinski, Sasha Levin,
	andrew+netdev, davem, edumazet, pabeni, linux-arm-kernel,
	linux-mediatek, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Lorenzo Bianconi <lorenzo@kernel.org>

[ Upstream commit 285fa6b1e03cff78ead0383e1b259c44b95faf90 ]

If an error occurs on the subsequents buffers belonging to the
non-linear part of the skb (e.g. due to an error in the payload length
reported by the NIC or if we consumed all the available fragments for
the skb), the page_pool fragment will not be linked to the skb so it will
not return to the pool in the airoha_qdma_rx_process() error path. Fix the
memory leak partially reverting commit 'd6d2b0e1538d ("net: airoha: Fix
page recycling in airoha_qdma_rx_process()")' and always running
page_pool_put_full_page routine in the airoha_qdma_rx_process() error
path.

Fixes: d6d2b0e1538d ("net: airoha: Fix page recycling in airoha_qdma_rx_process()")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260402-airoha_qdma_rx_process-mem-leak-fix-v1-1-b5706f402d3c@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 drivers/net/ethernet/airoha/airoha_eth.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 4fc6bd282b465..bdf600fea9508 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -709,9 +709,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
 		if (q->skb) {
 			dev_kfree_skb(q->skb);
 			q->skb = NULL;
-		} else {
-			page_pool_put_full_page(q->page_pool, page, true);
 		}
+		page_pool_put_full_page(q->page_pool, page, true);
 	}
 	airoha_qdma_fill_rx_queue(q);
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] net: lapbether: handle NETDEV_PRE_TYPE_CHANGE
From: Sasha Levin @ 2026-04-20 13:22 UTC (permalink / raw)
  To: patches, stable
  Cc: Eric Dumazet, syzbot+d8c285748fa7292580a9, Martin Schiller,
	Simon Horman, Jakub Kicinski, Sasha Levin, andrew+netdev, davem,
	pabeni, jeff, fubar, linux-x25, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Eric Dumazet <edumazet@google.com>

[ Upstream commit b120e4432f9f56c7103133d6a11245e617695adb ]

lapbeth_data_transmit() expects the underlying device type
to be ARPHRD_ETHER.

Returning NOTIFY_BAD from lapbeth_device_event() makes sure
bonding driver can not break this expectation.

Fixes: 872254dd6b1f ("net/bonding: Enable bonding to enslave non ARPHRD_ETHER")
Reported-by: syzbot+d8c285748fa7292580a9@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/69cd22a1.050a0220.70c3a.0002.GAE@google.com/T/#u
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Martin Schiller <ms@dev.tdt.de>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260402103519.1201565-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 drivers/net/wan/lapbether.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index f357a7ac70ac4..9861c99ea56c4 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -446,33 +446,36 @@ static void lapbeth_free_device(struct lapbethdev *lapbeth)
 static int lapbeth_device_event(struct notifier_block *this,
 				unsigned long event, void *ptr)
 {
-	struct lapbethdev *lapbeth;
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct lapbethdev *lapbeth;
 
 	if (dev_net(dev) != &init_net)
 		return NOTIFY_DONE;
 
-	if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev))
+	lapbeth = lapbeth_get_x25_dev(dev);
+	if (!dev_is_ethdev(dev) && !lapbeth)
 		return NOTIFY_DONE;
 
 	switch (event) {
 	case NETDEV_UP:
 		/* New ethernet device -> new LAPB interface	 */
-		if (!lapbeth_get_x25_dev(dev))
+		if (!lapbeth)
 			lapbeth_new_device(dev);
 		break;
 	case NETDEV_GOING_DOWN:
 		/* ethernet device closes -> close LAPB interface */
-		lapbeth = lapbeth_get_x25_dev(dev);
 		if (lapbeth)
 			dev_close(lapbeth->axdev);
 		break;
 	case NETDEV_UNREGISTER:
 		/* ethernet device disappears -> remove LAPB interface */
-		lapbeth = lapbeth_get_x25_dev(dev);
 		if (lapbeth)
 			lapbeth_free_device(lapbeth);
 		break;
+	case NETDEV_PRE_TYPE_CHANGE:
+		/* Our underlying device type must not change. */
+		if (lapbeth)
+			return NOTIFY_BAD;
 	}
 
 	return NOTIFY_DONE;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] xfrm_user: fix info leak in build_mapping()
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Greg Kroah-Hartman, Steffen Klassert, Herbert Xu, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Sasha Levin, martin, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

[ Upstream commit 1beb76b2053b68c491b78370794b8ff63c8f8c02 ]

struct xfrm_usersa_id has a one-byte padding hole after the proto
field, which ends up never getting set to zero before copying out to
userspace.  Fix that up by zeroing out the whole structure before
setting individual variables.

Fixes: 3a2dfbe8acb1 ("xfrm: Notify changes in UDP encapsulation via netlink")
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Assisted-by: gregkh_clanker_t1000
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/xfrm/xfrm_user.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 1ddcf2a1eff7a..b3f69c0760d4c 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -4164,6 +4164,7 @@ static int build_mapping(struct sk_buff *skb, struct xfrm_state *x,
 
 	um = nlmsg_data(nlh);
 
+	memset(&um->id, 0, sizeof(um->id));
 	memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr));
 	um->id.spi = x->id.spi;
 	um->id.family = x->props.family;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] xsk: validate MTU against usable frame size on bind
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Maciej Fijalkowski, Björn Töpel, Jakub Kicinski,
	Sasha Levin, magnus.karlsson, davem, edumazet, pabeni, ast,
	netdev, bpf, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>

[ Upstream commit 36ee60b569ba0dfb6f961333b90d19ab5b323fa9 ]

AF_XDP bind currently accepts zero-copy pool configurations without
verifying that the device MTU fits into the usable frame space provided
by the UMEM chunk.

This becomes a problem since we started to respect tailroom which is
subtracted from chunk_size (among with headroom). 2k chunk size might
not provide enough space for standard 1500 MTU, so let us catch such
settings at bind time. Furthermore, validate whether underlying HW will
be able to satisfy configured MTU wrt XSK's frame size multiplied by
supported Rx buffer chain length (that is exposed via
net_device::xdp_zc_max_segs).

Fixes: 24ea50127ecf ("xsk: support mbuf on ZC RX")
Reviewed-by: Björn Töpel <bjorn@kernel.org>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://patch.msgid.link/20260402154958.562179-5-maciej.fijalkowski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/xdp/xsk_buff_pool.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index 677c7d00f8c32..a129ce6f1c25f 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -10,6 +10,8 @@
 #include "xdp_umem.h"
 #include "xsk.h"
 
+#define ETH_PAD_LEN (ETH_HLEN + 2 * VLAN_HLEN  + ETH_FCS_LEN)
+
 void xp_add_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs)
 {
 	unsigned long flags;
@@ -165,8 +167,12 @@ static void xp_disable_drv_zc(struct xsk_buff_pool *pool)
 int xp_assign_dev(struct xsk_buff_pool *pool,
 		  struct net_device *netdev, u16 queue_id, u16 flags)
 {
+	u32 needed = netdev->mtu + ETH_PAD_LEN;
+	u32 segs = netdev->xdp_zc_max_segs;
+	bool mbuf = flags & XDP_USE_SG;
 	bool force_zc, force_copy;
 	struct netdev_bpf bpf;
+	u32 frame_size;
 	int err = 0;
 
 	ASSERT_RTNL();
@@ -186,7 +192,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 	if (err)
 		return err;
 
-	if (flags & XDP_USE_SG)
+	if (mbuf)
 		pool->umem->flags |= XDP_UMEM_SG_FLAG;
 
 	if (flags & XDP_USE_NEED_WAKEUP)
@@ -208,8 +214,24 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 		goto err_unreg_pool;
 	}
 
-	if (netdev->xdp_zc_max_segs == 1 && (flags & XDP_USE_SG)) {
-		err = -EOPNOTSUPP;
+	if (mbuf) {
+		if (segs == 1) {
+			err = -EOPNOTSUPP;
+			goto err_unreg_pool;
+		}
+	} else {
+		segs = 1;
+	}
+
+	/* open-code xsk_pool_get_rx_frame_size() as pool->dev is not
+	 * set yet at this point; we are before getting down to driver
+	 */
+	frame_size = __xsk_pool_get_rx_frame_size(pool) -
+		     xsk_pool_get_tailroom(mbuf);
+	frame_size = ALIGN_DOWN(frame_size, 128);
+
+	if (needed > frame_size * segs) {
+		err = -EINVAL;
 		goto err_unreg_pool;
 	}
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] nfc: s3fwrn5: allocate rx skb before consuming bytes
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Pengpeng Hou, Jakub Kicinski, Sasha Levin, krzk, bongsu.jeon,
	netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Pengpeng Hou <pengpeng@iscas.ac.cn>

[ Upstream commit 5c14a19d5b1645cce1cb1252833d70b23635b632 ]

s3fwrn82_uart_read() reports the number of accepted bytes to the serdev
core. The current code consumes bytes into recv_skb and may already
deliver a complete frame before allocating a fresh receive buffer.

If that alloc_skb() fails, the callback returns 0 even though it has
already consumed bytes, and it leaves recv_skb as NULL for the next
receive callback. That breaks the receive_buf() accounting contract and
can also lead to a NULL dereference on the next skb_put_u8().

Allocate the receive skb lazily before consuming the next byte instead.
If allocation fails, return the number of bytes already accepted.

Fixes: 3f52c2cb7e3a ("nfc: s3fwrn5: Support a UART interface")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260402042148.65236-1-pengpeng@iscas.ac.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 drivers/nfc/s3fwrn5/uart.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
index 9c09c10c2a464..4ee481bd7e965 100644
--- a/drivers/nfc/s3fwrn5/uart.c
+++ b/drivers/nfc/s3fwrn5/uart.c
@@ -58,6 +58,12 @@ static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
 	size_t i;
 
 	for (i = 0; i < count; i++) {
+		if (!phy->recv_skb) {
+			phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+			if (!phy->recv_skb)
+				return i;
+		}
+
 		skb_put_u8(phy->recv_skb, *data++);
 
 		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
@@ -69,9 +75,7 @@ static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
 
 		s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
 				   phy->common.mode);
-		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
-		if (!phy->recv_skb)
-			return 0;
+		phy->recv_skb = NULL;
 	}
 
 	return i;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] ipv4: icmp: fix null-ptr-deref in icmp_build_probe()
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Yiqi Sun, Jakub Kicinski, Sasha Levin, davem, dsahern, edumazet,
	pabeni, andreas.a.roeseler, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Yiqi Sun <sunyiqixm@gmail.com>

[ Upstream commit fde29fd9349327acc50d19a0b5f3d5a6c964dfd8 ]

ipv6_stub->ipv6_dev_find() may return ERR_PTR(-EAFNOSUPPORT) when the
IPv6 stack is not active (CONFIG_IPV6=m and not loaded), and passing
this error pointer to dev_hold() will cause a kernel crash with
null-ptr-deref.

Instead, silently discard the request. RFC 8335 does not appear to
define a specific response for the case where an IPv6 interface
identifier is syntactically valid but the implementation cannot perform
the lookup at runtime, and silently dropping the request may safer than
misreporting "No Such Interface".

Fixes: d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages")
Signed-off-by: Yiqi Sun <sunyiqixm@gmail.com>
Link: https://patch.msgid.link/20260402070419.2291578-1-sunyiqixm@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/ipv4/icmp.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index b39176b620785..980aa17f3534d 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1145,6 +1145,13 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
 			if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in6_addr))
 				goto send_mal_query;
 			dev = ipv6_stub->ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev);
+			/*
+			 * If IPv6 identifier lookup is unavailable, silently
+			 * discard the request instead of misreporting NO_IF.
+			 */
+			if (IS_ERR(dev))
+				return false;
+
 			dev_hold(dev);
 			break;
 #endif
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] net: ioam6: fix OOB and missing lock
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Justin Iurman, Jakub Kicinski, Sasha Levin, davem, dsahern,
	edumazet, pabeni, idosch, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Justin Iurman <justin.iurman@gmail.com>

[ Upstream commit b30b1675aa2bcf0491fd3830b051df4e08a7c8ca ]

When trace->type.bit6 is set:

    if (trace->type.bit6) {
        ...
        queue = skb_get_tx_queue(dev, skb);
        qdisc = rcu_dereference(queue->qdisc);

This code can lead to an out-of-bounds access of the dev->_tx[] array
when is_input is true. In such a case, the packet is on the RX path and
skb->queue_mapping contains the RX queue index of the ingress device. If
the ingress device has more RX queues than the egress device (dev) has
TX queues, skb_get_queue_mapping(skb) will exceed dev->num_tx_queues.
Add a check to avoid this situation since skb_get_tx_queue() does not
clamp the index. This issue has also revealed that per queue visibility
cannot be accurate and will be replaced later as a new feature.

While at it, add missing lock around qdisc_qstats_qlen_backlog(). The
function __ioam6_fill_trace_data() is called from both softirq and
process contexts, hence the use of spin_lock_bh() here.

Fixes: b63c5478e9cb ("ipv6: ioam: Support for Queue depth data field")
Reported-by: Jakub Kicinski <kuba@kernel.org>
Closes: https://lore.kernel.org/netdev/20260403214418.2233266-2-kuba@kernel.org/
Signed-off-by: Justin Iurman <justin.iurman@gmail.com>
Link: https://patch.msgid.link/20260404134137.24553-1-justin.iurman@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/ipv6/ioam6.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c
index 12350e1e18bde..b91de51ffa9ea 100644
--- a/net/ipv6/ioam6.c
+++ b/net/ipv6/ioam6.c
@@ -803,12 +803,16 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
 		struct Qdisc *qdisc;
 		__u32 qlen, backlog;
 
-		if (dev->flags & IFF_LOOPBACK) {
+		if (dev->flags & IFF_LOOPBACK ||
+		    skb_get_queue_mapping(skb) >= dev->num_tx_queues) {
 			*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
 		} else {
 			queue = skb_get_tx_queue(dev, skb);
 			qdisc = rcu_dereference(queue->qdisc);
+
+			spin_lock_bh(qdisc_lock(qdisc));
 			qdisc_qstats_qlen_backlog(qdisc, &qlen, &backlog);
+			spin_unlock_bh(qdisc_lock(qdisc));
 
 			*(__be32 *)data = cpu_to_be32(backlog);
 		}
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] dt-bindings: net: Fix Tegra234 MGBE PTP clock
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Jon Hunter, Krzysztof Kozlowski, Jakub Kicinski, Sasha Levin,
	andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
	thierry.reding, treding, vbhadram, netdev, devicetree,
	linux-tegra, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Jon Hunter <jonathanh@nvidia.com>

[ Upstream commit fb22b1fc5bca3c0aad95388933497ceb30f1fb26 ]

The PTP clock for the Tegra234 MGBE device is incorrectly named
'ptp-ref' and should be 'ptp_ref'. This is causing the following
warning to be observed on Tegra234 platforms that use this device:

 ERR KERN tegra-mgbe 6800000.ethernet eth0: Invalid PTP clock rate
 WARNING KERN tegra-mgbe 6800000.ethernet eth0: PTP init failed

Although this constitutes an ABI breakage in the binding for this
device, PTP support has clearly never worked and so fix this now
so we can correct the device-tree for this device. Note that the
MGBE driver still supports the legacy 'ptp-ref' clock name and so
older/existing device-trees will still work, but given that this
is not the correct name, there is no point to advertise this in the
binding.

Fixes: 189c2e5c7669 ("dt-bindings: net: Add Tegra234 MGBE")
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260401102941.17466-3-jonathanh@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 .../devicetree/bindings/net/nvidia,tegra234-mgbe.yaml         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nvidia,tegra234-mgbe.yaml b/Documentation/devicetree/bindings/net/nvidia,tegra234-mgbe.yaml
index 2bd3efff2485e..215f14d1897d2 100644
--- a/Documentation/devicetree/bindings/net/nvidia,tegra234-mgbe.yaml
+++ b/Documentation/devicetree/bindings/net/nvidia,tegra234-mgbe.yaml
@@ -42,7 +42,7 @@ properties:
       - const: mgbe
       - const: mac
       - const: mac-divider
-      - const: ptp-ref
+      - const: ptp_ref
       - const: rx-input-m
       - const: rx-input
       - const: tx
@@ -133,7 +133,7 @@ examples:
                  <&bpmp TEGRA234_CLK_MGBE0_RX_PCS_M>,
                  <&bpmp TEGRA234_CLK_MGBE0_RX_PCS>,
                  <&bpmp TEGRA234_CLK_MGBE0_TX_PCS>;
-        clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m",
+        clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m",
                       "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m",
                       "rx-pcs", "tx-pcs";
         resets = <&bpmp TEGRA234_RESET_MGBE0_MAC>,
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] net: ipa: fix GENERIC_CMD register field masks for IPA v5.0+
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Alexander Koskovich, Luca Weiss, Simon Horman, Paolo Abeni,
	Sasha Levin, andrew+netdev, davem, edumazet, kuba, netdev,
	linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Alexander Koskovich <akoskovich@pm.me>

[ Upstream commit 9709b56d908acc120fe8b4ae250b3c9d749ea832 ]

Fix the field masks to match the hardware layout documented in
downstream GSI (GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_*).

Notably this fixes a WARN I was seeing when I tried to send "stop"
to the MPSS remoteproc while IPA was up.

Fixes: faf0678ec8a0 ("net: ipa: add IPA v5.0 GSI register definitions")
Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260403-milos-ipa-v1-1-01e9e4e03d3e@fairphone.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 drivers/net/ipa/reg/gsi_reg-v5.0.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ipa/reg/gsi_reg-v5.0.c b/drivers/net/ipa/reg/gsi_reg-v5.0.c
index 36d1e65df71bb..3334d8e20ad28 100644
--- a/drivers/net/ipa/reg/gsi_reg-v5.0.c
+++ b/drivers/net/ipa/reg/gsi_reg-v5.0.c
@@ -156,9 +156,10 @@ REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x00025010 + 0x12000 * GSI_EE_AP);
 
 static const u32 reg_generic_cmd_fmask[] = {
 	[GENERIC_OPCODE]				= GENMASK(4, 0),
-	[GENERIC_CHID]					= GENMASK(9, 5),
-	[GENERIC_EE]					= GENMASK(13, 10),
-						/* Bits 14-31 reserved */
+	[GENERIC_CHID]					= GENMASK(12, 5),
+	[GENERIC_EE]					= GENMASK(16, 13),
+						/* Bits 17-23 reserved */
+	[GENERIC_PARAMS]				= GENMASK(31, 24),
 };
 
 REG_FIELDS(GENERIC_CMD, generic_cmd, 0x00025018 + 0x12000 * GSI_EE_AP);
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] net: sched: act_csum: validate nested VLAN headers
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Ruide Cao, Yifan Wu, Juefei Pu, Yuan Tan, Xin Liu, Ren Wei,
	Ren Wei, Simon Horman, Jakub Kicinski, Sasha Levin, jhs, jiri,
	davem, edumazet, pabeni, elibr, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Ruide Cao <caoruide123@gmail.com>

[ Upstream commit c842743d073bdd683606cb414eb0ca84465dd834 ]

tcf_csum_act() walks nested VLAN headers directly from skb->data when an
skb still carries in-payload VLAN tags. The current code reads
vlan->h_vlan_encapsulated_proto and then pulls VLAN_HLEN bytes without
first ensuring that the full VLAN header is present in the linear area.

If only part of an inner VLAN header is linearized, accessing
h_vlan_encapsulated_proto reads past the linear area, and the following
skb_pull(VLAN_HLEN) may violate skb invariants.

Fix this by requiring pskb_may_pull(skb, VLAN_HLEN) before accessing and
pulling each nested VLAN header. If the header still is not fully
available, drop the packet through the existing error path.

Fixes: 2ecba2d1e45b ("net: sched: act_csum: Fix csum calc for tagged packets")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Ruide Cao <caoruide123@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/22df2fcb49f410203eafa5d97963dd36089f4ecf.1774892775.git.caoruide123@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/sched/act_csum.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 0939e6b2ba4d1..3a377604ad343 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -604,8 +604,12 @@ TC_INDIRECT_SCOPE int tcf_csum_act(struct sk_buff *skb,
 			protocol = skb->protocol;
 			orig_vlan_tag_present = true;
 		} else {
-			struct vlan_hdr *vlan = (struct vlan_hdr *)skb->data;
+			struct vlan_hdr *vlan;
 
+			if (!pskb_may_pull(skb, VLAN_HLEN))
+				goto drop;
+
+			vlan = (struct vlan_hdr *)skb->data;
 			protocol = vlan->h_vlan_encapsulated_proto;
 			skb_pull(skb, VLAN_HLEN);
 			skb_reset_network_header(skb);
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0] netfilter: require Ethernet MAC header before using eth_hdr()
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Zhengchuan Liang, Florian Westphal, Ren Wei, Ren Wei, Sasha Levin,
	pablo, davem, dsahern, edumazet, kuba, pabeni, netfilter-devel,
	coreteam, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Zhengchuan Liang <zcliangcn@gmail.com>

[ Upstream commit 62443dc21114c0bbc476fa62973db89743f2f137 ]

`ip6t_eui64`, `xt_mac`, the `bitmap:ip,mac`, `hash:ip,mac`, and
`hash:mac` ipset types, and `nf_log_syslog` access `eth_hdr(skb)`
after either assuming that the skb is associated with an Ethernet
device or checking only that the `ETH_HLEN` bytes at
`skb_mac_header(skb)` lie between `skb->head` and `skb->data`.

Make these paths first verify that the skb is associated with an
Ethernet device, that the MAC header was set, and that it spans at
least a full Ethernet header before accessing `eth_hdr(skb)`.

Suggested-by: Florian Westphal <fw@strlen.de>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

`skb_mac_header_was_set` has been available since 2013, so it's
available in all currently supported stable trees. `skb_mac_header_len`
was introduced in 2017, also available in all supported stable trees
(5.4+).

Now I have all the information needed for the full analysis. Let me
compile it.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject Line
- **Subsystem**: netfilter (multiple files: ip6t_eui64, xt_mac, ipset
  types, nf_log_syslog)
- **Action verb**: "require" (ensuring precondition is met before use)
- **Summary**: Require Ethernet MAC header validation before calling
  `eth_hdr(skb)` across multiple netfilter modules

Record: [netfilter] [require] [validate MAC header is Ethernet and
properly set before accessing eth_hdr(skb)]

### Step 1.2: Tags
- **Suggested-by: Florian Westphal** - the netfilter subsystem co-
  maintainer suggested this broader fix
- **Tested-by: Ren Wei** - fix was tested
- **Signed-off-by: Florian Westphal** - the netfilter maintainer signed
  off and merged it
- No Fixes: tag (expected - this is a broader hardening patch)
- No Cc: stable tag (expected)

Record: Florian Westphal (netfilter maintainer) suggested and signed off
on this patch. Tested.

### Step 1.3: Commit Body
The commit explains that multiple netfilter modules access
`eth_hdr(skb)` after either:
1. Assuming the skb is associated with an Ethernet device, OR
2. Only checking that ETH_HLEN bytes at `skb_mac_header(skb)` lie
   between `skb->head` and `skb->data` (raw pointer arithmetic)

The fix adds three-part validation: (1) device is Ethernet
(`ARPHRD_ETHER`), (2) MAC header was set (`skb_mac_header_was_set`), (3)
MAC header spans a full Ethernet header (`skb_mac_header_len >=
ETH_HLEN`).

Record: Bug: `eth_hdr(skb)` accessed without proper validation that skb
has a valid Ethernet MAC header. Can lead to out-of-bounds reads. Root
cause: inadequate validation before dereferencing the MAC header.

### Step 1.4: Hidden Bug Fix Detection
This IS a memory safety fix. The commit message says "require...before
using" which means the existing code accesses `eth_hdr()` without proper
guards. Confirmed by KASAN report mentioned in the v2 changelog of patch
1/2. Florian Westphal explicitly identified the other files as
"suspicious spots."

Record: Yes, this is a genuine memory safety bug fix - prevents out-of-
bounds access on the MAC header.

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
- **net/ipv6/netfilter/ip6t_eui64.c**: +5/-2 lines (adds ARPHRD_ETHER
  check, uses `skb_mac_header_was_set`/`skb_mac_header_len`)
- **net/netfilter/ipset/ip_set_bitmap_ipmac.c**: +3/-2 lines
- **net/netfilter/ipset/ip_set_hash_ipmac.c**: +5/-4 lines (two
  functions)
- **net/netfilter/ipset/ip_set_hash_mac.c**: +3/-2 lines
- **net/netfilter/nf_log_syslog.c**: +6/-1 lines (two functions)
- **net/netfilter/xt_mac.c**: +1/-3 lines

Total: ~23 lines added, ~14 removed. Six files, all in netfilter
subsystem.

Record: Multi-file but mechanical/repetitive change. Each file gets the
same validation pattern. Scope: contained to netfilter MAC header
access.

### Step 2.2: Code Flow Changes
Each hunk follows the same pattern:
- **Before**: Raw pointer arithmetic `skb_mac_header(skb) < skb->head ||
  skb_mac_header(skb) + ETH_HLEN > skb->data`, or NO check at all
- **After**: Proper three-part check: `!skb->dev || skb->dev->type !=
  ARPHRD_ETHER || !skb_mac_header_was_set(skb) ||
  skb_mac_header_len(skb) < ETH_HLEN`

### Step 2.3: Bug Mechanism
**Category**: Memory safety (out-of-bounds read / invalid memory access)

The old checks were insufficient:
1. **ip6t_eui64.c**: Only checked pointer bounds, not device type
2. **ipset files**: Only checked pointer bounds, not device type or
   `skb_mac_header_was_set`
3. **nf_log_syslog.c dump_arp_packet**: NO check at all before
   `eth_hdr(skb)`
4. **nf_log_syslog.c dump_mac_header**: Checked device type via switch
   but not MAC header validity
5. **xt_mac.c**: Already had ARPHRD_ETHER check but used raw pointer
   comparison instead of proper API

Without proper validation, if the MAC header isn't set or isn't
Ethernet, `eth_hdr(skb)` returns a pointer to potentially uninitialized
or out-of-bounds memory.

### Step 2.4: Fix Quality
- **Obviously correct**: Yes. The pattern is simple and repeated
  mechanically.
- **Minimal/surgical**: Yes. Only replaces old check with new one; no
  logic changes.
- **Regression risk**: Very low. Adding validation before access can
  only make the code safer. If device isn't Ethernet, these functions
  should return early anyway.

Record: High quality fix. Uses proper kernel APIs instead of raw pointer
arithmetic.

## PHASE 3: GIT HISTORY

### Step 3.1: Blame
- The buggy code in ipset files dates from their initial introduction
- `xt_mac.c` buggy check from 2010 (Jan Engelhardt, commit
  1d1c397db95f1c)
- `ip6t_eui64.c` dates back to Linux 2.6.12 (2005)
- `nf_log_syslog.c` `dump_arp_packet` and `dump_mac_header` from the
  nf_log consolidation era

Record: Bugs present since the code was written. Affects all stable
trees.

### Step 3.2: Fixes tag
No Fixes: tag on this commit. Patch 1/2 has `Fixes: 1da177e4c3f41`
("Linux-2.6.12-rc2").

### Step 3.3: Prerequisites
This commit (2/2) depends on commit fdce0b3590f72 (1/2) for the
`ip6t_eui64.c` changes only. The other 5 files are independent.

Record: `ip6t_eui64.c` hunk requires patch 1/2 first. Other files:
standalone.

### Step 3.4: Author
Written by Zhengchuan Liang, **suggested by and signed off by Florian
Westphal** (netfilter maintainer). Very high confidence in the fix.

### Step 3.5: Dependencies
`skb_mac_header_was_set()` available since 2013. `skb_mac_header_len()`
available since 2017. Both available in all supported stable trees.

## PHASE 4: MAILING LIST RESEARCH

### Step 4.1-4.4: Patch Discussion
- **v1** (March 31, 2026): Single-patch fixing only `ip6t_eui64.c`
- Florian Westphal (netfilter maintainer) reviewed v1 and:
  - Asked "why is net/netfilter/xt_mac.c safe?" - implying it isn't
  - Suggested using `skb_mac_header_len()` instead of raw pointer checks
  - Suggested adding `ARPHRD_ETHER` device type check
  - Identified "other suspicious spots" in `nf_log_syslog.c` and ipset
  - Asked the author to make a patch covering all of them
- **v2** (April 4, 2026): Split into 2 patches. Patch 1/2 is the focused
  eui64 fix, patch 2/2 (this commit) is the broader hardening suggested
  by Florian.

Record: This patch was directly suggested and shaped by the netfilter
subsystem maintainer. Strong endorsement.

### Step 4.5: Stable Discussion
The v2 changelog mentions "KASAN report" with a PoC, indicating this is
a confirmed memory safety issue, not theoretical.

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1-5.4: Function Analysis
- `eui64_mt6()`: Called from netfilter match evaluation (PRE_ROUTING,
  LOCAL_IN, FORWARD hooks)
- `bitmap_ipmac_kadt()`, `hash_ipmac4_kadt()`, `hash_ipmac6_kadt()`,
  `hash_mac4_kadt()`: Called from ipset kernel-side operations
- `dump_arp_packet()`, `dump_mac_header()`: Called from nf_log_syslog
  packet logging
- All are reachable from packet processing paths triggered by network
  traffic

Record: All affected functions are on hot packet processing paths,
triggered by normal network traffic with appropriate netfilter rules
configured.

## PHASE 6: STABLE TREE ANALYSIS

### Step 6.1: Code Existence
- `xt_mac.c`: Unchanged since v5.4+ (will apply cleanly)
- ipset files: Unchanged since v5.15+ (will apply cleanly)
- `nf_log_syslog.c`: Has some churn but the relevant functions exist in
  v5.15+
- `ip6t_eui64.c`: Needs patch 1/2 as prerequisite

### Step 6.2: Backport Complications
For `ip6t_eui64.c`, patch 1/2 (fdce0b3590f72) must also be backported.
Other files: clean apply expected.

## PHASE 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem
- **Subsystem**: Netfilter (net/netfilter/, net/ipv6/netfilter/)
- **Criticality**: IMPORTANT - netfilter is the Linux firewall
  subsystem, used by nearly all networked systems

### Step 7.2: Activity
Active subsystem with regular maintenance.

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: Affected Users
Anyone using netfilter with MAC-address matching rules (iptables -m mac,
ip6tables eui64 match, ipset with mac types) or logging with MACDECODE
flag.

### Step 8.2: Trigger Conditions
- KASAN-confirmed: a PoC exists
- Triggered by network traffic matching rules that use MAC header access
- Could be triggered by non-Ethernet packets reaching netfilter rules
  that assume Ethernet

### Step 8.3: Severity
- **Out-of-bounds read on MAC header**: Can cause kernel crash (oops),
  potential info leak
- **KASAN-confirmed**: Severity HIGH

### Step 8.4: Risk-Benefit
- **Benefit**: HIGH - prevents memory safety bugs across 6 netfilter
  modules
- **Risk**: VERY LOW - mechanical replacement of validation checks, each
  change is 1-3 lines, obviously correct
- **Ratio**: Strongly favorable

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence
**FOR backporting:**
- KASAN-confirmed memory safety bug with PoC
- Suggested and signed off by netfilter maintainer Florian Westphal
- Tested
- Small, mechanical, obviously correct changes
- Uses proper kernel APIs
- Affects widely-used netfilter modules
- Buggy code present in all stable trees
- Functions available since kernel 4.x/5.x

**AGAINST backporting:**
- Part of a 2-patch series (ip6t_eui64.c hunk depends on patch 1/2)
- No explicit Cc: stable (expected)
- Touches 6 files (but all changes are identical pattern)

### Step 9.2: Stable Rules Checklist
1. Obviously correct? **YES** - mechanical pattern replacement,
   maintainer-suggested
2. Fixes real bug? **YES** - KASAN-confirmed out-of-bounds access
3. Important issue? **YES** - memory safety / potential crash / info
   leak
4. Small and contained? **YES** - ~37 lines total across 6 files, all
   same pattern
5. No new features? **YES** - only tightens validation
6. Can apply to stable? **YES** (with patch 1/2 for ip6t_eui64.c)

### Step 9.3: Exception Categories
Not an exception category - this is a straightforward bug fix.

### Step 9.4: Decision
This is a clear YES. Memory safety fix in the netfilter subsystem,
KASAN-confirmed, suggested by the maintainer, obviously correct, small
scope.

## Verification

- [Phase 1] Parsed tags: Suggested-by and Signed-off-by Florian Westphal
  (netfilter maintainer), Tested-by Ren Wei
- [Phase 2] Diff analysis: 6 files modified, each replacing inadequate
  MAC header validation with proper 3-part check (device type + header
  set + header length)
- [Phase 2] Confirmed `nf_log_syslog.c:dump_arp_packet()` had NO
  validation before `eth_hdr(skb)` access (line 81-83 in current tree)
- [Phase 2] Confirmed `nf_log_syslog.c:dump_mac_header()` entered
  ARPHRD_ETHER case without MAC header validity check (line 791-793)
- [Phase 3] git blame: buggy code in ip6t_eui64.c from Linux 2.6.12
  (2005), xt_mac.c from 2010, ipset from initial introduction
- [Phase 3] Confirmed patch 2/2 depends on patch 1/2 (fdce0b3590f72) for
  ip6t_eui64.c hunk only
- [Phase 3] Confirmed `skb_mac_header_was_set` available since 2013,
  `skb_mac_header_len` since 2017 - both in all supported stable trees
- [Phase 4] b4 dig found series at lore: v1->v2 evolution, v2 is [PATCH
  nf v2 2/2]
- [Phase 4] Mailing list: Florian Westphal explicitly asked for broader
  fix covering nf_log_syslog.c and ipset
- [Phase 4] v2 changelog mentions "KASAN report" with PoC confirming
  real vulnerability
- [Phase 5] All affected functions on packet processing paths (netfilter
  hooks, ipset kadt, nf_log)
- [Phase 6] xt_mac.c unchanged since v5.4, ipset files unchanged since
  v5.15 - clean apply expected
- [Phase 6] nf_log_syslog.c has more churn but relevant code sections
  exist in v5.15+
- [Phase 8] Failure mode: out-of-bounds memory read -> kernel oops or
  info leak, severity HIGH
- UNVERIFIED: Exact applicability to v5.10.y and v5.4.y for
  nf_log_syslog.c (nf_log consolidation happened around v5.12) - does
  not affect decision since most files apply cleanly

**YES**

 net/ipv6/netfilter/ip6t_eui64.c           | 7 +++++--
 net/netfilter/ipset/ip_set_bitmap_ipmac.c | 5 +++--
 net/netfilter/ipset/ip_set_hash_ipmac.c   | 9 +++++----
 net/netfilter/ipset/ip_set_hash_mac.c     | 5 +++--
 net/netfilter/nf_log_syslog.c             | 8 +++++++-
 net/netfilter/xt_mac.c                    | 4 +---
 6 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index da69a27e8332c..bbb684f9964c0 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ipv6.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 
 #include <linux/netfilter/x_tables.h>
@@ -21,8 +22,10 @@ eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 {
 	unsigned char eui64[8];
 
-	if (!(skb_mac_header(skb) >= skb->head &&
-	      skb_mac_header(skb) + ETH_HLEN <= skb->data)) {
+	if (!skb->dev || skb->dev->type != ARPHRD_ETHER)
+		return false;
+
+	if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) {
 		par->hotdrop = true;
 		return false;
 	}
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index 2c625e0f49ec0..752f59ef87442 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -11,6 +11,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/netlink.h>
 #include <linux/jiffies.h>
@@ -220,8 +221,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 		return -IPSET_ERR_BITMAP_RANGE;
 
 	/* Backward compatibility: we don't check the second flag */
-	if (skb_mac_header(skb) < skb->head ||
-	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+	if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+	    !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
 		return -EINVAL;
 
 	e.id = ip_to_id(map, ip);
diff --git a/net/netfilter/ipset/ip_set_hash_ipmac.c b/net/netfilter/ipset/ip_set_hash_ipmac.c
index 467c59a83c0ab..b9a2681e24888 100644
--- a/net/netfilter/ipset/ip_set_hash_ipmac.c
+++ b/net/netfilter/ipset/ip_set_hash_ipmac.c
@@ -11,6 +11,7 @@
 #include <linux/skbuff.h>
 #include <linux/errno.h>
 #include <linux/random.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -89,8 +90,8 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
 	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-	if (skb_mac_header(skb) < skb->head ||
-	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+	if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+	    !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
 		return -EINVAL;
 
 	if (opt->flags & IPSET_DIM_TWO_SRC)
@@ -205,8 +206,8 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
 	};
 	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-	if (skb_mac_header(skb) < skb->head ||
-	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+	if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+	    !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
 		return -EINVAL;
 
 	if (opt->flags & IPSET_DIM_TWO_SRC)
diff --git a/net/netfilter/ipset/ip_set_hash_mac.c b/net/netfilter/ipset/ip_set_hash_mac.c
index 718814730acf6..41a122591fe24 100644
--- a/net/netfilter/ipset/ip_set_hash_mac.c
+++ b/net/netfilter/ipset/ip_set_hash_mac.c
@@ -8,6 +8,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <net/netlink.h>
 
@@ -77,8 +78,8 @@ hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb,
 	struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
 	struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 
-	if (skb_mac_header(skb) < skb->head ||
-	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+	if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
+	    !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
 		return -EINVAL;
 
 	if (opt->flags & IPSET_DIM_ONE_SRC)
diff --git a/net/netfilter/nf_log_syslog.c b/net/netfilter/nf_log_syslog.c
index 41503847d9d7f..98d2b9db16efe 100644
--- a/net/netfilter/nf_log_syslog.c
+++ b/net/netfilter/nf_log_syslog.c
@@ -78,7 +78,10 @@ dump_arp_packet(struct nf_log_buf *m,
 	else
 		logflags = NF_LOG_DEFAULT_MASK;
 
-	if (logflags & NF_LOG_MACDECODE) {
+	if ((logflags & NF_LOG_MACDECODE) &&
+	    skb->dev && skb->dev->type == ARPHRD_ETHER &&
+	    skb_mac_header_was_set(skb) &&
+	    skb_mac_header_len(skb) >= ETH_HLEN) {
 		nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
 			       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
 		nf_log_dump_vlan(m, skb);
@@ -789,6 +792,9 @@ static void dump_mac_header(struct nf_log_buf *m,
 
 	switch (dev->type) {
 	case ARPHRD_ETHER:
+		if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
+			return;
+
 		nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
 			       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
 		nf_log_dump_vlan(m, skb);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 81649da57ba5d..4798cd2ca26ed 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -29,9 +29,7 @@ static bool mac_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	if (skb->dev == NULL || skb->dev->type != ARPHRD_ETHER)
 		return false;
-	if (skb_mac_header(skb) < skb->head)
-		return false;
-	if (skb_mac_header(skb) + ETH_HLEN > skb->data)
+	if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
 		return false;
 	ret  = ether_addr_equal(eth_hdr(skb)->h_source, info->srcaddr);
 	ret ^= info->invert;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-6.18] hinic3: Add msg_send_lock for message sending concurrecy
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Fan Gong, Zhu Yikai, Paolo Abeni, Sasha Levin, andrew+netdev,
	davem, edumazet, kuba, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Fan Gong <gongfan1@huawei.com>

[ Upstream commit 2a76f900d17dcb9e8322770ac9bcae34517805b3 ]

As send_mbox_msg is invoked by 3 functions: hinic3_send_mbox_to_mgmt,
hinic3_response_mbox_to_mgmt and hinic3_send_mbox_to_mgmt_no_ack, only
hinic3_response_mbox_to_mgmt does not has mutex and the other two has
mbox->mbox_send_lock because their send actions are mutually exclusive.
  As hinic3_response_mbox_to_mgmt does not conflict with them in send
actions but in mailbox resources, add the new mutex(msg_send_lock) in
send_mbox_msg to ensure message concurrency.

  Besdies, in mbox_send_seg change FIELD_PREP to FIELD_GET in
MBOX_STATUS_FINISHED and MBOX_STATUS_SUCCESS to be more reasonable.

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/d83f7f6eb4b5e94642a558fab75d61292c347e48.1773062356.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed. Let me compile the full analysis.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject Line
- **Subsystem:** `hinic3` (Huawei network driver)
- **Action verb:** "Add" (a mutex for concurrency)
- **Summary:** Adds `msg_send_lock` (actually `mbox_seg_send_lock`)
  mutex to protect `send_mbox_msg()` from concurrent access
- Record: [hinic3] [add/fix] [add mutex for message sending concurrency
  protection]

### Step 1.2: Tags
- **Co-developed-by:** Zhu Yikai
- **Signed-off-by:** Zhu Yikai, Fan Gong (primary author/submitter),
  Paolo Abeni (net maintainer)
- **Link:** to patch.msgid.link
- No Fixes: tag (expected for candidates under review)
- No Reported-by: tag (no bug report, but race found by code inspection)
- No Cc: stable tag (expected)
- Record: Accepted by net maintainer (Paolo Abeni). No syzbot/reporter.
  The author (Fan Gong) is a regular hinic3 driver developer with many
  commits.

### Step 1.3: Commit Body
- **Bug:** `send_mbox_msg()` is called by 3 functions. Two
  (`hinic3_send_mbox_to_mgmt`, `hinic3_send_mbox_to_mgmt_no_ack`) hold
  `mbox_send_lock`, but `hinic3_response_mbox_to_mgmt` does not. Since
  `hinic3_response_mbox_to_mgmt` can run concurrently with the others
  and they all share hardware mailbox resources, a race condition
  exists.
- **Also:** FIELD_PREP changed to FIELD_GET in two macros (cosmetic fix
  for semantic correctness).
- Record: Race condition in shared hardware mailbox resources. The
  response function can run from a workqueue handler concurrently with
  user-initiated sends.

### Step 1.4: Hidden Bug Fix Detection
- This is an explicit concurrency fix, not disguised. The commit message
  openly describes the missing synchronization.
- Record: Not a hidden fix; explicitly described race condition fix.

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
- **Files:** `hinic3_mbox.c` (+4/-2), `hinic3_mbox.h` (+4/+0)
- **Functions modified:** `MBOX_STATUS_FINISHED` macro,
  `MBOX_STATUS_SUCCESS` macro, `hinic3_mbox_pre_init()`,
  `send_mbox_msg()`
- **Scope:** Small, single-subsystem, surgical fix. ~8 net new lines.
- Record: 2 files, ~8 lines added, minimal scope.

### Step 2.2: Code Flow Change
1. **FIELD_PREP→FIELD_GET macros:** For mask 0xFF (starts at bit 0),
   both produce `val & 0xFF`. No functional change — purely semantic
   correctness.
2. **`hinic3_mbox_pre_init()`:** Added
   `mutex_init(&mbox->mbox_seg_send_lock)`.
3. **`send_mbox_msg()`:** Wraps the entire message preparation and
   segment send loop with
   `mutex_lock/unlock(&mbox->mbox_seg_send_lock)`.
- Record: Before: `send_mbox_msg()` had no internal locking. After:
  Protected by `mbox_seg_send_lock`.

### Step 2.3: Bug Mechanism
- **Category:** Race condition / synchronization fix
- **Mechanism:** `hinic3_response_mbox_to_mgmt()` calls
  `send_mbox_msg()` without any lock. Concurrently,
  `hinic3_send_mbox_to_mgmt()` or `hinic3_send_mbox_to_mgmt_no_ack()`
  can also call `send_mbox_msg()`. Both paths access the shared hardware
  mailbox area (`mbox->send_mbox`), including MMIO writes, DMA writeback
  status, and hardware control registers. Without the new lock,
  interleaved access corrupts mailbox state.
- Record: Race condition on shared hardware mailbox resources between
  response and send paths.

### Step 2.4: Fix Quality
- The fix is obviously correct: adds a mutex around a shared critical
  section.
- The lock hierarchy is documented: `mbox_send_lock ->
  mbox_seg_send_lock`.
- No deadlock risk: `mbox_seg_send_lock` is always the innermost lock.
- The FIELD_PREP→FIELD_GET change is a no-op for 0xFF mask but adds
  clutter.
- Record: Fix is correct, minimal, well-documented hierarchy. Low
  regression risk.

## PHASE 3: GIT HISTORY

### Step 3.1: Blame
- All of `send_mbox_msg()` and the macros were introduced by commit
  `a8255ea56aee9` (Fan Gong, 2025-08-20) "hinic3: Mailbox management
  interfaces".
- `hinic3_response_mbox_to_mgmt()` was introduced by `a30cc9b277903`
  (Fan Gong, 2026-01-14) "hinic3: Add PF management interfaces".
- The race has existed since PF management was added (a30cc9b), which
  first introduced the unprotected call path from a workqueue.
- Record: Bug introduced in a30cc9b277903 (v6.19 timeframe), present in
  7.0 tree.

### Step 3.2: Fixes Tag
- No Fixes: tag present. Expected for this review pipeline.

### Step 3.3: File History
- hinic3 is a very new driver, first appearing in v6.16-rc1.
- The mbox code has been stable since initial introduction, with only
  minor style fixes.
- Record: Standalone fix, no prerequisites needed beyond existing code.

### Step 3.4: Author
- Fan Gong is the primary hinic3 driver developer with 10+ commits.
- Record: Author is the driver developer/maintainer.

### Step 3.5: Dependencies
- This patch is self-contained. It adds a new mutex field and uses it.
  No other patches needed.
- Record: No dependencies. Applies standalone.

## PHASE 4: MAILING LIST

### Step 4.1-4.5
- b4 dig could not find this specific commit (it may not be in the
  current tree yet since it's a candidate).
- The original mailbox commit series was found via b4 dig for the parent
  commit.
- lore.kernel.org was blocked by bot protection during fetch.
- The patch was accepted by Paolo Abeni (net maintainer), giving it
  strong review credibility.
- Record: Accepted by net maintainer. Could not fetch full lore
  discussion due to access restrictions.

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1-5.4: Function Analysis
- `send_mbox_msg()` is called from 3 places (confirmed by grep):
  1. `hinic3_send_mbox_to_mgmt()` (line 815) - holds `mbox_send_lock`
  2. `hinic3_response_mbox_to_mgmt()` (line 873) - NO lock held
  3. `hinic3_send_mbox_to_mgmt_no_ack()` (line 886) - holds
     `mbox_send_lock`
- `hinic3_response_mbox_to_mgmt()` is called from
  `hinic3_recv_mgmt_msg_work_handler()` in a workqueue, triggered by
  incoming management messages from firmware.
- `hinic3_send_mbox_to_mgmt()` is called from many places: RSS config,
  NIC config, EQ setup, HW comm, command queue — any management
  operation.
- The race is easily triggerable: if the driver receives a management
  message while simultaneously sending one (very common scenario during
  initialization or config changes).
- Record: Race is reachable from normal driver operation paths.

### Step 5.5: Similar Patterns
- The older hinic driver (drivers/net/ethernet/huawei/hinic/) uses
  similar mbox locking patterns.
- Record: Pattern is common in Huawei NIC drivers.

## PHASE 6: STABLE TREE ANALYSIS

### Step 6.1: Code in Stable Trees
- hinic3 was introduced in v6.16-rc1. This commit is for v7.0 stable.
- The buggy code exists in the 7.0 tree (confirmed by reading the
  files).
- The driver does NOT exist in older stable trees (6.12.y, 6.6.y, etc.).
- Record: Code exists only in 7.0 stable tree.

### Step 6.2: Backport Complications
- The patch should apply cleanly to 7.0 — the files haven't changed
  significantly.
- Record: Clean apply expected.

### Step 6.3: Related Fixes
- No related fixes for this issue already in stable.
- Record: No existing related fixes.

## PHASE 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem Criticality
- drivers/net/ethernet/ — network driver, IMPORTANT level
- hinic3 is a Huawei enterprise NIC driver (used in Huawei server
  platforms)
- Record: [Network driver] [IMPORTANT — enterprise NIC used in Huawei
  servers]

### Step 7.2: Subsystem Activity
- Very active — new driver still being built out with many patches.
- Record: Highly active.

## PHASE 8: IMPACT AND RISK

### Step 8.1: Affected Users
- Users of Huawei hinic3 NICs (enterprise/datacenter environments).
- Record: Driver-specific but enterprise users.

### Step 8.2: Trigger Conditions
- Triggered when a management response from the workqueue coincides with
  a management send. This is realistic during driver initialization,
  configuration changes, or firmware events.
- Record: Realistic trigger during normal NIC operation.

### Step 8.3: Failure Mode
- Corrupted mailbox messages → firmware communication failure → garbled
  responses, timeouts, potential driver malfunction.
- Severity: HIGH (hardware communication failure, potential driver
  instability)
- Record: Hardware mailbox corruption, driver instability. Severity
  HIGH.

### Step 8.4: Risk-Benefit
- **Benefit:** Fixes a real race condition in hardware resource access.
  Prevents mailbox corruption. HIGH.
- **Risk:** ~8 lines, adds a well-understood mutex. VERY LOW.
- Record: Excellent risk-benefit ratio.

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence Summary
**FOR backporting:**
- Fixes a real race condition in concurrent access to shared hardware
  mailbox resources
- Small, surgical fix (~8 lines of real change)
- Self-contained, no dependencies
- Author is the driver developer, patch accepted by net maintainer
- Code exists in 7.0 stable tree
- Clean apply expected
- Race is triggerable under normal operation (workqueue response vs.
  user send)

**AGAINST backporting:**
- No Fixes: tag, no Reported-by: (found by code inspection, not user
  report)
- Bundles a cosmetic change (FIELD_PREP→FIELD_GET) with the race fix
- Very new driver (first in 6.16), limited user base
- The FIELD_PREP→FIELD_GET change is functionally a no-op for mask 0xFF

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **YES** — standard mutex addition,
   accepted by maintainer
2. Fixes real bug? **YES** — race condition in hardware resource access
3. Important issue? **YES** — can cause driver/firmware communication
   failure
4. Small and contained? **YES** — ~8 lines, 2 files in same driver
5. No new features? **Correct** — no new features
6. Applies to stable? **YES** — should apply cleanly to 7.0

### Step 9.3: Exception Categories
- Not an exception category; this is a standard race condition fix.

### Verification
- [Phase 1] Parsed commit message: race condition described for
  `send_mbox_msg()` concurrent access
- [Phase 2] Diff: mutex_init + lock/unlock in `send_mbox_msg()`,
  FIELD_PREP→FIELD_GET (no-op for 0xFF)
- [Phase 3] git blame: `send_mbox_msg()` from a8255ea56aee9
  (2025-08-20), response caller from a30cc9b277903 (2026-01-14)
- [Phase 3] git describe: hinic3 first in v6.16-rc1, present in v7.0
- [Phase 4] b4 dig: could not find this specific commit in local repo
  (candidate not yet applied)
- [Phase 4] Lore fetch blocked by bot protection
- [Phase 5] grep confirmed 3 callers of `send_mbox_msg()`, only response
  path is unprotected
- [Phase 5] Confirmed `hinic3_response_mbox_to_mgmt()` called from
  workqueue handler (`hinic3_recv_mgmt_msg_work_handler`)
- [Phase 5] Confirmed shared resources: `mbox->send_mbox` (MMIO data
  area), writeback status, HW registers
- [Phase 6] Code exists in 7.0 tree, confirmed by reading files
- [Phase 8] Race is triggerable during normal NIC operation when mgmt
  response and send overlap
- UNVERIFIED: Could not read full mailing list discussion due to lore
  access restriction

The fix addresses a genuine race condition where concurrent calls to
`send_mbox_msg()` from an unprotected response path and a locked send
path can corrupt shared hardware mailbox resources. The fix is small,
surgical, obviously correct, and self-contained. The bundled
FIELD_PREP→FIELD_GET change is a no-op for the specific mask value (0xFF
at bit position 0) and adds no risk.

**YES**

 drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c | 9 +++++++--
 drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h | 4 ++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
index 826fa8879a113..65528b2a7b7c8 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
@@ -50,9 +50,9 @@
 #define MBOX_WB_STATUS_NOT_FINISHED      0x00
 
 #define MBOX_STATUS_FINISHED(wb)  \
-	((FIELD_PREP(MBOX_WB_STATUS_MASK, (wb))) != MBOX_WB_STATUS_NOT_FINISHED)
+	((FIELD_GET(MBOX_WB_STATUS_MASK, (wb))) != MBOX_WB_STATUS_NOT_FINISHED)
 #define MBOX_STATUS_SUCCESS(wb)  \
-	((FIELD_PREP(MBOX_WB_STATUS_MASK, (wb))) ==  \
+	((FIELD_GET(MBOX_WB_STATUS_MASK, (wb))) ==  \
 	MBOX_WB_STATUS_FINISHED_SUCCESS)
 #define MBOX_STATUS_ERRCODE(wb)  \
 	((wb) & MBOX_WB_ERROR_CODE_MASK)
@@ -395,6 +395,7 @@ static int hinic3_mbox_pre_init(struct hinic3_hwdev *hwdev,
 {
 	mbox->hwdev = hwdev;
 	mutex_init(&mbox->mbox_send_lock);
+	mutex_init(&mbox->mbox_seg_send_lock);
 	spin_lock_init(&mbox->mbox_lock);
 
 	mbox->workq = create_singlethread_workqueue(HINIC3_MBOX_WQ_NAME);
@@ -706,6 +707,8 @@ static int send_mbox_msg(struct hinic3_mbox *mbox, u8 mod, u16 cmd,
 	else
 		rsp_aeq_id = 0;
 
+	mutex_lock(&mbox->mbox_seg_send_lock);
+
 	if (dst_func == MBOX_MGMT_FUNC_ID &&
 	    !(hwdev->features[0] & MBOX_COMM_F_MBOX_SEGMENT)) {
 		err = mbox_prepare_dma_msg(mbox, ack_type, &dma_msg,
@@ -759,6 +762,8 @@ static int send_mbox_msg(struct hinic3_mbox *mbox, u8 mod, u16 cmd,
 	}
 
 err_send:
+	mutex_unlock(&mbox->mbox_seg_send_lock);
+
 	return err;
 }
 
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h
index e26f22d1d5641..30de0c1295038 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h
@@ -114,6 +114,10 @@ struct hinic3_mbox {
 	struct hinic3_hwdev       *hwdev;
 	/* lock for send mbox message and ack message */
 	struct mutex              mbox_send_lock;
+	/* lock for send message transmission.
+	 * The lock hierarchy is mbox_send_lock -> mbox_seg_send_lock.
+	 */
+	struct mutex              mbox_seg_send_lock;
 	struct hinic3_send_mbox   send_mbox;
 	struct mbox_dma_queue     sync_msg_queue;
 	struct mbox_dma_queue     async_msg_queue;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] netfilter: ctnetlink: ensure safe access to master conntrack
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Pablo Neira Ayuso, Florian Westphal, Sasha Levin, davem, edumazet,
	kuba, pabeni, netfilter-devel, coreteam, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>

[ Upstream commit bffcaad9afdfe45d7fc777397d3b83c1e3ebffe5 ]

Holding reference on the expectation is not sufficient, the master
conntrack object can just go away, making exp->master invalid.

To access exp->master safely:

- Grab the nf_conntrack_expect_lock, this gets serialized with
  clean_from_lists() which also holds this lock when the master
  conntrack goes away.

- Hold reference on master conntrack via nf_conntrack_find_get().
  Not so easy since the master tuple to look up for the master conntrack
  is not available in the existing problematic paths.

This patch goes for extending the nf_conntrack_expect_lock section
to address this issue for simplicity, in the cases that are described
below this is just slightly extending the lock section.

The add expectation command already holds a reference to the master
conntrack from ctnetlink_create_expect().

However, the delete expectation command needs to grab the spinlock
before looking up for the expectation. Expand the existing spinlock
section to address this to cover the expectation lookup. Note that,
the nf_ct_expect_iterate_net() calls already grabs the spinlock while
iterating over the expectation table, which is correct.

The get expectation command needs to grab the spinlock to ensure master
conntrack does not go away. This also expands the existing spinlock
section to cover the expectation lookup too. I needed to move the
netlink skb allocation out of the spinlock to keep it GFP_KERNEL.

For the expectation events, the IPEXP_DESTROY event is already delivered
under the spinlock, just move the delivery of IPEXP_NEW under the
spinlock too because the master conntrack event cache is reached through
exp->master.

While at it, add lockdep notations to help identify what codepaths need
to grab the spinlock.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 include/net/netfilter/nf_conntrack_core.h |  5 ++++
 net/netfilter/nf_conntrack_ecache.c       |  2 ++
 net/netfilter/nf_conntrack_expect.c       | 10 +++++++-
 net/netfilter/nf_conntrack_netlink.c      | 28 +++++++++++++++--------
 4 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 3384859a89210..8883575adcc1e 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -83,6 +83,11 @@ void nf_conntrack_lock(spinlock_t *lock);
 
 extern spinlock_t nf_conntrack_expect_lock;
 
+static inline void lockdep_nfct_expect_lock_held(void)
+{
+	lockdep_assert_held(&nf_conntrack_expect_lock);
+}
+
 /* ctnetlink code shared by both ctnetlink and nf_conntrack_bpf */
 
 static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 81baf20826046..9df159448b897 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -247,6 +247,8 @@ void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
 	struct nf_ct_event_notifier *notify;
 	struct nf_conntrack_ecache *e;
 
+	lockdep_nfct_expect_lock_held();
+
 	rcu_read_lock();
 	notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
 	if (!notify)
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 2234c444a320e..24d0576d84b7f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -51,6 +51,7 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
 	struct net *net = nf_ct_exp_net(exp);
 	struct nf_conntrack_net *cnet;
 
+	lockdep_nfct_expect_lock_held();
 	WARN_ON(!master_help);
 	WARN_ON(timer_pending(&exp->timeout));
 
@@ -118,6 +119,8 @@ nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple,
 
 bool nf_ct_remove_expect(struct nf_conntrack_expect *exp)
 {
+	lockdep_nfct_expect_lock_held();
+
 	if (timer_delete(&exp->timeout)) {
 		nf_ct_unlink_expect(exp);
 		nf_ct_expect_put(exp);
@@ -177,6 +180,8 @@ nf_ct_find_expectation(struct net *net,
 	struct nf_conntrack_expect *i, *exp = NULL;
 	unsigned int h;
 
+	lockdep_nfct_expect_lock_held();
+
 	if (!cnet->expect_count)
 		return NULL;
 
@@ -459,6 +464,8 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
 	unsigned int h;
 	int ret = 0;
 
+	lockdep_nfct_expect_lock_held();
+
 	if (!master_help) {
 		ret = -ESHUTDOWN;
 		goto out;
@@ -515,8 +522,9 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
 
 	nf_ct_expect_insert(expect);
 
-	spin_unlock_bh(&nf_conntrack_expect_lock);
 	nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
+	spin_unlock_bh(&nf_conntrack_expect_lock);
+
 	return 0;
 out:
 	spin_unlock_bh(&nf_conntrack_expect_lock);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 879413b9fa06a..becffc15e7579 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3337,31 +3337,37 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
 	if (err < 0)
 		return err;
 
+	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb2)
+		return -ENOMEM;
+
+	spin_lock_bh(&nf_conntrack_expect_lock);
 	exp = nf_ct_expect_find_get(info->net, &zone, &tuple);
-	if (!exp)
+	if (!exp) {
+		spin_unlock_bh(&nf_conntrack_expect_lock);
+		kfree_skb(skb2);
 		return -ENOENT;
+	}
 
 	if (cda[CTA_EXPECT_ID]) {
 		__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
 
 		if (id != nf_expect_get_id(exp)) {
 			nf_ct_expect_put(exp);
+			spin_unlock_bh(&nf_conntrack_expect_lock);
+			kfree_skb(skb2);
 			return -ENOENT;
 		}
 	}
 
-	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!skb2) {
-		nf_ct_expect_put(exp);
-		return -ENOMEM;
-	}
-
 	rcu_read_lock();
 	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
 				      info->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
 				      exp);
 	rcu_read_unlock();
 	nf_ct_expect_put(exp);
+	spin_unlock_bh(&nf_conntrack_expect_lock);
+
 	if (err <= 0) {
 		kfree_skb(skb2);
 		return -ENOMEM;
@@ -3408,22 +3414,26 @@ static int ctnetlink_del_expect(struct sk_buff *skb,
 		if (err < 0)
 			return err;
 
+		spin_lock_bh(&nf_conntrack_expect_lock);
+
 		/* bump usage count to 2 */
 		exp = nf_ct_expect_find_get(info->net, &zone, &tuple);
-		if (!exp)
+		if (!exp) {
+			spin_unlock_bh(&nf_conntrack_expect_lock);
 			return -ENOENT;
+		}
 
 		if (cda[CTA_EXPECT_ID]) {
 			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
 
 			if (id != nf_expect_get_id(exp)) {
 				nf_ct_expect_put(exp);
+				spin_unlock_bh(&nf_conntrack_expect_lock);
 				return -ENOENT;
 			}
 		}
 
 		/* after list removal, usage count == 1 */
-		spin_lock_bh(&nf_conntrack_expect_lock);
 		if (timer_delete(&exp->timeout)) {
 			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
 						   nlmsg_report(info->nlh));
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-5.10] net: hamradio: bpqether: validate frame length in bpq_rcv()
From: Sasha Levin @ 2026-04-20 13:21 UTC (permalink / raw)
  To: patches, stable
  Cc: Mashiro Chen, Joerg Reuter, Jakub Kicinski, Sasha Levin,
	andrew+netdev, davem, edumazet, pabeni, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Mashiro Chen <mashiro.chen@mailbox.org>

[ Upstream commit 6183bd8723a3eecd2d89cbc506fe938bc6288345 ]

The BPQ length field is decoded as:

  len = skb->data[0] + skb->data[1] * 256 - 5;

If the sender sets bytes [0..1] to values whose combined value is
less than 5, len becomes negative.  Passing a negative int to
skb_trim() silently converts to a huge unsigned value, causing the
function to be a no-op.  The frame is then passed up to AX.25 with
its original (untrimmed) payload, delivering garbage beyond the
declared frame boundary.

Additionally, a negative len corrupts the 64-bit rx_bytes counter
through implicit sign-extension.

Add a bounds check before pulling the length bytes: reject frames
where len is negative or exceeds the remaining skb data.

Acked-by: Joerg Reuter <jreuter@yaina.de>
Signed-off-by: Mashiro Chen <mashiro.chen@mailbox.org>
Link: https://patch.msgid.link/20260409024927.24397-2-mashiro.chen@mailbox.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information I need. Let me compile the complete
analysis.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: Subject Line**
- Subsystem: `net: hamradio: bpqether`
- Action verb: "validate" — implies adding a missing safety check (a bug
  fix)
- Summary: Add bounds checking to the frame length parsing in
  `bpq_rcv()`
Record: [net/hamradio/bpqether] [validate] [Add missing frame length
bounds check in receive path]

**Step 1.2: Tags**
- `Acked-by: Joerg Reuter <jreuter@yaina.de>` — Joerg Reuter IS the
  hamradio subsystem maintainer (confirmed from MODULE_AUTHOR)
- `Signed-off-by: Mashiro Chen <mashiro.chen@mailbox.org>` — patch
  author
- `Link: https://patch.msgid.link/20260409024927.24397-2-
  mashiro.chen@mailbox.org` — lore reference
- `Signed-off-by: Jakub Kicinski <kuba@kernel.org>` — netdev maintainer
  applied it
- IMPORTANT: The original submission (from the mbox) includes `Cc:
  stable@vger.kernel.org` which was stripped during merge
Record: Acked by subsystem maintainer. Originally Cc'd to stable.
Applied by netdev maintainer.

**Step 1.3: Commit Body**
The bug mechanism is clearly described:
- `len = skb->data[0] + skb->data[1] * 256 - 5` can produce a negative
  value if bytes [0..1] sum to < 5
- Passing negative `int` to `skb_trim(unsigned int)` produces a huge
  unsigned value, making it a no-op
- Frame is delivered to AX.25 with untrimmed garbage payload
- Negative `len` also corrupts the 64-bit `rx_bytes` counter via
  implicit sign-extension
Record: Bug is clearly described with specific mechanism. Two distinct
problems: garbage data delivery and stats corruption.

**Step 1.4: Hidden Bug Fix**
This is explicitly a validation/bug fix — "validate" means adding a
missing safety check.
Record: Not hidden — explicitly a bug fix adding missing input
validation.

## PHASE 2: DIFF ANALYSIS

**Step 2.1: Inventory**
- 1 file modified: `drivers/net/hamradio/bpqether.c`
- +3 lines added, 0 removed
- Function modified: `bpq_rcv()`
- Scope: single-file surgical fix
Record: [1 file, +3 lines, bpq_rcv()] [Minimal single-file fix]

**Step 2.2: Code Flow Change**
The single hunk inserts a bounds check after the length calculation:

```190:192:drivers/net/hamradio/bpqether.c
        if (len < 0 || len > skb->len - 2)
                goto drop_unlock;
```

- BEFORE: `len` is calculated and used unconditionally — negative `len`
  passes through
- AFTER: Negative or oversized `len` causes the frame to be dropped
- This is on the data receive path (normal path for incoming frames)
Record: [Before: no validation on computed len → After: reject frames
with invalid len]

**Step 2.3: Bug Mechanism**
Category: **Logic/correctness fix + type conversion bug**
- `len` is `int` (line 152), computed from untrusted network data
- `skb_trim()` takes `unsigned int len` (confirmed from header: `void
  skb_trim(struct sk_buff *skb, unsigned int len)`)
- Negative `int` → huge `unsigned int` → `skb->len > len` is false → no
  trimming occurs
- `dev->stats.rx_bytes += len` with negative `len` corrupts stats via
  sign extension to 64-bit

The fix also checks `len > skb->len - 2` to reject frames claiming more
data than present (the `-2` accounts for the 2 length bytes about to be
pulled).
Record: [Type conversion bug causing no-op trim + stats corruption. Fix
adds proper bounds check.]

**Step 2.4: Fix Quality**
- Obviously correct: a bounds check of `len < 0 || len > skb->len - 2`
  before using `len`
- Minimal/surgical: 3 lines in one location
- No regression risk: rejecting invalid frames cannot harm valid
  operation
- Uses existing `drop_unlock` error path (already well-tested)
Record: [Clearly correct, minimal, no regression risk]

## PHASE 3: GIT HISTORY

**Step 3.1: Blame**
The buggy line (`len = skb->data[0] + skb->data[1] * 256 - 5`) dates to
commit `1da177e4c3f41` — Linus Torvalds' initial Linux import
(2005-04-16). This code has been present in every Linux version ever
released.
Record: [Bug present since initial Linux git commit — affects ALL stable
trees]

**Step 3.2: Fixes Tag**
No explicit `Fixes:` tag. The buggy code predates git history.
Record: [N/A — bug predates git history, all stable trees affected]

**Step 3.3: File History**
Recent changes to `bpqether.c` are all unrelated refactoring (lockdep,
netdev_features, dev_addr_set). None touch the `bpq_rcv()` length
parsing logic. The function `bpq_rcv` hasn't been meaningfully modified
in its length handling since the initial commit.
Record: [No related changes or prerequisites. Standalone fix.]

**Step 3.4: Author**
Mashiro Chen appears to be a contributor fixing input validation issues
(this series fixes two hamradio drivers). The patch was Acked by Joerg
Reuter (subsystem maintainer) and applied by Jakub Kicinski (netdev
maintainer).
Record: [Contributor fix, but Acked by subsystem maintainer and applied
by netdev maintainer — high confidence]

**Step 3.5: Dependencies**
This is patch 1/2 in a series, but both patches are independent
(different files: `bpqether.c` vs `scc.c`). No dependencies.
Record: [Self-contained, no dependencies. Applies standalone.]

## PHASE 4: MAILING LIST RESEARCH

**Step 4.1: Original Discussion**
From the b4 am output, the thread at
`20260409024927.24397-1-mashiro.chen@mailbox.org` contains 5 messages.
This is v2; the change between v1 and v2 for bpqether was only "add
Acked-by: Joerg Reuter" (no code change).

Critical finding from the mbox: **The original patch included `Cc:
stable@vger.kernel.org`**, indicating the author explicitly nominated it
for stable. This tag was stripped during the merge process (common
netdev practice).
Record: [Original submission Cc'd to stable. v2 adds only Acked-by.
Acked by subsystem maintainer.]

**Step 4.2: Reviewers**
- Acked-by: Joerg Reuter (hamradio subsystem maintainer)
- Applied by: Jakub Kicinski (netdev co-maintainer)
- CC'd to linux-hams mailing list
Record: [Reviewed by the right people]

**Step 4.3-4.5: Bug Report / Stable Discussion**
No external bug report referenced. This appears to be found by code
inspection. The author explicitly Cc'd stable.
Record: [Found by code inspection, author nominated for stable]

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: Functions Modified**
Only `bpq_rcv()`.

**Step 5.2: Callers**
`bpq_rcv` is registered as a packet_type handler via
`bpq_packet_type.func = bpq_rcv` (line 93). It is called by the kernel
networking stack for every incoming BPQ ethernet frame (`ETH_P_BPQ`).
This is the main receive path for the driver.
Record: [Called by kernel network stack on every incoming BPQ frame]

**Step 5.3-5.4: Call Chain**
The receive path: network driver → netif_receive_skb → protocol dispatch
→ `bpq_rcv()` → ax25_type_trans → netif_rx.
Any BPQ frame arriving on the network can trigger this. No special
privileges needed to send a malformed Ethernet frame on a local network.
Record: [Reachable from any incoming network frame — attack surface for
local network]

**Step 5.5: Similar Patterns**
The second patch in the series fixes a similar input validation issue in
`scc.c`, suggesting systematic review of hamradio drivers.
Record: [Systematic validation audit by author]

## PHASE 6: CROSS-REFERENCING AND STABLE TREE ANALYSIS

**Step 6.1: Code Exists in Stable?**
Yes. The buggy code (line 188: `len = skb->data[0] + skb->data[1] * 256
- 5`) has been present since the initial commit and exists in ALL stable
trees. The changes since v5.4 and v6.1 to this file are all unrelated
refactoring that don't touch the `bpq_rcv()` length logic.
Record: [Bug exists in ALL stable trees from v5.4 through v7.0]

**Step 6.2: Backport Complications**
None. The surrounding code in `bpq_rcv()` is essentially unchanged. The
fix is a 3-line insertion with no context dependencies on recent
changes.
Record: [Clean apply expected to all stable trees]

**Step 6.3: Related Fixes Already in Stable**
No prior fix for this issue exists.
Record: [No prior fix]

## PHASE 7: SUBSYSTEM CONTEXT

**Step 7.1: Subsystem**
- Path: `drivers/net/hamradio/` — Amateur (ham) radio networking driver
- Criticality: PERIPHERAL (niche driver for ham radio enthusiasts)
- However: it processes network frames and the bug is a missing input
  validation — security relevance
Record: [Peripheral subsystem, but network input validation issue gives
it security relevance]

**Step 7.2: Activity**
The file has had minimal changes. Mature, stable code that rarely gets
touched.
Record: [Very mature code — bug has been present for ~20 years]

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: Who Is Affected**
Users of the BPQ (AX.25-over-Ethernet) hamradio protocol. While niche,
these are real users.
Record: [Driver-specific: ham radio BPQ users]

**Step 8.2: Trigger Conditions**
- Any malformed BPQ frame with length field < 5 triggers the bug
- Can be triggered by any device on the local Ethernet segment (no
  privileges needed)
- Reliably reproducible — no race condition
Record: [Triggered by malformed network frame from local network,
reliably reproducible, no auth needed]

**Step 8.3: Failure Mode**
- Garbage data delivered to AX.25 protocol — potential info leak /
  protocol confusion
- Stats counter corruption (rx_bytes goes wildly negative)
- Severity: MEDIUM-HIGH (garbage data delivery from network, potential
  security implication)
Record: [Garbage data delivery + stats corruption. Severity: MEDIUM-
HIGH]

**Step 8.4: Risk-Benefit**
- BENEFIT: Prevents garbage data delivery and counter corruption from
  malformed frames. Has been broken for 20 years.
- RISK: Extremely low. 3-line bounds check using existing `drop_unlock`
  path. Obviously correct.
Record: [High benefit, very low risk. Excellent ratio.]

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: Evidence Compilation**

FOR backporting:
- Fixes a real input validation bug present since the initial Linux
  commit
- 3-line surgical fix — minimal risk
- Obviously correct bounds check
- Acked by subsystem maintainer (Joerg Reuter)
- Applied by netdev co-maintainer (Jakub Kicinski)
- Author explicitly Cc'd stable@vger.kernel.org in original submission
- Prevents garbage data delivery to AX.25 from malformed frames
- Prevents stats counter corruption
- Will apply cleanly to all stable trees
- No dependencies, self-contained

AGAINST backporting:
- Niche driver (ham radio) — limited user base
- No crash/panic, "only" garbage data and stats corruption

**Step 9.2: Stable Rules Checklist**
1. Obviously correct and tested? **YES** — trivial bounds check, Acked
   by maintainer
2. Fixes a real bug? **YES** — garbage data delivery + counter
   corruption
3. Important issue? **YES** — input validation on network data
   (security-adjacent)
4. Small and contained? **YES** — 3 lines, 1 file
5. No new features/APIs? **YES** — pure bug fix
6. Applies to stable? **YES** — code unchanged since initial commit

**Step 9.3: Exception Categories**
Not an exception category — this is a standard bug fix.

**Step 9.4: Decision**
This is a textbook stable backport: small, obviously correct input
validation fix for network-facing code, Acked by subsystem maintainer,
explicitly nominated for stable by author, fixes a 20-year-old bug.

## Verification

- [Phase 1] Parsed tags: Acked-by Joerg Reuter, Link to
  patch.msgid.link, SOB from Jakub Kicinski
- [Phase 2] Diff analysis: +3 lines adding bounds check in `bpq_rcv()`
  before `skb_trim`/`skb_pull`
- [Phase 2] Confirmed `skb_trim()` takes `unsigned int len`
  (include/linux/skbuff.h:3321)
- [Phase 3] git blame: buggy code from commit 1da177e4c3f41 (Linus
  initial, 2005-04-16), present in all stable trees
- [Phase 3] git log: no recent changes touch the length handling in
  bpq_rcv()
- [Phase 4] b4 am: found original thread, 5 messages, v2 series with 2
  patches
- [Phase 4] Read mbox: original submission includes `Cc:
  stable@vger.kernel.org` (line 28 of mbx)
- [Phase 4] Cover letter: v2 changes for bpqether are "no code change;
  add Acked-by"
- [Phase 5] bpq_rcv registered as packet_type handler, called on every
  incoming BPQ frame
- [Phase 6] Code exists in all active stable trees (v5.4+), no
  divergence in affected lines
- [Phase 6] Clean apply expected — surrounding code unchanged
- [Phase 8] Failure mode: garbage data to AX.25 + counter corruption,
  severity MEDIUM-HIGH

**YES**

 drivers/net/hamradio/bpqether.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 045c5177262ea..214fd1f819a1b 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -187,6 +187,9 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
 
 	len = skb->data[0] + skb->data[1] * 256 - 5;
 
+	if (len < 0 || len > skb->len - 2)
+		goto drop_unlock;
+
 	skb_pull(skb, 2);	/* Remove the length bytes */
 	skb_trim(skb, len);	/* Set the length of the data */
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] bridge: guard local VLAN-0 FDB helpers against NULL vlan group
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Zijing Yin, Ido Schimmel, Nikolay Aleksandrov, Jakub Kicinski,
	Sasha Levin, davem, edumazet, pabeni, petrm, bridge, netdev,
	linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Zijing Yin <yzjaurora@gmail.com>

[ Upstream commit 1979645e1842cb7017525a61a0e0e0beb924d02a ]

When CONFIG_BRIDGE_VLAN_FILTERING is not set, br_vlan_group() and
nbp_vlan_group() return NULL (br_private.h stub definitions). The
BR_BOOLOPT_FDB_LOCAL_VLAN_0 toggle code is compiled unconditionally and
reaches br_fdb_delete_locals_per_vlan_port() and
br_fdb_insert_locals_per_vlan_port(), where the NULL vlan group pointer
is dereferenced via list_for_each_entry(v, &vg->vlan_list, vlist).

The observed crash is in the delete path, triggered when creating a
bridge with IFLA_BR_MULTI_BOOLOPT containing BR_BOOLOPT_FDB_LOCAL_VLAN_0
via RTM_NEWLINK. The insert helper has the same bug pattern.

  Oops: general protection fault, probably for non-canonical address 0xdffffc0000000056: 0000 [#1] KASAN NOPTI
  KASAN: null-ptr-deref in range [0x00000000000002b0-0x00000000000002b7]
  RIP: 0010:br_fdb_delete_locals_per_vlan+0x2b9/0x310
  Call Trace:
   br_fdb_toggle_local_vlan_0+0x452/0x4c0
   br_toggle_fdb_local_vlan_0+0x31/0x80 net/bridge/br.c:276
   br_boolopt_toggle net/bridge/br.c:313
   br_boolopt_multi_toggle net/bridge/br.c:364
   br_changelink net/bridge/br_netlink.c:1542
   br_dev_newlink net/bridge/br_netlink.c:1575

Add NULL checks for the vlan group pointer in both helpers, returning
early when there are no VLANs to iterate. This matches the existing
pattern used by other bridge FDB functions such as br_fdb_add() and
br_fdb_delete().

Fixes: 21446c06b441 ("net: bridge: Introduce UAPI for BR_BOOLOPT_FDB_LOCAL_VLAN_0")
Signed-off-by: Zijing Yin <yzjaurora@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20260402140153.3925663-1-yzjaurora@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/bridge/br_fdb.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 0501ffcb8a3dd..e2c17f620f009 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -597,6 +597,9 @@ static void br_fdb_delete_locals_per_vlan_port(struct net_bridge *br,
 		dev = br->dev;
 	}
 
+	if (!vg)
+		return;
+
 	list_for_each_entry(v, &vg->vlan_list, vlist)
 		br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid);
 }
@@ -630,6 +633,9 @@ static int br_fdb_insert_locals_per_vlan_port(struct net_bridge *br,
 		dev = br->dev;
 	}
 
+	if (!vg)
+		return 0;
+
 	list_for_each_entry(v, &vg->vlan_list, vlist) {
 		if (!br_vlan_should_use(v))
 			continue;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] netfilter: nft_set_pipapo_avx2: don't return non-matching entry on expiry
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Florian Westphal, Stefano Brivio, Pablo Neira Ayuso, Sasha Levin,
	davem, edumazet, kuba, pabeni, netfilter-devel, coreteam, netdev,
	linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Florian Westphal <fw@strlen.de>

[ Upstream commit d3c0037ffe1273fa1961e779ff6906234d6cf53c ]

New test case fails unexpectedly when avx2 matching functions are used.

The test first loads a ranomly generated pipapo set
with 'ipv4 . port' key, i.e.  nft -f foo.

This works.  Then, it reloads the set after a flush:
(echo flush set t s; cat foo) | nft -f -

This is expected to work, because its the same set after all and it was
already loaded once.

But with avx2, this fails: nft reports a clashing element.

The reported clash is of following form:

    We successfully re-inserted
      a . b
      c . d

Then we try to insert a . d

avx2 finds the already existing a . d, which (due to 'flush set') is marked
as invalid in the new generation.  It skips the element and moves to next.

Due to incorrect masking, the skip-step finds the next matching
element *only considering the first field*,

i.e. we return the already reinserted "a . b", even though the
last field is different and the entry should not have been matched.

No such error is reported for the generic c implementation (no avx2) or when
the last field has to use the 'nft_pipapo_avx2_lookup_slow' fallback.

Bisection points to
7711f4bb4b36 ("netfilter: nft_set_pipapo: fix range overlap detection")
but that fix merely uncovers this bug.

Before this commit, the wrong element is returned, but erronously
reported as a full, identical duplicate.

The root-cause is too early return in the avx2 match functions.
When we process the last field, we should continue to process data
until the entire input size has been consumed to make sure no stale
bits remain in the map.

Link: https://lore.kernel.org/netfilter-devel/20260321152506.037f68c0@elisabeth/
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/netfilter/nft_set_pipapo_avx2.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c
index 7ff90325c97fa..6395982e4d95c 100644
--- a/net/netfilter/nft_set_pipapo_avx2.c
+++ b/net/netfilter/nft_set_pipapo_avx2.c
@@ -242,7 +242,7 @@ static int nft_pipapo_avx2_lookup_4b_2(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -319,7 +319,7 @@ static int nft_pipapo_avx2_lookup_4b_4(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -414,7 +414,7 @@ static int nft_pipapo_avx2_lookup_4b_8(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -505,7 +505,7 @@ static int nft_pipapo_avx2_lookup_4b_12(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -641,7 +641,7 @@ static int nft_pipapo_avx2_lookup_4b_32(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -699,7 +699,7 @@ static int nft_pipapo_avx2_lookup_8b_1(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -764,7 +764,7 @@ static int nft_pipapo_avx2_lookup_8b_2(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -839,7 +839,7 @@ static int nft_pipapo_avx2_lookup_8b_4(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -925,7 +925,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -1019,7 +1019,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] xfrm: account XFRMA_IF_ID in aevent size calculation
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Keenan Dong, Steffen Klassert, Sasha Levin, davem, edumazet, kuba,
	pabeni, sln, eyal.birger, benedictwong, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Keenan Dong <keenanat2000@gmail.com>

[ Upstream commit 7081d46d32312f1a31f0e0e99c6835a394037599 ]

xfrm_get_ae() allocates the reply skb with xfrm_aevent_msgsize(), then
build_aevent() appends attributes including XFRMA_IF_ID when x->if_id is
set.

xfrm_aevent_msgsize() does not include space for XFRMA_IF_ID. For states
with if_id, build_aevent() can fail with -EMSGSIZE and hit BUG_ON(err < 0)
in xfrm_get_ae(), turning a malformed netlink interaction into a kernel
panic.

Account XFRMA_IF_ID in the size calculation unconditionally and replace
the BUG_ON with normal error unwinding.

Fixes: 7e6526404ade ("xfrm: Add a new lookup key to match xfrm interfaces.")
Reported-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/xfrm/xfrm_user.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 306e4f65ce264..1ddcf2a1eff7a 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2668,7 +2668,8 @@ static inline unsigned int xfrm_aevent_msgsize(struct xfrm_state *x)
 	       + nla_total_size(4) /* XFRM_AE_RTHR */
 	       + nla_total_size(4) /* XFRM_AE_ETHR */
 	       + nla_total_size(sizeof(x->dir)) /* XFRMA_SA_DIR */
-	       + nla_total_size(4); /* XFRMA_SA_PCPU */
+	       + nla_total_size(4) /* XFRMA_SA_PCPU */
+	       + nla_total_size(sizeof(x->if_id)); /* XFRMA_IF_ID */
 }
 
 static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
@@ -2780,7 +2781,12 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
 	c.portid = nlh->nlmsg_pid;
 
 	err = build_aevent(r_skb, x, &c);
-	BUG_ON(err < 0);
+	if (err < 0) {
+		spin_unlock_bh(&x->lock);
+		xfrm_state_put(x);
+		kfree_skb(r_skb);
+		return err;
+	}
 
 	err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid);
 	spin_unlock_bh(&x->lock);
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-5.10] net: hamradio: scc: validate bufsize in SIOCSCCSMEM ioctl
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Mashiro Chen, Joerg Reuter, Jakub Kicinski, Sasha Levin,
	andrew+netdev, davem, edumazet, pabeni, linux-hams, netdev,
	linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Mashiro Chen <mashiro.chen@mailbox.org>

[ Upstream commit 8263e484d6622464ec72a5ad563f62492d84fa54 ]

The SIOCSCCSMEM ioctl copies a scc_mem_config from user space and
assigns its bufsize field directly to scc->stat.bufsize without any
range validation:

  scc->stat.bufsize = memcfg.bufsize;

If a privileged user (CAP_SYS_RAWIO) sets bufsize to 0, the receive
interrupt handler later calls dev_alloc_skb(0) and immediately writes
a KISS type byte via skb_put_u8() into a zero-capacity socket buffer,
corrupting the adjacent skb_shared_info region.

Reject bufsize values smaller than 16; this is large enough to hold
at least one KISS header byte plus useful data.

Signed-off-by: Mashiro Chen <mashiro.chen@mailbox.org>
Acked-by: Joerg Reuter <jreuter@yaina.de>
Link: https://patch.msgid.link/20260409024927.24397-3-mashiro.chen@mailbox.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

All the data is gathered. Let me compile the complete analysis.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: Subject Line**
- Subsystem: `net: hamradio: scc`
- Action verb: "validate" — indicates adding missing input validation,
  i.e., fixing missing bounds checking
- Summary: Add missing bounds check on `bufsize` parameter from
  userspace ioctl

**Step 1.2: Tags**
- `Signed-off-by: Mashiro Chen` — patch author
- `Acked-by: Joerg Reuter <jreuter@yaina.de>` — this is the **original
  driver author** (copyright holder since 1993, confirmed in file
  header). Strong endorsement.
- `Link:` to patch.msgid.link — standard netdev submission
- `Signed-off-by: Jakub Kicinski` — netdev maintainer applied it. Strong
  trust signal.

**Step 1.3: Commit Body**
- Bug: `SIOCSCCSMEM` ioctl copies `bufsize` from userspace without
  validation
- Symptom: If `bufsize` is set to 0, `dev_alloc_skb(0)` creates a zero-
  capacity skb, then `skb_put_u8()` writes past the buffer, corrupting
  `skb_shared_info`
- This is a **memory corruption bug** triggered via ioctl (requires
  CAP_SYS_RAWIO)
- Fix: reject `bufsize < 16`

**Step 1.4: Hidden Bug Fix?**
Not hidden — this is an explicit, well-described input validation bug
fix preventing memory corruption.

## PHASE 2: DIFF ANALYSIS

**Step 2.1: Inventory**
- 1 file changed: `drivers/net/hamradio/scc.c`
- 2 lines added, 0 lines removed
- Function: `scc_net_siocdevprivate()`

**Step 2.2: Code Flow**
- Before: `memcfg.bufsize` assigned directly to `scc->stat.bufsize`
  after `copy_from_user`, no validation
- After: `memcfg.bufsize < 16` returns `-EINVAL` before assignment

**Step 2.3: Bug Mechanism**
Category: **Buffer overflow / out-of-bounds write**. Setting `bufsize=0`
causes `dev_alloc_skb(0)` in `scc_rxint()`, then `skb_put_u8()` writes 1
byte into a zero-capacity buffer, corrupting adjacent `skb_shared_info`.

**Step 2.4: Fix Quality**
- Obviously correct: 2-line bounds check before assignment
- Minimal and surgical — cannot introduce a regression
- No side effects, no locking changes, no API changes

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: Blame**
The buggy code (line 1912: `scc->stat.bufsize = memcfg.bufsize`) traces
to `^1da177e4c3f41` (Linus Torvalds, 2005-04-16) — this is the initial
Linux git import. The bug has existed since the **very beginning of the
kernel source tree**.

**Step 3.2: Fixes tag**
No explicit `Fixes:` tag (expected — this is why it needs manual
review). The buggy code predates git history.

**Step 3.3: File history**
Changes since v6.6 are only treewide renames (`timer_container_of`,
`timer_delete_sync`, `irq_get_nr_irqs`). The SIOCSCCSMEM handler and
`scc_rxint()` are completely untouched.

**Step 3.5: Dependencies**
None. The fix is self-contained — a simple bounds check addition.

## PHASE 4: MAILING LIST

Lore is protected by anti-scraping measures and couldn't be fetched
directly. However:
- The patch was **Acked-by the original driver author** Joerg Reuter
- It was applied by **netdev maintainer Jakub Kicinski**
- It's patch 3 of a series (from message-id), but the fix is completely
  standalone

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: Functions modified**
`scc_net_siocdevprivate()` — the ioctl handler

**Step 5.2: Consumer of `bufsize`**
`scc_rxint()` (line 535) uses `scc->stat.bufsize` as the argument to
`dev_alloc_skb()`. This is an **interrupt handler** — called on every
received character from the Z8530 chip. When `bufsize=0`:
1. `dev_alloc_skb(0)` succeeds (returns a valid skb with 0 data
   capacity)
2. `skb_put_u8(skb, 0)` at line 546 writes 1 byte past the data area
   into `skb_shared_info`
3. This is **memory corruption in interrupt context**

**Step 5.4: Reachability**
The ioctl requires `CAP_SYS_RAWIO`. The corruption path is: ioctl sets
bufsize → hardware interrupt fires → `scc_rxint()` → `dev_alloc_skb(0)`
→ `skb_put_u8` overflows.

## PHASE 6: STABLE TREE ANALYSIS

**Step 6.1: Code exists in all stable trees**
Verified: the identical vulnerable code exists in v5.15, v6.1, and v6.6.
The buggy code dates to the initial kernel.

**Step 6.2: Clean apply**
The surrounding code is identical in v6.1 and v6.6 (verified). The
2-line addition will apply cleanly to all active stable trees.

## PHASE 7: SUBSYSTEM CONTEXT

- Subsystem: `drivers/net/hamradio` — networking driver (ham radio
  Z8530)
- Criticality: PERIPHERAL (niche hardware), but the bug is a **memory
  corruption**, which elevates priority regardless of driver popularity

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: Affected users** — Users of Z8530-based ham radio hardware
(niche, but real)

**Step 8.2: Trigger** — Requires `CAP_SYS_RAWIO` to set the bad bufsize
via ioctl, then hardware interrupt triggers corruption. Privileged user
action.

**Step 8.3: Severity** — **HIGH**: Memory corruption in interrupt
context. Corrupting `skb_shared_info` can lead to unpredictable behavior
including crashes, further memory corruption, or potential exploitation.

**Step 8.4: Risk-Benefit**
- Benefit: Prevents memory corruption from invalid ioctl input
- Risk: Near zero — 2 lines of obvious bounds checking
- Ratio: Excellent — trivial fix for a real memory corruption bug

## PHASE 9: FINAL SYNTHESIS

**Evidence FOR backporting:**
- Fixes real memory corruption (skb_shared_info overwrite in interrupt
  context)
- Only 2 lines added — obviously correct bounds check
- Buggy code exists since initial kernel tree — affects ALL stable trees
- Patch applies cleanly to all stable trees (verified v5.15, v6.1, v6.6)
- Acked by original driver author (Joerg Reuter)
- Applied by netdev maintainer (Jakub Kicinski)
- No dependencies, fully self-contained
- Zero regression risk

**Evidence AGAINST backporting:**
- Requires CAP_SYS_RAWIO (privileged) to trigger
- Niche driver (ham radio hardware)

**Stable rules checklist:**
1. Obviously correct and tested? **YES** — trivial 2-line bounds check,
   acked by driver author
2. Fixes a real bug? **YES** — memory corruption from unchecked
   userspace input
3. Important issue? **YES** — memory corruption in interrupt context
4. Small and contained? **YES** — 2 lines in one file
5. No new features/APIs? **YES** — pure validation addition
6. Applies to stable? **YES** — verified identical code in all active
   stable trees

## Verification

- [Phase 1] Parsed tags: Acked-by Joerg Reuter (driver author), SOB by
  Jakub Kicinski (netdev maintainer)
- [Phase 2] Diff: 2 lines added to `scc_net_siocdevprivate()`, bounds
  check on `memcfg.bufsize`
- [Phase 3] git blame: buggy code at line 1912 dates to `^1da177e4c3f41`
  (initial git import, 2005), present in ALL stable trees
- [Phase 3] git log v6.1/v6.6/v5.15 -- scc.c: only treewide changes,
  SIOCSCCSMEM handler untouched
- [Phase 5] Traced `scc->stat.bufsize` consumer: `scc_rxint()` line 535
  calls `dev_alloc_skb(bufsize)`, line 546 `skb_put_u8` overflows when
  bufsize=0
- [Phase 6] git show v6.1/v6.6/v5.15: SIOCSCCSMEM handler code is byte-
  for-byte identical — clean apply confirmed
- [Phase 4] Lore unavailable due to anti-scraping protection — could not
  verify discussion thread directly
- [Phase 8] Failure mode: memory corruption (skb_shared_info overwrite)
  in interrupt context, severity HIGH

**YES**

 drivers/net/hamradio/scc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index ae5048efde686..8569db4a71401 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1909,6 +1909,8 @@ static int scc_net_siocdevprivate(struct net_device *dev,
 			if (!capable(CAP_SYS_RAWIO)) return -EPERM;
 			if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))
 				return -EINVAL;
+			if (memcfg.bufsize < 16)
+				return -EINVAL;
 			scc->stat.bufsize   = memcfg.bufsize;
 			return 0;
 		
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-6.18] net: hsr: emit notification for PRP slave2 changed hw addr on port deletion
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Fernando Fernandez Mancera, Luka Gejak, Felix Maurer, Paolo Abeni,
	Sasha Levin, davem, edumazet, kuba, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Fernando Fernandez Mancera <fmancera@suse.de>

[ Upstream commit 2ce8a41113eda1adddc1e6dc43cf89383ec6dc22 ]

On PRP protocol, when deleting the port the MAC address change
notification was missing. In addition to that, make sure to only perform
the MAC address change on slave2 deletion and PRP protocol as the
operation isn't necessary for HSR nor slave1.

Note that the eth_hw_addr_set() is correct on PRP context as the slaves
are either in promiscuous mode or forward offload enabled.

Reported-by: Luka Gejak <luka.gejak@linux.dev>
Closes: https://lore.kernel.org/netdev/DHFCZEM93FTT.1RWFBIE32K7OT@linux.dev/
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Reviewed-by: Felix Maurer <fmaurer@redhat.com>
Link: https://patch.msgid.link/20260403123928.4249-2-fmancera@suse.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed. Let me compile the full analysis.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject Line
- **Subsystem**: net: hsr (HSR/PRP networking protocol)
- **Action verb**: "emit notification" (implies a missing notification =
  bug fix)
- **Summary**: Adds missing NETDEV_CHANGEADDR notification when PRP
  slave2's MAC is restored during port deletion, and scopes the MAC
  restore to only PRP slave_B.

### Step 1.2: Tags
- **Reported-by**: Luka Gejak <luka.gejak@linux.dev> — real user report
- **Closes**:
  https://lore.kernel.org/netdev/DHFCZEM93FTT.1RWFBIE32K7OT@linux.dev/ —
  links to the bug report
- **Signed-off-by**: Fernando Fernandez Mancera <fmancera@suse.de>
  (author, SUSE), Paolo Abeni <pabeni@redhat.com> (networking
  maintainer)
- **Reviewed-by**: Felix Maurer <fmaurer@redhat.com>
- **Link**:
  https://patch.msgid.link/20260403123928.4249-2-fmancera@suse.de
- **Fixes: b65999e7238e** ("net: hsr: sync hw addr of slave2 according
  to slave1 hw addr on PRP") — found in the original mbox, targets the
  commit that introduced the bug

### Step 1.3: Commit Body
The commit explains that on PRP protocol, when deleting a port, the
NETDEV_CHANGEADDR notification was missing. The commit also restricts
the MAC address restoration to only slave_B on PRP (since only slave_B's
MAC is changed at setup time). The commit author explicitly notes that
`eth_hw_addr_set()` is correct since PRP slaves are in promiscuous mode
or have forward offload enabled.

### Step 1.4: Hidden Bug Fix
This is an explicit bug fix — a missing notification and an overly-broad
MAC address restoration.

---

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
- **File**: `net/hsr/hsr_slave.c` (single file)
- **Lines**: +5, -1 (net 4 lines added)
- **Function**: `hsr_del_port()`
- **Scope**: Single-file surgical fix

### Step 2.2: Code Flow Change
**Before**: The unconditional `eth_hw_addr_set(port->dev,
port->original_macaddress)` was called for ALL non-master ports (both
HSR and PRP, both slave_A and slave_B), and no NETDEV_CHANGEADDR
notification was emitted.

**After**: The MAC restoration is conditional on `hsr->prot_version ==
PRP_V1 && port->type == HSR_PT_SLAVE_B`, and a
`call_netdevice_notifiers(NETDEV_CHANGEADDR, port->dev)` is emitted.

### Step 2.3: Bug Mechanism
**Category**: Logic/correctness fix — missing notification + overly
broad MAC restoration
- The creation path (`hsr_dev_finalize()` and `hsr_netdev_notify()`)
  correctly calls `call_netdevice_notifiers(NETDEV_CHANGEADDR, ...)` but
  the deletion path did not.
- The MAC address was restored even for ports that never had their MAC
  changed (HSR ports, PRP slave_A).

### Step 2.4: Fix Quality
- Obviously correct — symmetric with the creation path behavior
- Minimal and surgical — 4 net lines
- No regression risk — restricts behavior to only the case where it's
  needed
- Reviewed by Felix Maurer (Red Hat), applied by Paolo Abeni (networking
  maintainer)

---

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: Blame
The buggy line (`eth_hw_addr_set(port->dev, port->original_macaddress)`)
was introduced by commit `b65999e7238e6` (Fernando Fernandez Mancera,
2025-04-09).

### Step 3.2: Fixes Target
Commit `b65999e7238e6` ("net: hsr: sync hw addr of slave2 according to
slave1 hw addr on PRP") first appeared in v6.16. It added PRP MAC
synchronization: setting slave_B's MAC to match slave_A's during
creation, propagating MAC changes from slave_A to slave_B, and restoring
the original MAC during deletion. The deletion path was incomplete — no
notification and no scope restriction.

### Step 3.3: File History
Between `b65999e7238e6` and HEAD, `hsr_del_port()` was NOT modified —
the buggy code persists unchanged in current HEAD.

### Step 3.4: Author
Fernando Fernandez Mancera is both the author of the original buggy
commit and the fix. He has multiple HSR-related commits in the tree.
He's now at SUSE (was at riseup.net).

### Step 3.5: Dependencies
This is a standalone fix. The only prerequisite is `b65999e7238e6` which
introduced the code being fixed. No other patches needed.

---

## PHASE 4: MAILING LIST RESEARCH

### Step 4.1: Original Discussion
The original patch `b65999e7238e6` (v3, net-next) was reviewed on the
mailing list. Luka Gejak posted a detailed review pointing out the exact
issues this fix addresses: missing `call_netdevice_notifiers()` in
`hsr_del_port()` and the use of `eth_hw_addr_set()` vs
`dev_set_mac_address()`. Despite these review comments, the patch was
merged by David S. Miller.

### Step 4.2: Fix Review
The fix was reviewed by Felix Maurer (Red Hat) and applied by Paolo
Abeni (Red Hat, networking maintainer). DKIM verified.

### Step 4.3: Bug Report
The Closes: tag references Luka Gejak's review of the original commit
where he identified the missing notification and other issues.

### Step 4.4: Series Context
b4 confirms this is a single standalone patch (Total patches: 1),
despite the message-id suffix "-2".

### Step 4.5: Stable Discussion
The author noted in the patch: "routed through net-next tree as the next
net tree as rc6 batch is already out." The original mbox contains a
`Fixes:` tag targeting `b65999e7238e`.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1: Functions Modified
Only `hsr_del_port()` is modified.

### Step 5.2: Callers
`hsr_del_port()` is called during HSR/PRP interface teardown. This is
the standard port deletion path triggered by userspace via netlink.

### Step 5.3: Consistency
The creation path in `hsr_dev_finalize()` (line 798-800) correctly does:
```c
if (protocol_version == PRP_V1) {
    eth_hw_addr_set(slave[1], slave[0]->dev_addr);
    call_netdevice_notifiers(NETDEV_CHANGEADDR, slave[1]);
}
```
The fix makes the deletion path symmetric with this.

### Step 5.5: Similar Patterns
The `hsr_netdev_notify()` handler (lines 82-88) also correctly calls
`call_netdevice_notifiers(NETDEV_CHANGEADDR, ...)` when propagating MAC
changes to slave_B. The deletion path was the only one missing the
notification.

---

## PHASE 6: STABLE TREE ANALYSIS

### Step 6.1: Buggy Code in Stable
The buggy commit `b65999e7238e6` first appeared in v6.16. It is present
in v6.16.y, v6.17.y, v6.18.y, v6.19.y, and v7.0.y stable trees.

### Step 6.2: Backport Difficulty
The `hsr_del_port()` function has NOT changed between v6.16 and v7.0.
The patch applies cleanly to v6.16.y.

### Step 6.3: No prior fix exists for this issue in stable.

---

## PHASE 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem
- **Subsystem**: net/hsr (HSR/PRP networking protocol)
- **Criticality**: IMPORTANT — industrial Ethernet redundancy protocol
  used in factory automation and critical infrastructure

### Step 7.2: Activity
The HSR subsystem has seen steady development (20+ commits since
b65999e7238e6), indicating active maintenance.

---

## PHASE 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: Who is Affected
PRP (Parallel Redundancy Protocol) users — industrial networking
deployments that rely on PRP for redundancy. Not a huge user base, but
the users who need this need it to work correctly.

### Step 8.2: Trigger Conditions
The bug is triggered every time a PRP interface is deleted. This is a
common administrative operation.

### Step 8.3: Failure Mode Severity
- Userspace doesn't receive NETDEV_CHANGEADDR notification, meaning
  network management tools have stale MAC information after PRP teardown
  — **MEDIUM** severity
- Unnecessary MAC restoration on HSR/PRP slave_A — **LOW** (no-op in
  practice since the MAC matches)

### Step 8.4: Risk-Benefit Ratio
- **Benefit**: Fixes missing notification for PRP users, makes teardown
  path consistent with creation
- **Risk**: Very low — 4 lines, single function, restricts behavior to
  where it's needed
- **Ratio**: Favorable

---

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence Summary
**FOR backporting:**
- Fixes a real bug introduced by `b65999e7238e6` (missing
  NETDEV_CHANGEADDR notification)
- Has Fixes: tag in original patch
- Reported by a user (Luka Gejak)
- Reviewed by Felix Maurer (Red Hat)
- Applied by Paolo Abeni (networking maintainer)
- Small, surgical fix (4 net lines, single file, single function)
- Consistent with the creation path behavior
- Standalone — no dependencies beyond the already-present buggy commit

**AGAINST backporting:**
- MEDIUM severity (missing notification, not a crash or security issue)
- Affects a niche subsystem (PRP)

### Step 9.2: Stable Rules Checklist
1. Obviously correct? **YES** — makes deletion symmetric with creation
2. Fixes a real bug? **YES** — missing notification reported by a user
3. Important issue? **YES** — incorrect behavior visible to userspace
4. Small and contained? **YES** — 4 lines, single function
5. No new features or APIs? **YES** — no new features
6. Can apply to stable trees? **YES** — code unchanged since v6.16

### Step 9.3: Exception Categories
Not applicable — this is a standard bug fix, not a hardware quirk or
device ID.

### Step 9.4: Decision
The fix is small, obviously correct, fixes a real user-reported bug
(missing NETDEV_CHANGEADDR notification during PRP port deletion), has a
Fixes: tag, is reviewed, and applies cleanly to affected stable trees.

---

## Verification

- [Phase 1] Parsed tags: Reported-by from Luka Gejak, Closes link to
  lore, Reviewed-by Felix Maurer, Link to patch.msgid.link, applied by
  Paolo Abeni
- [Phase 2] Diff analysis: +5/-1 lines in `hsr_del_port()` in
  `net/hsr/hsr_slave.c`, adds PRP_V1+SLAVE_B condition and
  `call_netdevice_notifiers()` call
- [Phase 3] git blame: buggy line introduced by `b65999e7238e6`
  (2025-04-09), first in v6.16
- [Phase 3] git show b65999e7238e6: confirmed original commit adds MAC
  sync for PRP but misses notification in deletion path
- [Phase 3] git tag --contains: b65999e7238e6 is in v6.16, v6.17, v6.18,
  v6.19, v7.0
- [Phase 3] git diff v6.16: `hsr_del_port()` unchanged between v6.16 and
  v7.0, patch applies cleanly
- [Phase 4] b4 dig -c b65999e7238e6: found original submission at
  https://patch.msgid.link/20250409101911.3120-1-ffmancera@riseup.net
- [Phase 4] b4 dig -a: v1 and v3 revisions found for original commit
- [Phase 4] Read /tmp/hsr_thread.mbox: Luka Gejak's review explicitly
  identified the missing notification bug
- [Phase 4] b4 am: fix is standalone (Total patches: 1), Reviewed-by and
  DKIM verified
- [Phase 4] Original mbox contains Fixes: b65999e7238e tag
- [Phase 5] Creation path in hsr_device.c:798-800 does call
  `call_netdevice_notifiers()` — deletion should too
- [Phase 5] Notification path in hsr_main.c:82-88 also calls
  `call_netdevice_notifiers()` — consistent pattern
- [Phase 6] Bug exists in v6.16+ stable trees, patch applies cleanly to
  v6.16
- [Phase 8] Failure mode: missing userspace notification on PRP port
  deletion, severity MEDIUM

**YES**

 net/hsr/hsr_slave.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 44f83c8c56a79..d9af9e65f72f0 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -243,7 +243,11 @@ void hsr_del_port(struct hsr_port *port)
 		if (!port->hsr->fwd_offloaded)
 			dev_set_promiscuity(port->dev, -1);
 		netdev_upper_dev_unlink(port->dev, master->dev);
-		eth_hw_addr_set(port->dev, port->original_macaddress);
+		if (hsr->prot_version == PRP_V1 &&
+		    port->type == HSR_PT_SLAVE_B) {
+			eth_hw_addr_set(port->dev, port->original_macaddress);
+			call_netdevice_notifiers(NETDEV_CHANGEADDR, port->dev);
+		}
 	}
 
 	kfree_rcu(port, rcu);
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] ipvs: fix NULL deref in ip_vs_add_service error path
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Weiming Shi, Xiang Mei, Simon Horman, Julian Anastasov,
	Florian Westphal, Sasha Levin, horms, pablo, davem, edumazet,
	kuba, pabeni, jwiesner, netdev, lvs-devel, netfilter-devel,
	coreteam, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Weiming Shi <bestswngs@gmail.com>

[ Upstream commit 9a91797e61d286805ae10a92cc48959c30800556 ]

When ip_vs_bind_scheduler() succeeds in ip_vs_add_service(), the local
variable sched is set to NULL.  If ip_vs_start_estimator() subsequently
fails, the out_err cleanup calls ip_vs_unbind_scheduler(svc, sched)
with sched == NULL.  ip_vs_unbind_scheduler() passes the cur_sched NULL
check (because svc->scheduler was set by the successful bind) but then
dereferences the NULL sched parameter at sched->done_service, causing a
kernel panic at offset 0x30 from NULL.

 Oops: general protection fault, [..] [#1] PREEMPT SMP KASAN NOPTI
 KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
 RIP: 0010:ip_vs_unbind_scheduler (net/netfilter/ipvs/ip_vs_sched.c:69)
 Call Trace:
  <TASK>
  ip_vs_add_service.isra.0 (net/netfilter/ipvs/ip_vs_ctl.c:1500)
  do_ip_vs_set_ctl (net/netfilter/ipvs/ip_vs_ctl.c:2809)
  nf_setsockopt (net/netfilter/nf_sockopt.c:102)
  [..]

Fix by simply not clearing the local sched variable after a successful
bind.  ip_vs_unbind_scheduler() already detects whether a scheduler is
installed via svc->scheduler, and keeping sched non-NULL ensures the
error path passes the correct pointer to both ip_vs_unbind_scheduler()
and ip_vs_scheduler_put().

While the bug is older, the problem popups in more recent kernels (6.2),
when the new error path is taken after the ip_vs_start_estimator() call.

Fixes: 705dd3444081 ("ipvs: use kthreads for stats estimation")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Acked-by: Simon Horman <horms@kernel.org>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 net/netfilter/ipvs/ip_vs_ctl.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 4c8fa22be88ad..e442ba6033d5f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1453,7 +1453,6 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
 		ret = ip_vs_bind_scheduler(svc, sched);
 		if (ret)
 			goto out_err;
-		sched = NULL;
 	}
 
 	ret = ip_vs_start_estimator(ipvs, &svc->stats);
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-6.12] net: ethernet: mtk_eth_soc: avoid writing to ESW registers on MT7628
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Joris Vaisvila, Daniel Golle, Stefan Roese, Jakub Kicinski,
	Sasha Levin, nbd, lorenzo, andrew+netdev, davem, edumazet, pabeni,
	matthias.bgg, angelogioacchino.delregno, netdev, linux-kernel,
	linux-arm-kernel, linux-mediatek
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Joris Vaisvila <joey@tinyisr.com>

[ Upstream commit 9a04d3b2f0708a9e5e1f731bafb69b040bb934a0 ]

The MT7628 has a fixed-link PHY and does not expose MAC control
registers. Writes to these registers only corrupt the ESW VLAN
configuration.

This patch explicitly registers no-op phylink_mac_ops for MT7628, as
after removing the invalid register accesses, the existing
phylink_mac_ops effectively become no-ops.

This code was introduced by commit 296c9120752b
("net: ethernet: mediatek: Add MT7628/88 SoC support")

Signed-off-by: Joris Vaisvila <joey@tinyisr.com>
Reviewed-by: Daniel Golle <daniel@makrotpia.org>
Reviewed-by: Stefan Roese <stefan.roese@mailbox.org>
Link: https://patch.msgid.link/20260226154547.68553-1-joey@tinyisr.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Now I have all the information needed for a thorough analysis. Let me
compile my findings.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: Subject Line**
- Subsystem: `net: ethernet: mtk_eth_soc`
- Action verb: "avoid" — strongly implies a bug fix (preventing harmful
  behavior)
- Summary: Avoid writing to ESW (Embedded Switch) registers on MT7628 to
  prevent corruption

**Step 1.2: Tags**
- No `Fixes:` tag, but commit body references `296c9120752b` ("net:
  ethernet: mediatek: Add MT7628/88 SoC support") from August 2019 as
  the introducing commit
- `Signed-off-by: Joris Vaisvila <joey@tinyisr.com>` — author
- `Reviewed-by: Daniel Golle <daniel@makrotpia.org>` — MediaTek ethernet
  maintainer/expert
- `Reviewed-by: Stefan Roese <stefan.roese@mailbox.org>` — original
  author of the MT7628 support commit
- `Link:` to patch.msgid.link (standard netdev submission)
- `Signed-off-by: Jakub Kicinski <kuba@kernel.org>` — netdev maintainer
  applied it

Record: Two reviewer tags from highly relevant people (original MT7628
author + subsystem expert). No syzbot. No explicit Cc: stable.

**Step 1.3: Commit Body**
- Bug: MT7628 has a fixed-link PHY and does not expose MAC control
  registers. Writes to `MTK_MAC_MCR(x)` (offset 0x10100) on MT7628 hit
  the ESW VLAN configuration instead of non-existent MAC control
  registers.
- Symptom: VLAN configuration corruption on MT7628
- Root cause: The phylink_mac_ops callbacks (`link_down`, `link_up`,
  `mac_finish`) write to `MTK_MAC_MCR` registers without checking for
  MT7628

**Step 1.4: Hidden Bug Fix Detection**
This is clearly a data corruption fix. The word "avoid" means preventing
invalid register writes that corrupt VLAN config.

## PHASE 2: DIFF ANALYSIS

**Step 2.1: Inventory**
- Single file: `drivers/net/ethernet/mediatek/mtk_eth_soc.c`
- Approximate: +27 lines added, -5 lines removed
- Functions modified: `mtk_mac_config` (guard removed), `mtk_add_mac`
  (ops selection added)
- Functions added: `rt5350_mac_config`, `rt5350_mac_link_down`,
  `rt5350_mac_link_up` (all no-ops), `rt5350_phylink_ops` (new ops
  struct)

**Step 2.2: Code Flow Change**
1. In `mtk_mac_config`: The `!MTK_HAS_CAPS(eth->soc->caps,
   MTK_SOC_MT7628)` guard was removed. Safe because MT7628 now uses
   entirely different (no-op) ops, so this function is never called for
   MT7628.
2. In `mtk_add_mac`: Added conditional to select `rt5350_phylink_ops`
   for MT7628 instead of `mtk_phylink_ops`.
3. New no-op functions: `rt5350_mac_config`, `rt5350_mac_link_down`,
   `rt5350_mac_link_up` — all empty.

**Step 2.3: Bug Mechanism**
Category: **Hardware workaround / data corruption fix**

The bug: On MT7628, register offset 0x10100 is part of the ESW VLAN
configuration, not a MAC control register. The existing
`mtk_mac_link_down()`, `mtk_mac_link_up()`, and `mtk_mac_finish()` all
write to `MTK_MAC_MCR(mac->id)` (= 0x10100) without MT7628 checks. Only
`mtk_mac_config()` had a guard. Every link state change event corrupts
the VLAN configuration.

**Step 2.4: Fix Quality**
- Obviously correct: The fix prevents ALL register writes by
  substituting no-op callbacks
- Minimal regression risk: Empty callbacks for a fixed-link PHY that
  never needed MAC configuration
- Self-contained in one file
- Reviewed by the original MT7628 author (Stefan Roese) and MediaTek
  network expert (Daniel Golle)

## PHASE 3: GIT HISTORY

**Step 3.1: Blame**
- The buggy code in `mtk_mac_link_down`/`mtk_mac_link_up` was introduced
  by `b8fc9f30821ec0` (René van Dorst, 2019-08-25) during the phylink
  conversion
- The `mtk_mac_config` guard was already in `b8fc9f30821ec0` but was
  never added to `link_down`/`link_up`/`finish`

**Step 3.2: Original commit**
- `296c9120752b` ("Add MT7628/88 SoC support") was merged in v5.3-rc6
  (August 2019)
- This commit is present in all stable trees from v5.3 onwards
  (confirmed in p-5.10, p-5.15 tags)

**Step 3.3/3.4: Author & File History**
- Joris Vaisvila is not a frequent kernel contributor (only 1-2 commits
  found)
- However, both reviewers are well-known in this subsystem
- File has 231 commits since 296c9120752b; 32 since v6.12

**Step 3.5: Dependencies**
- The patch is self-contained. The no-op ops pattern doesn't depend on
  any other patches.
- In v6.6, the `mtk_mac_finish` function also writes to `MTK_MAC_MCR`
  without MT7628 guard — same bug. The no-op ops approach fixes all
  callbacks at once.

## PHASE 4: MAILING LIST

Lore/b4 dig returned results but couldn't access full discussions due to
Anubis protection. The patch was submitted as
`20260226154547.68553-1-joey@tinyisr.com` and accepted by Jakub Kicinski
(netdev maintainer).

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1-5.4: Impact Surface**
- `mtk_mac_link_down` is called by phylink whenever the link goes down —
  every cable disconnect, PHY negotiation change
- `mtk_mac_link_up` is called on every link up event
- `mtk_mac_finish` is called during PHY configuration
- On MT7628, these are called regularly during normal operation
- `mtk_set_mcr_max_rx` at line 3886 already has its own `MTK_SOC_MT7628`
  guard, confirming the developers know these registers don't exist on
  MT7628

## PHASE 6: STABLE TREE ANALYSIS

**Step 6.1:** The buggy code exists in ALL stable trees from v5.3+,
including v5.15, v6.1, v6.6, and 6.12.
- In v6.6: `mtk_mac_link_down` at line 689 unconditionally writes to
  `MTK_MAC_MCR` — confirmed the same bug
- In v6.6: `mtk_mac_link_up` at line 769 also unconditionally writes to
  `MTK_MAC_MCR` — confirmed
- In v6.6: `mtk_mac_finish` at line 660 also writes to `MTK_MAC_MCR` —
  confirmed

**Step 6.2: Backport Difficulty**
For v7.0: Should apply cleanly or with minor fuzz.
For v6.6 and older: Will need rework. The `mtk_mac_link_down`/`link_up`
implementations differ significantly (v7.0 has xgmii handling added by
`51cf06ddafc91e`). However, the *concept* of the fix (separate no-op
ops) is portable.

## PHASE 7: SUBSYSTEM CONTEXT

- Subsystem: Network driver (embedded Ethernet), IMPORTANT criticality
  for MT7628 users
- MT7628/MT7688 is a widely-used MIPS SoC found in popular embedded
  platforms (Omega2, VoCore2, many OpenWrt routers)

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: Affected Users**
- All MT7628/MT7688 users (embedded routers running Linux with VLANs)

**Step 8.2: Trigger Conditions**
- Triggered on every link state change (boot, cable plug/unplug, PHY
  state change)
- Extremely common — happens during normal boot

**Step 8.3: Failure Mode**
- **ESW VLAN configuration corruption** — MEDIUM-HIGH severity
- VLAN configuration is silently corrupted, leading to incorrect network
  behavior
- Not a crash but a data corruption issue affecting network
  configuration

**Step 8.4: Risk-Benefit**
- Benefit: HIGH — prevents VLAN corruption on every MT7628 system
- Risk: LOW — the fix adds empty callback functions and selects them
  conditionally; the no-op approach is obviously correct for a fixed-
  link PHY with no MAC control registers

## PHASE 9: FINAL SYNTHESIS

**Evidence FOR backporting:**
1. Fixes real data corruption (VLAN config) on real hardware
   (MT7628/MT7688)
2. Bug present since v5.3 (2019) — affects all stable trees
3. Reviewed by original MT7628 author and subsystem expert
4. Accepted by netdev maintainer (Jakub Kicinski)
5. Fix is obviously correct (no-op callbacks for hardware without MAC
   registers)
6. Single file change, well-contained
7. Other code in the same file already has MT7628 guards for the same
   registers (`mtk_set_mcr_max_rx` at line 3886)

**Evidence AGAINST backporting:**
1. ~30 lines of new code (not trivially small, but straightforward)
2. May need rework for older stable trees (6.6, 6.1, 5.15) due to
   function refactoring
3. No explicit Cc: stable (expected for commits under review)

**Stable Rules Checklist:**
1. Obviously correct and tested? YES — reviewed by 2 experts, one the
   original author
2. Fixes a real bug? YES — VLAN config corruption on MT7628
3. Important issue? YES — data corruption, affects all MT7628 users
4. Small and contained? YES — single file, ~30 lines
5. No new features? CORRECT — only prevents invalid register writes
6. Can apply to stable? YES for 7.0; needs rework for older trees

**Verification:**
- [Phase 1] Parsed tags: Reviewed-by from Daniel Golle and Stefan Roese,
  Link to netdev submission
- [Phase 2] Diff analysis: Adds no-op phylink_mac_ops for MT7628,
  selects them in `mtk_add_mac()`, removes now-unreachable guard in
  `mtk_mac_config()`
- [Phase 3] git blame: buggy code from `b8fc9f30821ec0` (2019), phylink
  conversion missing MT7628 guards in link_down/link_up
- [Phase 3] git show 296c9120752b: confirmed original MT7628 support
  commit from v5.3 era (2019-08-16)
- [Phase 3] git tag --contains: original commit present in p-5.10,
  p-5.15 tags (all active stable trees)
- [Phase 5] Verified `mtk_mac_link_down` writes to
  `MTK_MAC_MCR(mac->id)` without MT7628 check (line 731 in current code)
- [Phase 5] Verified `mtk_mac_link_up`→`mtk_gdm_mac_link_up` writes to
  `MTK_MAC_MCR(mac->id)` (line 846) without MT7628 check
- [Phase 5] Verified `mtk_mac_finish` writes to `MTK_MAC_MCR(mac->id)`
  (line 709/716) without MT7628 check
- [Phase 5] Confirmed `mtk_set_mcr_max_rx` (line 3886) already guards
  against MT7628, proving developers know these registers don't exist on
  MT7628
- [Phase 6] Verified v6.6 stable has the same bug: `mtk_mac_link_down`
  (line 689) and `mtk_mac_link_up` (line 769) unconditionally write to
  `MTK_MAC_MCR`
- [Phase 6] `MTK_MAC_MCR(x)` = 0x10100 + x*0x100, confirmed in header
  file (line 453)
- [Phase 8] VLAN corruption confirmed by commit message: "Writes to
  these registers only corrupt the ESW VLAN configuration"
- UNVERIFIED: Could not access full lore.kernel.org discussion due to
  Anubis protection; relied on tags in the commit message

**YES**

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 ++++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ddc321a02fdae..bb8ced22ca3be 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -562,9 +562,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
 	int val, ge_mode, err = 0;
 	u32 i;
 
-	/* MT76x8 has no hardware settings between for the MAC */
-	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
-	    mac->interface != state->interface) {
+	if (mac->interface != state->interface) {
 		/* Setup soc pin functions */
 		switch (state->interface) {
 		case PHY_INTERFACE_MODE_TRGMII:
@@ -956,6 +954,30 @@ static const struct phylink_mac_ops mtk_phylink_ops = {
 	.mac_enable_tx_lpi = mtk_mac_enable_tx_lpi,
 };
 
+static void rt5350_mac_config(struct phylink_config *config, unsigned int mode,
+				const struct phylink_link_state *state)
+{
+}
+
+static void rt5350_mac_link_down(struct phylink_config *config, unsigned int mode,
+				phy_interface_t interface)
+{
+}
+
+static void rt5350_mac_link_up(struct phylink_config *config,
+			    struct phy_device *phy,
+			    unsigned int mode, phy_interface_t interface,
+			    int speed, int duplex, bool tx_pause, bool rx_pause)
+{
+}
+
+/* MT76x8 (rt5350-eth) does not expose any MAC control registers */
+static const struct phylink_mac_ops rt5350_phylink_ops = {
+	.mac_config = rt5350_mac_config,
+	.mac_link_down = rt5350_mac_link_down,
+	.mac_link_up = rt5350_mac_link_up,
+};
+
 static void mtk_mdio_config(struct mtk_eth *eth)
 {
 	u32 val;
@@ -4780,6 +4802,7 @@ static const struct net_device_ops mtk_netdev_ops = {
 
 static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 {
+	const struct phylink_mac_ops *mac_ops = &mtk_phylink_ops;
 	const __be32 *_id = of_get_property(np, "reg", NULL);
 	phy_interface_t phy_mode;
 	struct phylink *phylink;
@@ -4914,9 +4937,12 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 			  mac->phylink_config.supported_interfaces);
 	}
 
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
+		mac_ops = &rt5350_phylink_ops;
+
 	phylink = phylink_create(&mac->phylink_config,
 				 of_fwnode_handle(mac->of_node),
-				 phy_mode, &mtk_phylink_ops);
+				 phy_mode, mac_ops);
 	if (IS_ERR(phylink)) {
 		err = PTR_ERR(phylink);
 		goto free_netdev;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] net: mdio: realtek-rtl9300: use scoped device_for_each_child_node loop
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Felix Gu, Andrew Lunn, Jakub Kicinski, Sasha Levin, hkallweit1,
	davem, edumazet, pabeni, chris.packham, netdev, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Felix Gu <ustc.gu@gmail.com>

[ Upstream commit c09ea768bdb975e828f8e17293c397c3d14ad85d ]

Switch to device_for_each_child_node_scoped() to auto-release fwnode
references on early exit.

Fixes: 24e31e474769 ("net: mdio: Add RTL9300 MDIO driver")
Signed-off-by: Felix Gu <ustc.gu@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260405-rtl9300-v1-1-08e4499cf944@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 drivers/net/mdio/mdio-realtek-rtl9300.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 405a07075dd11..8d5fb014ca06c 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -466,7 +466,6 @@ static int rtl9300_mdiobus_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rtl9300_mdio_priv *priv;
-	struct fwnode_handle *child;
 	int err;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -487,7 +486,7 @@ static int rtl9300_mdiobus_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	device_for_each_child_node(dev, child) {
+	device_for_each_child_node_scoped(dev, child) {
 		err = rtl9300_mdiobus_probe_one(dev, priv, child);
 		if (err)
 			return err;
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 7.0-6.18] tcp: use WRITE_ONCE() for tsoffset in tcp_v6_connect()
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Wesley Atwell, Eric Dumazet, Jiayuan Chen, Jakub Kicinski,
	Sasha Levin, ncardwell, davem, dsahern, pabeni, netdev,
	linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Wesley Atwell <atwellwea@gmail.com>

[ Upstream commit dc9902bbd480aae510b885b67cd30cd04cfce3a8 ]

Commit dd23c9f1e8d5 ("tcp: annotate data-races around tp->tsoffset")
updated do_tcp_getsockopt() to read tp->tsoffset with READ_ONCE()
for TCP_TIMESTAMP because another CPU may change it concurrently.

tcp_v6_connect() still stores tp->tsoffset with a plain write. That
store runs under lock_sock() via inet_stream_connect(), but the socket
lock does not serialize a concurrent getsockopt(TCP_TIMESTAMP) from
another task sharing the socket.

Use WRITE_ONCE() for the tcp_v6_connect() store so the connect-time
writer matches the lockless TCP_TIMESTAMP reader. This also makes the
IPv6 path consistent with tcp_v4_connect().

Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Link: https://patch.msgid.link/20260310012604.145661-1-atwellwea@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

I now have all the information needed for a comprehensive analysis. Let
me compile the findings.

---

## PHASE 1: COMMIT MESSAGE FORENSICS

**Step 1.1: Subject Line**
- **Subsystem**: `tcp` (networking, IPv6 TCP stack)
- **Action verb**: "use" - specifically requesting `WRITE_ONCE()`
  annotation
- **Summary**: Adds `WRITE_ONCE()` for `tp->tsoffset` in
  `tcp_v6_connect()` to fix a data race with concurrent
  `getsockopt(TCP_TIMESTAMP)`.

**Step 1.2: Tags**
- **Reviewed-by**: Eric Dumazet (Google networking maintainer, and
  importantly the AUTHOR of the original annotation commit
  dd23c9f1e8d5c)
- **Reviewed-by**: Jiayuan Chen
- **Link**:
  https://patch.msgid.link/20260310012604.145661-1-atwellwea@gmail.com
- **Signed-off-by**: Jakub Kicinski (net maintainer)
- No Fixes: tag, no Cc: stable tag (expected for manual review)

Record: Notably reviewed by Eric Dumazet who authored the original
tsoffset annotation commit. Strong quality signal.

**Step 1.3: Body Text Analysis**
The commit explains:
1. dd23c9f1e8d5c added `READ_ONCE()` to `do_tcp_getsockopt()` for
   `TCP_TIMESTAMP` and `WRITE_ONCE()` to `tcp_v4_connect()`
2. `tcp_v6_connect()` was missed - it still uses a plain write for
   `tp->tsoffset`
3. `tcp_v6_connect()` runs under `lock_sock()`, but
   `getsockopt(TCP_TIMESTAMP)` doesn't hold the socket lock when reading
   `tsoffset`
4. This creates a data race between the writer (connect) and the
   lockless reader (getsockopt)

Record: Bug is a data race in `tp->tsoffset` store in IPv6 connect path.
The IPv4 path was correctly annotated but IPv6 was missed. This is a gap
in the original fix dd23c9f1e8d5c.

**Step 1.4: Hidden Bug Fix?**
This is explicitly described as completing a data race annotation that
was missed. It IS a bug fix (data race fix).

## PHASE 2: DIFF ANALYSIS

**Step 2.1: Inventory**
- **Files**: 1 file changed (`net/ipv6/tcp_ipv6.c`)
- **Change**: 1 line modified (-1/+1)
- **Function**: `tcp_v6_connect()`
- **Scope**: Single-file, single-line, surgical fix

**Step 2.2: Code Flow Change**

Before:

```328:328:net/ipv6/tcp_ipv6.c
                tp->tsoffset = st.ts_off;
```

After (from the diff):
```c
                WRITE_ONCE(tp->tsoffset, st.ts_off);
```

The only change is wrapping a plain C store in `WRITE_ONCE()`, which
prevents store tearing and acts as a compiler barrier. The actual value
stored is identical.

**Step 2.3: Bug Mechanism**
Category: **Data race (KCSAN-class)**. The concurrent reader
(`do_tcp_getsockopt()` at line 4721 in `tcp.c`) uses `READ_ONCE()` but
the writer in IPv6 doesn't use `WRITE_ONCE()`, violating the kernel's
data race annotation convention. Under the C memory model, a plain write
concurrent with a `READ_ONCE` constitutes undefined behavior.

**Step 2.4: Fix Quality**
- Obviously correct: Yes. Trivially so. WRITE_ONCE wrapping a store is
  mechanically correct.
- Minimal/surgical: Yes. One line.
- Regression risk: Zero. WRITE_ONCE cannot change functional behavior.
- Consistent with existing pattern: IPv4 path already uses `WRITE_ONCE`
  since dd23c9f1e8d5c.

## PHASE 3: GIT HISTORY INVESTIGATION

**Step 3.1: Blame**
The blame shows line 328 (`tp->tsoffset = st.ts_off;`) was introduced by
commit `165573e41f2f66` (Eric Dumazet, 2026-03-02, "tcp: secure_seq: add
back ports to TS offset"). However, the underlying issue (plain write
without WRITE_ONCE) existed BEFORE this refactoring — the original
annotation commit dd23c9f1e8d5c (v6.5-rc3, July 2023) already missed the
IPv6 path.

**Step 3.2: Fixes Tag Follow-up**
The commit references dd23c9f1e8d5c ("tcp: annotate data-races around
tp->tsoffset"). Verified:
- dd23c9f1e8d5c only modified `net/ipv4/tcp.c` and `net/ipv4/tcp_ipv4.c`
  — it did NOT touch `net/ipv6/tcp_ipv6.c`
- It added `WRITE_ONCE()` to `tcp_v4_connect()` and
  `do_tcp_setsockopt()`, and `READ_ONCE()` to `do_tcp_getsockopt()`
- The IPv6 writer was missed entirely

dd23c9f1e8d5c is in mainline since v6.5-rc3, and was backported to
stable trees (6.1.y, 6.4.y, etc.).

**Step 3.3: File History**
Recent changes to `tcp_ipv6.c` include the `165573e41f2f66` refactoring
(March 2026). For stable trees older than this, the code around the
tsoffset assignment looks different (uses `secure_tcpv6_ts_off()`
directly), but the fix is trivially adaptable.

**Step 3.4: Author**
Wesley Atwell is not the subsystem maintainer but the patch was reviewed
by Eric Dumazet (Google TCP maintainer) who wrote the original
annotation commit. Applied by Jakub Kicinski (net maintainer).

**Step 3.5: Dependencies**
The recent refactoring `165573e41f2f66` changes the code shape in the
diff. In older stable trees (pre-7.0), the backport would need trivial
adaptation: wrapping `secure_tcpv6_ts_off(...)` in `WRITE_ONCE()`
instead of `st.ts_off`. The fix is logically independent.

## PHASE 4: MAILING LIST RESEARCH

**Step 4.1**: b4 dig found the submission at
https://patch.msgid.link/20260324221326.1395799-3-atwellwea@gmail.com
(v2 or later revision). Lore.kernel.org is behind anti-bot protection,
so direct access was blocked.

**Step 4.2**: Review from Eric Dumazet is the strongest possible signal
for this subsystem.

**Step 4.3-4.5**: No syzbot report (this is a code-inspection-found data
race). No specific bug report — found by reading the code and noticing
the IPv6 path was missed.

## PHASE 5: CODE SEMANTIC ANALYSIS

**Step 5.1: Functions Modified**: `tcp_v6_connect()`

**Step 5.2: Race Partners**
- Writer: `tcp_v6_connect()` → stores `tp->tsoffset` (under
  `lock_sock()` via `inet_stream_connect()`)
- Reader: `do_tcp_getsockopt()` at line 4721 → reads `tp->tsoffset` with
  `READ_ONCE()` — verified NO lock_sock() is held for `TCP_TIMESTAMP`
- Other writers: `do_tcp_setsockopt()` (already uses `WRITE_ONCE()`,
  line 4178), `tcp_v4_connect()` (already uses `WRITE_ONCE()`, line 336)

The race is real and verified: `getsockopt(TCP_TIMESTAMP)` can run
concurrently with `connect()` from another thread sharing the socket.

**Step 5.3: Other tsoffset accessors**
- `tcp_output.c` line 995: plain read of `tp->tsoffset` — but this runs
  in the data path under the socket lock, so no data race with connect
- `tcp_input.c` lines 4680, 4712, 6884: plain reads — also under socket
  lock
- `tcp_minisocks.c` line 350, 643: assignments during socket
  creation/accept — not concurrent

Record: The data race is specifically between
`getsockopt(TCP_TIMESTAMP)` lockless reader and `tcp_v6_connect()`
writer.

## PHASE 6: STABLE TREE ANALYSIS

**Step 6.1: Buggy Code in Stable?**
- The original annotation commit dd23c9f1e8d5c is in v6.5-rc3, so it was
  backported to stable trees 6.1.y, 6.4.y, 6.5.y, 6.6.y, etc.
- In ALL those trees, the IPv6 path was NOT annotated (because
  dd23c9f1e8d5c never touched `tcp_ipv6.c`)
- The bug exists in every stable tree that has dd23c9f1e8d5c

**Step 6.2: Backport Complications**
Minor: In stable trees without `165573e41f2f66` (which is a very recent
March 2026 change), the line looks different. The fix would need trivial
adaptation to wrap `secure_tcpv6_ts_off(...)` instead of `st.ts_off`.
This is a straightforward mechanical change.

**Step 6.3**: No other fix for this specific IPv6 data race was found.

## PHASE 7: SUBSYSTEM CONTEXT

**Step 7.1**: TCP networking subsystem — **CORE** criticality. Every
system uses TCP.

**Step 7.2**: Active subsystem with frequent commits.

## PHASE 8: IMPACT AND RISK ASSESSMENT

**Step 8.1: Affected Users**: All users using IPv6 TCP connections where
`getsockopt(TCP_TIMESTAMP)` is called concurrently with `connect()`.

**Step 8.2: Trigger**: A multi-threaded application where one thread
calls `connect()` on an IPv6 TCP socket while another calls
`getsockopt(TCP_TIMESTAMP)`. The race window exists but the practical
trigger is uncommon.

**Step 8.3: Severity**: MEDIUM. A torn read of `tsoffset` would yield an
incorrect timestamp value from `getsockopt()`. However, under the C
memory model this is undefined behavior, and KCSAN would flag it as a
data race.

**Step 8.4: Risk-Benefit**
- **Benefit**: Completes the data race annotation intended by
  dd23c9f1e8d5c. Fixes UB. Consistent with IPv4 path. Extremely
  important for KCSAN-clean kernels.
- **Risk**: Zero. `WRITE_ONCE()` is a transparent compiler annotation
  that cannot introduce regressions.

## PHASE 9: FINAL SYNTHESIS

**Step 9.1: Evidence**
FOR backporting:
- Fixes a real data race (UB under C memory model)
- Completes a fix that was already backported (dd23c9f1e8d5c) but missed
  the IPv6 path
- One-line change, zero regression risk
- Reviewed by Eric Dumazet (author of the original annotation, TCP
  maintainer)
- Makes IPv6 consistent with IPv4
- Core networking subsystem

AGAINST backporting:
- Practical impact is low (torn read returns slightly wrong timestamp)
- Minor adaptation needed for older stable trees (trivial)

**Step 9.2: Stable Rules Checklist**
1. Obviously correct and tested? **YES** — trivially correct one-line
   WRITE_ONCE wrapping
2. Fixes a real bug? **YES** — data race (undefined behavior per C
   memory model)
3. Important issue? **MEDIUM** — data race, potential KCSAN splat;
   completes an incomplete prior fix
4. Small and contained? **YES** — 1 line, 1 file
5. No new features or APIs? **Correct** — no new features
6. Can apply to stable trees? **YES** — with trivial adaptation for
   older trees

**Step 9.3: Exception Categories**: Not an exception category, but a
standard bug fix.

## Verification

- [Phase 1] Parsed tags: Reviewed-by Eric Dumazet and Jiayuan Chen, Link
  to submission, SOB from Jakub Kicinski
- [Phase 2] Diff: single line change `tp->tsoffset = st.ts_off` →
  `WRITE_ONCE(tp->tsoffset, st.ts_off)` in `tcp_v6_connect()`
- [Phase 3] git show dd23c9f1e8d5c: confirmed it only modified
  `net/ipv4/tcp.c` and `net/ipv4/tcp_ipv4.c`, NOT `net/ipv6/tcp_ipv6.c`
- [Phase 3] git blame: line 328 from `165573e41f2f66` (2026-03-02) but
  the missing annotation predates that refactoring
- [Phase 3] Verified dd23c9f1e8d5c is in v6.5-rc3 via `git describe
  --contains`
- [Phase 5] Verified `do_tcp_getsockopt()` at line 4510-4721 does NOT
  hold `lock_sock()` for `TCP_TIMESTAMP` case — confirmed lockless
  READ_ONCE reader
- [Phase 5] Verified `tcp_v4_connect()` at line 336 already has
  `WRITE_ONCE(tp->tsoffset, ...)` — IPv4 was fixed, IPv6 wasn't
- [Phase 5] Verified all other `tp->tsoffset` writers already use
  WRITE_ONCE (lines 336, 4178 in ipv4/)
- [Phase 6] dd23c9f1e8d5c was in v6.5-rc3, so present in all active
  stable trees (6.1.y through 6.12.y)
- [Phase 6] Backport needs trivial adaptation for pre-165573e41f2f66
  trees (wrap `secure_tcpv6_ts_off()` instead of `st.ts_off`)

This is a minimal, obviously correct, zero-risk fix that completes a
data race annotation already present in stable trees. The fix was
reviewed by the original annotation author (Eric Dumazet). It brings the
IPv6 path in line with the already-annotated IPv4 path.

**YES**

 net/ipv6/tcp_ipv6.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index bb09d5ccf5990..ba7cd7d3d4da0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -325,7 +325,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr_unsized *uaddr,
 						 inet->inet_dport);
 		if (!tp->write_seq)
 			WRITE_ONCE(tp->write_seq, st.seq);
-		tp->tsoffset = st.ts_off;
+		WRITE_ONCE(tp->tsoffset, st.ts_off);
 	}
 
 	if (tcp_fastopen_defer_connect(sk, &err))
-- 
2.53.0


^ permalink raw reply related

* [PATCH AUTOSEL 6.18] xsk: respect tailroom for ZC setups
From: Sasha Levin @ 2026-04-20 13:20 UTC (permalink / raw)
  To: patches, stable
  Cc: Maciej Fijalkowski, Björn Töpel, Stanislav Fomichev,
	Jakub Kicinski, Sasha Levin, magnus.karlsson, davem, edumazet,
	pabeni, ast, netdev, bpf, linux-kernel
In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org>

From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>

[ Upstream commit 1ee1605138fc94cc8f8f273321dd2471c64977f9 ]

Multi-buffer XDP stores information about frags in skb_shared_info that
sits at the tailroom of a packet. The storage space is reserved via
xdp_data_hard_end():

	((xdp)->data_hard_start + (xdp)->frame_sz -	\
	 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))

and then we refer to it via macro below:

static inline struct skb_shared_info *
xdp_get_shared_info_from_buff(const struct xdp_buff *xdp)
{
        return (struct skb_shared_info *)xdp_data_hard_end(xdp);
}

Currently we do not respect this tailroom space in multi-buffer AF_XDP
ZC scenario. To address this, introduce xsk_pool_get_tailroom() and use
it within xsk_pool_get_rx_frame_size() which is used in ZC drivers to
configure length of HW Rx buffer.

Typically drivers on Rx Hw buffers side work on 128 byte alignment so
let us align the value returned by xsk_pool_get_rx_frame_size() in order
to avoid addressing this on driver's side. This addresses the fact that
idpf uses mentioned function *before* pool->dev being set so we were at
risk that after subtracting tailroom we would not provide 128-byte
aligned value to HW.

Since xsk_pool_get_rx_frame_size() is actively used in xsk_rcv_check()
and __xsk_rcv(), add a variant of this routine that will not include 128
byte alignment and therefore old behavior is preserved.

Reviewed-by: Björn Töpel <bjorn@kernel.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Fixes: 24ea50127ecf ("xsk: support mbuf on ZC RX")
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://patch.msgid.link/20260402154958.562179-3-maciej.fijalkowski@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

Error: Failed to generate final synthesis

 include/net/xdp_sock_drv.h | 23 ++++++++++++++++++++++-
 net/xdp/xsk.c              |  4 ++--
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
index 33e072768de9d..dd1d3a6e1b780 100644
--- a/include/net/xdp_sock_drv.h
+++ b/include/net/xdp_sock_drv.h
@@ -37,16 +37,37 @@ static inline u32 xsk_pool_get_headroom(struct xsk_buff_pool *pool)
 	return XDP_PACKET_HEADROOM + pool->headroom;
 }
 
+static inline u32 xsk_pool_get_tailroom(bool mbuf)
+{
+	return mbuf ? SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : 0;
+}
+
 static inline u32 xsk_pool_get_chunk_size(struct xsk_buff_pool *pool)
 {
 	return pool->chunk_size;
 }
 
-static inline u32 xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
+static inline u32 __xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
 {
 	return xsk_pool_get_chunk_size(pool) - xsk_pool_get_headroom(pool);
 }
 
+static inline u32 xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
+{
+	u32 frame_size =  __xsk_pool_get_rx_frame_size(pool);
+	struct xdp_umem *umem = pool->umem;
+	bool mbuf;
+
+	/* Reserve tailroom only for zero-copy pools that opted into
+	 * multi-buffer. The reserved area is used for skb_shared_info,
+	 * matching the XDP core's xdp_data_hard_end() layout.
+	 */
+	mbuf = pool->dev && (umem->flags & XDP_UMEM_SG_FLAG);
+	frame_size -= xsk_pool_get_tailroom(mbuf);
+
+	return ALIGN_DOWN(frame_size, 128);
+}
+
 static inline u32 xsk_pool_get_rx_frag_step(struct xsk_buff_pool *pool)
 {
 	return pool->unaligned ? 0 : xsk_pool_get_chunk_size(pool);
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index a78cdc3356937..259ad9a3abcc4 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -239,7 +239,7 @@ static u32 xsk_copy_xdp(void *to, void **from, u32 to_len,
 
 static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 {
-	u32 frame_size = xsk_pool_get_rx_frame_size(xs->pool);
+	u32 frame_size = __xsk_pool_get_rx_frame_size(xs->pool);
 	void *copy_from = xsk_copy_xdp_start(xdp), *copy_to;
 	u32 from_len, meta_len, rem, num_desc;
 	struct xdp_buff_xsk *xskb;
@@ -338,7 +338,7 @@ static int xsk_rcv_check(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 	if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
 		return -EINVAL;
 
-	if (len > xsk_pool_get_rx_frame_size(xs->pool) && !xs->sg) {
+	if (len > __xsk_pool_get_rx_frame_size(xs->pool) && !xs->sg) {
 		xs->rx_dropped++;
 		return -ENOSPC;
 	}
-- 
2.53.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox