Netdev List
 help / color / mirror / Atom feed
* [PATCH net] net/sched: act_ife: use mac_len for ingress header offset
@ 2026-08-10 14:42 Victor Nogueira
  0 siblings, 0 replies; only message in thread
From: Victor Nogueira @ 2026-08-10 14:42 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni, jhs, jiri
  Cc: horms, yotam.gi, edragain, vega, netdev

On ingress, the L2 header stripped from the frame is skb->mac_len, not
skb->dev->hard_header_len. Use it for the skb_push/skb_pull offsets in
tcf_ife_encode()/tcf_ife_decode() and the matching header length inside
ife_encode()/ife_decode(). On egress keep hard_header_len.

For devices where hard_header_len differs from mac_len (e.g. PPP, which
reports 4 vs 0), the previous code pushed/pulled the wrong amount and
could hit skb_under_panic on ingress when headroom was tight.

Fixes: 295a6e06d21e1 ("net/sched: act_ife: Change to use ife module")
Reported-by: vega@nebusec.ai
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
---
 net/ife/ife.c       | 18 +++++++++++-------
 net/sched/act_ife.c |  6 +++---
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7a75947a31e3..3d31d68114ef 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -36,8 +36,10 @@ void *ife_encode(struct sk_buff *skb, u16 metalen)
 	/* OUTERHDR:TOTMETALEN:{TLVHDR:Metadatum:TLVHDR..}:ORIGDATA
 	 * where ORIGDATA = original ethernet header ...
 	 */
+	unsigned int hdrlen = skb_at_tc_ingress(skb) ?
+			      skb->mac_len : skb->dev->hard_header_len;
 	int hdrm = metalen + IFE_METAHDRLEN;
-	int total_push = hdrm + skb->dev->hard_header_len;
+	int total_push = hdrm + hdrlen;
 	struct ifeheadr *ifehdr;
 	struct ethhdr *iethh;	/* inner ether header */
 	int skboff = 0;
@@ -50,9 +52,9 @@ void *ife_encode(struct sk_buff *skb, u16 metalen)
 	iethh = (struct ethhdr *) skb->data;
 
 	__skb_push(skb, total_push);
-	memcpy(skb->data, iethh, skb->dev->hard_header_len);
+	memcpy(skb->data, iethh, hdrlen);
 	skb_reset_mac_header(skb);
-	skboff += skb->dev->hard_header_len;
+	skboff += hdrlen;
 
 	/* total metadata length */
 	ifehdr = (struct ifeheadr *) (skb->data + skboff);
@@ -65,16 +67,18 @@ EXPORT_SYMBOL_GPL(ife_encode);
 
 void *ife_decode(struct sk_buff *skb, u16 *metalen)
 {
+	unsigned int hdrlen = skb_at_tc_ingress(skb) ?
+			      skb->mac_len : skb->dev->hard_header_len;
 	struct ifeheadr *ifehdr;
 	int total_pull;
 	u16 ifehdrln;
 
-	if (!pskb_may_pull(skb, skb->dev->hard_header_len + IFE_METAHDRLEN))
+	if (!pskb_may_pull(skb, hdrlen + IFE_METAHDRLEN))
 		return NULL;
 
-	ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
+	ifehdr = (struct ifeheadr *)(skb->data + hdrlen);
 	ifehdrln = ntohs(ifehdr->metalen);
-	total_pull = skb->dev->hard_header_len + ifehdrln;
+	total_pull = hdrlen + ifehdrln;
 
 	if (unlikely(ifehdrln < 2))
 		return NULL;
@@ -82,7 +86,7 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
 	if (unlikely(!pskb_may_pull(skb, total_pull + ETH_HLEN)))
 		return NULL;
 
-	ifehdr = (struct ifeheadr *)(skb->data + skb->dev->hard_header_len);
+	ifehdr = (struct ifeheadr *)(skb->data + hdrlen);
 	skb_set_mac_header(skb, total_pull);
 	__skb_pull(skb, total_pull);
 	*metalen = ifehdrln - IFE_METAHDRLEN;
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 065228026c58..ea7df36ab7e3 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -723,7 +723,7 @@ static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
 	tcf_lastuse_update(&ife->tcf_tm);
 
 	if (skb_at_tc_ingress(skb))
-		skb_push(skb, skb->dev->hard_header_len);
+		skb_push(skb, skb->mac_len);
 
 	tlv_data = ife_decode(skb, &metalen);
 	if (unlikely(!tlv_data)) {
@@ -826,7 +826,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
 	}
 
 	if (skb_at_tc_ingress(skb))
-		skb_push(skb, skb->dev->hard_header_len);
+		skb_push(skb, skb->mac_len);
 
 	ife_meta = ife_encode(skb, metalen);
 	if (!ife_meta)
@@ -856,7 +856,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
 	oethh->h_proto = htons(p->eth_type);
 
 	if (skb_at_tc_ingress(skb))
-		skb_pull(skb, skb->dev->hard_header_len);
+		skb_pull(skb, skb->mac_len);
 
 	return action;
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-10 14:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-10 14:42 [PATCH net] net/sched: act_ife: use mac_len for ingress header offset Victor Nogueira

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox