{"id":29035,"date":"2026-09-25T20:31:43","date_gmt":"2026-09-25T12:31:43","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97603"},"modified":"2026-09-25T20:31:43","modified_gmt":"2026-09-25T12:31:43","slug":"cve-2026-97603","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-97603","title":{"rendered":"CVE-2026-97603 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nidpf: disable DIM wor"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>idpf: disable DIM work before freeing q_vectors<\/p>\n<p>idpf never drains the Tx\/Rx DIM works before freeing the memory they<br \/>\nlive in.  tx_dim and rx_dim are embedded in struct idpf_q_vector, they<br \/>\nare queued from the NAPI poll via net_dim(), and idpf_vport_intr_rel()<br \/>\nends with kfree(rsrc-&gt;q_vectors).  Nothing in the driver cancels them.<\/p>\n<p>idpf_tx_dim_work() and idpf_rx_dim_work() then run on freed memory:<br \/>\nidpf_vport_intr_write_itr() writes the ITR register through<br \/>\nq_vector-&gt;intr_reg.tx_itr \/ rx_itr, void __iomem pointers loaded out of<br \/>\nthe freed q_vector.  No configuration is needed to get there &#8212;<br \/>\nIDPF_ITR_IS_DYNAMIC() is defined as (itr_mode) and idpf_vport_alloc()<br \/>\ninitialises both modes to IDPF_ITR_DYNAMIC.<\/p>\n<p>Draining after idpf_vport_intr_napi_dis_all() is not enough on its own.<br \/>\nidpf_net_dim() is called from inside the<br \/>\n&#8220;if (napi_complete_done(napi, work_done))&#8221; branch of the poll, and<br \/>\nnapi_complete_done() has already cleared NAPIF_STATE_SCHED by then.<br \/>\nnapi_disable_locked() waits only while (val &amp; (NAPIF_STATE_SCHED |<br \/>\nNAPIF_STATE_NPSVC)), so napi_disable() can return while the poll tail is<br \/>\nstill queueing the work, and a plain cancel_work_sync() would be<br \/>\nre-armed behind the drain.<\/p>\n<p>Use disable_work_sync(): schedule_work() on a work with a non-zero<br \/>\ndisable count is dropped by clear_pending_if_disabled() before<br \/>\n__queue_work() is reached.<\/p>\n<p>Move idpf_init_dim() to idpf_vport_intr_alloc() so the works are<br \/>\ninitialised on every path that can reach the drain &#8212; the three<br \/>\n&#8220;goto intr_deinit&#8221; sites between idpf_vport_intr_init() and<br \/>\nidpf_vport_intr_ena() get there without the enable side having run.<br \/>\nNothing re-enables them: rsrc-&gt;q_vectors is freed on every exit from<br \/>\nidpf_vport_open() and on every idpf_vport_stop(), so the count dies with<br \/>\nthe object.<\/p>\n<p>It is a race, not a deterministic failure &#8212; net_dim() only schedules<br \/>\nonce DIM_NEVENTS events have accumulated and the profile index changes.<br \/>\nA KASAN ifup\/ifdown loop under load is the way to see it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>idpf: disable DIM work before freeing q_vectors<\/p>\n<p>idpf never drains the Tx\/Rx DIM works before freeing the memory they<br \/>\nlive in.  tx_<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-29035","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/29035","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=29035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=29035"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=29035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}