public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6.6] tpm: Lock TPM chip in tpm_pm_suspend() first
@ 2024-12-05  2:26 bin.lan.cn
  2024-12-05 13:34 ` Sasha Levin
  0 siblings, 1 reply; 2+ messages in thread
From: bin.lan.cn @ 2024-12-05  2:26 UTC (permalink / raw)
  To: stable, jarkko

From: Jarkko Sakkinen <jarkko@kernel.org>

[ Upstream commit 9265fed6db601ee2ec47577815387458ef4f047a ]

Setting TPM_CHIP_FLAG_SUSPENDED in the end of tpm_pm_suspend() can be racy
according, as this leaves window for tpm_hwrng_read() to be called while
the operation is in progress. The recent bug report gives also evidence of
this behaviour.

Aadress this by locking the TPM chip before checking any chip->flags both
in tpm_pm_suspend() and tpm_hwrng_read(). Move TPM_CHIP_FLAG_SUSPENDED
check inside tpm_get_random() so that it will be always checked only when
the lock is reserved.

Cc: stable@vger.kernel.org # v6.4+
Fixes: 99d464506255 ("tpm: Prevent hwrng from activating during resume")
Reported-by: Mike Seo <mikeseohyungjin@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219383
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Tested-by: Mike Seo <mikeseohyungjin@gmail.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
[ Don't call tpm2_end_auth_session() for this function does not exist
  in 6.6.y.]
Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
---
 drivers/char/tpm/tpm-chip.c      |  4 ----
 drivers/char/tpm/tpm-interface.c | 29 +++++++++++++++++++++--------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 42b1062e33cd..78999f7f248c 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -519,10 +519,6 @@ 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);
 }
 
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 66b16d26eecc..c8ea52dfa556 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -394,6 +394,13 @@ int tpm_pm_suspend(struct device *dev)
 	if (!chip)
 		return -ENODEV;
 
+	rc = tpm_try_get_ops(chip);
+	if (rc) {
+		/* Can be safely set out of locks, as no action cannot race: */
+		chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
+		goto out;
+	}
+
 	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
 		goto suspended;
 
@@ -401,19 +408,18 @@ int tpm_pm_suspend(struct device *dev)
 	    !pm_suspend_via_firmware())
 		goto suspended;
 
-	rc = tpm_try_get_ops(chip);
-	if (!rc) {
-		if (chip->flags & TPM_CHIP_FLAG_TPM2)
-			tpm2_shutdown(chip, TPM2_SU_STATE);
-		else
-			rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
-
-		tpm_put_ops(chip);
+	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+		tpm2_shutdown(chip, TPM2_SU_STATE);
+		goto suspended;
 	}
 
+	rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
+
 suspended:
 	chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
+	tpm_put_ops(chip);
 
+out:
 	if (rc)
 		dev_err(dev, "Ignoring error %d while suspending\n", rc);
 	return 0;
@@ -462,11 +468,18 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 	if (!chip)
 		return -ENODEV;
 
+	/* Give back zero bytes, as TPM chip has not yet fully resumed: */
+	if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
+		rc = 0;
+		goto out;
+	}
+
 	if (chip->flags & TPM_CHIP_FLAG_TPM2)
 		rc = tpm2_get_random(chip, out, max);
 	else
 		rc = tpm1_get_random(chip, out, max);
 
+out:
 	tpm_put_ops(chip);
 	return rc;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 6.6] tpm: Lock TPM chip in tpm_pm_suspend() first
  2024-12-05  2:26 [PATCH 6.6] tpm: Lock TPM chip in tpm_pm_suspend() first bin.lan.cn
@ 2024-12-05 13:34 ` Sasha Levin
  0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2024-12-05 13:34 UTC (permalink / raw)
  To: stable; +Cc: bin.lan.cn, Sasha Levin

[ Sasha's backport helper bot ]

Hi,

The upstream commit SHA1 provided is correct: 9265fed6db601ee2ec47577815387458ef4f047a

WARNING: Author mismatch between patch and upstream commit:
Backport author: bin.lan.cn@eng.windriver.com
Commit author: Jarkko Sakkinen <jarkko@kernel.org>


Status in newer kernel trees:
6.12.y | Present (exact SHA1)
6.11.y | Present (different SHA1: bc203fe416ab)
6.6.y | Not found

Note: The patch differs from the upstream commit:
---
1:  9265fed6db601 ! 1:  7fcb4bafb7f2d tpm: Lock TPM chip in tpm_pm_suspend() first
    @@ Metadata
      ## Commit message ##
         tpm: Lock TPM chip in tpm_pm_suspend() first
     
    +    [ Upstream commit 9265fed6db601ee2ec47577815387458ef4f047a ]
    +
         Setting TPM_CHIP_FLAG_SUSPENDED in the end of tpm_pm_suspend() can be racy
         according, as this leaves window for tpm_hwrng_read() to be called while
         the operation is in progress. The recent bug report gives also evidence of
    @@ Commit message
         Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
         Tested-by: Mike Seo <mikeseohyungjin@gmail.com>
         Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
    +    [ Don't call tpm2_end_auth_session() for this function does not exist
    +      in 6.6.y.]
    +    Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
     
      ## drivers/char/tpm/tpm-chip.c ##
     @@ drivers/char/tpm/tpm-chip.c: static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
    @@ drivers/char/tpm/tpm-interface.c: int tpm_pm_suspend(struct device *dev)
      
     -	rc = tpm_try_get_ops(chip);
     -	if (!rc) {
    --		if (chip->flags & TPM_CHIP_FLAG_TPM2) {
    --			tpm2_end_auth_session(chip);
    +-		if (chip->flags & TPM_CHIP_FLAG_TPM2)
     -			tpm2_shutdown(chip, TPM2_SU_STATE);
    --		} else {
    +-		else
     -			rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
    --		}
     -
     -		tpm_put_ops(chip);
     +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
    -+		tpm2_end_auth_session(chip);
     +		tpm2_shutdown(chip, TPM2_SU_STATE);
     +		goto suspended;
      	}
---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-6.6.y        |  Success    |  Success   |

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-12-05 14:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-05  2:26 [PATCH 6.6] tpm: Lock TPM chip in tpm_pm_suspend() first bin.lan.cn
2024-12-05 13:34 ` Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox