| From 7d9cd02537c8c7f57334c57f55bb70e615f6d9b4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 2 Apr 2026 22:46:20 +0800 |
| Subject: net: sched: act_csum: validate nested VLAN headers |
| |
| From: Ruide Cao <caoruide123@gmail.com> |
| |
| [ Upstream commit c842743d073bdd683606cb414eb0ca84465dd834 ] |
| |
| tcf_csum_act() walks nested VLAN headers directly from skb->data when an |
| skb still carries in-payload VLAN tags. The current code reads |
| vlan->h_vlan_encapsulated_proto and then pulls VLAN_HLEN bytes without |
| first ensuring that the full VLAN header is present in the linear area. |
| |
| If only part of an inner VLAN header is linearized, accessing |
| h_vlan_encapsulated_proto reads past the linear area, and the following |
| skb_pull(VLAN_HLEN) may violate skb invariants. |
| |
| Fix this by requiring pskb_may_pull(skb, VLAN_HLEN) before accessing and |
| pulling each nested VLAN header. If the header still is not fully |
| available, drop the packet through the existing error path. |
| |
| Fixes: 2ecba2d1e45b ("net: sched: act_csum: Fix csum calc for tagged packets") |
| Reported-by: Yifan Wu <yifanwucs@gmail.com> |
| Reported-by: Juefei Pu <tomapufckgml@gmail.com> |
| Co-developed-by: Yuan Tan <yuantan098@gmail.com> |
| Signed-off-by: Yuan Tan <yuantan098@gmail.com> |
| Suggested-by: Xin Liu <bird@lzu.edu.cn> |
| Tested-by: Ren Wei <enjou1224z@gmail.com> |
| Signed-off-by: Ruide Cao <caoruide123@gmail.com> |
| Signed-off-by: Ren Wei <n05ec@lzu.edu.cn> |
| Reviewed-by: Simon Horman <horms@kernel.org> |
| Link: https://patch.msgid.link/22df2fcb49f410203eafa5d97963dd36089f4ecf.1774892775.git.caoruide123@gmail.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/sched/act_csum.c | 6 +++++- |
| 1 file changed, 5 insertions(+), 1 deletion(-) |
| |
| diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c |
| index 4fa4fcb842ba7..107dc690de051 100644 |
| --- a/net/sched/act_csum.c |
| +++ b/net/sched/act_csum.c |
| @@ -602,8 +602,12 @@ static int tcf_csum_act(struct sk_buff *skb, const struct tc_action *a, |
| protocol = skb->protocol; |
| orig_vlan_tag_present = true; |
| } else { |
| - struct vlan_hdr *vlan = (struct vlan_hdr *)skb->data; |
| + struct vlan_hdr *vlan; |
| |
| + if (!pskb_may_pull(skb, VLAN_HLEN)) |
| + goto drop; |
| + |
| + vlan = (struct vlan_hdr *)skb->data; |
| protocol = vlan->h_vlan_encapsulated_proto; |
| skb_pull(skb, VLAN_HLEN); |
| skb_reset_network_header(skb); |
| -- |
| 2.53.0 |
| |