* [PATCH net] net/sched: act_ife: use mac_len for ingress header offset
@ 2026-08-10 14:42 Victor Nogueira
2026-08-12 0:45 ` Jakub Kicinski
0 siblings, 1 reply; 2+ messages 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] 2+ messages in thread
* Re: [PATCH net] net/sched: act_ife: use mac_len for ingress header offset
2026-08-10 14:42 [PATCH net] net/sched: act_ife: use mac_len for ingress header offset Victor Nogueira
@ 2026-08-12 0:45 ` Jakub Kicinski
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2026-08-12 0:45 UTC (permalink / raw)
To: Victor Nogueira
Cc: davem, edumazet, pabeni, jhs, jiri, horms, yotam.gi, edragain,
vega, netdev
On Mon, 10 Aug 2026 11:42:01 -0300 Victor Nogueira wrote:
> 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.
Clashiko points out that act_ife operates on Ethernet headers
pretty explicitly. IOW we're fixing a crash in a case that
functionally won't work, anyway.
Should we not simply drop all the packets if they are are destined
for a non ARPHRD_ETHER device?
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-12 0:45 UTC | newest]
Thread overview: 2+ messages (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
2026-08-12 0:45 ` Jakub Kicinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.