mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup
[ Upstream commit853e164c2b] When Linux forwards a packet and needs to generate an ICMP error, icmp_route_lookup() performs a reverse-path relookup. For non-local destinations, it performs a decoy lookup to find the expected egress interface (rt2->dst.dev) before validating the path with ip_route_input(). Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, .fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. When policy routing rules (such as ip rule add from $SRC lookup 100, or dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: 1. The decoy lookup fails to match the policy rule because saddr and other key flow selectors are missing in fl4_2. 2. It resolves a route using the default table instead, returning an incorrect egress netdev. 3. Passing the wrong netdev to ip_route_input() causes strict reverse-path filtering (rp_filter=1) to fail, logging false-positive "martian source" warnings and causing the relookup to fail. Fix this by initializing fl4_2 from fl4_dec and: - Swapping source/destination IP addresses. - Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) so port-based policy routing matches correctly. Non-port protocols (such as ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. - Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure VRF routing tables are respected. - Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups for non-local source IP addresses. - Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 so that raw FIB routing is used without triggering spurious XFRM policy lookups on the decoy flow (the actual XFRM lookup is performed later using fl4_dec). Fixes:415b3334a2("icmp: Fix regression in nexthop resolution during replies.") Reported-by: Muhammad Ziad <muhzi100@gmail.com> Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c34fbb0e85
commit
72e2ccfe39
+15
-3
@@ -536,11 +536,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
|
||||
if (IS_ERR(rt2))
|
||||
err = PTR_ERR(rt2);
|
||||
} else {
|
||||
struct flowi4 fl4_2 = {};
|
||||
struct flowi4 fl4_2 = fl4_dec;
|
||||
unsigned long orefdst;
|
||||
|
||||
fl4_2.daddr = fl4_dec.saddr;
|
||||
rt2 = ip_route_output_key(net, &fl4_2);
|
||||
swap(fl4_2.daddr, fl4_2.saddr);
|
||||
switch (fl4_2.flowi4_proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_DCCP:
|
||||
swap(fl4_2.fl4_sport, fl4_2.fl4_dport);
|
||||
break;
|
||||
}
|
||||
|
||||
fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev);
|
||||
fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC;
|
||||
|
||||
rt2 = __ip_route_output_key(net, &fl4_2);
|
||||
if (IS_ERR(rt2)) {
|
||||
err = PTR_ERR(rt2);
|
||||
goto relookup_failed;
|
||||
|
||||
Reference in New Issue
Block a user