Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH bpf] bpf, sockmap: zero-initialize pages allocated in bpf_msg_push_data
From: Jiayuan Chen @ 2026-04-25  3:17 UTC (permalink / raw)
  To: Weiming Shi, Martin KaFai Lau, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni
  Cc: John Fastabend, Stanislav Fomichev, Song Liu, Yonghong Song,
	Jiri Olsa, Simon Horman, bpf, netdev, Xiang Mei, Xinyu Ma
In-Reply-To: <20260424190310.1520555-2-bestswngs@gmail.com>


On 4/25/26 3:03 AM, Weiming Shi wrote:
> bpf_msg_push_data() allocates pages via alloc_pages() without
> __GFP_ZERO. In the non-copy path, the entire page of uninitialized
> heap content is added directly to the sk_msg scatterlist, which is
> then transmitted over TCP to userspace via tcp_bpf_push(). In the
> copy path, a gap of len bytes between the front and back memcpy
> regions is similarly left uninitialized.
>
> This leads to a kernel heap information leak: stale page content
> including kernel pointers from the direct-map and vmemmap regions
> is transmitted to userspace, which can be used to defeat KASLR.
>
> Add __GFP_ZERO to the alloc_pages() call to ensure the allocated
> page is always zeroed before it enters the scatterlist.



As the helper's own documentation says:

     If a program of type BPF_PROG_TYPE_SK_MSG is run on a msg it may
     want to insert metadata or options into the msg. This can later be
     read and used by any of the lower layer BPF hooks.

The inserted region is meant to be written by the BPF program — that's 
the entire point of calling push.

If the program doesn't fill it,  the push has no purpose to begin with.


Isn't the uninitialized content a bug in the BPF program rather than 
something the kernel helper should paper over?


> Link: https://lore.kernel.org/all/20260424155913.A19FDC19425@smtp.kernel.org
> Fixes: 6fff607e2f14 ("bpf: sk_msg program helper bpf_msg_push_data")
> Tested-by: Xiang Mei <xmei5@asu.edu>
> Tested-by: Xinyu Ma <mmmxny@gmail.com>
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> ---
>   net/core/filter.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index bc96c18df4e0..ea02239892fd 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -2820,7 +2820,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
>   	if (!space || (space == 1 && start != offset))
>   		copy = msg->sg.data[i].length;
>   
> -	page = alloc_pages(__GFP_NOWARN | GFP_ATOMIC | __GFP_COMP,
> +	page = alloc_pages(__GFP_NOWARN | GFP_ATOMIC | __GFP_COMP | __GFP_ZERO,
>   			   get_order(copy + len));
>   	if (unlikely(!page))
>   		return -ENOMEM;

^ permalink raw reply

* [PATCH] net: ethernet: rnpgbe: mark nonfunctional incomplete driver as BROKEN
From: Ethan Nelson-Moore @ 2026-04-25  4:18 UTC (permalink / raw)
  To: netdev
  Cc: Ethan Nelson-Moore, stable, Yibo Dong, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vadim Fedorenko, MD Danish Anwar

The rnpgbe driver as currently shipped in the kernel is incomplete and
has no useful functionality. It will bind to a PCI device and create a
network device, but that device does not function (its .ndo_start_xmit
callback, rnpgbe_xmit_frame, just drops all packets). This situation
means that users could enable this driver and have it load and attach
to their device but not transfer any data. To remove the potential for
user confusion, mark the driver as broken until it is completed and
explain why this was done.

Fixes: ee61c10cd482 ("net: rnpgbe: Add build support for rnpgbe")
Cc: stable@vger.kernel.org # 7.0+
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
 drivers/net/ethernet/mucse/Kconfig | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mucse/Kconfig b/drivers/net/ethernet/mucse/Kconfig
index 0b3e853d625f..c37a90a6c808 100644
--- a/drivers/net/ethernet/mucse/Kconfig
+++ b/drivers/net/ethernet/mucse/Kconfig
@@ -3,9 +3,12 @@
 # Mucse network device configuration
 #
 
+# This section depends on BROKEN because its only child item also does;
+# see the explanation below.
 config NET_VENDOR_MUCSE
 	bool "Mucse devices"
 	default y
+	depends on BROKEN
 	help
 	  If you have a network (Ethernet) card from Mucse(R), say Y.
 
@@ -16,12 +19,14 @@ config NET_VENDOR_MUCSE
 
 if NET_VENDOR_MUCSE
 
+# This driver is marked as broken because it is incomplete; this avoids users
+# enabling it and expecting it to work.
 config MGBE
 	tristate "Mucse(R) 1GbE PCI Express adapters support"
-	depends on PCI
+	depends on PCI && BROKEN
 	help
 	  This driver supports Mucse(R) 1GbE PCI Express family of
-	  adapters.
+	  adapters. It is incomplete and currently has no useful functionality.
 
 	  More specific information on configuring the driver is in
 	  <file:Documentation/networking/device_drivers/ethernet/mucse/rnpgbe.rst>.
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net] net: mana: Optimize irq affinity for low vcpu configs
From: Shradha Gupta @ 2026-04-25  6:15 UTC (permalink / raw)
  To: Dipayaan Roy
  Cc: Dexuan Cui, Wei Liu, Haiyang Zhang, K. Y. Srinivasan, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Konstantin Taranov, Simon Horman, Erni Sri Satya Vennela,
	Shiraz Saleem, Michael Kelley, Long Li, Yury Norov, linux-hyperv,
	linux-kernel, netdev, Paul Rosswurm, Shradha Gupta,
	Saurabh Singh Sengar, stable
In-Reply-To: <aetgQ1gCYlGJjiKk@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>

