CVE-2024-39488

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
10/07/2024
Last modified:
17/09/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY<br /> <br /> When CONFIG_DEBUG_BUGVERBOSE=n, we fail to add necessary padding bytes<br /> to bug_table entries, and as a result the last entry in a bug table will<br /> be ignored, potentially leading to an unexpected panic(). All prior<br /> entries in the table will be handled correctly.<br /> <br /> The arm64 ABI requires that struct fields of up to 8 bytes are<br /> naturally-aligned, with padding added within a struct such that struct<br /> are suitably aligned within arrays.<br /> <br /> When CONFIG_DEBUG_BUGVERPOSE=y, the layout of a bug_entry is:<br /> <br /> struct bug_entry {<br /> signed int bug_addr_disp; // 4 bytes<br /> signed int file_disp; // 4 bytes<br /> unsigned short line; // 2 bytes<br /> unsigned short flags; // 2 bytes<br /> }<br /> <br /> ... with 12 bytes total, requiring 4-byte alignment.<br /> <br /> When CONFIG_DEBUG_BUGVERBOSE=n, the layout of a bug_entry is:<br /> <br /> struct bug_entry {<br /> signed int bug_addr_disp; // 4 bytes<br /> unsigned short flags; // 2 bytes<br /> // 2 bytes<br /> }<br /> <br /> ... with 8 bytes total, with 6 bytes of data and 2 bytes of trailing<br /> padding, requiring 4-byte alginment.<br /> <br /> When we create a bug_entry in assembly, we align the start of the entry<br /> to 4 bytes, which implicitly handles padding for any prior entries.<br /> However, we do not align the end of the entry, and so when<br /> CONFIG_DEBUG_BUGVERBOSE=n, the final entry lacks the trailing padding<br /> bytes.<br /> <br /> For the main kernel image this is not a problem as find_bug() doesn&amp;#39;t<br /> depend on the trailing padding bytes when searching for entries:<br /> <br /> for (bug = __start___bug_table; bug num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);<br /> <br /> ... and as the last bug_entry lacks the necessary padding bytes, this entry<br /> will not be counted, e.g. in the case of a single entry:<br /> <br /> sechdrs[i].sh_size == 6<br /> sizeof(struct bug_entry) == 8;<br /> <br /> sechdrs[i].sh_size / sizeof(struct bug_entry) == 0;<br /> <br /> Consequently module_find_bug() will miss the last bug_entry when it does:<br /> <br /> for (i = 0; i num_bugs; ++i, ++bug)<br /> if (bugaddr == bug_addr(bug))<br /> goto out;<br /> <br /> ... which can lead to a kenrel panic due to an unhandled bug.<br /> <br /> This can be demonstrated with the following module:<br /> <br /> static int __init buginit(void)<br /> {<br /> WARN(1, "hello\n");<br /> return 0;<br /> }<br /> <br /> static void __exit bugexit(void)<br /> {<br /> }<br /> <br /> module_init(buginit);<br /> module_exit(bugexit);<br /> MODULE_LICENSE("GPL");<br /> <br /> ... which will trigger a kernel panic when loaded:<br /> <br /> ------------[ cut here ]------------<br /> hello<br /> Unexpected kernel BRK exception at EL1<br /> Internal error: BRK handler: 00000000f2000800 [#1] PREEMPT SMP<br /> Modules linked in: hello(O+)<br /> CPU: 0 PID: 50 Comm: insmod Tainted: G O 6.9.1 #8<br /> Hardware name: linux,dummy-virt (DT)<br /> pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)<br /> pc : buginit+0x18/0x1000 [hello]<br /> lr : buginit+0x18/0x1000 [hello]<br /> sp : ffff800080533ae0<br /> x29: ffff800080533ae0 x28: 0000000000000000 x27: 0000000000000000<br /> x26: ffffaba8c4e70510 x25: ffff800080533c30 x24: ffffaba8c4a28a58<br /> x23: 0000000000000000 x22: 0000000000000000 x21: ffff3947c0eab3c0<br /> x20: ffffaba8c4e3f000 x19: ffffaba846464000 x18: 0000000000000006<br /> x17: 0000000000000000 x16: ffffaba8c2492834 x15: 0720072007200720<br /> x14: 0720072007200720 x13: ffffaba8c49b27c8 x12: 0000000000000312<br /> x11: 0000000000000106 x10: ffffaba8c4a0a7c8 x9 : ffffaba8c49b27c8<br /> x8 : 00000000ffffefff x7 : ffffaba8c4a0a7c8 x6 : 80000000fffff000<br /> x5 : 0000000000000107 x4 : 0000000000000000 x3 : 0000000000000000<br /> x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff3947c0eab3c0<br /> Call trace:<br /> buginit+0x18/0x1000 [hello]<br /> do_one_initcall+0x80/0x1c8<br /> do_init_module+0x60/0x218<br /> load_module+0x1ba4/0x1d70<br /> __do_sys_init_module+0x198/0x1d0<br /> __arm64_sys_init_module+0x1c/0x28<br /> invoke_syscall+0x48/0x114<br /> el0_svc<br /> ---truncated---

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.3 (including) 4.19.316 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.20 (including) 5.4.278 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.5 (including) 5.10.219 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.15.161 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.16 (including) 6.1.93 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.2 (including) 6.6.33 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.7 (including) 6.9.4 (excluding)