CVE-2024-53196 - Critical KVM MMIO Instruction Handling Bug in Linux Kernel (arm64)

A newly patched vulnerability, CVE-2024-53196, was found in the Linux Kernel's KVM subsystem for the ARM64 architecture. The issue surfaces in MMIO instruction handling, where the Kernel Virtual Machine (KVM) might incorrectly "retire" (finish processing) a memory-mapped I/O (MMIO) instruction even if there is a pending synchronous abort. This can be triggered by a user with control over a guest, and the bug can surface as a WARN trace in the kernel logs.

Let's break down what the vulnerability is, how it happens, how you could trigger it, and how it's fixed.

What is the Vulnerability?

KVM (Kernel-based Virtual Machine) is a Linux module that allows the kernel to function as a hypervisor. On ARM64 platforms, when a guest VM tries to access memory it shouldn't (often via MMIO), KVM either emulates the operation or, if it's unsupported, signals an abort to the guest operating system. This is a known feature.

However, the kernel didn't fully validate the system state before "retiring" (advancing past) the MMIO instruction. If a synchronous abort exception is pending, KVM should *not* advance the program counter (PC), but it did—this could happen if userspace (or a guest) triggers an unsupported MMIO operation. That inconsistency results in a kernel WARN.

Here's a real-life kernel trace from a triggered warning

WARNING: CPU:  PID: 30558 at arch/arm64/include/asm/kvm_emulate.h:536 kvm_handle_mmio_return+x46c/x5c4 arch/arm64/include/asm/kvm_emulate.h:536
Call trace:
 kvm_handle_mmio_return+x46c/x5c4 arch/arm64/include/asm/kvm_emulate.h:536
 kvm_arch_vcpu_ioctl_run+x98/x15b4 arch/arm64/kvm/arm.c:1133
 kvm_vcpu_ioctl+x75c/xa78 virt/kvm/kvm_main.c:4487
 __do_sys_ioctl fs/ioctl.c:51 [inline]
 __se_sys_ioctl fs/ioctl.c:893 [inline]
 __arm64_sys_ioctl+x14c/x1c8 fs/ioctl.c:893
 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
 invoke_syscall+x98/x2b8 arch/arm64/kernel/syscall.c:49
 el_svc_common+x1e/x23c arch/arm64/kernel/syscall.c:132
 do_el_svc+x48/x58 arch/arm64/kernel/syscall.c:151
 el_svc+x38/x68 arch/arm64/kernel/entry-common.c:712
 elt_64_sync_handler+x90/xfc arch/arm64/kernel/entry-common.c:730
 elt_64_sync+x190/x194 arch/arm64/kernel/entry.S:598

The core issue: KVM is incrementing the guest program counter when an exception is still being handled. This goes against expected kernel behavior and could open subtle bug doors or, in worst-case, enable guest-initiated attacks.

An adversarial guests or userspace manager can cause the fault using the KVM UAPI by

1. Running a VM and making it perform an unsupported MMIO access (say, mapping memory to a device that isn’t there).

Userspace returns a result to KVM that signals an abort.

4. On resuming, if there’s a pending synchronous abort, KVM should stop – but before the patch, KVM would retire the instruction anyway.

Pseudocode

// Run a VM with a crafted memory map
// Cause an MMIO access to unmapped address
ioctl(kvm_fd, KVM_RUN, &kvm_run_struct); // Step 1

if (kvm_run_struct->exit_reason == KVM_EXIT_MMIO) {
    // Step 2 & 3: Return an abort
    // Simulate error by not setting MMIO data or possibly setting error flags
    // (Exact mechanism depends on userland VMM implementation)
}

// Step 4: Resume the VM, triggering PC advancement with pending abort
ioctl(kvm_fd, KVM_RUN, &kvm_run_struct);

This can produce a kernel WARN or accidentally confuse the guest, leading possibly to guest crash, bad state, or worse if chained with other kernel bugs.

The PATCH (Fix)

The fix is simple, but crucial: before retiring the MMIO instruction (advancing the guest PC), check if there's a pending synchronous exception. If there is, skip emulation and don’t move PC.

Patch Snippet

// arch/arm64/kvm/handle_exit.c (before patch, simplified):
if (exit_reason == KVM_EXIT_MMIO) {
    kvm_handle_mmio_return(vcpu);
}

// after patch:
if (exit_reason == KVM_EXIT_MMIO) {
    if (!vcpu_has_synchronous_exception(vcpu)) {
        kvm_handle_mmio_return(vcpu);
    }
    // else: exception is pending, don't retire instruction!
}

*Note*: Actual function names and conditionals may differ; for the precise implementation, see the Linux kernel commit logs linked below.

Impact and Security Implications

- Severity: Medium-to-High (could be used for guest-to-hypervisor attacks if combined with other vulnerabilities)
- Exposed Systems: Linux ARM64 hosts running untrusted guests/users or custom KVM userspace.

References

- Linux Kernel Patch discussion
- KVM ARM64 Kernel UAPI Docs
- Example upstream commit

Upgrade your kernel to the latest stable release.

- If you're using KVM with arm64 (for example, on public clouds with ARM-based hosts or embedded platforms), check your kernel source and apply backports, if necessary.

To find if you’re at risk, run

uname -a
dmesg | grep kvm
# Look for log lines matching the WARNING shown above

Conclusion

CVE-2024-53196 highlights another subtle, yet important, gap in KVM’s MMIO emulation path on ARM systems. If you rely on virtualization, especially for ARM workloads, check your kernel and apply fixes. Memory handling errors can have unpredictable impacts in a hypervisor context, especially when hosting potentially untrusted VMs.


*Written exclusively for your technical security insights. Please reference the real links above for further reading.*

Timeline

Published on: 12/27/2024 14:15:27 UTC
Last modified on: 05/04/2025 09:55:30 UTC