Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 0/3] first series for xpcs based rsfec configuration
From: mike.marciniszyn @ 2026-04-30 15:07 UTC (permalink / raw)
  To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Heiner Kallweit,
	Russell King, Jacob Keller, Mohsin Bashir, Lee Trager,
	Andrew Lunn
  Cc: mike.marciniszyn, netdev, linux-kernel

From: "Mike Marciniszyn (Meta)" <mike.marciniszyn@gmail.com>

The series:
- Fixes an addr validation error
- Adds MDIO defines associated with RS-FEC
- consolidates the handling of the boilerplat ID registers
  into a routine to report id'ish registers and reduces the lines
  of code across the entire set of c45 routines.
- adds PMA read/write routines

https://lore.kernel.org/all/20260428172810.175077-2-mike.marciniszyn@gmail.com/
has been removed from the series and submitted to net as
https://lore.kernel.org/all/20260429150049.1643-1-mike.marciniszyn@gmail.com/

pcs reads for DEVS1 and DEVS2 cleaned up 2/3

Mike Marciniszyn (Meta) (3):
  net: mdio: Add support for RSFEC Control register for PMA
  net: eth: fbnic: Consolidate register reads for ids and devs
  net: eth: fbnic: Add pma read and write access

 drivers/net/ethernet/meta/fbnic/fbnic_csr.h  |   1 +
 drivers/net/ethernet/meta/fbnic/fbnic_mdio.c | 135 +++++++++++++++----
 include/uapi/linux/mdio.h                    |  10 ++
 3 files changed, 122 insertions(+), 24 deletions(-)

--
2.43.0


^ permalink raw reply

* [PATCH net-next v2 1/3] net: mdio: Add support for RSFEC Control register for PMA
From: mike.marciniszyn @ 2026-04-30 15:08 UTC (permalink / raw)
  To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Heiner Kallweit,
	Russell King, Jacob Keller, Mohsin Bashir, Lee Trager,
	Andrew Lunn
  Cc: mike.marciniszyn, netdev, linux-kernel
In-Reply-To: <20260430150802.3521-1-mike.marciniszyn@gmail.com>

From: "Mike Marciniszyn (Meta)" <mike.marciniszyn@gmail.com>

Add the constants associated with RS-FEC configuration
and status as well as the indicated separated bits for
DEVS1 to convey a separated PMA.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
---
v2:
  - Added Reviewed-by
v1: https://lore.kernel.org/all/20260428172810.175077-3-mike.marciniszyn@gmail.com/
  - initial revision

 include/uapi/linux/mdio.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index 8d769f100de6..b2541c948fc1 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -23,6 +23,10 @@
 #define MDIO_MMD_DTEXS		5	/* DTE Extender Sublayer */
 #define MDIO_MMD_TC		6	/* Transmission Convergence */
 #define MDIO_MMD_AN		7	/* Auto-Negotiation */
+#define MDIO_MMD_SEP_PMA1	8	/* Separated PMA (1) */
+#define MDIO_MMD_SEP_PMA2	9	/* Separated PMA (2) */
+#define MDIO_MMD_SEP_PMA3	10	/* Separated PMA (3) */
+#define MDIO_MMD_SEP_PMA4	11	/* Separated PMA (4) */
 #define MDIO_MMD_POWER_UNIT	13	/* PHY Power Unit */
 #define MDIO_MMD_C22EXT		29	/* Clause 22 extension */
 #define MDIO_MMD_VEND1		30	/* Vendor specific 1 */
@@ -63,6 +67,8 @@
 					 * Lanes B-D are numbered 134-136. */
 #define MDIO_PMA_10GBR_FSRT_CSR	147	/* 10GBASE-R fast retrain status and control */
 #define MDIO_PMA_10GBR_FECABLE	170	/* 10GBASE-R FEC ability */
+#define MDIO_PMA_RSFEC_CTRL	200	/* RSFEC control */
+#define MDIO_PMA_RSFEC_LANE_MAP	206	/* RSFEC lane mapping */
 #define MDIO_PCS_10GBX_STAT1	24	/* 10GBASE-X PCS status 1 */
 #define MDIO_PCS_10GBRT_STAT1	32	/* 10GBASE-R/-T PCS status 1 */
 #define MDIO_PCS_10GBRT_STAT2	33	/* 10GBASE-R/-T PCS status 2 */
@@ -175,6 +181,10 @@
 #define MDIO_DEVS_DTEXS			MDIO_DEVS_PRESENT(MDIO_MMD_DTEXS)
 #define MDIO_DEVS_TC			MDIO_DEVS_PRESENT(MDIO_MMD_TC)
 #define MDIO_DEVS_AN			MDIO_DEVS_PRESENT(MDIO_MMD_AN)
+#define MDIO_DEVS_SEP_PMA1		MDIO_DEVS_PRESENT(MDIO_MMD_SEP_PMA1)
+#define MDIO_DEVS_SEP_PMA2		MDIO_DEVS_PRESENT(MDIO_MMD_SEP_PMA2)
+#define MDIO_DEVS_SEP_PMA3		MDIO_DEVS_PRESENT(MDIO_MMD_SEP_PMA3)
+#define MDIO_DEVS_SEP_PMA4		MDIO_DEVS_PRESENT(MDIO_MMD_SEP_PMA4)
 #define MDIO_DEVS_C22EXT		MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT)
 #define MDIO_DEVS_VEND1			MDIO_DEVS_PRESENT(MDIO_MMD_VEND1)
 #define MDIO_DEVS_VEND2			MDIO_DEVS_PRESENT(MDIO_MMD_VEND2)
--
2.43.0


^ permalink raw reply related

* [PATCH net-next v2 2/3] net: eth: fbnic: Consolidate register reads for ids and devs
From: mike.marciniszyn @ 2026-04-30 15:08 UTC (permalink / raw)
  To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Heiner Kallweit,
	Russell King, Jacob Keller, Mohsin Bashir, Lee Trager,
	Andrew Lunn
  Cc: mike.marciniszyn, netdev, linux-kernel
In-Reply-To: <20260430150802.3521-1-mike.marciniszyn@gmail.com>

From: "Mike Marciniszyn (Meta)" <mike.marciniszyn@gmail.com>

Consolidate the register reads for boiler plate registers
to reduce LOC and cleanup pcs reads for DEVS1 to
fetch overrides for reserved bits that the hardware does not
return.

Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
---
v2:
  - Restore pcs register read for DEVS2
  - read pcs DEVS1 overrides and or into return
v1: https://lore.kernel.org/all/20260428172810.175077-4-mike.marciniszyn@gmail.com/

 drivers/net/ethernet/meta/fbnic/fbnic_mdio.c | 64 ++++++++++++--------
 1 file changed, 40 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
index 709041f7fc43..a3a072597a2c 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
@@ -11,6 +11,26 @@
 #define FBNIC_PCS_VENDOR	BIT(9)
 #define FBNIC_PCS_ZERO_MASK	(DW_VENDOR - FBNIC_PCS_VENDOR)

+static int
+fbnic_mdio_ids(int id, int regnum)
+{
+	/* return correct IDs */
+	switch (regnum) {
+	case MDIO_DEVID1:
+		return id >> 16;
+	case MDIO_DEVID2:
+		return id & 0xffff;
+	case MDIO_DEVS1:
+		return MDIO_DEVS_SEP_PMA1 | MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS;
+	case MDIO_DEVS2:
+		return 0;
+	case MDIO_STAT2:
+		return MDIO_STAT2_DEVPRST_VAL;
+	}
+
+	return 0;
+}
+
 static int
 fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum)
 {
@@ -29,18 +49,6 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum)
 	}

 	switch (regnum) {
-	case MDIO_DEVID1:
-		ret = MP_FBNIC_XPCS_PMA_100G_ID >> 16;
-		break;
-	case MDIO_DEVID2:
-		ret = MP_FBNIC_XPCS_PMA_100G_ID & 0xffff;
-		break;
-	case MDIO_DEVS1:
-		ret = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS;
-		break;
-	case MDIO_STAT2:
-		ret = MDIO_STAT2_DEVPRST_VAL;
-		break;
 	case MDIO_PMA_RXDET:
 		/* If training isn't complete default to 0 */
 		if (fbd->pmd_state != FBNIC_PMD_SEND_DATA)
@@ -51,6 +59,7 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum)
 		       (MDIO_PMD_RXDET_1 / FBNIC_AUI_MODE_R2));
 		break;
 	default:
+		ret = fbnic_mdio_ids(MP_FBNIC_XPCS_PMA_100G_ID, regnum);
 		break;
 	}

@@ -64,7 +73,7 @@ fbnic_mdio_read_pmd(struct fbnic_dev *fbd, int addr, int regnum)
 static int
 fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum)
 {
-	int ret, offset = 0;
+	int ret, offset = 0, overrides = 0;

 	/* We will need access to both PCS instances to get config info */
 	if (addr >= 2)
@@ -75,18 +84,25 @@ fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum)
 		return 0;

 	/* Intercept and return correct ID for PCS */
