Skip to content
GoogleGHSA-h65x-r3mq-jr2v

KVM: Out-Of-Bounds Read in nested_svm_get_tpd_pdptr

MediumCVE-2024-50115 · Published Dec 9, 2024

### Summary A Out-Of-Bounds (OOB) read affecting KVM since v3.10 was discovered in `arch/x86/kvm/svm/nested.c`. The memory read is from the user-space process managing the associated KVM based Virtual Machine (VM). The values passed from `nested_svm_get_tdp_pdptr` are not masked to prevent the access from crossing a page boundary and `__kvm_read_guest_page` lacks similar validation. ### Severity Moderate - The `nested_svm_get_tdp_pdptr` function allows a guest Virtual Machine Monitor (VMM) to read memory OOB from its guest physical address (GPA) space. The data read is used to construct Nested Page Tables (NPT) and could be used to indirectly leak memory in the host virtual address (HVA) space. QEMU was used to develop the PoC and results in `__copy_from_user` returning an error and `__kvm_read_guest_page` returning `-EFAULT`. This is because QEMU adds a guard page directly before and after each region. Other products utilizing KVM could have different outcomes. ## Proof-of-Concept A `kvm-unit-test` was developed to create a 32-bit protected mode nested-VMM with PAE enabled. It uses existing code from the project and switches a nested-VMM from 64-bit long mode to the require sys...

GitHub advisory

Affected versions

PackageAffectedFixed in
KVM
Product
>= 3.2, < 5.15.1705.15.170
Details and references

### Summary A Out-Of-Bounds (OOB) read affecting KVM since v3.10 was discovered in `arch/x86/kvm/svm/nested.c`. The memory read is from the user-space process managing the associated KVM based Virtual Machine (VM). The values passed from `nested_svm_get_tdp_pdptr` are not masked to prevent the access from crossing a page boundary and `__kvm_read_guest_page` lacks similar validation. ### Severity Moderate - The `nested_svm_get_tdp_pdptr` function allows a guest Virtual Machine Monitor (VMM) to read memory OOB from its guest physical address (GPA) space. The data read is used to construct Nested Page Tables (NPT) and could be used to indirectly leak memory in the host virtual address (HVA) space. QEMU was used to develop the PoC and results in `__copy_from_user` returning an error and `__kvm_read_guest_page` returning `-EFAULT`. This is because QEMU adds a guard page directly before and after each region. Other products utilizing KVM could have different outcomes. ## Proof-of-Concept A `kvm-unit-test` was developed to create a 32-bit protected mode nested-VMM with PAE enabled. It uses existing code from the project and switches a nested-VMM from 64-bit long mode to the require system state and back after executing the VMRUN instruction. This setup triggers the `nested_svm_get_tdp_pdptr` execution path in KVM. Modifying the `vmcb->control.nested_cr3` value to a GPA at the edge of any memory slot will cause the OOB read access to take place. There are multiple locations that meet this criteria but change based on attached virtual devices and amount of memory. Testing with QEMU resulted in a return value of `-EFAULT` because it places guard pages at the start and end of every memory region exposed to the VM. Other applications leveraging KVM could have different results. ### Build and Run with kvm-unit-test 1. Copy `svm_p32pae_ncr3.c` and `_svm_p32pae_ncr3.S` to the `x86` directory 2. Update `Makefile.x86_64` in the `x86` directory to include the contents from the snippet below 3. Run QEMU with `qemu-system-x86_64 -cpu host -m size=2048 -serial stdio -kernel svm_p32pae_ncr3.flat` ``` // Makefile.x86_64 ... # add this line right before the "include $(SRCDIR)/$(TEST_DIR)/Makefile.common" line tests += $(TEST_DIR)/svm_p32pae_ncr3.$(exe) ... # add this line to the end of the file $(TEST_DIR)/svm_p32pae_ncr3.$(bin): $(TEST_DIR)/svm_p32pae_ncr3.o $(TEST_DIR)/_svm_p32pae_ncr3.o ``` ``` // svm_p32pae_ncr3.c #include "x86/fwcfg.h" #include "x86/msr.h" #include "x86/processor.h" #include "alloc_page.h" #include "desc.h" #include "vmalloc.h" #include "x86/asm/page.h" #include "alloc_phys.h" #define SVM_EXIT_VMMCALL 0x081 #define SVM_EXIT_SHUTDOWN 0x07f #define SVM_EXIT_NPF 0x400 #define MSR_BITMAP_SIZE 8192 #define TLB_CONTROL_FLUSH_ALL_ASID 1 #define SVM_SELECTOR_S_SHIFT 4 #define SVM_SELECTOR_P_SHIFT 7 #define SVM_SELECTOR_DB_SHIFT 10 #define SVM_SELECTOR_G_SHIFT 11 #define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT) #define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT) #define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT) #define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT) enum { INTERCEPT_INTR, INTERCEPT_NMI, INTERCEPT_SMI, INTERCEPT_INIT, INTERCEPT_VINTR, INTERCEPT_SELECTIVE_CR0, INTERCEPT_STORE_IDTR, INTERCEPT_STORE_GDTR, INTERCEPT_STORE_LDTR, INTERCEPT_STORE_TR, INTERCEPT_LOAD_IDTR, INTERCEPT_LOAD_GDTR, INTERCEPT_LOAD_LDTR, INTERCEPT_LOAD_TR, INTERCEPT_RDTSC, INTERCEPT_RDPMC, INTERCEPT_PUSHF, INTERCEPT_POPF, INTERCEPT_CPUID, INTERCEPT_RSM, INTERCEPT_IRET, INTERCEPT_INTn, INTERCEPT_INVD, INTERCEPT_PAUSE, INTERCEPT_HLT, INTERCEPT_INVLPG, INTERCEPT_INVLPGA, INTERCEPT_IOIO_PROT, INTERCEPT_MSR_PROT, INTERCEPT_TASK_SWITCH, INTERCEPT_FERR_FREEZE, INTERCEPT_SHUTDOWN, INTERCEPT_VMRUN, INTERCEPT_VMMCALL, INTERCEPT_VMLOAD, INTERCEPT_VMSAVE, INTERCEP

Severity from
GitHub (reviewed advisory)

More Google advisories

All Google
Advisory
Linux Kernel: Out of bounds Read in ksmbd_vfs_stream_read
Critical9.1Jan 9, 2025
Apple: WebKit Canvas Denoising
MediumDec 26, 2024
MacPorts: Remote Code Execution
MediumDec 23, 2024
Cisco NX OS: Bootloader Script Execution Vulnerability
HighDec 6, 2024
Linux Kernel: TOCTOU in Exec System
MediumDec 2, 2024
ION Group: Account Takeover
CriticalNov 11, 2024

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.