On Fri, Apr 24, 2026 at 05:21:23AM -0700, Dipayaan Roy wrote:
> On Thu, Apr 23, 2026 at 11:17:00PM -0700, Shradha Gupta wrote:
> > In mana driver, the number of IRQs allocated are capped by the
> > min(num_cpu + 1, queue count). In cases, where the IRQ count is greater
> > than the vcpu count, we want to utilize all the vcpus, irrespective of
> > their NUMA/core bindings.
> > 
> > This is important, especially in the envs where number of vcpus are so
> > few that the softIRQ handling overhead on two IRQs on the same vcpu is
> > much more than their overheads if they were spread across sibling vcpus
> > 
> > This behaviour is more evident with dynamic IRQ allocation. Since MANA
> > IRQs are assigned at a later stage compared to static allocation, other
> > device IRQs may already be affinitized to the vCPUs. As a result, IRQ
> > weights become imbalanced, causing multiple MANA IRQs to land on the
> > same vCPU.
> > 
> > In such cases when many parallel TCP connections are tested, the
> > throughput drops significantly
> > 
> > Test envs:
> > =======================================================
> > Case 1: without this patch
> > =======================================================
> > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > 
> > 	TYPE		effective vCPU aff
> > =======================================================
> > IRQ0:	HWC		0
> > IRQ1:	mana_q1		0
> > IRQ2:	mana_q2		2
> > IRQ3:	mana_q3		0
> > IRQ4:	mana_q4		3
> > 
> > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > vCPU		0	1	2	3
> > =======================================================
> > pass 1:		38.85	0.03	24.89	24.65
> > pass 2:		39.15	0.03	24.57	25.28
> > pass 3:		40.36	0.03	23.20	23.17
> > 
> > =======================================================
> > Case 2: with this patch
> > =======================================================
> > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > 
> >         TYPE            effective vCPU aff
> > =======================================================
> > IRQ0:   HWC             0
> > IRQ1:   mana_q1         0
> > IRQ2:   mana_q2         1
> > IRQ3:   mana_q3         2
> > IRQ4:   mana_q4         3
> > 
> > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > vCPU            0       1       2       3
> > =======================================================
> > pass 1:         15.42	15.85	14.99	14.51
> > pass 2:         15.53	15.94	15.81	15.93
> > pass 3:         16.41	16.35	16.40	16.36
> > 
> > =======================================================
> > Throughput Impact(in Gbps, same env)
> > =======================================================
> > TCP conn	with patch	w/o patch
> > 20480		15.65		7.73
> > 10240		15.63		8.93
> > 8192		15.64		9.69
> > 6144		15.64		13.16
> > 4096		15.69		15.75
> > 2048		15.69		15.83
> > 1024		15.71		15.28
> > 
> > Fixes: 755391121038 ("net: mana: Allocate MSI-X vectors dynamically")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
> > Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
> > Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> > ---
> >  .../net/ethernet/microsoft/mana/gdma_main.c   | 35 +++++++++++++++++--
> >  1 file changed, 33 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > index 098fbda0d128..433c044d53c6 100644
> > --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > @@ -1672,6 +1672,23 @@ static int irq_setup(unsigned int *irqs, unsigned int len, int node,
> >  	return 0;
> >  }
> >  
> > +static int irq_setup_linear(unsigned int *irqs, unsigned int len)
> > +{
> > +	int cpu;
> > +
> > +	rcu_read_lock();
> We do not need to call rcu_read_lock here, as the caller of this
> function has already acquired cpus_read_lock.

Thanks for your comments Dipayaan, I think this is still needed for the
irq_set_affinity_and_hint(), to protect the pointer returned by
irq_to_desc(). You can also see the same in the original function
irq_setup() for the same reason.

> > +	for_each_online_cpu(cpu) {
> > +		if (len <= 0)
> len is unsigned here so <= doesnot makes sense. PLease change it to int
> or better use if(!len)

sure, I think I will change it to explicitly exit when len == 0
Thanks.

> > +			break;
> > +
> > +		irq_set_affinity_and_hint(*irqs++, cpumask_of(cpu));
> > +		len--;
> > +	}
> > +	rcu_read_unlock();
> > +
> > +	return 0;
> > +}
> > +
> >  static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> >  {
> >  	struct gdma_context *gc = pci_get_drvdata(pdev);
> > @@ -1722,10 +1739,24 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> >  	 * first CPU sibling group since they are already affinitized to HWC IRQ
> >  	 */
> >  	cpus_read_lock();
> > -	if (gc->num_msix_usable <= num_online_cpus())
> > +	if (gc->num_msix_usable <= num_online_cpus()) {
> >  		skip_first_cpu = true;
> > +		err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> > +	} else {
> > +		/*
> > +		 * In case our IRQs are more than num_online_cpus, we try to
> > +		 * make sure we are using all vcpus. In such a case NUMA or
> > +		 * CPU core affinity does not matter.
> > +		 * Note that in this case the total mana IRQ should always be
> > +		 * num_online_cpu + 1. The first HWC IRQ is already handled
> > +		 * in HWC setup calls
> > +		 * So, the nvec value in this path should always be equal to
> > +		 * num_online_cpu
> nit: typo: should be num_online_cpus

noted

> > +		 */
> > +		WARN_ON(nvec > num_online_cpus());
> > +		err = irq_setup_linear(irqs, nvec);
> > +	}
> >  
> > -	err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> >  	if (err) {
> >  		cpus_read_unlock();
> >  		goto free_irq;
> > 
> > base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
> > -- 
> > 2.34.1
> > 
> Regards
> Dipayaan Roy

^ permalink raw reply

* Re: [PATCH RFC net-next 0/4] net: pse-pd: decouple controller lookup from MDIO probe
From: Corey Leavitt @ 2026-04-25  6:33 UTC (permalink / raw)
  To: Kory Maincent
  Cc: Carlo Szelinsky, Oleksij Rempel, Andrew Lunn, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Heiner Kallweit, Russell King, netdev, linux-kernel

Hi Kory,

Thanks for the Ack on 1/4 and the kind words on the design. Agreed,
we'll solve this without MDI-binding for now.

On the Fixes: tag for 4/4, I'll drop it for v2. Patches 2 and 3 are
infrastructure (notifier chain, lifecycle events) rather than direct
fixes against a single prior commit, so dropping reads cleaner than
propagating fa2f0454174c onto scaffolding. The cover letter will note
the regression context.

Thanks for pulling Jakub and Russell in on the rtnl_lock question;
I'll hold v2 until they've had a chance to weigh in, and until Carlo
has had a chance to test.

Regards,
Corey


^ permalink raw reply

* Re: [PATCH net] net: mana: Optimize irq affinity for low vcpu configs
From: Shradha Gupta @ 2026-04-25  6:42 UTC (permalink / raw)
  To: Yury Norov
  Cc: Dexuan Cui, Wei Liu, Haiyang Zhang, K. Y. Srinivasan, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Konstantin Taranov, Simon Horman, Erni Sri Satya Vennela,
	Dipayaan Roy, Shiraz Saleem, Michael Kelley, Long Li, Yury Norov,
	linux-hyperv, linux-kernel, netdev, Paul Rosswurm, Shradha Gupta,
	Saurabh Singh Sengar, stable
In-Reply-To: <aevf2bPLBiAzX7UC@yury>

On Fri, Apr 24, 2026 at 05:25:45PM -0400, Yury Norov wrote:
> On Thu, Apr 23, 2026 at 11:17:00PM -0700, Shradha Gupta wrote:
> > In mana driver, the number of IRQs allocated are capped by the
> > min(num_cpu + 1, queue count). In cases, where the IRQ count is greater
> > than the vcpu count, we want to utilize all the vcpus, irrespective of
> > their NUMA/core bindings.
> > 
> > This is important, especially in the envs where number of vcpus are so
> > few that the softIRQ handling overhead on two IRQs on the same vcpu is
> > much more than their overheads if they were spread across sibling vcpus
> > 
> > This behaviour is more evident with dynamic IRQ allocation. Since MANA
> > IRQs are assigned at a later stage compared to static allocation, other
> > device IRQs may already be affinitized to the vCPUs. As a result, IRQ
> > weights become imbalanced, causing multiple MANA IRQs to land on the
> > same vCPU.
> > 
> > In such cases when many parallel TCP connections are tested, the
> > throughput drops significantly
> > 
> > Test envs:
> > =======================================================
> > Case 1: without this patch
> > =======================================================
> > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > 
> > 	TYPE		effective vCPU aff
> > =======================================================
> > IRQ0:	HWC		0
> > IRQ1:	mana_q1		0
> > IRQ2:	mana_q2		2
> > IRQ3:	mana_q3		0
> > IRQ4:	mana_q4		3
> > 
> > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > vCPU		0	1	2	3
> > =======================================================
> > pass 1:		38.85	0.03	24.89	24.65
> > pass 2:		39.15	0.03	24.57	25.28
> > pass 3:		40.36	0.03	23.20	23.17
> > 
> > =======================================================
> > Case 2: with this patch
> > =======================================================
> > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > 
> >         TYPE            effective vCPU aff
> > =======================================================
> > IRQ0:   HWC             0
> > IRQ1:   mana_q1         0
> > IRQ2:   mana_q2         1
> > IRQ3:   mana_q3         2
> > IRQ4:   mana_q4         3
> > 
> > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > vCPU            0       1       2       3
> > =======================================================
> > pass 1:         15.42	15.85	14.99	14.51
> > pass 2:         15.53	15.94	15.81	15.93
> > pass 3:         16.41	16.35	16.40	16.36
> > 
> > =======================================================
> > Throughput Impact(in Gbps, same env)
> > =======================================================
> > TCP conn	with patch	w/o patch
> > 20480		15.65		7.73
> > 10240		15.63		8.93
> > 8192		15.64		9.69
> > 6144		15.64		13.16
> > 4096		15.69		15.75
> > 2048		15.69		15.83
> > 1024		15.71		15.28
> > 
> > Fixes: 755391121038 ("net: mana: Allocate MSI-X vectors dynamically")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
> > Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
> > Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> > ---
> >  .../net/ethernet/microsoft/mana/gdma_main.c   | 35 +++++++++++++++++--
> >  1 file changed, 33 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > index 098fbda0d128..433c044d53c6 100644
> > --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > @@ -1672,6 +1672,23 @@ static int irq_setup(unsigned int *irqs, unsigned int len, int node,
> >  	return 0;
> >  }
> >  
> > +static int irq_setup_linear(unsigned int *irqs, unsigned int len)
> > +{
> > +	int cpu;
> > +
> > +	rcu_read_lock();
> > +	for_each_online_cpu(cpu) {
> > +		if (len <= 0)
> > +			break;
> > +
> > +		irq_set_affinity_and_hint(*irqs++, cpumask_of(cpu));
> > +		len--;
> > +	}
> > +	rcu_read_unlock();
> > +
> > +	return 0;
> > +}
> > +
> >  static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> >  {
> >  	struct gdma_context *gc = pci_get_drvdata(pdev);
> > @@ -1722,10 +1739,24 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> >  	 * first CPU sibling group since they are already affinitized to HWC IRQ
> >  	 */
> >  	cpus_read_lock();
> > -	if (gc->num_msix_usable <= num_online_cpus())
> > +	if (gc->num_msix_usable <= num_online_cpus()) {
> >  		skip_first_cpu = true;
> > +		err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> 
> Then you don't need the 'skip_first_cpu' variable.

That's right, let me change that.

> 
> > +	} else {
> > +		/*
> > +		 * In case our IRQs are more than num_online_cpus, we try to
> > +		 * make sure we are using all vcpus. In such a case NUMA or
> > +		 * CPU core affinity does not matter.
> > +		 * Note that in this case the total mana IRQ should always be
> > +		 * num_online_cpu + 1. The first HWC IRQ is already handled
> > +		 * in HWC setup calls
> > +		 * So, the nvec value in this path should always be equal to
> > +		 * num_online_cpu
> > +		 */
> > +		WARN_ON(nvec > num_online_cpus());
> 
> That sounds weird. If you don't support IRQs more than CPUs , and want to
> warn about it, you'd do that earlier in the function, and align the other
> logic accordingly. For example:
> 
>         if (WARN_ON(nvec > num_online_cpus()))
>                 nvec = num_online_cpus();
> 
>         irqs = kmalloc_objs(int, nvec);
>         if (!irqs)
>                 return -ENOMEM;
> 
>         ...
> 
> So you'll decrease pressure on allocator.
> 
> What would happen with those IRQs beyond num_online_cpus()? Can you explain
> it in the comment? I'm not an expert in your driver, but usually if you pass
> a vector to function, and the function is able to handle only a part of it,
> it returns the number of processed elements.
> 
> Thanks,
> Yury
> 

so, by design the nvec should never exceed num_online_cpus(). I only
added the WARN_ON as a defensive safegaurd. But I agree with your
suggestion to move this earlier before the allocations.

Thanks Yury!

> > +		err = irq_setup_linear(irqs, nvec);
> > +	}
> >  
> > -	err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> >  	if (err) {
> >  		cpus_read_unlock();
> >  		goto free_irq;
> > 
> > base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
> > -- 
> > 2.34.1

^ permalink raw reply

* [PATCH net v2] ipv6: Implement limits on extension header parsing
From: Daniel Borkmann @ 2026-04-25  7:55 UTC (permalink / raw)
  To: kuba
  Cc: edumazet, dsahern, tom, willemdebruijn.kernel, idosch,
	justin.iurman, pabeni, netdev

ipv6_{skip_exthdr,find_hdr}() and ip6_{tnl_parse_tlv_enc_lim,
protocol_deliver_rcu}() iterate over IPv6 extension headers until they
find a non-extension-header protocol or run out of packet data. The
loops have no iteration counter, relying solely on the packet length
to bound them. For a crafted packet with 8-byte extension headers
filling a 64KB jumbogram, this means a worst case of up to ~8k
iterations with a skb_header_pointer call each. ipv6_skip_exthdr(),
for example, is used where it parses the inner quoted packet inside
an incoming ICMPv6 error:

  - icmpv6_rcv
    - checksum validation
    - case ICMPV6_DEST_UNREACH
      - icmpv6_notify
        - pskb_may_pull()       <- pull inner IPv6 header
        - ipv6_skip_exthdr()    <- iterates here
        - pskb_may_pull()
        - ipprot->err_handler() <- sk lookup

The per-iteration cost of ipv6_skip_exthdr itself is generally
light, but skb_header_pointer becomes more costly on reassembled
packets: the first ~1232 bytes of the inner packet are in the skb's
linear area, but the remaining ~63KB are in the frag_list where
skb_copy_bits is needed to read data.

Add a configurable limit via a new sysctl net.ipv6.max_ext_hdrs_number
(default 8, minimum 1). All four extension header walking functions
are bound by this limit. The sysctl is in line with commit 47d3d7ac656a
("ipv6: Implement limits on Hop-by-Hop and Destination options").
As documented, init_net is used to derive max_ext_hdrs_number to
be consistent given a net cannot always reliably be retrieved.

Note that the check in ip6_protocol_deliver_rcu() happens right
before the goto resubmit, such that we don't have to have a test
for ipv6_ext_hdr() in the fast-path.

There's an ongoing IETF draft-iurman-6man-eh-occurrences to enforce
IPv6 extension headers ordering and occurrence. The latter also
discusses security implications. As per RFC8200 section 4.1, the
occurrence rules for extension headers provide a practical upper
bound, thus 8 was used as the default.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 v1->v2:
   - Set the default to 8 (Justin)
   - Update IETF references (Justin)
   - Add core path coverage as well (Justin)

 Documentation/networking/ip-sysctl.rst |  7 +++++++
 include/net/dropreason-core.h          |  6 ++++++
 include/net/ipv6.h                     |  2 ++
 include/net/netns/ipv6.h               |  1 +
 net/ipv6/af_inet6.c                    |  1 +
 net/ipv6/exthdrs_core.c                | 11 +++++++++++
 net/ipv6/ip6_input.c                   |  6 ++++++
 net/ipv6/ip6_tunnel.c                  |  5 +++++
 net/ipv6/sysctl_net_ipv6.c             |  8 ++++++++
 9 files changed, 47 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 2e3a746fcc6d..f7412f4049d1 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -2537,6 +2537,13 @@ max_hbh_length - INTEGER
 
 	Default: INT_MAX (unlimited)
 
+max_ext_hdrs_number - INTEGER
+	Maximum number of IPv6 extension headers allowed in a packet.
+	Limits how many extension headers will be traversed. The value
+	is read from the initial netns.
+
+	Default: 8
+
 skip_notify_on_dev_down - BOOLEAN
 	Controls whether an RTM_DELROUTE message is generated for routes
 	removed when a device is taken down or deleted. IPv4 does not
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index e0ca3904ff8e..1fd91e59b84e 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -99,6 +99,7 @@
 	FN(FRAG_TOO_FAR)		\
 	FN(TCP_MINTTL)			\
 	FN(IPV6_BAD_EXTHDR)		\
+	FN(IPV6_TOO_MANY_EXTHDRS)	\
 	FN(IPV6_NDISC_FRAG)		\
 	FN(IPV6_NDISC_HOP_LIMIT)	\
 	FN(IPV6_NDISC_BAD_CODE)		\
@@ -494,6 +495,11 @@ enum skb_drop_reason {
 	SKB_DROP_REASON_TCP_MINTTL,
 	/** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */
 	SKB_DROP_REASON_IPV6_BAD_EXTHDR,
+	/**
+	 * @SKB_DROP_REASON_IPV6_TOO_MANY_EXTHDRS: Number of IPv6 extension
+	 * headers in the packet exceeds net.ipv6.max_ext_hdrs_number.
+	 */
+	SKB_DROP_REASON_IPV6_TOO_MANY_EXTHDRS,
 	/** @SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc). */
 	SKB_DROP_REASON_IPV6_NDISC_FRAG,
 	/** @SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit. */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index d042afe7a245..c540b750726e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -90,6 +90,8 @@ struct ip_tunnel_info;
 #define IP6_DEFAULT_MAX_DST_OPTS_LEN	 INT_MAX /* No limit */
 #define IP6_DEFAULT_MAX_HBH_OPTS_LEN	 INT_MAX /* No limit */
 
+#define IP6_DEFAULT_MAX_EXT_HDRS_CNT	 8
+
 /*
  *	Addr type
  *	
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 499e4288170f..2cea457bddb4 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -54,6 +54,7 @@ struct netns_sysctl_ipv6 {
 	int max_hbh_opts_cnt;
 	int max_dst_opts_len;
 	int max_hbh_opts_len;
+	int max_ext_hdrs_cnt;
 	int seg6_flowlabel;
 	u32 ioam6_id;
 	u64 ioam6_id_wide;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 0a88b376141d..19424c3f2dfc 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -945,6 +945,7 @@ static int __net_init inet6_net_init(struct net *net)
 	net->ipv6.sysctl.flowlabel_state_ranges = 0;
 	net->ipv6.sysctl.max_dst_opts_cnt = IP6_DEFAULT_MAX_DST_OPTS_CNT;
 	net->ipv6.sysctl.max_hbh_opts_cnt = IP6_DEFAULT_MAX_HBH_OPTS_CNT;
+	net->ipv6.sysctl.max_ext_hdrs_cnt = IP6_DEFAULT_MAX_EXT_HDRS_CNT;
 	net->ipv6.sysctl.max_dst_opts_len = IP6_DEFAULT_MAX_DST_OPTS_LEN;
 	net->ipv6.sysctl.max_hbh_opts_len = IP6_DEFAULT_MAX_HBH_OPTS_LEN;
 	net->ipv6.sysctl.fib_notify_on_flag_change = 0;
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 49e31e4ae7b7..9df892e7f7fb 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -4,6 +4,8 @@
  * not configured or static.
  */
 #include <linux/export.h>
+
+#include <net/net_namespace.h>
 #include <net/ipv6.h>
 
 /*
@@ -72,7 +74,9 @@ EXPORT_SYMBOL(ipv6_ext_hdr);
 int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
 		     __be16 *frag_offp)
 {
+	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
 	u8 nexthdr = *nexthdrp;
+	int exthdr_cnt = 0;
 
 	*frag_offp = 0;
 
@@ -82,6 +86,8 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
 
 		if (nexthdr == NEXTHDR_NONE)
 			return -1;
+		if (unlikely(exthdr_cnt++ >= exthdr_max))
+			return -1;
 		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
 		if (!hp)
 			return -1;
@@ -188,8 +194,10 @@ EXPORT_SYMBOL_GPL(ipv6_find_tlv);
 int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 		  int target, unsigned short *fragoff, int *flags)
 {
+	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
 	unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
 	u8 nexthdr = ipv6_hdr(skb)->nexthdr;
+	int exthdr_cnt = 0;
 	bool found;
 
 	if (fragoff)
@@ -216,6 +224,9 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
 			return -ENOENT;
 		}
 
+		if (unlikely(exthdr_cnt++ >= exthdr_max))
+			return -EBADMSG;
+
 		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
 		if (!hp)
 			return -EBADMSG;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 967b07aeb683..a5bbbc16e8d7 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -403,8 +403,10 @@ INDIRECT_CALLABLE_DECLARE(int tcp_v6_rcv(struct sk_buff *));
 void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
 			      bool have_final)
 {
+	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
 	const struct inet6_protocol *ipprot;
 	struct inet6_dev *idev;
+	int exthdr_cnt = 0;
 	unsigned int nhoff;
 	SKB_DR(reason);
 	bool raw;
@@ -487,6 +489,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
 				nexthdr = ret;
 				goto resubmit_final;
 			} else {
+				if (unlikely(exthdr_cnt++ >= exthdr_max)) {
+					SKB_DR_SET(reason, IPV6_TOO_MANY_EXTHDRS);
+					goto discard;
+				}
 				goto resubmit;
 			}
 		} else if (ret == 0) {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index c468c83af0f2..4546a60942ab 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -395,15 +395,20 @@ ip6_tnl_dev_uninit(struct net_device *dev)
 
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
 {
+	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
 	const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
 	unsigned int nhoff = raw - skb->data;
 	unsigned int off = nhoff + sizeof(*ipv6h);
 	u8 nexthdr = ipv6h->nexthdr;
+	int exthdr_cnt = 0;
 
 	while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
 		struct ipv6_opt_hdr *hdr;
 		u16 optlen;
 
+		if (unlikely(exthdr_cnt++ >= exthdr_max))
+			break;
+
 		if (!pskb_may_pull(skb, off + sizeof(*hdr)))
 			break;
 
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index d2cd33e2698d..93f865545a7c 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -135,6 +135,14 @@ static struct ctl_table ipv6_table_template[] = {
 		.extra1		= SYSCTL_ZERO,
 		.extra2		= &flowlabel_reflect_max,
 	},
+	{
+		.procname	= "max_ext_hdrs_number",
+		.data		= &init_net.ipv6.sysctl.max_ext_hdrs_cnt,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= SYSCTL_ONE,
+	},
 	{
 		.procname	= "max_dst_opts_number",
 		.data		= &init_net.ipv6.sysctl.max_dst_opts_cnt,
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net-next v6 0/2] net: mana: add ethtool private flag for full-page RX buffers
From: Dipayaan Roy @ 2026-04-25  8:05 UTC (permalink / raw)
  To: David Wei, kuba
  Cc: Jakub Kicinski, kys, haiyangz, wei.liu, decui, andrew+netdev,
	davem, edumazet, pabeni, leon, longli, kotaranov, horms,
	shradhagupta, ssengar, ernis, shirazsaleem, linux-hyperv, netdev,
	linux-kernel, linux-rdma, stephen, jacob.e.keller, leitao, kees,
	john.fastabend, hawk, bpf, daniel, ast, sdf, dipayanroy
In-Reply-To: <685d7bf9-062d-4bd2-8448-f7714bb05302@davidwei.uk>

On Fri, Apr 24, 2026 at 01:05:24PM -0700, David Wei wrote:
> On 2026-04-23 05:48, Dipayaan Roy wrote:
> > On Thu, Apr 16, 2026 at 08:31:46AM -0700, Jakub Kicinski wrote:
> > > On Tue, 14 Apr 2026 09:00:56 -0700 Dipayaan Roy wrote:
> > > > I still see roughly a 5% overhead from the atomic refcount operation
> > > > itself, but on that platform there is no throughput drop when using
> > > > page fragments versus full-page mode.
> > > 
> > > That seems to contradict your claim that it's a problem with a specific
> > > platform.. Since we're in the merge window I asked David Wei to try to
> > > experiment with disabling page fragmentation on the ARM64 platforms we
> > > have at Meta. If it repros we should use the generic rx-buf-len
> > > ringparam because more NICs may want to implement this strategy.
> > 
> > Hi Jakub,
> > 
> > Thanks. I think I was not precise enough in my previous reply.
> > 
> > What I meant is that the atomic refcount cost itself does not appear to
> > be unique to the affected platform. I see a similar ~5% overhead on
> > another ARM64 platformi (different vendor) as well. However, on that platform
> > there is no throughput delta between fragment mode and full-page mode; both reach
> > line rate.
> > 
> > On the affected platform, fragment mode shows an additional ~15%
> > throughput drop versus full-page mode. So the current data suggests that
> > the atomic overhead is common, but the throughput regression is not
> > explained by that overhead alone and likely depends on an additional
> > platform-specific factor.
> > 
> > Separately, the hardware team collected PCIe traces on the affected
> > platform and reported stalls in the fragment-mode case that are not seen
> > in full-page mode. They are still investigating the root cause, but
> > their current hypothesis is that this is related to that platform’s
> > PCIe/root-port microarchitecture rather than to page_pool refcounting
> > alone.
> > 
> > That said, I agree the right direction depends on whether this
> > reproduces on other ARM64 platforms. If David is able to reproduce the
> > same behavior, then using the generic rx-buf-len ringparam sounds like
> > the better direction.
> > 
> > Please let me know what David finds, and I can rework the patch
> > accordingly.
> 
> I ran a test on Grace, 4 KB pages, 72 cores, 1 NUMA node.
> 
> Broadcom NIC, bnxt driver, 50 Gbps bandwidth. Hacked it up to either
> give me 1 or 2 frags per page. No agg ring, no HDS, no HW GRO.
> 
> Use 1 combined queue only for the server. Affinitized its net rx softirq
> to run on core 4.
> 
> Ran iperf3 server, taskset onto cpu cores 32-47. The iperf3 client is
> running on a host w/ same hw in the same region. Using 32 queues, no
> softirq affinities. The idea is to hammer page->pp_ref_count from
> different cores.
> 
> * 1 frag/page  -> 32.3 Gbps
> * 2 frags/page -> 36.0 Gbps
> 
> Comparing perf, for 2 frags/page the cost of skb_release_data() hitting
> pp_ref_count goes up, as expected. Is this what you see? When you say
> there's a +5% overhead, what function?
> 
> Overall tput is higher with multiple frags. That's to be expected w/
> page pool.

Hi David,

Thanks for running this. Your results are consistent with mine.

I have tested this on 2 ARM64 platforms from different vendors,
running ntttcp and iperf3 using 4k as base page size.
In my observation I see both platforms show a 5% overhead in
napi_pp_put_page (~3.9%) and page_pool_alloc_frag_netmem (~1.9%)
when running in fragment mode, both stalling on the LSE ldaddal
atomic that maintains pp_ref_count.
This seems to be same as your observation as well. However in my
observation one of the platform shows 15% drop in throughput when
in fragment mode vs page mode. The other platform I ran the test on
infact performs slighty better in fragment mode than in full page
mode (simillar observation as yours).

So the atomic refcount overhead appears to be common across ARM64
platforms, but it does not cause a throughput regression.
The throughput regression seems specific to one platform only for which
we want to have the full page work around, also the HW team has
identified PCIe stalls in fragment mode that are absent in full-page mode.
Their investigation points to a suspected microarchitectural
issue in the PCIe root port. IMO, there seems to be no issue with
page_pool itself.

Given that:
 - Grace shows fragments are faster (your data)
 - A second ARM64 platform shows no regression (my data)
 - Only the affected platform shows a throughput drop
 - The HW team suspects this to a platform-specific PCIe issue,
   also form our experiment data the drop in throughput seems to
   be platform specific only.

I believe this remains a platform-specific workaround rather than
a generic issue. Would a private flag still be acceptable for this
case?


> 
> There are some 200 Gbps NICs but they're mlx5 so I'd have to redo the
> driver hack. Are you going to re-implement this change with rx-buf-len
> instead of a private flag? If so, I won't spend more time running this
> test.
> 
I can go either way depending on what Jakub prefers.
Hi Jakub,
with this new data from David, is it convincing enough for a mana driver
specific private flag, which can be set from user space by a udev rule
by detecting the underlying platform? If not then I will send the next
version with the other rxbuflen approach. 
> > 
> > 
> > Regards
> > Dipayaan Roy


Thanks and Regards
Dipayaan Roy

^ permalink raw reply

* Re: [PATCH bpf] bpf, sockmap: Fix wrong rsge offset in bpf_msg_push_data()
From: Jiayuan Chen @ 2026-04-25  8:25 UTC (permalink / raw)
  To: Weiming Shi, Martin KaFai Lau, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: John Fastabend, Stanislav Fomichev, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Simon Horman, bpf,
	netdev, Xiang Mei
In-Reply-To: <20260423155807.1245644-2-bestswngs@gmail.com>


On 4/23/26 11:58 PM, Weiming Shi wrote:
> When bpf_msg_push_data() splits a scatterlist element into head and
> tail, the tail's page offset is advanced by `start` (absolute message
> byte offset) instead of `start - offset` (byte position within the
> element). This makes rsge.offset overshoot by `offset` bytes, pointing
> to the wrong location within the page or beyond its boundary. Consumers
> of the corrupted entry either silently read wrong data or trigger an
> out-of-bounds access.
>
>   BUG: KASAN: slab-use-after-free in bpf_msg_pull_data (net/core/filter.c:2728)
>   Read of size 32752 at addr ffff8881042f0010 by task poc/130
>   Call Trace:
>    __asan_memcpy (mm/kasan/shadow.c:105)
>    bpf_msg_pull_data (net/core/filter.c:2728)
>    bpf_prog_run_pin_on_cpu (include/linux/bpf.h:1402)
>    sk_psock_msg_verdict (net/core/skmsg.c:934)
>    tcp_bpf_send_verdict (net/ipv4/tcp_bpf.c:421)
>    sock_sendmsg_nosec (net/socket.c:727)
>
> Fixes: 6fff607e2f14 ("bpf: sk_msg program helper bpf_msg_push_data")
> Reported-by: Xiang Mei <xmei5@asu.edu>
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>


Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>


Fix looks correct.
The bug only surfaces when the split branch is taken and start lands
inside a non-first SG element (offset > 0).

It took me 2 hours to reproduce it. Repos or self-tests are welcome next 
time you reported a bug...

> ---
>   net/core/filter.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 3e56b567bd18..f12fbc49bc03 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -2865,7 +2865,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
>
>   		psge->length = start - offset;
>   		rsge.length -= psge->length;
> -		rsge.offset += start;
> +		rsge.offset += start - offset;
>
>   		sk_msg_iter_var_next(i);
>   		sg_unmark_end(psge);
> --
> 2.43.0

^ permalink raw reply

* [PATCH net] sfc: fix error code in efx_devlink_info_running_versions()
From: Dan Carpenter @ 2026-04-25  9:09 UTC (permalink / raw)
  To: Alejandro Lucero
  Cc: Edward Cree, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Martin Habets, Jiri Pirko, netdev,
	linux-net-drivers, linux-kernel, kernel-janitors

Return -EINVAL if efx_mcdi_rpc() doesn't return enough space.

Fixes: 14743ddd2495 ("sfc: add devlink info support for ef100")
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
 drivers/net/ethernet/sfc/efx_devlink.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index d842c60dfc10..45f412bb9b5d 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -531,7 +531,7 @@ static int efx_devlink_info_running_versions(struct efx_nic *efx,
 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
 		netif_err(efx, drv, efx->net_dev,
 			  "mcdi MC_CMD_GET_VERSION failed\n");
-		return rc;
+		return rc ?: -EINVAL;
 	}
 
 	/* Handle previous output */
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH net-next v6 3/3] riscv: dts: eswin: eic7700-hifive-premier-p550: enable Ethernet controller
From: Krzysztof Kozlowski @ 2026-04-25  9:33 UTC (permalink / raw)
  To: lizhi2
  Cc: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
	conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
	rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
	linux-arm-kernel, linux-kernel, maxime.chevallier, ningyu, linmin,
	pinkesh.vaghela, pritesh.patel, weishangjuan, horms
In-Reply-To: <20260423085650.820-1-lizhi2@eswincomputing.com>

On Thu, Apr 23, 2026 at 04:56:50PM +0800, lizhi2@eswincomputing.com wrote:
> From: Zhi Li <lizhi2@eswincomputing.com>
> 
> Enable the on-board Gigabit Ethernet controller on the
> HiFive Premier P550 development board.
> 
> Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
> ---
>  .../devicetree/bindings/mfd/syscon.yaml       |   2 +
>  .../dts/eswin/eic7700-hifive-premier-p550.dts | 232 ++++++++++++++++++
>  arch/riscv/boot/dts/eswin/eic7700.dtsi        | 103 ++++++++
>  3 files changed, 337 insertions(+)
> 

Please split the patches.

Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v4 net 3/3] net: hns3: fix CWR handling in drivers to preserve ACE signal
From: Jijie Shao @ 2026-04-25  9:35 UTC (permalink / raw)
  To: chia-yu.chang, linyunsheng, andrew+netdev, parav, jasowang, mst,
	shenjian15, salil.mehta, saeedm, tariqt, mbloch, leonro,
	linux-rdma, netdev, davem, edumazet, kuba, pabeni, horms, ij,
	ncardwell, koen.de_schepper, g.white, ingemar.s.johansson,
	mirja.kuehlewind, cheshire, rs.ietf, Jason_Livingood, vidhi_goel
  Cc: shaojijie
In-Reply-To: <20260417152642.71674-4-chia-yu.chang@nokia-bell-labs.com>


on 2026/4/17 23:26, chia-yu.chang@nokia-bell-labs.com wrote:
> From: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
>
> Currently, hns3 Rx paths use SKB_GSO_TCP_ECN flag when a TCP segment
> with the CWR flag set. This is wrong because SKB_GSO_TCP_ECN is only
> valid for RFC3168 ECN on Tx, and using it on Rx allows RFC3168 ECN
> offload to clear the CWR flag. As a result, incoming TCP segments
> lose their ACE signal integrity required for AccECN (RFC9768),
> especially when the packet is forwarded and later re-segmented by GSO.
>
> Fix this by setting SKB_GSO_TCP_ACCECN for any Rx segment with the CWR
> flag set. SKB_GSO_TCP_ACCECN ensure that RFC3168 ECN offload will
> not clear the CWR flag, therefore preserving the ACE signal.
>
> Fixes: d474d88f88261 ("net: hns3: add hns3_gro_complete for HW GRO process")
> Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
> ---
>   drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> index a3206c97923e..e1b0dba56182 100644
> --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> @@ -3904,7 +3904,7 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info)
>   
>   	skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
>   	if (th->cwr)
> -		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
> +		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ACCECN;
>   
>   	if (l234info & BIT(HNS3_RXD_GRO_FIXID_B))
>   		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID;

I agree with Paolo's previous point;
for already released hardware, it is indeed not suitable to modify it.
During the hardware aggregation process, the ACE signal may have already been lost.

Jijie Shao




^ permalink raw reply

* Re: [PATCH net] net: mana: Optimize irq affinity for low vcpu configs
From: Dipayaan Roy @ 2026-04-25  9:43 UTC (permalink / raw)
  To: Shradha Gupta
  Cc: Dexuan Cui, Wei Liu, Haiyang Zhang, K. Y. Srinivasan, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Konstantin Taranov, Simon Horman, Erni Sri Satya Vennela,
	Shiraz Saleem, Michael Kelley, Long Li, Yury Norov, linux-hyperv,
	linux-kernel, netdev, Paul Rosswurm, Shradha Gupta,
	Saurabh Singh Sengar, stable
In-Reply-To: <aexcDgNJw4Nr/uMU@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>

On Fri, Apr 24, 2026 at 11:15:42PM -0700, Shradha Gupta wrote:
> On Fri, Apr 24, 2026 at 05:21:23AM -0700, Dipayaan Roy wrote:
> > On Thu, Apr 23, 2026 at 11:17:00PM -0700, Shradha Gupta wrote:
> > > In mana driver, the number of IRQs allocated are capped by the
> > > min(num_cpu + 1, queue count). In cases, where the IRQ count is greater
> > > than the vcpu count, we want to utilize all the vcpus, irrespective of
> > > their NUMA/core bindings.
> > > 
> > > This is important, especially in the envs where number of vcpus are so
> > > few that the softIRQ handling overhead on two IRQs on the same vcpu is
> > > much more than their overheads if they were spread across sibling vcpus
> > > 
> > > This behaviour is more evident with dynamic IRQ allocation. Since MANA
> > > IRQs are assigned at a later stage compared to static allocation, other
> > > device IRQs may already be affinitized to the vCPUs. As a result, IRQ
> > > weights become imbalanced, causing multiple MANA IRQs to land on the
> > > same vCPU.
> > > 
> > > In such cases when many parallel TCP connections are tested, the
> > > throughput drops significantly
> > > 
> > > Test envs:
> > > =======================================================
> > > Case 1: without this patch
> > > =======================================================
> > > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > > 
> > > 	TYPE		effective vCPU aff
> > > =======================================================
> > > IRQ0:	HWC		0
> > > IRQ1:	mana_q1		0
> > > IRQ2:	mana_q2		2
> > > IRQ3:	mana_q3		0
> > > IRQ4:	mana_q4		3
> > > 
> > > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > > vCPU		0	1	2	3
> > > =======================================================
> > > pass 1:		38.85	0.03	24.89	24.65
> > > pass 2:		39.15	0.03	24.57	25.28
> > > pass 3:		40.36	0.03	23.20	23.17
> > > 
> > > =======================================================
> > > Case 2: with this patch
> > > =======================================================
> > > 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4 Queue)
> > > 
> > >         TYPE            effective vCPU aff
> > > =======================================================
> > > IRQ0:   HWC             0
> > > IRQ1:   mana_q1         0
> > > IRQ2:   mana_q2         1
> > > IRQ3:   mana_q3         2
> > > IRQ4:   mana_q4         3
> > > 
> > > %soft on each vCPU(mpstat -P ALL 1) on receiver
> > > vCPU            0       1       2       3
> > > =======================================================
> > > pass 1:         15.42	15.85	14.99	14.51
> > > pass 2:         15.53	15.94	15.81	15.93
> > > pass 3:         16.41	16.35	16.40	16.36
> > > 
> > > =======================================================
> > > Throughput Impact(in Gbps, same env)
> > > =======================================================
> > > TCP conn	with patch	w/o patch
> > > 20480		15.65		7.73
> > > 10240		15.63		8.93
> > > 8192		15.64		9.69
> > > 6144		15.64		13.16
> > > 4096		15.69		15.75
> > > 2048		15.69		15.83
> > > 1024		15.71		15.28
> > > 
> > > Fixes: 755391121038 ("net: mana: Allocate MSI-X vectors dynamically")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
> > > Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
> > > Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> > > ---
> > >  .../net/ethernet/microsoft/mana/gdma_main.c   | 35 +++++++++++++++++--
> > >  1 file changed, 33 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > > index 098fbda0d128..433c044d53c6 100644
> > > --- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > > +++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
> > > @@ -1672,6 +1672,23 @@ static int irq_setup(unsigned int *irqs, unsigned int len, int node,
> > >  	return 0;
> > >  }
> > >  
> > > +static int irq_setup_linear(unsigned int *irqs, unsigned int len)
> > > +{
> > > +	int cpu;
> > > +
> > > +	rcu_read_lock();
> > We do not need to call rcu_read_lock here, as the caller of this
> > function has already acquired cpus_read_lock.
> 
> Thanks for your comments Dipayaan, I think this is still needed for the
> irq_set_affinity_and_hint(), to protect the pointer returned by
> irq_to_desc(). You can also see the same in the original function
> irq_setup() for the same reason.
Hi Shradha,

The original irq_setup() function uses rcu_read_lock() because it relies
on for_each_numa_hop_mask(), which explicitly mandates that RCU be held.
You have not used it in irq_setup_linear(), hence the requirement does not apply
here.
https://elixir.bootlin.com/linux/v7.0.1/source/include/linux/topology.h#L314
/**
 * for_each_numa_hop_mask - iterate over cpumasks of increasing NUMA
 * distance
 *                          from a given node.
 * @mask: the iteration variable.
 * @node: the NUMA node to start the search from.
 *
 * Requires rcu_lock to be held.
 *
.....
Regarding irq_set_affinity_and_hint it also garbs rcu locks internally:
irq_set_affinity_and_hint ->__irq_apply_affinity_hint() -> irq_to_desc() -> mtree_load().
Also see how irq_set_affinity_and_hint is called in mana_gd_setup_irqs.
IMO we should drop the nesting when not needed, even though it appears
harmless.

Thanks and Regards
Dipayaan Roy

> 
> > > +	for_each_online_cpu(cpu) {
> > > +		if (len <= 0)
> > len is unsigned here so <= doesnot makes sense. PLease change it to int
> > or better use if(!len)
> 
> sure, I think I will change it to explicitly exit when len == 0
> Thanks.
> 
> > > +			break;
> > > +
> > > +		irq_set_affinity_and_hint(*irqs++, cpumask_of(cpu));
> > > +		len--;
> > > +	}
> > > +	rcu_read_unlock();
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> > >  {
> > >  	struct gdma_context *gc = pci_get_drvdata(pdev);
> > > @@ -1722,10 +1739,24 @@ static int mana_gd_setup_dyn_irqs(struct pci_dev *pdev, int nvec)
> > >  	 * first CPU sibling group since they are already affinitized to HWC IRQ
> > >  	 */
> > >  	cpus_read_lock();
> > > -	if (gc->num_msix_usable <= num_online_cpus())
> > > +	if (gc->num_msix_usable <= num_online_cpus()) {
> > >  		skip_first_cpu = true;
> > > +		err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> > > +	} else {
> > > +		/*
> > > +		 * In case our IRQs are more than num_online_cpus, we try to
> > > +		 * make sure we are using all vcpus. In such a case NUMA or
> > > +		 * CPU core affinity does not matter.
> > > +		 * Note that in this case the total mana IRQ should always be
> > > +		 * num_online_cpu + 1. The first HWC IRQ is already handled
> > > +		 * in HWC setup calls
> > > +		 * So, the nvec value in this path should always be equal to
> > > +		 * num_online_cpu
> > nit: typo: should be num_online_cpus
> 
> noted
> 
> > > +		 */
> > > +		WARN_ON(nvec > num_online_cpus());
> > > +		err = irq_setup_linear(irqs, nvec);
> > > +	}
> > >  
> > > -	err = irq_setup(irqs, nvec, gc->numa_node, skip_first_cpu);
> > >  	if (err) {
> > >  		cpus_read_unlock();
> > >  		goto free_irq;
> > > 
> > > base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
> > > -- 
> > > 2.34.1
> > > 
> > Regards
> > Dipayaan Roy

^ permalink raw reply

* Re: [PATCH net-deletions v2] net: remove unused ATM protocols and legacy ATM device drivers
From: Maciej W. Rozycki @ 2026-04-25 10:16 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David S. Miller, netdev, edumazet, pabeni, andrew+netdev, horms,
	corbet, skhan, linux, Thomas Bogendoerfer, maddy, mpe, npiggin,
	chleroy, 3chas3, razor, idosch, jani.nikula, mchehab+huawei,
	tytso, herbert, Geert Uytterhoeven, ebiggers, johannes.berg,
	jonathan.cameron, kees, kuniyu, fourier.thomas, andriy.shevchenko,
	rdunlap, Andrew Morton, linux-doc, linux-mips, linuxppc-dev,
	bridge, David Woodhouse
In-Reply-To: <20260422041846.2035118-1-kuba@kernel.org>

On Tue, 21 Apr 2026, Jakub Kicinski wrote:

> Removed PCI/SBUS ATM device drivers (drivers/atm/):
>  - adummy, atmtcp - software/testing ATM devices
>  - eni - Efficient Networks ENI155P (OC-3, ~1995)

 I have one of those though sadly it broke a couple years back and doesn't 
work anymore.

>  - fore200e - FORE Systems 200E PCI/SBUS (OC-3, ~1999)
>  - he - ForeRunner HE (OC-3/OC-12, ~2000)
>  - idt77105 - IDT 77105 25 Mbps ATM PHY
>  - idt77252 - IDT 77252 NICStAR II (OC-3, ~2000)
>  - iphase - Interphase ATM PCI (OC-3/DS3/E3)
>  - lanai - Efficient Networks Speedstream 3010
>  - nicstar - IDT 77201 NICStAR (155/25 Mbps, ~1999)

 And I have a number of these, both 77201 and 77211 variants, scattered 
across several systems of various architectures in my lab.

>  - solos-pci - Traverse Technologies ADSL2+ PCI
>  - suni - PMC S/UNI SONET PHY library

 Plus a bunch of TURBOchannel ATM interfaces, a couple of LightStream ATM 
switches and some Ethernet switches with LANE ports.  Never found time to 
get this all set up, so I guess I can't complain really to see this stuff 
go.  Still sad to see the continuous trend to strip Linux of features. :(

  Maciej

^ permalink raw reply

* Re: [PATCH net v2] ipv6: Implement limits on extension header parsing
From: Justin Iurman @ 2026-04-25 10:19 UTC (permalink / raw)
  To: Daniel Borkmann, kuba
  Cc: edumazet, dsahern, tom, willemdebruijn.kernel, idosch, pabeni,
	netdev
In-Reply-To: <20260425075521.736328-1-daniel@iogearbox.net>

On 4/25/26 09:55, Daniel Borkmann wrote:
> ipv6_{skip_exthdr,find_hdr}() and ip6_{tnl_parse_tlv_enc_lim,
> protocol_deliver_rcu}() iterate over IPv6 extension headers until they
> find a non-extension-header protocol or run out of packet data. The
> loops have no iteration counter, relying solely on the packet length
> to bound them. For a crafted packet with 8-byte extension headers
> filling a 64KB jumbogram, this means a worst case of up to ~8k
> iterations with a skb_header_pointer call each. ipv6_skip_exthdr(),
> for example, is used where it parses the inner quoted packet inside
> an incoming ICMPv6 error:
> 
>    - icmpv6_rcv
>      - checksum validation
>      - case ICMPV6_DEST_UNREACH
>        - icmpv6_notify
>          - pskb_may_pull()       <- pull inner IPv6 header
>          - ipv6_skip_exthdr()    <- iterates here
>          - pskb_may_pull()
>          - ipprot->err_handler() <- sk lookup
> 
> The per-iteration cost of ipv6_skip_exthdr itself is generally
> light, but skb_header_pointer becomes more costly on reassembled
> packets: the first ~1232 bytes of the inner packet are in the skb's
> linear area, but the remaining ~63KB are in the frag_list where
> skb_copy_bits is needed to read data.
> 
> Add a configurable limit via a new sysctl net.ipv6.max_ext_hdrs_number
> (default 8, minimum 1). All four extension header walking functions
> are bound by this limit. The sysctl is in line with commit 47d3d7ac656a
> ("ipv6: Implement limits on Hop-by-Hop and Destination options").
> As documented, init_net is used to derive max_ext_hdrs_number to
> be consistent given a net cannot always reliably be retrieved.
> 
> Note that the check in ip6_protocol_deliver_rcu() happens right
> before the goto resubmit, such that we don't have to have a test
> for ipv6_ext_hdr() in the fast-path.
> 
> There's an ongoing IETF draft-iurman-6man-eh-occurrences to enforce
> IPv6 extension headers ordering and occurrence. The latter also
> discusses security implications. As per RFC8200 section 4.1, the
> occurrence rules for extension headers provide a practical upper
> bound, thus 8 was used as the default.
> 
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
> ---
>   v1->v2:
>     - Set the default to 8 (Justin)
>     - Update IETF references (Justin)
>     - Add core path coverage as well (Justin)
> 
>   Documentation/networking/ip-sysctl.rst |  7 +++++++
>   include/net/dropreason-core.h          |  6 ++++++
>   include/net/ipv6.h                     |  2 ++
>   include/net/netns/ipv6.h               |  1 +
>   net/ipv6/af_inet6.c                    |  1 +
>   net/ipv6/exthdrs_core.c                | 11 +++++++++++
>   net/ipv6/ip6_input.c                   |  6 ++++++
>   net/ipv6/ip6_tunnel.c                  |  5 +++++
>   net/ipv6/sysctl_net_ipv6.c             |  8 ++++++++
>   9 files changed, 47 insertions(+)
> 

[snip]

> diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
> index 967b07aeb683..a5bbbc16e8d7 100644
> --- a/net/ipv6/ip6_input.c
> +++ b/net/ipv6/ip6_input.c
> @@ -403,8 +403,10 @@ INDIRECT_CALLABLE_DECLARE(int tcp_v6_rcv(struct sk_buff *));
>   void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
>   			      bool have_final)
>   {
> +	int exthdr_max = READ_ONCE(init_net.ipv6.sysctl.max_ext_hdrs_cnt);
>   	const struct inet6_protocol *ipprot;
>   	struct inet6_dev *idev;
> +	int exthdr_cnt = 0;
>   	unsigned int nhoff;
>   	SKB_DR(reason);
>   	bool raw;
> @@ -487,6 +489,10 @@ void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr,
>   				nexthdr = ret;
>   				goto resubmit_final;
>   			} else {
> +				if (unlikely(exthdr_cnt++ >= exthdr_max)) {
> +					SKB_DR_SET(reason, IPV6_TOO_MANY_EXTHDRS);
> +					goto discard;
> +				}
>   				goto resubmit;
>   			}
>   		} else if (ret == 0) {

The hop-by-hop options header (if present) is not taken into account 
based on the above. However, the max number of extension headers 
(implicitly 7***, as per RFC 8200 Section 4.1) must include it. I 
suggest adding this at the beginning of ip6_protocol_deliver_rcu():

struct inet6_skb_parm *opt = IP6CB(skb);

if (opt->flags & IP6SKB_HOPBYHOP)
	exthdr_cnt++;

*** FYI, rounding to 8 is fine for this fix

> diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
> index d2cd33e2698d..93f865545a7c 100644
> --- a/net/ipv6/sysctl_net_ipv6.c
> +++ b/net/ipv6/sysctl_net_ipv6.c
> @@ -135,6 +135,14 @@ static struct ctl_table ipv6_table_template[] = {
>   		.extra1		= SYSCTL_ZERO,
>   		.extra2		= &flowlabel_reflect_max,
>   	},
> +	{
> +		.procname	= "max_ext_hdrs_number",
> +		.data		= &init_net.ipv6.sysctl.max_ext_hdrs_cnt,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec_minmax,
> +		.extra1		= SYSCTL_ONE,
> +	},
>   	{
>   		.procname	= "max_dst_opts_number",
>   		.data		= &init_net.ipv6.sysctl.max_dst_opts_cnt,

I've given it a lot of thought. I came to the conclusion that we should 
use a hard-coded value here as well (just like we did for 076b8cad77aa, 
with the same logic), not a sysctl. IMO, the main reason is that it 
provides as is a suitable security fix to be backported, i.e., the max 
value is the max number of EHs allowed by RFC 8200, Section 4.1. Also, 
we remain consistent with draft-iurman-6man-eh-occurrences (I think Tom 
is about to send a revision of the series soon for net-next). What this 
series does is not only enforcing ordering, but also verifying the 
specific number of occurrences for each type of Extension Header. Which 
is totally compatible with what this patch does, i.e., limiting the 
total number of Extension Headers (regardless of their types) to 8. I 
guess what I'm trying to say is that it seems like a good 
plan/compromise and that the aforementioned series would build perfectly 
on top of this fix.

^ permalink raw reply

* [PATCH bpf v3 0/2] bpf: prevent offloaded programs from running on host via tcx/netkit
From: Jiayuan Chen @ 2026-04-25 10:59 UTC (permalink / raw)
  To: bpf
  Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jesper Dangaard Brouer, Stanislav Fomichev,
	Willem de Bruijn, Samiullah Khawaja, Hangbin Liu, Krishna Kumar,
	Kuniyuki Iwashima, linux-kernel, netdev

Yinhao reported a splat [1] when attaching a BPF program loaded with
prog_ifindex (targeted at an offload-capable device such as netdevsim)
to the software path via BPF_TCX_EGRESS. The program's bpf_func had
already been replaced by bpf_prog_warn_on_exec() during offload compile,
so the first packet that reaches tcx_run() trips the WARN:

[   19.592982] ------------[ cut here ]------------
[   19.594654] attempt to execute device eBPF program on the host!
[   19.594659] WARNING: kernel/bpf/offload.c:420 at 0x0, CPU#0: poc/337
[   19.599906] Modules linked in:
[   19.600680] CPU: 0 UID: 0 PID: 337 Comm: poc Not tainted
6.18.0-rc7-next-20251125 #10 PREEMPT(none)
[   19.601659] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX,
1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   19.602684] RIP: 0010:bpf_prog_warn_on_exec+0xc/0x20
[   19.603241] Code: 28 00 48 89 ef e8 74 44 2f 00 eb d7 66 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 44 00 00 48 8d 3d a4 eb 95
06 <67> 48 0f b9 3a 31 c0 e9 83 76 44 ff 0f 1f 84 00 00 00 00 00 90 90
[   19.605093] RSP: 0018:ffff8881066e73d8 EFLAGS: 00010246
[   19.605663] RAX: ffffffff81cbca70 RBX: ffff8881013c4210 RCX:
0000000000000004
[   19.606378] RDX: 1ffff11020278842 RSI: ffffc90000563060 RDI:
ffffffff8861b620
[   19.607107] RBP: ffff8881010d0640 R08: ffff8881013c4210 R09:
ffff8881010d06b0
[   19.607827] R10: ffff8881010d06c3 R11: ffffc90000563000 R12:
ffffc90000563000
[   19.608751] R13: ffff8881010d06b4 R14: ffff888115eb1a34 R15:
dffffc0000000000
[   19.609478] FS:  000000000294c380(0000) GS:ffff8881911e9000(0000)
knlGS:0000000000000000
[   19.610316] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   19.610943] CR2: 000057f6b9eb38c0 CR3: 00000001010ea000 CR4:
0000000000750ef0
[   19.611712] PKRU: 55555554
[   19.612006] Call Trace:
[   19.612281]  <TASK>
[   19.612523]  __dev_queue_xmit+0x22cb/0x3530
[   19.617607]  ip_finish_output2+0x621/0x1a60
[   19.621371]  ip_output+0x170/0x2e0
[   19.624586]  ip_send_skb+0x129/0x180
[   19.624940]  udp_send_skb+0x65d/0x1300
[   19.625316]  udp_sendmsg+0x13bf/0x2000
[   19.629960]  __sys_sendto+0x396/0x470
[   19.633720]  __x64_sys_sendto+0xdc/0x1b0
[   19.635066]  do_syscall_64+0x76/0x10a0
[   19.641701]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   19.642240] RIP: 0033:0x4240d7
[   19.642597] Code: 00 89 01 e9 c1 fe ff ff e8 f6 03 00 00 66 0f 1f 44
00 00 f3 0f 1e fa 80 3d 8d 3f 09 00 00 41 89 ca 74 10 b8 2c 00 00 00 0f
05 <48> 3d 00 f0 ff ff 77 69 c3 55 48 89 e5 53 48 83 ec 38 44 89 4d d0
[   19.646088] RSP: 002b:00007fffcb9ecb68 EFLAGS: 00000202 ORIG_RAX:
000000000000002c
[   19.648938] RAX: ffffffffffffffda RBX: 0000000000000001 RCX:
00000000004240d7
[   19.652116] RDX: 0000000000000008 RSI: 00007fffcb9ecce0 RDI:
0000000000000005
[   19.653148] RBP: 00007fffcb9eccf0 R08: 00007fffcb9ecbb0 R09:
0000000000000010
[   19.653951] R10: 0000000000000000 R11: 0000000000000202 R12:
00007fffcb9ece08
[   19.654760] R13: 00007fffcb9ece18 R14: 00000000004b2868 R15:
0000000000000001
[   19.657462]  </TASK>
[   19.657703] ---[ end trace 0000000000000000 ]---

The reason is that tcx, netkit and bpf_xdp_link_update() can install an
offloaded program onto a software execution path without rejecting it.
Rather than sprinkling the same check across every attach/update entry
point, do it at the source:

  - bpf_mprog_attach() is the single chokepoint for tcx/netkit (covers
    all three of attach, link create and link update on both subsystems,
    six call sites in total).
  - dev_xdp_install() is the single chokepoint for XDP (covers both the
    dev_xdp_attach() path and the bpf_xdp_link_update() path which
    previously bypassed the check).

This series adds/moves the check into those two functions so offloaded
programs can no longer be attached to (or swapped into) the software
path, regardless of which entry point is used.

v2 -> v3:
  - Alexei suggested converging the check rather than spreading it
    across attach entry points. Consolidated into a single check at
    bpf_mprog_attach() (covers all six tcx/netkit paths) and moved the
    existing XDP check from dev_xdp_attach() into dev_xdp_install() so
    the bpf_xdp_link_update() path is also covered. Three patches
    collapse into two.
v2: https://lore.kernel.org/bpf/20260424104201.217604-1-jiayuan.chen@linux.dev/

v1 -> v2:
  - tcx/netkit: also reject offloaded progs in the link update callback
    (tcx_link_update/netkit_link_update), not just attach; pointed out
    by the AI review on v1.
  - Add patch 3/3 for the same hole in bpf_xdp_link_update().
v1: https://lore.kernel.org/bpf/20260423033609.252464-1-jiayuan.chen@linux.dev/

[1]: https://lore.kernel.org/bpf/64d8e2b5-a214-4f3c-b9e8-bcedbcb2c602@hust.edu.cn/

Jiayuan Chen (2):
  bpf, tcx, netkit: reject offloaded programs
  bpf, xdp: move offload check into dev_xdp_install()

 kernel/bpf/mprog.c | 11 +++++++++++
 net/core/dev.c     |  9 +++++----
 2 files changed, 16 insertions(+), 4 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH bpf v3 1/2] bpf, tcx, netkit: reject offloaded programs
From: Jiayuan Chen @ 2026-04-25 10:59 UTC (permalink / raw)
  To: bpf
  Cc: Jiayuan Chen, Yinhao Hu, Kaiyan Mei, Dongliang Mu,
	Alexei Starovoitov, Daniel Borkmann, John Fastabend,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jesper Dangaard Brouer, Stanislav Fomichev,
	Willem de Bruijn, Samiullah Khawaja, Hangbin Liu, Krishna Kumar,
	Kuniyuki Iwashima, linux-kernel, netdev
In-Reply-To: <20260425105942.223757-1-jiayuan.chen@linux.dev>

An offloaded prog has its bpf_func replaced by bpf_prog_warn_on_exec()
during bpf_prog_offload_compile(), since it is supposed to run on the
NIC. Both current mprog users, tcx and netkit, dispatch programs via
bpf_prog_run() on the host. Attaching an offloaded prog through any
of their entry points (BPF_PROG_ATTACH, BPF_LINK_CREATE, BPF_LINK_UPDATE
on tcx_*/netkit_*) ends up tripping the WARN on the first packet.

Ideally this validation would live in tcx and netkit, since "must not
be offloaded" is a property of those subsystems' software dispatch,
not of the generic multi-prog attachment layer. However, those two
together have six attach call sites and putting the check in each of
them duplicates the same logic. mprog happens to be the only chokepoint
shared by all of them, so add the check there instead and scope it to
BPF_PROG_TYPE_SCHED_CLS via a small helper, so a future mprog user that
legitimately accepts offloaded programs is not affected.

