CVE-2026-13216 Overview
CVE-2026-13216 is an out-of-bounds write vulnerability [CWE-787] in the Zephyr RTOS virtio PCI driver (drivers/virtio/virtio_pci.c). The virtio_pci_read_cap() function trusts a device-supplied cap_len byte read from PCI configuration space without runtime validation. The pre-existing assert() compiles out in production builds because CONFIG_ASSERT defaults to off. An attacker-controlled cap_len value then drives a copy loop into a fixed-size stack buffer, producing either a near-unbounded underflow write or an overflow of up to ~228 bytes past the caller's buffer during boot-time device probe.
Critical Impact
A malicious or passthrough virtio PCIe device can corrupt the Zephyr kernel stack with device-controlled content, enabling potential code execution or system crash on bare-metal or confidential-computing deployments.
Affected Products
- Zephyr RTOS with CONFIG_VIRTIO_PCI enabled
- Bare-metal systems exposing untrusted or passthrough virtio PCIe devices
- Confidential-computing guests defending against an untrusted host
Discovery Timeline
- 2026-08-25 - CVE-2026-13216 published to NVD
- 2026-08-26 - Last updated in NVD database
Technical Details for CVE-2026-13216
Vulnerability Analysis
The Zephyr virtio PCI driver walks a device's PCI capability list during initialization. Inside virtio_pci_read_cap(), the driver reads capability structures via pcie_conf_read() into a stack tmp buffer. The device-supplied cap_len field was validated only through assert(tmp.cap_len == cap_struct_size), which resolves to __ASSERT_NO_MSG() and is gated by CONFIG_ASSERT. Production builds ship with assertions disabled, so cap_len reached the copy logic unchecked.
The driver then computes extra_data_words = (tmp.cap_len - sizeof(struct virtio_pci_cap)) / sizeof(uint32_t). Because cap_len is attacker-controlled and extra_data_words is unsigned, the subtraction and subsequent copy loop become fully device-driven memory writes on the kernel stack.
Root Cause
The root cause is missing runtime bounds validation on untrusted input from a PCI device. Reliance on assert() for a security-relevant boundary check leaves production builds unprotected. This is a classic input-validation failure at a trust boundary between kernel and peripheral.
Attack Vector
The vulnerability requires a physically attached or passthrough virtio PCIe device that the Zephyr kernel treats as untrusted. Two exploit primitives exist:
- A cap_len value below 24 (sizeof(struct virtio_pci_cap)) underflows extra_data_words toward SIZE_MAX, yielding an effectively unbounded stack write.
- A cap_len above the caller's buffer (up to 255) writes up to roughly 228 bytes of device-controlled data past the stack buffer.
Both primitives execute during device probe with device-controlled content, positioning the attacker for kernel-mode code execution or a controlled crash.
((uint32_t *)&tmp)[i] = pcie_conf_read(bdf, cap_off + i);
}
if (tmp.cfg_type == cfg_type) {
- assert(tmp.cap_len == cap_struct_size);
+ if (tmp.cap_len < sizeof(struct virtio_pci_cap) ||
+ tmp.cap_len > cap_struct_size) {
+ LOG_ERR("invalid virtio pci cap_len %u for bdf 0x%x",
+ tmp.cap_len, bdf);
+ return false;
+ }
size_t extra_data_words =
(tmp.cap_len - sizeof(struct virtio_pci_cap)) / sizeof(uint32_t);
size_t extra_data_offset =
Source: Zephyr commit d98dacee24ad10c972d3b7281c9009d82ed351c9
Detection Methods for CVE-2026-13216
Indicators of Compromise
- Unexpected boot-time crashes or stack canary faults on Zephyr systems immediately after PCI device enumeration.
- Post-patch log entries matching invalid virtio pci cap_len %u for bdf 0x%x indicating a device advertising malformed capability lengths.
- Presence of unauthorized or unexpected virtio PCIe devices on bare-metal Zephyr hardware.
Detection Strategies
- Audit Zephyr build configurations for CONFIG_VIRTIO_PCI=y and confirm the patched driver revision is in use.
- Inspect firmware and device inventories for physical or passthrough virtio devices whose provenance is not fully trusted.
- Review Zephyr boot logs and hypervisor device-attach events for capability parsing failures.
Monitoring Recommendations
- Aggregate Zephyr device-driver log output centrally and alert on the new LOG_ERR message emitted by the fixed virtio_pci_read_cap().
- Monitor confidential-computing guest attestation reports for unexpected PCI topology changes prior to virtio probe.
- Track upstream Zephyr security advisories via GHSA-qrh3-4mvv-w667 for follow-up fixes.
How to Mitigate CVE-2026-13216
Immediate Actions Required
- Apply the upstream Zephyr patch that replaces the compiled-out assert() with a runtime range check on cap_len.
- Rebuild and redeploy firmware images for any bare-metal or confidential-computing target using CONFIG_VIRTIO_PCI.
- Restrict PCI passthrough to virtio backends whose trust model matches the guest's assumptions.
Patch Information
The fix is committed to Zephyr in commit d98dacee24ad10c972d3b7281c9009d82ed351c9. It rejects any cap_len value outside [sizeof(struct virtio_pci_cap), cap_struct_size] before arithmetic or copy, and logs the offending bus/device/function identifier. See GHSA-qrh3-4mvv-w667 for advisory metadata.
Workarounds
- Enable CONFIG_ASSERT=y in Zephyr builds as a temporary hardening measure so the existing assertion triggers instead of silently proceeding.
- Disable CONFIG_VIRTIO_PCI on targets that do not require virtio PCI transport.
- Prevent attachment of untrusted virtio PCIe devices via platform firmware policy or hypervisor configuration until the patch is deployed.
# Zephyr build hardening (temporary mitigation)
CONFIG_ASSERT=y
# Or, if virtio PCI is not required, disable the driver
CONFIG_VIRTIO_PCI=n
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

