Skip to content

Commit 568c4d7

Browse files
mtottenh-AKAMroxanan1996
authored andcommitted
net/sched: act_pedit: Parse L3 Header for L4 offset
jira VULN-188478 cve-pre CVE-2026-46331 commit-author Rajat Gupta <rajat.gupta@oss.qualcomm.com> commit 6c02568 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: 71d0ed7 ("net/act_pedit: Support using offset relative to the conventional network headers") Signed-off-by: Max Tottenham <mtottenh@akamai.com> Reviewed-by: Josh Hunt <johunt@akamai.com> Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202305261541.N165u9TZ-lkp@intel.com/ Reviewed-by: Pedro Tammela <pctammela@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit 6c02568) Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
1 parent 40a5659 commit 568c4d7

1 file changed

Lines changed: 43 additions & 5 deletions

File tree

net/sched/act_pedit.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
#include <linux/rtnetlink.h>
1818
#include <linux/module.h>
1919
#include <linux/init.h>
20+
#include <linux/ip.h>
21+
#include <linux/ipv6.h>
2022
#include <linux/slab.h>
23+
#include <net/ipv6.h>
2124
#include <net/netlink.h>
2225
#include <net/pkt_sched.h>
2326
#include <linux/tc_act/tc_pedit.h>
@@ -316,28 +319,58 @@ static bool offset_valid(struct sk_buff *skb, int offset)
316319
return true;
317320
}
318321

319-
static void pedit_skb_hdr_offset(struct sk_buff *skb,
322+
static int pedit_l4_skb_offset(struct sk_buff *skb, int *hoffset, const int header_type)
323+
{
324+
const int noff = skb_network_offset(skb);
325+
int ret = -EINVAL;
326+
struct iphdr _iph;
327+
328+
switch (skb->protocol) {
329+
case htons(ETH_P_IP): {
330+
const struct iphdr *iph = skb_header_pointer(skb, noff, sizeof(_iph), &_iph);
331+
332+
if (!iph)
333+
goto out;
334+
*hoffset = noff + iph->ihl * 4;
335+
ret = 0;
336+
break;
337+
}
338+
case htons(ETH_P_IPV6):
339+
ret = ipv6_find_hdr(skb, hoffset, header_type, NULL, NULL) == header_type ? 0 : -EINVAL;
340+
break;
341+
}
342+
out:
343+
return ret;
344+
}
345+
346+
static int pedit_skb_hdr_offset(struct sk_buff *skb,
320347
enum pedit_header_type htype, int *hoffset)
321348
{
349+
int ret = -EINVAL;
322350
/* 'htype' is validated in the netlink parsing */
323351
switch (htype) {
324352
case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH:
325-
if (skb_mac_header_was_set(skb))
353+
if (skb_mac_header_was_set(skb)) {
326354
*hoffset = skb_mac_offset(skb);
355+
ret = 0;
356+
}
327357
break;
328358
case TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK:
329359
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4:
330360
case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6:
331361
*hoffset = skb_network_offset(skb);
362+
ret = 0;
332363
break;
333364
case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP:
365+
ret = pedit_l4_skb_offset(skb, hoffset, IPPROTO_TCP);
366+
break;
334367
case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP:
335-
if (skb_transport_header_was_set(skb))
336-
*hoffset = skb_transport_offset(skb);
368+
ret = pedit_l4_skb_offset(skb, hoffset, IPPROTO_UDP);
337369
break;
338370
default:
339371
break;
340372
}
373+
return ret;
341374
}
342375

343376
static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
@@ -372,6 +405,7 @@ static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
372405
int hoffset = 0;
373406
u32 *ptr, hdata;
374407
u32 val;
408+
int rc;
375409

376410
if (tkey_ex) {
377411
htype = tkey_ex->htype;
@@ -380,7 +414,11 @@ static int tcf_pedit_act(struct sk_buff *skb, const struct tc_action *a,
380414
tkey_ex++;
381415
}
382416

383-
pedit_skb_hdr_offset(skb, htype, &hoffset);
417+
rc = pedit_skb_hdr_offset(skb, htype, &hoffset);
418+
if (rc) {
419+
pr_info_ratelimited("tc action pedit unable to extract header offset for header type (0x%x)\n", htype);
420+
goto bad;
421+
}
384422

385423
if (tkey->offmask) {
386424
u8 *d, _d;

0 commit comments

Comments
 (0)