tpm: Replace WARN_ONCE() with dev_err_once() in tpm_tis_status()
authorJarkko Sakkinen <jarkko@kernel.org>
Wed, 9 Jun 2021 13:26:19 +0000 (16:26 +0300)
committerJarkko Sakkinen <jarkko@kernel.org>
Wed, 23 Jun 2021 13:51:04 +0000 (16:51 +0300)
Do not tear down the system when getting invalid status from a TPM chip.
This can happen when panic-on-warn is used.

Instead, introduce TPM_TIS_INVALID_STATUS bitflag and use it to trigger
once the error reporting per chip. In addition, print out the value of
TPM_STS for improved forensics.

Link: https://lore.kernel.org/keyrings/YKzlTR1AzUigShtZ@kroah.com/
Fixes: 55707d531af6 ("tpm_tis: Add a check for invalid status")
Cc: stable@vger.kernel.org
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_core.h

index 55b9d39..69579ef 100644 (file)
@@ -196,13 +196,24 @@ static u8 tpm_tis_status(struct tpm_chip *chip)
                return 0;
 
        if (unlikely((status & TPM_STS_READ_ZERO) != 0)) {
-               /*
-                * If this trips, the chances are the read is
-                * returning 0xff because the locality hasn't been
-                * acquired.  Usually because tpm_try_get_ops() hasn't
-                * been called before doing a TPM operation.
-                */
-               WARN_ONCE(1, "TPM returned invalid status\n");
+               if  (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) {
+                       /*
+                        * If this trips, the chances are the read is
+                        * returning 0xff because the locality hasn't been
+                        * acquired.  Usually because tpm_try_get_ops() hasn't
+                        * been called before doing a TPM operation.
+                        */
+                       dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n",
+                               status);
+
+                       /*
+                        * Dump stack for forensics, as invalid TPM_STS.x could be
+                        * potentially triggered by impaired tpm_try_get_ops() or
+                        * tpm_find_get_ops().
+                        */
+                       dump_stack();
+               }
+
                return 0;
        }
 
index 9b2d32a..b2a3c6c 100644 (file)
@@ -83,6 +83,7 @@ enum tis_defaults {
 
 enum tpm_tis_flags {
        TPM_TIS_ITPM_WORKAROUND         = BIT(0),
+       TPM_TIS_INVALID_STATUS          = BIT(1),
 };
 
 struct tpm_tis_data {
@@ -90,7 +91,7 @@ struct tpm_tis_data {
        int locality;
        int irq;
        bool irq_tested;
-       unsigned int flags;
+       unsigned long flags;
        void __iomem *ilb_base_addr;
        u16 clkrun_enabled;
        wait_queue_head_t int_queue;