]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net/sched: act_pedit: require matching IPv4 L4 protocol
authorSamuel Moelius <sam.moelius@trailofbits.com>
Tue, 9 Jun 2026 18:56:34 +0000 (18:56 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 12 Jun 2026 22:16:10 +0000 (15:16 -0700)
The extended IPv4 L4 header mode in act_pedit can select TCP or UDP
header fields without confirming that the IPv4 protocol field matches
the selected transport header.

That lets a rule written for TCP or UDP modify unrelated payload bytes
in a packet carrying a different protocol.

Verify that the IPv4 header is long enough, that the protocol matches
the selected TCP or UDP header, and that the packet is not a non-initial
fragment before applying TCP or UDP extended header edits.

Cc: stable+noautosel@kernel.org # in real rule sets the match confirms this before calling the action
Signed-off-by: Samuel Moelius <sam.moelius@trailofbits.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sched/act_pedit.c

index bd3b1da3cd63b5b446abaf249b46f5bfcd0e876c..0d652dea4a691fce18f467bc7f256718d62f5981 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/overflow.h>
 #include <linux/unaligned.h>
+#include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -331,6 +332,9 @@ static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int head
 
                if (!iph)
                        goto out;
+               if (iph->ihl < 5 || iph->protocol != header_type ||
+                   (iph->frag_off & htons(IP_OFFSET)))
+                       goto out;
                *hoffset = noff + iph->ihl * 4;
                ret = 0;
                break;