Skip to content

Commit cfaf835

Browse files
jarkkojsgregkh
authored andcommitted
tpm: Lock TPM chip in tpm_pm_suspend() first
commit 9265fed upstream. 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: 99d4645 ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 135b481 commit cfaf835

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed

drivers/char/tpm/tpm-chip.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,6 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
519519
{
520520
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
521521

522-
/* Give back zero bytes, as TPM chip has not yet fully resumed: */
523-
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
524-
return 0;
525-
526522
return tpm_get_random(chip, data, max);
527523
}
528524

drivers/char/tpm/tpm-interface.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -394,26 +394,32 @@ int tpm_pm_suspend(struct device *dev)
394394
if (!chip)
395395
return -ENODEV;
396396

397+
rc = tpm_try_get_ops(chip);
398+
if (rc) {
399+
/* Can be safely set out of locks, as no action cannot race: */
400+
chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
401+
goto out;
402+
}
403+
397404
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
398405
goto suspended;
399406

400407
if ((chip->flags & TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED) &&
401408
!pm_suspend_via_firmware())
402409
goto suspended;
403410

404-
rc = tpm_try_get_ops(chip);
405-
if (!rc) {
406-
if (chip->flags & TPM_CHIP_FLAG_TPM2)
407-
tpm2_shutdown(chip, TPM2_SU_STATE);
408-
else
409-
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
410-
411-
tpm_put_ops(chip);
411+
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
412+
tpm2_shutdown(chip, TPM2_SU_STATE);
413+
goto suspended;
412414
}
413415

416+
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
417+
414418
suspended:
415419
chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
420+
tpm_put_ops(chip);
416421

422+
out:
417423
if (rc)
418424
dev_err(dev, "Ignoring error %d while suspending\n", rc);
419425
return 0;
@@ -462,11 +468,18 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
462468
if (!chip)
463469
return -ENODEV;
464470

471+
/* Give back zero bytes, as TPM chip has not yet fully resumed: */
472+
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
473+
rc = 0;
474+
goto out;
475+
}
476+
465477
if (chip->flags & TPM_CHIP_FLAG_TPM2)
466478
rc = tpm2_get_random(chip, out, max);
467479
else
468480
rc = tpm1_get_random(chip, out, max);
469481

482+
out:
470483
tpm_put_ops(chip);
471484
return rc;
472485
}

0 commit comments

Comments
 (0)