Eric Dumazet (3): net: watchdog: rename __dev_watchdog_up() and dev_watchdog_down() net: watchdog: fix refcount tracking races net: do not acquire dev->tx_global_lock in netdev_watchdog_up() JiangJieHua (1): net: watchdog: fix kabi breakage of struct net_device drivers/net/ethernet/freescale/ucc_geth.c | 2 +- include/linux/netdevice.h | 9 ++-- net/core/dev.c | 5 +- net/sched/sch_generic.c | 60 ++++++++++++++--------- 4 files changed, 46 insertions(+), 30 deletions(-) -- 2.33.8
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/27209 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/NRC... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/27209 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/NRC...
From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v6.14-rc1 commit 1b960cd19311c0bb653afa3633aaa9ef8edcfdde category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17648 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- In commit d7811e623dd4 ("[NET]: Drop tx lock in dev_watchdog_up") dev_watchdog_up() became a simple wrapper for __netdev_watchdog_up() Herbert also said : "In 2.6.19 we can eliminate the unnecessary __dev_watchdog_up and replace it with dev_watchdog_up." This patch consolidates things to have only two functions, with a common prefix. - netdev_watchdog_up(), exported for the sake of one freescale driver. This replaces __netdev_watchdog_up() and dev_watchdog_up(). - netdev_watchdog_down(), static to net/sched/sch_generic.c This replaces dev_watchdog_down(). Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Reviewed-by: Jason Xing <kerneljasonxing@gmail.com> Link: https://patch.msgid.link/20250105090924.1661822-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: drivers/net/ethernet/freescale/ucc_geth.c [Context Adjust] Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- drivers/net/ethernet/freescale/ucc_geth.c | 2 +- include/linux/netdevice.h | 2 +- net/core/dev.c | 2 +- net/sched/sch_generic.c | 33 ++++++++++------------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index ab421243a4192..e866fda595240 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -1545,7 +1545,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth) /* allow to xmit again */ netif_tx_wake_all_queues(ugeth->ndev); - __netdev_watchdog_up(ugeth->ndev); + netdev_watchdog_up(ugeth->ndev); } /* Called every time the controller might need to be made diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0965453f248c9..a57fb36c6c1d3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4270,7 +4270,7 @@ static inline bool netif_carrier_ok(const struct net_device *dev) unsigned long dev_trans_start(struct net_device *dev); -void __netdev_watchdog_up(struct net_device *dev); +void netdev_watchdog_up(struct net_device *dev); void netif_carrier_on(struct net_device *dev); void netif_carrier_off(struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index d21b3bf2700b3..990238824764a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3280,7 +3280,7 @@ void netif_device_attach(struct net_device *dev) if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) && netif_running(dev)) { netif_tx_wake_all_queues(dev); - __netdev_watchdog_up(dev); + netdev_watchdog_up(dev); } } EXPORT_SYMBOL(netif_device_attach); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 428d0bd1f3ab6..158067a798213 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -553,25 +553,20 @@ static void dev_watchdog(struct timer_list *t) netdev_put(dev, &dev->watchdog_dev_tracker); } -void __netdev_watchdog_up(struct net_device *dev) -{ - if (dev->netdev_ops->ndo_tx_timeout) { - if (dev->watchdog_timeo <= 0) - dev->watchdog_timeo = 5*HZ; - if (!mod_timer(&dev->watchdog_timer, - round_jiffies(jiffies + dev->watchdog_timeo))) - netdev_hold(dev, &dev->watchdog_dev_tracker, - GFP_ATOMIC); - } -} -EXPORT_SYMBOL_GPL(__netdev_watchdog_up); - -static void dev_watchdog_up(struct net_device *dev) +void netdev_watchdog_up(struct net_device *dev) { - __netdev_watchdog_up(dev); + if (!dev->netdev_ops->ndo_tx_timeout) + return; + if (dev->watchdog_timeo <= 0) + dev->watchdog_timeo = 5*HZ; + if (!mod_timer(&dev->watchdog_timer, + round_jiffies(jiffies + dev->watchdog_timeo))) + netdev_hold(dev, &dev->watchdog_dev_tracker, + GFP_ATOMIC); } +EXPORT_SYMBOL_GPL(netdev_watchdog_up); -static void dev_watchdog_down(struct net_device *dev) +static void netdev_watchdog_down(struct net_device *dev) { netif_tx_lock_bh(dev); if (del_timer(&dev->watchdog_timer)) @@ -593,7 +588,7 @@ void netif_carrier_on(struct net_device *dev) atomic_inc(&dev->carrier_up_count); linkwatch_fire_event(dev); if (netif_running(dev)) - __netdev_watchdog_up(dev); + netdev_watchdog_up(dev); } } EXPORT_SYMBOL(netif_carrier_on); @@ -1260,7 +1255,7 @@ void dev_activate(struct net_device *dev) if (need_watchdog) { netif_trans_update(dev); - dev_watchdog_up(dev); + netdev_watchdog_up(dev); } } EXPORT_SYMBOL(dev_activate); @@ -1332,7 +1327,7 @@ void dev_deactivate_many(struct list_head *head) dev_deactivate_queue(dev, dev_ingress_queue(dev), &noop_qdisc); - dev_watchdog_down(dev); + netdev_watchdog_down(dev); } /* Wait for outstanding qdisc-less dev_queue_xmit calls or -- 2.33.8
From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v7.2-rc1 commit 8eed5519e496b7a07f441a0f579cb228a33189f7 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17648 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Blamed commit converted the untracked dev_hold()/dev_put() calls in the watchdog code to use the tracked dev_hold_track()/dev_put_track() (which were later renamed/interfaced to netdev_hold() and netdev_put()). By introducing dev->watchdog_dev_tracker to store the reference tracking information without adding synchronization between netdev_watchdog_up() and dev_watchdog(), it enabled the race condition where this pointer could be overwritten or freed concurrently, leading to the list corruption crash syzbot reported: list_del corruption, ffff888114a18c00->next is NULL kernel BUG at lib/list_debug.c:52 ! Oops: invalid opcode: 0000 [#1] SMP KASAN PTI CPU: 1 UID: 0 PID: 91 Comm: kworker/u8:5 Not tainted syzkaller #0 PREEMPT(lazy) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026 Workqueue: events_unbound linkwatch_event RIP: 0010:__list_del_entry_valid_or_report.cold+0x22/0x2a lib/list_debug.c:52 Call Trace: <TASK> __list_del_entry_valid include/linux/list.h:132 [inline] __list_del_entry include/linux/list.h:246 [inline] list_move_tail include/linux/list.h:341 [inline] ref_tracker_free+0x1a7/0x6c0 lib/ref_tracker.c:329 netdev_tracker_free include/linux/netdevice.h:4491 [inline] netdev_put include/linux/netdevice.h:4508 [inline] netdev_put include/linux/netdevice.h:4504 [inline] netdev_watchdog_down net/sched/sch_generic.c:600 [inline] dev_deactivate_many+0x28c/0xfe0 net/sched/sch_generic.c:1363 dev_deactivate+0x109/0x1d0 net/sched/sch_generic.c:1397 linkwatch_do_dev net/core/link_watch.c:184 [inline] linkwatch_do_dev+0xd3/0x120 net/core/link_watch.c:166 __linkwatch_run_queue+0x3a5/0x810 net/core/link_watch.c:240 linkwatch_event+0x8f/0xc0 net/core/link_watch.c:314 process_one_work+0xa0e/0x1980 kernel/workqueue.c:3314 process_scheduled_works kernel/workqueue.c:3397 [inline] worker_thread+0x5ef/0xe50 kernel/workqueue.c:3478 kthread+0x370/0x450 kernel/kthread.c:436 ret_from_fork+0x69a/0xc80 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 This patch has three coordinated parts: 1) Add dev->watchdog_lock and dev->watchdog_ref_held to serialize watchdog operations. 2) Remove netdev_watchdog_up() call from netif_carrier_on(): This ensures netdev_watchdog_up() is only called from process/BH context (via linkwatch workqueue dev_activate()), allowing us to use spin_lock_bh() for synchronization. 3) Synchronize watchdog up and watchdog timer: Protect netdev_watchdog_up() with tx_global_lock and watchdog_lock. Only allocate a new tracker in netdev_watchdog_up() if one is not already present. In dev_watchdog(), ensure we don't release the tracker if the timer was rescheduled either by dev_watchdog() itself or concurrently by netdev_watchdog_up(). Fixes: f12bf6f3f942 ("net: watchdog: add net device refcount tracker") Reported-by: syzbot+381d82bbf0253710b35d@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/6a26b751.c25708ab.1b19ef.0013.GAE@google.com/... Tested-by: syzbot+3479efbc2821cb2a79f2@syzkaller.appspotmail.com Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260611152737.2580480-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: include/linux/netdevice.h net/sched/sch_generic.c [8fa7292fee5c ("treewide: Switch/rename to timer_delete[_sync]()") is not merged.] Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- include/linux/netdevice.h | 4 ++++ net/core/dev.c | 3 ++- net/sched/sch_generic.c | 44 +++++++++++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a57fb36c6c1d3..f50d39af3edbf 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1986,6 +1986,8 @@ enum netdev_stat_type { * @qdisc_hash: qdisc hash table * @watchdog_timeo: Represents the timeout that is used by * the watchdog (see dev_watchdog()) + * @watchdog_lock: protect watchdog_ref_held + * @watchdog_ref_held: True if the watchdog device ref is taken. * @watchdog_timer: List of timers * * @proto_down_reason: reason a netdev interface is held down @@ -2329,6 +2331,8 @@ struct net_device { /* These may be needed for future network-power-down code. */ struct timer_list watchdog_timer; int watchdog_timeo; + spinlock_t watchdog_lock; + bool watchdog_ref_held; u32 proto_down_reason; diff --git a/net/core/dev.c b/net/core/dev.c index 990238824764a..f6188d2ac8b46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10280,7 +10280,8 @@ static int netif_alloc_netdev_queues(struct net_device *dev) netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL); spin_lock_init(&dev->tx_global_lock); - + spin_lock_init(&dev->watchdog_lock); + dev->watchdog_ref_held = false; return 0; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 158067a798213..6b0125206c048 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -541,16 +541,24 @@ static void dev_watchdog(struct timer_list *t) dev->netdev_ops->ndo_tx_timeout(dev, i); netif_unfreeze_queues(dev); } - if (!mod_timer(&dev->watchdog_timer, - round_jiffies(oldest_start + - dev->watchdog_timeo))) - release = false; + spin_lock(&dev->watchdog_lock); + mod_timer(&dev->watchdog_timer, + round_jiffies(oldest_start + + dev->watchdog_timeo)); + release = false; + spin_unlock(&dev->watchdog_lock); } } spin_unlock(&dev->tx_global_lock); - if (release) + spin_lock(&dev->watchdog_lock); + if (timer_pending(&dev->watchdog_timer)) + release = false; + if (release && dev->watchdog_ref_held) { netdev_put(dev, &dev->watchdog_dev_tracker); + dev->watchdog_ref_held = false; + } + spin_unlock(&dev->watchdog_lock); } void netdev_watchdog_up(struct net_device *dev) @@ -559,18 +567,34 @@ void netdev_watchdog_up(struct net_device *dev) return; if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; + spin_lock_bh(&dev->tx_global_lock); + + spin_lock(&dev->watchdog_lock); if (!mod_timer(&dev->watchdog_timer, - round_jiffies(jiffies + dev->watchdog_timeo))) - netdev_hold(dev, &dev->watchdog_dev_tracker, - GFP_ATOMIC); + round_jiffies(jiffies + dev->watchdog_timeo))) { + if (!dev->watchdog_ref_held) { + netdev_hold(dev, &dev->watchdog_dev_tracker, + GFP_ATOMIC); + dev->watchdog_ref_held = true; + } + } + spin_unlock(&dev->watchdog_lock); + + spin_unlock_bh(&dev->tx_global_lock); } EXPORT_SYMBOL_GPL(netdev_watchdog_up); static void netdev_watchdog_down(struct net_device *dev) { netif_tx_lock_bh(dev); - if (del_timer(&dev->watchdog_timer)) + + spin_lock(&dev->watchdog_lock); + if (del_timer(&dev->watchdog_timer)) { netdev_put(dev, &dev->watchdog_dev_tracker); + dev->watchdog_ref_held = false; + } + spin_unlock(&dev->watchdog_lock); + netif_tx_unlock_bh(dev); } @@ -587,8 +611,6 @@ void netif_carrier_on(struct net_device *dev) return; atomic_inc(&dev->carrier_up_count); linkwatch_fire_event(dev); - if (netif_running(dev)) - netdev_watchdog_up(dev); } } EXPORT_SYMBOL(netif_carrier_on); -- 2.33.8
From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v7.2-rc1 commit d09a78a2a469e4fab75108325efb813c49520809 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17648 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Marek Szyprowski reported a deadlock during system resume when virtio_net driver is used. The deadlock occurs because netif_device_attach() is called while holding dev->tx_global_lock (via netif_tx_lock_bh() in virtnet_restore_up()). netif_device_attach() calls __netdev_watchdog_up(), which now also tries to acquire dev->tx_global_lock to synchronize with dev_watchdog(). This recursive lock acquisition results in a deadlock. Fix this by removing the tx_global_lock acquisition from netdev_watchdog_up(). The critical state (watchdog_timer and watchdog_ref_held) is already protected by dev->watchdog_lock, which was introduced in the blamed commit. Fixes: 8eed5519e496 ("net: watchdog: fix refcount tracking races") Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Closes: https://lore.kernel.org/netdev/a443376e-5187-4268-93b3-58047ef113a8@samsung.... Signed-off-by: Eric Dumazet <edumazet@google.com> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260622110108.69541-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- net/sched/sch_generic.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 6b0125206c048..20abe6bf7faf9 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -567,9 +567,8 @@ void netdev_watchdog_up(struct net_device *dev) return; if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; - spin_lock_bh(&dev->tx_global_lock); - spin_lock(&dev->watchdog_lock); + spin_lock_bh(&dev->watchdog_lock); if (!mod_timer(&dev->watchdog_timer, round_jiffies(jiffies + dev->watchdog_timeo))) { if (!dev->watchdog_ref_held) { @@ -578,9 +577,7 @@ void netdev_watchdog_up(struct net_device *dev) dev->watchdog_ref_held = true; } } - spin_unlock(&dev->watchdog_lock); - - spin_unlock_bh(&dev->tx_global_lock); + spin_unlock_bh(&dev->watchdog_lock); } EXPORT_SYMBOL_GPL(netdev_watchdog_up); -- 2.33.8
hulk inclusion category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17648 CVE: CVE-2026-74264 -------------------------------- To maintain KABI stability, replace the direct addition of watchdog_lock and watchdog_ref_held in struct net_device with KABI_RENAME(_KABI_RESERVE(2), spinlock_t watchdog_lock) and KABI_USE(3, bool watchdog_ref_held), respectively. This preserves the structure layout and ensures binary compatibility with external kernel modules on the target branch. Fixes: f12bf6f3f942 ("net: watchdog: add net device refcount tracker") Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- include/linux/netdevice.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f50d39af3edbf..47a4e2cb94779 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2331,9 +2331,6 @@ struct net_device { /* These may be needed for future network-power-down code. */ struct timer_list watchdog_timer; int watchdog_timeo; - spinlock_t watchdog_lock; - bool watchdog_ref_held; - u32 proto_down_reason; struct list_head todo_list; @@ -2459,8 +2456,8 @@ struct net_device { #else KABI_RESERVE(1) #endif - KABI_RESERVE(2) - KABI_RESERVE(3) + KABI_RENAME(_KABI_RESERVE(2), spinlock_t watchdog_lock); + KABI_USE(3, bool watchdog_ref_held) KABI_RESERVE(4) KABI_RESERVE(5) KABI_RESERVE(6) -- 2.33.8
participants (2)
-
JiangJieHua -
patchwork bot