Re: [PATCH net] ipv4: require matching source address for route hint reuse
From: Yizhou Zhao <hidden>
Date: 2026-07-22 02:54:43
Also in:
lkml, stable
Hi Ido, Thanks for your review.
On Jul 20, 2026, at 20:16, Ido Schimmel [off-list ref] wrote: On Tue, Jul 14, 2026 at 08:26:17PM +0800, Yizhou Zhao wrote:quoted
IPv4 list receive can reuse a route from the previous skb in the same receive batch. The current eligibility check only compares the destination address and TOS before calling ip_route_use_hint(). For forwarded routes, ip_route_use_hint() skips fib_validate_source() unless the hinted route is local. This means a packet with a different source address can reuse a forwarding dst created for an earlier packet and avoid source validation such as strict rp_filter.I'm not sure why we are skipping source validation for non-local routes. The comment above ip_route_use_hint() says "Implements all the saddr-related checks as ip_route_input_slow()". I agree that ip_route_input_slow() only does source validation for RTN_LOCAL, but for RTN_UNICAST it is calling ip_mkroute_input(), which eventually calls fib_validate_source(). Paolo, WDYT about always performing source validation [1]?quoted
In a KASAN QEMU router with strict rp_filter on the ingress device, aWhy mention KASAN? How is it related to this bug / patch?
The KASAN mention was only intended to describe the test kernel, but I agree that it is not relevant to the issue itself and should be removed.
quoted hunk ↗ jump to hunk
quoted
bad-only burst was dropped entirely, however, a paired valid/bad burst with the same destination/TOS made all of the bad packets pass rp_filter. Require the source address to match before reusing the hint. Packets from the same source/destination/TOS still take the fast path; packets whose source changes go through the normal route lookup and source validation path.I agree that it fixes the problem, but we will always pay the performance penalty, even when rp_filter is disabled. According to commit 02b24941619f ("ipv4: use dst hint for ipv4 list receive"), there is still a performance gain when we perform the source validation per-packet. [1]diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3f3de5164d6e..89338111793b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c@@ -2194,6 +2194,7 @@ ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,struct rtable *rt = skb_rtable(hint); struct net *net = dev_net(dev); u32 tag = 0; + int oif = 0; if (!in_dev) return reason;@@ -2214,14 +2215,13 @@ ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,} if (!(rt->rt_flags & RTCF_LOCAL)) - goto skip_validate_source; + oif = dst_dev_rcu(&rt->dst)->ifindex; - reason = fib_validate_source_reason(skb, saddr, daddr, dscp, 0, dev, + reason = fib_validate_source_reason(skb, saddr, daddr, dscp, oif, dev, in_dev, &tag); if (reason) goto martian_source; -skip_validate_source: skb_dst_copy(skb, hint); return SKB_NOT_DROPPED_YET;
The approach in [1] looks better to me. It appears to make the hint path consistent with the source validation performed by __mkroute_input(), while still allowing the route hint to be reused. I'll wait for Paolo’s comments before preparing a v2. Thanks, Yizhou