From: Wyatt Feng tcf_skbmod_act() rewrites DMAC, SMAC, ETYPE and SWAPMAC through eth_hdr(skb), but it derives the writable length from skb_mac_header_len(skb). After a prior action strips or shortens the L2 header, skbmod can still attempt the Ethernet rewrite without a full Ethernet header being present. Reject non-ECN skbmod rewrites unless the skb is on an Ethernet device, the MAC header is set, and the MAC header length is at least ETH_HLEN. Also use ETH_HLEN as the writable length for these rewrites, which matches the bytes actually modified. This fixes a buffer-size length miscalculation that can corrupt short or non-linear packets. Fixes: 56af5e749f20 ("net/sched: act_skbmod: Add SKBMOD_F_ECN option support") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: Codex:GPT-5.4 Signed-off-by: Wyatt Feng Signed-off-by: Ren Wei --- net/sched/act_skbmod.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index a464b0a3c1b8..30c2eac17aff 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c @@ -38,7 +38,6 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb, if (unlikely(p->action == TC_ACT_SHOT)) goto drop; - max_edit_len = skb_mac_header_len(skb); flags = p->flags; /* tcf_skbmod_init() guarantees "flags" to be one of the following: @@ -49,6 +48,8 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb, * packets. */ if (flags == SKBMOD_F_ECN) { + max_edit_len = skb_mac_header_len(skb); + switch (skb_protocol(skb, true)) { case cpu_to_be16(ETH_P_IP): case cpu_to_be16(ETH_P_IPV6): @@ -57,8 +58,12 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb, default: goto out; } - } else if (!skb->dev || skb->dev->type != ARPHRD_ETHER) { + } else if (!skb->dev || skb->dev->type != ARPHRD_ETHER || + !skb_mac_header_was_set(skb) || + skb_mac_header_len(skb) < ETH_HLEN) { goto out; + } else { + max_edit_len = ETH_HLEN; } err = skb_ensure_writable(skb, max_edit_len); -- 2.47.3