]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipv4: Convert ip_route_input_noref() to dscp_t.
authorGuillaume Nault <gnault@redhat.com>
Tue, 1 Oct 2024 19:28:49 +0000 (21:28 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 3 Oct 2024 23:21:21 +0000 (16:21 -0700)
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>
drivers/net/ipvlan/ipvlan_l3s.c
include/net/route.h
net/core/lwt_bpf.c
net/ipv4/ip_fragment.c
net/ipv4/ip_input.c
net/ipv4/route.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_protocol.c

index d5b05e8032199a7bd10380547df7d5e82e667f69..b4ef386bdb1ba54ece47c8e75406dfcfd09c084d 100644 (file)
@@ -2,6 +2,8 @@
 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
  */
 
+#include <net/ip.h>
+
 #include "ipvlan.h"
 
 static unsigned int ipvlan_netid __read_mostly;
@@ -48,11 +50,11 @@ static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
        switch (proto) {
        case AF_INET:
        {
-               struct iphdr *ip4h = ip_hdr(skb);
+               const struct iphdr *ip4h = ip_hdr(skb);
                int err;
 
                err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
-                                          ip4h->tos, sdev);
+                                          ip4h_dscp(ip4h), sdev);
                if (unlikely(err))
                        goto out;
                break;
index 03dd28cf4bc48c015d647b5c1c509b9f85cccdd1..5e4374d66927d7b871e082fe2f01055f18950daa 100644 (file)
@@ -201,8 +201,8 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
 int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                          u8 tos, struct net_device *dev,
                          struct in_device *in_dev, u32 *itag);
-int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
-                        u8 tos, struct net_device *devin);
+int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                        dscp_t dscp, struct net_device *dev);
 int ip_route_use_hint(struct sk_buff *skb, __be32 dst, __be32 src,
                      u8 tos, struct net_device *devin,
                      const struct sk_buff *hint);
@@ -213,8 +213,7 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
        int err;
 
        rcu_read_lock();
-       err = ip_route_input_noref(skb, dst, src, inet_dscp_to_dsfield(dscp),
-                                  devin);
+       err = ip_route_input_noref(skb, dst, src, dscp, devin);
        if (!err) {
                skb_dst_force(skb);
                if (!skb_dst(skb))
index 1a14f915b7a448cfacaea15bdeb886695ad10921..e0ca24a58810ff4a441613fc455a83a85ada1848 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/bpf.h>
 #include <net/lwtunnel.h>
 #include <net/gre.h>
+#include <net/ip.h>
 #include <net/ip6_route.h>
 #include <net/ipv6_stubs.h>
 #include <net/inet_dscp.h>
@@ -91,12 +92,12 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb)
 
        if (skb->protocol == htons(ETH_P_IP)) {
                struct net_device *dev = skb_dst(skb)->dev;
-               struct iphdr *iph = ip_hdr(skb);
+               const struct iphdr *iph = ip_hdr(skb);
 
                dev_hold(dev);
                skb_dst_drop(skb);
                err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                          iph->tos, dev);
+                                          ip4h_dscp(iph), dev);
                dev_put(dev);
        } else if (skb->protocol == htons(ETH_P_IPV6)) {
                skb_dst_drop(skb);
index a92664a5ef2efe0c2ced9984886d865f9067f721..48e2810f1f27cd5949fbd7dee93073adea3da568 100644 (file)
@@ -175,8 +175,8 @@ static void ip_expire(struct timer_list *t)
 
        /* skb has no dst, perform route lookup again */
        iph = ip_hdr(head);
-       err = ip_route_input_noref(head, iph->daddr, iph->saddr,
-                                          iph->tos, head->dev);
+       err = ip_route_input_noref(head, iph->daddr, iph->saddr, ip4h_dscp(iph),
+                                  head->dev);
        if (err)
                goto out;
 
index b6e7d4921309741193a8c096aeb278255ec56794..c0a2490eb7c1b0b21cfce3d7f6a7799b1eb4c7fb 100644 (file)
@@ -363,7 +363,7 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk,
         */
        if (!skb_valid_dst(skb)) {
                err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                          iph->tos, dev);
+                                          ip4h_dscp(iph), dev);
                if (unlikely(err))
                        goto drop_error;
        } else {
index 723ac9181558c3240204d7b6830a9557d06b10f3..00bfc0a11f64c6d9e2de39e79ab5de635c4030cd 100644 (file)
@@ -2465,14 +2465,14 @@ static int ip_route_input_rcu(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 }
 
 int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-                        u8 tos, struct net_device *dev)
+                        dscp_t dscp, struct net_device *dev)
 {
        struct fib_result res;
        int err;
 
-       tos &= INET_DSCP_MASK;
        rcu_read_lock();
-       err = ip_route_input_rcu(skb, daddr, saddr, tos, dev, &res);
+       err = ip_route_input_rcu(skb, daddr, saddr, inet_dscp_to_dsfield(dscp),
+                                dev, &res);
        rcu_read_unlock();
 
        return err;
index a620618cc568a547cb1a07949e7866da3137e268..b5b06323cfd94afe81497a30bace25c5a3d14e29 100644 (file)
@@ -33,7 +33,7 @@ static inline int xfrm4_rcv_encap_finish(struct net *net, struct sock *sk,
                const struct iphdr *iph = ip_hdr(skb);
 
                if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                        iph->tos, skb->dev))
+                                        ip4h_dscp(iph), skb->dev))
                        goto drop;
        }
 
index b146ce88c5d0c4f5a019b3a54823b2082920cc4c..4ee624d8e66fc88f9a986116e177cf4e48d15621 100644 (file)
@@ -76,7 +76,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
                const struct iphdr *iph = ip_hdr(skb);
 
                if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                        iph->tos, skb->dev))
+                                        ip4h_dscp(iph), skb->dev))
                        goto drop;
        }