TPM code fixes - #8305
Merged
Merged
TPM code fixes#8305
Conversation
The swtpm control socket is a Unix SOCK_STREAM, so a single read() is
not guaranteed to return the full response in one shot. swtpm may
split a response into multiple writes, in which case the existing
single read() returns only the first chunk and subsequent parsing
fails with "Response for ... cmd is of incorrect length". This has
been observed on Azure Linux during emulator initialization.
In addition, when swtpm encounters an error processing a control
command (e.g. PTM_BAD_ORDINAL = 0x0A returned for commands issued
before CMD_INIT), the swtpm protocol returns only the 4-byte result
code instead of the full response. Blindly looping until msg_len_out
bytes arrive would deadlock in that case.
Add SocketDev::read_exact() that loops until the requested number of
bytes has been received (retrying on EINTR), and rework
run_control_cmd() to:
* read_exact the 4-byte result code first;
* on error, set the result code on the PTM message and return a
clean error without waiting for a payload that will never arrive;
* on success, read_exact the remaining (msg_len_out - 4) payload
bytes.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <[email protected]>
Emulator::new() refused to start the VMM unless the TPM Establishment
bit (TPM_LOC_STATE.tpmEstablished, bit 0) was already set, aborting
with "TPM not in established state" otherwise.
That gate is not justified by the TCG PC Client Platform TPM Profile
(PTP) specification:
* tpmEstablished == 0 is the defined default state after a cold
reset of the TPM.
* The bit transitions to 1 only after a TPM2_Startup is issued from
Locality 3 or 4 -- something the guest firmware/OS may or may not
ever do, and which has not happened by the time the VMM is wiring
up the device.
So the check was rejecting the spec-defined normal case. It also had
inverted internal naming (the boolean called "established_flag" was
true when the bit was 0), which is what made the conditional read as
if it were testing the opposite of what it actually tested.
In practice the check happened to pass on KVM and fail on MSHV (issue
socket, but the bug is independent of the backend: the VMM has no
business gating startup on tpmEstablished at all.
Drop the check. The bit is still surfaced to the guest from
Tpm::read() when CRB_LOC_STATE is read, which is the only place the
PTP spec requires it to be visible.
Assisted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <[email protected]>
The helper used to communicate the TPM Establishment bit between the
swtpm backend and the CRB device had inverted semantics:
self.established_flag = est.resp.bit == 0;
so `established_flag == true` actually meant "*not* established". The
device-side call site then double-negated:
if !self.emulator.get_established_flag() {
val |= 0x1; // tpmEstablished in TPM_LOC_STATE
}
The end-to-end behaviour was correct but the boundary between the
swtpm-specific backend and the (TCG-spec defined) CRB device was hard
to follow and easy to misuse -- the now-removed pre-init check in
Emulator::new() was an example of that confusion (it errored out with
"TPM not in established state" precisely when the TPM *was*
established).
Per the TCG PC Client Platform TPM Profile (PTP) specification, bit 0
of TPM_LOC_STATE_x is `tpmEstablished`:
* 0 = default state after a cold reset
* 1 = a TPM2_Startup from Locality 3 or 4 has occurred
Rename the backend accessor to `get_established_bit()` and return the
bit value directly (true == 1, false == 0). The CRB device then simply
forwards the bit, with no inversion, which makes the spec mapping
obvious and removes swtpm-flavoured naming from the device layer.
No functional change.
Asissted-by: Copilot:GPT-5.5
Signed-off-by: Wei Liu <[email protected]>
Signed-off-by: Wei Liu <[email protected]>
Member
Author
|
The MSHV TPM test is passing now. |
liuw
marked this pull request as draft
May 31, 2026 04:49
rbradford
approved these changes
Jun 1, 2026
liuw
marked this pull request as ready for review
June 1, 2026 16:30
Member
Author
|
I checked our internal bug report. The test doesn't fail 100% of the time. Hopefully this fix can help with that. |
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.
TPM test didn't work on MSHV. This series attempts to fix it.