* Re: [PATCH v2] selftests: net: broadcast_pmtu: Fix false failure from incorrect ping exit code logic
From: Jakub Kicinski @ 2026-03-26 14:58 UTC (permalink / raw)
To: fffsqian
Cc: davem, edumazet, pabeni, horms, shuah, netdev, linux-kselftest,
linux-kernel, Qingshuang Fu
In-Reply-To: <20260326094219.2160239-1-fffsqian@163.com>
On Thu, 26 Mar 2026 17:42:19 +0800 fffsqian@163.com wrote:
> The broadcast_pmtu.sh test verifies that broadcast route MTU is respected,
> but it uses an incorrect criteria for test success: it relies solely on
> the ping command's exit code, which leads to false failures.
Still failing, does it pass for you?
Also please read this -
https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#tl-dr
^ permalink raw reply
* Re: [PATCH net-next] net: add sysctl to toggle napi_consume_skb() alien skb defer
From: Eric Dumazet @ 2026-03-26 14:55 UTC (permalink / raw)
To: Jason Xing; +Cc: davem, kuba, pabeni, horms, netdev
In-Reply-To: <20260326144249.97213-1-kerneljasonxing@gmail.com>
On Thu, Mar 26, 2026 at 7:43 AM Jason Xing <kerneljasonxing@gmail.com> wrote:
>
> Commit e20dfbad8aab ("net: fix napi_consume_skb() with alien skbs")
> defers freeing of alien SKBs (alloc_cpu != current cpu) via
> skb_attempt_defer_free() on the TX completion path to reduce cross-NUMA
> SLUB spinlock contention to improve multi-queue UDP workloads.
>
> However, this unconditionally impacts the napi_skb_cache fast recycle
> path for single-flow / few-flow workloads (e.g. AF_XDP benchmarks[1]):
> when the TX completion NAPI CPU differs from the SKB allocation CPU,
> SKBs are deferred instead of being returned to the local napi_skb_cache,
> forcing RX allocations back to the slow slab path.
>
> The existing net.core.skb_defer_max=0 could disable this, but it is a
> global switch that also disables the defer mechanism in TCP/UDP/MPTCP
> recvmsg paths, losing its positive SLUB locality benefits there. AF_XDP
> can co-exist with other protocols. That's the reason why I gave up
> reusing skb_defer_disable_key. Besides, if the defer path is disabled,
> that means TCP/UDP/MPTCP in process path will trigger directly freeing
> skb with enabling/disabling bottom half(in kfree_skb_napi_cache())
> which could affect others. So my thinking is not to touch this path.
>
> Add a dedicated sysctl net.core.napi_consume_skb_defer backed by a
> static key to selectively control the alien skb defer feature. Let
> users decide which is the best fit for their own requirements.
>
> This patch also avoids touching local_bh* pair(in
> kfree_skb_napi_cache())
> to minimize the overhead.
>
> [1]: taskset -c 0 ./xdpsock -i enp2s0f1 -q 1 -t -S -s 64
> 1) sysctl -w net.core.napi_consume_skb_defer=1 (as default)
> sock0@enp2s0f1:1 txonly xdp-skb
> pps pkts 1.00
> rx 0 0
> tx 1,851,950 20,397,952
>
> 2)sysctl -w net.core.napi_consume_skb_defer=0
> sock0@enp2s0f1:1 txonly xdp-skb
> pps pkts 1.00
> rx 0 0
> tx 1,985,067 25,530,432
>
> For AF_XDP scenario, it turns out to be around 6.6% improvement.
>
> Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
> ---
> net/core/net-sysfs.h | 1 +
> net/core/skbuff.c | 5 ++++-
> net/core/sysctl_net_core.c | 35 +++++++++++++++++++++++++++++++++++
> 3 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h
> index 38e2e3ffd0bd..a026f757867e 100644
> --- a/net/core/net-sysfs.h
> +++ b/net/core/net-sysfs.h
> @@ -14,4 +14,5 @@ int netdev_change_owner(struct net_device *, const struct net *net_old,
> extern struct mutex rps_default_mask_mutex;
>
> DECLARE_STATIC_KEY_FALSE(skb_defer_disable_key);
> +DECLARE_STATIC_KEY_TRUE(napi_consume_skb_defer_key);
> #endif
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 3d6978dd0aa8..3db90a9aa61d 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -94,6 +94,7 @@
>
> #include "dev.h"
> #include "devmem.h"
> +#include "net-sysfs.h"
> #include "netmem_priv.h"
> #include "sock_destructor.h"
>
> @@ -1519,7 +1520,8 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
>
> DEBUG_NET_WARN_ON_ONCE(!in_softirq());
>
> - if (skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
> + if (static_branch_likely(&napi_consume_skb_defer_key) &&
> + skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
> skb_release_head_state(skb);
> return skb_attempt_defer_free(skb);
> }
> @@ -7257,6 +7259,7 @@ static void kfree_skb_napi_cache(struct sk_buff *skb)
> }
>
> DEFINE_STATIC_KEY_FALSE(skb_defer_disable_key);
> +DEFINE_STATIC_KEY_TRUE(napi_consume_skb_defer_key);
>
> /**
> * skb_attempt_defer_free - queue skb for remote freeing
> diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
> index b508618bfc12..33e8217ee1ce 100644
> --- a/net/core/sysctl_net_core.c
> +++ b/net/core/sysctl_net_core.c
> @@ -372,6 +372,35 @@ static int proc_do_skb_defer_max(const struct ctl_table *table, int write,
> return ret;
> }
>
> +static int proc_do_napi_consume_skb_defer(const struct ctl_table *table,
> + int write, void *buffer,
> + size_t *lenp, loff_t *ppos)
> +{
> + static DEFINE_MUTEX(napi_consume_skb_defer_mutex);
> + int val, ret;
> +
> + mutex_lock(&napi_consume_skb_defer_mutex);
> +
> + val = static_key_enabled(&napi_consume_skb_defer_key);
> + struct ctl_table tmp = {
> + .data = &val,
> + .maxlen = sizeof(val),
> + .extra1 = SYSCTL_ZERO,
> + .extra2 = SYSCTL_ONE,
> + };
> +
> + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
> + if (!ret && write) {
> + if (val)
> + static_branch_enable(&napi_consume_skb_defer_key);
> + else
> + static_branch_disable(&napi_consume_skb_defer_key);
> + }
> +
> + mutex_unlock(&napi_consume_skb_defer_mutex);
> + return ret;
> +}
> +
Seems a copy/paste of proc_do_static_key() ?
^ permalink raw reply
* Re: [PATCH net-next v5] net: pppoe: implement GRO/GSO support
From: Xin Long @ 2026-03-26 14:43 UTC (permalink / raw)
To: Qingfang Deng
Cc: Jakub Kicinski, Felix Fietkau, linux-ppp, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni, David Ahern,
Simon Horman, netdev, linux-kernel, Richard Gobert
In-Reply-To: <CADvbK_fj_26MLP=+U+rzOMfqdPpdvFQJgN_fozd2uAjRsfHweQ@mail.gmail.com>
On Thu, Mar 26, 2026 at 10:43 AM Xin Long <lucien.xin@gmail.com> wrote:
>
> On Wed, Mar 25, 2026 at 10:43 PM Qingfang Deng <dqfext@gmail.com> wrote:
> >
> > Hi all,
> >
> > In some cases (such as BIG TCP) a GRO skb length can overflow a u16,
> > then what should I do with the u16 length field here?
>
> I think you can either add a check in pppoe_gro_complete() to ensure
sorry, I meant add a check in pppoe_gro_receive().
> the aggregated size does not exceed U16_MAX, avoiding BIG TCP
> behavior; Or, set phdr->length to 0 and rely on skb->len to determine
> the actual length, as done in BIG TCP itself.
^ permalink raw reply
* [PATCH net-next] net: add sysctl to toggle napi_consume_skb() alien skb defer
From: Jason Xing @ 2026-03-26 14:42 UTC (permalink / raw)
To: davem, edumazet, kuba, pabeni, horms; +Cc: netdev, Jason Xing
Commit e20dfbad8aab ("net: fix napi_consume_skb() with alien skbs")
defers freeing of alien SKBs (alloc_cpu != current cpu) via
skb_attempt_defer_free() on the TX completion path to reduce cross-NUMA
SLUB spinlock contention to improve multi-queue UDP workloads.
However, this unconditionally impacts the napi_skb_cache fast recycle
path for single-flow / few-flow workloads (e.g. AF_XDP benchmarks[1]):
when the TX completion NAPI CPU differs from the SKB allocation CPU,
SKBs are deferred instead of being returned to the local napi_skb_cache,
forcing RX allocations back to the slow slab path.
The existing net.core.skb_defer_max=0 could disable this, but it is a
global switch that also disables the defer mechanism in TCP/UDP/MPTCP
recvmsg paths, losing its positive SLUB locality benefits there. AF_XDP
can co-exist with other protocols. That's the reason why I gave up
reusing skb_defer_disable_key. Besides, if the defer path is disabled,
that means TCP/UDP/MPTCP in process path will trigger directly freeing
skb with enabling/disabling bottom half(in kfree_skb_napi_cache())
which could affect others. So my thinking is not to touch this path.
Add a dedicated sysctl net.core.napi_consume_skb_defer backed by a
static key to selectively control the alien skb defer feature. Let
users decide which is the best fit for their own requirements.
This patch also avoids touching local_bh* pair(in
kfree_skb_napi_cache())
to minimize the overhead.
[1]: taskset -c 0 ./xdpsock -i enp2s0f1 -q 1 -t -S -s 64
1) sysctl -w net.core.napi_consume_skb_defer=1 (as default)
sock0@enp2s0f1:1 txonly xdp-skb
pps pkts 1.00
rx 0 0
tx 1,851,950 20,397,952
2)sysctl -w net.core.napi_consume_skb_defer=0
sock0@enp2s0f1:1 txonly xdp-skb
pps pkts 1.00
rx 0 0
tx 1,985,067 25,530,432
For AF_XDP scenario, it turns out to be around 6.6% improvement.
Signed-off-by: Jason Xing <kerneljasonxing@gmail.com>
---
net/core/net-sysfs.h | 1 +
net/core/skbuff.c | 5 ++++-
net/core/sysctl_net_core.c | 35 +++++++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h
index 38e2e3ffd0bd..a026f757867e 100644
--- a/net/core/net-sysfs.h
+++ b/net/core/net-sysfs.h
@@ -14,4 +14,5 @@ int netdev_change_owner(struct net_device *, const struct net *net_old,
extern struct mutex rps_default_mask_mutex;
DECLARE_STATIC_KEY_FALSE(skb_defer_disable_key);
+DECLARE_STATIC_KEY_TRUE(napi_consume_skb_defer_key);
#endif
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3d6978dd0aa8..3db90a9aa61d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -94,6 +94,7 @@
#include "dev.h"
#include "devmem.h"
+#include "net-sysfs.h"
#include "netmem_priv.h"
#include "sock_destructor.h"
@@ -1519,7 +1520,8 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
- if (skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
+ if (static_branch_likely(&napi_consume_skb_defer_key) &&
+ skb->alloc_cpu != smp_processor_id() && !skb_shared(skb)) {
skb_release_head_state(skb);
return skb_attempt_defer_free(skb);
}
@@ -7257,6 +7259,7 @@ static void kfree_skb_napi_cache(struct sk_buff *skb)
}
DEFINE_STATIC_KEY_FALSE(skb_defer_disable_key);
+DEFINE_STATIC_KEY_TRUE(napi_consume_skb_defer_key);
/**
* skb_attempt_defer_free - queue skb for remote freeing
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index b508618bfc12..33e8217ee1ce 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -372,6 +372,35 @@ static int proc_do_skb_defer_max(const struct ctl_table *table, int write,
return ret;
}
+static int proc_do_napi_consume_skb_defer(const struct ctl_table *table,
+ int write, void *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ static DEFINE_MUTEX(napi_consume_skb_defer_mutex);
+ int val, ret;
+
+ mutex_lock(&napi_consume_skb_defer_mutex);
+
+ val = static_key_enabled(&napi_consume_skb_defer_key);
+ struct ctl_table tmp = {
+ .data = &val,
+ .maxlen = sizeof(val),
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ };
+
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+ if (!ret && write) {
+ if (val)
+ static_branch_enable(&napi_consume_skb_defer_key);
+ else
+ static_branch_disable(&napi_consume_skb_defer_key);
+ }
+
+ mutex_unlock(&napi_consume_skb_defer_mutex);
+ return ret;
+}
+
#ifdef CONFIG_BPF_JIT
static int proc_dointvec_minmax_bpf_enable(const struct ctl_table *table, int write,
void *buffer, size_t *lenp,
@@ -676,6 +705,12 @@ static struct ctl_table net_core_table[] = {
.proc_handler = proc_do_skb_defer_max,
.extra1 = SYSCTL_ZERO,
},
+ {
+ .procname = "napi_consume_skb_defer",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_do_napi_consume_skb_defer,
+ },
};
static struct ctl_table netns_core_table[] = {
--
2.41.3
^ permalink raw reply related
* Re: [PATCH net-next v5] net: pppoe: implement GRO/GSO support
From: Xin Long @ 2026-03-26 14:43 UTC (permalink / raw)
To: Qingfang Deng
Cc: Jakub Kicinski, Felix Fietkau, linux-ppp, Andrew Lunn,
David S. Miller, Eric Dumazet, Paolo Abeni, David Ahern,
Simon Horman, netdev, linux-kernel, Richard Gobert
In-Reply-To: <CALW65jZRyKydW6bs-mYwh2mEn0dpv3opVEr=WczKn_0952_+Yg@mail.gmail.com>
On Wed, Mar 25, 2026 at 10:43 PM Qingfang Deng <dqfext@gmail.com> wrote:
>
> Hi all,
>
> In some cases (such as BIG TCP) a GRO skb length can overflow a u16,
> then what should I do with the u16 length field here?
I think you can either add a check in pppoe_gro_complete() to ensure
the aggregated size does not exceed U16_MAX, avoiding BIG TCP
behavior; Or, set phdr->length to 0 and rely on skb->len to determine
the actual length, as done in BIG TCP itself.
^ permalink raw reply
* Re: [PATCH net-next v1 4/4] net: hsr: reject unresolved interlink ifindex
From: Felix Maurer @ 2026-03-26 14:30 UTC (permalink / raw)
To: luka.gejak
Cc: davem, edumazet, kuba, pabeni, netdev, horms, liuhangbin, bigeasy,
linux-kernel
In-Reply-To: <20260324143503.187642-5-luka.gejak@linux.dev>
On Tue, Mar 24, 2026 at 03:35:03PM +0100, luka.gejak@linux.dev wrote:
> From: Luka Gejak <luka.gejak@linux.dev>
>
> In hsr_newlink(), a provided but invalid IFLA_HSR_INTERLINK attribute
> was silently ignored if __dev_get_by_index() returned NULL. This leads
> to incorrect RedBox topology creation without notifying the user.
Not really incorrect, it's just not a RedBox at all.
> Fix this by returning -EINVAL and an extack message when the
> interlink attribute is present but cannot be resolved.
>
> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
Reviewed-by: Felix Maurer <fmaurer@redhat.com>
> ---
> net/hsr/hsr_netlink.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
> index db0b0af7a692..f0ca23da3ab9 100644
> --- a/net/hsr/hsr_netlink.c
> +++ b/net/hsr/hsr_netlink.c
> @@ -76,9 +76,14 @@ static int hsr_newlink(struct net_device *dev,
> return -EINVAL;
> }
>
> - if (data[IFLA_HSR_INTERLINK])
> + if (data[IFLA_HSR_INTERLINK]) {
> interlink = __dev_get_by_index(link_net,
> nla_get_u32(data[IFLA_HSR_INTERLINK]));
> + if (!interlink) {
> + NL_SET_ERR_MSG_MOD(extack, "Interlink does not exist");
> + return -EINVAL;
> + }
> + }
>
> if (interlink && interlink == link[0]) {
> NL_SET_ERR_MSG_MOD(extack, "Interlink and Slave1 are the same");
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH net-next v1 3/4] net: hsr: require valid EOT supervision TLV
From: Felix Maurer @ 2026-03-26 14:29 UTC (permalink / raw)
To: luka.gejak
Cc: davem, edumazet, kuba, pabeni, netdev, horms, liuhangbin, bigeasy,
linux-kernel
In-Reply-To: <20260324143503.187642-4-luka.gejak@linux.dev>
On Tue, Mar 24, 2026 at 03:35:02PM +0100, luka.gejak@linux.dev wrote:
> From: Luka Gejak <luka.gejak@linux.dev>
>
> Supervision frames are only valid if terminated with a zero-length EOT
> TLV. The current check fails to reject non-EOT entries as the terminal
> TLV, potentially allowing malformed supervision traffic.
>
> Fix this by strictly requiring the terminal TLV to be HSR_TLV_EOT
> with a length of zero.
>
> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
Reviewed-by: Felix Maurer <fmaurer@redhat.com>
> ---
> net/hsr/hsr_forward.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
> index aefc9b6936ba..d26c7d0e8109 100644
> --- a/net/hsr/hsr_forward.c
> +++ b/net/hsr/hsr_forward.c
> @@ -110,7 +110,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
> }
>
> /* end of tlvs must follow at the end */
> - if (hsr_sup_tlv->HSR_TLV_type == HSR_TLV_EOT &&
> + if (hsr_sup_tlv->HSR_TLV_type != HSR_TLV_EOT ||
> hsr_sup_tlv->HSR_TLV_length != 0)
> return false;
>
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH net-next v1 2/4] net: hsr: fix VLAN add unwind on slave errors
From: Felix Maurer @ 2026-03-26 14:29 UTC (permalink / raw)
To: luka.gejak
Cc: davem, edumazet, kuba, pabeni, netdev, horms, liuhangbin, bigeasy,
linux-kernel
In-Reply-To: <20260324143503.187642-3-luka.gejak@linux.dev>
On Tue, Mar 24, 2026 at 03:35:01PM +0100, luka.gejak@linux.dev wrote:
> From: Luka Gejak <luka.gejak@linux.dev>
>
> When vlan_vid_add() fails for a secondary slave, the error path calls
> vlan_vid_del() on the failing port instead of the peer slave that had
> already succeeded. This results in asymmetric VLAN state across the HSR
> pair.
>
> Fix this by ensuring the cleanup path targets the previously
> programmed slave device when the second slave fails to add the VID.
The cross-dev cleanup is already complex enough and I don't think this
makes it much better. How about having a central cleanup at the end that
cleans whatever ports have the VID added?
> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
> ---
> net/hsr/hsr_device.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
> index 5c3eca2235ce..6185f9f2630f 100644
> --- a/net/hsr/hsr_device.c
> +++ b/net/hsr/hsr_device.c
> @@ -534,6 +534,8 @@ static int hsr_ndo_vlan_rx_add_vid(struct net_device *dev,
> {
> bool is_slave_a_added = false;
> bool is_slave_b_added = false;
> + struct net_device *slave_a_dev = NULL;
> + struct net_device *slave_b_dev = NULL;
No matter if my previous comment, the is_slave_{a,b}_added bools are not
necessary with your changes but just duplicate state. Testing
slave_{a,b}_dev == NULL serves the same purpose.
> struct hsr_port *port;
> struct hsr_priv *hsr;
> int ret = 0;
> @@ -552,11 +554,12 @@ static int hsr_ndo_vlan_rx_add_vid(struct net_device *dev,
> /* clean up Slave-B */
> netdev_err(dev, "add vid failed for Slave-A\n");
> if (is_slave_b_added)
> - vlan_vid_del(port->dev, proto, vid);
> + vlan_vid_del(slave_b_dev, proto, vid);
> return ret;
> }
>
> is_slave_a_added = true;
> + slave_a_dev = port->dev;
> break;
>
> case HSR_PT_SLAVE_B:
> @@ -564,11 +567,12 @@ static int hsr_ndo_vlan_rx_add_vid(struct net_device *dev,
> /* clean up Slave-A */
> netdev_err(dev, "add vid failed for Slave-B\n");
> if (is_slave_a_added)
> - vlan_vid_del(port->dev, proto, vid);
> + vlan_vid_del(slave_a_dev, proto, vid);
> return ret;
> }
>
> is_slave_b_added = true;
> + slave_b_dev = port->dev;
> break;
> default:
> break;
> --
> 2.53.0
>
^ permalink raw reply
* Re: [PATCH net-next v1 1/4] net: hsr: serialize seq_blocks merge across nodes
From: Felix Maurer @ 2026-03-26 14:28 UTC (permalink / raw)
To: luka.gejak
Cc: davem, edumazet, kuba, pabeni, netdev, horms, liuhangbin, bigeasy,
linux-kernel
In-Reply-To: <20260324143503.187642-2-luka.gejak@linux.dev>
On Tue, Mar 24, 2026 at 03:35:00PM +0100, luka.gejak@linux.dev wrote:
> From: Luka Gejak <luka.gejak@linux.dev>
>
> During node merging, hsr_handle_sup_frame() walks node_curr->seq_blocks
> to update node_real without holding node_curr->seq_out_lock. This
> allows concurrent mutations from duplicate registration paths, risking
> inconsistent state or XArray/bitmap corruption.
I'm not sure if I see "duplicate registration" happening (without a more
serious problem in the network).
> Fix this by locking both nodes' seq_out_lock during the merge.
> To prevent ABBA deadlocks, locks are acquired in order of memory
> address.
But I agree that this is probably a good idea, as long as the node with
wrong macaddressA is still in the node table and might still see updates
in the sequence number tracking because we can still receive traffic for
it. I originally didn't consider this to be too bad, but if a block is
reused we could be dropping some valid packets.
Reviewed-by: Felix Maurer <fmaurer@redhat.com>
> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
> ---
> net/hsr/hsr_framereg.c | 38 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
> index 577fb588bc2f..d09875b33588 100644
> --- a/net/hsr/hsr_framereg.c
> +++ b/net/hsr/hsr_framereg.c
> @@ -123,6 +123,40 @@ static void hsr_free_node_rcu(struct rcu_head *rn)
> hsr_free_node(node);
> }
>
> +static void hsr_lock_seq_out_pair(struct hsr_node *node_a,
> + struct hsr_node *node_b)
> +{
> + if (node_a == node_b) {
> + spin_lock_bh(&node_a->seq_out_lock);
> + return;
> + }
> +
> + if (node_a < node_b) {
> + spin_lock_bh(&node_a->seq_out_lock);
> + spin_lock_nested(&node_b->seq_out_lock, SINGLE_DEPTH_NESTING);
> + } else {
> + spin_lock_bh(&node_b->seq_out_lock);
> + spin_lock_nested(&node_a->seq_out_lock, SINGLE_DEPTH_NESTING);
> + }
> +}
> +
> +static void hsr_unlock_seq_out_pair(struct hsr_node *node_a,
> + struct hsr_node *node_b)
> +{
> + if (node_a == node_b) {
> + spin_unlock_bh(&node_a->seq_out_lock);
> + return;
> + }
> +
> + if (node_a < node_b) {
> + spin_unlock(&node_b->seq_out_lock);
> + spin_unlock_bh(&node_a->seq_out_lock);
> + } else {
> + spin_unlock(&node_a->seq_out_lock);
> + spin_unlock_bh(&node_b->seq_out_lock);
> + }
> +}
> +
> void hsr_del_nodes(struct list_head *node_db)
> {
> struct hsr_node *node;
> @@ -432,7 +466,7 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame)
> }
>
> ether_addr_copy(node_real->macaddress_B, ethhdr->h_source);
> - spin_lock_bh(&node_real->seq_out_lock);
> + hsr_lock_seq_out_pair(node_real, node_curr);
> for (i = 0; i < HSR_PT_PORTS; i++) {
> if (!node_curr->time_in_stale[i] &&
> time_after(node_curr->time_in[i], node_real->time_in[i])) {
> @@ -455,7 +489,7 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame)
> src_blk->seq_nrs[i], HSR_SEQ_BLOCK_SIZE);
> }
> }
> - spin_unlock_bh(&node_real->seq_out_lock);
> + hsr_unlock_seq_out_pair(node_real, node_curr);
> node_real->addr_B_port = port_rcv->type;
>
> spin_lock_bh(&hsr->list_lock);
> --
> 2.53.0
>
^ permalink raw reply
* RE: [Intel-wired-lan] [PATCH iwl-next] ice: call mutex_lock() before mutex_unlock() in ice_dcb_rebuild()
From: Loktionov, Aleksandr @ 2026-03-26 14:26 UTC (permalink / raw)
To: Kitszel, Przemyslaw, Bart Van Assche
Cc: netdev@vger.kernel.org, intel-wired-lan@lists.osuosl.org,
Wieczerzycka, Katarzyna, Nguyen, Anthony L
In-Reply-To: <4b1927b5-2a3c-4465-9181-2e8885afd122@intel.com>
> -----Original Message-----
> From: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>
> Sent: Friday, March 20, 2026 11:13 AM
> To: Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Bart Van
> Assche <bvanassche@acm.org>
> Cc: netdev@vger.kernel.org; intel-wired-lan@lists.osuosl.org;
> Wieczerzycka, Katarzyna <katarzyna.wieczerzycka@intel.com>; Nguyen,
> Anthony L <anthony.l.nguyen@intel.com>
> Subject: Re: [Intel-wired-lan] [PATCH iwl-next] ice: call mutex_lock()
> before mutex_unlock() in ice_dcb_rebuild()
>
> On 3/20/26 06:05, Aleksandr Loktionov wrote:
> > From: Katarzyna Wieczerzycka <katarzyna.wieczerzycka@intel.com>
> >
> > In ice_dcb_rebuild(), the first call to ice_query_port_ets() is
> > checked for error, and on failure jumps to the 'dcb_error' label.
> The
> > error path always calls mutex_unlock(&pf->tc_mutex), but at this
> point
> > in the code the mutex has never been locked -- mutex_lock() came
> after the check.
> >
> > Releasing a mutex that was not locked is undefined behaviour and can
> > cause a deadlock or crash. Fix this by moving mutex_lock() to before
> > the error check, so that 'dcb_error' always pairs with a prior lock.
> >
> > Fixes: 242b5e068b25 ("ice: Fix DCB rebuild after reset")
> > Signed-off-by: Katarzyna Wieczerzycka
> > <katarzyna.wieczerzycka@intel.com>
> > Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
>
> NACK
>
> there is a better fix proposed by community, we are awaiting v2
> https://patchew.org/linux/20260223220102.2158611-1-
> bart.vanassche@linux.dev/20260223220102.2158611-20-
> bart.vanassche@linux.dev/
>
> > ---
> > drivers/net/ethernet/intel/ice/ice_dcb_lib.c | 3 +--
> > 1 file changed, 1 insertion(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> > b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> > index bd77f1c..d516734 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_dcb_lib.c
> > @@ -538,12 +538,11 @@ void ice_dcb_rebuild(struct ice_pf *pf)
> > int ret;
> >
> > ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf),
> > NULL);
>
> the difference is to move mutex_lock() over ice_query_port_ets()
>
> > + mutex_lock(&pf->tc_mutex);
> > if (ret) {
> > dev_err(dev, "Query Port ETS failed\n");
> > goto dcb_error;
> > }
> >
> > - mutex_lock(&pf->tc_mutex);
> > -
> > if (!pf->hw.port_info->qos_cfg.is_sw_lldp)
> > ice_cfg_etsrec_defaults(pf->hw.port_info);
> >
Withdrawing this patch (just in case NACK is not enough).
Bart Van Assche's series covers the same fix with a more complete
approach (moving mutex_lock() above ice_query_port_ets()). His v4
has been reviewed and accepted.
With the best regards
Alex
^ permalink raw reply
* [PATCH net,v5] virtio_net: clamp rss_max_key_size to NETDEV_RSS_KEY_LEN
From: Srujana Challa @ 2026-03-26 14:23 UTC (permalink / raw)
To: netdev, virtualization
Cc: pabeni, mst, jasowang, xuanzhuo, eperezma, davem, edumazet, kuba,
ndabilpuram, kshankar, schalla, stable
rss_max_key_size in the virtio spec is the maximum key size supported by
the device, not a mandatory size the driver must use. Also the value 40
is a spec minimum, not a spec maximum.
The current code rejects RSS and can fail probe when the device reports a
larger rss_max_key_size than the driver buffer limit. Instead, clamp the
effective key length to min(device rss_max_key_size, NETDEV_RSS_KEY_LEN)
and keep RSS enabled.
This keeps probe working on devices that advertise larger maximum key sizes
while respecting the netdev RSS key buffer size limit.
Fixes: 3f7d9c1964fc ("virtio_net: Add hash_key_length check")
Cc: stable@vger.kernel.org
Signed-off-by: Srujana Challa <schalla@marvell.com>
---
v3:
- Moved RSS key validation checks to virtnet_validate.
- Add fixes: tag and CC -stable
v4:
- Use NETDEV_RSS_KEY_LEN instead of type_max for the maximum rss key size.
v5:
- Interpret rss_max_key_size as a maximum and clamp it to NETDEV_RSS_KEY_LEN.
- Do not disable RSS/HASH_REPORT when device rss_max_key_size exceeds NETDEV_RSS_KEY_LEN.
- Drop the separate patch that replaced the runtime check with BUILD_BUG_ON.
drivers/net/virtio_net.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 022f60728721..b241c8dbb4e1 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -373,8 +373,6 @@ struct receive_queue {
struct xdp_buff **xsk_buffs;
};
-#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40
-
/* Control VQ buffers: protected by the rtnl lock */
struct control_buf {
struct virtio_net_ctrl_hdr hdr;
@@ -478,7 +476,7 @@ struct virtnet_info {
/* Must be last as it ends in a flexible-array member. */
TRAILING_OVERLAP(struct virtio_net_rss_config_trailer, rss_trailer, hash_key_data,
- u8 rss_hash_key_data[VIRTIO_NET_RSS_MAX_KEY_SIZE];
+ u8 rss_hash_key_data[NETDEV_RSS_KEY_LEN];
);
};
static_assert(offsetof(struct virtnet_info, rss_trailer.hash_key_data) ==
@@ -6717,6 +6715,7 @@ static int virtnet_probe(struct virtio_device *vdev)
struct virtnet_info *vi;
u16 max_queue_pairs;
int mtu = 0;
+ u16 key_sz;
/* Find if host supports multiqueue/rss virtio_net device */
max_queue_pairs = 1;
@@ -6851,14 +6850,13 @@ static int virtnet_probe(struct virtio_device *vdev)
}
if (vi->has_rss || vi->has_rss_hash_report) {
- vi->rss_key_size =
- virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));
- if (vi->rss_key_size > VIRTIO_NET_RSS_MAX_KEY_SIZE) {
- dev_err(&vdev->dev, "rss_max_key_size=%u exceeds the limit %u.\n",
- vi->rss_key_size, VIRTIO_NET_RSS_MAX_KEY_SIZE);
- err = -EINVAL;
- goto free;
- }
+ key_sz = virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));
+
+ vi->rss_key_size = min_t(u16, key_sz, NETDEV_RSS_KEY_LEN);
+ if (key_sz > vi->rss_key_size)
+ dev_warn(&vdev->dev,
+ "rss_max_key_size=%u exceeds driver limit %u, clamping\n",
+ key_sz, vi->rss_key_size);
vi->rss_hash_types_supported =
virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types));
--
2.25.1
^ permalink raw reply related
* [PATCH net v3] bnxt_en: validate firmware backing store types
From: Pengpeng Hou @ 2026-03-26 14:20 UTC (permalink / raw)
To: michael.chan
Cc: pavan.chebbi, andrew+netdev, davem, edumazet, kuba, pabeni,
netdev, linux-kernel, pengpeng
In-Reply-To: <20260323080336.36905-1-pengpeng@iscas.ac.cn>
bnxt_hwrm_func_backing_store_qcaps_v2() stores resp->type from the
firmware response in ctxm->type and later uses that value to index
fixed backing-store metadata arrays such as ctx_arr[] and
bnxt_bstore_to_trace[] without a local range check.
Validate the returned type before storing it and abort the query when
firmware reports a type outside BNXT_CTX_V2_MAX. Keep next_valid_type in
a dedicated variable so loop control stays clear for non-valid or
unchanged entries while resp->type is validated directly before use.
Fixes: 6a4d0774f02d ("bnxt_en: Add support for new backing store query firmware API")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v3:
- mark the patch for net
- add a Fixes tag
- replace resp_type with next_type for loop control and validate resp->type directly
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 0751c0e4581a..59ddf7a0c0ba 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -8692,6 +8692,7 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
u8 init_val, init_off, i;
u32 max_entries;
u16 entry_size;
+ u16 next_type;
__le32 *p;
u32 flags;
@@ -8700,7 +8701,7 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
if (rc)
goto ctx_done;
flags = le32_to_cpu(resp->flags);
- type = le16_to_cpu(resp->next_valid_type);
+ next_type = le16_to_cpu(resp->next_valid_type);
if (!(flags & BNXT_CTX_MEM_TYPE_VALID)) {
bnxt_free_one_ctx_mem(bp, ctxm, true);
continue;
@@ -8708,12 +8709,21 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
entry_size = le16_to_cpu(resp->entry_size);
max_entries = le32_to_cpu(resp->max_num_entries);
if (ctxm->mem_valid) {
- if (!(flags & BNXT_CTX_MEM_PERSIST) ||
- ctxm->entry_size != entry_size ||
- ctxm->max_entries != max_entries)
- bnxt_free_one_ctx_mem(bp, ctxm, true);
- else
+ if ((flags & BNXT_CTX_MEM_PERSIST) &&
+ ctxm->entry_size == entry_size &&
+ ctxm->max_entries == max_entries) {
+ type = next_type;
continue;
+ }
+
+ bnxt_free_one_ctx_mem(bp, ctxm, true);
+ }
+ if (le16_to_cpu(resp->type) >= BNXT_CTX_V2_MAX) {
+ netdev_warn(bp->dev,
+ "invalid backing store type %u returned by firmware\n",
+ le16_to_cpu(resp->type));
+ rc = -EINVAL;
+ goto ctx_done;
}
ctxm->type = le16_to_cpu(resp->type);
ctxm->entry_size = entry_size;
@@ -8731,6 +8741,8 @@ static int bnxt_hwrm_func_backing_store_qcaps_v2(struct bnxt *bp)
for (i = 0, p = &resp->split_entry_0; i < ctxm->split_entry_cnt;
i++, p++)
ctxm->split[i] = le32_to_cpu(*p);
+
+ type = next_type;
}
rc = bnxt_alloc_all_ctx_pg_info(bp, BNXT_CTX_V2_MAX);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH net v2] NFC: pn533: bound the UART receive buffer
From: Pengpeng Hou @ 2026-03-26 14:20 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, tglx, mingo, kees, pabeni, pengpeng
In-Reply-To: <20260323072409.60086-1-pengpeng@iscas.ac.cn>
pn532_receive_buf() appends every incoming byte to dev->recv_skb and
only resets the buffer after pn532_uart_rx_is_frame() recognizes a
complete frame. A continuous stream of bytes without a valid PN532 frame
header therefore keeps growing the skb until skb_put_u8() hits the tail
limit.
Drop the accumulated partial frame once the fixed receive buffer is full
so malformed UART traffic cannot grow the skb past
PN532_UART_SKB_BUFF_LEN.
Fixes: c656aa4c27b1 ("nfc: pn533: add UART phy driver")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
v2:
- add the requested Fixes tag for the UART receive path
drivers/nfc/pn533/uart.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
index 6d2f520a5bc8..1b82b7b2a5fa 100644
--- a/drivers/nfc/pn533/uart.c
+++ b/drivers/nfc/pn533/uart.c
@@ -211,6 +211,9 @@ static size_t pn532_receive_buf(struct serdev_device *serdev,
timer_delete(&dev->cmd_timeout);
for (i = 0; i < count; i++) {
+ if (unlikely(!skb_tailroom(dev->recv_skb)))
+ skb_trim(dev->recv_skb, 0);
+
skb_put_u8(dev->recv_skb, *data++);
if (!pn532_uart_rx_is_frame(dev->recv_skb))
continue;
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* Re: [PATCH net 0/6][pull request] Intel Wired LAN Driver Updates 2026-03-23 (ice, iavf, idpf)
From: patchwork-bot+netdevbpf @ 2026-03-26 14:20 UTC (permalink / raw)
To: Tony Nguyen; +Cc: davem, kuba, pabeni, edumazet, andrew+netdev, netdev
In-Reply-To: <20260323205843.624704-1-anthony.l.nguyen@intel.com>
Hello:
This series was applied to netdev/net.git (main)
by Tony Nguyen <anthony.l.nguyen@intel.com>:
On Mon, 23 Mar 2026 13:58:35 -0700 you wrote:
> For ice:
> Michal corrects call to alloc_etherdev_mqs() to provide maximum number
> of queues supported rather than currently allocated number of queues.
>
> Petr Oros fixes issues related to some ethtool operations in switchdev
> mode.
>
> [...]
Here is the summary with links:
- [net,1/6] ice: set max queues in alloc_etherdev_mqs()
https://git.kernel.org/netdev/net/c/c7fcd269e1e0
- [net,2/6] ice: fix inverted ready check for VF representors
https://git.kernel.org/netdev/net/c/ad85de0fc09e
- [net,3/6] ice: use ice_update_eth_stats() for representor stats
https://git.kernel.org/netdev/net/c/2526e440df27
- [net,4/6] iavf: fix out-of-bounds writes in iavf_get_ethtool_stats()
https://git.kernel.org/netdev/net/c/fecacfc95f19
- [net,5/6] idpf: clear stale cdev_info ptr
https://git.kernel.org/netdev/net/c/1eb0db7e39da
- [net,6/6] idpf: only assign num refillqs if allocation was successful
https://git.kernel.org/netdev/net/c/b5e5797e3cd1
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* [PATCH iwl-next v3] ice: remove excessive memory allocation in ice_create_lag_recipe()
From: Aleksandr Loktionov @ 2026-03-26 14:17 UTC (permalink / raw)
To: intel-wired-lan, anthony.l.nguyen, aleksandr.loktionov
Cc: netdev, Marcin Szycik
From: Marcin Szycik <marcin.szycik@intel.com>
For some reason ice_create_lag_recipe() allocates an array of 64
struct ice_aqc_recipe_data_elem elements, while it only needs one (1).
Fix it, while also using kzalloc_obj().
Signed-off-by: Marcin Szycik <marcin.szycik@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
---
v2 -> v3 use sizeof(*new_rcp) in memcpy() to match the allocation (Jakub)
v1 -> v2 remove 'Fixes' from commit message because it's not a critical bug
---
drivers/net/ethernet/intel/ice/ice_lag.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index 310e8fe..9ad19c3 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -2418,11 +2418,11 @@ static int ice_create_lag_recipe(struct ice_hw *hw, u16 *rid,
if (err)
return err;
- new_rcp = kzalloc(ICE_RECIPE_LEN * ICE_MAX_NUM_RECIPES, GFP_KERNEL);
+ new_rcp = kzalloc_obj(*new_rcp, GFP_KERNEL);
if (!new_rcp)
return -ENOMEM;
- memcpy(new_rcp, base_recipe, ICE_RECIPE_LEN);
+ memcpy(new_rcp, base_recipe, sizeof(*new_rcp));
new_rcp->content.act_ctrl_fwd_priority = prio;
new_rcp->content.rid = *rid | ICE_AQ_RECIPE_ID_IS_ROOT;
new_rcp->recipe_indx = *rid;
^ permalink raw reply related
* RE: [PATCH] ice: add missing reset of the mac header
From: Loktionov, Aleksandr @ 2026-03-26 14:14 UTC (permalink / raw)
To: Simon Horman
Cc: intel-wired-lan@lists.osuosl.org, Nguyen, Anthony L,
netdev@vger.kernel.org, Wieczerzycka, Katarzyna
In-Reply-To: <20260320180410.GA151863@horms.kernel.org>
> -----Original Message-----
> From: Simon Horman <horms@kernel.org>
> Sent: Friday, March 20, 2026 7:05 PM
> To: Loktionov, Aleksandr <aleksandr.loktionov@intel.com>
> Cc: intel-wired-lan@lists.osuosl.org; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>; netdev@vger.kernel.org; Wieczerzycka,
> Katarzyna <katarzyna.wieczerzycka@intel.com>
> Subject: Re: [PATCH] ice: add missing reset of the mac header
>
> On Fri, Mar 20, 2026 at 06:05:18AM +0100, Aleksandr Loktionov wrote:
> > From: Katarzyna Wieczerzycka <katarzyna.wieczerzycka@intel.com>
> >
> > By default skb->mac_header is not set, so reset prevents access to
> an
> > invalid pointer.
> >
> > Call skb_reset_mac_header() before accessing the mac header from
> skb.
> >
> > Signed-off-by: Katarzyna Wieczerzycka
> > <katarzyna.wieczerzycka@intel.com>
> > Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
>
> Hi Katarzyna and Aleksandr,
>
> I am curious:
>
> Is this a bug? If so then it should probably have a fixes tag and a
> bit more of a description around how this can happen.
>
> If it is not a bug, then is this defensive? And if so, is it really
> necessary?
>
> ...
Withdrawing this patch. The bug justification and repro are not
strong enough to meet the bar for upstream. Will drop for now.
With the best regards
Alex
^ permalink raw reply
* Re: [PATCH net-next v2] net: mana: Set default number of queues to 16
From: patchwork-bot+netdevbpf @ 2026-03-26 14:10 UTC (permalink / raw)
To: Long Li
Cc: kotaranov, kuba, davem, pabeni, edumazet, andrew+netdev, jgg,
leon, haiyangz, kys, wei.liu, decui, horms, netdev, linux-rdma,
linux-hyperv, linux-kernel
In-Reply-To: <20260323194925.1766385-1-longli@microsoft.com>
Hello:
This patch was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Mon, 23 Mar 2026 12:49:25 -0700 you wrote:
> Set the default number of queues per vPort to MANA_DEF_NUM_QUEUES (16),
> as 16 queues can achieve optimal throughput for typical workloads. The
> actual number of queues may be lower if it exceeds the hardware reported
> limit. Users can increase the number of queues up to max_queues via
> ethtool if needed.
>
> Signed-off-by: Long Li <longli@microsoft.com>
>
> [...]
Here is the summary with links:
- [net-next,v2] net: mana: Set default number of queues to 16
https://git.kernel.org/netdev/net-next/c/45b2b84ac6fd
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net] net: macb: use the current queue number for stats
From: patchwork-bot+netdevbpf @ 2026-03-26 14:10 UTC (permalink / raw)
To: Paolo Valerio
Cc: netdev, nicolas.ferre, claudiu.beznea, andrew+netdev, davem,
edumazet, kuba, pabeni, nb
In-Reply-To: <20260323191634.2185840-1-pvalerio@redhat.com>
Hello:
This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Mon, 23 Mar 2026 20:16:34 +0100 you wrote:
> There's a potential mismatch between the memory reserved for statistics
> and the amount of memory written.
>
> gem_get_sset_count() correctly computes the number of stats based on the
> active queues, whereas gem_get_ethtool_stats() indiscriminately copies
> data using the maximum number of queues, and in the case the number of
> active queues is less than MACB_MAX_QUEUES, this results in a OOB write
> as observed in the KASAN splat.
>
> [...]
Here is the summary with links:
- [net] net: macb: use the current queue number for stats
https://git.kernel.org/netdev/net/c/72d96e4e24bb
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH] net/ipv6: ioam6: prevent schema length wraparound in trace fill
From: Justin Iurman @ 2026-03-26 14:05 UTC (permalink / raw)
To: Pengpeng Hou, David S . Miller, David Ahern, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, netdev, linux-kernel
In-Reply-To: <20260325074152.17064-1-pengpeng@iscas.ac.cn>
On 3/25/26 08:41, Pengpeng Hou wrote:
> ioam6_fill_trace_data() stores the schema contribution to the trace
> length in a u8. With bit 22 enabled and the largest schema payload,
> sclen becomes 1 + 1020 / 4, wraps from 256 to 0, and bypasses the
> remaining-space check. __ioam6_fill_trace_data() then positions the
> write cursor without reserving the schema area but still copies the
> 4-byte schema header and the full schema payload, overrunning the trace
> buffer.
>
> Keep sclen in an unsigned int so the remaining-space check and the write
> cursor calculation both see the full schema length.
>
> Fixes: 8c6f6fa67726 ("ipv6: ioam: IOAM Generic Netlink API")
... should be:
Fixes: 9ee11f0fff20 ("ipv6: ioam: Data plane support for Pre-allocated
Trace")
Respin needed? Otherwise, LGTM.
Reviewed-by: Justin Iurman <justin.iurman@gmail.com>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
> ---
> net/ipv6/ioam6.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c
> index b76f89d92e7b..3978773bec42 100644
> --- a/net/ipv6/ioam6.c
> +++ b/net/ipv6/ioam6.c
> @@ -708,7 +708,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
> struct ioam6_namespace *ns,
> struct ioam6_trace_hdr *trace,
> struct ioam6_schema *sc,
> - u8 sclen, bool is_input)
> + unsigned int sclen, bool is_input)
> {
> struct net_device *dev = skb_dst_dev(skb);
> struct timespec64 ts;
> @@ -939,7 +939,7 @@ void ioam6_fill_trace_data(struct sk_buff *skb,
> bool is_input)
> {
> struct ioam6_schema *sc;
> - u8 sclen = 0;
> + unsigned int sclen = 0;
>
> /* Skip if Overflow flag is set
> */
^ permalink raw reply
* Re: [PATCH net] ipv6: fix data race in fib6_metric_set() using cmpxchg
From: Eric Dumazet @ 2026-03-26 14:01 UTC (permalink / raw)
To: Jiayuan Chen
Cc: Hangbin Liu, David S. Miller, David Ahern, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Ahern, netdev, linux-kernel,
Fei Liu
In-Reply-To: <39c100fe-1f6f-46d2-8dd5-cf82320508ff@linux.dev>
On Thu, Mar 26, 2026 at 6:44 AM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
>
> On 3/26/26 9:13 PM, Hangbin Liu wrote:
> > On Thu, Mar 26, 2026 at 05:05:57AM -0700, Eric Dumazet wrote:
> >>> diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
> >>> index dd26657b6a4a..64de761f40d5 100644
> >>> --- a/net/ipv6/ip6_fib.c
> >>> +++ b/net/ipv6/ip6_fib.c
> >>> @@ -730,14 +730,16 @@ void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val)
> >>> if (!f6i)
> >>> return;
> >>>
> >>> - if (f6i->fib6_metrics == &dst_default_metrics) {
> >>> + if (READ_ONCE(f6i->fib6_metrics) == &dst_default_metrics) {
> >>> + struct dst_metrics *dflt = (struct dst_metrics *)&dst_default_metrics;
> >>> struct dst_metrics *p = kzalloc_obj(*p, GFP_ATOMIC);
> >>>
> >>> if (!p)
> >>> return;
> >>>
> >>> refcount_set(&p->refcnt, 1);
> >>> - f6i->fib6_metrics = p;
> >>> + if (cmpxchg(&f6i->fib6_metrics, dflt, p) != dflt)
> >>> + kfree(p);
> >>> }
> >>>
> >> The following line should happen before the cmpxchg(),
> >> ->metrics[X] accesses also need READ_ONCE()/WRITE_ONCE() annotations.
> > Hi Eric,
> >
> > Jiayuan also suggested to using READ_ONCE()/WRITE_ONCE() for metrics[X]
> > accesses. But I don't get why this line should happen before the cmpxchg(),
> > Would you please help explain?
>
>
> I think what Eric means is something like this:
>
>
> ...
> struct dst_metrics *p = kzalloc_obj(*p, GFP_ATOMIC);
>
> if (!p)
> return;
>
> p->metrics[metric - 1] = val;
> refcount_set(&p->refcnt, 1);
> if (cmpxchg(&f6i->fib6_metrics, dflt, p) != dflt)
> kfree(p);
> else
> return;
> }
> }
>
> m = READ_ONCE(f6i->fib6_metrics);
> WRITE_ONCE(m->metrics[metric - 1], val);
>
>
> Since p is private data before being published via cmpxchg(), we can
> safely initialize its metrics beforehand. This way we don't need to
> worry about concurrent access to f6i->fib6_metrics->metrics[] during
> initialization. Right?
Yes. Think about RCU (Read Copy Update) rules.
We allocate an object, and populate it, then make sure changes are
committed, before publishing the new pointer.
Othewise an other cpu could read a 0 metric, while we wanted something else.
^ permalink raw reply
* [PATCH net-next v6 6/6] tls: Flush backlog before waiting for a new record
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
While lock_sock is held, incoming TCP segments land on
sk->sk_backlog rather than sk->sk_receive_queue.
tls_rx_rec_wait() inspects only sk_receive_queue, so
backlog data remains invisible. For non-blocking callers
(read_sock, and recvmsg or splice_read with MSG_DONTWAIT)
this causes a spurious -EAGAIN. For blocking callers it
forces an unnecessary sleep/wakeup cycle.
Flush the backlog inside tls_rx_rec_wait() before checking
sk_receive_queue so the strparser can parse newly-arrived
segments immediately. On the next loop iteration
tls_read_flush_backlog() may redundantly flush, but this
path is cold and the cost is negligible.
Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls_sw.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 8fb2f2a93846..e15adf250d78 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1372,6 +1372,8 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock,
if (ret < 0)
return ret;
+ if (sk_flush_backlog(sk))
+ released = true;
if (!skb_queue_empty(&sk->sk_receive_queue)) {
/* Defer notification to the exit point;
* this thread will consume the record
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 5/6] tls: Suppress spurious saved_data_ready on all receive paths
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Alistair Francis,
Hannes Reinecke
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
Each record release via tls_strp_msg_done() triggers
tls_strp_check_rcv(), which calls tls_rx_msg_ready() and
fires saved_data_ready(). During a multi-record receive,
the first N-1 wakeups are pure overhead: the caller is
already running and will pick up subsequent records on
the next loop iteration. On the splice_read path the
per-record wakeup is similarly unnecessary because the
caller still holds the socket lock.
Replace tls_strp_msg_done() with tls_strp_msg_release()
in all three receive paths (read_sock, recvmsg,
splice_read), deferring the tls_strp_check_rcv() call
to each path's exit point. Factor tls_rx_msg_ready()
out of tls_strp_read_sock() so that parsing a record
no longer fires the callback directly, and add a @wake
parameter to tls_strp_check_rcv() so callers can parse
queued data without notifying.
With no remaining callers, tls_strp_msg_done() and its
wrapper tls_rx_rec_done() are removed.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls.h | 3 +--
net/tls/tls_main.c | 2 +-
net/tls/tls_strp.c | 35 +++++++++++++++++++++--------------
net/tls/tls_sw.c | 22 +++++++++++++++-------
4 files changed, 38 insertions(+), 24 deletions(-)
diff --git a/net/tls/tls.h b/net/tls/tls.h
index a97f1acef31d..f41dac6305f4 100644
--- a/net/tls/tls.h
+++ b/net/tls/tls.h
@@ -192,9 +192,8 @@ void tls_strp_stop(struct tls_strparser *strp);
int tls_strp_init(struct tls_strparser *strp, struct sock *sk);
void tls_strp_data_ready(struct tls_strparser *strp);
-void tls_strp_check_rcv(struct tls_strparser *strp);
+void tls_strp_check_rcv(struct tls_strparser *strp, bool wake);
void tls_strp_msg_release(struct tls_strparser *strp);
-void tls_strp_msg_done(struct tls_strparser *strp);
int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb);
void tls_rx_msg_ready(struct tls_strparser *strp);
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index fd39acf41a61..c10a3fd7fc17 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -769,7 +769,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
} else {
struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(ctx);
- tls_strp_check_rcv(&rx_ctx->strp);
+ tls_strp_check_rcv(&rx_ctx->strp, true);
}
return 0;
diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
index a7648ebde162..b0b2ca92fa99 100644
--- a/net/tls/tls_strp.c
+++ b/net/tls/tls_strp.c
@@ -368,7 +368,6 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
desc->count = 0;
WRITE_ONCE(strp->msg_ready, 1);
- tls_rx_msg_ready(strp);
}
return ret;
@@ -539,18 +538,32 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
return tls_strp_read_copy(strp, false);
WRITE_ONCE(strp->msg_ready, 1);
- tls_rx_msg_ready(strp);
return 0;
}
-void tls_strp_check_rcv(struct tls_strparser *strp)
+/**
+ * tls_strp_check_rcv - parse queued data and optionally notify
+ * @strp: TLS stream parser instance
+ * @wake: if true, fire consumer notification when a message is ready
+ *
+ * When @wake is false, queued data is parsed without consumer
+ * notification. A subsequent call with @wake set to true is
+ * required before the socket lock is released; otherwise queued
+ * data stalls until the next tls_strp_data_ready() event.
+ */
+void tls_strp_check_rcv(struct tls_strparser *strp, bool wake)
{
- if (unlikely(strp->stopped) || strp->msg_ready)
+ if (unlikely(strp->stopped))
return;
- if (tls_strp_read_sock(strp) == -ENOMEM)
- queue_work(tls_strp_wq, &strp->work);
+ if (!strp->msg_ready) {
+ if (tls_strp_read_sock(strp) == -ENOMEM)
+ queue_work(tls_strp_wq, &strp->work);
+ }
+
+ if (wake && strp->msg_ready)
+ tls_rx_msg_ready(strp);
}
/* Lower sock lock held */
@@ -568,7 +581,7 @@ void tls_strp_data_ready(struct tls_strparser *strp)
return;
}
- tls_strp_check_rcv(strp);
+ tls_strp_check_rcv(strp, true);
}
static void tls_strp_work(struct work_struct *w)
@@ -577,7 +590,7 @@ static void tls_strp_work(struct work_struct *w)
container_of(w, struct tls_strparser, work);
lock_sock(strp->sk);
- tls_strp_check_rcv(strp);
+ tls_strp_check_rcv(strp, true);
release_sock(strp->sk);
}
@@ -603,12 +616,6 @@ void tls_strp_msg_release(struct tls_strparser *strp)
memset(&strp->stm, 0, sizeof(strp->stm));
}
-void tls_strp_msg_done(struct tls_strparser *strp)
-{
- tls_strp_msg_release(strp);
- tls_strp_check_rcv(strp);
-}
-
void tls_strp_stop(struct tls_strparser *strp)
{
strp->stopped = 1;
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 5fdd43a55f1e..8fb2f2a93846 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1373,7 +1373,11 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock,
return ret;
if (!skb_queue_empty(&sk->sk_receive_queue)) {
- tls_strp_check_rcv(&ctx->strp);
+ /* Defer notification to the exit point;
+ * this thread will consume the record
+ * directly.
+ */
+ tls_strp_check_rcv(&ctx->strp, false);
if (tls_strp_msg_ready(ctx))
break;
}
@@ -1859,9 +1863,9 @@ static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm,
return 1;
}
-static void tls_rx_rec_done(struct tls_sw_context_rx *ctx)
+static void tls_rx_rec_release(struct tls_sw_context_rx *ctx)
{
- tls_strp_msg_done(&ctx->strp);
+ tls_strp_msg_release(&ctx->strp);
}
/* This function traverses the rx_list in tls receive context to copies the
@@ -2142,7 +2146,7 @@ int tls_sw_recvmsg(struct sock *sk,
err = tls_record_content_type(msg, tls_msg(darg.skb), &control);
if (err <= 0) {
DEBUG_NET_WARN_ON_ONCE(darg.zc);
- tls_rx_rec_done(ctx);
+ tls_rx_rec_release(ctx);
put_on_rx_list_err:
__skb_queue_tail(&ctx->rx_list, darg.skb);
goto recv_end;
@@ -2156,7 +2160,8 @@ int tls_sw_recvmsg(struct sock *sk,
/* TLS 1.3 may have updated the length by more than overhead */
rxm = strp_msg(darg.skb);
chunk = rxm->full_len;
- tls_rx_rec_done(ctx);
+ tls_rx_rec_release(ctx);
+ tls_strp_check_rcv(&ctx->strp, false);
if (!darg.zc) {
bool partially_consumed = chunk > len;
@@ -2250,6 +2255,7 @@ int tls_sw_recvmsg(struct sock *sk,
copied += decrypted;
end:
+ tls_strp_check_rcv(&ctx->strp, true);
tls_rx_reader_unlock(sk, ctx);
if (psock)
sk_psock_put(sk, psock);
@@ -2290,7 +2296,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
if (err < 0)
goto splice_read_end;
- tls_rx_rec_done(ctx);
+ tls_rx_rec_release(ctx);
skb = darg.skb;
}
@@ -2317,6 +2323,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
consume_skb(skb);
splice_read_end:
+ tls_strp_check_rcv(&ctx->strp, true);
tls_rx_reader_unlock(sk, ctx);
return copied ? : err;
@@ -2382,7 +2389,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
tlm = tls_msg(skb);
decrypted += rxm->full_len;
- tls_rx_rec_done(ctx);
+ tls_rx_rec_release(ctx);
}
/* read_sock does not support reading control messages */
@@ -2412,6 +2419,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
}
read_sock_end:
+ tls_strp_check_rcv(&ctx->strp, true);
tls_rx_reader_release(sk, ctx);
return copied ? : err;
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 4/6] tls: Factor tls_strp_msg_release() from tls_strp_msg_done()
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke,
Alistair Francis
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
tls_strp_msg_done() conflates releasing the current record with
checking for the next one via tls_strp_check_rcv(). Batch
processing requires releasing a record without immediately
triggering that check, so the release step is separated into
tls_strp_msg_release(). tls_strp_msg_done() is preserved as a
wrapper for existing callers.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls.h | 1 +
net/tls/tls_strp.c | 15 ++++++++++++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/net/tls/tls.h b/net/tls/tls.h
index e8f81a006520..a97f1acef31d 100644
--- a/net/tls/tls.h
+++ b/net/tls/tls.h
@@ -193,6 +193,7 @@ int tls_strp_init(struct tls_strparser *strp, struct sock *sk);
void tls_strp_data_ready(struct tls_strparser *strp);
void tls_strp_check_rcv(struct tls_strparser *strp);
+void tls_strp_msg_release(struct tls_strparser *strp);
void tls_strp_msg_done(struct tls_strparser *strp);
int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb);
diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
index 98e12f0ff57e..a7648ebde162 100644
--- a/net/tls/tls_strp.c
+++ b/net/tls/tls_strp.c
@@ -581,7 +581,16 @@ static void tls_strp_work(struct work_struct *w)
release_sock(strp->sk);
}
-void tls_strp_msg_done(struct tls_strparser *strp)
+/**
+ * tls_strp_msg_release - release the current strparser message
+ * @strp: TLS stream parser instance
+ *
+ * Release the current record without triggering a check for the
+ * next record. Callers must invoke tls_strp_check_rcv() before
+ * releasing the socket lock, or queued data will stall until
+ * the next tls_strp_data_ready() event.
+ */
+void tls_strp_msg_release(struct tls_strparser *strp)
{
WARN_ON(!strp->stm.full_len);
@@ -592,7 +601,11 @@ void tls_strp_msg_done(struct tls_strparser *strp)
WRITE_ONCE(strp->msg_ready, 0);
memset(&strp->stm, 0, sizeof(strp->stm));
+}
+void tls_strp_msg_done(struct tls_strparser *strp)
+{
+ tls_strp_msg_release(strp);
tls_strp_check_rcv(strp);
}
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 3/6] tls: Fix dangling skb pointer in tls_sw_read_sock()
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke,
Alistair Francis
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
Per ISO/IEC 9899:2011 section 6.2.4p2, a pointer value becomes
indeterminate when the object it points to reaches the end of its
lifetime; Annex J.2 classifies the use of such a value as undefined
behavior. In tls_sw_read_sock(), consume_skb(skb) in the
fully-consumed path frees the skb, but the "do { } while (skb)"
loop condition then evaluates that freed pointer. Although the
value is never dereferenced -- the loop either continues and
overwrites skb, or exits -- any future change that adds a
dereference between consume_skb() and the loop condition would
produce a silent use-after-free.
Fixes: 662fbcec32f4 ("net/tls: implement ->read_sock()")
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls_sw.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 5626fdd4ea0a..5fdd43a55f1e 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -2356,7 +2356,7 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
goto read_sock_end;
decrypted = 0;
- do {
+ for (;;) {
if (!skb_queue_empty(&ctx->rx_list)) {
skb = __skb_dequeue(&ctx->rx_list);
rxm = strp_msg(skb);
@@ -2405,10 +2405,11 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
goto read_sock_requeue;
} else {
consume_skb(skb);
+ skb = NULL;
if (!desc->count)
- skb = NULL;
+ break;
}
- } while (skb);
+ }
read_sock_end:
tls_rx_reader_release(sk, ctx);
--
2.53.0
^ permalink raw reply related
* [PATCH net-next v6 2/6] tls: Abort the connection on decrypt failure
From: Chuck Lever @ 2026-03-26 13:50 UTC (permalink / raw)
To: john.fastabend, kuba, sd
Cc: netdev, kernel-tls-handshake, Chuck Lever, Hannes Reinecke
In-Reply-To: <20260326-tls-read-sock-v6-0-fd887b9e7f06@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
recvmsg, read_sock, and splice_read each open-code a
tls_err_abort() call after tls_rx_one_record() fails. Move
the abort into tls_rx_one_record() so each receive path
shares a single decrypt-and-abort sequence.
A tls_check_pending_rekey() failure after successful
decryption no longer triggers tls_err_abort(). That path
fires only when skb_copy_bits() fails on a valid skb,
which is not a realistic scenario.
Suggested-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/tls/tls_sw.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 20f8fc84c5f5..5626fdd4ea0a 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1799,6 +1799,9 @@ static int tls_check_pending_rekey(struct sock *sk, struct tls_context *ctx,
return 0;
}
+/* Decrypt and return one TLS record. On decrypt failure the connection is
+ * aborted (sk_err set) before returning a negative errno.
+ */
static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
struct tls_decrypt_arg *darg)
{
@@ -1810,8 +1813,10 @@ static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
err = tls_decrypt_device(sk, msg, tls_ctx, darg);
if (!err)
err = tls_decrypt_sw(sk, tls_ctx, msg, darg);
- if (err < 0)
+ if (err < 0) {
+ tls_err_abort(sk, -EBADMSG);
return err;
+ }
rxm = strp_msg(darg->skb);
rxm->offset += prot->prepend_size;
@@ -2122,10 +2127,8 @@ int tls_sw_recvmsg(struct sock *sk,
darg.async = false;
err = tls_rx_one_record(sk, msg, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto recv_end;
- }
async |= darg.async;
@@ -2284,10 +2287,8 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
memset(&darg.inargs, 0, sizeof(darg.inargs));
err = tls_rx_one_record(sk, NULL, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto splice_read_end;
- }
tls_rx_rec_done(ctx);
skb = darg.skb;
@@ -2370,10 +2371,8 @@ int tls_sw_read_sock(struct sock *sk, read_descriptor_t *desc,
memset(&darg.inargs, 0, sizeof(darg.inargs));
err = tls_rx_one_record(sk, NULL, &darg);
- if (err < 0) {
- tls_err_abort(sk, -EBADMSG);
+ if (err < 0)
goto read_sock_end;
- }
released = tls_read_flush_backlog(sk, prot, INT_MAX,
0, decrypted,
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox