CVE-2021-47465
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
22/05/2024
Last modified:
24/09/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
KVM: PPC: Book3S HV: Fix stack handling in idle_kvm_start_guest()<br />
<br />
In commit 10d91611f426 ("powerpc/64s: Reimplement book3s idle code in<br />
C") kvm_start_guest() became idle_kvm_start_guest(). The old code<br />
allocated a stack frame on the emergency stack, but didn&#39;t use the<br />
frame to store anything, and also didn&#39;t store anything in its caller&#39;s<br />
frame.<br />
<br />
idle_kvm_start_guest() on the other hand is written more like a normal C<br />
function, it creates a frame on entry, and also stores CR/LR into its<br />
callers frame (per the ABI). The problem is that there is no caller<br />
frame on the emergency stack.<br />
<br />
The emergency stack for a given CPU is allocated with:<br />
<br />
paca_ptrs[i]->emergency_sp = alloc_stack(limit, i) + THREAD_SIZE;<br />
<br />
So emergency_sp actually points to the first address above the emergency<br />
stack allocation for a given CPU, we must not store above it without<br />
first decrementing it to create a frame. This is different to the<br />
regular kernel stack, paca->kstack, which is initialised to point at an<br />
initial frame that is ready to use.<br />
<br />
idle_kvm_start_guest() stores the backchain, CR and LR all of which<br />
write outside the allocation for the emergency stack. It then creates a<br />
stack frame and saves the non-volatile registers. Unfortunately the<br />
frame it creates is not large enough to fit the non-volatiles, and so<br />
the saving of the non-volatile registers also writes outside the<br />
emergency stack allocation.<br />
<br />
The end result is that we corrupt whatever is at 0-24 bytes, and 112-248<br />
bytes above the emergency stack allocation.<br />
<br />
In practice this has gone unnoticed because the memory immediately above<br />
the emergency stack happens to be used for other stack allocations,<br />
either another CPUs mc_emergency_sp or an IRQ stack. See the order of<br />
calls to irqstack_early_init() and emergency_stack_init().<br />
<br />
The low addresses of another stack are the top of that stack, and so are<br />
only used if that stack is under extreme pressue, which essentially<br />
never happens in practice - and if it did there&#39;s a high likelyhood we&#39;d<br />
crash due to that stack overflowing.<br />
<br />
Still, we shouldn&#39;t be corrupting someone else&#39;s stack, and it is purely<br />
luck that we aren&#39;t corrupting something else.<br />
<br />
To fix it we save CR/LR into the caller&#39;s frame using the existing r1 on<br />
entry, we then create a SWITCH_FRAME_SIZE frame (which has space for<br />
pt_regs) on the emergency stack with the backchain pointing to the<br />
existing stack, and then finally we switch to the new frame on the<br />
emergency stack.
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:*:*:*:*:*:*:*:* | 5.2 (including) | 5.4.156 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.5 (including) | 5.10.76 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.14.15 (excluding) |
| cpe:2.3:o:linux:linux_kernel:5.15:rc1:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:5.15:rc2:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:5.15:rc3:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:5.15:rc4:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:5.15:rc5:*:*:*:*:*:* |
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/6d077c37c4643394b1bae9682da48164fc147ea8
- https://git.kernel.org/stable/c/80bbb0bc3a0288442f7fe6fc514f4ee1cb06ccb7
- https://git.kernel.org/stable/c/9b4416c5095c20e110c82ae602c254099b83b72f
- https://git.kernel.org/stable/c/fbd724c49bead048ae9fc1a5b7bff2fb3e54f855
- https://git.kernel.org/stable/c/6d077c37c4643394b1bae9682da48164fc147ea8
- https://git.kernel.org/stable/c/80bbb0bc3a0288442f7fe6fc514f4ee1cb06ccb7
- https://git.kernel.org/stable/c/9b4416c5095c20e110c82ae602c254099b83b72f
- https://git.kernel.org/stable/c/fbd724c49bead048ae9fc1a5b7bff2fb3e54f855



