| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2024-39488: arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY |
| |
| When CONFIG_DEBUG_BUGVERBOSE=n, we fail to add necessary padding bytes |
| to bug_table entries, and as a result the last entry in a bug table will |
| be ignored, potentially leading to an unexpected panic(). All prior |
| entries in the table will be handled correctly. |
| |
| The arm64 ABI requires that struct fields of up to 8 bytes are |
| naturally-aligned, with padding added within a struct such that struct |
| are suitably aligned within arrays. |
| |
| When CONFIG_DEBUG_BUGVERPOSE=y, the layout of a bug_entry is: |
| |
| struct bug_entry { |
| signed int bug_addr_disp; // 4 bytes |
| signed int file_disp; // 4 bytes |
| unsigned short line; // 2 bytes |
| unsigned short flags; // 2 bytes |
| } |
| |
| ... with 12 bytes total, requiring 4-byte alignment. |
| |
| When CONFIG_DEBUG_BUGVERBOSE=n, the layout of a bug_entry is: |
| |
| struct bug_entry { |
| signed int bug_addr_disp; // 4 bytes |
| unsigned short flags; // 2 bytes |
| < implicit padding > // 2 bytes |
| } |
| |
| ... with 8 bytes total, with 6 bytes of data and 2 bytes of trailing |
| padding, requiring 4-byte alginment. |
| |
| When we create a bug_entry in assembly, we align the start of the entry |
| to 4 bytes, which implicitly handles padding for any prior entries. |
| However, we do not align the end of the entry, and so when |
| CONFIG_DEBUG_BUGVERBOSE=n, the final entry lacks the trailing padding |
| bytes. |
| |
| For the main kernel image this is not a problem as find_bug() doesn't |
| depend on the trailing padding bytes when searching for entries: |
| |
| for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) |
| if (bugaddr == bug_addr(bug)) |
| return bug; |
| |
| However for modules, module_bug_finalize() depends on the trailing |
| bytes when calculating the number of entries: |
| |
| mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); |
| |
| ... and as the last bug_entry lacks the necessary padding bytes, this entry |
| will not be counted, e.g. in the case of a single entry: |
| |
| sechdrs[i].sh_size == 6 |
| sizeof(struct bug_entry) == 8; |
| |
| sechdrs[i].sh_size / sizeof(struct bug_entry) == 0; |
| |
| Consequently module_find_bug() will miss the last bug_entry when it does: |
| |
| for (i = 0; i < mod->num_bugs; ++i, ++bug) |
| if (bugaddr == bug_addr(bug)) |
| goto out; |
| |
| ... which can lead to a kenrel panic due to an unhandled bug. |
| |
| This can be demonstrated with the following module: |
| |
| static int __init buginit(void) |
| { |
| WARN(1, "hello\n"); |
| return 0; |
| } |
| |
| static void __exit bugexit(void) |
| { |
| } |
| |
| module_init(buginit); |
| module_exit(bugexit); |
| MODULE_LICENSE("GPL"); |
| |
| ... which will trigger a kernel panic when loaded: |
| |
| ------------[ cut here ]------------ |
| hello |
| Unexpected kernel BRK exception at EL1 |
| Internal error: BRK handler: 00000000f2000800 [#1] PREEMPT SMP |
| Modules linked in: hello(O+) |
| CPU: 0 PID: 50 Comm: insmod Tainted: G O 6.9.1 #8 |
| Hardware name: linux,dummy-virt (DT) |
| pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) |
| pc : buginit+0x18/0x1000 [hello] |
| lr : buginit+0x18/0x1000 [hello] |
| sp : ffff800080533ae0 |
| x29: ffff800080533ae0 x28: 0000000000000000 x27: 0000000000000000 |
| x26: ffffaba8c4e70510 x25: ffff800080533c30 x24: ffffaba8c4a28a58 |
| x23: 0000000000000000 x22: 0000000000000000 x21: ffff3947c0eab3c0 |
| x20: ffffaba8c4e3f000 x19: ffffaba846464000 x18: 0000000000000006 |
| x17: 0000000000000000 x16: ffffaba8c2492834 x15: 0720072007200720 |
| x14: 0720072007200720 x13: ffffaba8c49b27c8 x12: 0000000000000312 |
| x11: 0000000000000106 x10: ffffaba8c4a0a7c8 x9 : ffffaba8c49b27c8 |
| x8 : 00000000ffffefff x7 : ffffaba8c4a0a7c8 x6 : 80000000fffff000 |
| x5 : 0000000000000107 x4 : 0000000000000000 x3 : 0000000000000000 |
| x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff3947c0eab3c0 |
| Call trace: |
| buginit+0x18/0x1000 [hello] |
| do_one_initcall+0x80/0x1c8 |
| do_init_module+0x60/0x218 |
| load_module+0x1ba4/0x1d70 |
| __do_sys_init_module+0x198/0x1d0 |
| __arm64_sys_init_module+0x1c/0x28 |
| invoke_syscall+0x48/0x114 |
| el0_svc_common.constprop.0+0x40/0xe0 |
| do_el0_svc+0x1c/0x28 |
| el0_svc+0x34/0xd8 |
| el0t_64_sync_handler+0x120/0x12c |
| el0t_64_sync+0x190/0x194 |
| Code: d0ffffe0 910003fd 91000000 9400000b (d4210000) |
| ---[ end trace 0000000000000000 ]--- |
| Kernel panic - not syncing: BRK handler: Fatal exception |
| |
| Fix this by always aligning the end of a bug_entry to 4 bytes, which is |
| correct regardless of CONFIG_DEBUG_BUGVERBOSE. |
| |
| The Linux kernel CVE team has assigned CVE-2024-39488 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 4.19.316 with commit f221bd58db0f6ca087ac0392284f6bce21f4f8ea |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 5.4.278 with commit 22469a0335a1a1a690349b58bcb55822457df81e |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 5.10.219 with commit 461a760d578b2b2c2faac3040b6b7c77baf128f8 |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 5.15.161 with commit c1929c041a262a4a27265db8dce3619c92aa678c |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 6.1.93 with commit 3fd487ffaa697ddb05af78a75aaaddabe71c52b0 |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 6.6.33 with commit 9f2ad88f9b349554f64e4037ec185c84d7dd9c7d |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 6.9.4 with commit c27a2f7668e215c1ebbccd96fab27a220a93f1f7 |
| Issue introduced in 4.3 with commit 9fb7410f955f7a62c1f882ca8f9ffd4525907e28 and fixed in 6.10 with commit ffbf4fb9b5c12ff878a10ea17997147ea4ebea6f |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2024-39488 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| arch/arm64/include/asm/asm-bug.h |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/f221bd58db0f6ca087ac0392284f6bce21f4f8ea |
| https://git.kernel.org/stable/c/22469a0335a1a1a690349b58bcb55822457df81e |
| https://git.kernel.org/stable/c/461a760d578b2b2c2faac3040b6b7c77baf128f8 |
| https://git.kernel.org/stable/c/c1929c041a262a4a27265db8dce3619c92aa678c |
| https://git.kernel.org/stable/c/3fd487ffaa697ddb05af78a75aaaddabe71c52b0 |
| https://git.kernel.org/stable/c/9f2ad88f9b349554f64e4037ec185c84d7dd9c7d |
| https://git.kernel.org/stable/c/c27a2f7668e215c1ebbccd96fab27a220a93f1f7 |
| https://git.kernel.org/stable/c/ffbf4fb9b5c12ff878a10ea17997147ea4ebea6f |