{"id":21518,"date":"2026-09-12T04:31:17","date_gmt":"2026-09-11T20:31:17","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89596"},"modified":"2026-09-12T04:31:17","modified_gmt":"2026-09-11T20:31:17","slug":"cve-2026-89596","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89596","title":{"rendered":"CVE-2026-89596 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nforcedeth: fix off-by"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>forcedeth: fix off-by-one when saving\/restoring non-PCI config space<\/p>\n<p>nv_suspend() and nv_resume() walk the non-PCI configuration space with<\/p>\n<p>\tfor (i = 0; i register_size\/sizeof(u32); i++)<\/p>\n<p>which runs one iteration too many. saved_config_space is declared as<\/p>\n<p>\tu32 saved_config_space[NV_PCI_REGSZ_MAX\/4];<\/p>\n<p>and NV_PCI_REGSZ_VER3 is equal to NV_PCI_REGSZ_MAX (0x604), so on a VER3<br \/>\ndevice register_size\/sizeof(u32) is exactly the array length and the last<br \/>\niteration addresses one element past the end.<\/p>\n<p>The element it lands on is np-&gt;name_rx[0..3]: saved_config_space[] is<br \/>\nfollowed immediately by char name_rx[IFNAMSIZ + 3], and char needs no<br \/>\npadding. Nothing observable is corrupted by that, because nv_request_irq()<br \/>\nrewrites name_rx with sprintf() before it is ever passed to request_irq().<br \/>\nThe bug is the out-of-bounds access itself, which UBSAN reports and which<br \/>\nCONFIG_UBSAN_TRAP=y turns into a trap that aborts the running kernel code,<br \/>\nplus an MMIO read and, on resume, an MMIO writel() to base + 0x604, one<br \/>\ndword past the range the driver mapped:<\/p>\n<p>\tnp-&gt;base = ioremap(addr, np-&gt;register_size);<\/p>\n<p>VER1 and VER2 devices stay inside the array, but they too get the stray<br \/>\nread and the stray write one dword past their own window.<\/p>\n<p>Caught by UBSAN on an Apple Macmini3,1 (MCP79) during a deep S3 cycle.<br \/>\nThe splat below is trimmed: the build path in the file name, the CPU<br \/>\nand taint lines, the Workqueue line, the &#8220;?&#8221; hint frames, and the<br \/>\nframes below device_suspend are all cut. The kernel was tainted, with<br \/>\nan out-of-tree nouveau and CPU_OUT_OF_SPEC; forcedeth itself was the<br \/>\nstock module.<\/p>\n<p>  UBSAN: array-index-out-of-bounds in drivers\/net\/ethernet\/nvidia\/forcedeth.c:6225:25<br \/>\n  index 385 is out of range for type &#8216;u32 [385]&#8217;<br \/>\n  Call Trace:<br \/>\n   dump_stack_lvl+0x5d\/0x80<br \/>\n   ubsan_epilogue+0x5\/0x2b<br \/>\n   __ubsan_handle_out_of_bounds.cold+0x54\/0x59<br \/>\n   __this_module+0xe398c\/0xe9010 [forcedeth]<br \/>\n   pci_pm_suspend+0x80\/0x170<br \/>\n   dpm_run_callback+0x51\/0x160<br \/>\n   device_suspend+0x1a2\/0x4a0<br \/>\n   &#8230;<\/p>\n<p>Both loops are hit. UBSAN reports each source location only once per module<br \/>\nload (__ubsan_handle_out_of_bounds() calls suppress_report(), which does<br \/>\ntest_and_set_bit(REPORTED_BIT, &#8230;) on the struct source_location), so the<br \/>\ntwo splats land in the first S3 cycle after the module is loaded and later<br \/>\ncycles are silent even though the access still runs off the end every time.<br \/>\nIn that first cycle line 6225 is reported from pci_pm_suspend and line 6240<br \/>\nfrom pci_pm_resume.<\/p>\n<p>The same off-by-one was fixed in nv_get_regs() by commit ba9aa134287f<br \/>\n(&#8220;forcedeth: fix buffer overflow&#8221;) in 2012; these two loops were missed.<br \/>\nThe suspend and resume side was reported on LKML in September 2013 by Marc<br \/>\nWeber, with the same analysis and the same one-character fix, but the patch<br \/>\nwas attached rather than sent inline and the thread ended there.<\/p>\n<p>Use &lt; instead of &lt;=, which saves and restores exactly register_size bytes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>forcedeth: fix off-by-one when saving\/restoring non-PCI config space<\/p>\n<p>nv_suspend() and nv_resume() walk the non-PCI configuration s<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-21518","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/21518","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=21518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=21518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=21518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}