Re: [PATCH] tpm: Disable RNG for all AMD fTPMs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed Aug 2, 2023 at 12:18 AM EEST, Mario Limonciello wrote:
> The TPM RNG functionality is not necessary for entropy when the CPU
> already supports the RDRAND instruction. The TPM RNG functionality
> was previously disabled on a subset of AMD fTPM series, but reports
> continue to show problems on some systems causing stutter root caused
> to TPM RNG functionality.
>
> Expand disabling TPM RNG use for all AMD fTPMs whether they have versions
> that claim to have fixed or not. To accomplish this, move the detection
> into part of the TPM CRB registration and add a flag indicating that
> the TPM should opt-out of registration to hwrng.
>
> Cc: stable@xxxxxxxxxxxxxxx # 6.1.y+
> Fixes: b006c439d58d ("hwrng: core - start hwrng kthread also for untrusted sources")
> Fixes: f1324bbc4011 ("tpm: disable hwrng for fTPM on some AMD designs")
> Reported-by: daniil.stas@xxxxxxxxxx
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217719
> Reported-by: bitlord0xff@xxxxxxxxx
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217212
> Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
> ---
>  drivers/char/tpm/tpm-chip.c | 80 +++++++------------------------------
>  drivers/char/tpm/tpm_crb.c  | 23 +++++++++++
>  include/linux/tpm.h         |  7 ++++
>  3 files changed, 44 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index cf5499e51999b..3154a5ef2611f 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -89,6 +89,14 @@ static void tpm_clk_disable(struct tpm_chip *chip)
>  		chip->ops->clk_enable(chip, false);
>  }
>  
> +static int tpm_check_flags(struct tpm_chip *chip)
> +{
> +	if (!chip->ops->check_flags)
> +		return 0;
> +
> +	return chip->ops->check_flags(chip);
> +}

Instead of adding a new callback, you should probably do the following
in crb_acpi_add(), and get a much less complicated fix:

1. Call tpm_chip_bootstrap() (see tpm_tis_core_init()).
2. Set TPM_CHIP_FLAG_HWRNG_DISABLED if the conditions have been met.
3. Call tpm_chip_register().

