* FAILED: patch "[PATCH] vlan: fix skb_under_panic and races when toggling HW VLAN" failed to apply to 5.15-stable tree
@ 2026-08-31 12:57 gregkh
2026-09-01 16:02 ` [PATCH 5.15.y 1/2] vlan: defer real device state propagation to netdev_work Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2026-08-31 12:57 UTC (permalink / raw)
To: edumazet, kuba, stable, xietangxin; +Cc: stable
The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 447cbe95ebb95392b5d8f6a01c0556826919ce23
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026083120-reunion-cadillac-38bb@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 447cbe95ebb95392b5d8f6a01c0556826919ce23 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Tue, 11 Aug 2026 08:52:46 +0000
Subject: [PATCH] vlan: fix skb_under_panic and races when toggling HW VLAN
offload
Toggling hardware VLAN TX offload (NETIF_F_HW_VLAN_CTAG_TX or
NETIF_F_HW_VLAN_STAG_TX) on a lower device invokes vlan_transfer_features(),
which dynamically changed vlandev->hard_header_len.
This causes two issues:
1. Lockless TX paths (e.g. packet_snd in af_packet.c, ip6_finish_output2)
read dev->hard_header_len without holding RTNL lock. Mutating
hard_header_len dynamically under RTNL creates a data race where upper
layers reserve insufficient headroom based on a stale hard_header_len,
resulting in skb_under_panic when vlan_dev_hard_header() is called.
2. In addition, vlan_transfer_features() updated hard_header_len without
updating header_ops, causing a mismatch between allocated headroom
and header creation.
Always setting dev->hard_header_len = real_dev->hard_header_len and
dev->needed_headroom = real_dev->needed_headroom + VLAN_HLEN unconditionally
ensures:
- dev->hard_header_len remains 100% static and immutable at real_dev->hard_header_len,
eliminating all dynamic runtime updates and data races on hard_header_len.
- Upper layers allocating skbs via LL_RESERVED_SPACE() will always reserve
sufficient headroom for software VLAN tag insertion (real_dev->hard_header_len +
real_dev->needed_headroom + VLAN_HLEN).
- vlandev inherits real_dev->needed_tailroom so underlying trailer/padding/ICV
requirements are honored.
- AF_PACKET SOCK_RAW network header offsets remain correctly aligned at
real_dev->hard_header_len.
- vlan_header_ops is used unconditionally.
Note to stable teams: Make sure to backport these commits:
e16e960d55a4 ("ipvlan: inherit needed_headroom and needed_tailroom from phy_dev")
cef51860becd ("macvlan: inherit needed_headroom and needed_tailroom from lowerdev")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Tangxin Xie <xietangxin@h-partners.com>
Closes: https://lore.kernel.org/netdev/99d678ae-c7b2-4b44-b534-b8320679deb3@h-partners.com/
Cc: <stable@vger.kernel.org> # 3.19: e16e960d55a4: ipvlan: inherit needed_headroom and needed_tailroom from phy_dev
Cc: <stable@vger.kernel.org> # 3.19: cef51860becd: macvlan: inherit needed_headroom and needed_tailroom from lowerdev
Cc: <stable@vger.kernel.org> # 3.19
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260811085246.2267779-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec2569b3f8da..2859cbac3f26 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -502,26 +502,6 @@ static const struct header_ops vlan_header_ops = {
.parse_protocol = vlan_parse_protocol,
};
-static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type,
- const void *daddr, const void *saddr,
- unsigned int len)
-{
- struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
- struct net_device *real_dev = vlan->real_dev;
-
- if (saddr == NULL)
- saddr = dev->dev_addr;
-
- return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
-}
-
-static const struct header_ops vlan_passthru_header_ops = {
- .create = vlan_passthru_hard_header,
- .parse = eth_header_parse,
- .parse_protocol = vlan_parse_protocol,
-};
-
static const struct device_type vlan_type = {
.name = "vlan",
};
@@ -580,14 +560,10 @@ static int vlan_dev_init(struct net_device *dev)
dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
#endif
- dev->needed_headroom = real_dev->needed_headroom;
- if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) {
- dev->header_ops = &vlan_passthru_header_ops;
- dev->hard_header_len = real_dev->hard_header_len;
- } else {
- dev->header_ops = &vlan_header_ops;
- dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
- }
+ dev->needed_headroom = real_dev->needed_headroom + VLAN_HLEN;
+ dev->needed_tailroom = real_dev->needed_tailroom;
+ dev->header_ops = &vlan_header_ops;
+ dev->hard_header_len = real_dev->hard_header_len;
dev->netdev_ops = &vlan_netdev_ops;
@@ -1029,10 +1005,9 @@ static void vlan_transfer_features(struct net_device *dev,
netif_inherit_tso_max(vlandev, dev);
- if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
- vlandev->hard_header_len = dev->hard_header_len;
- else
- vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
+ vlandev->needed_headroom = dev->needed_headroom + VLAN_HLEN;
+ vlandev->needed_tailroom = dev->needed_tailroom;
+ vlandev->hard_header_len = dev->hard_header_len;
#if IS_ENABLED(CONFIG_FCOE)
vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 5.15.y 1/2] vlan: defer real device state propagation to netdev_work
2026-08-31 12:57 FAILED: patch "[PATCH] vlan: fix skb_under_panic and races when toggling HW VLAN" failed to apply to 5.15-stable tree gregkh
@ 2026-09-01 16:02 ` Sasha Levin
2026-09-01 16:02 ` [PATCH 5.15.y 2/2] vlan: fix skb_under_panic and races when toggling HW VLAN offload Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-09-01 16:02 UTC (permalink / raw)
To: stable
Cc: Jakub Kicinski, syzbot+09da62a8b78959ceb8bb,
syzbot+cb67c392b0b8f0fd0fc1, syzbot+9bb8bd77f3966641f298,
Kuniyuki Iwashima, Nicolai Buchwitz, Stanislav Fomichev,
Sasha Levin
From: Jakub Kicinski <kuba@kernel.org>
[ Upstream commit cd1c188db1091991fc1d7f565824d077d659425b ]
vlan_device_event() generates nested UP/DOWN, MTU and feature
change events. It executes an event for the VLAN device directly
from the notifier - while the locks of the lower device are held.
This causes deadlocks, for example:
bond (3) bond_update_speed_duplex(vlan)
| ^ v
vlan (2) UP(vlan) (4) vlan_ethtool_get_link_ksettings()
| ^ v
dummy (1) UP(dummy) (5) __ethtool_get_link_ksettings()
The dummy device is ops locked, vlan creates a nested event (2),
then bond wants to ask vlan for link state (3). bond uses the
"I'm already holding the instance lock" flavor of API. But in
this case the lock held refers to vlan itself. We hit vlan's
link settings trampoline (4) and call __ethtool_get_link_ksettings()
which tries to lock dummy. Deadlock. There's no clean way for us
to tell the vlan_ethtool_get_link_ksettings() that the caller
is already in lower device's critical section.
Defer the propagation to the per-netdev work facility instead:
the notifier only schedules netdev_work_sched(vlandev, VLAN_WORK_*),
and ndo_work (vlan_dev_work) applies the change later. Hopefully
nobody expects the VLAN state changes to be instantaneous.
If someone does expect the changes to be instantaneous we will
have to do the same thing Stan did for rx_mode and "strategically"
place sync calls, to make sure such delayed works are executed
after we drop the ops lock but before we drop rtnl_lock.
Stan suggests that if we need that down the line we may
consider reshaping the mechanism into "async notifications".
AFAICT only vlan does this sort of netdev open chaining,
so as a first try I think that sticking the complexity into
the vlan code makes sense.
One corner case is that we need to cancel the event if user
explicitly changes the state before work could run. Consider
the following operations with vlan0 on top of dummy0:
ip link set dev dummy0 up # queues work to up vlan0
ip link set dev vlan0 down # user explicitly downs the vlan
ndo_work # acts on the stale event
Reported-by: syzbot+09da62a8b78959ceb8bb@syzkaller.appspotmail.com
Reported-by: syzbot+cb67c392b0b8f0fd0fc1@syzkaller.appspotmail.com
Reported-by: syzbot+9bb8bd77f3966641f298@syzkaller.appspotmail.com
Fixes: 9f275c2e9020 ("net: ethtool: make sure __ethtool_get_link_ksettings() is ops-locked")
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260624182018.2445732-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable 5.15 adaptation: the netdev_work and per-netdev ops-locking infrastructure used by the upstream change is not available in this tree. Keep the existing synchronous state propagation and relocate vlan_transfer_features() to vlan_dev.c so the follow-up VLAN header-length fix can update it without conflicts.
[ sashal: Reduced backport -- upstream cd1c188db1091 touches 5 file(s), this
backport carries 3. Not backported here:
Documentation/networking/netdevices.rst
net/core/dev.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: 447cbe95ebb9 ("vlan: fix skb_under_panic and races when toggling HW VLAN offload")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/8021q/vlan.c | 24 ------------------------
net/8021q/vlan.h | 2 ++
net/8021q/vlan_dev.c | 26 +++++++++++++++++++++++++-
3 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 7d61ab0647f20..3744333b5e85f 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -317,30 +317,6 @@ static void vlan_sync_address(struct net_device *dev,
ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
}
-static void vlan_transfer_features(struct net_device *dev,
- struct net_device *vlandev)
-{
- struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
-
- vlandev->gso_max_size = dev->gso_max_size;
- vlandev->gso_max_segs = dev->gso_max_segs;
-
- if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
- vlandev->hard_header_len = dev->hard_header_len;
- else
- vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
-
-#if IS_ENABLED(CONFIG_FCOE)
- vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
-#endif
-
- vlandev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
- vlandev->priv_flags |= (vlan->real_dev->priv_flags & IFF_XMIT_DST_RELEASE);
- vlandev->hw_enc_features = vlan_tnl_features(vlan->real_dev);
-
- netdev_update_features(vlandev);
-}
-
static int __vlan_device_event(struct net_device *dev, unsigned long event)
{
int err = 0;
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index c7ffe591d5936..578715881034e 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -124,6 +124,8 @@ static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev)
int vlan_filter_push_vids(struct vlan_info *vlan_info, __be16 proto);
void vlan_filter_drop_vids(struct vlan_info *vlan_info, __be16 proto);
+void vlan_transfer_features(struct net_device *dev,
+ struct net_device *vlandev);
/* found in vlan_dev.c */
void vlan_dev_set_ingress_priority(const struct net_device *dev,
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 945a5bb7402d2..63d55eab7227d 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -520,7 +520,7 @@ static const struct header_ops vlan_passthru_header_ops = {
.parse_protocol = vlan_parse_protocol,
};
-static struct device_type vlan_type = {
+static const struct device_type vlan_type = {
.name = "vlan",
};
@@ -793,6 +793,30 @@ static const struct ethtool_ops vlan_ethtool_ops = {
.get_ts_info = vlan_ethtool_get_ts_info,
};
+void vlan_transfer_features(struct net_device *dev,
+ struct net_device *vlandev)
+{
+ struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
+
+ vlandev->gso_max_size = dev->gso_max_size;
+ vlandev->gso_max_segs = dev->gso_max_segs;
+
+ if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
+ vlandev->hard_header_len = dev->hard_header_len;
+ else
+ vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
+
+#if IS_ENABLED(CONFIG_FCOE)
+ vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
+#endif
+
+ vlandev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ vlandev->priv_flags |= (vlan->real_dev->priv_flags & IFF_XMIT_DST_RELEASE);
+ vlandev->hw_enc_features = vlan_tnl_features(vlan->real_dev);
+
+ netdev_update_features(vlandev);
+}
+
static const struct net_device_ops vlan_netdev_ops = {
.ndo_change_mtu = vlan_dev_change_mtu,
.ndo_init = vlan_dev_init,
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 5.15.y 2/2] vlan: fix skb_under_panic and races when toggling HW VLAN offload
2026-09-01 16:02 ` [PATCH 5.15.y 1/2] vlan: defer real device state propagation to netdev_work Sasha Levin
@ 2026-09-01 16:02 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-09-01 16:02 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, Tangxin Xie, Jakub Kicinski, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 447cbe95ebb95392b5d8f6a01c0556826919ce23 ]
Toggling hardware VLAN TX offload (NETIF_F_HW_VLAN_CTAG_TX or
NETIF_F_HW_VLAN_STAG_TX) on a lower device invokes vlan_transfer_features(),
which dynamically changed vlandev->hard_header_len.
This causes two issues:
1. Lockless TX paths (e.g. packet_snd in af_packet.c, ip6_finish_output2)
read dev->hard_header_len without holding RTNL lock. Mutating
hard_header_len dynamically under RTNL creates a data race where upper
layers reserve insufficient headroom based on a stale hard_header_len,
resulting in skb_under_panic when vlan_dev_hard_header() is called.
2. In addition, vlan_transfer_features() updated hard_header_len without
updating header_ops, causing a mismatch between allocated headroom
and header creation.
Always setting dev->hard_header_len = real_dev->hard_header_len and
dev->needed_headroom = real_dev->needed_headroom + VLAN_HLEN unconditionally
ensures:
- dev->hard_header_len remains 100% static and immutable at real_dev->hard_header_len,
eliminating all dynamic runtime updates and data races on hard_header_len.
- Upper layers allocating skbs via LL_RESERVED_SPACE() will always reserve
sufficient headroom for software VLAN tag insertion (real_dev->hard_header_len +
real_dev->needed_headroom + VLAN_HLEN).
- vlandev inherits real_dev->needed_tailroom so underlying trailer/padding/ICV
requirements are honored.
- AF_PACKET SOCK_RAW network header offsets remain correctly aligned at
real_dev->hard_header_len.
- vlan_header_ops is used unconditionally.
Note to stable teams: Make sure to backport these commits:
e16e960d55a4 ("ipvlan: inherit needed_headroom and needed_tailroom from phy_dev")
cef51860becd ("macvlan: inherit needed_headroom and needed_tailroom from lowerdev")
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Tangxin Xie <xietangxin@h-partners.com>
Closes: https://lore.kernel.org/netdev/99d678ae-c7b2-4b44-b534-b8320679deb3@h-partners.com/
Cc: <stable@vger.kernel.org> # 3.19: e16e960d55a4: ipvlan: inherit needed_headroom and needed_tailroom from phy_dev
Cc: <stable@vger.kernel.org> # 3.19: cef51860becd: macvlan: inherit needed_headroom and needed_tailroom from lowerdev
Cc: <stable@vger.kernel.org> # 3.19
Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260811085246.2267779-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/8021q/vlan_dev.c | 39 +++++++--------------------------------
1 file changed, 7 insertions(+), 32 deletions(-)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 63d55eab7227d..8309423e742dc 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -500,26 +500,6 @@ static const struct header_ops vlan_header_ops = {
.parse_protocol = vlan_parse_protocol,
};
-static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type,
- const void *daddr, const void *saddr,
- unsigned int len)
-{
- struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
- struct net_device *real_dev = vlan->real_dev;
-
- if (saddr == NULL)
- saddr = dev->dev_addr;
-
- return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
-}
-
-static const struct header_ops vlan_passthru_header_ops = {
- .create = vlan_passthru_hard_header,
- .parse = eth_header_parse,
- .parse_protocol = vlan_parse_protocol,
-};
-
static const struct device_type vlan_type = {
.name = "vlan",
};
@@ -573,14 +553,10 @@ static int vlan_dev_init(struct net_device *dev)
dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
#endif
- dev->needed_headroom = real_dev->needed_headroom;
- if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) {
- dev->header_ops = &vlan_passthru_header_ops;
- dev->hard_header_len = real_dev->hard_header_len;
- } else {
- dev->header_ops = &vlan_header_ops;
- dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
- }
+ dev->needed_headroom = real_dev->needed_headroom + VLAN_HLEN;
+ dev->needed_tailroom = real_dev->needed_tailroom;
+ dev->header_ops = &vlan_header_ops;
+ dev->hard_header_len = real_dev->hard_header_len;
dev->netdev_ops = &vlan_netdev_ops;
@@ -801,10 +777,9 @@ void vlan_transfer_features(struct net_device *dev,
vlandev->gso_max_size = dev->gso_max_size;
vlandev->gso_max_segs = dev->gso_max_segs;
- if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
- vlandev->hard_header_len = dev->hard_header_len;
- else
- vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
+ vlandev->needed_headroom = dev->needed_headroom + VLAN_HLEN;
+ vlandev->needed_tailroom = dev->needed_tailroom;
+ vlandev->hard_header_len = dev->hard_header_len;
#if IS_ENABLED(CONFIG_FCOE)
vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-01 16:02 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 12:57 FAILED: patch "[PATCH] vlan: fix skb_under_panic and races when toggling HW VLAN" failed to apply to 5.15-stable tree gregkh
2026-09-01 16:02 ` [PATCH 5.15.y 1/2] vlan: defer real device state propagation to netdev_work Sasha Levin
2026-09-01 16:02 ` [PATCH 5.15.y 2/2] vlan: fix skb_under_panic and races when toggling HW VLAN offload Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox