CVE-2024-39488
Publication date:
10/07/2024
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&#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---
Severity CVSS v4.0: Pending analysis
Last modification:
17/09/2025