CVE-2026-75900: Out-of-Bounds Read in swtpm (Software TPM Emulator)

Author: Suraj Theekshana Component: swtpm Severity: CVSS 6.1 (Moderate)

Overview

During an audit of the swtpm codebase, I discovered an Out-of-Bounds (OOB) read vulnerability in the NVRAM state header validation logic. The flaw allows an attacker with write access to the swtpm control channel to crash the daemon, resulting in a Denial of Service (DoS) to the associated virtual machine, and potentially leak a small amount of adjacent heap memory into the logs.

The Vulnerability

The issue resides in src/swtpm/swtpm_nvstore.c within the SWTPM_NVRAM_CheckHeader() function. The function attempts to validate a caller-supplied length against the size of the blobheader structure. However, it mistakenly checks the length against the size of the pointer to the structure, rather than the structure itself.

blobheader *bh = (blobheader *)data;
if (length < sizeof(bh)) {          /* 8 bytes on 64-bit, 4 on 32-bit */

Because blobheader is __attribute__((packed)) and 10 bytes wide, checking against the 8-byte pointer size on 64-bit systems allows an 8-byte blob to pass the check. The very first field dereferenced after this guard is ntohl(bh->totlen) (located at offsets 6-9). This causes a 4-byte load that reaches 2 bytes past the 8-byte allocation.

Reachability & Impact

When loading state files or processing a CMD_SET_STATEBLOB over the control channel, the daemon allocates exactly the length the client declares. Sending an 8-byte state blob yields an 8-byte heap allocation, followed immediately by the out-of-bounds 4-byte read.

Impact: Out-of-bounds read of up to 2 bytes (6 bytes on 32-bit builds), causing daemon termination (CWE-125). Additionally, the mismatch branch passes the out-of-bounds value to a logging function, placing a small number of adjacent heap bytes into the log file.

Steps to Reproduce

The vulnerability was verified on Ubuntu 24.04 LTS (aarch64) using AddressSanitizer (ASan) against swtpm v0.10.1.

$ ./autogen.sh --with-openssl --without-seccomp --without-cuse CC=clang \
    CFLAGS="-g -O1 -fsanitize=address -fno-omit-frame-pointer" \
    LDFLAGS="-fsanitize=address"
$ make
$ swtpm socket --tpmstate dir=/tmp/vtpm \
    --ctrl type=unixio,path=/tmp/vtpm/sock --tpm2

Sending an 8-byte payload via a custom python script instantly crashes the daemon. The AddressSanitizer trace confirms the heap-buffer-overflow:

==45678==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000001179
READ of size 4 at 0x502000001179 thread T0
0x502000001179 is located 1 bytes after 8-byte region [0x502000001170,0x502000001178)

The Fix

The vulnerability was patched by correcting the sizeof operator to evaluate the dereferenced pointer structure size instead of the pointer itself.

-    if (length < sizeof(bh)) {
+    if (length < sizeof(*bh)) {

Timeline