Use bpf_prog_is_offloaded() rather than bpf_prog_is_dev_bound() +
bpf_offload_dev_match() (as XDP does): bpf_prog_dev_bound_init()
already rejects BPF_F_XDP_DEV_BOUND_ONLY for BPF_PROG_TYPE_SCHED_CLS,
so a dev-bound SCHED_CLS program is always offloaded. The simpler
check is sufficient and also rejects attaching a program offloaded to
device A onto device B.

Fixes: 053c8e1f235dc ("bpf: Add generic attach/detach/query API for multi-progs")
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Dongliang Mu <dzm91@hust.edu.cn>
Closes: https://lore.kernel.org/bpf/64d8e2b5-a214-4f3c-b9e8-bcedbcb2c602@hust.edu.cn/
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
 kernel/bpf/mprog.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/kernel/bpf/mprog.c b/kernel/bpf/mprog.c
index 1394168062e85..0b50464ec902d 100644
--- a/kernel/bpf/mprog.c
+++ b/kernel/bpf/mprog.c
@@ -222,6 +222,14 @@ static int bpf_mprog_pos_after(struct bpf_mprog_entry *entry,
 	return tuple->prog ? -ENOENT : bpf_mprog_total(entry);
 }
 
+static int bpf_mprog_check_prog(const struct bpf_prog *prog)
+{
+	if (prog->type == BPF_PROG_TYPE_SCHED_CLS &&
+	    bpf_prog_is_offloaded(prog->aux))
+		return -EINVAL;
+	return 0;
+}
+
 int bpf_mprog_attach(struct bpf_mprog_entry *entry,
 		     struct bpf_mprog_entry **entry_new,
 		     struct bpf_prog *prog_new, struct bpf_link *link,
@@ -237,6 +245,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry,
 	};
 	int ret, idx = -ERANGE, tidx;
 
