CVE-2022-4172 - Explaining the Integer and Buffer Overflow Bugs in QEMU’s ACPI ERST Device
Security vulnerabilities in virtualization software like QEMU are a big deal—they can let a malicious virtual machine mess with, or even crash, the host it runs on. One such issue, CVE-2022-4172, created a way for a guest VM to crash the QEMU process on the host by exploiting integer and buffer overflows in the ERST device's code.
In this post, I’ll break down what CVE-2022-4172 is, how it works (with code snippets), where you can read the original reports, and how exploitation is possible. This is straight-talk—no advanced computer science degree needed!
What is CVE-2022-4172?
CVE-2022-4172 is all about two bugs—integer overflow and classic buffer overflow—in specific functions of QEMU’s code that handle the ACPI Error Record Serialization Table (ERST), a device meant for recording hardware errors.
write_erst_record()
Both functions deal with memory and, if tricked with special requests from the guest, can overrun QEMU’s internal buffers. If you run (or let guests run) untrusted code inside VMs using QEMU with the ERST device enabled, this is important for you.
Integer Overflow
This is when a math calculation with variables exceeds what can be stored in the variable type, causing it to “wrap around.”
Example
uint32_t size = ...; // read from guest input
uint8_t *buf = malloc(size);
If size is very large (near the max integer value), adding or multiplying with it later can roll over to a small value (like or 1), causing much smaller memory to be allocated or checked than intended—but following memory operations still use the full, too-large value.
Buffer Overflow
This happens when you read or write more data into a buffer than it was allocated for, overwriting adjacent memory. This leads to crashes, memory corruption, or even code execution.
Code Walkthrough
Let’s look at simplified, illustrative snippets inspired by the vulnerable code (see links below for full context):
static void read_erst_record(ERSTState *s, uint32_t offset, uint32_t size) {
// Buffer allocated for 'size' given by guest
uint8_t *buf = g_malloc(size);
// 'size' unchecked, so if it's too large, g_malloc may fail or wrap
memcpy(buf, s->memory + offset, size);
// Possible over-read or over-write!
}
static void write_erst_record(ERSTState *s, uint32_t offset, uint32_t size) {
// Same unchecked 'size' from guest
memcpy(s->memory + offset, guest_input, size);
// If 'offset + size' > ERST memory size, buffer overflow
}
The guest (attacker) controls size and maybe offset, and if these aren’t checked against the actual buffer (s->memory) length, it can easily end up writing or reading outside of the allocated area.
The attacker designs a request with extremely large size and/or offset fields. For example
- Integer Overflow: Give a size so large that, when added to offset, it wraps back to a small number. The check if (offset + size > buf_size) would then mistakenly pass, since offset + size is now small.
- Buffer Overflow: Provide a size much bigger than the allocated buffer, so that memcpy copies way more than it should—spilling into other host memory.
This can overwrite QEMU’s memory, corrupting state, often leading to a crash (denial of service), though code execution could be possible with further research.
Practical impact: A VM with access to the ERST device (sometimes enabled by default) can crash your host QEMU process if it’s not patched!
Links to Official Reports
- QEMU Upstream Patch List
- Red Hat Security Advisory
- CVE Record at NIST NVD
How to Fix
Patches landed to check buffer boundaries and sizes before any allocations or memory operations. For example:
if (offset > MAX_OFFSET || size > s->mem_size || offset + size > s->mem_size) {
// Handle error - don't process further
}
To stay safe:
Final Thoughts
Bugs like CVE-2022-4172 show that even obscure corners of virtual machine software can be security weak spots. If you run QEMU as a hypervisor and let guests run with hardware-like privileges, patch early and patch often.
Timeline
Published on: 11/29/2022 18:15:00 UTC
Last modified on: 02/01/2023 16:02:00 UTC