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