CVE-2024-50194
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
08/11/2024
Last modified:
03/11/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
arm64: probes: Fix uprobes for big-endian kernels<br />
<br />
The arm64 uprobes code is broken for big-endian kernels as it doesn&#39;t<br />
convert the in-memory instruction encoding (which is always<br />
little-endian) into the kernel&#39;s native endianness before analyzing and<br />
simulating instructions. This may result in a few distinct problems:<br />
<br />
* The kernel may may erroneously reject probing an instruction which can<br />
safely be probed.<br />
<br />
* The kernel may erroneously erroneously permit stepping an<br />
instruction out-of-line when that instruction cannot be stepped<br />
out-of-line safely.<br />
<br />
* The kernel may erroneously simulate instruction incorrectly dur to<br />
interpretting the byte-swapped encoding.<br />
<br />
The endianness mismatch isn&#39;t caught by the compiler or sparse because:<br />
<br />
* The arch_uprobe::{insn,ixol} fields are encoded as arrays of u8, so<br />
the compiler and sparse have no idea these contain a little-endian<br />
32-bit value. The core uprobes code populates these with a memcpy()<br />
which similarly does not handle endianness.<br />
<br />
* While the uprobe_opcode_t type is an alias for __le32, both<br />
arch_uprobe_analyze_insn() and arch_uprobe_skip_sstep() cast from u8[]<br />
to the similarly-named probe_opcode_t, which is an alias for u32.<br />
Hence there is no endianness conversion warning.<br />
<br />
Fix this by changing the arch_uprobe::{insn,ixol} fields to __le32 and<br />
adding the appropriate __le32_to_cpu() conversions prior to consuming<br />
the instruction encoding. The core uprobes copies these fields as opaque<br />
ranges of bytes, and so is unaffected by this change.<br />
<br />
At the same time, remove MAX_UINSN_BYTES and consistently use<br />
AARCH64_INSN_SIZE for clarity.<br />
<br />
Tested with the following:<br />
<br />
| #include <br />
| #include <br />
|<br />
| #define noinline __attribute__((noinline))<br />
|<br />
| static noinline void *adrp_self(void)<br />
| {<br />
| void *addr;<br />
|<br />
| asm volatile(<br />
| " adrp %x0, adrp_self\n"<br />
| " add %x0, %x0, :lo12:adrp_self\n"<br />
| : "=r" (addr));<br />
| }<br />
|<br />
|<br />
| int main(int argc, char *argv)<br />
| {<br />
| void *ptr = adrp_self();<br />
| bool equal = (ptr == adrp_self);<br />
|<br />
| printf("adrp_self => %p\n"<br />
| "adrp_self() => %p\n"<br />
| "%s\n",<br />
| adrp_self, ptr, equal ? "EQUAL" : "NOT EQUAL");<br />
|<br />
| return 0;<br />
| }<br />
<br />
.... where the adrp_self() function was compiled to:<br />
<br />
| 00000000004007e0 :<br />
| 4007e0: 90000000 adrp x0, 400000 <br />
| 4007e4: 911f8000 add x0, x0, #0x7e0<br />
| 4007e8: d65f03c0 ret<br />
<br />
Before this patch, the ADRP is not recognized, and is assumed to be<br />
steppable, resulting in corruption of the result:<br />
<br />
| # ./adrp-self<br />
| adrp_self => 0x4007e0<br />
| adrp_self() => 0x4007e0<br />
| EQUAL<br />
| # echo &#39;p /root/adrp-self:0x007e0&#39; > /sys/kernel/tracing/uprobe_events<br />
| # echo 1 > /sys/kernel/tracing/events/uprobes/enable<br />
| # ./adrp-self<br />
| adrp_self => 0x4007e0<br />
| adrp_self() => 0xffffffffff7e0<br />
| NOT EQUAL<br />
<br />
After this patch, the ADRP is correctly recognized and simulated:<br />
<br />
| # ./adrp-self<br />
| adrp_self => 0x4007e0<br />
| adrp_self() => 0x4007e0<br />
| EQUAL<br />
| #<br />
| # echo &#39;p /root/adrp-self:0x007e0&#39; > /sys/kernel/tracing/uprobe_events<br />
| # echo 1 > /sys/kernel/tracing/events/uprobes/enable<br />
| # ./adrp-self<br />
| adrp_self => 0x4007e0<br />
| adrp_self() => 0x4007e0<br />
| EQUAL
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
| CPE | From | Up to |
|---|---|---|
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 4.10 (including) | 4.19.323 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 4.20 (including) | 5.4.285 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.5 (including) | 5.10.229 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.15.170 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.16 (including) | 6.1.115 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.2 (including) | 6.6.58 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.7 (including) | 6.11.5 (excluding) |
| cpe:2.3:o:linux:linux_kernel:6.12:rc1:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.12:rc2:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.12:rc3:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/13f8f1e05f1dc36dbba6cba0ae03354c0dafcde7
- https://git.kernel.org/stable/c/14841bb7a531b96e2dde37423a3b33e75147c60d
- https://git.kernel.org/stable/c/3d2530c65be04e93720e30f191a7cf1a3aa8b51c
- https://git.kernel.org/stable/c/8165bf83b8a64be801d59cd2532b0d1ffed74d00
- https://git.kernel.org/stable/c/b6a638cb600e13f94b5464724eaa6ab7f3349ca2
- https://git.kernel.org/stable/c/cf60d19d40184e43d9a624e55a0da73be09e938d
- https://git.kernel.org/stable/c/cf9ddf9ed94c15564a05bbf6e9f18dffa0c7df80
- https://git.kernel.org/stable/c/e6ab336213918575124d6db43dc5d3554526242e
- https://lists.debian.org/debian-lts-announce/2025/01/msg00001.html
- https://lists.debian.org/debian-lts-announce/2025/03/msg00002.html