+	ret = bpf_mprog_check_prog(prog_new);
+	if (ret)
+		return ret;
 	if (revision && revision != bpf_mprog_revision(entry))
 		return -ESTALE;
 	if (bpf_mprog_exists(entry, prog_new))
-- 
2.43.0


^ permalink raw reply related

* [PATCH bpf v3 2/2] bpf, xdp: move offload check into dev_xdp_install()
From: Jiayuan Chen @ 2026-04-25 10:59 UTC (permalink / raw)
  To: bpf
  Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Jesper Dangaard Brouer, Stanislav Fomichev,
	Willem de Bruijn, Samiullah Khawaja, Hangbin Liu, Krishna Kumar,
	Kuniyuki Iwashima, linux-kernel, netdev
In-Reply-To: <20260425105942.223757-1-jiayuan.chen@linux.dev>

bpf_xdp_link_update() calls dev_xdp_install() directly and bypasses
dev_xdp_attach(), so the offload check that lived in dev_xdp_attach()
does not apply. A user can create an XDP link in SKB or native mode
with a regular program and then replace it via BPF_LINK_UPDATE with an
offloaded program, whose bpf_func is bpf_prog_warn_on_exec(), tripping
the WARN on the first packet.

Move the check from dev_xdp_attach() into dev_xdp_install() so both
the attach path and the link update path are covered by a single check
at the actual install site.

