Fix TPM 1.2 resume
Subsystems (3)
Jarkko Sakkinen
maintainerv2 cover Fix TPM 1.2 resume
During TPM 1.2 resume, the first PCR read operation used inside tpm1_do_selftest() fails. Fix the bugs preventing resume from working.
v2:
* Added Jerry's reviewed-by's.
* Rebased to 865fdb08197e ("Merge tag 'input-for-v6.4-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input").
* Mirrored patches to linux-next.
Jarkko Sakkinen (2):
tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume
tpm: Prevent hwrng from activating during resume
drivers/char/tpm/tpm-chip.c | 4 +++ drivers/char/tpm/tpm-interface.c | 10 ++++++++ drivers/char/tpm/tpm_tis_core.c | 43 ++++++++++++++------------------ include/linux/tpm.h | 1 + 4 files changed, 34 insertions(+), 24 deletions(-)
Signature · 1 line
2.39.2
Jarkko Sakkinen
maintainerPATCH v2 1/2 tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume
Before sending a TPM command, CLKRUN protocol must be disabled. This is not done in the case of tpm1_do_selftest() call site inside tpm_tis_resume().
Address this by decorating the calls with tpm_chip_{start,stop}, which should be always used to arm and disarm the TPM chip for transmission.
Finally, move the call to the main TPM driver callback as the last step because it should arm the chip by itself, if it needs that type of functionality.
--- drivers/char/tpm/tpm_tis_core.c | 43 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-)
drivers/char/tpm/tpm_tis_core.c +19 -24
@@ -1209,25 +1209,20 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)u32 intmask;int rc; -if (chip->ops->clk_enable !=NULL ) - chip->ops->clk_enable (chip, true); - -/* reenable interrupts that device may have lost or -* BIOS/firmware may have disabled +/* +* Re-enable interrupts that device may have lost or BIOS/firmware may +* have disabled. */ rc =tpm_tis_write8 (priv,TPM_INT_VECTOR (priv->locality), priv->irq); -if (rc <0 ) - goto out; +if (rc <0 ) { +dev_err (&chip->dev,"Setting IRQ failed.\n" ); +return ; + } intmask = priv->int_mask |TPM_GLOBAL_INT_ENABLE ; - -tpm_tis_write32 (priv,TPM_INT_ENABLE (priv->locality), intmask); - -out: -if (chip->ops->clk_enable !=NULL ) - chip->ops->clk_enable (chip, false); - -return ; + rc =tpm_tis_write32 (priv,TPM_INT_ENABLE (priv->locality), intmask); +if (rc <0 ) +dev_err (&chip->dev,"Enabling interrupts failed.\n" ); }int tpm_tis_resume (struct device *dev)
@@ -1235,27 +1230,27 @@ int tpm_tis_resume(struct device *dev)struct tpm_chip *chip =dev_get_drvdata (dev);int ret; - ret =tpm_tis_request_locality (chip,0 ); -if (ret <0 ) + ret =tpm_chip_start (chip); +if (ret)return ret;if (chip->flags &TPM_CHIP_FLAG_IRQ )tpm_tis_reenable_interrupts (chip); - ret =tpm_pm_resume (dev); -if (ret) - goto out; -/* * TPM 1.2 requires self-test on resume. This function actually returns * an error code but for unknown reason it isn't handled. */ if (!(chip->flags &TPM_CHIP_FLAG_TPM2 ))tpm1_do_selftest (chip); -out: -tpm_tis_relinquish_locality (chip,0 ); - return ret; +tpm_chip_stop (chip); + + ret =tpm_pm_resume (dev); +if (ret) +return ret; + + return 0; }EXPORT_SYMBOL_GPL (tpm_tis_resume);#endif
Signature · 1 line
2.39.2
Jarkko Sakkinen
maintainerPATCH v2 2/2 tpm: Prevent hwrng from activating during resume
In reply to Jarkko SakkinenSet TPM_CHIP_FLAG_SUSPENDED in tpm_pm_suspend() and reset in tpm_pm_resume(). While the flag is set, tpm_hwrng() gives back zero bytes. This prevents hwrng from racing during resume.
--- drivers/char/tpm/tpm-chip.c | 4 ++++ drivers/char/tpm/tpm-interface.c | 10 ++++++++++ include/linux/tpm.h | 1 + 3 files changed, 15 insertions(+)
drivers/char/tpm/tpm-chip.c +4 -0
@@ -571,6 +571,10 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); +/* Give back zero bytes, as TPM chip has not yet fully resumed: */ +if (chip->flags &TPM_CHIP_FLAG_SUSPENDED ) +return 0 ; +return tpm_get_random (chip, data, max); }
drivers/char/tpm/tpm-interface.c +10 -0
@@ -412,6 +412,8 @@ int tpm_pm_suspend(struct device *dev) } suspended: + chip->flags |=TPM_CHIP_FLAG_SUSPENDED ; +if (rc)dev_err (dev,"Ignoring error %d while suspending\n" , rc);return 0 ;
@@ -429,6 +431,14 @@ int tpm_pm_resume(struct device *dev)if (chip ==NULL )return -ENODEV ; + chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED ; + +/* +* Guarantee that SUSPENDED is written last, so that hwrng does not +* activate before the chip has been fully resumed. +*/ +wmb (); +return 0 ; }EXPORT_SYMBOL_GPL (tpm_pm_resume);
include/linux/tpm.h +1 -0
@@ -282,6 +282,7 @@ enum tpm_chip_flags {TPM_CHIP_FLAG_ALWAYS_POWERED =BIT (5 ),TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED =BIT (6 ),TPM_CHIP_FLAG_FIRMWARE_UPGRADE =BIT (7 ), + TPM_CHIP_FLAG_SUSPENDED = BIT(8), };#define to_tpm_chip (d) container_of(d, struct tpm_chip, dev)
Signature · 1 line
2.39.2
Quoted 2 lines · Jarkko Sakkinen
During TPM 1.2 resume, the first PCR read operation used inside
tpm1_do_selftest()fails. Fix the bugs preventing resume from working.
Thanks for fixing this, unfortunately I can no longer test the fix as I've got a new laptop since when I was hitting the bug on the older one.
Vlastimil
Quoted 21 lines
v2:
* Added Jerry's reviewed-by's.
* Rebased to865fdb08197e("Merge tag 'input-for-v6.4-rc0' ofgit://git.kernel.org/pub/scm/linux/kernel/git/dtor/input").
* Mirrored patches to linux-next.Cc Vlastimil Babka <[email protected]>Cc Jason A. Donenfeld <[email protected]>Cc Jason Gunthorpe <[email protected]>Cc Jerry Snitselaar <[email protected]>Jarkko Sakkinen (2):
tpm_tis: Use tpm_chip_{start,stop} decoration insidetpm_tis_resume
tpm: Prevent hwrng from activating during resumedrivers/char/tpm/tpm-chip.c | 4 +++ drivers/char/tpm/tpm-interface.c | 10 ++++++++ drivers/char/tpm/tpm_tis_core.c | 43 ++++++++++++++------------------ include/linux/tpm.h | 1 + 4 files changed, 34 insertions(+), 24 deletions(-)
Jarkko Sakkinen
maintainerQuoted 6 lines · Vlastimil Babka
Quoted 2 lines · Jarkko Sakkinen
During TPM 1.2 resume, the first PCR read operation used inside
tpm1_do_selftest()fails. Fix the bugs preventing resume from working.Thanks for fixing this, unfortunately I can no longer test the fix as I've got a new laptop since when I was hitting the bug on the older one.
I don't think these fixed make things worse, and I could reproduce the bug locally, so I'll put them to my PR :-)
BR, Jarkko