From: Tristan Madani <tristmd@gmail.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
Mahesh Bandewar <maheshb@google.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org,
Tristan Madani <tristan@talencesecurity.com>
Subject: [PATCH net v4] net: reduce XMIT_RECURSION_LIMIT under KASAN
Date: Wed, 2 Sep 2026 12:30:40 +0000 [thread overview]
Message-ID: <20260902123040.2172805-1-tristmd@gmail.com> (raw)
In-Reply-To: <20260727200454.4048141-1-tristmd@gmail.com>
From: Tristan Madani <tristan@talencesecurity.com>
Virtual network devices (ipvlan, macvlan, bonding) can enter legitimate
transmit recursion when combined with packet forwarding configurations
such as IPVS NAT. The existing XMIT_RECURSION_LIMIT (8) in
__dev_queue_xmit() detects and breaks these loops, but the allowed
depth is too high for KASAN-instrumented kernels: each recursion level
consumes significantly more stack due to KASAN inline instrumentation,
and the cumulative usage overflows the kernel stack before the limit
fires.
On x86_64, CONFIG_KASAN_GENERIC doubles THREAD_SIZE from 16KB to 32KB
(KASAN_STACK_ORDER=1), but KASAN per-access checks inflate individual
function frames by roughly 2-3x. For an ipvlan L3 + IPVS NAT routing
loop, objdump measurements on a non-KASAN kernel show ~1.4KB of stack
consumed per recursion level (across 17 functions from __dev_queue_xmit
through the full IP output path and back). At KASAN ~2.3x inflation
factor that becomes ~3.3KB per level. Eight levels -- the current
limit -- consume ~26KB plus the initial call chain (~8KB), which
exceeds the 32KB KASAN stack. The overflow hits the VMAP_STACK guard
page and causes a non-recoverable kernel panic (BUG: stack guard page
was hit).
On non-KASAN kernels the same loop is safely caught by the existing
limit: the "Dead loop on virtual device" message fires and the packet
is dropped without any stack overflow.
Reduce XMIT_RECURSION_LIMIT to 4 when CONFIG_KASAN is enabled.
The deepest legitimate transmit recursion observed in the kernel
selftests is 5 levels of __dev_queue_xmit nesting, in VXLAN symmetric
routing topologies with VRF (vxlan_symmetric, vxlan_asymmetric):
__dev_queue_xmit(vrf) depth 1
__dev_queue_xmit(vlan-svi) depth 2
__dev_queue_xmit(bridge) depth 3
__dev_queue_xmit(vxlan) depth 4
__dev_queue_xmit(veth) depth 5
Since the recursion check fires when the counter exceeds the limit
(strictly greater than), a limit of 4 permits 5 levels of nesting
while blocking the 6th. At ~3.3KB per level, five levels consume
~16.5KB; combined with the ~8KB initial call chain, total usage is
~24.5KB -- well within the 32KB KASAN stack with ~7.5KB of margin.
A limit of 3 (v2/v3 of this patch) allows only 4 levels, which broke
the VXLAN symmetric selftests: the 5th __dev_queue_xmit call was
incorrectly dropped, as reported by Jakub Kicinski and the kernel test
robot.
The recursion path triggering this is:
__dev_queue_xmit -> dev_hard_start_xmit -> ipvlan_start_xmit
-> ipvlan_queue_xmit -> ipvlan_process_outbound -> ip_local_out
-> nf_hook (IPVS) -> ip_vs_in_hook -> ip_vs_nat_xmit -> ip_output
-> ip_finish_output2 -> neigh_resolve_output -> __dev_queue_xmit
Tested:
- KASAN kernel (6.8.12 x86_64): panic before fix, "Dead loop"
drop after fix (at recursion level 4 instead of 8).
- Non-KASAN kernel (6.8.12 x86_64): "Dead loop" drop both before
and after fix (no behavior change for production kernels).
- Measured max __dev_queue_xmit nesting depth via bpftrace in a
VXLAN symmetric cross-VLAN topology (VRF + VLAN + bridge + VXLAN +
veth underlay): 5 levels, confirming limit=4 is sufficient.
Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
v4: Raise the KASAN limit from 3 to 4 after investigating the recursion
depth of VXLAN symmetric forwarding selftests. Measured max nesting
depth of 5 via bpftrace (VRF + VLAN + bridge + VXLAN + underlay),
which requires limit >= 4. Limit 3 (v2/v3) incorrectly dropped the
5th call, breaking cross-VLAN tests, as reported by Jakub Kicinski
and the kernel test robot.
v3: Resend as new thread per Jakub Kicinski request (no code change
from v2).
v2: Switch from per-driver recursion guard in ipvlan_core.c to
reducing the global XMIT_RECURSION_LIMIT under CONFIG_KASAN,
as suggested by Eric Dumazet.
https://lore.kernel.org/20260711204700.1760374-1-tristmd@gmail.com
v1: https://lore.kernel.org/20260711134732.1385563-1-tristmd@gmail.com
include/linux/netdevice.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 87cafc932e9e6..3ccd1e65bcd9e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3669,7 +3669,11 @@ struct page_pool_bh {
};
DECLARE_PER_CPU(struct page_pool_bh, system_page_pool);
+#ifdef CONFIG_KASAN
+#define XMIT_RECURSION_LIMIT 4
+#else
#define XMIT_RECURSION_LIMIT 8
+#endif
#ifndef CONFIG_PREEMPT_RT
static inline int dev_recursion_level(void)
--
2.47.3
next prev parent reply other threads:[~2026-09-02 12:31 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 20:04 [PATCH net v3] net: reduce XMIT_RECURSION_LIMIT under KASAN Tristan Madani
2026-07-27 23:24 ` Jakub Kicinski
2026-08-12 8:55 ` kernel test robot
2026-09-02 12:30 ` Tristan Madani [this message]
2026-09-04 0:32 ` [PATCH net v4] " netdev-bot+sashiko
2026-09-04 23:10 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260902123040.2172805-1-tristmd@gmail.com \
--to=tristmd@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maheshb@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
--cc=tristan@talencesecurity.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.