When the kernel is started by a loader that leaves a locality other than Locality0 open, for example Intel TXT SINIT ACM leaves Locality2 open, this triggers a failure condition in the initialization of the TPM driver. The result being that despite calls to request/relinquish locality, the locality that was open at startup is never open/closed. The impact for an Intel TXT platform is that after SMX mode is exited, access to the Locality2 register space is blocked, and the TPM is locked in Locality 2 rendering the TPM unusable. The ability to trigger this failure condition was introduced in commit 933bfc5ad213, which introduced a locality counter to control when locality requests were actually sent to the TPM. The commit introduces a series of missing or incorrect protections in place for incrementing and decrementing the counter. The protection around incrementing the counter was protected with an incorrect check. The check was incorrect in two ways, 1.) it assumed that zero was the only successful value that would be returned by __tpm_tis_request_locality() and 2.) was evaluated outside the if block under which __tpm_tis_request_locality() is called. The effect of (1) is that __tpm_tis_request_locality() in fact returns the locality number that was requested, e.g. 1-4, and therefore the protection check would fail and the counter does not get incremented. The effect of (2) is a combination with the ret variable being initialized to 0 and the counter not being 0. The result is that __tpm_tis_request_locality() does not get called, but the counter is still incremented. Another effect seen is an indirect result of commit 933bfc5ad213 and is due to locality being tracked in two different locations. The first is at the TIS layer in struct tpm_tis_data and at the chip layer in struct tpm_chip. The failures experienced by commit 933bfc5ad213 causes the locality value in these two locations to fall out of sync with the value in tpm_tis_data reflecting Locality0 and struct tpm_chip having a value of -1, no locality open. This series seeks to address these conditions by introducing a protection against underflowing the locality counter. The closing of all localities at the beginning of initialization to begin with the TPM in the state expected by the sequencing codified in the initialization. Lastly to adjust the return error codes from __tpm_tis_request_locality() and tpm_tis_request_locality() to ensure they are consistent and that the locality counter is only incremented for a successful call to __tpm_tis_request_locality(). Changes in v2: - split into three patches - adjust code comments per review - dropped incorrect return value change for tpm_request_locality in tpm-chip.c - additional -1 replacement in __tpm_tis_relinquish_locality - changed -EIO to -EBUSY, which is more appropriate, in tpm_tis_relinquish_locality Daniel P. Smith (3): tpm: protect against locality counter underflow tpm: ensure tpm is in known state at startup tpm: make locality request return value consistent drivers/char/tpm/tpm_tis_core.c | 25 +++++++++++++++++++------ include/linux/tpm.h | 6 ++++++ 2 files changed, 25 insertions(+), 6 deletions(-) -- 2.30.2