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
- Reported to Upstream: Stefan Berger (IBM) acknowledged and verified the vulnerability.
- Reported to Red Hat Product Security: Coordinated disclosure and CVE assignment requested.
- Patch Merged: Commit dc5f5ee merged upstream.