Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-13216

CVE-2026-13216: Zephyr virtio PCI Driver RCE Vulnerability

CVE-2026-13216 is a remote code execution flaw in Zephyr's virtio PCI driver that allows malicious devices to corrupt kernel stack memory through unvalidated capability lengths. This post explains its impact, technical details, and mitigation.

Published:

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.

c
			((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.
bash
# 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.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.