Fixes: 026a4c28e1db3 ("bpf, xdp: Implement LINK_UPDATE for BPF XDP link")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
 net/core/dev.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 831129f2a69b5..e3958281e8d63 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10330,6 +10330,11 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
 
 	netdev_ops_assert_locked(dev);
 
+	if (prog && mode != XDP_MODE_HW && bpf_prog_is_offloaded(prog->aux)) {
+		NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
+		return -EINVAL;
+	}
+
 	if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
 	    prog && !prog->aux->xdp_has_frags) {
 		NL_SET_ERR_MSG(extack, "unable to install XDP to device using tcp-data-split");
@@ -10481,10 +10486,6 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
 			NL_SET_ERR_MSG(extack, "Native and generic XDP can't be active at the same time");
 			return -EEXIST;
 		}
-		if (!offload && bpf_prog_is_offloaded(new_prog->aux)) {
-			NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
-			return -EINVAL;
-		}
 		if (bpf_prog_is_dev_bound(new_prog->aux) && !bpf_offload_dev_match(new_prog, dev)) {
 			NL_SET_ERR_MSG(extack, "Program bound to different device");
 			return -EINVAL;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH bpf v3 2/2] bpf, xdp: move offload check into dev_xdp_install()
From: bot+bpf-ci @ 2026-04-25 11:30 UTC (permalink / raw)
  To: jiayuan.chen, bpf
  Cc: jiayuan.chen, ast, daniel, john.fastabend, andrii, martin.lau,
	eddyz87, memxor, song, yonghong.song, jolsa, davem, edumazet,
	kuba, pabeni, horms, hawk, sdf, willemb, skhawaja, liuhangbin,
	krikku, kuniyu, linux-kernel, netdev, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260425105942.223757-3-jiayuan.chen@linux.dev>

[-- Attachment #1: Type: text/plain, Size: 2869 bytes --]

> diff --git a/net/core/dev.c b/net/core/dev.c
> index e59f6025067c..8635de70efe7 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -10359,6 +10359,11 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
>
>  	netdev_ops_assert_locked(dev);
>
> +	if (prog && mode != XDP_MODE_HW && bpf_prog_is_offloaded(prog->aux)) {
> +		NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
> +		return -EINVAL;
> +	}
> +

While this check addresses offloaded programs (bpf_prog_is_offloaded()),
does it cover device-bound programs? Looking at dev_xdp_attach(), there
are two distinct checks that were in place:

(1) bpf_prog_is_offloaded() check - now moved to dev_xdp_install()
(2) bpf_prog_is_dev_bound() && !bpf_offload_dev_match() check - still in
    dev_xdp_attach()

A program loaded with BPF_F_XDP_DEV_BOUND_ONLY has dev_bound set to true
but offload_requested set to false, meaning bpf_prog_is_offloaded() will
return false. When bpf_xdp_link_update() calls dev_xdp_install() directly,
could such a device-bound program bypass both checks?

If so, this could allow attaching a device-bound program to an SKB-mode
link, potentially causing the generic XDP runner to execute device-specific
kfuncs that cast the generic xdp_md context to driver-specific structures.

Additionally, if the link is in HW mode, the new check evaluates to false
(mode != XDP_MODE_HW) and validation is skipped. Can a program offloaded
to device A be attached via BPF_LINK_UPDATE to an HW link on device B?
If so, the driver might receive XDP_SETUP_PROG_HW and incorrectly cast
the new program's aux->offload->dev_priv to its own internal structure,
resulting in memory corruption.

This concern was raised by sashiko-bot in v2:
https://lore.kernel.org/bpf/20260425104435.ED443C2BCB5@smtp.kernel.org/

>  	if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
>  	    prog && !prog->aux->xdp_has_frags) {
>  		NL_SET_ERR_MSG(extack, "unable to install XDP to device using tcp-data-split");
> @@ -10510,10 +10515,6 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
>  			NL_SET_ERR_MSG(extack, "Native and generic XDP can't be active at the same time");
>  			return -EEXIST;
>  		}
> -		if (!offload && bpf_prog_is_offloaded(new_prog->aux)) {
> -			NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
> -			return -EINVAL;
> -		}
>  		if (bpf_prog_is_dev_bound(new_prog->aux) && !bpf_offload_dev_match(new_prog, dev)) {
>  			NL_SET_ERR_MSG(extack, "Program bound to different device");
>  			return -EINVAL;


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/24929498218

^ permalink raw reply

* [PATCH] net: stmmac: fix RX DMA leak on TX alloc failure
From: Abid Ali via B4 Relay @ 2026-04-25 12:38 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Maxime Coquelin, Alexandre Torgue
  Cc: netdev, linux-stm32, linux-arm-kernel, linux-kernel, Abid Ali

From: Abid Ali <dev.taqnialabs@gmail.com>

Free RX DMA resources when alloc_dma_tx_desc_resources() fails in
alloc_dma_desc_resources().

Signed-off-by: Abid Ali <dev.taqnialabs@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 13d3cac05..8bb843b55 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2370,8 +2370,12 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv,
 		return ret;
 
 	ret = alloc_dma_tx_desc_resources(priv, dma_conf);
+	if (ret) {
+		free_dma_rx_desc_resources(priv, dma_conf);
+		return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 /**

---
base-commit: 028ef9c96e96197026887c0f092424679298aae8
change-id: 20260425-stmmac-rx-desc-cleanup-440f05845492

Best regards,
-- 
Abid Ali <dev.taqnialabs@gmail.com>



^ permalink raw reply related

* [PATCH net 1/1] batman-adv: stop tp_meter sessions during mesh teardown
From: Ren Wei @ 2026-04-25 12:59 UTC (permalink / raw)
  To: b.a.t.m.a.n, netdev
  Cc: marek.lindner, sw, antonio, sven, davem, edumazet, kuba, pabeni,
	horms, yuantan098, yifanwucs, tomapufckgml, bird, tr0jan,
	wangjiexun2025, n05ec
In-Reply-To: <cover.1776998957.git.wangjiexun2025@gmail.com>

From: Jiexun Wang <wangjiexun2025@gmail.com>

TP meter sessions are started asynchronously and remain linked on
bat_priv->tp_list after the netlink request has already finished.
When the mesh interface is removed, batadv_mesh_free() currently tears
down the mesh without first draining these sessions.

A running sender thread or a late incoming tp_meter packet can then keep
processing against a mesh instance which is already shutting down.
Synchronize tp_meter with the mesh lifetime by stopping all active
sessions from batadv_mesh_free(), refusing new sender/receiver setup once
the mesh is no longer active, and waiting for sender threads to exit
before teardown continues.

Fixes: 33a3bb4a3345 ("batman-adv: throughput meter implementation")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Co-developed-by: Luxing Yin <tr0jan@lzu.edu.cn>
Signed-off-by: Luxing Yin <tr0jan@lzu.edu.cn>
Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
 net/batman-adv/main.c     |   1 +
 net/batman-adv/tp_meter.c | 112 +++++++++++++++++++++++++++++++-------
 net/batman-adv/tp_meter.h |   1 +
 net/batman-adv/types.h    |   4 ++
 4 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 3a35aadd8b41..a4d33ee0fda5 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -249,6 +249,7 @@ void batadv_mesh_free(struct net_device *mesh_iface)
 	atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
 
 	batadv_purge_outstanding_packets(bat_priv, NULL);
+	batadv_tp_stop_all(bat_priv);
 
 	batadv_gw_node_free(bat_priv);
 
diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
index 2e42f6b348c8..028cd4e0f9d1 100644
--- a/net/batman-adv/tp_meter.c
+++ b/net/batman-adv/tp_meter.c
@@ -365,23 +365,38 @@ static void batadv_tp_vars_put(struct batadv_tp_vars *tp_vars)
 }
 
 /**
- * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer
- * @bat_priv: the bat priv with all the mesh interface information
- * @tp_vars: the private data of the current TP meter session to cleanup
+ * batadv_tp_list_detach() - remove tp session from mesh session list once
+ * @tp_vars: the private data of the current TP meter session
  */
-static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv,
-				     struct batadv_tp_vars *tp_vars)
+static void batadv_tp_list_detach(struct batadv_tp_vars *tp_vars)
 {
-	cancel_delayed_work(&tp_vars->finish_work);
+	bool detached = false;
 
 	spin_lock_bh(&tp_vars->bat_priv->tp_list_lock);
-	hlist_del_rcu(&tp_vars->list);
+	if (!hlist_unhashed(&tp_vars->list)) {
+		hlist_del_init_rcu(&tp_vars->list);
+		detached = true;
+	}
 	spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock);
 
+	if (!detached)
+		return;
+
+	atomic_dec(&tp_vars->bat_priv->tp_num);
+
 	/* drop list reference */
 	batadv_tp_vars_put(tp_vars);
+}
 