-	if (regnum == MDIO_DEVID1)
-		return DW_XPCS_ID >> 16;
-	if (regnum == MDIO_DEVID2)
-		return DW_XPCS_ID & 0xffff;
-	if (regnum == MDIO_DEVS1)
-		return MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS;
-
-	/* Swap vendor page bit for FBNIC PCS vendor page bit */
-	if (regnum & DW_VENDOR)
-		offset ^= DW_VENDOR | FBNIC_PCS_VENDOR;
+	switch (regnum) {
+	case MDIO_DEVID1 ... MDIO_DEVID2:
+		ret = fbnic_mdio_ids(DW_XPCS_ID, regnum);
+		break;
+	case MDIO_DEVS1:
+		/* DW IP returns MDIO_DEVS_SEP_PMA1, MDIO_DEVS_PMAPMD,
+		 * and MDIO_DEVS_PCS as 0
+		 */
+		overrides = fbnic_mdio_ids(DW_XPCS_ID, regnum);
+		fallthrough;
+	default:
+		/* Swap vendor page bit for FBNIC PCS vendor page bit */
+		if (regnum & DW_VENDOR)
+			offset ^= DW_VENDOR | FBNIC_PCS_VENDOR;

-	ret = fbnic_rd32(fbd, FBNIC_PCS_PAGE(addr) + (regnum ^ offset));
+		ret = fbnic_rd32(fbd, FBNIC_PCS_PAGE(addr) + (regnum ^ offset));
+		ret |= overrides;
+		break;
+	}

 	dev_dbg(fbd->dev,
 		"SWMII PCS Rd: Addr: %d RegNum: %d Value: 0x%04x\n",
--
2.43.0


^ permalink raw reply related

* [PATCH net-next v2 3/3] net: eth: fbnic: Add pma read and write access
From: mike.marciniszyn @ 2026-04-30 15:08 UTC (permalink / raw)
  To: Alexander Duyck, Jakub Kicinski, kernel-team, Andrew Lunn,
	David S. Miller, Eric Dumazet, Paolo Abeni, Heiner Kallweit,
	Russell King, Jacob Keller, Mohsin Bashir, Lee Trager,
	Andrew Lunn
  Cc: mike.marciniszyn, netdev, linux-kernel
In-Reply-To: <20260430150802.3521-1-mike.marciniszyn@gmail.com>

From: "Mike Marciniszyn (Meta)" <mike.marciniszyn@gmail.com>

Document the MDIO interface topology with an ASCII diagram
showing the MAC, PCS (MMD 3), FEC, Separated PMA (MMD 8), and PMD
(MMD 1) blocks and their interconnects. The diagram illustrates how
4 lanes connect the MAC through PCS, FEC, and PMA, then narrow to
2 lanes at the PMD.

The c45 read and write routines are enhanced to support
read and write of the separated PMA for the fbnic.

Co-developed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
---
v2:
  - no changes
v1: https://lore.kernel.org/all/20260428172810.175077-5-mike.marciniszyn@gmail.com/

 drivers/net/ethernet/meta/fbnic/fbnic_csr.h  |  1 +
 drivers/net/ethernet/meta/fbnic/fbnic_mdio.c | 71 ++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
index 81794bd326e1..64b958df7774 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h
@@ -805,6 +805,7 @@ enum {
 #define FBNIC_CSR_END_PCS		0x10668 /* CSR section delimiter */

 #define FBNIC_CSR_START_RSFEC		0x10800 /* CSR section delimiter */
+#define FBNIC_RSFEC_CONTROL(n)	(0x10800 + 8 * (n))	/* 0x42000 + 32*n */

 /* We have 4 RSFEC engines present in our part, however we are only using 1.
  * As such only CCW(0) and NCCW(0) will never be non-zero and the other
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
index a3a072597a2c..7a8727e8f6f2 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c
@@ -7,6 +7,25 @@
 #include "fbnic.h"
 #include "fbnic_netdev.h"

+/* fbnic MDIO Interface Layout
+ *
+ *        +-------------------+
+ *        |        MAC        |
+ *        +-------------------+
+ *            |   |   |   |  <-- 25GMII, 50GMII, or CGMII
+ *        +-------------------+
+ *  MMD 3 |        PCS        |
+ *        +-------------------+
+ *        |        FEC        |
+ *        +-------------------+
+ *  MMD 8 |  Separated PMA    |
+ *        +-------------------+
+ *              |       |     <-- PMD Service Interface
+ *        +-------------------+
+ *  MMD 1 |        PMD        |
+ *        +-------------------+
+ */
+
 #define DW_VENDOR		BIT(15)
 #define FBNIC_PCS_VENDOR	BIT(9)
 #define FBNIC_PCS_ZERO_MASK	(DW_VENDOR - FBNIC_PCS_VENDOR)
@@ -111,6 +130,32 @@ fbnic_mdio_read_pcs(struct fbnic_dev *fbd, int addr, int regnum)
 	return ret;
 }

+static int
+fbnic_mdio_read_pma(struct fbnic_dev *fbd, int addr, int regnum)
+{
+	int ret = 0;
+
+	/* We will need access to both PMA instances to get config info */
+	if (addr >= 2)
+		return 0;
+
+	switch (regnum) {
+	case MDIO_PMA_RSFEC_CTRL ... MDIO_PMA_RSFEC_LANE_MAP:
+		ret = fbnic_rd32(fbd, FBNIC_RSFEC_CONTROL(addr) +
+				 regnum - MDIO_PMA_RSFEC_CTRL);
+		break;
+	default:
+		ret = fbnic_mdio_ids(MP_FBNIC_XPCS_PMA_100G_ID, regnum);
+		break;
+	}
+
+	dev_dbg(fbd->dev,
+		"SWMII PMA Rd: Addr: %d RegNum: %d Value: 0x%04x\n",
+		addr, regnum, ret);
+
+	return ret;
+}
+
 static int
 fbnic_mdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
 {
@@ -122,6 +167,9 @@ fbnic_mdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
 	if (devnum == MDIO_MMD_PCS)
 		return fbnic_mdio_read_pcs(fbd, addr, regnum);

+	if (devnum == MDIO_MMD_SEP_PMA1)
+		return fbnic_mdio_read_pma(fbd, addr, regnum);
+
 	return 0;
 }

@@ -155,6 +203,26 @@ fbnic_mdio_write_pcs(struct fbnic_dev *fbd, int addr, int regnum, u16 val)
 	fbnic_wr32(fbd, FBNIC_PCS_PAGE(addr) + regnum, val);
 }

+static void
+fbnic_mdio_write_pma(struct fbnic_dev *fbd, int addr, int regnum, u16 val)
+{
+	dev_dbg(fbd->dev,
+		"SWMII PMA Wr: Addr: %d RegNum: %d Value: 0x%04x\n",
+		addr, regnum, val);
+
+	if (addr >= 2)
+		return;
+
+	switch (regnum) {
+	case MDIO_PMA_RSFEC_CTRL ... MDIO_PMA_RSFEC_LANE_MAP:
+		fbnic_wr32(fbd, FBNIC_RSFEC_CONTROL(addr) +
+				regnum - MDIO_PMA_RSFEC_CTRL, val);
+		break;
+	default:
+		break;
+	}
+}
+
 static int
 fbnic_mdio_write_c45(struct mii_bus *bus, int addr, int devnum,
 		     int regnum, u16 val)
@@ -167,6 +235,9 @@ fbnic_mdio_write_c45(struct mii_bus *bus, int addr, int devnum,
 	if (devnum == MDIO_MMD_PCS)
 		fbnic_mdio_write_pcs(fbd, addr, regnum, val);

+	if (devnum == MDIO_MMD_SEP_PMA1)
+		fbnic_mdio_write_pma(fbd, addr, regnum, val);
+
 	return 0;
 }

--
2.43.0


^ permalink raw reply related

* Re: [RFC PATCH] xprtrdma: Move long delayed work on system_dfl_long_wq
From: Chuck Lever @ 2026-04-30 15:09 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Marco Crivellari, linux-kernel, linux-nfs, netdev, Tejun Heo,
	Lai Jiangshan, Sebastian Andrzej Siewior, Michal Hocko,
	Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
In-Reply-To: <afNvZKtiQPLbi-3F@localhost.localdomain>


On Thu, Apr 30, 2026, at 11:04 AM, Frederic Weisbecker wrote:
> Le Thu, Apr 30, 2026 at 10:05:52AM -0400, Chuck Lever a écrit :

>> Does the patch address a bug (work isn't getting rescheduled at
>> all) or is it merely a minor optimization for certain platforms?
>> 
>> What's the user-visible issue that will be improved with this
>> change?
>
> It's not a bug, it's an optimization power-wise and performance-wise
> and also part of a bigger sanity change:
>
> - Long works have no reason to stick to a single CPU. If they are converted to
>   be unbound, the scheduler can move them to relevant targets to optimize
>   performances and power consumption. Hence the new system_unbound_long_wq.
>   The goal is to remove system_long_wq if none of its users rely on locality.
>
> - Using queue_delayed_work() with a bound workqueue doesn't make any sense
>   since the target is completely random.

The light dawns (for me). That's what I'd like to see in the commit message.

I don't have any technical objections to the code change.


-- 
Chuck Lever

^ permalink raw reply

* Re: [PATCH net-next] net: Consistently define pci_device_ids using named initializers
From: Arend van Spriel @ 2026-04-30 15:14 UTC (permalink / raw)
  To: Uwe Kleine-König (The Capable Hub), Michael Grzeschik,
	Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Marc Kleine-Budde, Vincent Mailhol, Krzysztof Halasa,
	Johannes Berg
  Cc: Markus Schneider-Pargmann, Steffen Klassert, David Dillow,
	Ion Badulescu, Mark Einon, Rasesh Mody, GR-Linux-NIC-Dev,
	Ido Schimmel, Sudarsana Kalluru, Manish Chopra,
	Potnuri Bharat Teja, Denis Kirjanov, Jijie Shao, Jian Shen,
	Cai Huoqing, Fan Gong, Tony Nguyen, Przemek Kitszel, Tariq Toukan,
	Saeed Mahameed, Leon Romanovsky, Mark Bloch, Petr Machata,
	Yibo Dong, Simon Horman, Heiner Kallweit, nic_swsd, Jiri Pirko,
	Francois Romieu, Daniele Venzano, Samuel Chessman, Jiawen Wu,
	Mengyuan Lou, Kevin Curtis, Stanislav Yakovlev, Richard Cochran,
	Kees Cook, Thomas Gleixner, Thomas Fourier, Ingo Molnar,
	Kory Maincent, Zilin Guan, Marco Crivellari, Vadim Fedorenko,
	Jacob Keller, Philipp Stanner, Bjorn Helgaas, Yeounsu Moon,
	Denis Benato, Peiyang Wang, Yonglong Liu, Andy Shevchenko,
	Yicong Hui, Randy Dunlap, MD Danish Anwar, Nathan Chancellor,
	Sai Krishna, Ethan Nelson-Moore, Larysa Zaremba, Joe Damato,
	Double Lo, Chi-hsien Lin, Colin Ian King, netdev, linux-kernel,
	linux-can, linux-parisc, intel-wired-lan, linux-rdma, oss-drivers,
	linux-wireless, brcm80211, brcm80211-dev-list.pdl
In-Reply-To: <20260428171845.2288395-2-u.kleine-koenig@baylibre.com>

On 28/04/2026 19:18, Uwe Kleine-König (The Capable Hub) wrote:
> ... and PCI device helpers.
> 
> The various struct pci_device_id arrays were initialized mostly by one
> the PCI_DEVICE macros and then list expressions. The latter isn't easily
> readable if you're not into PCI. Using named initializers is more
> explicit and thus easier to parse.
> 
> Also use PCI_DEVICE* helper macros to assign .vendor, .device,
> .subvendor and .subdevice where appropriate and skip explicit
> assignments of 0 (which the compiler takes care of).
> 
> The secret plan is to make struct pci_device_id::driver_data an
> anonymous union (similar to
> https://lore.kernel.org/all/cover.1776579304.git.u.kleine-koenig@baylibre.com/)
> and that requires named initializers. But it's also a nice cleanup on
> its own.
> 
> This change doesn't introduce changes to the compiled pci_device_id
> arrays. Tested on x86 and arm64.

for brcmfmac change...

Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>

> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
[...]

>   .../broadcom/brcm80211/brcmfmac/pcie.c        |  17 +-
>   drivers/net/wireless/intel/ipw2x00/ipw2200.c  |  52 +-
>   69 files changed, 1308 insertions(+), 1101 deletions(-)

^ permalink raw reply

* [syzbot] [net?] WARNING in hci_sock_sendmsg
From: syzbot @ 2026-04-30 15:25 UTC (permalink / raw)
  To: davem, edumazet, horms, kuba, kuniyu, linux-kernel, netdev,
	pabeni, syzkaller-bugs, willemb

Hello,

syzbot found the following issue on:

HEAD commit:    9974969c1403 Add linux-next specific files for 20260428
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=16056b6c580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=fff2b12da07ad
dashboard link: https://syzkaller.appspot.com/bug?extid=8fe47b0d0d2830a8d3be
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/755177aac4cc/disk-9974969c.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/fe2f57d4e79e/vmlinux-9974969c.xz
kernel image: https://storage.googleapis.com/syzbot-assets/15b13a4a7518/bzImage-9974969c.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+8fe47b0d0d2830a8d3be@syzkaller.appspotmail.com

------------[ cut here ]------------
workqueue: cannot queue hci_tx_work on wq hci0
WARNING: kernel/workqueue.c:2298 at __queue_work+0xd67/0x1010 kernel/workqueue.c:2296, CPU#1: syz.0.23/5836
Modules linked in:
CPU: 1 UID: 0 PID: 5836 Comm: syz.0.23 Not tainted syzkaller #0 PREEMPT_{RT,(full)} 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
RIP: 0010:__queue_work+0xd87/0x1010 kernel/workqueue.c:2296
Code: 01 00 00 4c 8d 35 49 c5 21 0e 4c 89 e8 48 c1 e8 03 42 80 3c 20 00 74 08 4c 89 ef e8 b3 f6 a0 00 49 8b 75 00 4c 89 f7 4c 89 fa <67> 48 0f b9 3a 48 83 c4 58 5b 41 5c 41 5d 41 5e 41 5f 5d e9 11 48
RSP: 0018:ffffc90005817958 EFLAGS: 00010046
RAX: 1ffff11004a2198f RBX: 0000000000000008 RCX: 0000000000080000
RDX: ffff888037302968 RSI: ffffffff8a252410 RDI: ffffffff8faf47a0
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: dffffc0000000000 R11: ffffed1004a2198d R12: dffffc0000000000
R13: ffff88802510cc78 R14: ffffffff8faf47a0 R15: ffff888037302968
FS:  00007f2b3bbfe6c0(0000) GS:ffff888125dd8000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000110c459547 CR3: 000000004410a000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 queue_work_on+0x106/0x1d0 kernel/workqueue.c:2432
 queue_work include/linux/workqueue.h:696 [inline]
 hci_sock_sendmsg+0xb3d/0xf40 net/bluetooth/hci_sock.c:-1
 sock_sendmsg_nosec+0x112/0x150 net/socket.c:797
 __sock_sendmsg net/socket.c:812 [inline]
 sock_write_iter+0x308/0x410 net/socket.c:1269
 new_sync_write fs/read_write.c:595 [inline]
 vfs_write+0x629/0xba0 fs/read_write.c:688
 ksys_write+0x156/0x270 fs/read_write.c:740
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2b3d9acdd9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f2b3bbfe028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f2b3dc25fa0 RCX: 00007f2b3d9acdd9
RDX: 0000000000000006 RSI: 0000200000000240 RDI: 0000000000000006
RBP: 00007f2b3da42d69 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f2b3dc26038 R14: 00007f2b3dc25fa0 R15: 00007fffb59042a8
 </TASK>
----------------
Code disassembly (best guess), 1 bytes skipped:
   0:	00 00                	add    %al,(%rax)
   2:	4c 8d 35 49 c5 21 0e 	lea    0xe21c549(%rip),%r14        # 0xe21c552
   9:	4c 89 e8             	mov    %r13,%rax
   c:	48 c1 e8 03          	shr    $0x3,%rax
  10:	42 80 3c 20 00       	cmpb   $0x0,(%rax,%r12,1)
  15:	74 08                	je     0x1f
  17:	4c 89 ef             	mov    %r13,%rdi
  1a:	e8 b3 f6 a0 00       	call   0xa0f6d2
  1f:	49 8b 75 00          	mov    0x0(%r13),%rsi
  23:	4c 89 f7             	mov    %r14,%rdi
  26:	4c 89 fa             	mov    %r15,%rdx
* 29:	67 48 0f b9 3a       	ud1    (%edx),%rdi <-- trapping instruction
  2e:	48 83 c4 58          	add    $0x58,%rsp
  32:	5b                   	pop    %rbx
  33:	41 5c                	pop    %r12
  35:	41 5d                	pop    %r13
  37:	41 5e                	pop    %r14
  39:	41 5f                	pop    %r15
  3b:	5d                   	pop    %rbp
  3c:	e9                   	.byte 0xe9
  3d:	11                   	.byte 0x11
  3e:	48                   	rex.W


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* [PATCH net v3] net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
From: Kai Zen @ 2026-04-30 15:26 UTC (permalink / raw)
  To: netdev; +Cc: stable, edumazet, davem, kuba, pabeni, horms, gregkh
In-Reply-To: <CALynFi54eQj7SOmF6QNG0eqhLw7AuURzo6tSYQavvM3ZP74ikw@mail.gmail.com>

rtnl_fill_vfinfo() declares struct ifla_vf_broadcast on the stack
without initialisation:

	struct ifla_vf_broadcast vf_broadcast;

The struct contains a single fixed 32-byte field:

	/* include/uapi/linux/if_link.h */
	struct ifla_vf_broadcast {
		__u8 broadcast[32];
	};

The function then copies dev->broadcast into it using dev->addr_len
as the length:

	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);

On Ethernet devices (the overwhelming majority of SR-IOV NICs)
dev->addr_len is 6, so only the first 6 bytes of broadcast[] are
written. The remaining 26 bytes retain whatever was previously on
the kernel stack. The full struct is then handed to userspace via:

	nla_put(skb, IFLA_VF_BROADCAST,
		sizeof(vf_broadcast), &vf_broadcast)

leaking up to 26 bytes of uninitialised kernel stack per VF per
RTM_GETLINK request, repeatable.

The other vf_* structs in the same function are explicitly zeroed
for exactly this reason - see the memset() calls for ivi,
vf_vlan_info, node_guid and port_guid a few lines above.
vf_broadcast was simply missed when it was added.

Reachability: any unprivileged local process can open AF_NETLINK /
NETLINK_ROUTE without capabilities and send RTM_GETLINK with an
IFLA_EXT_MASK attribute carrying RTEXT_FILTER_VF. The kernel walks
each VF and emits IFLA_VF_BROADCAST, leaking 26 bytes of stack per
VF per request. Stack residue at this call site can include return
addresses and transient sensitive data; KASAN with stack
instrumentation, or KMSAN, will flag the nla_put() when reproduced.

Zero the on-stack struct before the partial memcpy, matching the
existing pattern used for the other vf_* structs in the same
function.

Fixes: 75345f888f70 ("ipoib: show VF broadcast address")
Cc: stable@vger.kernel.org
Signed-off-by: Kai Zen <kai.aizen.dev@gmail.com>
---
 net/core/rtnetlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b613bb6e0..df042da42 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
 		port_guid.vf = ivi.vf;
 
 	memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+	memset(&vf_broadcast, 0, sizeof(vf_broadcast));
 	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
 	vf_vlan.vlan = ivi.vlan;
 	vf_vlan.qos = ivi.qos;
-- 
2.43.0


^ permalink raw reply related

* [PATCH net v3] tipc: fix UAF race in tipc_mon_peer_up/down/remove_peer vs bearer teardown
From: SnailSploit | Kai Aizen @ 2026-04-30 15:26 UTC (permalink / raw)
  To: netdev
  Cc: stable, jmaloy, ying.xue, kuba, pabeni, tipc-discussion,
	tung.q.nguyen, lkp, oe-kbuild-all, syzkaller-bugs,
	SnailSploit | Kai Aizen, syzbot ci
In-Reply-To: <CALynFi5d0DuGW50xq7xQnsDPdEuN5jBGTqh8bcsUwxk6L-FAdA@mail.gmail.com>

From: "SnailSploit | Kai Aizen" <95986478+SnailSploit@users.noreply.github.com>

CVE-2025-40280 fixed tipc_mon_reinit_self() accessing monitors[] from a
workqueue without RTNL.  That patch closed the workqueue path by adding
rtnl_lock() around the call.

However, three additional functions in the same subsystem access
tipc_net->monitors[] from softirq context with no RCU protection at all:

  tipc_mon_peer_up()     - called from tipc_node_write_unlock()
  tipc_mon_peer_down()   - called from tipc_node_write_unlock()
  tipc_mon_remove_peer() - called from tipc_node_link_down()

These are invoked from the packet receive path (tipc_rcv ->
tipc_node_write_unlock / tipc_node_link_down) and hold only the per-node
rwlock, not RTNL.

Concurrently, bearer_disable() -- which always holds RTNL -- calls
tipc_mon_delete(), which sets tn->monitors[bearer_id] = NULL and then
kfree(mon) without an RCU grace period. A softirq reader can observe
the non-NULL slot, take a reference, get preempted, and resume after
kfree(mon) on another CPU, dereferencing freed memory.

Convert monitors[] to __rcu, use rcu_assign_pointer() on creation,
RCU_INIT_POINTER() + synchronize_rcu() on deletion before kfree(), and
the appropriate dereference variant at each read site:

  - tipc_monitor() returns rcu_dereference_bh(...) for softirq callers
    (tipc_mon_peer_up/down/remove_peer/rcv/prep/get_state).
  - tipc_monitor_rtnl() returns rtnl_dereference(...) for RTNL-held
    callers (tipc_mon_delete via bearer_disable, tipc_mon_reinit_self
    via tipc_net_finalize_work which wraps in rtnl_lock(), and the
    netlink dump handlers tipc_nl_add_monitor_peer /
    __tipc_nl_add_monitor).

Also, get_self() was a thin wrapper over tipc_monitor() + ->self deref,
duplicating the RCU-checked load that callers already perform on entry.
With monitors[] becoming __rcu, get_self()'s use of tipc_monitor()
generates a lockdep splat in tipc_mon_delete() (RTNL context) because
the inner load is rcu_dereference_bh().  syzbot CI reported this on
v1/v2 of this patch:

  WARNING: suspicious RCU usage in tipc_mon_delete
  net/tipc/monitor.c:108 suspicious rcu_dereference_check() usage!
  ...
  tipc_monitor_rcu_bh+0xf5/0x110  net/tipc/monitor.c:108
  get_self                        net/tipc/monitor.c:209
  tipc_mon_delete+0x10b/0x4d0     net/tipc/monitor.c:704

Drop get_self() entirely.  Each existing caller already has a valid
mon pointer from its initial RCU-correct load, and mon->self is the
result get_self() was returning.  Replace each "self = get_self(...)"
with "self = mon->self;".  This both removes the duplicate dereference
and fixes the lockdep splat.

synchronize_rcu() in tipc_mon_delete() is placed after
write_unlock_bh() and before timer_shutdown_sync() + kfree() so all
softirq readers that already observed the old pointer have completed
before the memory is freed.

Fixes: 35c55c9877f8 ("tipc: add neighbor monitoring framework")
Cc: stable@vger.kernel.org
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604301148.jfXKC9HF-lkp@intel.com/
Reported-by: syzbot ci <syzbot+ci779e8ed86620f383@syzkaller.appspotmail.com>
Closes: https://ci.syzbot.org/series/6267bc07-4172-4821-b3e5-dac381479d9d
Signed-off-by: SnailSploit | Kai Aizen <95986478+SnailSploit@users.noreply.github.com>
---
 net/tipc/core.h    |  2 +-
 net/tipc/monitor.c | 42 +++++++++++++++++++++++-------------------
 2 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/net/tipc/core.h b/net/tipc/core.h
