Patch "net/sched: act_pedit: Parse L3 Header for L4 offset" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net/sched: act_pedit: Parse L3 Header for L4 offset

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-sched-act_pedit-parse-l3-header-for-l4-offset.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit a9edd5b2aa760857864eb65619f4206ecf63e779
Author: Max Tottenham <mtottenh@xxxxxxxxxx>
Date:   Wed Jun 7 12:23:54 2023 -0400

    net/sched: act_pedit: Parse L3 Header for L4 offset
    
    [ Upstream commit 6c02568fd1ae53099b4ab86365c5be1ff15f586b ]
    
    Instead of relying on skb->transport_header being set correctly, opt
    instead to parse the L3 header length out of the L3 headers for both
    IPv4/IPv6 when the Extended Layer Op for tcp/udp is used. This fixes a
    bug if GRO is disabled, when GRO is disabled skb->transport_header is
    set by __netif_receive_skb_core() to point to the L3 header, it's later
    fixed by the upper protocol layers, but act_pedit will receive the SKB
    before the fixups are completed. The existing behavior causes the
    following to edit the L3 header if GRO is disabled instead of the UDP
    header:
    
        tc filter add dev eth0 ingress protocol ip flower ip_proto udp \
     dst_ip 192.168.1.3 action pedit ex munge udp set dport 18053
    
    Also re-introduce a rate-limited warning if we were unable to extract
    the header offset when using the 'ex' interface.
    
    Fixes: 71d0ed7079df ("net/act_pedit: Support using offset relative to
    the conventional network headers")
    Signed-off-by: Max Tottenham <mtottenh@xxxxxxxxxx>
    Reviewed-by: Josh Hunt <johunt@xxxxxxxxxx>
    Reported-by: kernel test robot <lkp@xxxxxxxxx>
    Closes: https://lore.kernel.org/oe-kbuild-all/202305261541.N165u9TZ-lkp@xxxxxxxxx/
    Reviewed-by: Pedro Tammela <pctammela@xxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 48e14cbcd8ffe..180669aa9d097 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -13,7 +13,10 @@
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <linux/slab.h>
+#include <net/ipv6.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_pedit.h>
@@ -312,28 +315,58 @@ static bool offset_valid(struct sk_buff *skb, int offset)
 	return true;
 }
 
-static void pedit_skb_hdr_offset(struct sk_buff *skb,
+static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type)
+{
+	const int noff = skb_network_offset(skb);
+	int ret = -EINVAL;
+	struct iphdr _iph;
+
+	switch (skb->protocol) {
+	case htons(ETH_P_IP): {
+		const struct iphdr *iph = skb_header_pointer(skb, noff, sizeof(_iph), &_iph);
+
+		if (!iph)
+			goto out;
+		*hoffset = noff + iph->ihl * 4;
+		ret = 0;
+		break;
+	}
+	case htons(ETH_P_IPV6):
+		ret = ipv6_find_hdr(skb, hoffset, header_type, NULL, NULL) == header_type ? 0 : -EINVAL;
+		break;
+	}
+out:
+	return ret;
+}
+
+static int pedit_skb_hdr_offset(struct sk_buff *skb,
 				 enum pedit_header_type htype, int *hoffset)
 {
+	int ret = -EINVAL;
 	/* 'htype' is validated in the netlink parsing */
 	switch (htype) {
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
-		if (skb_mac_header_was_set(skb))
+		if (skb_mac_header_was_set(skb)) {
 			*hoffset = skb_mac_offset(skb);
+			ret = 0;
+		}
 		break;
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK:
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
 		*hoffset = skb_network_offset(skb);
+		ret = 0;
 		break;
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
+		ret = pedit_l4_skb_offset(skb, hoffset, IPPROTO_TCP);
+		break;
 	case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
-		if (skb_transport_header_was_set(skb))
-			*hoffset = skb_transport_offset(skb);
+		ret = pedit_l4_skb_offset(skb, hoffset, IPPROTO_UDP);
 		break;
 	default:
 		break;
 	}
+	return ret;
 }
 
 static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
@@ -368,6 +401,7 @@ static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
 		int hoffset = 0;
 		u32 *ptr, hdata;
 		u32 val;
+		int rc;
 
 		if (tkey_ex) {
 			htype = tkey_ex->htype;
@@ -376,7 +410,11 @@ static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
 			tkey_ex++;
 		}
 
-		pedit_skb_hdr_offset(skb, htype, &hoffset);
+		rc = pedit_skb_hdr_offset(skb, htype, &hoffset);
+		if (rc) {
+			pr_info_ratelimited("tc action pedit unable to extract header offset for header type (0x%x)\n", htype);
+			goto bad;
+		}
 
 		if (tkey->offmask) {
 			u8 *d, _d;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux