Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'tpmdd-next-6.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd

Pull tpm fix from Jarkko Sakkinen:
"Fix a race condition between tpm_pm_suspend() and tpm_hwrng_read() (I
think for good now)"

* tag 'tpmdd-next-6.12-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
tpm: Lock TPM chip in tpm_pm_suspend() first

+22 -14
-4
drivers/char/tpm/tpm-chip.c
··· 525 525 { 526 526 struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); 527 527 528 - /* Give back zero bytes, as TPM chip has not yet fully resumed: */ 529 - if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) 530 - return 0; 531 - 532 528 return tpm_get_random(chip, data, max); 533 529 } 534 530
+22 -10
drivers/char/tpm/tpm-interface.c
··· 370 370 if (!chip) 371 371 return -ENODEV; 372 372 373 + rc = tpm_try_get_ops(chip); 374 + if (rc) { 375 + /* Can be safely set out of locks, as no action cannot race: */ 376 + chip->flags |= TPM_CHIP_FLAG_SUSPENDED; 377 + goto out; 378 + } 379 + 373 380 if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) 374 381 goto suspended; 375 382 ··· 384 377 !pm_suspend_via_firmware()) 385 378 goto suspended; 386 379 387 - rc = tpm_try_get_ops(chip); 388 - if (!rc) { 389 - if (chip->flags & TPM_CHIP_FLAG_TPM2) { 390 - tpm2_end_auth_session(chip); 391 - tpm2_shutdown(chip, TPM2_SU_STATE); 392 - } else { 393 - rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); 394 - } 395 - 396 - tpm_put_ops(chip); 380 + if (chip->flags & TPM_CHIP_FLAG_TPM2) { 381 + tpm2_end_auth_session(chip); 382 + tpm2_shutdown(chip, TPM2_SU_STATE); 383 + goto suspended; 397 384 } 385 + 386 + rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); 398 387 399 388 suspended: 400 389 chip->flags |= TPM_CHIP_FLAG_SUSPENDED; 390 + tpm_put_ops(chip); 401 391 392 + out: 402 393 if (rc) 403 394 dev_err(dev, "Ignoring error %d while suspending\n", rc); 404 395 return 0; ··· 445 440 if (!chip) 446 441 return -ENODEV; 447 442 443 + /* Give back zero bytes, as TPM chip has not yet fully resumed: */ 444 + if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) { 445 + rc = 0; 446 + goto out; 447 + } 448 + 448 449 if (chip->flags & TPM_CHIP_FLAG_TPM2) 449 450 rc = tpm2_get_random(chip, out, max); 450 451 else 451 452 rc = tpm1_get_random(chip, out, max); 452 453 454 + out: 453 455 tpm_put_ops(chip); 454 456 return rc; 455 457 }