index 9ce5f9ff6..cd582f7a2 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -109,7 +109,7 @@ struct tipc_net {
 	u32 num_links;
 
 	/* Neighbor monitoring list */
-	struct tipc_monitor *monitors[MAX_BEARERS];
+	struct tipc_monitor __rcu *monitors[MAX_BEARERS];
 	int mon_threshold;
 
 	/* Bearer list */
diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c
index a94b9b36a..0095a62ae 100644
--- a/net/tipc/monitor.c
+++ b/net/tipc/monitor.c
@@ -99,7 +99,14 @@ struct tipc_monitor {
 
 static struct tipc_monitor *tipc_monitor(struct net *net, int bearer_id)
 {
-	return tipc_net(net)->monitors[bearer_id];
+	return rcu_dereference_bh(tipc_net(net)->monitors[bearer_id]);
+}
+
+/* tipc_monitor_rtnl - dereference monitors[] from RTNL-held control path. */
+static struct tipc_monitor * __maybe_unused
+tipc_monitor_rtnl(struct net *net, int bearer_id)
+{
+	return rtnl_dereference(tipc_net(net)->monitors[bearer_id]);
 }
 
 const int tipc_max_domain_size = sizeof(struct tipc_mon_domain);
@@ -192,13 +199,6 @@ static struct tipc_peer *get_peer(struct tipc_monitor *mon, u32 addr)
 	return NULL;
 }
 
-static struct tipc_peer *get_self(struct net *net, int bearer_id)
-{
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
-
-	return mon->self;
-}
-
 static inline bool tipc_mon_is_active(struct net *net, struct tipc_monitor *mon)
 {
 	struct tipc_net *tn = tipc_net(net);
@@ -358,7 +358,7 @@ void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id)
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer)
@@ -422,9 +422,12 @@ static bool tipc_mon_add_peer(struct tipc_monitor *mon, u32 addr,
 void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id)
 {
 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
-	struct tipc_peer *self = get_self(net, bearer_id);
+	struct tipc_peer *self;
 	struct tipc_peer *peer, *head;
 
+	if (!mon)
+		return;
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer && !tipc_mon_add_peer(mon, addr, &peer))
@@ -449,7 +452,7 @@ void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id)
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer) {
@@ -651,7 +654,7 @@ int tipc_mon_create(struct net *net, int bearer_id)
 	struct tipc_peer *self;
 	struct tipc_mon_domain *dom;
 
-	if (tn->monitors[bearer_id])
+	if (rtnl_dereference(tn->monitors[bearer_id]))
 		return 0;
 
 	mon = kzalloc_obj(*mon, GFP_ATOMIC);
@@ -663,7 +666,7 @@ int tipc_mon_create(struct net *net, int bearer_id)
 		kfree(dom);
 		return -ENOMEM;
 	}
-	tn->monitors[bearer_id] = mon;
+	rcu_assign_pointer(tn->monitors[bearer_id], mon);
 	rwlock_init(&mon->lock);
 	mon->net = net;
 	mon->peer_cnt = 1;
