Skip to content

Commit

Permalink
ipv4: Fix route lookups when handling ICMP redirects and PMTU updates
Browse files Browse the repository at this point in the history
The PMTU update and ICMP redirect helper functions initialise their fl4
variable with either __build_flow_key() or build_sk_flow_key(). These
initialisation functions always set ->flowi4_scope with
RT_SCOPE_UNIVERSE and might set the ECN bits of ->flowi4_tos. This is
not a problem when the route lookup is later done via
ip_route_output_key_hash(), which properly clears the ECN bits from
->flowi4_tos and initialises ->flowi4_scope based on the RTO_ONLINK
flag. However, some helpers call fib_lookup() directly, without
sanitising the tos and scope fields, so the route lookup can fail and,
as a result, the ICMP redirect or PMTU update aren't taken into
account.

Fix this by extracting the ->flowi4_tos and ->flowi4_scope sanitisation
code into ip_rt_fix_tos(), then use this function in handlers that call
fib_lookup() directly.

Note 1: We can't sanitise ->flowi4_tos and ->flowi4_scope in a central
place (like __build_flow_key() or flowi4_init_output()), because
ip_route_output_key_hash() expects non-sanitised values. When called
with sanitised values, it can erroneously overwrite RT_SCOPE_LINK with
RT_SCOPE_UNIVERSE in ->flowi4_scope. Therefore we have to be careful to
sanitise the values only for those paths that don't call
ip_route_output_key_hash().

Note 2: The problem is mostly about sanitising ->flowi4_tos. Having
->flowi4_scope initialised with RT_SCOPE_UNIVERSE instead of
RT_SCOPE_LINK probably wasn't really a problem: sockets with the
SOCK_LOCALROUTE flag set (those that'd result in RTO_ONLINK being set)
normally shouldn't receive ICMP redirects or PMTU updates.

Fixes: 4895c77 ("ipv4: Add FIB nexthop exceptions.")
Signed-off-by: Guillaume Nault <[email protected]>
Reviewed-by: David Ahern <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
Guillaume Nault authored and kuba-moo committed Mar 18, 2022
1 parent 6bd0c76 commit 544b4dd
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,15 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
}
EXPORT_SYMBOL(__ip_select_ident);

static void ip_rt_fix_tos(struct flowi4 *fl4)
{
__u8 tos = RT_FL_TOS(fl4);

fl4->flowi4_tos = tos & IPTOS_RT_MASK;
fl4->flowi4_scope = tos & RTO_ONLINK ?
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
}

static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
const struct sock *sk,
const struct iphdr *iph,
Expand Down Expand Up @@ -824,6 +833,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
rt = (struct rtable *) dst;

__build_flow_key(net, &fl4, sk, iph, oif, tos, prot, mark, 0);
ip_rt_fix_tos(&fl4);
__ip_do_redirect(rt, skb, &fl4, true);
}

Expand Down Expand Up @@ -1048,6 +1058,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct flowi4 fl4;

ip_rt_build_flow_key(&fl4, sk, skb);
ip_rt_fix_tos(&fl4);

/* Don't make lookup fail for bridged encapsulations */
if (skb && netif_is_any_bridge_port(skb->dev))
Expand Down Expand Up @@ -1122,6 +1133,8 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
goto out;

new = true;
} else {
ip_rt_fix_tos(&fl4);
}

__ip_rt_update_pmtu((struct rtable *)xfrm_dst_path(&rt->dst), &fl4, mtu);
Expand Down Expand Up @@ -2603,7 +2616,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
const struct sk_buff *skb)
{
__u8 tos = RT_FL_TOS(fl4);
struct fib_result res = {
.type = RTN_UNSPEC,
.fi = NULL,
Expand All @@ -2613,9 +2625,7 @@ struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
struct rtable *rth;

fl4->flowi4_iif = LOOPBACK_IFINDEX;
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
ip_rt_fix_tos(fl4);

rcu_read_lock();
rth = ip_route_output_key_hash_rcu(net, fl4, &res, skb);
Expand Down

0 comments on commit 544b4dd

Please sign in to comment.