Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: Convert ip_route_input_noref() to dscp_t.

Pass a dscp_t variable to ip_route_input_noref(), instead of a plain
u8, to prevent accidental setting of ECN bits in ->flowi4_tos.

Callers of ip_route_input_noref() to consider are:

* arp_process() in net/ipv4/arp.c. This function sets the tos
parameter to 0, which is already a valid dscp_t value, so it
doesn't need to be adjusted for the new prototype.

* ip_route_input(), which already has a dscp_t variable to pass as
parameter. We just need to remove the inet_dscp_to_dsfield()
conversion.

* ipvlan_l3_rcv(), bpf_lwt_input_reroute(), ip_expire(),
ip_rcv_finish_core(), xfrm4_rcv_encap_finish() and
xfrm4_rcv_encap(), which get the DSCP directly from IPv4 headers
and can simply use the ip4h_dscp() helper.

While there, declare the IPv4 header pointers as const in
ipvlan_l3_rcv() and bpf_lwt_input_reroute().
Also, modify the declaration of ip_route_input_noref() in
include/net/route.h so that it matches the prototype of its
implementation in net/ipv4/route.c.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/a8a747bed452519c4d0cc06af32c7e7795d7b627.1727807926.git.gnault@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Guillaume Nault and committed by
Jakub Kicinski
66fb6386 7e863e5d

+18 -16
+4 -2
drivers/net/ipvlan/ipvlan_l3s.c
··· 2 2 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> 3 3 */ 4 4 5 + #include <net/ip.h> 6 + 5 7 #include "ipvlan.h" 6 8 7 9 static unsigned int ipvlan_netid __read_mostly; ··· 50 48 switch (proto) { 51 49 case AF_INET: 52 50 { 53 - struct iphdr *ip4h = ip_hdr(skb); 51 + const struct iphdr *ip4h = ip_hdr(skb); 54 52 int err; 55 53 56 54 err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, 57 - ip4h->tos, sdev); 55 + ip4h_dscp(ip4h), sdev); 58 56 if (unlikely(err)) 59 57 goto out; 60 58 break;
+3 -4
include/net/route.h
··· 201 201 int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr, 202 202 u8 tos, struct net_device *dev, 203 203 struct in_device *in_dev, u32 *itag); 204 - int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, 205 - u8 tos, struct net_device *devin); 204 + int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, 205 + dscp_t dscp, struct net_device *dev); 206 206 int ip_route_use_hint(struct sk_buff *skb, __be32 dst, __be32 src, 207 207 u8 tos, struct net_device *devin, 208 208 const struct sk_buff *hint); ··· 213 213 int err; 214 214 215 215 rcu_read_lock(); 216 - err = ip_route_input_noref(skb, dst, src, inet_dscp_to_dsfield(dscp), 217 - devin); 216 + err = ip_route_input_noref(skb, dst, src, dscp, devin); 218 217 if (!err) { 219 218 skb_dst_force(skb); 220 219 if (!skb_dst(skb))
+3 -2
net/core/lwt_bpf.c
··· 10 10 #include <linux/bpf.h> 11 11 #include <net/lwtunnel.h> 12 12 #include <net/gre.h> 13 + #include <net/ip.h> 13 14 #include <net/ip6_route.h> 14 15 #include <net/ipv6_stubs.h> 15 16 #include <net/inet_dscp.h> ··· 92 91 93 92 if (skb->protocol == htons(ETH_P_IP)) { 94 93 struct net_device *dev = skb_dst(skb)->dev; 95 - struct iphdr *iph = ip_hdr(skb); 94 + const struct iphdr *iph = ip_hdr(skb); 96 95 97 96 dev_hold(dev); 98 97 skb_dst_drop(skb); 99 98 err = ip_route_input_noref(skb, iph->daddr, iph->saddr, 100 - iph->tos, dev); 99 + ip4h_dscp(iph), dev); 101 100 dev_put(dev); 102 101 } else if (skb->protocol == htons(ETH_P_IPV6)) { 103 102 skb_dst_drop(skb);
+2 -2
net/ipv4/ip_fragment.c
··· 175 175 176 176 /* skb has no dst, perform route lookup again */ 177 177 iph = ip_hdr(head); 178 - err = ip_route_input_noref(head, iph->daddr, iph->saddr, 179 - iph->tos, head->dev); 178 + err = ip_route_input_noref(head, iph->daddr, iph->saddr, ip4h_dscp(iph), 179 + head->dev); 180 180 if (err) 181 181 goto out; 182 182
+1 -1
net/ipv4/ip_input.c
··· 363 363 */ 364 364 if (!skb_valid_dst(skb)) { 365 365 err = ip_route_input_noref(skb, iph->daddr, iph->saddr, 366 - iph->tos, dev); 366 + ip4h_dscp(iph), dev); 367 367 if (unlikely(err)) 368 368 goto drop_error; 369 369 } else {
+3 -3
net/ipv4/route.c
··· 2465 2465 } 2466 2466 2467 2467 int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr, 2468 - u8 tos, struct net_device *dev) 2468 + dscp_t dscp, struct net_device *dev) 2469 2469 { 2470 2470 struct fib_result res; 2471 2471 int err; 2472 2472 2473 - tos &= INET_DSCP_MASK; 2474 2473 rcu_read_lock(); 2475 - err = ip_route_input_rcu(skb, daddr, saddr, tos, dev, &res); 2474 + err = ip_route_input_rcu(skb, daddr, saddr, inet_dscp_to_dsfield(dscp), 2475 + dev, &res); 2476 2476 rcu_read_unlock(); 2477 2477 2478 2478 return err;
+1 -1
net/ipv4/xfrm4_input.c
··· 33 33 const struct iphdr *iph = ip_hdr(skb); 34 34 35 35 if (ip_route_input_noref(skb, iph->daddr, iph->saddr, 36 - iph->tos, skb->dev)) 36 + ip4h_dscp(iph), skb->dev)) 37 37 goto drop; 38 38 } 39 39
+1 -1
net/ipv4/xfrm4_protocol.c
··· 76 76 const struct iphdr *iph = ip_hdr(skb); 77 77 78 78 if (ip_route_input_noref(skb, iph->daddr, iph->saddr, 79 - iph->tos, skb->dev)) 79 + ip4h_dscp(iph), skb->dev)) 80 80 goto drop; 81 81 } 82 82