aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 16:20:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 16:20:42 -0500
commit1d9e71404e2c3f37387991534983dcb2ab05660d (patch)
treedaddf50cdd0cbf0727bf83e33caf1839c988389e /drivers/char
parentcc4f9c2a91b7be7b3590bb1cbe8148873556aa3f (diff)
parent0d309cbddb49d4d948b3e9fe8423e80b3b64486b (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem fixes from James Morris. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: Don't leak a key reference if request_key() tries to use a revoked keyring Added Little Endian support to vtpm module tpm, tpm_tis: fix TPM 2.0 probing tpm: fix suspend/resume paths for TPM 2.0 Smack: secmark connections
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm-interface.c6
-rw-r--r--drivers/char/tpm/tpm.h5
-rw-r--r--drivers/char/tpm/tpm2-cmd.c59
-rw-r--r--drivers/char/tpm/tpm_crb.c20
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c20
-rw-r--r--drivers/char/tpm/tpm_tis.c37
6 files changed, 85 insertions, 62 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index bf53a3771da5..e85d3416d899 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -901,8 +901,10 @@ int tpm_pm_suspend(struct device *dev)
901 if (chip == NULL) 901 if (chip == NULL)
902 return -ENODEV; 902 return -ENODEV;
903 903
904 if (chip->flags & TPM_CHIP_FLAG_TPM2) 904 if (chip->flags & TPM_CHIP_FLAG_TPM2) {
905 return tpm2_shutdown(chip, TPM2_SU_CLEAR); 905 tpm2_shutdown(chip, TPM2_SU_STATE);
906 return 0;
907 }
906 908
907 /* for buggy tpm, flush pcrs with extend to selected dummy */ 909 /* for buggy tpm, flush pcrs with extend to selected dummy */
908 if (tpm_suspend_pcr) { 910 if (tpm_suspend_pcr) {
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 7b0727c5e803..f8319a0860fd 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -432,7 +432,8 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
432 u32 *value, const char *desc); 432 u32 *value, const char *desc);
433 433
434extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); 434extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
435extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); 435extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
436extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); 436extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
437extern int tpm2_do_selftest(struct tpm_chip *chip); 437extern int tpm2_do_selftest(struct tpm_chip *chip);
438extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); 438extern int tpm2_gen_interrupt(struct tpm_chip *chip);
439extern int tpm2_probe(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 1abe6502219f..011909a9be96 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -456,20 +456,23 @@ static const struct tpm_input_header tpm2_shutdown_header = {
456 * @chip: TPM chip to use. 456 * @chip: TPM chip to use.
457 * @shutdown_type shutdown type. The value is either 457 * @shutdown_type shutdown type. The value is either
458 * TPM_SU_CLEAR or TPM_SU_STATE. 458 * TPM_SU_CLEAR or TPM_SU_STATE.
459 *
460 * 0 is returned when the operation is successful. If a negative number is
461 * returned it remarks a POSIX error code. If a positive number is returned
462 * it remarks a TPM error.
463 */ 459 */
464int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) 460void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
465{ 461{
466 struct tpm2_cmd cmd; 462 struct tpm2_cmd cmd;
463 int rc;
467 464
468 cmd.header.in = tpm2_shutdown_header; 465 cmd.header.in = tpm2_shutdown_header;
469
470 cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); 466 cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
471 return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 467
472 "stopping the TPM"); 468 rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
469
470 /* In places where shutdown command is sent there's no much we can do
471 * except print the error code on a system failure.
472 */
473 if (rc < 0)
474 dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
475 rc);
473} 476}
474EXPORT_SYMBOL_GPL(tpm2_shutdown); 477EXPORT_SYMBOL_GPL(tpm2_shutdown);
475 478
@@ -598,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest);
598/** 601/**
599 * tpm2_gen_interrupt() - generate an interrupt 602 * tpm2_gen_interrupt() - generate an interrupt
600 * @chip: TPM chip to use 603 * @chip: TPM chip to use
601 * @quiet: surpress the error message
602 * 604 *
603 * 0 is returned when the operation is successful. If a negative number is 605 * 0 is returned when the operation is successful. If a negative number is
604 * returned it remarks a POSIX error code. If a positive number is returned 606 * returned it remarks a POSIX error code. If a positive number is returned
605 * it remarks a TPM error. 607 * it remarks a TPM error.
606 */ 608 */
607int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) 609int tpm2_gen_interrupt(struct tpm_chip *chip)
608{ 610{
609 const char *desc = NULL;
610 u32 dummy; 611 u32 dummy;
611 612
612 if (!quiet) 613 return tpm2_get_tpm_pt(chip, 0x100, &dummy,
613 desc = "attempting to generate an interrupt"; 614 "attempting to generate an interrupt");
614
615 return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc);
616} 615}
617EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); 616EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
617
618/**
619 * tpm2_probe() - probe TPM 2.0
620 * @chip: TPM chip to use
621 *
622 * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
623 * the reply tag.
624 */
625int tpm2_probe(struct tpm_chip *chip)
626{
627 struct tpm2_cmd cmd;
628 int rc;
629
630 cmd.header.in = tpm2_get_tpm_pt_header;
631 cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
632 cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
633 cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
634
635 rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
636 if (rc < 0)
637 return rc;
638 else if (rc < TPM_HEADER_SIZE)
639 return -EFAULT;
640
641 if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
642 chip->flags |= TPM_CHIP_FLAG_TPM2;
643
644 return 0;
645}
646EXPORT_SYMBOL_GPL(tpm2_probe);
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 3dd23cfae4fe..b26ceee3585e 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -95,21 +95,7 @@ struct crb_priv {
95 u8 __iomem *rsp; 95 u8 __iomem *rsp;
96}; 96};
97 97
98#ifdef CONFIG_PM_SLEEP 98static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
99static int crb_resume(struct device *dev)
100{
101 int rc;
102 struct tpm_chip *chip = dev_get_drvdata(dev);
103
104 rc = tpm2_shutdown(chip, TPM2_SU_STATE);
105 if (!rc)
106 rc = tpm2_do_selftest(chip);
107
108 return rc;
109}
110#endif
111
112static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume);
113 99
114static u8 crb_status(struct tpm_chip *chip) 100static u8 crb_status(struct tpm_chip *chip)
115{ 101{
@@ -326,6 +312,10 @@ static int crb_acpi_remove(struct acpi_device *device)
326 struct tpm_chip *chip = dev_get_drvdata(dev); 312 struct tpm_chip *chip = dev_get_drvdata(dev);
327 313
328 tpm_chip_unregister(chip); 314 tpm_chip_unregister(chip);
315
316 if (chip->flags & TPM_CHIP_FLAG_TPM2)
317 tpm2_shutdown(chip, TPM2_SU_CLEAR);
318
329 return 0; 319 return 0;
330} 320}
331 321
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 0840347e251c..b1e53e3aece5 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
148 crq.len = (u16)count; 148 crq.len = (u16)count;
149 crq.data = ibmvtpm->rtce_dma_handle; 149 crq.data = ibmvtpm->rtce_dma_handle;
150 150
151 rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); 151 rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
152 cpu_to_be64(word[1]));
152 if (rc != H_SUCCESS) { 153 if (rc != H_SUCCESS) {
153 dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); 154 dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
154 rc = 0; 155 rc = 0;
@@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
186 crq.valid = (u8)IBMVTPM_VALID_CMD; 187 crq.valid = (u8)IBMVTPM_VALID_CMD;
187 crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; 188 crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
188 189
189 rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); 190 rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
191 cpu_to_be64(buf[1]));
190 if (rc != H_SUCCESS) 192 if (rc != H_SUCCESS)
191 dev_err(ibmvtpm->dev, 193 dev_err(ibmvtpm->dev,
192 "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); 194 "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
@@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
212 crq.valid = (u8)IBMVTPM_VALID_CMD; 214 crq.valid = (u8)IBMVTPM_VALID_CMD;
213 crq.msg = (u8)VTPM_GET_VERSION; 215 crq.msg = (u8)VTPM_GET_VERSION;
214 216
215 rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); 217 rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
218 cpu_to_be64(buf[1]));
216 if (rc != H_SUCCESS) 219 if (rc != H_SUCCESS)
217 dev_err(ibmvtpm->dev, 220 dev_err(ibmvtpm->dev,
218 "ibmvtpm_crq_get_version failed rc=%d\n", rc); 221 "ibmvtpm_crq_get_version failed rc=%d\n", rc);
@@ -336,7 +339,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
336 crq.valid = (u8)IBMVTPM_VALID_CMD; 339 crq.valid = (u8)IBMVTPM_VALID_CMD;
337 crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; 340 crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
338 341
339 rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); 342 rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
343 cpu_to_be64(buf[1]));
340 if (rc != H_SUCCESS) 344 if (rc != H_SUCCESS)
341 dev_err(ibmvtpm->dev, 345 dev_err(ibmvtpm->dev,
342 "tpm_ibmvtpm_suspend failed rc=%d\n", rc); 346 "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
@@ -481,11 +485,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
481 case IBMVTPM_VALID_CMD: 485 case IBMVTPM_VALID_CMD:
482 switch (crq->msg) { 486 switch (crq->msg) {
483 case VTPM_GET_RTCE_BUFFER_SIZE_RES: 487 case VTPM_GET_RTCE_BUFFER_SIZE_RES:
484 if (crq->len <= 0) { 488 if (be16_to_cpu(crq->len) <= 0) {
485 dev_err(ibmvtpm->dev, "Invalid rtce size\n"); 489 dev_err(ibmvtpm->dev, "Invalid rtce size\n");
486 return; 490 return;
487 } 491 }
488 ibmvtpm->rtce_size = crq->len; 492 ibmvtpm->rtce_size = be16_to_cpu(crq->len);
489 ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, 493 ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
490 GFP_KERNEL); 494 GFP_KERNEL);
491 if (!ibmvtpm->rtce_buf) { 495 if (!ibmvtpm->rtce_buf) {
@@ -506,11 +510,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
506 510
507 return; 511 return;
508 case VTPM_GET_VERSION_RES: 512 case VTPM_GET_VERSION_RES:
509 ibmvtpm->vtpm_version = crq->data; 513 ibmvtpm->vtpm_version = be32_to_cpu(crq->data);
510 return; 514 return;
511 case VTPM_TPM_COMMAND_RES: 515 case VTPM_TPM_COMMAND_RES:
512 /* len of the data in rtce buffer */ 516 /* len of the data in rtce buffer */
513 ibmvtpm->res_len = crq->len; 517 ibmvtpm->res_len = be16_to_cpu(crq->len);
514 wake_up_interruptible(&ibmvtpm->wq); 518 wake_up_interruptible(&ibmvtpm->wq);
515 return; 519 return;
516 default: 520 default:
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 6725bef7cb96..f2dffa770b8e 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -588,6 +588,9 @@ MODULE_PARM_DESC(interrupts, "Enable interrupts");
588 588
589static void tpm_tis_remove(struct tpm_chip *chip) 589static void tpm_tis_remove(struct tpm_chip *chip)
590{ 590{
591 if (chip->flags & TPM_CHIP_FLAG_TPM2)
592 tpm2_shutdown(chip, TPM2_SU_CLEAR);
593
591 iowrite32(~TPM_GLOBAL_INT_ENABLE & 594 iowrite32(~TPM_GLOBAL_INT_ENABLE &
592 ioread32(chip->vendor.iobase + 595 ioread32(chip->vendor.iobase +
593 TPM_INT_ENABLE(chip->vendor. 596 TPM_INT_ENABLE(chip->vendor.
@@ -639,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
639 goto out_err; 642 goto out_err;
640 } 643 }
641 644
642 /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. 645 rc = tpm2_probe(chip);
643 * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. 646 if (rc)
644 */ 647 goto out_err;
645 rc = tpm2_gen_interrupt(chip, true);
646 if (rc == 0 || rc == TPM2_RC_INITIALIZE)
647 chip->flags |= TPM_CHIP_FLAG_TPM2;
648 648
649 vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); 649 vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
650 chip->vendor.manufacturer_id = vendor; 650 chip->vendor.manufacturer_id = vendor;
@@ -747,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
747 747
748 /* Generate Interrupts */ 748 /* Generate Interrupts */
749 if (chip->flags & TPM_CHIP_FLAG_TPM2) 749 if (chip->flags & TPM_CHIP_FLAG_TPM2)
750 tpm2_gen_interrupt(chip, false); 750 tpm2_gen_interrupt(chip);
751 else 751 else
752 tpm_gen_interrupt(chip); 752 tpm_gen_interrupt(chip);
753 753
@@ -865,25 +865,22 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
865static int tpm_tis_resume(struct device *dev) 865static int tpm_tis_resume(struct device *dev)
866{ 866{
867 struct tpm_chip *chip = dev_get_drvdata(dev); 867 struct tpm_chip *chip = dev_get_drvdata(dev);
868 int ret = 0; 868 int ret;
869 869
870 if (chip->vendor.irq) 870 if (chip->vendor.irq)
871 tpm_tis_reenable_interrupts(chip); 871 tpm_tis_reenable_interrupts(chip);
872 872
873 if (chip->flags & TPM_CHIP_FLAG_TPM2) { 873 ret = tpm_pm_resume(dev);
874 /* NOP if firmware properly does this. */ 874 if (ret)
875 tpm2_startup(chip, TPM2_SU_STATE); 875 return ret;
876 876
877 ret = tpm2_shutdown(chip, TPM2_SU_STATE); 877 /* TPM 1.2 requires self-test on resume. This function actually returns
878 if (!ret) 878 * an error code but for unknown reason it isn't handled.
879 ret = tpm2_do_selftest(chip); 879 */
880 } else { 880 if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
881 ret = tpm_pm_resume(dev); 881 tpm_do_selftest(chip);
882 if (!ret)
883 tpm_do_selftest(chip);
884 }
885 882
886 return ret; 883 return 0;
887} 884}
888#endif 885#endif
889 886