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&amp;#39;t use the<br /> frame to store anything, and also didn&amp;#39;t store anything in its caller&amp;#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]-&gt;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-&gt;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&amp;#39;s a high likelyhood we&amp;#39;d<br /> crash due to that stack overflowing.<br /> <br /> Still, we shouldn&amp;#39;t be corrupting someone else&amp;#39;s stack, and it is purely<br /> luck that we aren&amp;#39;t corrupting something else.<br /> <br /> To fix it we save CR/LR into the caller&amp;#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.

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:*:*:*:*:*:*