diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 16:20:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 16:20:42 -0500 |
commit | 1d9e71404e2c3f37387991534983dcb2ab05660d (patch) | |
tree | daddf50cdd0cbf0727bf83e33caf1839c988389e /drivers/char | |
parent | cc4f9c2a91b7be7b3590bb1cbe8148873556aa3f (diff) | |
parent | 0d309cbddb49d4d948b3e9fe8423e80b3b64486b (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.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 59 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 20 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 20 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 37 |
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 | ||
434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); | 434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); |
435 | extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); | 435 | extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); |
436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); | 436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); |
437 | extern int tpm2_do_selftest(struct tpm_chip *chip); | 437 | extern int tpm2_do_selftest(struct tpm_chip *chip); |
438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); | 438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip); |
439 | extern 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 | */ |
464 | int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | 460 | void 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 | } |
474 | EXPORT_SYMBOL_GPL(tpm2_shutdown); | 477 | EXPORT_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 | */ |
607 | int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) | 609 | int 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 | } |
617 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); | 616 | EXPORT_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 | */ | ||
625 | int 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 | } | ||
646 | EXPORT_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 | 98 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); |
99 | static 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 | |||
112 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume); | ||
113 | 99 | ||
114 | static u8 crb_status(struct tpm_chip *chip) | 100 | static 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 | ||
589 | static void tpm_tis_remove(struct tpm_chip *chip) | 589 | static 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) | |||
865 | static int tpm_tis_resume(struct device *dev) | 865 | static 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 | ||