Repository navigation
Fix swtpm UART read timeout to keep waiting until cumulative limit - #660
Merged
Merged
Conversation
embhorn
requested changes
Nov 2, 2026
embhorn
left a comment
Member
There was a problem hiding this comment.
Skoll Multi-Scan Review
Modes: review + review-security
Overall recommendation: REQUEST_CHANGES
Findings: 3 total — 3 posted, 0 skipped
3 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [High] [review+review-security] Terminal hangup causes a busy retry loop on zero-byte UART read —
src/tpm2_swtpm.c:225-230 - [High] [review+review-security] Zero-byte retry can exceed the configured cumulative timeout —
src/tpm2_swtpm.c:225-230 - [Medium] [review] Add automated coverage for zero-byte UART reads —
src/tpm2_swtpm.c:225-230
Review generated by Skoll
dgarske
force-pushed
the
swtpm_uart_timeout
branch
from
November 2, 2026 20:43
fb8a26b to
25ee20e
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The UART receive-timeout changes have no outstanding review issues blocking approval.
No open issues 🎉
What changed in this PR
Updates wolfTPM’s SWTPM UART transport to wait for slow TPM responses beyond a single serial-read timeout, while preserving socket transport behavior.
Changes:
- Uses deadline-bounded polling for UART receives and raises the default cumulative timeout to 60 seconds.
- Adds pseudo-terminal tests for delayed responses, silence, and hangups, and runs them in CI.
- Documents the timeout settings and UART receive behavior.
| File | Description |
|---|---|
tests/swtpm_uart_unit_tests.c |
Adds hardware-free UART receive and CPU-use tests. |
tests/include.am |
Builds the UART tests with shortened timeouts. |
src/tpm2_swtpm.c |
Adds deadline-bounded polling and configurable read timing. |
docs/system-interfaces.md |
Documents timeout options and hangup handling. |
configure.ac |
Adds a UART-specific build conditional. |
.gitignore |
Ignores UART test binaries and logs. |
.github/workflows/make-test-swtpm.yml |
Runs the UART tests in the existing CI configuration. |
Review effort: Balanced
embhorn
approved these changes
Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The SWTPM UART transport configures the TTY with
VMIN=0,VTIME=200, soread()returns 0 after 20 seconds with no data. Found on a NUCLEO-H563ZI running the wolftpm-examples STM32H5 fwTPM over the ST-LINK VCP, where RSA-2048 primary key generation takes longer than one period. Three related problems.1. A per-read timeout was treated as EOF
SwTpmReceive()failed withTPM_RC_FAILUREon any zero-byte read, so a command slower than oneVTIMEperiod failed on the host even though the device completed it andWOLFTPM_SWTPM_UART_RX_TIMEOUT_SECSallowed longer. Because a primary key is derived from the NV seed, a given board then failed the same command every time.2. A zero-byte read cannot distinguish a timeout from a hangup
A hung-up TTY also returns zero, immediately and indefinitely, so simply retrying a zero-byte read until the cumulative timeout spins on
read()for the whole timeout once the device resets or the port is unplugged.SwTpmReceive()now waits withpoll()and fails onPOLLHUP/POLLERR, which means a zero-byte read can only follow a readable descriptor and is unambiguously EOF.3. The cumulative timeout was not enforced at its stated value
The deadline was compared in whole seconds with
<=, which allowed a further full read at the limit. It is now a monotonic millisecond deadline, equality counts as expiry, and each wait is capped at the time remaining.WOLFTPM_SWTPM_UART_RX_TIMEOUT_SECSdefault is raised from 30 to 60 seconds.WOLFTPM_SWTPM_UART_VTIMEis added, defaulting to the previous 200, so the per-read period is overridable. Socket transports are unchanged.Testing
tests/swtpm_uart_unit_tests.cdrives the receive path over a pseudo-terminal, with a forked child as the TPM: a response arriving manyVTIMEperiods late, sustained silence, and peer closure, each checked for result code, elapsed time and CPU cost. Theswtpm-uartCI job was compile-only and now runs it.Configure sweep over
--enable-swtpm=uart, the socket swtpm build and the default build.Not re-tested on the NUCLEO-H563ZI since the receive path was rewritten around
poll(). The earlierwrap/wrap_test,capsandexamples/pqcruns on that board were against the previous implementation.