[lvc-project] [PATCH net 1/2] net: dwc-xlgmac: fix channel count initialization

Fedor Pchelkin pchelkin at ispras.ru
Sat May 23 13:45:27 MSK 2026


The number of channels used by the driver is determined by the maximum
value of TX and RX rings.  Currently it is initialized once during the
driver's probing phase.  However, the value is zeroed inside
xlgmac_free_channels() when closing the interface.  The further attempts
to transmit data after reopening the interface fail with a crash because
xlgmac_alloc_channels() "allocates" a ZERO_SIZE_PTR channel_head now which
is directly dereferenced in xmit path.

general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
CPU: 1 PID: 21 Comm: kworker/1:0 Not tainted 6.1.164 #116
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.1-0-g3208b098f51a-prebuilt.qemu.org 04/01/2014
Workqueue: mld mld_ifc_work
RIP: 0010:xlgmac_xmit+0xde/0x13f0 drivers/net/ethernet/synopsys/dwc-xlgmac-net.c:716
Call Trace:
 <TASK>
 __netdev_start_xmit include/linux/netdevice.h:4896 [inline]
 netdev_start_xmit include/linux/netdevice.h:4910 [inline]
 xmit_one net/core/dev.c:3683 [inline]
 dev_hard_start_xmit+0x126/0x680 net/core/dev.c:3699
 sch_direct_xmit+0x18a/0x7e0 net/sched/sch_generic.c:345
 __dev_xmit_skb net/core/dev.c:3920 [inline]
 __dev_queue_xmit+0x19ef/0x3da0 net/core/dev.c:4325
 dev_queue_xmit include/linux/netdevice.h:3051 [inline]
 neigh_resolve_output net/core/neighbour.c:1568 [inline]
 neigh_resolve_output+0x563/0x880 net/core/neighbour.c:1548
 neigh_output include/net/neighbour.h:545 [inline]
 ip6_finish_output2+0xb4f/0x2390 net/ipv6/ip6_output.c:138
 __ip6_finish_output+0x48c/0x1300 net/ipv6/ip6_output.c:205
 ip6_finish_output net/ipv6/ip6_output.c:216 [inline]
 NF_HOOK_COND include/linux/netfilter.h:291 [inline]
 ip6_output+0x250/0x910 net/ipv6/ip6_output.c:237
 dst_output include/net/dst.h:453 [inline]
 NF_HOOK.constprop.0+0x111/0x8a0 include/linux/netfilter.h:302
 mld_sendpack+0x67b/0xd40 net/ipv6/mcast.c:1825
 mld_send_cr net/ipv6/mcast.c:2126 [inline]
 mld_ifc_work+0x7a5/0xd80 net/ipv6/mcast.c:2656
 process_one_work+0x97f/0x1470 kernel/workqueue.c:2292
 worker_thread+0x5a1/0x1090 kernel/workqueue.c:2439
 kthread+0x2e1/0x3a0 kernel/kthread.c:376
 ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:295

Move the pdata->channel_count initialization into xlgmac_alloc_channels()
where it logically belongs.  Nothing should touch the channel-related
properties before this function succeeds anyway.

This also makes it similar to the pattern of pdata->channel_count handling
preferred in akin amd-xgbe driver.

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Fixes: 65e0ace2c5cd ("net: dwc-xlgmac: Initial driver for DesignWare Enterprise Ethernet")
Cc: stable at vger.kernel.org
Signed-off-by: Fedor Pchelkin <pchelkin at ispras.ru>
---
 drivers/net/ethernet/synopsys/dwc-xlgmac-common.c | 6 +-----
 drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c   | 9 +++++----
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
index 131786aa4d5b..9275f64401e4 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -98,8 +98,7 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 		return ret;
 	}
 
-	/* Channel and ring params initializtion
-	 *  pdata->channel_count;
+	/* Ring params initialization
 	 *  pdata->tx_ring_count;
 	 *  pdata->rx_ring_count;
 	 *  pdata->tx_desc_count;
@@ -145,9 +144,6 @@ static int xlgmac_init(struct xlgmac_pdata *pdata)
 		return ret;
 	}
 
-	pdata->channel_count =
-		max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count);
-
 	/* Initialize RSS hash key and lookup table */
 	netdev_rss_key_fill(pdata->rss_key, sizeof(pdata->rss_key));
 
diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c
index 2a40257ab47c..e08cd28c8699 100644
--- a/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c
+++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-desc.c
@@ -230,10 +230,11 @@ static int xlgmac_alloc_channels(struct xlgmac_pdata *pdata)
 {
 	struct xlgmac_channel *channel_head, *channel;
 	struct xlgmac_ring *tx_ring, *rx_ring;
+	unsigned int i, count;
 	int ret = -ENOMEM;
-	unsigned int i;
 
-	channel_head = kzalloc_objs(struct xlgmac_channel, pdata->channel_count);
+	count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count);
+	channel_head = kzalloc_objs(struct xlgmac_channel, count);
 	if (!channel_head)
 		return ret;
 
@@ -248,8 +249,7 @@ static int xlgmac_alloc_channels(struct xlgmac_pdata *pdata)
 	if (!rx_ring)
 		goto err_rx_ring;
 
-	for (i = 0, channel = channel_head; i < pdata->channel_count;
-		i++, channel++) {
+	for (i = 0, channel = channel_head; i < count; i++, channel++) {
 		snprintf(channel->name, sizeof(channel->name), "channel-%u", i);
 		channel->pdata = pdata;
 		channel->queue_index = i;
@@ -281,6 +281,7 @@ static int xlgmac_alloc_channels(struct xlgmac_pdata *pdata)
 	}
 
 	pdata->channel_head = channel_head;
+	pdata->channel_count = count;
 
 	return 0;
 
-- 
2.53.0




More information about the lvc-project mailing list