| From bippy-1.1.0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@kernel.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2022-49888: arm64: entry: avoid kprobe recursion |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| arm64: entry: avoid kprobe recursion |
| |
| The cortex_a76_erratum_1463225_debug_handler() function is called when |
| handling debug exceptions (and synchronous exceptions from BRK |
| instructions), and so is called when a probed function executes. If the |
| compiler does not inline cortex_a76_erratum_1463225_debug_handler(), it |
| can be probed. |
| |
| If cortex_a76_erratum_1463225_debug_handler() is probed, any debug |
| exception or software breakpoint exception will result in recursive |
| exceptions leading to a stack overflow. This can be triggered with the |
| ftrace multiple_probes selftest, and as per the example splat below. |
| |
| This is a regression caused by commit: |
| |
| 6459b8469753e9fe ("arm64: entry: consolidate Cortex-A76 erratum 1463225 workaround") |
| |
| ... which removed the NOKPROBE_SYMBOL() annotation associated with the |
| function. |
| |
| My intent was that cortex_a76_erratum_1463225_debug_handler() would be |
| inlined into its caller, el1_dbg(), which is marked noinstr and cannot |
| be probed. Mark cortex_a76_erratum_1463225_debug_handler() as |
| __always_inline to ensure this. |
| |
| Example splat prior to this patch (with recursive entries elided): |
| |
| | # echo p cortex_a76_erratum_1463225_debug_handler > /sys/kernel/debug/tracing/kprobe_events |
| | # echo p do_el0_svc >> /sys/kernel/debug/tracing/kprobe_events |
| | # echo 1 > /sys/kernel/debug/tracing/events/kprobes/enable |
| | Insufficient stack space to handle exception! |
| | ESR: 0x0000000096000047 -- DABT (current EL) |
| | FAR: 0xffff800009cefff0 |
| | Task stack: [0xffff800009cf0000..0xffff800009cf4000] |
| | IRQ stack: [0xffff800008000000..0xffff800008004000] |
| | Overflow stack: [0xffff00007fbc00f0..0xffff00007fbc10f0] |
| | CPU: 0 PID: 145 Comm: sh Not tainted 6.0.0 #2 |
| | Hardware name: linux,dummy-virt (DT) |
| | pstate: 604003c5 (nZCv DAIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--) |
| | pc : arm64_enter_el1_dbg+0x4/0x20 |
| | lr : el1_dbg+0x24/0x5c |
| | sp : ffff800009cf0000 |
| | x29: ffff800009cf0000 x28: ffff000002c74740 x27: 0000000000000000 |
| | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 |
| | x23: 00000000604003c5 x22: ffff80000801745c x21: 0000aaaac95ac068 |
| | x20: 00000000f2000004 x19: ffff800009cf0040 x18: 0000000000000000 |
| | x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 |
| | x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 |
| | x11: 0000000000000010 x10: ffff800008c87190 x9 : ffff800008ca00d0 |
| | x8 : 000000000000003c x7 : 0000000000000000 x6 : 0000000000000000 |
| | x5 : 0000000000000000 x4 : 0000000000000000 x3 : 00000000000043a4 |
| | x2 : 00000000f2000004 x1 : 00000000f2000004 x0 : ffff800009cf0040 |
| | Kernel panic - not syncing: kernel stack overflow |
| | CPU: 0 PID: 145 Comm: sh Not tainted 6.0.0 #2 |
| | Hardware name: linux,dummy-virt (DT) |
| | Call trace: |
| | dump_backtrace+0xe4/0x104 |
| | show_stack+0x18/0x4c |
| | dump_stack_lvl+0x64/0x7c |
| | dump_stack+0x18/0x38 |
| | panic+0x14c/0x338 |
| | test_taint+0x0/0x2c |
| | panic_bad_stack+0x104/0x118 |
| | handle_bad_stack+0x34/0x48 |
| | __bad_stack+0x78/0x7c |
| | arm64_enter_el1_dbg+0x4/0x20 |
| | el1h_64_sync_handler+0x40/0x98 |
| | el1h_64_sync+0x64/0x68 |
| | cortex_a76_erratum_1463225_debug_handler+0x0/0x34 |
| ... |
| | el1h_64_sync_handler+0x40/0x98 |
| | el1h_64_sync+0x64/0x68 |
| | cortex_a76_erratum_1463225_debug_handler+0x0/0x34 |
| ... |
| | el1h_64_sync_handler+0x40/0x98 |
| | el1h_64_sync+0x64/0x68 |
| | cortex_a76_erratum_1463225_debug_handler+0x0/0x34 |
| | el1h_64_sync_handler+0x40/0x98 |
| | el1h_64_sync+0x64/0x68 |
| | do_el0_svc+0x0/0x28 |
| | el0t_64_sync_handler+0x84/0xf0 |
| | el0t_64_sync+0x18c/0x190 |
| | Kernel Offset: disabled |
| | CPU features: 0x0080,00005021,19001080 |
| | Memory Limit: none |
| | ---[ end Kernel panic - not syncing: kernel stack overflow ]--- |
| |
| With this patch, cortex_a76_erratum_1463225_debug_handler() is inlined |
| into el1_dbg(), and el1_dbg() cannot be probed: |
| |
| | # echo p cortex_a76_erratum_1463225_debug_handler > /sys/kernel/debug/tracing/kprobe_events |
| | sh: write error: No such file or directory |
| | # grep -w cortex_a76_erratum_1463225_debug_handler /proc/kallsyms | wc -l |
| | 0 |
| | # echo p el1_dbg > /sys/kernel/debug/tracing/kprobe_events |
| | sh: write error: Invalid argument |
| | # grep -w el1_dbg /proc/kallsyms | wc -l |
| | 1 |
| |
| The Linux kernel CVE team has assigned CVE-2022-49888 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 5.12 with commit 6459b8469753e9feaa8b34691d097cffad905931 and fixed in 5.15.78 with commit 71d6c33fe223255f4416a01514da2c0bc3e283e7 |
| Issue introduced in 5.12 with commit 6459b8469753e9feaa8b34691d097cffad905931 and fixed in 6.0.8 with commit db66629d43b2d12cb43b004a4ca6be1d03228e97 |
| Issue introduced in 5.12 with commit 6459b8469753e9feaa8b34691d097cffad905931 and fixed in 6.1 with commit 024f4b2e1f874934943eb2d3d288ebc52c79f55c |
| |
| 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-2022-49888 |
| 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/kernel/entry-common.c |
| |
| |
| 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/71d6c33fe223255f4416a01514da2c0bc3e283e7 |
| https://git.kernel.org/stable/c/db66629d43b2d12cb43b004a4ca6be1d03228e97 |
| https://git.kernel.org/stable/c/024f4b2e1f874934943eb2d3d288ebc52c79f55c |