* [PATCH iwl-net] ice: fix NULL pointer dereference in ice_reset_all_vfs()
From: Petr Oros @ 2026-04-01 11:09 UTC (permalink / raw)
To: netdev
Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Brett Creeley, intel-wired-lan, linux-kernel
ice_reset_all_vfs() ignores the return value of ice_vf_rebuild_vsi().
When the VSI rebuild fails (e.g. during NVM firmware update via
nvmupdate64e), ice_vsi_rebuild() tears down the VSI on its error path,
leaving txq_map and rxq_map as NULL. The subsequent unconditional call
to ice_vf_post_vsi_rebuild() leads to a NULL pointer dereference in
ice_ena_vf_q_mappings() when it accesses vsi->txq_map[0].
The single-VF reset path in ice_reset_vf() already handles this
correctly by checking the return value of ice_vf_reconfig_vsi() and
skipping ice_vf_post_vsi_rebuild() on failure.
Apply the same pattern to ice_reset_all_vfs(): check the return value
of ice_vf_rebuild_vsi() and skip ice_vf_post_vsi_rebuild() and
ice_eswitch_attach_vf() on failure. The VF is left safely disabled
(ICE_VF_STATE_INIT not set, VFGEN_RSTAT not set to VFACTIVE) and can
be recovered via a VFLR triggered by a PCI reset of the VF
(sysfs reset or driver rebind).
Note that this patch does not prevent the VF VSI rebuild from failing
during NVM update — the underlying cause is firmware being in a
transitional state while the EMP reset is processed, which can cause
Admin Queue commands (ice_add_vsi, ice_cfg_vsi_lan) to fail. This
patch only prevents the subsequent NULL pointer dereference that
crashes the kernel when the rebuild does fail.
crash> bt
PID: 50795 TASK: ff34c9ee708dc680 CPU: 1 COMMAND: "kworker/u512:5"
#0 [ff72159bcfe5bb50] machine_kexec at ffffffffaa8850ee
#1 [ff72159bcfe5bba8] __crash_kexec at ffffffffaaa15fba
#2 [ff72159bcfe5bc68] crash_kexec at ffffffffaaa16540
#3 [ff72159bcfe5bc70] oops_end at ffffffffaa837eda
#4 [ff72159bcfe5bc90] page_fault_oops at ffffffffaa893997
#5 [ff72159bcfe5bce8] exc_page_fault at ffffffffab528595
#6 [ff72159bcfe5bd10] asm_exc_page_fault at ffffffffab600bb2
[exception RIP: ice_ena_vf_q_mappings+0x79]
RIP: ffffffffc0a85b29 RSP: ff72159bcfe5bdc8 RFLAGS: 00010206
RAX: 00000000000f0000 RBX: ff34c9efc9c00000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000010 RDI: ff34c9efc9c00000
RBP: ff34c9efc27d4828 R8: 0000000000000093 R9: 0000000000000040
R10: ff34c9efc27d4828 R11: 0000000000000040 R12: 0000000000100000
R13: 0000000000000010 R14: R15:
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#7 [ff72159bcfe5bdf8] ice_sriov_post_vsi_rebuild at ffffffffc0a85e2e [ice]
#8 [ff72159bcfe5be08] ice_reset_all_vfs at ffffffffc0a920b4 [ice]
#9 [ff72159bcfe5be48] ice_service_task at ffffffffc0a31519 [ice]
#10 [ff72159bcfe5be88] process_one_work at ffffffffaa93dca4
#11 [ff72159bcfe5bec8] worker_thread at ffffffffaa93e9de
#12 [ff72159bcfe5bf18] kthread at ffffffffaa946663
#13 [ff72159bcfe5bf50] ret_from_fork at ffffffffaa8086b9
The panic occurs attempting to dereference the NULL pointer in RDX at
ice_sriov.c:294, which loads vsi->txq_map (offset 0x4b8 in ice_vsi).
The faulting VSI is an allocated slab object but not fully initialized
after a failed ice_vsi_rebuild():
crash> struct ice_vsi 0xff34c9efc27d4828
netdev = 0x0,
rx_rings = 0x0,
tx_rings = 0x0,
q_vectors = 0x0,
txq_map = 0x0,
rxq_map = 0x0,
alloc_txq = 0x10,
num_txq = 0x10,
alloc_rxq = 0x10,
num_rxq = 0x10,
The nvmupdate64e process was performing NVM firmware update:
crash> bt 0xff34c9edd1a30000
PID: 49858 TASK: ff34c9edd1a30000 CPU: 1 COMMAND: "nvmupdate64e"
#0 [ff72159bcd617618] __schedule at ffffffffab5333f8
#4 [ff72159bcd617750] ice_sq_send_cmd at ffffffffc0a35347 [ice]
#5 [ff72159bcd6177a8] ice_sq_send_cmd_retry at ffffffffc0a35b47 [ice]
#6 [ff72159bcd617810] ice_aq_send_cmd at ffffffffc0a38018 [ice]
#7 [ff72159bcd617848] ice_aq_read_nvm at ffffffffc0a40254 [ice]
#8 [ff72159bcd6178b8] ice_read_flat_nvm at ffffffffc0a4034c [ice]
#9 [ff72159bcd617918] ice_devlink_nvm_snapshot at ffffffffc0a6ffa5 [ice]
dmesg:
ice 0000:13:00.0: firmware recommends not updating fw.mgmt, as it
may result in a downgrade. continuing anyways
ice 0000:13:00.1: ice_init_nvm failed -5
ice 0000:13:00.1: Rebuild failed, unload and reload driver
Fixes: 12bb018c538c ("ice: Refactor VF reset")
Signed-off-by: Petr Oros <poros@redhat.com>
---
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index c8bc952f05cdb5..51259a4fdda4b9 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -804,7 +804,12 @@ void ice_reset_all_vfs(struct ice_pf *pf)
ice_vf_ctrl_invalidate_vsi(vf);
ice_vf_pre_vsi_rebuild(vf);
- ice_vf_rebuild_vsi(vf);
+ if (ice_vf_rebuild_vsi(vf)) {
+ dev_err(dev, "VF %u VSI rebuild failed, leaving VF disabled\n",
+ vf->vf_id);
+ mutex_unlock(&vf->cfg_lock);
+ continue;
+ }
ice_vf_post_vsi_rebuild(vf);
ice_eswitch_attach_vf(pf, vf);
--
2.52.0
^ permalink raw reply related
* Re: [PATCH net-next v4 1/2] net: hsr: require valid EOT supervision TLV
From: Luka Gejak @ 2026-04-01 11:06 UTC (permalink / raw)
To: Fernando Fernandez Mancera, davem, edumazet, kuba, pabeni
Cc: netdev, fmaurer, horms
In-Reply-To: <4549f521-6395-4c26-921e-eaead7248a36@suse.de>
On April 1, 2026 11:52:02 AM GMT+02:00, Fernando Fernandez Mancera <fmancera@suse.de> wrote:
>On 4/1/26 11:23 AM, 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.
>>
>> Reviewed-by: Felix Maurer <fmaurer@redhat.com>
>> Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
>> ---
>
>Hi,
>
>This has not been reviewed by Felix. Felix provided his Reviewed-by tag for the v1 which was completely different than this.
>
>Revisions of this patch:
>
>v3: https://lore.kernel.org/all/20260329112313.17164-4-luka.gejak@linux.dev/
>
>v2: https://lore.kernel.org/all/20260326154715.38405-4-luka.gejak@linux.dev/
>
>v1: https://lore.kernel.org/all/20260324143503.187642-4-luka.gejak@linux.dev/
>
>Are these contributions LLM/AI generated? I believe so based on the email history.
>
>AI generated review on rtl8723bs: https://lore.kernel.org/all/B2394A3C-25FD-4CEA-8557-3E68F1F60357@linux.dev/
>
>Another AI generated review on rtl8723bs: https://lore.kernel.org/all/3831D599-655E-40B2-9E5D-9DF956013088@linux.dev/
>
>Likely an AI generated review on a 1 year old HSR patch: https://lore.kernel.org/all/DHFG26KI6L23.1YCOVQ5SSYMO5@linux.dev/
>
>If these are indeed, AI generated contributions or reviews they should be disclosed beforehand. Also there is the Assisted-by: tag. Also note that developer must take full responsibility for the contribution which means understanding it completely.
>
>https://docs.kernel.org/process/coding-assistants.html#signed-off-by-and-developer-certificate-of-origin
>
>Thanks,
>Fernando.
Hi Fernando,
About the Reviewed-by tag, that was my mistake. I forgot to remove it
when rebasing. And about AI. I’ve been using it to help format my
emails and translate them into English since it isn't my native
language. However, the technical logic and the code itself are my own
work, written without AI. Should I send v5, and if so, what should I
do besides stripping the Reviewed-by tag? I've read the documentation
on coding assistants you linked and will make sure to follow it on the
next revision.
Best regards,
Luka Gejak
^ permalink raw reply
* Re: [PATCH net] net: ethernet: cortina: Fix SKB leak
From: Li Xiasong @ 2026-04-01 11:06 UTC (permalink / raw)
To: Linus Walleij
Cc: Hans Ulli Kroll, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Michał Mirosław, netdev,
Andreas Haarmann-Thiemann, yuehaibing, zhangchangzhong,
weiyongjun1
In-Reply-To: <20260330-gemini-ethernet-fix-v1-1-18783a45d13a@kernel.org>
Hi,Linus
On 3/30/2026 2:00 PM, Linus Walleij wrote:
> From: Andreas Haarmann-Thiemann <eitschman@nebelreich.de>
>
> Under sustained RX load (e.g. large file transfers over the network), the
> device freezes completely and requires a hard power cycle. No kernel panic
> or oops is produced; the system simply stops responding.
>
> In gmac_rx() (drivers/net/ethernet/cortina/gemini.c), when
> gmac_get_queue_page() returns NULL for the second page of a multi-page
> fragment, the driver logs an error and continues — but does not free the
> in-progress skb that was already being assembled via napi_build_skb() /
> napi_get_frags():
>
> gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
> if (!gpage) {
> dev_err(geth->dev, "could not find mapping\n");
> /* BUG: skb leaked here */
> port->stats.rx_dropped++;
> continue;
> }
>
> This path is distinct from the similar block in gmac_cleanup_rxq(), which
> correctly only logs "could not find page" without an skb in flight.
>
> Each occurrence of this error path leaks one skb. Under sustained traffic
> the leak exhausts kernel memory, causing the observed lockup.
>
> Free the in-progress skb via napi_free_frags() before continuing, matching
> the pattern already used elsewhere in the driver.
>
> Fixes: 4d5ae32f5e1e ("net: ethernet: Add a driver for Gemini gigabit ethernet")
> Signed-off-by: Andreas Haarmann-Thiemann <eitschman@nebelreich.de>
> Signed-off-by: Linus Walleij <linusw@kernel.org>
> ---
> drivers/net/ethernet/cortina/gemini.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
> index 4824232f4890..723d90d5fdf3 100644
> --- a/drivers/net/ethernet/cortina/gemini.c
> +++ b/drivers/net/ethernet/cortina/gemini.c
> @@ -1491,6 +1491,10 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
> gpage = gmac_get_queue_page(geth, port, mapping + PAGE_SIZE);
> if (!gpage) {
> dev_err(geth->dev, "could not find mapping\n");
> + if (skb) {
> + napi_free_frags(&port->napi);
> + skb = NULL;
Quick question out of curiosity.
In the fix at gmac_rx(), when gmac_get_queue_page() fails for the second
page of a multi-page fragment, the SKB is freed via napi_free_frags().
However, I noticed that port->stats.rx_dropped++ is not incremented here.
Comparing with the similar code path, when a stale SKB is found at SOF_BIT,
both napi_free_frags() and rx_dropped++ are called. Would it make sense to
add the drop counter here for consistency, or is there a reason to omit it.
Thanks for your time,
Li Xiasong
> + }
> continue;
> }
> page = gpage->page;
>
> ---
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
> change-id: 20260330-gemini-ethernet-fix-604c28c53da1
>
> Best regards,
^ permalink raw reply
* [PATCH bpf v5 2/2] selftests/bpf: Add protocol check test for bpf_sk_assign_tcp_reqsk()
From: Jiayuan Chen @ 2026-04-01 11:04 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Martin KaFai Lau, Daniel Borkmann, John Fastabend,
Stanislav Fomichev, Alexei Starovoitov, Andrii Nakryiko,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Shuah Khan, Kuniyuki Iwashima, netdev,
linux-kernel, linux-kselftest
In-Reply-To: <20260401110511.73355-1-jiayuan.chen@linux.dev>
Add test_tcp_custom_syncookie_protocol_check to verify that
bpf_sk_assign_tcp_reqsk() rejects non-TCP skbs. The test sends a UDP
packet through TC ingress where a BPF program calls
bpf_sk_assign_tcp_reqsk() on it and checks that the kfunc returns an
error. A UDP server recv() is used as synchronization to ensure the
BPF program has finished processing before checking the result.
Without the fix in bpf_sk_assign_tcp_reqsk(), the kfunc succeeds and
attaches a TCP reqsk to the UDP skb, which causes a null pointer
dereference panic when the kernel processes it through the UDP receive
path.
Test result:
./test_progs -a tcp_custom_syncookie_protocol_check -v
setup_netns:PASS:create netns 0 nsec
setup_netns:PASS:ip 0 nsec
write_sysctl:PASS:open sysctl 0 nsec
write_sysctl:PASS:write sysctl 0 nsec
setup_netns:PASS:write_sysctl 0 nsec
test_tcp_custom_syncookie_protocol_check:PASS:open_and_load 0 nsec
setup_tc:PASS:qdisc add dev lo clsact 0 nsec
setup_tc:PASS:filter add dev lo ingress 0 nsec
run_protocol_check:PASS:start tcp_server 0 nsec
run_protocol_check:PASS:start udp_server 0 nsec
run_protocol_check:PASS:connect udp_client 0 nsec
run_protocol_check:PASS:send udp 0 nsec
run_protocol_check:PASS:recv udp 0 nsec
run_protocol_check:PASS:recv data 0 nsec
run_protocol_check:PASS:udp_intercepted 0 nsec
run_protocol_check:PASS:assign_ret 0 nsec
#471/1 tcp_custom_syncookie_protocol_check/IPv4 TCP:OK
run_protocol_check:PASS:start tcp_server 0 nsec
run_protocol_check:PASS:start udp_server 0 nsec
run_protocol_check:PASS:connect udp_client 0 nsec
run_protocol_check:PASS:send udp 0 nsec
run_protocol_check:PASS:recv udp 0 nsec
run_protocol_check:PASS:recv data 0 nsec
run_protocol_check:PASS:udp_intercepted 0 nsec
run_protocol_check:PASS:assign_ret 0 nsec
#471/2 tcp_custom_syncookie_protocol_check/IPv6 TCP:OK
#471 tcp_custom_syncookie_protocol_check:OK
Summary: 1/2 PASSED, 0 SKIPPED, 0 FAILED
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
.../bpf/prog_tests/tcp_custom_syncookie.c | 93 ++++++++++++++-
.../bpf/progs/test_tcp_custom_syncookie.c | 109 ++++++++++++++++++
2 files changed, 198 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c b/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
index eaf441dc7e79..017836581669 100644
--- a/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
+++ b/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
@@ -5,6 +5,7 @@
#include <sched.h>
#include <stdlib.h>
#include <net/if.h>
+#include <netinet/in.h>
#include "test_progs.h"
#include "cgroup_helpers.h"
@@ -47,11 +48,10 @@ static int setup_netns(void)
return -1;
}
-static int setup_tc(struct test_tcp_custom_syncookie *skel)
+static int setup_tc(int prog_fd)
{
LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = BPF_TC_INGRESS);
- LIBBPF_OPTS(bpf_tc_opts, tc_attach,
- .prog_fd = bpf_program__fd(skel->progs.tcp_custom_syncookie));
+ LIBBPF_OPTS(bpf_tc_opts, tc_attach, .prog_fd = prog_fd);
qdisc_lo.ifindex = if_nametoindex("lo");
if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo clsact"))
@@ -127,7 +127,7 @@ void test_tcp_custom_syncookie(void)
if (!ASSERT_OK_PTR(skel, "open_and_load"))
return;
- if (setup_tc(skel))
+ if (setup_tc(bpf_program__fd(skel->progs.tcp_custom_syncookie)))
goto destroy_skel;
for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
@@ -145,6 +145,91 @@ void test_tcp_custom_syncookie(void)
destroy_skel:
system("tc qdisc del dev lo clsact");
+ test_tcp_custom_syncookie__destroy(skel);
+}
+
+/* Test: bpf_sk_assign_tcp_reqsk() should reject non-TCP skb.
+ *
+ * Send a UDP packet through TC ingress where a BPF program calls
+ * bpf_sk_assign_tcp_reqsk() on it. The kfunc should return an error
+ * because the skb carries UDP, not TCP.
+ *
+ * TCP and UDP servers share the same port. The BPF program intercepts
+ * the UDP packet, looks up the TCP listener via the dest port, and
+ * attempts to assign a TCP reqsk to the UDP skb.
+ */
+static void run_protocol_check(struct test_tcp_custom_syncookie *skel,
+ int family, const char *addr)
+{
+ int tcp_server, udp_server, udp_client;
+ char buf[] = "test";
+ int port, ret;
+
+ tcp_server = start_server(family, SOCK_STREAM, addr, 0, 0);
+ if (!ASSERT_NEQ(tcp_server, -1, "start tcp_server"))
+ return;
+
+ port = ntohs(get_socket_local_port(tcp_server));
+
+ /* UDP server on same port for synchronization and port sharing */
+ udp_server = start_server(family, SOCK_DGRAM, addr, port, 0);
+ if (!ASSERT_NEQ(udp_server, -1, "start udp_server"))
+ goto close_tcp;
+
+ skel->bss->udp_intercepted = false;
+ skel->bss->assign_ret = 0;
+
+ udp_client = connect_to_fd(udp_server, 0);
+ if (!ASSERT_NEQ(udp_client, -1, "connect udp_client"))
+ goto close_udp_server;
+
+ ret = send(udp_client, buf, sizeof(buf), 0);
+ if (!ASSERT_EQ(ret, sizeof(buf), "send udp"))
+ goto close_udp_client;
+
+ memset(buf, 0, sizeof(buf));
+
+ /* recv() ensures TC ingress BPF has processed the skb */
+ ret = recv(udp_server, buf, sizeof(buf), 0);
+ if (!ASSERT_EQ(ret, sizeof(buf), "recv udp"))
+ goto close_udp_client;
+
+ ASSERT_STREQ(buf, "test", "recv data");
+ ASSERT_EQ(skel->bss->udp_intercepted, true, "udp_intercepted");
+ ASSERT_EQ(skel->bss->assign_ret, -EINVAL, "assign_ret");
+
+close_udp_client:
+ close(udp_client);
+close_udp_server:
+ close(udp_server);
+close_tcp:
+ close(tcp_server);
+}
+
+void test_tcp_custom_syncookie_protocol_check(void)
+{
+ struct test_tcp_custom_syncookie *skel;
+ int i;
+
+ if (setup_netns())
+ return;
+
+ skel = test_tcp_custom_syncookie__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open_and_load"))
+ return;
+
+ if (setup_tc(bpf_program__fd(skel->progs.tcp_custom_syncookie_badproto)))
+ goto destroy_skel;
+
+ for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
+ if (!test__start_subtest(test_cases[i].name))
+ continue;
+ run_protocol_check(skel, test_cases[i].family,
+ test_cases[i].addr);
+ }
+
+destroy_skel:
+ system("tc qdisc del dev lo clsact");
test_tcp_custom_syncookie__destroy(skel);
}
diff --git a/tools/testing/selftests/bpf/progs/test_tcp_custom_syncookie.c b/tools/testing/selftests/bpf/progs/test_tcp_custom_syncookie.c
index 7d5293de1952..331435c837cc 100644
--- a/tools/testing/selftests/bpf/progs/test_tcp_custom_syncookie.c
+++ b/tools/testing/selftests/bpf/progs/test_tcp_custom_syncookie.c
@@ -588,4 +588,113 @@ int tcp_custom_syncookie(struct __sk_buff *skb)
return tcp_handle_ack(&ctx);
}
+/* Test: call bpf_sk_assign_tcp_reqsk() on a UDP skb.
+ * The kfunc should reject it because the skb is not TCP.
+ *
+ * TCP and UDP servers share the same port. The BPF program intercepts
+ * UDP packets, looks up the TCP listener on the same port, and tries
+ * to assign a TCP reqsk to the UDP skb.
+ */
+int assign_ret;
+bool udp_intercepted;
+
+static int badproto_lookup_assign(struct __sk_buff *skb, struct udphdr *udp,
+ struct bpf_sock_tuple *tuple, u32 tuple_size)
+{
+ struct bpf_tcp_req_attrs attrs = {};
+ struct bpf_sock *skc;
+ struct sock *sk;
+
+ skc = bpf_skc_lookup_tcp(skb, tuple, tuple_size, -1, 0);
+ if (!skc)
+ return TC_ACT_OK;
+
+ if (skc->state != TCP_LISTEN) {
+ bpf_sk_release(skc);
+ return TC_ACT_OK;
+ }
+
+ sk = (struct sock *)bpf_skc_to_tcp_sock(skc);
+ if (!sk) {
+ bpf_sk_release(skc);
+ return TC_ACT_OK;
+ }
+
+ attrs.mss = 1460;
+ attrs.wscale_ok = 1;
+ attrs.snd_wscale = 7;
+ attrs.rcv_wscale = 7;
+ attrs.sack_ok = 1;
+
+ assign_ret = bpf_sk_assign_tcp_reqsk(skb, sk, &attrs, sizeof(attrs));
+
+ bpf_sk_release(skc);
+ return TC_ACT_OK;
+}
+
+SEC("tc")
+int tcp_custom_syncookie_badproto(struct __sk_buff *skb)
+{
+ void *data = (void *)(long)skb->data;
+ void *data_end = (void *)(long)skb->data_end;
+ struct bpf_sock_tuple tuple = {};
+ struct ethhdr *eth;
+ struct iphdr *iph;
+ struct ipv6hdr *ip6h;
+ struct udphdr *udp;
+
+ eth = (struct ethhdr *)data;
+ if (eth + 1 > data_end)
+ return TC_ACT_OK;
+
+ switch (bpf_ntohs(eth->h_proto)) {
+ case ETH_P_IP:
+ iph = (struct iphdr *)(eth + 1);
+ if (iph + 1 > data_end)
+ return TC_ACT_OK;
+
+ if (iph->protocol != IPPROTO_UDP)
+ return TC_ACT_OK;
+
+ udp = (struct udphdr *)(iph + 1);
+ if (udp + 1 > data_end)
+ return TC_ACT_OK;
+
+ udp_intercepted = true;
+
+ tuple.ipv4.saddr = iph->saddr;
+ tuple.ipv4.daddr = iph->daddr;
+ tuple.ipv4.sport = udp->source;
+ tuple.ipv4.dport = udp->dest;
+
+ return badproto_lookup_assign(skb, udp, &tuple,
+ sizeof(tuple.ipv4));
+ case ETH_P_IPV6:
+ ip6h = (struct ipv6hdr *)(eth + 1);
+ if (ip6h + 1 > data_end)
+ return TC_ACT_OK;
+
+ if (ip6h->nexthdr != IPPROTO_UDP)
+ return TC_ACT_OK;
+
+ udp = (struct udphdr *)(ip6h + 1);
+ if (udp + 1 > data_end)
+ return TC_ACT_OK;
+
+ udp_intercepted = true;
+
+ __builtin_memcpy(tuple.ipv6.saddr, &ip6h->saddr,
+ sizeof(tuple.ipv6.saddr));
+ __builtin_memcpy(tuple.ipv6.daddr, &ip6h->daddr,
+ sizeof(tuple.ipv6.daddr));
+ tuple.ipv6.sport = udp->source;
+ tuple.ipv6.dport = udp->dest;
+
+ return badproto_lookup_assign(skb, udp, &tuple,
+ sizeof(tuple.ipv6));
+ default:
+ return TC_ACT_OK;
+ }
+}
+
char _license[] SEC("license") = "GPL";
--
2.43.0
^ permalink raw reply related
* [PATCH bpf v5 1/2] bpf: tcp: Reject non-TCP skb in bpf_sk_assign_tcp_reqsk()
From: Jiayuan Chen @ 2026-04-01 11:04 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Kuniyuki Iwashima, Martin KaFai Lau,
Daniel Borkmann, John Fastabend, Stanislav Fomichev,
Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Shuah Khan, netdev, linux-kernel, linux-kselftest
In-Reply-To: <20260401110511.73355-1-jiayuan.chen@linux.dev>
bpf_sk_assign_tcp_reqsk() only validates skb->protocol (L3) but does not
check the L4 protocol in the IP header. A BPF program can call this kfunc
on a UDP skb with a valid TCP listener socket, which will succeed and
attach a TCP reqsk to the UDP skb.
When the UDP skb enters the UDP receive path, skb_steal_sock() returns
the TCP listener from the reqsk. The UDP code then passes this TCP socket
to udp_unicast_rcv_skb() -> __udp_enqueue_schedule_skb(), which casts
it to udp_sock and accesses UDP-specific fields at invalid offsets,
causing a null pointer dereference and kernel panic:
BUG: KASAN: null-ptr-deref in __udp_enqueue_schedule_skb+0x19d/0x1df0
Read of size 4 at addr 0000000000000008 by task test_progs/537
CPU: 1 UID: 0 PID: 537 Comm: test_progs Not tainted 7.0.0-rc4+ #46 PREEMPT
Call Trace:
<IRQ>
dump_stack_lvl (lib/dump_stack.c:123)
print_report (mm/kasan/report.c:487)
kasan_report (mm/kasan/report.c:597)
__kasan_check_read (mm/kasan/shadow.c:32)
__udp_enqueue_schedule_skb (net/ipv4/udp.c:1719)
udp_queue_rcv_one_skb (net/ipv4/udp.c:2370 net/ipv4/udp.c:2500)
udp_queue_rcv_skb (net/ipv4/udp.c:2532)
udp_unicast_rcv_skb (net/ipv4/udp.c:2684)
__udp4_lib_rcv (net/ipv4/udp.c:2742)
udp_rcv (net/ipv4/udp.c:2937)
ip_protocol_deliver_rcu (net/ipv4/ip_input.c:209)
ip_local_deliver_finish (./include/linux/rcupdate.h:879 net/ipv4/ip_input.c:242)
ip_local_deliver (net/ipv4/ip_input.c:265)
__netif_receive_skb_one_core (net/core/dev.c:6164 (discriminator 4))
__netif_receive_skb (net/core/dev.c:6280)
Fix this by checking the IP header's protocol field in
bpf_sk_assign_tcp_reqsk() and rejecting non-TCP skbs with -EINVAL.
Note that for IPv6, the nexthdr check does not walk extension headers.
This is uncommon for TCP SYN packets in practice, and keeping it simple
was agreed upon by Kuniyuki Iwashima.
Fixes: e472f88891ab ("bpf: tcp: Support arbitrary SYN Cookie.")
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
net/core/filter.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/core/filter.c b/net/core/filter.c
index 78b548158fb0..f251744025e2 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12248,11 +12248,23 @@ __bpf_kfunc int bpf_sk_assign_tcp_reqsk(struct __sk_buff *s, struct sock *sk,
switch (skb->protocol) {
case htons(ETH_P_IP):
+ if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ return -EINVAL;
+
+ if (ip_hdr(skb)->protocol != IPPROTO_TCP)
+ return -EINVAL;
+
ops = &tcp_request_sock_ops;
min_mss = 536;
break;
#if IS_BUILTIN(CONFIG_IPV6)
case htons(ETH_P_IPV6):
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ return -EINVAL;
+
+ if (ipv6_hdr(skb)->nexthdr != IPPROTO_TCP)
+ return -EINVAL;
+
ops = &tcp6_request_sock_ops;
min_mss = IPV6_MIN_MTU - 60;
break;
--
2.43.0
^ permalink raw reply related
* [PATCH bpf v5 0/2] bpf: tcp: Fix null-ptr-deref in arbitrary SYN Cookie
From: Jiayuan Chen @ 2026-04-01 11:04 UTC (permalink / raw)
To: bpf
Cc: Jiayuan Chen, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Shuah Khan, Jiayuan Chen,
Kuniyuki Iwashima, netdev, linux-kernel, linux-kselftest
From: Jiayuan Chen <jiayuan.chen@shopee.com>
bpf_sk_assign_tcp_reqsk() does not validate the L4 protocol of the skb,
only checking skb->protocol (L3). A BPF program that calls this kfunc on
a non-TCP skb (e.g. UDP) will succeed, attaching a TCP reqsk to the skb.
When the skb enters the UDP receive path, skb_steal_sock() returns the
TCP listener socket from the reqsk. The UDP code then casts this TCP
socket to udp_sock and accesses UDP-specific fields at invalid offsets,
causing a null pointer dereference:
BUG: KASAN: null-ptr-deref in __udp_enqueue_schedule_skb+0x19d/0x1df0
Read of size 4 at addr 0000000000000008 by task test_progs/537
CPU: 1 UID: 0 PID: 537 Comm: test_progs Not tainted 7.0.0-rc4+ #46 PREEMPT
Call Trace:
<IRQ>
dump_stack_lvl (lib/dump_stack.c:123)
print_report (mm/kasan/report.c:487)
kasan_report (mm/kasan/report.c:597)
__kasan_check_read (mm/kasan/shadow.c:32)
__udp_enqueue_schedule_skb (net/ipv4/udp.c:1719)
udp_queue_rcv_one_skb (net/ipv4/udp.c:2370 net/ipv4/udp.c:2500)
udp_queue_rcv_skb (net/ipv4/udp.c:2532)
udp_unicast_rcv_skb (net/ipv4/udp.c:2684)
__udp4_lib_rcv (net/ipv4/udp.c:2742)
udp_rcv (net/ipv4/udp.c:2937)
ip_protocol_deliver_rcu (net/ipv4/ip_input.c:209)
ip_local_deliver_finish (./include/linux/rcupdate.h:879 net/ipv4/ip_input.c:242)
ip_local_deliver (net/ipv4/ip_input.c:265)
__netif_receive_skb_one_core (net/core/dev.c:6164 (discriminator 4))
__netif_receive_skb (net/core/dev.c:6280)
Solution
Patch 1: Add L4 protocol validation in bpf_sk_assign_tcp_reqsk(). Check
ip_hdr(skb)->protocol (IPv4) and ipv6_hdr(skb)->nexthdr (IPv6) against
IPPROTO_TCP, returning -EINVAL for non-TCP skbs.
Patch 2: Add selftest that calls bpf_sk_assign_tcp_reqsk() on a UDP skb
and verifies the kfunc rejects it.
---
v1: https://lore.kernel.org/bpf/20260323105510.51990-1-jiayuan.chen@linux.dev/
v2: https://lore.kernel.org/bpf/20260326062657.88446-1-jiayuan.chen@linux.dev/
v3: https://lore.kernel.org/bpf/20260327133915.286037-1-jiayuan.chen@linux.dev/
v4: https://lore.kernel.org/bpf/20260330080746.319680-1-jiayuan.chen@linux.dev/
Changes in v5:
- Add pskb_may_pull before accessing IP/IPv6 headers in kfunc
- Use buf[] instead of buf[32], verify recv data with ASSERT_STREQ
- Remove unnecessary variable initializations in selftest and BPF
Changes in v4:
- Check if assign_ret is EINVAL instead of checking if it is 0
Changes in v3:
- Add IPv6 test coverage, reuse test_cases[] to iterate over both
address families
- Share TCP/UDP port to simplify BPF program, remove unnecessary
global variables
- Use connect_to_fd() + send()/recv() instead of manual sockaddr
construction
- Suggested by Kuniyuki Iwashima
Changes in v2:
- Add Reviewed-by tag from Kuniyuki Iwashima for patch 1
- Use UDP socket recv() instead of kern_sync_rcu() for synchronization
in selftest
Jiayuan Chen (2):
bpf: tcp: Reject non-TCP skb in bpf_sk_assign_tcp_reqsk()
selftests/bpf: Add protocol check test for bpf_sk_assign_tcp_reqsk()
net/core/filter.c | 12 ++
.../bpf/prog_tests/tcp_custom_syncookie.c | 93 ++++++++++++++-
.../bpf/progs/test_tcp_custom_syncookie.c | 109 ++++++++++++++++++
3 files changed, 210 insertions(+), 4 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH net v4 15/15] rxrpc: fix reference count leak in rxrpc_server_keyring()
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Luxiao Xu,
Yifan Wu, Juefei Pu, Yuan Tan, Xin Liu, Ren Wei, Ren Wei,
Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Luxiao Xu <rakukuip@gmail.com>
This patch fixes a reference count leak in rxrpc_server_keyring()
by checking if rx->securities is already set.
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/server_key.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
index 36b05fd842a7..d4777851079f 100644
--- a/net/rxrpc/server_key.c
+++ b/net/rxrpc/server_key.c
@@ -125,6 +125,9 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
_enter("");
+ if (rx->securities)
+ return -EEXIST;
+
if (optlen <= 0 || optlen > PAGE_SIZE - 1)
return -EINVAL;
^ permalink raw reply related
* [PATCH net v4 14/15] rxrpc: fix oversized RESPONSE authenticator length check
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Keenan Dong,
Simon Horman, Willy Tarreau, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Keenan Dong <keenanat2000@gmail.com>
rxgk_verify_response() decodes auth_len from the packet and is supposed
to verify that it fits in the remaining bytes. The existing check is
inverted, so oversized RESPONSE authenticators are accepted and passed
to rxgk_decrypt_skb(), which can later reach skb_to_sgvec() with an
impossible length and hit BUG_ON(len).
Decoded from the original latest-net reproduction logs with
scripts/decode_stacktrace.sh:
RIP: __skb_to_sgvec()
[net/core/skbuff.c:5285 (discriminator 1)]
Call Trace:
skb_to_sgvec() [net/core/skbuff.c:5305]
rxgk_decrypt_skb() [net/rxrpc/rxgk_common.h:81]
rxgk_verify_response() [net/rxrpc/rxgk.c:1268]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]
process_one_work() [kernel/workqueue.c:3281]
worker_thread()
[kernel/workqueue.c:3353 kernel/workqueue.c:3440]
kthread() [kernel/kthread.c:436]
ret_from_fork() [arch/x86/kernel/process.c:164]
Reject authenticator lengths that exceed the remaining packet payload.
Fixes: 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)")
Signed-off-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: Willy Tarreau <w@1wt.eu>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/rxgk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
index 01dbdf0b5cf2..9e4a4ff28913 100644
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -1224,7 +1224,7 @@ static int rxgk_verify_response(struct rxrpc_connection *conn,
auth_offset = offset;
auth_len = ntohl(xauth_len);
- if (auth_len < len)
+ if (auth_len > len)
goto short_packet;
if (auth_len & 3)
goto inconsistent;
^ permalink raw reply related
* [PATCH net v4 13/15] rxrpc: fix RESPONSE authenticator parser OOB read
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Keenan Dong,
Simon Horman, Willy Tarreau, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Keenan Dong <keenanat2000@gmail.com>
rxgk_verify_authenticator() copies auth_len bytes into a temporary
buffer and then passes p + auth_len as the parser limit to
rxgk_do_verify_authenticator(). Since p is a __be32 *, that inflates the
parser end pointer by a factor of four and lets malformed RESPONSE
authenticators read past the kmalloc() buffer.
Decoded from the original latest-net reproduction logs with
scripts/decode_stacktrace.sh:
BUG: KASAN: slab-out-of-bounds in rxgk_verify_response()
Call Trace:
dump_stack_lvl() [lib/dump_stack.c:123]
print_report() [mm/kasan/report.c:379 mm/kasan/report.c:482]
kasan_report() [mm/kasan/report.c:597]
rxgk_verify_response()
[net/rxrpc/rxgk.c:1103 net/rxrpc/rxgk.c:1167
net/rxrpc/rxgk.c:1274]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]
process_one_work() [kernel/workqueue.c:3281]
worker_thread()
[kernel/workqueue.c:3353 kernel/workqueue.c:3440]
kthread() [kernel/kthread.c:436]
ret_from_fork() [arch/x86/kernel/process.c:164]
Allocated by task 54:
rxgk_verify_response()
[include/linux/slab.h:954 net/rxrpc/rxgk.c:1155
net/rxrpc/rxgk.c:1274]
rxrpc_process_connection()
[net/rxrpc/conn_event.c:266 net/rxrpc/conn_event.c:364
net/rxrpc/conn_event.c:386]
Convert the byte count to __be32 units before constructing the parser
limit.
Fixes: 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)")
Signed-off-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: Willy Tarreau <w@1wt.eu>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/rxgk.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
index f9f5a2dc62ed..01dbdf0b5cf2 100644
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -1164,7 +1164,8 @@ static int rxgk_verify_authenticator(struct rxrpc_connection *conn,
}
p = auth;
- ret = rxgk_do_verify_authenticator(conn, krb5, skb, p, p + auth_len);
+ ret = rxgk_do_verify_authenticator(conn, krb5, skb, p,
+ p + auth_len / sizeof(*p));
error:
kfree(auth);
return ret;
^ permalink raw reply related
* [PATCH net v4 12/15] rxrpc: reject undecryptable rxkad response tickets
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Yuqi Xu,
Yifan Wu, Juefei Pu, Yuan Tan, Xin Liu, Ren Wei, Ren Wei,
Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Yuqi Xu <xuyuqiabc@gmail.com>
rxkad_decrypt_ticket() decrypts the RXKAD response ticket and then
parses the buffer as plaintext without checking whether
crypto_skcipher_decrypt() succeeded.
A malformed RESPONSE can therefore use a non-block-aligned ticket
length, make the decrypt operation fail, and still drive the ticket
parser with attacker-controlled bytes.
Check the decrypt result and abort the connection with RXKADBADTICKET
when ticket decryption fails.
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Co-developed-by: Yuan Tan <yuantan098@gmail.com>
Signed-off-by: Yuan Tan <yuantan098@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Tested-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Yuqi Xu <xuyuqiabc@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/rxkad.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index e923d6829008..0f79d694cb08 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -958,6 +958,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
struct in_addr addr;
unsigned int life;
time64_t issue, now;
+ int ret;
bool little_endian;
u8 *p, *q, *name, *end;
@@ -977,8 +978,11 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
sg_init_one(&sg[0], ticket, ticket_len);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x);
- crypto_skcipher_decrypt(req);
+ ret = crypto_skcipher_decrypt(req);
skcipher_request_free(req);
+ if (ret < 0)
+ return rxrpc_abort_conn(conn, skb, RXKADBADTICKET, -EPROTO,
+ rxkad_abort_resp_tkt_short);
p = ticket;
end = p + ticket_len;
^ permalink raw reply related
* [PATCH net v4 11/15] rxrpc: Only put the call ref if one was acquired
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Douya Le,
Yifan Wu, Juefei Pu, Yuan Tan, Xin Liu, Ao Zhou, Simon Horman,
stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Douya Le <ldy3087146292@gmail.com>
rxrpc_input_packet_on_conn() can process a to-client packet after the
current client call on the channel has already been torn down. In that
case chan->call is NULL, rxrpc_try_get_call() returns NULL and there is
no reference to drop.
The client-side implicit-end error path does not account for that and
unconditionally calls rxrpc_put_call(). This turns a protocol error
path into a kernel crash instead of rejecting the packet.
Only drop the call reference if one was actually acquired. Keep the
existing protocol error handling unchanged.
Fixes: 5e6ef4f1017c ("rxrpc: Make the I/O thread take over the call and local processor work")
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Co-developed-by: Yuan Tan <tanyuan98@gmail.com>
Signed-off-by: Yuan Tan <tanyuan98@gmail.com>
Suggested-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Ao Zhou <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/io_thread.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index e939ecf417c4..697956931925 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -419,7 +419,8 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
if (sp->hdr.callNumber > chan->call_id) {
if (rxrpc_to_client(sp)) {
- rxrpc_put_call(call, rxrpc_call_put_input);
+ if (call)
+ rxrpc_put_call(call, rxrpc_call_put_input);
return rxrpc_protocol_error(skb,
rxrpc_eproto_unexpected_implicit_end);
}
^ permalink raw reply related
* [PATCH net v4 10/15] rxrpc: Fix to request an ack if window is limited
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Marc Dionne,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Marc Dionne <marc.c.dionne@gmail.com>
Peers may only send immediate acks for every 2 UDP packets received.
When sending a jumbogram, it is important to check that there is
sufficient window space to send another same sized jumbogram following
the current one, and request an ack if there isn't. Failure to do so may
cause the call to stall waiting for an ack until the resend timer fires.
Where jumbograms are in use this causes a very significant drop in
performance.
Fixes: fe24a5494390 ("rxrpc: Send jumbo DATA packets")
Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/ar-internal.h | 2 +-
net/rxrpc/output.c | 2 ++
net/rxrpc/proc.c | 5 +++--
4 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index f7f559204b87..578b8038b211 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -521,6 +521,7 @@
#define rxrpc_req_ack_traces \
EM(rxrpc_reqack_ack_lost, "ACK-LOST ") \
EM(rxrpc_reqack_app_stall, "APP-STALL ") \
+ EM(rxrpc_reqack_jumbo_win, "JUMBO-WIN ") \
EM(rxrpc_reqack_more_rtt, "MORE-RTT ") \
EM(rxrpc_reqack_no_srv_last, "NO-SRVLAST") \
EM(rxrpc_reqack_old_rtt, "OLD-RTT ") \
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 36d6ca0d1089..96ecb83c9071 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -117,7 +117,7 @@ struct rxrpc_net {
atomic_t stat_tx_jumbo[10];
atomic_t stat_rx_jumbo[10];
- atomic_t stat_why_req_ack[8];
+ atomic_t stat_why_req_ack[9];
atomic_t stat_io_loop;
};
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index d70db367e358..870e59bf06af 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -479,6 +479,8 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call,
why = rxrpc_reqack_old_rtt;
else if (!last && !after(READ_ONCE(call->send_top), txb->seq))
why = rxrpc_reqack_app_stall;
+ else if (call->tx_winsize <= (2 * req->n) || call->cong_cwnd <= (2 * req->n))
+ why = rxrpc_reqack_jumbo_win;
else
goto dont_set_request_ack;
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 59292f7f9205..7755fca5beb8 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -518,11 +518,12 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]),
atomic_read(&rxnet->stat_rx_acks[0]));
seq_printf(seq,
- "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u\n",
+ "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u jwin=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]),
- atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]));
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]),
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_jumbo_win]));
seq_printf(seq,
"Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]),
^ permalink raw reply related
* [PATCH net v4 09/15] rxrpc: Fix key reference count leak from call->key
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Anderson Nascimento, Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Anderson Nascimento <anderson@allelesecurity.com>
When creating a client call in rxrpc_alloc_client_call(), the code obtains
a reference to the key. This is never cleaned up and gets leaked when the
call is destroyed.
Fix this by freeing call->key in rxrpc_destroy_call().
Before the patch, it shows the key reference counter elevated:
$ cat /proc/keys | grep afs@54321
1bffe9cd I--Q--i 8053480 4169w 3b010000 1000 1000 rxrpc afs@54321: ka
$
After the patch, the invalidated key is removed when the code exits:
$ cat /proc/keys | grep afs@54321
$
Fixes: f3441d4125fc ("rxrpc: Copy client call parameters into rxrpc_call earlier")
Signed-off-by: Anderson Nascimento <anderson@allelesecurity.com>
Co-developed-by: David Howells <dhowells@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/call_object.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 59329cfe1532..f035f486c139 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -692,6 +692,7 @@ static void rxrpc_destroy_call(struct work_struct *work)
rxrpc_put_bundle(call->bundle, rxrpc_bundle_put_call);
rxrpc_put_peer(call->peer, rxrpc_peer_put_call);
rxrpc_put_local(call->local, rxrpc_local_put_call);
+ key_put(call->key);
call_rcu(&call->rcu, rxrpc_rcu_free_call);
}
^ permalink raw reply related
* [PATCH net v4 08/15] rxrpc: Fix keyring reference count leak in rxrpc_setsockopt()
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Anderson Nascimento, Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Anderson Nascimento <anderson@allelesecurity.com>
In rxrpc_setsockopt(), the code checks 'rx->key' when handling the
RXRPC_SECURITY_KEYRING option. However, this appears to be a logic error.
The code should be checking 'rx->securities' to determine if a keyring has
already been defined for the socket.
Currently, if a user calls setsockopt(RXRPC_SECURITY_KEYRING) multiple
times on the same socket, the check 'if (rx->key)' fails to block
subsequent calls because 'rx->key' has not been defined by the function.
This results in a reference count leak on the keyring.
This patch changes the check to 'rx->securities' to correctly identify if
the socket security keyring has already been configured, returning -EINVAL
on subsequent attempts.
Before the patch:
It shows the keyring reference counter elevated.
$ cat /proc/keys | grep AFSkeys1
27aca8ae I--Q--- 24469721 perm 3f010000 1000 1000 keyring AFSkeys1: empty
$
After the patch:
The keyring reference counter remains stable and subsequent calls return an
error:
$ ./poc
setsockopt: Invalid argument
$
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Signed-off-by: Anderson Nascimento <anderson@allelesecurity.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/af_rxrpc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0f90272ac254..0b7ed99a3025 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -665,7 +665,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
case RXRPC_SECURITY_KEYRING:
ret = -EINVAL;
- if (rx->key)
+ if (rx->securities)
goto error;
ret = -EISCONN;
if (rx->sk.sk_state != RXRPC_UNBOUND)
^ permalink raw reply related
* [PATCH net v4 07/15] rxrpc: Fix rack timer warning to report unexpected mode
From: David Howells @ 2026-04-01 10:56 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Alok Tiwari,
Simon Horman, Jeffrey Altman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Alok Tiwari <alok.a.tiwari@oracle.com>
rxrpc_rack_timer_expired() clears call->rack_timer_mode to OFF before
the switch. The default case warning therefore always prints OFF and
doesn't identify the unexpected timer mode.
Log the saved mode value instead so the warning reports the actual
unexpected rack timer mode.
Fixes: 7c482665931b ("rxrpc: Implement RACK/TLP to deal with transmission stalls [RFC8985]")
Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/input_rack.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/input_rack.c b/net/rxrpc/input_rack.c
index 13c371261e0a..9eb109ffba56 100644
--- a/net/rxrpc/input_rack.c
+++ b/net/rxrpc/input_rack.c
@@ -413,6 +413,6 @@ void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by)
break;
//case RXRPC_CALL_RACKTIMER_ZEROWIN:
default:
- pr_warn("Unexpected rack timer %u", call->rack_timer_mode);
+ pr_warn("Unexpected rack timer %u", mode);
}
}
^ permalink raw reply related
* [PATCH net v4 06/15] rxrpc: Fix use of wrong skb when comparing queued RESP challenge serial
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Alok Tiwari,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Alok Tiwari <alok.a.tiwari@oracle.com>
In rxrpc_post_response(), the code should be comparing the challenge serial
number from the cached response before deciding to switch to a newer
response, but looks at the newer packet private data instead, rendering the
comparison always false.
Fix this by switching to look at the older packet.
Fix further[1] to substitute the new packet in place of the old one if
newer and also to release whichever we don't use.
Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE")
Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
Link: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com [1]
---
include/trace/events/rxrpc.h | 1 +
net/rxrpc/conn_event.c | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index a826cd80007b..f7f559204b87 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -185,6 +185,7 @@
EM(rxrpc_skb_put_input, "PUT input ") \
EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \
EM(rxrpc_skb_put_oob, "PUT oob ") \
+ EM(rxrpc_skb_put_old_response, "PUT old-resp ") \
EM(rxrpc_skb_put_purge, "PUT purge ") \
EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \
EM(rxrpc_skb_put_response, "PUT response ") \
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 98ad9b51ca2c..c50cbfc5a313 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -557,11 +557,11 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
spin_lock_irq(&local->lock);
old = conn->tx_response;
if (old) {
- struct rxrpc_skb_priv *osp = rxrpc_skb(skb);
+ struct rxrpc_skb_priv *osp = rxrpc_skb(old);
/* Always go with the response to the most recent challenge. */
if (after(sp->resp.challenge_serial, osp->resp.challenge_serial))
- conn->tx_response = old;
+ conn->tx_response = skb;
else
old = skb;
} else {
@@ -569,4 +569,5 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
}
spin_unlock_irq(&local->lock);
rxrpc_poke_conn(conn, rxrpc_conn_get_poke_response);
+ rxrpc_free_skb(old, rxrpc_skb_put_old_response);
}
^ permalink raw reply related
* [PATCH net v4 05/15] rxrpc: Fix RxGK token loading to check bounds
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel, Oleh Konko,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
From: Oleh Konko <security@1seal.org>
rxrpc_preparse_xdr_yfs_rxgk() reads the raw key length and ticket length
from the XDR token as u32 values and passes each through round_up(x, 4)
before using the rounded value for validation and allocation. When the raw
length is >= 0xfffffffd, round_up() wraps to 0, so the bounds check and
kzalloc both use 0 while the subsequent memcpy still copies the original
~4 GiB value, producing a heap buffer overflow reachable from an
unprivileged add_key() call.
Fix this by:
(1) Rejecting raw key lengths above AFSTOKEN_GK_KEY_MAX and raw ticket
lengths above AFSTOKEN_GK_TOKEN_MAX before rounding, consistent with
the caps that the RxKAD path already enforces via AFSTOKEN_RK_TIX_MAX.
(2) Sizing the flexible-array allocation from the validated raw key
length via struct_size_t() instead of the rounded value.
(3) Caching the raw lengths so that the later field assignments and
memcpy calls do not re-read from the token, eliminating a class of
TOCTOU re-parse.
The control path (valid token with lengths within bounds) is unaffected.
Fixes: 0ca100ff4df6 ("rxrpc: Add YFS RxGK (GSSAPI) security class")
Signed-off-by: Oleh Konko <security@1seal.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/key.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 26d4336a4a02..77237a82be3b 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -13,6 +13,7 @@
#include <crypto/skcipher.h>
#include <linux/module.h>
#include <linux/net.h>
+#include <linux/overflow.h>
#include <linux/skbuff.h>
#include <linux/key-type.h>
#include <linux/ctype.h>
@@ -171,7 +172,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
size_t plen;
const __be32 *ticket, *key;
s64 tmp;
- u32 tktlen, keylen;
+ size_t raw_keylen, raw_tktlen, keylen, tktlen;
_enter(",{%x,%x,%x,%x},%x",
ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -181,18 +182,22 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
goto reject;
key = xdr + (6 * 2 + 1);
- keylen = ntohl(key[-1]);
- _debug("keylen: %x", keylen);
- keylen = round_up(keylen, 4);
+ raw_keylen = ntohl(key[-1]);
+ _debug("keylen: %zx", raw_keylen);
+ if (raw_keylen > AFSTOKEN_GK_KEY_MAX)
+ goto reject;
+ keylen = round_up(raw_keylen, 4);
if ((6 * 2 + 2) * 4 + keylen > toklen)
goto reject;
ticket = xdr + (6 * 2 + 1 + (keylen / 4) + 1);
- tktlen = ntohl(ticket[-1]);
- _debug("tktlen: %x", tktlen);
- tktlen = round_up(tktlen, 4);
+ raw_tktlen = ntohl(ticket[-1]);
+ _debug("tktlen: %zx", raw_tktlen);
+ if (raw_tktlen > AFSTOKEN_GK_TOKEN_MAX)
+ goto reject;
+ tktlen = round_up(raw_tktlen, 4);
if ((6 * 2 + 2) * 4 + keylen + tktlen != toklen) {
- kleave(" = -EKEYREJECTED [%x!=%x, %x,%x]",
+ kleave(" = -EKEYREJECTED [%zx!=%x, %zx,%zx]",
(6 * 2 + 2) * 4 + keylen + tktlen, toklen,
keylen, tktlen);
goto reject;
@@ -206,7 +211,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
if (!token)
goto nomem;
- token->rxgk = kzalloc(sizeof(*token->rxgk) + keylen, GFP_KERNEL);
+ token->rxgk = kzalloc(struct_size_t(struct rxgk_key, _key, raw_keylen), GFP_KERNEL);
if (!token->rxgk)
goto nomem_token;
@@ -221,9 +226,9 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
token->rxgk->enctype = tmp = xdr_dec64(xdr + 5 * 2);
if (tmp < 0 || tmp > UINT_MAX)
goto reject_token;
- token->rxgk->key.len = ntohl(key[-1]);
+ token->rxgk->key.len = raw_keylen;
token->rxgk->key.data = token->rxgk->_key;
- token->rxgk->ticket.len = ntohl(ticket[-1]);
+ token->rxgk->ticket.len = raw_tktlen;
if (token->rxgk->endtime != 0) {
expiry = rxrpc_s64_to_time64(token->rxgk->endtime);
@@ -236,8 +241,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
memcpy(token->rxgk->key.data, key, token->rxgk->key.len);
/* Pad the ticket so that we can use it directly in XDR */
- token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
- GFP_KERNEL);
+ token->rxgk->ticket.data = kzalloc(tktlen, GFP_KERNEL);
if (!token->rxgk->ticket.data)
goto nomem_yrxgk;
memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
^ permalink raw reply related
* [PATCH net v4 04/15] rxrpc: Fix call removal to use RCU safe deletion
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Jeffrey Altman, Linus Torvalds, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
Fix rxrpc call removal from the rxnet->calls list to use list_del_rcu()
rather than list_del_init() to prevent stuffing up reading
/proc/net/rxrpc/calls from potentially getting into an infinite loop.
This, however, means that list_empty() no longer works on an entry that's
been deleted from the list, making it harder to detect prior deletion. Fix
this by:
Firstly, make rxrpc_destroy_all_calls() only dump the first ten calls that
are unexpectedly still on the list. Limiting the number of steps means
there's no need to call cond_resched() or to remove calls from the list
here, thereby eliminating the need for rxrpc_put_call() to check for that.
rxrpc_put_call() can then be fixed to unconditionally delete the call from
the list as it is the only place that the deletion occurs.
Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Linus Torvalds <torvalds@linux-foundation.org>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
include/trace/events/rxrpc.h | 2 +-
net/rxrpc/call_object.c | 24 +++++++++---------------
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 869f97c9bf73..a826cd80007b 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -347,7 +347,7 @@
EM(rxrpc_call_see_release, "SEE release ") \
EM(rxrpc_call_see_userid_exists, "SEE u-exists") \
EM(rxrpc_call_see_waiting_call, "SEE q-conn ") \
- E_(rxrpc_call_see_zap, "SEE zap ")
+ E_(rxrpc_call_see_still_live, "SEE !still-l")
#define rxrpc_txqueue_traces \
EM(rxrpc_txqueue_await_reply, "AWR") \
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 918f41d97a2f..59329cfe1532 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -654,11 +654,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)
if (dead) {
ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE);
- if (!list_empty(&call->link)) {
- spin_lock(&rxnet->call_lock);
- list_del_init(&call->link);
- spin_unlock(&rxnet->call_lock);
- }
+ spin_lock(&rxnet->call_lock);
+ list_del_rcu(&call->link);
+ spin_unlock(&rxnet->call_lock);
rxrpc_cleanup_call(call);
}
@@ -730,24 +728,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
_enter("");
if (!list_empty(&rxnet->calls)) {
- spin_lock(&rxnet->call_lock);
+ int shown = 0;
- while (!list_empty(&rxnet->calls)) {
- call = list_entry(rxnet->calls.next,
- struct rxrpc_call, link);
- _debug("Zapping call %p", call);
+ spin_lock(&rxnet->call_lock);
- rxrpc_see_call(call, rxrpc_call_see_zap);
- list_del_init(&call->link);
+ list_for_each_entry(call, &rxnet->calls, link) {
+ rxrpc_see_call(call, rxrpc_call_see_still_live);
pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
call, refcount_read(&call->ref),
rxrpc_call_states[__rxrpc_call_state(call)],
call->flags, call->events);
- spin_unlock(&rxnet->call_lock);
- cond_resched();
- spin_lock(&rxnet->call_lock);
+ if (++shown >= 10)
+ break;
}
spin_unlock(&rxnet->call_lock);
^ permalink raw reply related
* [PATCH net v4 03/15] rxrpc: Fix anonymous key handling
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
In rxrpc_new_client_call_for_sendmsg(), a key with no payload is meant to
be substituted for a NULL key pointer, but the variable this is done with
is subsequently not used.
Fix this by using "key" rather than "rx->key" when filling in the
connection parameters.
Note that this only affects direct use of AF_RXRPC; the kAFS filesystem
doesn't use sendmsg() directly and so bypasses the issue. Further,
AF_RXRPC passes a NULL key in if no key is set, so using an anonymous key
in that manner works. Since this hasn't been noticed to this point, it
might be better just to remove the "key" variable and the code that sets it
- and, arguably, rxrpc_init_client_call_security() would be a better place
to handle it.
Fixes: 19ffa01c9c45 ("rxrpc: Use structs to hold connection params and protocol info")
Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/sendmsg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 04f9c5f2dc24..c35de4fd75e3 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -637,7 +637,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
memset(&cp, 0, sizeof(cp));
cp.local = rx->local;
cp.peer = peer;
- cp.key = rx->key;
+ cp.key = key;
cp.security_level = rx->min_sec_level;
cp.exclusive = rx->exclusive | p->exclusive;
cp.upgrade = p->upgrade;
^ permalink raw reply related
* [PATCH net v4 02/15] rxrpc: Fix key parsing memleak
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
In rxrpc_preparse_xdr_yfs_rxgk(), the memory attached to token->rxgk can be
leaked in a few error paths after it's allocated.
Fix this by freeing it in the "reject_token:" case.
Fixes: 0ca100ff4df6 ("rxrpc: Add YFS RxGK (GSSAPI) security class")
Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/key.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index af403f0ccab5..26d4336a4a02 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -274,6 +274,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
nomem:
return -ENOMEM;
reject_token:
+ kfree(token->rxgk);
kfree(token);
reject:
return -EKEYREJECTED;
^ permalink raw reply related
* [PATCH net v4 01/15] rxrpc: Fix key quota calculation for multitoken keys
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel,
Jeffrey Altman, Simon Horman, stable
In-Reply-To: <20260401105614.1696001-1-dhowells@redhat.com>
In the rxrpc key preparsing, every token extracted sets the proposed quota
value, but for multitoken keys, this will overwrite the previous proposed
quota, losing it.
Fix this by adding to the proposed quota instead.
Fixes: 8a7a3eb4ddbe ("KEYS: RxRPC: Use key preparsing")
Closes: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
cc: stable@kernel.org
---
net/rxrpc/key.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 85078114b2dd..af403f0ccab5 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -72,7 +72,7 @@ static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
return -EKEYREJECTED;
plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
- prep->quotalen = datalen + plen;
+ prep->quotalen += datalen + plen;
plen -= sizeof(*token);
token = kzalloc_obj(*token);
@@ -199,7 +199,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
}
plen = sizeof(*token) + sizeof(*token->rxgk) + tktlen + keylen;
- prep->quotalen = datalen + plen;
+ prep->quotalen += datalen + plen;
plen -= sizeof(*token);
token = kzalloc_obj(*token);
@@ -460,6 +460,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
memcpy(&kver, prep->data, sizeof(kver));
prep->data += sizeof(kver);
prep->datalen -= sizeof(kver);
+ prep->quotalen = 0;
_debug("KEY I/F VERSION: %u", kver);
@@ -497,7 +498,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
goto error;
plen = sizeof(*token->kad) + v1->ticket_length;
- prep->quotalen = plen + sizeof(*token);
+ prep->quotalen += plen + sizeof(*token);
ret = -ENOMEM;
token = kzalloc_obj(*token);
^ permalink raw reply related
* [PATCH net v4 00/15] rxrpc: Miscellaneous fixes
From: David Howells @ 2026-04-01 10:55 UTC (permalink / raw)
To: netdev
Cc: David Howells, Marc Dionne, Jakub Kicinski, David S. Miller,
Eric Dumazet, Paolo Abeni, linux-afs, linux-kernel
Here are some fixes for rxrpc:
(1) Fix key quota calculation.
(2) Fix a memory leak.
(3) Fix rxrpc_new_client_call_for_sendmsg() to substitute NULL for an
empty key.
Might want to remove this substitution entirely or handle it in
rxrpc_init_client_call_security() instead.
(4) Fix deletion of call->link to be RCU safe.
(5) Fix missing bounds checks when parsing RxGK tickets.
(6) Fix use of wrong skbuff to get challenge serial number. Also actually
substitute the newer response skbuff and release the older one.
(7) Fix unexpected RACK timer warning to report old mode.
(8) Fix server keyring refcount leak.
(9) Fix call key refcount leak.
(10) Fix the interaction of jumbograms with Tx window space, setting the
request-ack flag when the window space is getting low, typically
because each jumbogram take a big bite out of the window and fewer UDP
packets get traded.
(11) Don't call rxrpc_put_call() with a NULL pointer.
(12) Reject undecryptable rxkad response tickets by checking result of
decryption.
(13) Fix buffer bounds calculation in the RESPONSE authenticator parser.
(14) Fix refcount leak on multiple setting of server keyring.
David
The patches can be found here also:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-fixes
Changes
=======
ver #4)
- Got rid of the on_list()/on_list_rcu() patch.
- Removed the list_del_init from rxrpc_destroy_all_calls().
- Made the list_del_rcu() in rxrpc_put_call() unconditional.
- Added four new patches.
ver #3)
- Rename the dwc2's on_list() to dwc2_on_list() to free up the name.
- Added a patch to fix the interaction of jumbograms with window space.
ver #2)
- AI review[1]:
- Added a patch to fix key quota calculation.
- Added a patch to fix a memory leak.
- Added a patch to use NULL instead of an empty key in rxrpc_sengmsg().
- Added a patch to use RCU-safe deletion on call->link.
- Modified the response packet selection patch to select the newer
response when there's an older response - and to release the older
response skbuff.
- Move on_list_rcu() and add on_list().
Link: https://sashiko.dev/#/patchset/20260319150150.4189381-1-dhowells%40redhat.com [1]
Alok Tiwari (2):
rxrpc: Fix use of wrong skb when comparing queued RESP challenge
serial
rxrpc: Fix rack timer warning to report unexpected mode
Anderson Nascimento (2):
rxrpc: Fix keyring reference count leak in rxrpc_setsockopt()
rxrpc: Fix key reference count leak from call->key
David Howells (4):
rxrpc: Fix key quota calculation for multitoken keys
rxrpc: Fix key parsing memleak
rxrpc: Fix anonymous key handling
rxrpc: Fix call removal to use RCU safe deletion
Douya Le (1):
rxrpc: Only put the call ref if one was acquired
Keenan Dong (2):
rxrpc: fix RESPONSE authenticator parser OOB read
rxrpc: fix oversized RESPONSE authenticator length check
Luxiao Xu (1):
rxrpc: fix reference count leak in rxrpc_server_keyring()
Marc Dionne (1):
rxrpc: Fix to request an ack if window is limited
Oleh Konko (1):
rxrpc: Fix RxGK token loading to check bounds
Yuqi Xu (1):
rxrpc: reject undecryptable rxkad response tickets
include/trace/events/rxrpc.h | 4 +++-
net/rxrpc/af_rxrpc.c | 2 +-
net/rxrpc/ar-internal.h | 2 +-
net/rxrpc/call_object.c | 25 ++++++++++--------------
net/rxrpc/conn_event.c | 5 +++--
net/rxrpc/input_rack.c | 2 +-
net/rxrpc/io_thread.c | 3 ++-
net/rxrpc/key.c | 38 +++++++++++++++++++++---------------
net/rxrpc/output.c | 2 ++
net/rxrpc/proc.c | 5 +++--
net/rxrpc/rxgk.c | 5 +++--
net/rxrpc/rxkad.c | 6 +++++-
net/rxrpc/sendmsg.c | 2 +-
net/rxrpc/server_key.c | 3 +++
14 files changed, 60 insertions(+), 44 deletions(-)
^ permalink raw reply
* [PATCH net-next 2/2] macvlan: avoid spinlock contention in macvlan_broadcast_enqueue()
From: Eric Dumazet @ 2026-04-01 10:38 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Andrew Lunn, netdev, eric.dumazet, Eric Dumazet
In-Reply-To: <20260401103809.3038139-1-edumazet@google.com>
Under high stress, we spend a lot of time cloning skbs,
then acquiring a spinlock, then freeing the clone because
the queue is full.
Add a shortcut to avoid these costs under pressure.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/macvlan.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index bbb5c32541f996fdf97caa19d2c6d99e5c994a3d..54c514acacc5e24fcdb88904f41fd1d29b1e34d0 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -360,6 +360,9 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
struct sk_buff *nskb;
int err = -ENOMEM;
+ if (skb_queue_len_lockless(&port->bc_queue) >= bc_queue_len_used)
+ goto err;
+
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
goto err;
--
2.53.0.1118.gaef5881109-goog
^ permalink raw reply related
* [PATCH net-next 1/2] macvlan: annotate data-races around port->bc_queue_len_used
From: Eric Dumazet @ 2026-04-01 10:38 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Andrew Lunn, netdev, eric.dumazet, Eric Dumazet
In-Reply-To: <20260401103809.3038139-1-edumazet@google.com>
port->bc_queue_len_used is read and written locklessly,
add READ_ONCE()/WRITE_ONCE() annotations.
While WRITE_ONCE() in macvlan_fill_info() is not yet needed,
it is a prereq for future RTNL avoidance.
Fixes: d4bff72c8401 ("macvlan: Support for high multicast packet rate")
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/macvlan.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ea22909cb09de43fbf26b16144430b4d6687de3e..bbb5c32541f996fdf97caa19d2c6d99e5c994a3d 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -356,6 +356,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
const struct macvlan_dev *src,
struct sk_buff *skb)
{
+ u32 bc_queue_len_used = READ_ONCE(port->bc_queue_len_used);
struct sk_buff *nskb;
int err = -ENOMEM;
@@ -366,7 +367,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port,
MACVLAN_SKB_CB(nskb)->src = src;
spin_lock(&port->bc_queue.lock);
- if (skb_queue_len(&port->bc_queue) < port->bc_queue_len_used) {
+ if (skb_queue_len(&port->bc_queue) < bc_queue_len_used) {
if (src)
dev_hold(src->dev);
__skb_queue_tail(&port->bc_queue, nskb);
@@ -1731,7 +1732,8 @@ static int macvlan_fill_info(struct sk_buff *skb,
}
if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN, vlan->bc_queue_len_req))
goto nla_put_failure;
- if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED, port->bc_queue_len_used))
+ if (nla_put_u32(skb, IFLA_MACVLAN_BC_QUEUE_LEN_USED,
+ READ_ONCE(port->bc_queue_len_used)))
goto nla_put_failure;
if (port->bc_cutoff != 1 &&
nla_put_s32(skb, IFLA_MACVLAN_BC_CUTOFF, port->bc_cutoff))
@@ -1791,7 +1793,7 @@ static void update_port_bc_queue_len(struct macvlan_port *port)
if (vlan->bc_queue_len_req > max_bc_queue_len_req)
max_bc_queue_len_req = vlan->bc_queue_len_req;
}
- port->bc_queue_len_used = max_bc_queue_len_req;
+ WRITE_ONCE(port->bc_queue_len_used, max_bc_queue_len_req);
}
static int macvlan_device_event(struct notifier_block *unused,
--
2.53.0.1118.gaef5881109-goog
^ permalink raw reply related
* [PATCH net-next 0/2] macvlan: broadcast delivery changes
From: Eric Dumazet @ 2026-04-01 10:38 UTC (permalink / raw)
To: David S . Miller, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Andrew Lunn, netdev, eric.dumazet, Eric Dumazet
First patch adds data-race annotations.
Second patch changes macvlan_broadcast_enqueue() to return
early if the queue is full.
Eric Dumazet (2):
macvlan: annotate data-races around port->bc_queue_len_used
macvlan: avoid spinlock contention in macvlan_broadcast_enqueue()
drivers/net/macvlan.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--
2.53.0.1118.gaef5881109-goog
^ permalink raw reply
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