{"id":71949,"date":"2025-10-18T11:45:34","date_gmt":"2025-10-18T08:15:34","guid":{"rendered":"https:\/\/afaghhosting.net\/blog\/cve-2025-40003-net-mscc-ocelot-fix-use-after-free-caused-by-cyclic-delayed-work\/"},"modified":"2025-10-18T11:45:34","modified_gmt":"2025-10-18T08:15:34","slug":"cve-2025-40003-net-mscc-ocelot-fix-use-after-free-caused-by-cyclic-delayed-work","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/cve-2025-40003-net-mscc-ocelot-fix-use-after-free-caused-by-cyclic-delayed-work\/","title":{"rendered":"CVE-2025-40003 &#8211; net: mscc: ocelot: Fix use-after-free caused by cyclic delayed work"},"content":{"rendered":"<p>CVE ID : CVE-2025-40003<\/p>\n<p>Published :  Oct. 18, 2025, 8:15 a.m. | 25\u00a0minutes ago<\/p>\n<p>Description : In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>net: mscc: ocelot: Fix use-after-free caused by cyclic delayed work<\/p>\n<p>The origin code calls cancel_delayed_work() in ocelot_stats_deinit()<br \/>\nto cancel the cyclic delayed work item ocelot-&gt;stats_work. However,<br \/>\ncancel_delayed_work() may fail to cancel the work item if it is already<br \/>\nexecuting. While destroy_workqueue() does wait for all pending work items<br \/>\nin the work queue to complete before destroying the work queue, it cannot<br \/>\nprevent the delayed work item from being rescheduled within the<br \/>\nocelot_check_stats_work() function. This limitation exists because the<br \/>\ndelayed work item is only enqueued into the work queue after its timer<br \/>\nexpires. Before the timer expiration, destroy_workqueue() has no visibility<br \/>\nof this pending work item. Once the work queue appears empty,<br \/>\ndestroy_workqueue() proceeds with destruction. When the timer eventually<br \/>\nexpires, the delayed work item gets queued again, leading to the following<br \/>\nwarning:<\/p>\n<p>workqueue: cannot queue ocelot_check_stats_work on wq ocelot-switch-stats<br \/>\nWARNING: CPU: 2 PID: 0 at kernel\/workqueue.c:2255 __queue_work+0x875\/0xaf0<br \/>\n&#8230;<br \/>\nRIP: 0010:__queue_work+0x875\/0xaf0<br \/>\n&#8230;<br \/>\nRSP: 0018:ffff88806d108b10 EFLAGS: 00010086<br \/>\nRAX: 0000000000000000 RBX: 0000000000000101 RCX: 0000000000000027<br \/>\nRDX: 0000000000000027 RSI: 0000000000000004 RDI: ffff88806d123e88<br \/>\nRBP: ffffffff813c3170 R08: 0000000000000000 R09: ffffed100da247d2<br \/>\nR10: ffffed100da247d1 R11: ffff88806d123e8b R12: ffff88800c00f000<br \/>\nR13: ffff88800d7285c0 R14: ffff88806d0a5580 R15: ffff88800d7285a0<br \/>\nFS:  0000000000000000(0000) GS:ffff8880e5725000(0000) knlGS:0000000000000000<br \/>\nCS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br \/>\nCR2: 00007fe18e45ea10 CR3: 0000000005e6c000 CR4: 00000000000006f0<br \/>\nCall Trace:<\/p>\n<p> ? kasan_report+0xc6\/0xf0<br \/>\n ? __pfx_delayed_work_timer_fn+0x10\/0x10<br \/>\n ? __pfx_delayed_work_timer_fn+0x10\/0x10<br \/>\n call_timer_fn+0x25\/0x1c0<br \/>\n __run_timer_base.part.0+0x3be\/0x8c0<br \/>\n ? __pfx_delayed_work_timer_fn+0x10\/0x10<br \/>\n ? rcu_sched_clock_irq+0xb06\/0x27d0<br \/>\n ? __pfx___run_timer_base.part.0+0x10\/0x10<br \/>\n ? try_to_wake_up+0xb15\/0x1960<br \/>\n ? _raw_spin_lock_irq+0x80\/0xe0<br \/>\n ? __pfx__raw_spin_lock_irq+0x10\/0x10<br \/>\n tmigr_handle_remote_up+0x603\/0x7e0<br \/>\n ? __pfx_tmigr_handle_remote_up+0x10\/0x10<br \/>\n ? sched_balance_trigger+0x1c0\/0x9f0<br \/>\n ? sched_tick+0x221\/0x5a0<br \/>\n ? _raw_spin_lock_irq+0x80\/0xe0<br \/>\n ? __pfx__raw_spin_lock_irq+0x10\/0x10<br \/>\n ? tick_nohz_handler+0x339\/0x440<br \/>\n ? __pfx_tmigr_handle_remote_up+0x10\/0x10<br \/>\n __walk_groups.isra.0+0x42\/0x150<br \/>\n tmigr_handle_remote+0x1f4\/0x2e0<br \/>\n ? __pfx_tmigr_handle_remote+0x10\/0x10<br \/>\n ? ktime_get+0x60\/0x140<br \/>\n ? lapic_next_event+0x11\/0x20<br \/>\n ? clockevents_program_event+0x1d4\/0x2a0<br \/>\n ? hrtimer_interrupt+0x322\/0x780<br \/>\n handle_softirqs+0x16a\/0x550<br \/>\n irq_exit_rcu+0xaf\/0xe0<br \/>\n sysvec_apic_timer_interrupt+0x70\/0x80<\/p>\n<p>&#8230;<\/p>\n<p>The following diagram reveals the cause of the above warning:<\/p>\n<p>CPU 0 (remove)             | CPU 1 (delayed work callback)<br \/>\nmscc_ocelot_remove()       |<br \/>\n  ocelot_deinit()          | ocelot_check_stats_work()<br \/>\n    ocelot_stats_deinit()  |<br \/>\n      cancel_delayed_work()|   &#8230;<br \/>\n                           |   queue_delayed_work()<br \/>\n      destroy_workqueue()  | (wait a time)<br \/>\n                           | __queue_work() \/\/UAF<\/p>\n<p>The above scenario actually constitutes a UAF vulnerability.<\/p>\n<p>The ocelot_stats_deinit() is only invoked when initialization<br \/>\nfailure or resource destruction, so we must ensure that any<br \/>\ndelayed work items cannot be rescheduled.<\/p>\n<p>Replace cancel_delayed_work() with disable_delayed_work_sync()<br \/>\nto guarantee proper cancellation of the delayed work item and<br \/>\nensure completion of any currently executing work before the<br \/>\nworkqueue is deallocated.<\/p>\n<p>A deadlock concern was considered: ocelot_stats_deinit() is called<br \/>\nin a process context and is not holding any locks that the delayed<br \/>\nwork item might also need. Therefore, the use of the _sync() variant<br \/>\nis safe here.<\/p>\n<p>This bug was identified through static analysis. To reproduce the<br \/>\nissue and validate the fix, I simulated ocelot-swit<br \/>\n&#8212;truncated&#8212;<\/p>\n<p>Severity: 0.0 | NA<\/p>\n<p>Visit the link for more details, such as CVSS details, affected products, timeline, and more&#8230;\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>CVE ID : CVE-2025-40003 Published : Oct. 18, 2025, 8:15 a.m. | 25\u00a0minutes ago Description : In the Linux kernel, the following vulnerability has been resolved: net: mscc: ocelot: Fix use-after-free caused by cyclic delayed work The origin code calls cancel_delayed_work() in ocelot_stats_deinit() to cancel the cyclic delayed work item ocelot-&gt;stats_work. However, cancel_delayed_work() may fail &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-71949","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/71949","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=71949"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/71949\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=71949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=71949"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=71949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}