| 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-2022-49721: arm64: ftrace: consistently handle PLTs. |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| arm64: ftrace: consistently handle PLTs. |
| |
| Sometimes it is necessary to use a PLT entry to call an ftrace |
| trampoline. This is handled by ftrace_make_call() and ftrace_make_nop(), |
| with each having *almost* identical logic, but this is not handled by |
| ftrace_modify_call() since its introduction in commit: |
| |
| 3b23e4991fb66f6d ("arm64: implement ftrace with regs") |
| |
| Due to this, if we ever were to call ftrace_modify_call() for a callsite |
| which requires a PLT entry for a trampoline, then either: |
| |
| a) If the old addr requires a trampoline, ftrace_modify_call() will use |
| an out-of-range address to generate the 'old' branch instruction. |
| This will result in warnings from aarch64_insn_gen_branch_imm() and |
| ftrace_modify_code(), and no instructions will be modified. As |
| ftrace_modify_call() will return an error, this will result in |
| subsequent internal ftrace errors. |
| |
| b) If the old addr does not require a trampoline, but the new addr does, |
| ftrace_modify_call() will use an out-of-range address to generate the |
| 'new' branch instruction. This will result in warnings from |
| aarch64_insn_gen_branch_imm(), and ftrace_modify_code() will replace |
| the 'old' branch with a BRK. This will result in a kernel panic when |
| this BRK is later executed. |
| |
| Practically speaking, case (a) is vastly more likely than case (b), and |
| typically this will result in internal ftrace errors that don't |
| necessarily affect the rest of the system. This can be demonstrated with |
| an out-of-tree test module which triggers ftrace_modify_call(), e.g. |
| |
| | # insmod test_ftrace.ko |
| | test_ftrace: Function test_function raw=0xffffb3749399201c, callsite=0xffffb37493992024 |
| | branch_imm_common: offset out of range |
| | branch_imm_common: offset out of range |
| | ------------[ ftrace bug ]------------ |
| | ftrace failed to modify |
| | [<ffffb37493992024>] test_function+0x8/0x38 [test_ftrace] |
| | actual: 1d:00:00:94 |
| | Updating ftrace call site to call a different ftrace function |
| | ftrace record flags: e0000002 |
| | (2) R |
| | expected tramp: ffffb374ae42ed54 |
| | ------------[ cut here ]------------ |
| | WARNING: CPU: 0 PID: 165 at kernel/trace/ftrace.c:2085 ftrace_bug+0x280/0x2b0 |
| | Modules linked in: test_ftrace(+) |
| | CPU: 0 PID: 165 Comm: insmod Not tainted 5.19.0-rc2-00002-g4d9ead8b45ce #13 |
| | Hardware name: linux,dummy-virt (DT) |
| | pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) |
| | pc : ftrace_bug+0x280/0x2b0 |
| | lr : ftrace_bug+0x280/0x2b0 |
| | sp : ffff80000839ba00 |
| | x29: ffff80000839ba00 x28: 0000000000000000 x27: ffff80000839bcf0 |
| | x26: ffffb37493994180 x25: ffffb374b0991c28 x24: ffffb374b0d70000 |
| | x23: 00000000ffffffea x22: ffffb374afcc33b0 x21: ffffb374b08f9cc8 |
| | x20: ffff572b8462c000 x19: ffffb374b08f9000 x18: ffffffffffffffff |
| | x17: 6c6c6163202c6331 x16: ffffb374ae5ad110 x15: ffffb374b0d51ee4 |
| | x14: 0000000000000000 x13: 3435646532346561 x12: 3437336266666666 |
| | x11: 203a706d61727420 x10: 6465746365707865 x9 : ffffb374ae5149e8 |
| | x8 : 336266666666203a x7 : 706d617274206465 x6 : 00000000fffff167 |
| | x5 : ffff572bffbc4a08 x4 : 00000000fffff167 x3 : 0000000000000000 |
| | x2 : 0000000000000000 x1 : ffff572b84461e00 x0 : 0000000000000022 |
| | Call trace: |
| | ftrace_bug+0x280/0x2b0 |
| | ftrace_replace_code+0x98/0xa0 |
| | ftrace_modify_all_code+0xe0/0x144 |
| | arch_ftrace_update_code+0x14/0x20 |
| | ftrace_startup+0xf8/0x1b0 |
| | register_ftrace_function+0x38/0x90 |
| | test_ftrace_init+0xd0/0x1000 [test_ftrace] |
| | do_one_initcall+0x50/0x2b0 |
| | do_init_module+0x50/0x1f0 |
| | load_module+0x17c8/0x1d64 |
| | __do_sys_finit_module+0xa8/0x100 |
| | __arm64_sys_finit_module+0x2c/0x3c |
| | invoke_syscall+0x50/0x120 |
| | el0_svc_common.constprop.0+0xdc/0x100 |
| | do_el0_svc+0x3c/0xd0 |
| | el0_svc+0x34/0xb0 |
| | el0t_64_sync_handler+0xbc/0x140 |
| | el0t_64_sync+0x18c/0x190 |
| | ---[ end trace 0000000000000000 ]--- |
| |
| We can solve this by consistently determining whether to use a PLT entry |
| for an address. |
| |
| Note that since (the earlier) commit: |
| |
| f1a54ae9af0da4d7 ("arm64: module/ftrace: intialize PLT at load time") |
| |
| ... we can consistently determine the PLT address that a given callsite |
| will use, and therefore ftrace_make_nop() does not need to skip |
| validation when a PLT is in use. |
| |
| This patch factors the existing logic out of ftrace_make_call() and |
| ftrace_make_nop() into a common ftrace_find_callable_addr() helper |
| function, which is used by ftrace_make_call(), ftrace_make_nop(), and |
| ftrace_modify_call(). In ftrace_make_nop() the patching is consistently |
| validated by ftrace_modify_code() as we can always determine what the |
| old instruction should have been. |
| |
| The Linux kernel CVE team has assigned CVE-2022-49721 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 5.5 with commit 3b23e4991fb66f6d152f9055ede271a726ef9f21 and fixed in 5.10.124 with commit bc28fde90937a920f7714ec4408269cac744f796 |
| Issue introduced in 5.5 with commit 3b23e4991fb66f6d152f9055ede271a726ef9f21 and fixed in 5.15.49 with commit db73aa9466338ec821ed2a0b01721fe4d06876b1 |
| Issue introduced in 5.5 with commit 3b23e4991fb66f6d152f9055ede271a726ef9f21 and fixed in 5.18.6 with commit dcecc96ed16f73417de5550f384e348c9d56f279 |
| Issue introduced in 5.5 with commit 3b23e4991fb66f6d152f9055ede271a726ef9f21 and fixed in 5.19 with commit a6253579977e4c6f7818eeb05bf2bc65678a7187 |
| |
| 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-49721 |
| 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/ftrace.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/bc28fde90937a920f7714ec4408269cac744f796 |
| https://git.kernel.org/stable/c/db73aa9466338ec821ed2a0b01721fe4d06876b1 |
| https://git.kernel.org/stable/c/dcecc96ed16f73417de5550f384e348c9d56f279 |
| https://git.kernel.org/stable/c/a6253579977e4c6f7818eeb05bf2bc65678a7187 |