
Reading Firecracker's CVE-2026-122192: How Failing to Free Memory Lets a Guest Read and Write VMM Memory, and the Conditions Under Which It Applies
This page has been translated by machine translation. View original
Hello! I'm Yuji Nishimura from the Ops team!
On November 4, 2026, AWS Security Bulletin 2026-169-AWS disclosed CVE-2026-122192, a vulnerability in Firecracker. Under certain host memory conditions, in a microVM restored from a snapshot, the guest's root could read and write the memory of the Firecracker process on the host side. AWS states that its own services, such as AWS Lambda, are not affected. However, environments where you operate Firecracker yourself may be affected.
In this article, I read the fix PR and the advisory, use diagrams to sort out "why a hole opens in memory," and summarize how to check whether your environment is affected and what countermeasures to take.
Conclusion First: Conditions and Countermeasures
You are affected if all three of the following apply.
| What to check | Condition for being affected |
|---|---|
| Firecracker version | v0.23.0 to v1.16.1 (in the supported release lines, v1.16.0 and v1.16.1) |
| How snapshots are restored | You use the File memory backend with PUT /snapshot/load |
| VM devices | The VM has a balloon (a device that returns guest memory to the host) or virtio-mem (a device that adds and removes memory later) |
The countermeasure is to update to v1.16.2 or to v1.17.0 or later. Both change the snapshot format, so saved snapshots need to be recreated. If you cannot update right away, restoring with the Uffd backend is the mitigation. VMs started without using snapshots and VMs restored with the Uffd backend are not affected.
The host kernel version is not included in the affected conditions in the advisory. How the kernel version changes whether the hole remains is explained in "Why It Works."
What Happened
What I could confirm from the AWS bulletin and the Firecracker advisory GHSA-48ww-rqpp-2mgm is as follows.
- Description: When the process of releasing (discarding) a range of guest memory failed, Firecracker kept running with part of that range left unmapped. Afterward, memory that Firecracker allocated in the same range could sometimes be read and written from the guest.
- Severity: The advisory rates it CVSS 3.1 7.5 (
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H). The AWS bulletin does not list a CVSS score. - Exploitation: Neither the bulletin nor the advisory mentions exploitation.
- Reporter: Juan Pablo Martinez Kuhn of Coinspect (according to the bulletin and the advisory).
Lining up the timeline, the fixed versions were released about two months before the disclosure.
| Date | Event | Source |
|---|---|---|
| 2026-09-01 | Fix PR #6174 merged (backport #6178 to the 1.16 line was on 09-02) | PR #6174 |
| 2026-09-10 | v1.16.2 and v1.17.0 released | v1.16.2 release notes |
| 2026-11-04 | Advisory and AWS bulletin published | The bulletin and advisory above |
The v1.16.2 release notes describe the problem fixed by #6174 as follows: in a microVM restored from a snapshot memory file, memory unplugged by virtio-mem was left in a state writable from the VMM, and in some cases it was left unmapped. The release notes mention only virtio-mem, but the advisory also covers VMs with a balloon.
Attack Flow
- Prerequisites: The VM must meet the three conditions above, and the attacker must have root inside the guest (CVSS
PR:H). In addition, the host must be in a memory state in which the memory replacement described later fails (AC:H). - Exploitation: When the guest returns memory through a balloon or a virtio-mem unplug, Firecracker replaces that range with an empty mapping in order to release it (hereafter, the replacement). If this replacement fails, Firecracker keeps running with the range left as a hole.
- Impact: If memory that Firecracker allocates later lands in that hole, it can be read and written from the guest. The advisory explains that the guest's root can read and write the memory of the Firecracker process. The CVSS also rates this as a scope change (
S:C).
All the diagrams in this article are conceptual diagrams I made myself based on primary sources, and they are not official architecture diagrams. Figure 1 shows the relationships among the components involved and the flow of steps 2 and 3 above.

Steps ① and ② in Figure 1 correspond to step 2 above, and ③ corresponds to step 3. The reason reads and writes are possible along the path ③ is that the actual backing of guest memory is the memory of the Firecracker process. Firecracker is a VMM that runs microVMs using KVM (Firecracker README). According to the explanation of KVM_SET_USER_MEMORY_REGION in the KVM API documentation, a guest memory region uses memory starting from an address in the VMM's process (userspace_addr). When memory in this region is swapped out, the change is automatically reflected in the guest, and the documentation gives as an example "an mmap() that affects the region will be made visible immediately".
Note that the primary sources do not describe specifics such as which data can be targeted or how to cause the failure.
Why It Works
According to the description and commit message of PR #6174, this problem arose from three factors overlapping in the replacement mechanism for VMs restored from snapshots.
Premise: Restored guest memory is replaced by overlaying an anonymous mapping
The snapshot documentation explains that File leaves page-fault handling to the kernel, while Uffd has a dedicated userspace process handle page faults. According to the PR, when restoring with the File backend, guest memory becomes a region (file-backed) that maps the memory file with MAP_PRIVATE.
When the guest returns memory, Firecracker gives the memory in that range back to the host. According to the memory hotplug documentation, for anonymous memory (memory not associated with a file) it uses madvise(MADV_DONTNEED). For a file-mapped region, on the other hand, the PR explains that Firecracker forcibly overlaid an anonymous zero-page mapping on top of the existing mapping with mmap(MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE). According to the comment in the v1.16.1 source, this is because for a file-mapped region, even after MADV_DONTNEED, the contents saved in the file would be visible on the next read.
Factor 1: The replacement mapping lacked MAP_NORESERVE
The original mapping was created with MAP_NORESERVE, but the replacement mapping did not have it. According to the PR, without MAP_NORESERVE, the replacement mapping is subject to overcommit accounting and could fail with ENOMEM.
Overcommit accounting is a mechanism by which the kernel counts the amount of memory allocated and refuses allocations according to the vm.overcommit_memory setting. According to the kernel documentation, in mode 0 (the default if you have not changed the setting), only obviously excessive allocations are refused. In mode 2 (strict), the total allocation is compared against a limit, and MAP_NORESERVE is ignored.
Factor 2: On kernels before 6.12, MAP_FIXED removes the old mapping first
The PR and commit message explain that when the host's Linux kernel is older than 6.9, MAP_FIXED removes the existing mapping before checking the accounting. Therefore, if the replacement fails, the range remains in an unmapped state.
However, checking the kernel source (mmap_region in mm/mmap.c; internally __mmap_region in 6.12), up to 6.11 the order was to remove the existing mapping and then check the accounting. This order changed in 6.12. In 6.12, the kernel only gathers the mappings to be removed without committing to anything, then checks the accounting, and if that fails it restores the original mapping. This change comes from the patch series "Avoid MAP_FIXED gap exposure" that landed in 6.12. The message of commit 224c1c702c08, one commit in that series, also says that nothing is committed during the gathering stage, so it can be undone on failure. The "change in Linux 6.12 overcommit handling" that the AWS bulletin cites as a condition for its mitigation is also consistent with this change. Since it differs from the PR's "older than 6.9," it is safest to assume that hosts on 6.9 to 6.11 also fall on the side where the hole remains.
Even on 6.12 and later hosts, the possibility that the replacement fails for other reasons does not disappear. The advisory also does not include the kernel version in its affected conditions, so judge whether you are affected by the three conditions in "Conclusion First."
Factor 3: Firecracker did not stop even when it failed
Firecracker did not treat this failure as a fatal error. According to the commit message, the caller only logged the error and continued processing, and the device continued to treat that range as valid guest memory. The advisory also lists CWE-390 (Detection of Error Condition Without Action) and CWE-825 (Expired Pointer Dereference) as CWEs.
Figure 2 shows how the returned range changes when the premise and the three factors overlap.

The Fix: Add MAP_NORESERVE and Stop the Process on Failure
PR #6174 made the following two changes for this vulnerability.
- Add
MAP_NORESERVEto the replacementmmap(themmaprules in the seccomp filters for x86_64 and aarch64 were also updated to accommodate the new flag) - If the replacement
mmapfails, stop the process, because the range has already been removed and cannot be restored. According to the commit message, the arguments are validated beforehand, so this failure never occurs with a valid request
The same PR also fixes a problem where the protection of memory unplugged by virtio-mem was being removed. Firecracker sets a slot that has been fully unplugged to PROT_NONE so that it cannot be accessed. However, because the replacement mapping was created with PROT_READ | PROT_WRITE, this protection was lost. As a result, the unplugged memory remained readable and writable from the VMM side for as long as the process was running. After the fix, each slot is remapped directly with its final protection: PROT_NONE for fully unplugged slots and PROT_READ | PROT_WRITE for slots containing plugged blocks. According to the commit message, this is because making it readable and writable first and then reapplying protection would create a window during which it is writable.
In addition, there is a change so that an unplug request for a range with no plugged blocks does not release anything (eliminating the waste of releasing the entire region on every UNPLUG_ALL), as well as an integration test. The integration test goes through virtio-mem plug and unplug and verifies that slots remain PROT_NONE after unplug even in file-mapped regions. According to the commit message, the existing virtio-mem unit tests used anonymous memory and therefore did not exercise this branch.
Figure 3 summarizes the differences before and after the fix. The top two rows are this vulnerability, and the third row is a separate fix for virtio-mem (added in v1.14.0).

Checking Whether Your Environment Is Affected
Following the advisory's conditions, check in this order.
- Firecracker version: Use
firecracker --versionto see whether it is in the range v0.23.0 to v1.16.1 - Restore method: In your orchestrator's settings or code, check whether
mem_backend.backend_typeofPUT /snapshot/loadis set toFile. Older clients that specify the deprecatedmem_file_pathfield are also handled as theFilebackend by the API implementation (v1.16.1 source). If it isUffd, you are not affected - Devices: Check whether the restored VM has a balloon or virtio-mem. You can check with
balloonandmemory-hotplugin the response ofGET /vm/config(API definition). According to the CHANGELOG, since v1.0.0 the original VM's configuration is returned even for a VM restored from a snapshot. If you only need to check for a balloon,GET /balloonalso works, and the API definition states that a 400 (Balloon device not configured.) is returned when there is no balloon
How to Protect Yourself
Update to v1.16.2 or later and recreate snapshots
Update to v1.16.2 or to v1.17.0 or later. The AWS bulletin and advisory also ask that if you use forks or derived code, you incorporate the same fix.
When updating, you need to pay attention to snapshot compatibility. According to the v1.16.2 release notes, this release raises the snapshot format version (a change from #6100, separate from this fix). As a result, snapshots created with v1.16.2 cannot be loaded by v1.16.0 / v1.16.1, and snapshots created with v1.16.0 / v1.16.1 cannot be loaded by v1.16.2.
The v1.17.0 release notes do not mention the snapshot format. However, in the source, SNAPSHOT_VERSION is 10.0.0 in v1.16.1, 11.0.0 in v1.16.2, and 12.0.0 in v1.17.0, so the MAJOR differs in all of them. In the v1.17.0 source, a snapshot whose MAJOR does not match is rejected with an InvalidFormatVersion error (snapshot/mod.rs). Therefore, even when upgrading to v1.17.0, snapshots created with v1.16.x or earlier need to be recreated. If your operations start VMs from saved snapshots, you need to plan the order of the update and the recreation.
If you cannot update right away
The advisory and the AWS bulletin list the following mitigations.
- Restore with the
Uffdbackend. In that case, you need to satisfy the requirements of the page fault handler for handling released pages. The page fault handling documentation explains that pages in ranges returned by the balloon must be filled with zeros rather than read from the file. If you use virtio-mem, you also need to handle theUFFD_EVENT_REMOVEevent for hot-removed blocks, as described in the memory hotplug documentation. - Use heuristic overcommit (
vm.overcommit_memory=0) and set an upper limit on memory size. The advisory says to keep each VM's guest memory (including the virtio-mem region) at or below the sum of the host's RAM and swap. The AWS bulletin makes the maximum discard size the subject of the limit and presents this mitigation for kernels that do not include the Linux 6.12 overcommit handling change (for the 6.12 change, see Factor 2 in "Why It Works"). - Leave the OOM killer enabled for Firecracker's memory cgroup. Neither the advisory nor the bulletin explains why this works as a mitigation.
Both the advisory and the bulletin state that the second and third mitigations only reduce how likely a failure is and do not prevent all failures.
Clues for detection
Even in versions before the fix, replacement failures were logged as errors (commit message). In the v1.16.1 source, when the replacement of a file-mapped region fails, a discard_range: mmap failed error is emitted (memory.rs). The calling devices also emit errors: virtio-mem emits virtio-mem: Failed to discard memory range, and the balloon emits Error removing memory range. If you have enabled the balloon's free page hinting or free page reporting, balloon hinting: failed to remove range and balloon: failed to remove range are also emitted. If these appear in the Firecracker logs, they are a clue that a replacement failed. The wording may change by version, so you need to verify it in the source of the version you use. Also, the logs cannot tell you whether memory ended up in that range and was read or written from the guest.
In fixed versions, the process stops when a replacement fails. In the v1.16.2 source, the same discard_range: mmap failed is included in the message emitted when it stops. An abnormal termination of the Firecracker process is also one clue (there can be other causes of abnormal termination).
Summary
- CVE-2026-122192 affects only those VMs on Firecracker v0.23.0 to v1.16.1 that were restored from a snapshot with the
Filebackend and have a balloon or virtio-mem. According to AWS, AWS services are not affected. - Because the actual backing of guest memory is the memory of the Firecracker process, if Firecracker's memory lands in a hole opened by a failed replacement, it becomes visible from the guest. The hole opened and remained because of the overlap of the replacement
mmaplackingMAP_NORESERVE,MAP_FIXEDremoving the old mapping first on kernels before 6.12, and processing not stopping even on failure. - The fixed versions, v1.16.2 and v1.17.0, were released in September 2026. You need to update to these versions and recreate existing snapshots with the new version. If you cannot update right away, restoring with the
Uffdbackend is the mitigation.
I hope this is helpful to someone.
Reference links:
- CVE-2026-122192: Guest Access to Firecracker Process Memory After a Failed Memory Discard (AWS Security Bulletin 2026-169-AWS)
- GHSA-48ww-rqpp-2mgm (Firecracker security advisory)
- fix(vmm): correct virtio-mem memory discard on snapshot restore (PR #6174)
- Firecracker v1.16.2 release notes
- Firecracker snapshot documentation
- Handling page faults on snapshot resume
- Memory hotplug (virtio-mem) documentation
- Balloon device documentation
- KVM API documentation (KVM_SET_USER_MEMORY_REGION)
- Overcommit Accounting (Linux kernel documentation)
- mm/mmap.c in Linux 6.12 (__mmap_region)