> +
>  /**
>   * tpm_chip_start() - power on the TPM
>   * @chip:	a TPM chip to use
> @@ -510,70 +518,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
>  	return 0;
>  }
>  
> -/*
> - * Some AMD fTPM versions may cause stutter
> - * https://www.amd.com/en/support/kb/faq/pa-410
> - *
> - * Fixes are available in two series of fTPM firmware:
> - * 6.x.y.z series: 6.0.18.6 +
> - * 3.x.y.z series: 3.57.y.5 +
> - */
> -#ifdef CONFIG_X86
> -static bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
> -{
> -	u32 val1, val2;
> -	u64 version;
> -	int ret;
> -
> -	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
> -		return false;
> -
> -	ret = tpm_request_locality(chip);
> -	if (ret)
> -		return false;
> -
> -	ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL);
> -	if (ret)
> -		goto release;
> -	if (val1 != 0x414D4400U /* AMD */) {
> -		ret = -ENODEV;
> -		goto release;
> -	}
> -	ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL);
> -	if (ret)
> -		goto release;
> -	ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL);
> -
> -release:
> -	tpm_relinquish_locality(chip);
> -
> -	if (ret)
> -		return false;
> -
> -	version = ((u64)val1 << 32) | val2;
> -	if ((version >> 48) == 6) {
> -		if (version >= 0x0006000000180006ULL)
> -			return false;
> -	} else if ((version >> 48) == 3) {
> -		if (version >= 0x0003005700000005ULL)
> -			return false;
> -	} else {
> -		return false;
> -	}
> -
> -	dev_warn(&chip->dev,
> -		 "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n",
> -		 version);
> -
> -	return true;
> -}
> -#else
> -static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip)
> -{
> -	return false;
> -}
> -#endif /* CONFIG_X86 */
> -
>  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);
> @@ -588,7 +532,7 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>  static int tpm_add_hwrng(struct tpm_chip *chip)
>  {
>  	if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) ||
> -	    tpm_amd_is_rng_defective(chip))
> +	    tpm_is_rng_disabled(chip))
>  		return 0;
>  
>  	snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
> @@ -670,6 +614,10 @@ int tpm_chip_register(struct tpm_chip *chip)
>  	if (rc)
>  		return rc;
>  
> +	rc = tpm_check_flags(chip);
> +	if (rc)
> +		return rc;
> +
>  	tpm_sysfs_add_device(chip);
>  
>  	tpm_bios_log_setup(chip);
> @@ -719,7 +667,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
>  {
>  	tpm_del_legacy_sysfs(chip);
>  	if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) &&
> -	    !tpm_amd_is_rng_defective(chip))
> +	    !tpm_is_rng_disabled(chip))
>  		hwrng_unregister(&chip->hwrng);
>  	tpm_bios_log_teardown(chip);
>  	if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
> diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
> index 1a5d09b185134..5614b68ef1905 100644
> --- a/drivers/char/tpm/tpm_crb.c
> +++ b/drivers/char/tpm/tpm_crb.c
> @@ -463,6 +463,28 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
>  	return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
>  }
>  
> +static int crb_check_flags(struct tpm_chip *chip)
> +{
> +	u32 val;
> +	int ret;
> +
> +	ret = crb_request_locality(chip, 0);
> +	if (ret)
> +		return ret;
> +
> +	ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL);
> +	if (ret)
> +		goto release;
> +
> +	if (val == 0x414D4400U /* AMD */)
> +		chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED;
> +
> +release:
> +	crb_relinquish_locality(chip, 0);
> +
> +	return ret;
> +}
> +
>  static const struct tpm_class_ops tpm_crb = {
>  	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = crb_status,
> @@ -476,6 +498,7 @@ static const struct tpm_class_ops tpm_crb = {
>  	.relinquish_locality = crb_relinquish_locality,
>  	.req_complete_mask = CRB_DRV_STS_COMPLETE,
>  	.req_complete_val = CRB_DRV_STS_COMPLETE,
> +	.check_flags = crb_check_flags,
>  };
>  
>  static int crb_check_resource(struct acpi_resource *ares, void *data)
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 6a1e8f1572551..aeb84944b0ca4 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -82,6 +82,7 @@ struct tpm_class_ops {
>  	int (*request_locality)(struct tpm_chip *chip, int loc);
>  	int (*relinquish_locality)(struct tpm_chip *chip, int loc);
>  	void (*clk_enable)(struct tpm_chip *chip, bool value);
> +	int (*check_flags)(struct tpm_chip *chip);
>  };
>  
>  #define TPM_NUM_EVENT_LOG_FILES		3
> @@ -283,6 +284,7 @@ enum tpm_chip_flags {
>  	TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED	= BIT(6),
>  	TPM_CHIP_FLAG_FIRMWARE_UPGRADE		= BIT(7),
>  	TPM_CHIP_FLAG_SUSPENDED			= BIT(8),
> +	TPM_CHIP_FLAG_HWRNG_DISABLED		= BIT(9),
>  };
>  
>  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
> @@ -417,6 +419,11 @@ static inline u32 tpm2_rc_value(u32 rc)
>  	return (rc & BIT(7)) ? rc & 0xff : rc;
>  }
>  
> +static inline bool tpm_is_rng_disabled(struct tpm_chip *chip)
> +{
> +	return chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED;
> +}

Please open code to the call sites.

Wrapping a flag check is not very useful and makes the bug fix
only more complex.

> +
>  #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
>  
>  extern int tpm_is_tpm2(struct tpm_chip *chip);
> -- 
> 2.34.1

BR, Jarkko




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux