From nobody Thu Apr 9 03:28:42 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA5B22EBB84; Wed, 11 Mar 2026 08:16:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773216979; cv=none; b=tw/qlHFWcY5vgNALHtqjjQ97Jmzl48NgtJ/Qttn9E5RD6R7X/pS+pmErscpXUtSgit5x0PdqtcjFPqGiTg0EJusq75eXpAQ0QYiL3IjIhWwsvvsRHjbKdydY2pYbtUf4qnsI83PEFjjbBI4TmKTB4tFvpg960Tv+xyfVqQML4lQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773216979; c=relaxed/simple; bh=K8MJFjvgxoN2vFb0y2A8WHuorv2Iwnc6DzqS4N4JARw=; h=Date:From:To:Subject:Content-Type:MIME-Version:Message-ID; b=KeCY22QaAtLrd/QHG1uPWk63PIWK12kIa5PNqWI5BqNJb3Hr9Tc1tysVbYRVJSitqQUtOm04SJbH975YmEGr8Bo9/4Lg+MJGUdeC8b1+orKCUsof738TKHxtE7x5ojCc6Eh7bnZqHxRJPr+RcFXIt57c6qK4nHbiP5wsWjsqwTE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=YKDV2Wnm; arc=none smtp.client-ip=117.135.210.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="YKDV2Wnm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=Date:From:To:Subject:Content-Type:MIME-Version: Message-ID; bh=K8MJFjvgxoN2vFb0y2A8WHuorv2Iwnc6DzqS4N4JARw=; b=Y KDV2WnmZGwkKijMX9ddQwkQMNlDbXCL8lSjV8aI7zYu6WdOj1I/2iLU2Cjh+Fc4A ua1kb6wFlGCIDYHzK5DrX7jZ/NmvbT95irCGFWeOUFnx5ndvFlR23MT0DpRQK3W6 GGaDK5yI6NHCV/N90P/yDUvbup7vL+oud8iKJ36HYo= Received: from luckd0g$163.com ( [183.205.138.18] ) by ajax-webmail-wmsvr-40-127 (Coremail) ; Wed, 11 Mar 2026 16:15:25 +0800 (CST) Date: Wed, 11 Mar 2026 16:15:25 +0800 (CST) From: "Jianzhou Zhao" To: kuba@kernel.org, davem@davemloft.net, przemyslaw.kitszel@intel.com, anthony.l.nguyen@intel.com, andrew+netdev@lunn.ch, edumazet@google.com, pabeni@redhat.com, intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: KCSAN: data-race in e1000_clean / e1000_xmit_frame X-Priority: 3 X-Mailer: Coremail Webmail Server Version 2023.4-cmXT build 20251222(83accb85) Copyright (c) 2002-2026 www.mailtech.cn 163com X-NTES-SC: AL_Qu2cAf6auUEp4yiZbOkfmU4Rhug7UMO3uf8n24JfPJ9wjA/p2yseUUF9NmPf88CwFTuXvxiGfTNO1/ZAU5Bifrwxk3hmxm5gz3tIpjQH1wzxxw== Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <43b9914b.706c.19cdbf70885.Coremail.luckd0g@163.com> X-Coremail-Locale: zh_CN X-CM-TRANSID: fygvCgDX75qdJLFpZch2AA--.39436W X-CM-SenderInfo: poxfyvkqj6il2tof0z/xtbC9h32gWmxJJ0zLQAA3j X-Coremail-Antispam: 1U5529EdanIXcx71UUUUU7vcSsGvfC2KfnxnUU== Content-Type: text/plain; charset="utf-8" Subject: [BUG] e1000: KCSAN: data-race in e1000_clean_tx_irq / e1000_tso Dear Maintainers, We are writing to report a KCSAN-detected data race vulnerability within th= e `e1000` network driver. This bug was found by our custom fuzzing tool, Ra= cePilot. The race occurs when `e1000_tso()` writes a new `next_to_watch` tr= acking array index for a transmission buffer without volatile locking, whil= e the `e1000_clean_tx_irq()` subroutine locklessly evaluates this field con= currently. We observed this bug on the Linux kernel version 6.18.0-08691-g2= 061f18ad76e-dirty. Call Trace & Context =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D BUG: KCSAN: data-race in e1000_clean / e1000_xmit_frame write to 0xffffc9000414e492 of 2 bytes by task 5500 on cpu 0: e1000_tso drivers/net/ethernet/intel/e1000/e1000_main.c:2752 [inline] e1000_xmit_frame+0x14fe/0x2a90 drivers/net/ethernet/intel/e1000/e1000_main= .c:3226 __netdev_start_xmit include/linux/netdevice.h:5273 [inline] netdev_start_xmit include/linux/netdevice.h:5282 [inline] xmit_one net/core/dev.c:3853 [inline] dev_hard_start_xmit+0xee/0x3a0 net/core/dev.c:3869 ... tcp_write_xmit+0xf64/0x3ee0 net/ipv4/tcp_output.c:3002 tcp_push_one+0x87/0xa0 net/ipv4/tcp_output.c:3199 =20 read to 0xffffc9000414e492 of 2 bytes by interrupt on cpu 1: e1000_clean_tx_irq drivers/net/ethernet/intel/e1000/e1000_main.c:3871 [inl= ine] e1000_clean+0x2fb/0x1570 drivers/net/ethernet/intel/e1000/e1000_main.c:3804 __napi_poll+0x5d/0x3f0 net/core/dev.c:7666 napi_poll net/core/dev.c:7729 [inline] net_rx_action+0x6cc/0x890 net/core/dev.c:7881 handle_softirqs+0xbe/0x290 kernel/softirq.c:622 ... value changed: 0x0083 -> 0x008d Reported by Kernel Concurrency Sanitizer on: CPU: 1 UID: 0 PID: 194865 Comm: syz.3.8279 Not tainted 6.18.0-08691-g2061f1= 8ad76e-dirty #44 PREEMPT(voluntary)=20 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/= 2014 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Execution Flow & Code Context During standard outgoing network transactions over the `e1000` queue layout= , `e1000_tso` maps buffer parameters into descriptions and sets `buffer_inf= o->next_to_watch`: ```c // drivers/net/ethernet/intel/e1000/e1000_main.c static int e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, struct sk_buff *skb, __be16 protocol) { ... context_desc->cmd_and_length =3D cpu_to_le32(cmd_length); buffer_info->time_stamp =3D jiffies; buffer_info->next_to_watch =3D i; // <-- Concurrent 2-byte lockless write if (++i =3D=3D tx_ring->count) i =3D 0; ... } ``` Simultaneously, `e1000_clean_tx_irq()` operates from IRQ/NAPI loops trackin= g trailing descriptor completion, directly reading `next_to_watch` from act= ive bounds before evaluating the hardware completion marker bit: ```c // drivers/net/ethernet/intel/e1000/e1000_main.c static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring) { ... i =3D tx_ring->next_to_clean; eop =3D tx_ring->buffer_info[i].next_to_watch; // <-- Concurrent 2-byte lo= ckless read eop_desc =3D E1000_TX_DESC(*tx_ring, eop); while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && ... ``` Root Cause Analysis A KCSAN data race arises because `e1000_clean_tx_irq()` fetches `next_to_wa= tch` before examining the transmit completion synchronization `E1000_TXD_ST= AT_DD` bit asynchronously across independent core cycles. This inherently c= auses collision overlaps against background `e1000_xmit_frame` calls queuin= g buffers onto identical arrays during transmission pipelines. While logica= l structures inherently mask off processing loops if the `DD` bit defaults = logically, unpredictable compiler caching causes unoptimized structure tear= ing. Unfortunately, we were unable to generate a reproducer for this bug. Potential Impact This data race presents theoretical local memory corruption or networking s= tate breakdown risks alongside constant KCSAN performance degradation if a = compiler incorrectly infers visibility assumptions across unannotated varia= bles bridging hardware transmission synchronizations.=20 Proposed Fix Implementing `READ_ONCE()` and `WRITE_ONCE()` bounds around `next_to_watch`= resolves the data race logically, ensuring correct load barriers on NAPI c= onsumers: ```diff --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -2749,7 +2749,7 @@ static int e1000_tso(struct e1000_adapter *adapter, context_desc->cmd_and_length =3D cpu_to_le32(cmd_length); =20 buffer_info->time_stamp =3D jiffies; - buffer_info->next_to_watch =3D i; + WRITE_ONCE(buffer_info->next_to_watch, i); =20 if (++i =3D=3D tx_ring->count) i =3D 0; @@ -3839,7 +3839,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *= adapter, unsigned int bytes_compl =3D 0, pkts_compl =3D 0; =20 i =3D tx_ring->next_to_clean; - eop =3D tx_ring->buffer_info[i].next_to_watch; + eop =3D READ_ONCE(tx_ring->buffer_info[i].next_to_watch); eop_desc =3D E1000_TX_DESC(*tx_ring, eop); =20 while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && ``` *(Note: Similar `WRITE_ONCE` bounds should also be applied to `e1000_tx_map= ` and `e1000_tx_csum` respectively)* We would be highly honored if this could be of any help. Best regards, RacePilot Team