@@ -682,16 +685,16 @@ int tipc_mon_create(struct net *net, int bearer_id)
 void tipc_mon_delete(struct net *net, int bearer_id)
 {
 	struct tipc_net *tn = tipc_net(net);
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	struct tipc_peer *self;
 	struct tipc_peer *peer, *tmp;
 
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
+	RCU_INIT_POINTER(tn->monitors[bearer_id], NULL);
 	write_lock_bh(&mon->lock);
-	tn->monitors[bearer_id] = NULL;
 	list_for_each_entry_safe(peer, tmp, &self->list, list) {
 		list_del(&peer->list);
 		hlist_del(&peer->hash);
@@ -700,6 +703,7 @@ void tipc_mon_delete(struct net *net, int bearer_id)
 	}
 	mon->self = NULL;
 	write_unlock_bh(&mon->lock);
+	synchronize_rcu();
 	timer_shutdown_sync(&mon->timer);
 	kfree(self->domain);
 	kfree(self);
@@ -712,7 +716,7 @@ void tipc_mon_reinit_self(struct net *net)
 	int bearer_id;
 
 	for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
-		mon = tipc_monitor(net, bearer_id);
+		mon = tipc_monitor_rtnl(net, bearer_id);
 		if (!mon)
 			continue;
 		write_lock_bh(&mon->lock);
@@ -798,7 +802,7 @@ static int __tipc_nl_add_monitor_peer(struct tipc_peer *peer,
 int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg,
 			     u32 bearer_id, u32 *prev_node)
 {
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	struct tipc_peer *peer;
 
 	if (!mon)
@@ -827,7 +831,7 @@ int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg,
 int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg,
 			  u32 bearer_id)
 {
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	char bearer_name[TIPC_MAX_BEARER_NAME];
 	struct nlattr *attrs;
 	void *hdr;
-- 
2.43.0


^ permalink raw reply related

* [PATCH net 1/3] net/sched: sch_red: Replace direct dequeue call with peek and qdisc_dequeue_peeked
From: Jamal Hadi Salim @ 2026-04-30 15:29 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, davem, kuba, edumazet, pabeni, horms, jiri,
	victor, pctammela, ghandatmanas, rakshitawasthi17, security
In-Reply-To: <20260430152957.194015-1-jhs@mojatatu.com>

When red qdisc has children (eg qfq qdisc) whose peek() callback is
qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
its child (red in this case), it will do the following:
 1a. do a peek() - and when sensing there's an skb the child can offer, then
     - the child in this case(red) calls its child's (qfq) peek.
        qfq does the right thing and will return the gso_skb queue packet.
        Note: if there wasnt a gso_skb entry then qfq will store it there.
 1b. invoke a dequeue() on the child (red). And herein lies the problem.
     - red will call the child's dequeue() which will essentially just
       try to grab something of qfq's queue.

[   78.667668][  T363] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
[   78.667927][  T363] CPU: 1 UID: 0 PID: 363 Comm: ping Not tainted 7.1.0-rc1-00033-g46f74a3f7d57-dirty #790 PREEMPT(full)
[   78.668263][  T363] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[   78.668486][  T363] RIP: 0010:qfq_dequeue+0x446/0xc90 [sch_qfq]
[   78.668718][  T363] Code: 54 c0 e8 dd 90 00 f1 48 c7 c7 e0 03 54 c0 48 89 de e8 ce 90 00 f1 48 8d 7b 48 b8 ff ff 37 00 48 89 fa 48 c1 e0 2a 48 c1 ea 03 <80> 3c 02 00 74 05 e8 ef a1 e1 f1 48 8b 7b 48 48 8d 54 24 58 48 8d
[   78.669312][  T363] RSP: 0018:ffff88810de573e0 EFLAGS: 00010216
[   78.669533][  T363] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
[   78.669790][  T363] RDX: 0000000000000009 RSI: 0000000000000004 RDI: 0000000000000048
[   78.670044][  T363] RBP: ffff888110dc4000 R08: ffffffffb1b0885a R09: fffffbfff6ba9078
[   78.670297][  T363] R10: 0000000000000003 R11: ffff888110e31c80 R12: 0000001880000000
[   78.670560][  T363] R13: ffff888110dc4150 R14: ffff888110dc42b8 R15: 0000000000000200
[   78.670814][  T363] FS:  00007f66a8f09c40(0000) GS:ffff888163428000(0000) knlGS:0000000000000000
[   78.671110][  T363] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   78.671324][  T363] CR2: 000055db4c6a30a8 CR3: 000000010da67000 CR4: 0000000000750ef0
[   78.671585][  T363] PKRU: 55555554
[   78.671713][  T363] Call Trace:
[   78.671843][  T363]  <TASK>
[   78.671936][  T363]  ? __pfx_qfq_dequeue+0x10/0x10 [sch_qfq]
[   78.672148][  T363]  ? __pfx__printk+0x10/0x10
[   78.672322][  T363]  ? srso_alias_return_thunk+0x5/0xfbef5
[   78.672496][  T363]  ? lockdep_hardirqs_on_prepare+0xa8/0x1a0
[   78.672706][  T363]  ? srso_alias_return_thunk+0x5/0xfbef5
[   78.672875][  T363]  ? trace_hardirqs_on+0x19/0x1a0
[   78.673047][  T363]  red_dequeue+0x65/0x270 [sch_red]
[   78.673217][  T363]  ? srso_alias_return_thunk+0x5/0xfbef5
[   78.673385][  T363]  tbf_dequeue.cold+0xb0/0x70c [sch_tbf]
[   78.673566][  T363]  __qdisc_run+0x169/0x1900

The right thing to do in #1b is to grab the skb off gso_skb queue.
This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
method instead.


Fixes: 77be155cba4e ("pkt_sched: Add peek emulation for non-work-conserving qdiscs.")
Reported-by: Manas <ghandatmanas@gmail.com>
Reported-by: Rakshit Awasthi <rakshitawasthi17@gmail.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/sched/sch_red.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 432b8a3000a5..4d0e44a2e7c6 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -162,7 +162,7 @@ static struct sk_buff *red_dequeue(struct Qdisc *sch)
 	struct red_sched_data *q = qdisc_priv(sch);
 	struct Qdisc *child = q->qdisc;
 
-	skb = child->dequeue(child);
+	skb = qdisc_dequeue_peeked(child);
 	if (skb) {
 		qdisc_bstats_update(sch, skb);
 		qdisc_qstats_backlog_dec(sch, skb);
-- 
2.34.1


^ permalink raw reply related

* [PATCH net 2/3] net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked
From: Jamal Hadi Salim @ 2026-04-30 15:29 UTC (permalink / raw)
  To: netdev
  Cc: Victor Nogueria, davem, kuba, edumazet, pabeni, horms, jiri,
	pctammela, ghandatmanas, rakshitawasthi17, security
In-Reply-To: <20260430152957.194015-1-jhs@mojatatu.com>

From: Victor Nogueria <victor@mojatatu.com>

When sfb has children (eg qfq qdisc) whose peek() callback is
qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
its child (sfb in this case), it will do the following:
 1a. do a peek() - and when sensing there's an skb the child can offer, then
     - the child in this case(sfb) calls its child's (qfq) peek.
        qfq does the right thing and will return the gso_skb queue packet.
        Note: if there wasnt a gso_skb entry then qfq will store it there.
 1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
     - sfb will call the child's dequeue() which will essentially just
       try to grab something of qfq's queue.

[  127.594489][  T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f]
[  127.594741][  T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full)
[  127.595059][  T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[  127.595254][  T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq]
[  127.595461][  T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b
[  127.596081][  T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216
[  127.596337][  T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000
[  127.596623][  T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0
[  127.596917][  T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3
[  127.597165][  T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000
[  127.597404][  T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000
[  127.597644][  T453] FS:  00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000
[  127.597956][  T453] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  127.598160][  T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0
[  127.598390][  T453] PKRU: 55555554
[  127.598509][  T453] Call Trace:
[  127.598629][  T453]  <TASK>
[  127.598718][  T453]  ? mark_held_locks+0x40/0x70
[  127.598890][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599053][  T453]  sfb_dequeue+0x88/0x4d0
[  127.599174][  T453]  ? ktime_get+0x137/0x230
[  127.599328][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599480][  T453]  ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq]
[  127.599670][  T453]  ? srso_alias_return_thunk+0x5/0xfbef5
[  127.599831][  T453]  tbf_dequeue+0x6b1/0x1098 [sch_tbf]
[  127.599988][  T453]  __qdisc_run+0x169/0x1900

The right thing to do in #1b is to grab the skb off gso_skb queue.
This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
method instead.

Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler")
Signed-off-by: Victor Nogueria <victor@mojatatu.com>
---
 net/sched/sch_sfb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index bd5ef561030f..d3ee8e5479b3 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -441,7 +441,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
 	struct Qdisc *child = q->qdisc;
 	struct sk_buff *skb;
 
-	skb = child->dequeue(q->qdisc);
+	skb = qdisc_dequeue_peeked(child);
 
 	if (skb) {
 		qdisc_bstats_update(sch, skb);
-- 
2.34.1


^ permalink raw reply related

* [PATCH net 0/3] Replace direct dequeue call with qdisc_dequeue_peeked
From: Jamal Hadi Salim @ 2026-04-30 15:29 UTC (permalink / raw)
  To: netdev
  Cc: Jamal Hadi Salim, davem, kuba, edumazet, pabeni, horms, jiri,
	victor, pctammela, ghandatmanas, rakshitawasthi17, security


When sfb and red qdiscs have children (eg qfq qdisc) whose peek() callback is
qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
its child (red/sfb in this case), it will do the following:
 1a. do a peek() - and when sensing there's an skb the child can offer, then
     - the child in this case(red/sfb) calls its child's (qfq) peek.
        qfq does the right thing and will return the gso_skb queue packet.
        Note: if there wasnt a gso_skb entry then qfq will store it there.
 1b. invoke a dequeue() on the child (red/sfb). And herein lies the problem.
     - red/sfb will call the child's dequeue() which will essentially just
       try to grab something of qfq's queue.

The right thing to do in #1b is to grab the skb off gso_skb queue.
This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
method instead.

Patch 1 fixes the issue for red qdisc. Patch 2 fixes it for sfb.
Patch 3 adds testcases for the two setups.

Jamal Hadi Salim (2):
  net/sched: sch_red: Replace direct dequeue call with peek and
    qdisc_dequeue_peeked
  net/sched: sch_sfb: Replace direct dequeue call with peek and
    qdisc_dequeue_peeked

Victor Nogueira (1):
  selftests/tc-testing: Add tests that force red and sfb to dequeue from
    child's gso_skb

 net/sched/sch_red.c                           |   2 +-
 net/sched/sch_sfb.c                           |   2 +-
 .../tc-testing/tc-tests/infra/qdiscs.json     | 148 ++++++++++++++++++
 3 files changed, 150 insertions(+), 2 deletions(-)

-- 
2.34.1


^ permalink raw reply

* [PATCH net 3/3] selftests/tc-testing: Add tests that force red and sfb to dequeue from child's gso_skb
From: Jamal Hadi Salim @ 2026-04-30 15:29 UTC (permalink / raw)
  To: netdev
  Cc: Victor Nogueira, davem, kuba, edumazet, pabeni, horms, jiri,
	pctammela, ghandatmanas, rakshitawasthi17, security,
	Jamal Hadi Salim
In-Reply-To: <20260430152957.194015-1-jhs@mojatatu.com>

From: Victor Nogueira <victor@mojatatu.com>

Create 4 test cases:
- Force red to dequeue from its child's gso_skb with qfq leaf
- Force sfb to dequeue from its child's gso_skb with qfq leaf
- Force red to dequeue from its child's gso_skb with dualpi2 leaf
- Force sfb to dequeue from its child's gso_skb with dualpi2 leaf

All of them have tbf followed by red (or sfb) followed by qfq (or
dualpi2). Since tbf calls its child's peek followed by
qdisc_dequeue_peeked, it will force red/sfb to call their child's peek.
In this case, since the child (qfq/dualpi2) has qdisc_peek_dequeued as
its peek callback, the packet will be stored in its gso_skb queue. During
the subsequent call to qdisc_dequeue_peeked, red/sfb will have to dequeue
from the child's gso_skb to retrieve the packet.
Not doing so will cause a NULL ptr deref which was happening before a
recent fix.

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
---
 .../tc-testing/tc-tests/infra/qdiscs.json     | 148 ++++++++++++++++++
 1 file changed, 148 insertions(+)

diff --git a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
index eefadd0546d3..b1f856cf62c1 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json
@@ -1136,5 +1136,153 @@
         "teardown": [
             "$TC qdisc del dev $DUMMY handle 1: root"
         ]
+    },
+    {
+        "id": "7a5f",
+        "name": "Force red to dequeue from its child's gso_skb with qfq leaf",
+        "category": [
+            "qdisc",
+            "tbf",
+            "red",
+            "qfq"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link set dev $DUMMY up || true",
+            "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+            "$TC qdisc add dev $DUMMY root handle 1: tbf rate 88bit burst 1661b peakrate 2257333 minburst 1024 limit 7b",
+            "$TC qdisc add dev $DUMMY parent 1: handle 2: red limit 757 min 16 max 24 avpkt 16",
+            "$TC qdisc add dev $DUMMY parent 2: handle 3: qfq",
+            "$TC class add dev $DUMMY classid 3:1 parent 3: qfq maxpkt 512 weight 1",
+            "$TC filter add dev $DUMMY parent 3: protocol ip prio 1 matchall classid 3:1 action ok"
+        ],
+        "cmdUnderTest": "ping -c 1 10.10.10.1 -W0.01 -I$DUMMY || true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:",
+        "matchJSON": [
+            {
+                "kind": "red",
+                "handle": "2:",
+                "bytes": 98,
+                "packets": 1,
+                "backlog": 0,
+                "qlen": 0
+            }
+        ],
+        "teardown": [
+            "$TC qdisc del dev $DUMMY handle 1: root"
+        ]
+    },
+    {
+        "id": "cdae",
+        "name": "Force sfb to dequeue from its child's gso_skb with qfq leaf",
+        "category": [
+            "qdisc",
+            "tbf",
+            "sfb",
+            "qfq"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link set dev $DUMMY up || true",
+            "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+            "$TC qdisc add dev $DUMMY root handle 1: tbf rate 88bit burst 1661b peakrate 2257333 minburst 1024 limit 7b",
+            "$TC qdisc add dev $DUMMY parent 1: handle 2: sfb",
+            "$TC qdisc add dev $DUMMY parent 2: handle 3: qfq",
+            "$TC class add dev $DUMMY classid 3:1 parent 3: qfq maxpkt 512 weight 1",
+            "$TC filter add dev $DUMMY parent 3: protocol ip prio 1 matchall classid 3:1 action ok"
+        ],
+        "cmdUnderTest": "ping -c 1 10.10.10.1 -W0.01 -I$DUMMY || true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:",
+        "matchJSON": [
+            {
+                "kind": "sfb",
+                "handle": "2:",
+                "bytes": 98,
+                "packets": 1,
+                "backlog": 0,
+                "qlen": 0
+            }
+        ],
+        "teardown": [
+            "$TC qdisc del dev $DUMMY handle 1: root"
+        ]
+    },
+    {
+        "id": "291d",
+        "name": "Force red to dequeue from its child's gso_skb with dualpi2 leaf",
+        "category": [
+            "qdisc",
+            "tbf",
+            "red",
+            "dualpi2"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link set dev $DUMMY up || true",
+            "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+            "$TC qdisc add dev $DUMMY root handle 1: tbf rate 88bit burst 1661b peakrate 2257333 minburst 1024 limit 7b",
+            "$TC qdisc add dev $DUMMY parent 1: handle 2: red limit 757 min 16 max 24 avpkt 16",
+            "$TC qdisc add dev $DUMMY parent 2: handle 3: dualpi2"
+        ],
+        "cmdUnderTest": "ping -c 1 10.10.10.1 -W0.01 -I$DUMMY || true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:",
+        "matchJSON": [
+            {
+                "kind": "red",
+                "handle": "2:",
+                "bytes": 98,
+                "packets": 1,
+                "backlog": 0,
+                "qlen": 0
+            }
+        ],
+        "teardown": [
+            "$TC qdisc del dev $DUMMY handle 1: root"
+        ]
+    },
+    {
+        "id": "9c6d",
+        "name": "Force sfb to dequeue from its child's gso_skb with dualpi2 leaf",
+        "category": [
+            "qdisc",
+            "tbf",
+            "sfb",
+            "dualpi2"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link set dev $DUMMY up || true",
+            "$IP addr add 10.10.11.10/24 dev $DUMMY || true",
+            "$TC qdisc add dev $DUMMY root handle 1: tbf rate 88bit burst 1661b peakrate 2257333 minburst 1024 limit 7b",
+            "$TC qdisc add dev $DUMMY parent 1: handle 2: sfb",
+            "$TC qdisc add dev $DUMMY parent 2: handle 3: dualpi2"
+        ],
+        "cmdUnderTest": "ping -c 1 10.10.10.1 -W0.01 -I$DUMMY || true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC -s -j qdisc ls dev $DUMMY parent 1:",
+        "matchJSON": [
+            {
+                "kind": "sfb",
+                "handle": "2:",
+                "bytes": 98,
+                "packets": 1,
+                "backlog": 0,
+                "qlen": 0
+            }
+        ],
+        "teardown": [
+            "$TC qdisc del dev $DUMMY handle 1: root"
+        ]
     }
 ]
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v2 iproute2-next] utils: add fflush_monitor() helper
From: David Ahern @ 2026-04-30 15:35 UTC (permalink / raw)
  To: Eric Dumazet, Stephen Hemminger
  Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, netdev,
	eric.dumazet
In-Reply-To: <20260427081953.364819-1-edumazet@google.com>

On 4/27/26 2:19 AM, Eric Dumazet wrote:
> Some fflush() calls only make sense for monitor programs.
> 
> For other cases, forcing a flush is expensive.
> 
> After this patch, ip, tc and ss are correctly buffering most of their
> output when redirected to a file.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  include/utils.h  |  7 +++++++
>  ip/ipaddress.c   | 12 +++++++-----
>  ip/iplink.c      |  4 ++--
>  ip/ipmonitor.c   |  1 +
>  ip/ipmptcp.c     | 10 +++++-----
>  ip/ipneigh.c     |  4 ++--
>  ip/ipnetconf.c   |  2 +-
>  ip/ipnetns.c     |  2 +-
>  ip/ipnexthop.c   | 12 ++++++------
>  ip/iproute.c     |  4 ++--
>  ip/iprule.c      |  2 +-
>  ip/iptoken.c     |  2 +-
>  ip/tcp_metrics.c |  2 +-
>  lib/utils.c      |  1 +
>  misc/ss.c        |  3 ++-
>  tc/tc_class.c    |  2 +-
>  tc/tc_filter.c   |  2 +-
>  tc/tc_monitor.c  |  1 +
>  tc/tc_qdisc.c    |  2 +-
>  19 files changed, 44 insertions(+), 31 deletions(-)
> 

no longer applies after merging main to next.


^ permalink raw reply

* Re: [PATCH iproute2-next] tc: use ll_init_map() only when needed
From: David Ahern @ 2026-04-30 15:36 UTC (permalink / raw)
  To: Eric Dumazet, Stephen Hemminger, Jamal Hadi Salim
  Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, netdev,
	eric.dumazet
In-Reply-To: <20260428082851.3240821-1-edumazet@google.com>

Jamal: waiting for your review ...

On 4/28/26 2:28 AM, Eric Dumazet wrote:
> Some setups can have thousands of devices.
> 
> ll_init_map() is rather expensive for them.
> 
> Only call ll_init_map() in the following cases:
> 
> 1) tc runs in batch mode.
> 2) tc runs in monitor mode.
> 3) tc dumps qdiscs/classes/filters for all netdev.
> 
> This greatly reduces RTNL pressure on common operations.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  tc/f_route.c   |  1 -
>  tc/m_mirred.c  |  2 --
>  tc/tc.c        |  1 +
>  tc/tc_class.c  |  6 ++----
>  tc/tc_filter.c | 32 ++++++++++++++++----------------
>  tc/tc_qdisc.c  |  5 ++---
>  6 files changed, 21 insertions(+), 26 deletions(-)
> 
> diff --git a/tc/f_route.c b/tc/f_route.c
> index 96b99b06be179c90dfb0d24d9577b5206dd98ef1..c234ddf0cb9309556844c85047d0f9ef53a2fd7b 100644
> --- a/tc/f_route.c
> +++ b/tc/f_route.c
> @@ -76,7 +76,6 @@ static int route_parse_opt(const struct filter_util *qu, char *handle, int argc,
>  			__u32 id;
>  
>  			NEXT_ARG();
> -			ll_init_map(&rth);
>  			if ((id = ll_name_to_index(*argv)) <= 0) {
>  				fprintf(stderr, "Illegal \"fromif\"\n");
>  				return -1;
> diff --git a/tc/m_mirred.c b/tc/m_mirred.c
> index f4da3c76284460d7f4bb73c7c3c172732f054632..e9ae5199432e828026f15ce226c5f5f84998c660 100644
> --- a/tc/m_mirred.c
> +++ b/tc/m_mirred.c
> @@ -213,8 +213,6 @@ parse_direction(const struct action_util *a, int *argc_p, char ***argv_p,
>  	if (d[0])  {
>  		int idx;
>  
> -		ll_init_map(&rth);
> -
>  		idx = ll_name_to_index(d);
>  		if (!idx)
>  			return nodev(d);
> diff --git a/tc/tc.c b/tc/tc.c
> index 0fc658c881f0f553f1f1f8d87b46943d4d0eed8f..7d69e4d533a98b9c071cb954443a049a52252f2c 100644
> --- a/tc/tc.c
> +++ b/tc/tc.c
> @@ -243,6 +243,7 @@ static int batch(const char *name)
>  		return -1;
>  	}
>  
> +	ll_init_map(&rth);
>  	ret = do_batch(name, force, tc_batch_cmd, NULL);
>  
>  	rtnl_close(&rth);
> diff --git a/tc/tc_class.c b/tc/tc_class.c
> index 6d707d8c924f4b5e90201d4de8e9779f82ce17f3..9aace019e6c8b96fb51edb4fe89bea5b7469beed 100644
> --- a/tc/tc_class.c
> +++ b/tc/tc_class.c
> @@ -136,11 +136,11 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)
>  	}
>  
>  	if (d[0])  {
> -		ll_init_map(&rth);
> -
>  		req.t.tcm_ifindex = ll_name_to_index(d);
>  		if (!req.t.tcm_ifindex)
>  			return -nodev(d);
> +	} else {
> +		ll_init_map(&rth);
>  	}
>  
>  	if (rtnl_talk(&rth, &req.n, NULL) < 0)
> @@ -437,8 +437,6 @@ static int tc_class_list(int argc, char **argv)
>  		argc--; argv++;
>  	}
>  
> -	ll_init_map(&rth);
> -
>  	if (d[0]) {
>  		t.tcm_ifindex = ll_name_to_index(d);
>  		if (!t.tcm_ifindex)
> diff --git a/tc/tc_filter.c b/tc/tc_filter.c
> index 7db850bda11a3408ec66b457c9fc590f3a734f65..be70e360849e5058192640da0f061810a99e2ea8 100644
> --- a/tc/tc_filter.c
> +++ b/tc/tc_filter.c
> @@ -188,16 +188,17 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
>  		addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
>  
>  	if (d[0])  {
> -		ll_init_map(&rth);
> -
>  		req.t.tcm_ifindex = ll_name_to_index(d);
>  		if (req.t.tcm_ifindex == 0) {
>  			fprintf(stderr, "Cannot find device \"%s\"\n", d);
>  			return 1;
>  		}
> -	} else if (block_index) {
> -		req.t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
> -		req.t.tcm_block_index = block_index;
> +	} else {
> +		ll_init_map(&rth);
> +		if (block_index) {
> +			req.t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
> +			req.t.tcm_block_index = block_index;
> +		}
>  	}
>  
>  	if (q) {
> @@ -539,8 +540,6 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
>  	}
>  
>  	if (d[0])  {
> -		ll_init_map(&rth);
> -
>  		req.t.tcm_ifindex = ll_name_to_index(d);
>  		if (!req.t.tcm_ifindex)
>  			return -nodev(d);
> @@ -704,21 +703,22 @@ static int tc_filter_list(int cmd, int argc, char **argv)
>  
>  	req.t.tcm_info = TC_H_MAKE(prio<<16, protocol);
>  
> -	ll_init_map(&rth);
> -
>  	if (d[0]) {
>  		req.t.tcm_ifindex = ll_name_to_index(d);
>  		if (!req.t.tcm_ifindex)
>  			return -nodev(d);
>  		filter_ifindex = req.t.tcm_ifindex;
> -	} else if (block_index) {
> -		if (!tc_qdisc_block_exists(block_index)) {
> -			fprintf(stderr, "Cannot find block \"%u\"\n", block_index);
> -			return 1;
> +	} else {
> +		ll_init_map(&rth);
> +		if (block_index) {
> +			if (!tc_qdisc_block_exists(block_index)) {
> +				fprintf(stderr, "Cannot find block \"%u\"\n", block_index);
> +				return 1;
> +			}
> +			req.t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
> +			req.t.tcm_block_index = block_index;
> +			filter_block_index = block_index;
>  		}
> -		req.t.tcm_ifindex = TCM_IFINDEX_MAGIC_BLOCK;
> -		req.t.tcm_block_index = block_index;
> -		filter_block_index = block_index;
>  	}
>  
>  	if (filter_chain_index_set)
> diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
> index 7eb9a31baa31fb91a8141c9eca1135e76a52fa8b..252ea861f249a5a71cf782389776e68c3e48c6cc 100644
> --- a/tc/tc_qdisc.c
> +++ b/tc/tc_qdisc.c
> @@ -193,8 +193,6 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
>  	if (d[0])  {
>  		int idx;
>  
> -		ll_init_map(&rth);
> -
>  		idx = ll_name_to_index(d);
>  		if (!idx)
>  			return -nodev(d);
> @@ -411,13 +409,14 @@ static int tc_qdisc_list(int argc, char **argv)
>  		argc--; argv++;
>  	}
>  
> -	ll_init_map(&rth);
>  
>  	if (d[0]) {
>  		req.t.tcm_ifindex = ll_name_to_index(d);
>  		if (!req.t.tcm_ifindex)
>  			return -nodev(d);
>  		filter_ifindex = req.t.tcm_ifindex;
> +	} else {
> +		ll_init_map(&rth);
>  	}
>  
>  	if (dump_invisible) {


^ permalink raw reply

* Re: [PATCH v2 iproute2-next] utils: add fflush_monitor() helper
From: Eric Dumazet @ 2026-04-30 15:36 UTC (permalink / raw)
  To: David Ahern
  Cc: Stephen Hemminger, David S . Miller, Jakub Kicinski, Paolo Abeni,
	netdev, eric.dumazet
In-Reply-To: <6e00eaa5-a4d7-45dd-9d90-fb319b76c9fa@kernel.org>

On Thu, Apr 30, 2026 at 8:35 AM David Ahern <dsahern@kernel.org> wrote:
>
> On 4/27/26 2:19 AM, Eric Dumazet wrote:
> > Some fflush() calls only make sense for monitor programs.
> >
> > For other cases, forcing a flush is expensive.
> >
> > After this patch, ip, tc and ss are correctly buffering most of their
> > output when redirected to a file.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > ---
> >  include/utils.h  |  7 +++++++
> >  ip/ipaddress.c   | 12 +++++++-----
> >  ip/iplink.c      |  4 ++--
> >  ip/ipmonitor.c   |  1 +
> >  ip/ipmptcp.c     | 10 +++++-----
> >  ip/ipneigh.c     |  4 ++--
> >  ip/ipnetconf.c   |  2 +-
> >  ip/ipnetns.c     |  2 +-
> >  ip/ipnexthop.c   | 12 ++++++------
> >  ip/iproute.c     |  4 ++--
> >  ip/iprule.c      |  2 +-
> >  ip/iptoken.c     |  2 +-
> >  ip/tcp_metrics.c |  2 +-
> >  lib/utils.c      |  1 +
> >  misc/ss.c        |  3 ++-
> >  tc/tc_class.c    |  2 +-
> >  tc/tc_filter.c   |  2 +-
> >  tc/tc_monitor.c  |  1 +
> >  tc/tc_qdisc.c    |  2 +-
> >  19 files changed, 44 insertions(+), 31 deletions(-)
> >
>
> no longer applies after merging main to next.0

Hmm... I thought Stephen had a better implementation?

^ permalink raw reply

* Re: [PATCH] net/sched: sch_dualpi2: Add missing skb check
From: Jamal Hadi Salim @ 2026-04-30 15:37 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Manas, jiri, davem, edumazet, pabeni, horms, rakshitawasthi17,
	netdev, linux-kernel
In-Reply-To: <20260429185248.4761905d@kernel.org>

On Wed, Apr 29, 2026 at 9:52 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Tue, 28 Apr 2026 20:27:30 +0530 Manas wrote:
> > A packed is dequeued using the function `dequeue_packet()` but there is
> > no check to see if a packet is dequeued. The assignment is always
> > considered as true resulting in null-ptr-deref
> >
> > Fixes: 8f9516daedd6 ("sched: Add enqueue/dequeue of dualpi2 qdisc")
> > Reported-by: Manas <ghandatmanas@gmail.com>
> > Reported-by: Rakshit Awasthi <rakshitawasthi17@gmail.com>
> > Signed-off-by: Manas <ghandatmanas@gmail.com>
>
> Sorry but the patch is nonsensical. Please don't waste our time.
>

Fixed in: https://lore.kernel.org/netdev/20260430152957.194015-1-jhs@mojatatu.com/T/#mfe773e91a05e103f47dfa71ea434210aebb74e17

As I have mentioned a few times, when you find issues, please either
a) describe how you found the issue (a reproducer helps) or b) provide
tdc test case for extra bonus.
As you can see the issue has _nothing_ to do with dualpi2.

cheers,
jamal

^ permalink raw reply

* Re: [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO
From: kernel test robot @ 2026-04-30 15:36 UTC (permalink / raw)
  To: Ren Wei, netdev
  Cc: llvm, oe-kbuild-all, davem, edumazet, kuba, pabeni, horms, jbenc,
	yuantan098, yifanwucs, tomapufckgml, bird, lx24, caoruide123,
	n05ec
In-Reply-To: <6112cce99b4e3571444a616d0fb19e91e2fcca72.1776597598.git.caoruide123@gmail.com>

Hi Ren,

kernel test robot noticed the following build errors:

[auto build test ERROR on net/main]

url:    https://github.com/intel-lab-lkp/linux/commits/Ren-Wei/net-nsh-handle-nested-NSH-headers-during-GSO/20260423-084001
base:   net/main
patch link:    https://lore.kernel.org/r/6112cce99b4e3571444a616d0fb19e91e2fcca72.1776597598.git.caoruide123%40gmail.com
patch subject: [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO
config: i386-randconfig-003-20260430 (https://download.01.org/0day-ci/archive/20260430/202604302359.kU59LnTI-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260430/202604302359.kU59LnTI-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604302359.kU59LnTI-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "skb_network_protocol" [net/nsh/nsh.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH net v3] net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
From: Kai Zen @ 2026-04-30 15:40 UTC (permalink / raw)
  To: netdev; +Cc: stable, edumazet, davem, kuba, pabeni, horms, gregkh
In-Reply-To: <CALynFi54eQj7SOmF6QNG0eqhLw7AuURzo6tSYQavvM3ZP74ikw@mail.gmail.com>

rtnl_fill_vfinfo() declares struct ifla_vf_broadcast on the stack
without initialisation:

	struct ifla_vf_broadcast vf_broadcast;

The struct contains a single fixed 32-byte field:

	/* include/uapi/linux/if_link.h */
	struct ifla_vf_broadcast {
		__u8 broadcast[32];
	};

The function then copies dev->broadcast into it using dev->addr_len
as the length:

	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);

On Ethernet devices (the overwhelming majority of SR-IOV NICs)
dev->addr_len is 6, so only the first 6 bytes of broadcast[] are
written. The remaining 26 bytes retain whatever was previously on
the kernel stack. The full struct is then handed to userspace via:

	nla_put(skb, IFLA_VF_BROADCAST,
		sizeof(vf_broadcast), &vf_broadcast)

leaking up to 26 bytes of uninitialised kernel stack per VF per
RTM_GETLINK request, repeatable.

The other vf_* structs in the same function are explicitly zeroed
for exactly this reason - see the memset() calls for ivi,
vf_vlan_info, node_guid and port_guid a few lines above.
vf_broadcast was simply missed when it was added.

Reachability: any unprivileged local process can open AF_NETLINK /
NETLINK_ROUTE without capabilities and send RTM_GETLINK with an
IFLA_EXT_MASK attribute carrying RTEXT_FILTER_VF. The kernel walks
each VF and emits IFLA_VF_BROADCAST, leaking 26 bytes of stack per
VF per request. Stack residue at this call site can include return
addresses and transient sensitive data; KASAN with stack
instrumentation, or KMSAN, will flag the nla_put() when reproduced.

Zero the on-stack struct before the partial memcpy, matching the
existing pattern used for the other vf_* structs in the same
function.

Fixes: 75345f888f70 ("ipoib: show VF broadcast address")
Cc: stable@vger.kernel.org
Signed-off-by: Kai Zen <kai.aizen.dev@gmail.com>
---
 net/core/rtnetlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b613bb6e0..df042da42 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
 		port_guid.vf = ivi.vf;
 
 	memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+	memset(&vf_broadcast, 0, sizeof(vf_broadcast));
 	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
 	vf_vlan.vlan = ivi.vlan;
 	vf_vlan.qos = ivi.qos;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH iproute2-next] ll_map: add RTEXT_FILTER_SKIP_STATS to ll_init_map()
From: patchwork-bot+netdevbpf @ 2026-04-30 15:40 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: dsahern, stephen, davem, kuba, pabeni, netdev, eric.dumazet
In-Reply-To: <20260428075647.3206962-1-edumazet@google.com>

Hello:

This patch was applied to iproute2/iproute2-next.git (main)
by David Ahern <dsahern@kernel.org>:

On Tue, 28 Apr 2026 07:56:47 +0000 you wrote:
> ll_init_map() only cares about names and ifindex.
> 
> We can save ~300 bytes per device if we ask the kernel to skip stats,
> not counting many cpu cycles if per-cpu stats are involved.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> 
> [...]

Here is the summary with links:
  - [iproute2-next] ll_map: add RTEXT_FILTER_SKIP_STATS to ll_init_map()
    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=7bd7f33509d0

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH iproute2-next] bash-completion: devlink: Fix dev completion trailing colon
From: patchwork-bot+netdevbpf @ 2026-04-30 15:40 UTC (permalink / raw)
  To: Danielle Ratson; +Cc: netdev, jiri, dsahern
In-Reply-To: <20260426115139.712959-1-danieller@nvidia.com>

Hello:

This patch was applied to iproute2/iproute2-next.git (main)
by David Ahern <dsahern@kernel.org>:

On Sun, 26 Apr 2026 14:51:39 +0300 you wrote:
> Cited commit extended 'devlink dev show' to print the instance index when
> the kernel provides DEVLINK_ATTR_INDEX, printing the device handle followed
> by a colon and the index. The completion code was using the raw text output
> as a word list, causing the device handle to be offered with a trailing
> colon, e.g. "pci/0000:01:00.0:" instead of "pci/0000:01:00.0".
> 
> Switch to JSON output and extract device names using jq, consistent
> with how port completion already works, to reliably get only the device
> handle names regardless of what additional attributes are printed.
> 
> [...]

Here is the summary with links:
  - [iproute2-next] bash-completion: devlink: Fix dev completion trailing colon
    https://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git/commit/?id=03b33c7550e9

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* [PATCH net v3] tipc: fix UAF race in tipc_mon_peer_up/down/remove_peer vs bearer teardown
From: SnailSploit | Kai Aizen @ 2026-04-30 15:40 UTC (permalink / raw)
  To: netdev
  Cc: stable, jmaloy, ying.xue, kuba, pabeni, tipc-discussion,
	tung.q.nguyen, lkp, oe-kbuild-all, syzkaller-bugs,
	SnailSploit | Kai Aizen, syzbot ci
In-Reply-To: <CALynFi5d0DuGW50xq7xQnsDPdEuN5jBGTqh8bcsUwxk6L-FAdA@mail.gmail.com>

From: "SnailSploit | Kai Aizen" <95986478+SnailSploit@users.noreply.github.com>

CVE-2025-40280 fixed tipc_mon_reinit_self() accessing monitors[] from a
workqueue without RTNL.  That patch closed the workqueue path by adding
rtnl_lock() around the call.

However, three additional functions in the same subsystem access
tipc_net->monitors[] from softirq context with no RCU protection at all:

  tipc_mon_peer_up()     - called from tipc_node_write_unlock()
  tipc_mon_peer_down()   - called from tipc_node_write_unlock()
  tipc_mon_remove_peer() - called from tipc_node_link_down()

These are invoked from the packet receive path (tipc_rcv ->
tipc_node_write_unlock / tipc_node_link_down) and hold only the per-node
rwlock, not RTNL.

Concurrently, bearer_disable() -- which always holds RTNL -- calls
tipc_mon_delete(), which sets tn->monitors[bearer_id] = NULL and then
kfree(mon) without an RCU grace period. A softirq reader can observe
the non-NULL slot, take a reference, get preempted, and resume after
kfree(mon) on another CPU, dereferencing freed memory.

Convert monitors[] to __rcu, use rcu_assign_pointer() on creation,
RCU_INIT_POINTER() + synchronize_rcu() on deletion before kfree(), and
the appropriate dereference variant at each read site:

  - tipc_monitor() returns rcu_dereference_bh(...) for softirq callers
    (tipc_mon_peer_up/down/remove_peer/rcv/prep/get_state).
  - tipc_monitor_rtnl() returns rtnl_dereference(...) for RTNL-held
    callers (tipc_mon_delete via bearer_disable, tipc_mon_reinit_self
    via tipc_net_finalize_work which wraps in rtnl_lock(), and the
    netlink dump handlers tipc_nl_add_monitor_peer /
    __tipc_nl_add_monitor).

Also, get_self() was a thin wrapper over tipc_monitor() + ->self deref,
duplicating the RCU-checked load that callers already perform on entry.
With monitors[] becoming __rcu, get_self()'s use of tipc_monitor()
generates a lockdep splat in tipc_mon_delete() (RTNL context) because
the inner load is rcu_dereference_bh().  syzbot CI reported this on
v1/v2 of this patch:

  WARNING: suspicious RCU usage in tipc_mon_delete
  net/tipc/monitor.c:108 suspicious rcu_dereference_check() usage!
  ...
  tipc_monitor_rcu_bh+0xf5/0x110  net/tipc/monitor.c:108
  get_self                        net/tipc/monitor.c:209
  tipc_mon_delete+0x10b/0x4d0     net/tipc/monitor.c:704

Drop get_self() entirely.  Each existing caller already has a valid
mon pointer from its initial RCU-correct load, and mon->self is the
result get_self() was returning.  Replace each "self = get_self(...)"
with "self = mon->self;".  This both removes the duplicate dereference
and fixes the lockdep splat.

synchronize_rcu() in tipc_mon_delete() is placed after
write_unlock_bh() and before timer_shutdown_sync() + kfree() so all
softirq readers that already observed the old pointer have completed
before the memory is freed.

Fixes: 35c55c9877f8 ("tipc: add neighbor monitoring framework")
Cc: stable@vger.kernel.org
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604301148.jfXKC9HF-lkp@intel.com/
Reported-by: syzbot ci <syzbot+ci779e8ed86620f383@syzkaller.appspotmail.com>
Closes: https://ci.syzbot.org/series/6267bc07-4172-4821-b3e5-dac381479d9d
Signed-off-by: SnailSploit | Kai Aizen <95986478+SnailSploit@users.noreply.github.com>
---
 net/tipc/core.h    |  2 +-
 net/tipc/monitor.c | 42 +++++++++++++++++++++++-------------------
 2 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/net/tipc/core.h b/net/tipc/core.h
index 9ce5f9ff6..cd582f7a2 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -109,7 +109,7 @@ struct tipc_net {
 	u32 num_links;
 
 	/* Neighbor monitoring list */
-	struct tipc_monitor *monitors[MAX_BEARERS];
+	struct tipc_monitor __rcu *monitors[MAX_BEARERS];
 	int mon_threshold;
 
 	/* Bearer list */
diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c
index a94b9b36a..0095a62ae 100644
--- a/net/tipc/monitor.c
+++ b/net/tipc/monitor.c
@@ -99,7 +99,14 @@ struct tipc_monitor {
 
 static struct tipc_monitor *tipc_monitor(struct net *net, int bearer_id)
 {
-	return tipc_net(net)->monitors[bearer_id];
+	return rcu_dereference_bh(tipc_net(net)->monitors[bearer_id]);
+}
+
+/* tipc_monitor_rtnl - dereference monitors[] from RTNL-held control path. */
+static struct tipc_monitor * __maybe_unused
+tipc_monitor_rtnl(struct net *net, int bearer_id)
+{
+	return rtnl_dereference(tipc_net(net)->monitors[bearer_id]);
 }
 
 const int tipc_max_domain_size = sizeof(struct tipc_mon_domain);
@@ -192,13 +199,6 @@ static struct tipc_peer *get_peer(struct tipc_monitor *mon, u32 addr)
 	return NULL;
 }
 
-static struct tipc_peer *get_self(struct net *net, int bearer_id)
-{
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
-
-	return mon->self;
-}
-
 static inline bool tipc_mon_is_active(struct net *net, struct tipc_monitor *mon)
 {
 	struct tipc_net *tn = tipc_net(net);
@@ -358,7 +358,7 @@ void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id)
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer)
@@ -422,9 +422,12 @@ static bool tipc_mon_add_peer(struct tipc_monitor *mon, u32 addr,
 void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id)
 {
 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
-	struct tipc_peer *self = get_self(net, bearer_id);
+	struct tipc_peer *self;
 	struct tipc_peer *peer, *head;
 
+	if (!mon)
+		return;
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer && !tipc_mon_add_peer(mon, addr, &peer))
@@ -449,7 +452,7 @@ void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id)
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
 	write_lock_bh(&mon->lock);
 	peer = get_peer(mon, addr);
 	if (!peer) {
@@ -651,7 +654,7 @@ int tipc_mon_create(struct net *net, int bearer_id)
 	struct tipc_peer *self;
 	struct tipc_mon_domain *dom;
 
-	if (tn->monitors[bearer_id])
+	if (rtnl_dereference(tn->monitors[bearer_id]))
 		return 0;
 
 	mon = kzalloc_obj(*mon, GFP_ATOMIC);
@@ -663,7 +666,7 @@ int tipc_mon_create(struct net *net, int bearer_id)
 		kfree(dom);
 		return -ENOMEM;
 	}
-	tn->monitors[bearer_id] = mon;
+	rcu_assign_pointer(tn->monitors[bearer_id], mon);
 	rwlock_init(&mon->lock);
 	mon->net = net;
 	mon->peer_cnt = 1;
@@ -682,16 +685,16 @@ int tipc_mon_create(struct net *net, int bearer_id)
 void tipc_mon_delete(struct net *net, int bearer_id)
 {
 	struct tipc_net *tn = tipc_net(net);
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	struct tipc_peer *self;
 	struct tipc_peer *peer, *tmp;
 
 	if (!mon)
 		return;
 
-	self = get_self(net, bearer_id);
+	self = mon->self;
+	RCU_INIT_POINTER(tn->monitors[bearer_id], NULL);
 	write_lock_bh(&mon->lock);
-	tn->monitors[bearer_id] = NULL;
 	list_for_each_entry_safe(peer, tmp, &self->list, list) {
 		list_del(&peer->list);
 		hlist_del(&peer->hash);
@@ -700,6 +703,7 @@ void tipc_mon_delete(struct net *net, int bearer_id)
 	}
 	mon->self = NULL;
 	write_unlock_bh(&mon->lock);
+	synchronize_rcu();
 	timer_shutdown_sync(&mon->timer);
 	kfree(self->domain);
 	kfree(self);
@@ -712,7 +716,7 @@ void tipc_mon_reinit_self(struct net *net)
 	int bearer_id;
 
 	for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
-		mon = tipc_monitor(net, bearer_id);
+		mon = tipc_monitor_rtnl(net, bearer_id);
 		if (!mon)
 			continue;
 		write_lock_bh(&mon->lock);
@@ -798,7 +802,7 @@ static int __tipc_nl_add_monitor_peer(struct tipc_peer *peer,
 int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg,
 			     u32 bearer_id, u32 *prev_node)
 {
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	struct tipc_peer *peer;
 
 	if (!mon)
@@ -827,7 +831,7 @@ int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg,
 int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg,
 			  u32 bearer_id)
 {
-	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
+	struct tipc_monitor *mon = tipc_monitor_rtnl(net, bearer_id);
 	char bearer_name[TIPC_MAX_BEARER_NAME];
 	struct nlattr *attrs;
 	void *hdr;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net 1/3] net/sched: sch_red: Replace direct dequeue call with peek and qdisc_dequeue_peeked
From: Eric Dumazet @ 2026-04-30 15:41 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: netdev, davem, kuba, pabeni, horms, jiri, victor, pctammela,
	ghandatmanas, rakshitawasthi17, security
In-Reply-To: <20260430152957.194015-2-jhs@mojatatu.com>

On Thu, Apr 30, 2026 at 8:30 AM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>
> When red qdisc has children (eg qfq qdisc) whose peek() callback is
> qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such
> qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from
> its child (red in this case), it will do the following:
>  1a. do a peek() - and when sensing there's an skb the child can offer, then
>      - the child in this case(red) calls its child's (qfq) peek.
>         qfq does the right thing and will return the gso_skb queue packet.
>         Note: if there wasnt a gso_skb entry then qfq will store it there.
>  1b. invoke a dequeue() on the child (red). And herein lies the problem.
>      - red will call the child's dequeue() which will essentially just
>        try to grab something of qfq's queue.
>
>
> The right thing to do in #1b is to grab the skb off gso_skb queue.
> This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked()
> method instead.
>
>
> Fixes: 77be155cba4e ("pkt_sched: Add peek emulation for non-work-conserving qdiscs.")
> Reported-by: Manas <ghandatmanas@gmail.com>
> Reported-by: Rakshit Awasthi <rakshitawasthi17@gmail.com>
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

Reviewed-by: Eric Dumazet <edumazet@google.com>

^ permalink raw reply

* [PATCH net v3] net: rtnetlink: zero ifla_vf_broadcast to avoid stack infoleak in rtnl_fill_vfinfo
From: Kai Zen @ 2026-04-30 15:41 UTC (permalink / raw)
  To: netdev; +Cc: stable, edumazet, davem, kuba, pabeni, horms, gregkh
In-Reply-To: <CALynFi54eQj7SOmF6QNG0eqhLw7AuURzo6tSYQavvM3ZP74ikw@mail.gmail.com>

rtnl_fill_vfinfo() declares struct ifla_vf_broadcast on the stack
without initialisation:

	struct ifla_vf_broadcast vf_broadcast;

The struct contains a single fixed 32-byte field:

	/* include/uapi/linux/if_link.h */
	struct ifla_vf_broadcast {
		__u8 broadcast[32];
	};

The function then copies dev->broadcast into it using dev->addr_len
as the length:

	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);

On Ethernet devices (the overwhelming majority of SR-IOV NICs)
dev->addr_len is 6, so only the first 6 bytes of broadcast[] are
written. The remaining 26 bytes retain whatever was previously on
the kernel stack. The full struct is then handed to userspace via:

	nla_put(skb, IFLA_VF_BROADCAST,
		sizeof(vf_broadcast), &vf_broadcast)

leaking up to 26 bytes of uninitialised kernel stack per VF per
RTM_GETLINK request, repeatable.

The other vf_* structs in the same function are explicitly zeroed
for exactly this reason - see the memset() calls for ivi,
vf_vlan_info, node_guid and port_guid a few lines above.
vf_broadcast was simply missed when it was added.

Reachability: any unprivileged local process can open AF_NETLINK /
NETLINK_ROUTE without capabilities and send RTM_GETLINK with an
IFLA_EXT_MASK attribute carrying RTEXT_FILTER_VF. The kernel walks
each VF and emits IFLA_VF_BROADCAST, leaking 26 bytes of stack per
VF per request. Stack residue at this call site can include return
addresses and transient sensitive data; KASAN with stack
instrumentation, or KMSAN, will flag the nla_put() when reproduced.

Zero the on-stack struct before the partial memcpy, matching the
existing pattern used for the other vf_* structs in the same
function.

Fixes: 75345f888f70 ("ipoib: show VF broadcast address")
Cc: stable@vger.kernel.org
Signed-off-by: Kai Zen <kai.aizen.dev@gmail.com>
---
 net/core/rtnetlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b613bb6e0..df042da42 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1572,6 +1572,7 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
 		port_guid.vf = ivi.vf;
 
 	memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+	memset(&vf_broadcast, 0, sizeof(vf_broadcast));
 	memcpy(vf_broadcast.broadcast, dev->broadcast, dev->addr_len);
 	vf_vlan.vlan = ivi.vlan;
 	vf_vlan.qos = ivi.qos;
-- 
2.43.0


^ permalink raw reply related

* [PATCH net-next v3 0/3] Add ZTE DingHai Ethernet PF driver
From: Junyang Han @ 2026-04-30 15:11 UTC (permalink / raw)
  To: andrew+netdev
  Cc: netdev, vadim.fedorenko, davem, edumazet, kuba, pabeni,
	han.junyang, ran.ming, han.chengfei, zhang.yanze


[-- Attachment #1.1.1: Type: text/plain, Size: 2851 bytes --]

This series adds initial support for the ZTE DingHai Ethernet controller,
a high-performance PCIe Ethernet device supporting SR-IOV, hardware
offloading, and advanced virtualization features.

Changes from v2:
- Address maintainer feedback from v2 review:
  * Remove meaningless initialization
  * Change dh_pf_pci_table to static const for better encapsulation
  * Simplify MODULE_DESCRIPTION for brevity
- Coding style improvements:
  * Ensure all lines are within 80-column limit
  * Use kernel types (u32/u8) consistently throughout
  * Improve code readability with better formatting


Changes from v1 (addressing feedback from AndrewLunn):
- Update copyright years to 2022-2026
- Remove DRV_VERSION, MODULE_VERSION and related boilerplate
- Fix MODULE_AUTHOR to use person with email address
- Use module_pci_driver() instead of manual init/exit
- Remove empty suspend/resume callbacks
- Replace char priv[] flexible array with void *priv + kzalloc
- Switch logging from printk wrappers to dev_*() based macros
- Remove dh_helper.h and dh_log.c, simplify to dh_log.h only
- Fix variable declaration ordering (reverse Christmas tree)
- Remove unnecessary NULL check in remove and pf_dev=NULL in probe
- Fix indentation and remove unnecessary type casts
- Use kernel idiomatic "if (ret)" style

This is the initial submission and only includes the PF (Physical Function)
driver. The VF (Virtual Function) driver will be submitted separately.

Junyang Han (3):
  net/ethernet: add ZTE network driver support
  net/ethernet/zte/dinghai: add logging infrastructure
  net/ethernet/zte/dinghai: add hardware register access and PCI
    capability scanning

 MAINTAINERS                                 |   6 +
 drivers/net/ethernet/Kconfig                |   1 +
 drivers/net/ethernet/Makefile               |   1 +
 drivers/net/ethernet/zte/Kconfig            |  20 +
 drivers/net/ethernet/zte/Makefile           |   6 +
 drivers/net/ethernet/zte/dinghai/Kconfig    |  34 ++
 drivers/net/ethernet/zte/dinghai/Makefile   |  10 +
 drivers/net/ethernet/zte/dinghai/dh_log.h   |  64 ++
 drivers/net/ethernet/zte/dinghai/dh_queue.h |  71 +++
 drivers/net/ethernet/zte/dinghai/en_pf.c    | 637 ++++++++++++++++++++
 drivers/net/ethernet/zte/dinghai/en_pf.h    | 102 ++++
 11 files changed, 952 insertions(+)
 create mode 100644 drivers/net/ethernet/zte/Kconfig
 create mode 100644 drivers/net/ethernet/zte/Makefile
 create mode 100644 drivers/net/ethernet/zte/dinghai/Kconfig
 create mode 100644 drivers/net/ethernet/zte/dinghai/Makefile
 create mode 100644 drivers/net/ethernet/zte/dinghai/dh_log.h
 create mode 100644 drivers/net/ethernet/zte/dinghai/dh_queue.h
 create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.c
 create mode 100644 drivers/net/ethernet/zte/dinghai/en_pf.h

-- 
2.27.0

[-- Attachment #1.1.2: Type: text/html , Size: 5150 bytes --]

^ permalink raw reply


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