-	atomic_dec(&tp_vars->bat_priv->tp_num);
+/**
+ * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer
+ * @tp_vars: the private data of the current TP meter session to cleanup
+ */
+static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars)
+{
+	cancel_delayed_work_sync(&tp_vars->finish_work);
+
+	batadv_tp_list_detach(tp_vars);
 
 	/* kill the timer and remove its reference */
 	timer_delete_sync(&tp_vars->timer);
@@ -886,7 +901,8 @@ static int batadv_tp_send(void *arg)
 	batadv_orig_node_put(orig_node);
 
 	batadv_tp_sender_end(bat_priv, tp_vars);
-	batadv_tp_sender_cleanup(bat_priv, tp_vars);
+	batadv_tp_sender_cleanup(tp_vars);
+	complete(&tp_vars->finished);
 
 	batadv_tp_vars_put(tp_vars);
 
@@ -918,7 +934,8 @@ static void batadv_tp_start_kthread(struct batadv_tp_vars *tp_vars)
 		batadv_tp_vars_put(tp_vars);
 
 		/* cleanup of failed tp meter variables */
-		batadv_tp_sender_cleanup(bat_priv, tp_vars);
+		batadv_tp_sender_cleanup(tp_vars);
+		complete(&tp_vars->finished);
 		return;
 	}
 
@@ -947,6 +964,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
 
 	/* look for an already existing test towards this node */
 	spin_lock_bh(&bat_priv->tp_list_lock);
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
+		spin_unlock_bh(&bat_priv->tp_list_lock);
+		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
+					      dst, bat_priv, session_cookie);
+		return;
+	}
+
 	tp_vars = batadv_tp_list_find(bat_priv, dst);
 	if (tp_vars) {
 		spin_unlock_bh(&bat_priv->tp_list_lock);
@@ -966,7 +990,6 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
 					      bat_priv, session_cookie);
 		return;
 	}
-
 	tp_vars = kmalloc_obj(*tp_vars, GFP_ATOMIC);
 	if (!tp_vars) {
 		spin_unlock_bh(&bat_priv->tp_list_lock);
@@ -1017,6 +1040,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
 	tp_vars->start_time = jiffies;
 
 	init_waitqueue_head(&tp_vars->more_bytes);
+	init_completion(&tp_vars->finished);
 
 	spin_lock_init(&tp_vars->unacked_lock);
 	INIT_LIST_HEAD(&tp_vars->unacked_list);
@@ -1119,14 +1143,7 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t)
 		   "Shutting down for inactivity (more than %dms) from %pM\n",
 		   BATADV_TP_RECV_TIMEOUT, tp_vars->other_end);
 
-	spin_lock_bh(&tp_vars->bat_priv->tp_list_lock);
-	hlist_del_rcu(&tp_vars->list);
-	spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock);
-
-	/* drop list reference */
-	batadv_tp_vars_put(tp_vars);
-
-	atomic_dec(&bat_priv->tp_num);
+	batadv_tp_list_detach(tp_vars);
 
 	spin_lock_bh(&tp_vars->unacked_lock);
 	list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) {
@@ -1329,9 +1346,12 @@ static struct batadv_tp_vars *
 batadv_tp_init_recv(struct batadv_priv *bat_priv,
 		    const struct batadv_icmp_tp_packet *icmp)
 {
-	struct batadv_tp_vars *tp_vars;
+	struct batadv_tp_vars *tp_vars = NULL;
 
 	spin_lock_bh(&bat_priv->tp_list_lock);
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
+		goto out_unlock;
+
 	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
 					      icmp->session);
 	if (tp_vars)
@@ -1342,7 +1362,6 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv,
 			   "Meter: too many ongoing sessions, aborting (RECV)\n");
 		goto out_unlock;
 	}
-
 	tp_vars = kmalloc_obj(*tp_vars, GFP_ATOMIC);
 	if (!tp_vars)
 		goto out_unlock;
@@ -1464,6 +1483,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
 {
 	struct batadv_icmp_tp_packet *icmp;
 
+	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
+		goto out;
+
 	icmp = (struct batadv_icmp_tp_packet *)skb->data;
 
 	switch (icmp->subtype) {
@@ -1478,9 +1500,57 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
 			   "Received unknown TP Metric packet type %u\n",
 			   icmp->subtype);
 	}
+
+out:
 	consume_skb(skb);
 }
 
+/**
+ * batadv_tp_stop_all() - stop all currently running tp meter sessions
+ * @bat_priv: the bat priv with all the mesh interface information
+ */
+void batadv_tp_stop_all(struct batadv_priv *bat_priv)
+{
+	struct batadv_tp_vars *tp_vars[BATADV_TP_MAX_NUM];
+	struct batadv_tp_vars *tp_var;
+	int count = 0;
+	int i;
+
+	spin_lock_bh(&bat_priv->tp_list_lock);
+	hlist_for_each_entry(tp_var, &bat_priv->tp_list, list) {
+		if (WARN_ON_ONCE(count >= BATADV_TP_MAX_NUM))
+			break;
+
+		if (!kref_get_unless_zero(&tp_var->refcount))
+			continue;
+
+		tp_vars[count++] = tp_var;
+	}
+	spin_unlock_bh(&bat_priv->tp_list_lock);
+
+	for (i = 0; i < count; i++) {
+		tp_var = tp_vars[i];
+
+		switch (tp_var->role) {
+		case BATADV_TP_SENDER:
+			batadv_tp_sender_shutdown(tp_var,
+						  BATADV_TP_REASON_CANCEL);
+			wake_up(&tp_var->more_bytes);
+			wait_for_completion(&tp_var->finished);
+			break;
+		case BATADV_TP_RECEIVER:
+			batadv_tp_list_detach(tp_var);
+			if (timer_shutdown_sync(&tp_var->timer))
+				batadv_tp_vars_put(tp_var);
+			break;
+		}
+
+		batadv_tp_vars_put(tp_var);
+	}
+
+	synchronize_net();
+}
+
 /**
  * batadv_tp_meter_init() - initialize global tp_meter structures
  */
diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h
index f0046d366eac..4e97cd10cd02 100644
--- a/net/batman-adv/tp_meter.h
+++ b/net/batman-adv/tp_meter.h
@@ -17,6 +17,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
 		     u32 test_length, u32 *cookie);
 void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst,
 		    u8 return_value);
+void batadv_tp_stop_all(struct batadv_priv *bat_priv);
 void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb);
 
 #endif /* _NET_BATMAN_ADV_TP_METER_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 8fc5fe0e9b05..daa06f421154 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -14,6 +14,7 @@
 #include <linux/average.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
+#include <linux/completion.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/kref.h>
@@ -1328,6 +1329,9 @@ struct batadv_tp_vars {
 	/** @finish_work: work item for the finishing procedure */
 	struct delayed_work finish_work;
 
+	/** @finished: completion signaled when a sender thread exits */
+	struct completion finished;
+
 	/** @test_length: test length in milliseconds */
 	u32 test_length;
 
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH net] net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels
From: Andrea Mayer @ 2026-04-25 14:08 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: davem, dsahern, edumazet, kuba, pabeni, horms, clrkwllms, rostedt,
	david.lebrun, alex.aring, Justin Iurman, stefano.salsano, netdev,
	linux-rt-devel, linux-kernel, stable, Andrea Mayer
In-Reply-To: <20260423080056.KgHlh9Oa@linutronix.de>

On Thu, 23 Apr 2026 10:00:56 +0200
Sebastian Andrzej Siewior <bigeasy@linutronix.de> wrote:

Hi Sebastian,

thanks for the review, and to Simon and Justin as well.


> On 2026-04-21 11:47:35 [+0200], Andrea Mayer wrote:
> >
> > [snip]
> 
> So the dst passed to skb_dst_set_noref() has no reference count. The fix
> is to use skb_dst_force() to increment the refcount on it. But this
> requires that we are in the same RCU section. And I guess we are since
> none of the warnings are visible.
 
Yes. lwtunnel_input() holds rcu_read_lock() around ops->input(), which is
where seg6_input_core()/rpl_input() execute. The skb_dst_force() is called
within that RCU section.
 

> Doesn't this make ip6_route_input() on RT fragile in general due to the
> RT6_LOOKUP_F_DST_NOREF usage or here something special about the two
> files that are patched?
> Based on your explanation it all makes sense, I am just not sure if this
> race is limited to those two are if there is more to it.

seg6_input_core() and rpl_input() cache the dst via dst_cache_set_ip6(), which
invokes dst_hold(). The dst_hold() calls rcuref_get(), failing on a zero
refcount and triggering a WARN, but the pointer is still stored in the cache.
After the RCU grace period completes the dst is freed, and a subsequent
dst_cache_get() returns a dangling pointer.
 
The other callers of ip6_route_input() (e.g., ipv6_srh_rcv, ipv6_rpl_srh_rcv,
ip6_rcv_finish_core) consume the NOREF dst without caching it. Even if the
pcpu_rt's refcount is concurrently dropped to zero, the dst memory remains
valid because dst_release() defers the actual free via call_rcu_hurry() and the
caller is still inside the RCU read-side critical section.


> > [snip]
> >
> > Fixes: af4a2209b134 ("ipv6: sr: use dst_cache in seg6_input")
> > Fixes: a7a29f9c361f ("net: ipv6: add rpl sr tunnel")
> 
> If having PREEMPT_RT_NEEDS_BH_LOCK unset is the requirement then the
> right fixes: would be
> Fixes: 3253cb49cbad4 ("softirq: Allow to drop the softirq-BKL lock on PREEMPT_RT")
> 
> as prior this commit the race is not possible, right?

I built and tested kernels at 3253cb49cbad and its parent fd4e876f59b7 (both
CONFIG_PREEMPT_RT=y, without the fix): no issues at fd4e876f59b7.
At 3253cb49cbad, a pcpu_rt cmpxchg contention in rt6_make_pcpu_route() shows
up, which was addressed in 1adaea51c61b. I also tested at 1adaea51c61b, and at
that point the dst_hold() race described in this patch appears.
 
The seg6/rpl code obtains a NOREF dst from ip6_route_input(), does not promote
it via skb_dst_force(), and passes it to dst_cache_set_ip6() which calls
dst_hold(). This pattern has been present since af4a2209b134 and a7a29f9c361f,
and the current Fixes: tags point to the commits where it was introduced.
Does that seem reasonable?


> Does this mean that rpl_input() does a local_bh_disable() while
> obtaining the dst but it never runs outside of bh-disabled section?
> Because if it can run in preemptible context then it would not be to
> PREEMPT_RT at which point the Fixes: tags from above would make sense
> again.
> 

rpl_input() and seg6_input_core() run in softirq context via lwtunnel_input().
They do local_bh_disable() around dst_cache_get() and dst_cache_set_ip6(), but
not around ip6_route_input(). The race window is between ip6_route_input()
returning and dst_cache_set_ip6().
 
> Sebastian

Ciao,
Andrea

^ permalink raw reply

* Re: [PATCH net] net: airoha: Do not read uninitialized fragment address in airoha_dev_xmit()
From: Lorenzo Bianconi @ 2026-04-25 14:10 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Simon Horman, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260424-airoha-xmit-fix-read-frag-v1-1-fdc0a83c79e8@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 3356 bytes --]

> The transmit loop in airoha_dev_xmit() reads fragment address and length
> during its final iteration, when the loop index equals
> skb_shinfo(skb)->nr_frags, at which point the fragment data is
> uninitialized. While these values are never consumed, the read itself is
> unsafe and may trigger a page fault. Fix this by avoiding the fragment
> read on the last iteration.
> Additionally, move the skb pointer from the first to the last used packet
> descriptor, so that airoha_qdma_tx_napi_poll() defers freeing the skb
> until the final descriptor is processed.
> 
> Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
>  drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 2bb0a3ff9810..d3a841908c82 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1997,8 +1997,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  	struct netdev_queue *txq;
>  	struct airoha_queue *q;
>  	LIST_HEAD(tx_list);
> +	int i = 0, qid;
>  	void *data;
> -	int i, qid;
>  	u16 index;
>  	u8 fport;
>  
> @@ -2057,7 +2057,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  			     list);
>  	index = e - q->entry;
>  
> -	for (i = 0; i < nr_frags; i++) {
> +	while (true) {
>  		struct airoha_qdma_desc *desc = &q->desc[index];
>  		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
>  		dma_addr_t addr;
> @@ -2069,7 +2069,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  			goto error_unmap;
>  
>  		list_move_tail(&e->list, &tx_list);
> -		e->skb = i ? NULL : skb;
> +		e->skb = i == nr_frags - 1 ? skb : NULL;
>  		e->dma_addr = addr;
>  		e->dma_len = len;
>  
> @@ -2088,6 +2088,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>  		WRITE_ONCE(desc->msg1, cpu_to_le32(msg1));
>  		WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff));
>  
> +		if (++i == nr_frags)
> +			break;
> +
>  		data = skb_frag_address(frag);
>  		len = skb_frag_size(frag);
>  	}
> 
> ---
> base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
> change-id: 20260423-airoha-xmit-fix-read-frag-dc6aa001ca4b
> 
> Best regards,
> -- 
> Lorenzo Bianconi <lorenzo@kernel.org>
> 

Commenting on Sashiko reported issues:
https://sashiko.dev/#/patchset/20260424-airoha-xmit-fix-read-frag-v1-1-fdc0a83c79e8%40kernel.org

- Does the TSO checksum calculation earlier in this function ensure the
  TCP header is in the linear portion of the SKB?
  This issue is not related to the current patch. Moreover, can we have a TSO
  packet where the tcp header is not in the linear area of the skb?

- If dma_map_single() fails partway through a multi-fragment packet and
  triggers this goto error_unmap, will it break the Tx ring contiguity?
  This issue is not related to the current patch. Moreover, I guess the hw is
  capable of managing out-of-order descriptors.

- Is it safe to map fragment data using dma_map_single() instead of
  skb_frag_dma_map()?
  This issue is not related to the current patch. I will post a dedicated patch
  for it.

Regards,
Lorenzo

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* RE: [PATCH v4 net 3/3] net: hns3: fix CWR handling in drivers to preserve ACE signal
From: Chia-Yu Chang (Nokia) @ 2026-04-25 14:30 UTC (permalink / raw)
  To: Jijie Shao, linyunsheng@huawei.com, andrew+netdev@lunn.ch,
	parav@nvidia.com, jasowang@redhat.com, mst@redhat.com,
	shenjian15@huawei.com, salil.mehta@huawei.com, saeedm@nvidia.com,
	tariqt@nvidia.com, mbloch@nvidia.com, leonro@nvidia.com,
	linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, ij@kernel.org,
	ncardwell@google.com, Koen De Schepper (Nokia),
	g.white@cablelabs.com, ingemar.s.johansson@ericsson.com,
	mirja.kuehlewind@ericsson.com, cheshire@apple.com, rs.ietf@gmx.at,
	Jason_Livingood@comcast.com, vidhi_goel@apple.com
In-Reply-To: <6ae96ead-61b3-470a-a30b-3418350a45f0@huawei.com>

> -----Original Message-----
> From: Jijie Shao <shaojijie@huawei.com> 
> Sent: Saturday, April 25, 2026 11:35 AM
> To: Chia-Yu Chang (Nokia) <chia-yu.chang@nokia-bell-labs.com>; linyunsheng@huawei.com; andrew+netdev@lunn.ch; parav@nvidia.com; jasowang@redhat.com; mst@redhat.com; shenjian15@huawei.com; salil.mehta@huawei.com; saeedm@nvidia.com; tariqt@nvidia.com; mbloch@nvidia.com; leonro@nvidia.com; linux-rdma@vger.kernel.org; netdev@vger.kernel.org; davem@davemloft.net; edumazet@google.com; kuba@kernel.org; pabeni@redhat.com; horms@kernel.org; ij@kernel.org; ncardwell@google.com; Koen De Schepper (Nokia) <koen.de_schepper@nokia-bell-labs.com>; g.white@cablelabs.com; ingemar.s.johansson@ericsson.com; mirja.kuehlewind@ericsson.com; cheshire@apple.com; rs.ietf@gmx.at; Jason_Livingood@comcast.com; vidhi_goel@apple.com
> Cc: shaojijie@huawei.com
> Subject: Re: [PATCH v4 net 3/3] net: hns3: fix CWR handling in drivers to preserve ACE signal
> 
> 
> on 2026/4/17 23:26, chia-yu.chang@nokia-bell-labs.com wrote:
> > From: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
> >
> > Currently, hns3 Rx paths use SKB_GSO_TCP_ECN flag when a TCP segment 
> > with the CWR flag set. This is wrong because SKB_GSO_TCP_ECN is only 
> > valid for RFC3168 ECN on Tx, and using it on Rx allows RFC3168 ECN 
> > offload to clear the CWR flag. As a result, incoming TCP segments lose 
> > their ACE signal integrity required for AccECN (RFC9768), especially 
> > when the packet is forwarded and later re-segmented by GSO.
> >
> > Fix this by setting SKB_GSO_TCP_ACCECN for any Rx segment with the CWR 
> > flag set. SKB_GSO_TCP_ACCECN ensure that RFC3168 ECN offload will not 
> > clear the CWR flag, therefore preserving the ACE signal.
> >
> > Fixes: d474d88f88261 ("net: hns3: add hns3_gro_complete for HW GRO 
> > process")
> > Signed-off-by: Chia-Yu Chang <chia-yu.chang@nokia-bell-labs.com>
> > ---
> >   drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c 
> > b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> > index a3206c97923e..e1b0dba56182 100644
> > --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
> > @@ -3904,7 +3904,7 @@ static int hns3_gro_complete(struct sk_buff 
> > *skb, u32 l234info)
> >   
> >   	skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
> >   	if (th->cwr)
> > -		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
> > +		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ACCECN;
> >   
> >   	if (l234info & BIT(HNS3_RXD_GRO_FIXID_B))
> >   		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID;
> 
> I agree with Paolo's previous point;
> for already released hardware, it is indeed not suitable to modify it.
> During the hardware aggregation process, the ACE signal may have already been lost.
> 
> Jijie Shao

Hi Jijie,

I would disagree with not fixing on released hardware. (Did Paolo explicit mention that?)
The ACCECN protocol is based on ACE signal, and a broken ACE signal might be due to SKB_GSO_TCP_ECN at the RX path.
You can see the explicit explanations and examples in the commit message.
There is already a fix in patch 4e4f7cefb130af6aba6a393b2d13930b49390df9 for tcp_gro_receive() of tcp_offload.c

And In this patch series, we would like to propose the similar fix on hns3 and mlx5e.
While one main issue is to confirm is how the GRO is done in the corresponding HW-GRO.
And if the driver can be safely changed from SKB_GSO_TCP_ECN to SKB_GSO_TCP_ACCECN, then we can ensure ECN and AccECN can be supported over existing hardware.

Thanks!
Chia-Yu

^ permalink raw reply

* Re: [PATCH net 1/1] batman-adv: stop tp_meter sessions during mesh teardown
From: Sven Eckelmann @ 2026-04-25 14:22 UTC (permalink / raw)
  To: Ren Wei
  Cc: b.a.t.m.a.n, netdev, marek.lindner, sw, antonio, sven, davem,
	edumazet, kuba, pabeni, horms, yuantan098, yifanwucs,
	tomapufckgml, bird, tr0jan, wangjiexun2025
In-Reply-To: <80ccaa2c7ce0f72c4555b039217834386282aa0e.1776998957.git.wangjiexun2025@gmail.com>

On Sat, 25 Apr 2026 20:59:16 +0800, Ren Wei <n05ec@lzu.edu.cn> wrote:
> [...]
> Reported-by: Juefei Pu <tomapufckgml@gmail.com>
> Reported-by: Xin Liu <bird@lzu.edu.cn>
> Co-developed-by: Luxing Yin <tr0jan@lzu.edu.cn>
> Signed-off-by: Luxing Yin <tr0jan@lzu.edu.cn>
> Signed-off-by: Jiexun Wang <wangjiexun2025@gmail.com>
> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>

Thanks. I have some minor notes about the patch:

>
>
> diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
> index 2e42f6b3..028cd4e0 100644
> --- a/net/batman-adv/tp_meter.c
> +++ b/net/batman-adv/tp_meter.c
> @@ -947,6 +964,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
>  
>  	/* look for an already existing test towards this node */
>  	spin_lock_bh(&bat_priv->tp_list_lock);
> +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
> +		spin_unlock_bh(&bat_priv->tp_list_lock);
> +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
> +					      dst, bat_priv, session_cookie);
> +		return;
> +	}
> +
>  	tp_vars = batadv_tp_list_find(bat_priv, dst);
>  	if (tp_vars) {
>  		spin_unlock_bh(&bat_priv->tp_list_lock);

Hm, this looks a little bit out of place. Maybe split it in a patch for
handling the starting part (this) and the rest (the shutdown handling).

> @@ -966,7 +990,6 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
>  					      bat_priv, session_cookie);
>  		return;
>  	}
> -
>  	tp_vars = kmalloc_obj(*tp_vars, GFP_ATOMIC);
>  	if (!tp_vars) {
>  		spin_unlock_bh(&bat_priv->tp_list_lock);

Why was this changed?

> @@ -1342,7 +1362,6 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv,
>  			   "Meter: too many ongoing sessions, aborting (RECV)\n");
>  		goto out_unlock;
>  	}
> -
>  	tp_vars = kmalloc_obj(*tp_vars, GFP_ATOMIC);
>  	if (!tp_vars)
>  		goto out_unlock;

Why was this changed?

> @@ -1478,9 +1500,57 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
> [ ... skip 12 lines ... ]
> +void batadv_tp_stop_all(struct batadv_priv *bat_priv)
> +{
> +	struct batadv_tp_vars *tp_vars[BATADV_TP_MAX_NUM];
> +	struct batadv_tp_vars *tp_var;
> +	int count = 0;
> +	int i;

size_t count = 0;
size_t i;

-- 
Sven Eckelmann <sven@narfation.org>

^ permalink raw reply

* [PATCH net 1/1] openvswitch: reject oversized NSH MD2 metadata in push_nsh
From: Ren Wei @ 2026-04-25 16:40 UTC (permalink / raw)
  To: netdev, dev
  Cc: aconole, echaudro, i.maximets, davem, edumazet, kuba, pabeni,
	horms, jbenc, e, yi.y.yang, pshelar, yuantan098, yifanwucs,
	tomapufckgml, bird, ldy3087146292, n05ec
In-Reply-To: <cover.1776929256.git.ldy3087146292@gmail.com>

From: Douya Le <ldy3087146292@gmail.com>

The NSH header length is encoded in 4-byte words in a 6-bit field.
The current push_nsh validation only checks the MD2 payload against
NSH_CTX_HDRS_MAX_LEN, which still allows metadata sizes that cannot be
represented once the base header is included.

Reject MD2 metadata lengths whose total NSH header size cannot be
encoded exactly in the NSH length field, whether because the field
would wrap or because the length is not a multiple of 4 bytes.

Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
 net/openvswitch/flow_netlink.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 13052408a132..8a1ae5309c2c 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1432,7 +1432,13 @@ static int nsh_key_put_from_nlattr(const struct nlattr *attr,
 
 			has_md2 = true;
 			mdlen = nla_len(a);
-			if (mdlen > NSH_CTX_HDRS_MAX_LEN || mdlen <= 0) {
+			/* The NSH length field stores the total header size
+			 * in 4-byte words in 6 bits. Reject MD2 metadata
+			 * lengths that cannot be encoded exactly or would
+			 * make the length field wrap.
+			 */
+			if (mdlen <= 0 || !IS_ALIGNED(mdlen, 4) ||
+			    NSH_BASE_HDR_LEN + mdlen > (NSH_LEN_MASK << 2)) {
 				OVS_NLERR(
 				    log,
 				    "Invalid MD length %d for MD type %d",
-- 
2.43.0


^ permalink raw reply related


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