CVE-2021-47465
Publication date:
22/05/2024
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.
Severity CVSS v4.0: Pending analysis
Last modification:
24/09/2025