From 2aef9da60bfdeb68dbcd4f114c098cbaa841b4ee Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 5 Nov 2015 17:19:09 +0100 Subject: tpm_tis: free irq after probing Release IRQs used for probing only. Otherwise the TPM will end up with all IRQs 3-15 assigned. Fixes: afb5abc262e9 ("tpm: two-phase chip management functions") Signed-off-by: Martin Wilck Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 696ef1d56b4f..19f9c7dc7bc0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -805,6 +805,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, iowrite32(intmask, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); + + devm_free_irq(dev, i, chip); } } if (chip->vendor.irq) { -- cgit v1.2.3 From 14b5c1c9159bf6f109b667d31da82859d8c8cdcd Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 9 Nov 2015 16:38:50 +0200 Subject: tpm_tis: restore IRQ vector in IO memory after failed probing If the probing finishes without success, it will leave the value 15 in the TPM_IRQ_VECTOR register. If the driver is unloaded and reloaded, it will "think" that the hardware had been programmed with IRQ 15, and will not probe again. This patch restores the original value in the IO memory if no IRQ is probed. Signed-off-by: Martin Wilck Acked-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 19f9c7dc7bc0..65f7eecc45b0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -645,6 +645,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, { u32 vendor, intfcaps, intmask; int rc, i, irq_s, irq_e, probe; + int irq_r = -1; struct tpm_chip *chip; struct priv_data *priv; @@ -751,6 +752,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, irq_s = ioread8(chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); + irq_r = irq_s; if (irq_s) { irq_e = irq_s; } else { @@ -833,7 +835,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); } - } + } else if (irq_r != -1) + iowrite8(irq_r, chip->vendor.iobase + + TPM_INT_VECTOR(chip->vendor.locality)); if (chip->flags & TPM_CHIP_FLAG_TPM2) { chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); -- cgit v1.2.3 From eb8ed1eb9a158c460d10205eaff71fd4ac67c160 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 22 Oct 2015 22:32:41 +0200 Subject: TPM: Avoid reference to potentially freed memory Reference to the 'np' node is dropped before dereferencing the 'sizep' and 'basep' pointers, which could by then point to junk if the node has been freed. Refactor code to call 'of_node_put' later. Fixes: c5df39262dd5 ("drivers/char/tpm: Add securityfs support for event log") Signed-off-by: Christophe JAILLET Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm_of.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c index 1141456a4b1f..570f30c5c5f4 100644 --- a/drivers/char/tpm/tpm_of.c +++ b/drivers/char/tpm/tpm_of.c @@ -53,17 +53,18 @@ int read_log(struct tpm_bios_log *log) goto cleanup_eio; } - of_node_put(np); log->bios_event_log = kmalloc(*sizep, GFP_KERNEL); if (!log->bios_event_log) { pr_err("%s: ERROR - Not enough memory for BIOS measurements\n", __func__); + of_node_put(np); return -ENOMEM; } log->bios_event_log_end = log->bios_event_log + *sizep; memcpy(log->bios_event_log, __va(*basep), *sizep); + of_node_put(np); return 0; -- cgit v1.2.3 From b1a4144a695ff4a6834a2680600f36f991fa4926 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Mon, 2 Nov 2015 19:55:29 +0200 Subject: TPM: revert the list handling logic fixed in 398a1e7 Mimi reported that afb5abc reverts the fix in 398a1e7. This patch reverts it back. Fixes: afb5abc262e9 ("tpm: two-phase chip management functions") Reported-by: Mimi Zohar Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm-chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index f26b0ae23bea..a5cdce74adab 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -236,7 +236,7 @@ int tpm_chip_register(struct tpm_chip *chip) /* Make the chip available. */ spin_lock(&driver_lock); - list_add_rcu(&chip->list, &tpm_chip_list); + list_add_tail_rcu(&chip->list, &tpm_chip_list); spin_unlock(&driver_lock); chip->flags |= TPM_CHIP_FLAG_REGISTERED; -- cgit v1.2.3 From 2e31125c241212e2407d61a2d1cbdad0055a30b0 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 30 Oct 2015 14:57:02 +0200 Subject: tpm: fix missing migratable flag in sealing functionality for TPM2 The 'migratable' flag was not added to the key payload. This patch fixes the problem. Fixes: 0fe5480303a1 ("keys, trusted: seal/unseal with TPM 2.0 chips") Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm2-cmd.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index bd7039fafa8a..c12130485fc1 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -443,12 +443,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip, TPM_DIGEST_SIZE); /* sensitive */ - tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len); + tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1); tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); - tpm_buf_append_u16(&buf, payload->key_len); + tpm_buf_append_u16(&buf, payload->key_len + 1); tpm_buf_append(&buf, payload->key, payload->key_len); + tpm_buf_append_u8(&buf, payload->migratable); /* public */ tpm_buf_append_u16(&buf, 14); @@ -573,6 +574,8 @@ static int tpm2_unseal(struct tpm_chip *chip, u32 blob_handle) { struct tpm_buf buf; + u16 data_len; + u8 *data; int rc; rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); @@ -591,11 +594,13 @@ static int tpm2_unseal(struct tpm_chip *chip, rc = -EPERM; if (!rc) { - payload->key_len = be16_to_cpup( + data_len = be16_to_cpup( (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); + data = &buf.data[TPM_HEADER_SIZE + 6]; - memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6], - payload->key_len); + memcpy(payload->key, data, data_len - 1); + payload->key_len = data_len - 1; + payload->migratable = data[data_len - 1]; } tpm_buf_destroy(&buf); -- cgit v1.2.3 From d56e4f75346933dd2cb11533a668ce883908c859 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Sat, 7 Nov 2015 13:33:25 +0200 Subject: tpm: fix compat 'ppi' link handling in tpm_chip_register() __compat_only_sysfs_link_entry_to_kobj() was unconditionally called for TPM1 chips, which caused crash on Acer C720 laptop where DSM for the ACPI object did not exist. There are two reasons for unwanted behavior: * The code did not check whether __compat_only_sysfs_link_entry_to_kobj() returned -ENOENT. This is OK. It just meanst that ppi is not available. * The code did not clean up properly. Compat link should added only after all other init is done. This patch sorts out these issues. Fixes: 9b774d5cf2db Reported-by: Jeremiah Mahler Signed-off-by: Jarkko Sakkinen Tested-by: Jeremiah Mahler Acked-by: Peter Huewe --- drivers/char/tpm/tpm-chip.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index a5cdce74adab..45cc39aabeee 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -226,14 +226,6 @@ int tpm_chip_register(struct tpm_chip *chip) if (rc) goto out_err; - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { - rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj, - &chip->dev.kobj, - "ppi"); - if (rc) - goto out_err; - } - /* Make the chip available. */ spin_lock(&driver_lock); list_add_tail_rcu(&chip->list, &tpm_chip_list); @@ -241,6 +233,16 @@ int tpm_chip_register(struct tpm_chip *chip) chip->flags |= TPM_CHIP_FLAG_REGISTERED; + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { + rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj, + &chip->dev.kobj, + "ppi"); + if (rc && rc != -ENOENT) { + tpm_chip_unregister(chip); + return rc; + } + } + return 0; out_err: tpm1_chip_unregister(chip); -- cgit v1.2.3