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...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| KVM Product | >= 3.2, < 5.15.170 | 5.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| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Jan 92025 | Linux Kernel: Out of bounds Read in ksmbd_vfs_stream_read | Critical9.1 | v6.13-rc2 |
| Dec 262024 | Apple: WebKit Canvas Denoising | Medium | No fix yet |
| Dec 232024 | MacPorts: Remote Code Execution | Medium | No fix yet |
| Dec 62024 | Cisco NX OS: Bootloader Script Execution Vulnerability | High | No fix yet |
| Dec 22024 | Linux Kernel: TOCTOU in Exec System | Medium | See the advisory |
| Nov 112024 | ION Group: Account Takeover | Critical | No fix yet |