diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-07 20:06:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-07 20:06:28 -0400 |
commit | a7d4026834f8263a8a4eabeb753e3747988ef0d2 (patch) | |
tree | 5204ced6419a70d8539318fd20098e8e733f4213 | |
parent | 98ced886dd79a7028d203ed8adea8452bbfb47b6 (diff) | |
parent | a750cfde1397dbbee1efe7737c2e952d6fc2d878 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer fixes from James Morris:
"Bugfixes for TPM and SELinux"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
IB/core: Fix static analysis warning in ib_policy_change_task
IB/core: Fix uninitialized variable use in check_qp_port_pkey_settings
tpm: do not suspend/resume if power stays on
tpm: use tpm2_pcr_read() in tpm2_do_selftest()
tpm: use tpm_buf functions in tpm2_pcr_read()
tpm_tis: make ilb_base_addr static
tpm: consolidate the TPM startup code
tpm: Enable CLKRUN protocol for Braswell systems
tpm/tpm_crb: fix priv->cmd_size initialisation
tpm: fix a kernel memory leak in tpm-sysfs.c
tpm: Issue a TPM2_Shutdown for TPM2 devices.
Add "shutdown" to "struct class".
-rw-r--r-- | drivers/base/core.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 34 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 70 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 11 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 121 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_of.c | 3 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 113 | ||||
-rw-r--r-- | drivers/infiniband/core/device.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/core/security.c | 20 | ||||
-rw-r--r-- | include/linux/device.h | 2 |
12 files changed, 261 insertions, 133 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 8dde934f8d15..755451f684bc 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -2664,7 +2664,11 @@ void device_shutdown(void) | |||
2664 | pm_runtime_get_noresume(dev); | 2664 | pm_runtime_get_noresume(dev); |
2665 | pm_runtime_barrier(dev); | 2665 | pm_runtime_barrier(dev); |
2666 | 2666 | ||
2667 | if (dev->bus && dev->bus->shutdown) { | 2667 | if (dev->class && dev->class->shutdown) { |
2668 | if (initcall_debug) | ||
2669 | dev_info(dev, "shutdown\n"); | ||
2670 | dev->class->shutdown(dev); | ||
2671 | } else if (dev->bus && dev->bus->shutdown) { | ||
2668 | if (initcall_debug) | 2672 | if (initcall_debug) |
2669 | dev_info(dev, "shutdown\n"); | 2673 | dev_info(dev, "shutdown\n"); |
2670 | dev->bus->shutdown(dev); | 2674 | dev->bus->shutdown(dev); |
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 322b8a51ffc6..67ec9d3d04f5 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -143,6 +143,39 @@ static void tpm_devs_release(struct device *dev) | |||
143 | } | 143 | } |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * tpm_class_shutdown() - prepare the TPM device for loss of power. | ||
147 | * @dev: device to which the chip is associated. | ||
148 | * | ||
149 | * Issues a TPM2_Shutdown command prior to loss of power, as required by the | ||
150 | * TPM 2.0 spec. | ||
151 | * Then, calls bus- and device- specific shutdown code. | ||
152 | * | ||
153 | * XXX: This codepath relies on the fact that sysfs is not enabled for | ||
154 | * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2 | ||
155 | * has sysfs support enabled before TPM sysfs's implicit locking is fixed. | ||
156 | */ | ||
157 | static int tpm_class_shutdown(struct device *dev) | ||
158 | { | ||
159 | struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); | ||
160 | |||
161 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | ||
162 | down_write(&chip->ops_sem); | ||
163 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
164 | chip->ops = NULL; | ||
165 | up_write(&chip->ops_sem); | ||
166 | } | ||
167 | /* Allow bus- and device-specific code to run. Note: since chip->ops | ||
168 | * is NULL, more-specific shutdown code will not be able to issue TPM | ||
169 | * commands. | ||
170 | */ | ||
171 | if (dev->bus && dev->bus->shutdown) | ||
172 | dev->bus->shutdown(dev); | ||
173 | else if (dev->driver && dev->driver->shutdown) | ||
174 | dev->driver->shutdown(dev); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /** | ||
146 | * tpm_chip_alloc() - allocate a new struct tpm_chip instance | 179 | * tpm_chip_alloc() - allocate a new struct tpm_chip instance |
147 | * @pdev: device to which the chip is associated | 180 | * @pdev: device to which the chip is associated |
148 | * At this point pdev mst be initialized, but does not have to | 181 | * At this point pdev mst be initialized, but does not have to |
@@ -181,6 +214,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, | |||
181 | device_initialize(&chip->devs); | 214 | device_initialize(&chip->devs); |
182 | 215 | ||
183 | chip->dev.class = tpm_class; | 216 | chip->dev.class = tpm_class; |
217 | chip->dev.class->shutdown = tpm_class_shutdown; | ||
184 | chip->dev.release = tpm_dev_release; | 218 | chip->dev.release = tpm_dev_release; |
185 | chip->dev.parent = pdev; | 219 | chip->dev.parent = pdev; |
186 | chip->dev.groups = chip->groups; | 220 | chip->dev.groups = chip->groups; |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index d2b4df6d9894..fe597e6c55c4 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | |||
540 | } | 540 | } |
541 | EXPORT_SYMBOL_GPL(tpm_transmit_cmd); | 541 | EXPORT_SYMBOL_GPL(tpm_transmit_cmd); |
542 | 542 | ||
543 | #define TPM_ORD_STARTUP 153 | ||
544 | #define TPM_ST_CLEAR 1 | ||
545 | |||
546 | /** | ||
547 | * tpm_startup - turn on the TPM | ||
548 | * @chip: TPM chip to use | ||
549 | * | ||
550 | * Normally the firmware should start the TPM. This function is provided as a | ||
551 | * workaround if this does not happen. A legal case for this could be for | ||
552 | * example when a TPM emulator is used. | ||
553 | * | ||
554 | * Return: same as tpm_transmit_cmd() | ||
555 | */ | ||
556 | int tpm_startup(struct tpm_chip *chip) | ||
557 | { | ||
558 | struct tpm_buf buf; | ||
559 | int rc; | ||
560 | |||
561 | dev_info(&chip->dev, "starting up the TPM manually\n"); | ||
562 | |||
563 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | ||
564 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); | ||
565 | if (rc < 0) | ||
566 | return rc; | ||
567 | |||
568 | tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); | ||
569 | } else { | ||
570 | rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); | ||
571 | if (rc < 0) | ||
572 | return rc; | ||
573 | |||
574 | tpm_buf_append_u16(&buf, TPM_ST_CLEAR); | ||
575 | } | ||
576 | |||
577 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, | ||
578 | "attempting to start the TPM"); | ||
579 | |||
580 | tpm_buf_destroy(&buf); | ||
581 | return rc; | ||
582 | } | ||
583 | |||
543 | #define TPM_DIGEST_SIZE 20 | 584 | #define TPM_DIGEST_SIZE 20 |
544 | #define TPM_RET_CODE_IDX 6 | 585 | #define TPM_RET_CODE_IDX 6 |
545 | #define TPM_INTERNAL_RESULT_SIZE 200 | 586 | #define TPM_INTERNAL_RESULT_SIZE 200 |
@@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, | |||
586 | } | 627 | } |
587 | EXPORT_SYMBOL_GPL(tpm_getcap); | 628 | EXPORT_SYMBOL_GPL(tpm_getcap); |
588 | 629 | ||
589 | #define TPM_ORD_STARTUP 153 | ||
590 | #define TPM_ST_CLEAR cpu_to_be16(1) | ||
591 | #define TPM_ST_STATE cpu_to_be16(2) | ||
592 | #define TPM_ST_DEACTIVATED cpu_to_be16(3) | ||
593 | static const struct tpm_input_header tpm_startup_header = { | ||
594 | .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), | ||
595 | .length = cpu_to_be32(12), | ||
596 | .ordinal = cpu_to_be32(TPM_ORD_STARTUP) | ||
597 | }; | ||
598 | |||
599 | static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) | ||
600 | { | ||
601 | struct tpm_cmd_t start_cmd; | ||
602 | start_cmd.header.in = tpm_startup_header; | ||
603 | |||
604 | start_cmd.params.startup_in.startup_type = startup_type; | ||
605 | return tpm_transmit_cmd(chip, NULL, &start_cmd, | ||
606 | TPM_INTERNAL_RESULT_SIZE, 0, | ||
607 | 0, "attempting to start the TPM"); | ||
608 | } | ||
609 | |||
610 | int tpm_get_timeouts(struct tpm_chip *chip) | 630 | int tpm_get_timeouts(struct tpm_chip *chip) |
611 | { | 631 | { |
612 | cap_t cap; | 632 | cap_t cap; |
@@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
636 | rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, | 656 | rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, |
637 | sizeof(cap.timeout)); | 657 | sizeof(cap.timeout)); |
638 | if (rc == TPM_ERR_INVALID_POSTINIT) { | 658 | if (rc == TPM_ERR_INVALID_POSTINIT) { |
639 | /* The TPM is not started, we are the first to talk to it. | 659 | if (tpm_startup(chip)) |
640 | Execute a startup command. */ | ||
641 | dev_info(&chip->dev, "Issuing TPM_STARTUP\n"); | ||
642 | if (tpm_startup(chip, TPM_ST_CLEAR)) | ||
643 | return rc; | 660 | return rc; |
644 | 661 | ||
645 | rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, | 662 | rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, |
@@ -1102,6 +1119,9 @@ int tpm_pm_suspend(struct device *dev) | |||
1102 | if (chip == NULL) | 1119 | if (chip == NULL) |
1103 | return -ENODEV; | 1120 | return -ENODEV; |
1104 | 1121 | ||
1122 | if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED) | ||
1123 | return 0; | ||
1124 | |||
1105 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 1125 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
1106 | tpm2_shutdown(chip, TPM2_SU_STATE); | 1126 | tpm2_shutdown(chip, TPM2_SU_STATE); |
1107 | return 0; | 1127 | return 0; |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 4bd0997cfa2d..86f38d239476 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
@@ -36,9 +36,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
36 | ssize_t err; | 36 | ssize_t err; |
37 | int i, rc; | 37 | int i, rc; |
38 | char *str = buf; | 38 | char *str = buf; |
39 | |||
40 | struct tpm_chip *chip = to_tpm_chip(dev); | 39 | struct tpm_chip *chip = to_tpm_chip(dev); |
41 | 40 | ||
41 | memset(&tpm_cmd, 0, sizeof(tpm_cmd)); | ||
42 | |||
42 | tpm_cmd.header.in = tpm_readpubek_header; | 43 | tpm_cmd.header.in = tpm_readpubek_header; |
43 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 44 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, |
44 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, | 45 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, |
@@ -294,6 +295,9 @@ static const struct attribute_group tpm_dev_group = { | |||
294 | 295 | ||
295 | void tpm_sysfs_add_device(struct tpm_chip *chip) | 296 | void tpm_sysfs_add_device(struct tpm_chip *chip) |
296 | { | 297 | { |
298 | /* XXX: If you wish to remove this restriction, you must first update | ||
299 | * tpm_sysfs to explicitly lock chip->ops. | ||
300 | */ | ||
297 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 301 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
298 | return; | 302 | return; |
299 | 303 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 1df0521138d3..04fbff2edbf3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -36,6 +36,10 @@ | |||
36 | #include <linux/highmem.h> | 36 | #include <linux/highmem.h> |
37 | #include <crypto/hash_info.h> | 37 | #include <crypto/hash_info.h> |
38 | 38 | ||
39 | #ifdef CONFIG_X86 | ||
40 | #include <asm/intel-family.h> | ||
41 | #endif | ||
42 | |||
39 | enum tpm_const { | 43 | enum tpm_const { |
40 | TPM_MINOR = 224, /* officially assigned */ | 44 | TPM_MINOR = 224, /* officially assigned */ |
41 | TPM_BUFSIZE = 4096, | 45 | TPM_BUFSIZE = 4096, |
@@ -170,6 +174,7 @@ enum tpm_chip_flags { | |||
170 | TPM_CHIP_FLAG_IRQ = BIT(2), | 174 | TPM_CHIP_FLAG_IRQ = BIT(2), |
171 | TPM_CHIP_FLAG_VIRTUAL = BIT(3), | 175 | TPM_CHIP_FLAG_VIRTUAL = BIT(3), |
172 | TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), | 176 | TPM_CHIP_FLAG_HAVE_TIMEOUTS = BIT(4), |
177 | TPM_CHIP_FLAG_ALWAYS_POWERED = BIT(5), | ||
173 | }; | 178 | }; |
174 | 179 | ||
175 | struct tpm_bios_log { | 180 | struct tpm_bios_log { |
@@ -378,10 +383,6 @@ struct tpm_getrandom_in { | |||
378 | __be32 num_bytes; | 383 | __be32 num_bytes; |
379 | } __packed; | 384 | } __packed; |
380 | 385 | ||
381 | struct tpm_startup_in { | ||
382 | __be16 startup_type; | ||
383 | } __packed; | ||
384 | |||
385 | typedef union { | 386 | typedef union { |
386 | struct tpm_readpubek_params_out readpubek_out; | 387 | struct tpm_readpubek_params_out readpubek_out; |
387 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; | 388 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; |
@@ -389,7 +390,6 @@ typedef union { | |||
389 | struct tpm_pcrread_out pcrread_out; | 390 | struct tpm_pcrread_out pcrread_out; |
390 | struct tpm_getrandom_in getrandom_in; | 391 | struct tpm_getrandom_in getrandom_in; |
391 | struct tpm_getrandom_out getrandom_out; | 392 | struct tpm_getrandom_out getrandom_out; |
392 | struct tpm_startup_in startup_in; | ||
393 | } tpm_cmd_params; | 393 | } tpm_cmd_params; |
394 | 394 | ||
395 | struct tpm_cmd_t { | 395 | struct tpm_cmd_t { |
@@ -515,6 +515,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, | |||
515 | const void *buf, size_t bufsiz, | 515 | const void *buf, size_t bufsiz, |
516 | size_t min_rsp_body_length, unsigned int flags, | 516 | size_t min_rsp_body_length, unsigned int flags, |
517 | const char *desc); | 517 | const char *desc); |
518 | int tpm_startup(struct tpm_chip *chip); | ||
518 | ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, | 519 | ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, |
519 | const char *desc, size_t min_cap_length); | 520 | const char *desc, size_t min_cap_length); |
520 | int tpm_get_timeouts(struct tpm_chip *); | 521 | int tpm_get_timeouts(struct tpm_chip *); |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3a9964326279..f7f34b2aa981 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -35,24 +35,6 @@ struct tpm2_self_test_in { | |||
35 | u8 full_test; | 35 | u8 full_test; |
36 | } __packed; | 36 | } __packed; |
37 | 37 | ||
38 | struct tpm2_pcr_read_in { | ||
39 | __be32 pcr_selects_cnt; | ||
40 | __be16 hash_alg; | ||
41 | u8 pcr_select_size; | ||
42 | u8 pcr_select[TPM2_PCR_SELECT_MIN]; | ||
43 | } __packed; | ||
44 | |||
45 | struct tpm2_pcr_read_out { | ||
46 | __be32 update_cnt; | ||
47 | __be32 pcr_selects_cnt; | ||
48 | __be16 hash_alg; | ||
49 | u8 pcr_select_size; | ||
50 | u8 pcr_select[TPM2_PCR_SELECT_MIN]; | ||
51 | __be32 digests_cnt; | ||
52 | __be16 digest_size; | ||
53 | u8 digest[TPM_DIGEST_SIZE]; | ||
54 | } __packed; | ||
55 | |||
56 | struct tpm2_get_tpm_pt_in { | 38 | struct tpm2_get_tpm_pt_in { |
57 | __be32 cap_id; | 39 | __be32 cap_id; |
58 | __be32 property_id; | 40 | __be32 property_id; |
@@ -79,8 +61,6 @@ struct tpm2_get_random_out { | |||
79 | union tpm2_cmd_params { | 61 | union tpm2_cmd_params { |
80 | struct tpm2_startup_in startup_in; | 62 | struct tpm2_startup_in startup_in; |
81 | struct tpm2_self_test_in selftest_in; | 63 | struct tpm2_self_test_in selftest_in; |
82 | struct tpm2_pcr_read_in pcrread_in; | ||
83 | struct tpm2_pcr_read_out pcrread_out; | ||
84 | struct tpm2_get_tpm_pt_in get_tpm_pt_in; | 64 | struct tpm2_get_tpm_pt_in get_tpm_pt_in; |
85 | struct tpm2_get_tpm_pt_out get_tpm_pt_out; | 65 | struct tpm2_get_tpm_pt_out get_tpm_pt_out; |
86 | struct tpm2_get_random_in getrandom_in; | 66 | struct tpm2_get_random_in getrandom_in; |
@@ -227,18 +207,16 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { | |||
227 | TPM_UNDEFINED /* 18f */ | 207 | TPM_UNDEFINED /* 18f */ |
228 | }; | 208 | }; |
229 | 209 | ||
230 | #define TPM2_PCR_READ_IN_SIZE \ | 210 | struct tpm2_pcr_read_out { |
231 | (sizeof(struct tpm_input_header) + \ | 211 | __be32 update_cnt; |
232 | sizeof(struct tpm2_pcr_read_in)) | 212 | __be32 pcr_selects_cnt; |
233 | 213 | __be16 hash_alg; | |
234 | #define TPM2_PCR_READ_RESP_BODY_SIZE \ | 214 | u8 pcr_select_size; |
235 | sizeof(struct tpm2_pcr_read_out) | 215 | u8 pcr_select[TPM2_PCR_SELECT_MIN]; |
236 | 216 | __be32 digests_cnt; | |
237 | static const struct tpm_input_header tpm2_pcrread_header = { | 217 | __be16 digest_size; |
238 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | 218 | u8 digest[]; |
239 | .length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE), | 219 | } __packed; |
240 | .ordinal = cpu_to_be32(TPM2_CC_PCR_READ) | ||
241 | }; | ||
242 | 220 | ||
243 | /** | 221 | /** |
244 | * tpm2_pcr_read() - read a PCR value | 222 | * tpm2_pcr_read() - read a PCR value |
@@ -251,29 +229,33 @@ static const struct tpm_input_header tpm2_pcrread_header = { | |||
251 | int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | 229 | int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
252 | { | 230 | { |
253 | int rc; | 231 | int rc; |
254 | struct tpm2_cmd cmd; | 232 | struct tpm_buf buf; |
255 | u8 *buf; | 233 | struct tpm2_pcr_read_out *out; |
234 | u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0}; | ||
256 | 235 | ||
257 | if (pcr_idx >= TPM2_PLATFORM_PCR) | 236 | if (pcr_idx >= TPM2_PLATFORM_PCR) |
258 | return -EINVAL; | 237 | return -EINVAL; |
259 | 238 | ||
260 | cmd.header.in = tpm2_pcrread_header; | 239 | rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); |
261 | cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); | 240 | if (rc) |
262 | cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | 241 | return rc; |
263 | cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN; | 242 | |
243 | pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | ||
264 | 244 | ||
265 | memset(cmd.params.pcrread_in.pcr_select, 0, | 245 | tpm_buf_append_u32(&buf, 1); |
266 | sizeof(cmd.params.pcrread_in.pcr_select)); | 246 | tpm_buf_append_u16(&buf, TPM2_ALG_SHA1); |
267 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | 247 | tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN); |
248 | tpm_buf_append(&buf, (const unsigned char *)pcr_select, | ||
249 | sizeof(pcr_select)); | ||
268 | 250 | ||
269 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), | 251 | rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, |
270 | TPM2_PCR_READ_RESP_BODY_SIZE, | 252 | res_buf ? "attempting to read a pcr value" : NULL); |
271 | 0, "attempting to read a pcr value"); | 253 | if (rc == 0 && res_buf) { |
272 | if (rc == 0) { | 254 | out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; |
273 | buf = cmd.params.pcrread_out.digest; | 255 | memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE); |
274 | memcpy(res_buf, buf, TPM_DIGEST_SIZE); | ||
275 | } | 256 | } |
276 | 257 | ||
258 | tpm_buf_destroy(&buf); | ||
277 | return rc; | 259 | return rc; |
278 | } | 260 | } |
279 | 261 | ||
@@ -779,36 +761,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, | |||
779 | } | 761 | } |
780 | EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); | 762 | EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); |
781 | 763 | ||
782 | #define TPM2_STARTUP_IN_SIZE \ | ||
783 | (sizeof(struct tpm_input_header) + \ | ||
784 | sizeof(struct tpm2_startup_in)) | ||
785 | |||
786 | static const struct tpm_input_header tpm2_startup_header = { | ||
787 | .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), | ||
788 | .length = cpu_to_be32(TPM2_STARTUP_IN_SIZE), | ||
789 | .ordinal = cpu_to_be32(TPM2_CC_STARTUP) | ||
790 | }; | ||
791 | |||
792 | /** | ||
793 | * tpm2_startup() - send startup command to the TPM chip | ||
794 | * | ||
795 | * @chip: TPM chip to use. | ||
796 | * @startup_type: startup type. The value is either | ||
797 | * TPM_SU_CLEAR or TPM_SU_STATE. | ||
798 | * | ||
799 | * Return: Same as with tpm_transmit_cmd. | ||
800 | */ | ||
801 | static int tpm2_startup(struct tpm_chip *chip, u16 startup_type) | ||
802 | { | ||
803 | struct tpm2_cmd cmd; | ||
804 | |||
805 | cmd.header.in = tpm2_startup_header; | ||
806 | |||
807 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); | ||
808 | return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, | ||
809 | "attempting to start the TPM"); | ||
810 | } | ||
811 | |||
812 | #define TPM2_SHUTDOWN_IN_SIZE \ | 764 | #define TPM2_SHUTDOWN_IN_SIZE \ |
813 | (sizeof(struct tpm_input_header) + \ | 765 | (sizeof(struct tpm_input_header) + \ |
814 | sizeof(struct tpm2_startup_in)) | 766 | sizeof(struct tpm2_startup_in)) |
@@ -928,7 +880,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip) | |||
928 | unsigned int loops; | 880 | unsigned int loops; |
929 | unsigned int delay_msec = 100; | 881 | unsigned int delay_msec = 100; |
930 | unsigned long duration; | 882 | unsigned long duration; |
931 | struct tpm2_cmd cmd; | ||
932 | int i; | 883 | int i; |
933 | 884 | ||
934 | duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); | 885 | duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); |
@@ -941,20 +892,10 @@ static int tpm2_do_selftest(struct tpm_chip *chip) | |||
941 | 892 | ||
942 | for (i = 0; i < loops; i++) { | 893 | for (i = 0; i < loops; i++) { |
943 | /* Attempt to read a PCR value */ | 894 | /* Attempt to read a PCR value */ |
944 | cmd.header.in = tpm2_pcrread_header; | 895 | rc = tpm2_pcr_read(chip, 0, NULL); |
945 | cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1); | ||
946 | cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | ||
947 | cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN; | ||
948 | cmd.params.pcrread_in.pcr_select[0] = 0x01; | ||
949 | cmd.params.pcrread_in.pcr_select[1] = 0x00; | ||
950 | cmd.params.pcrread_in.pcr_select[2] = 0x00; | ||
951 | |||
952 | rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, | ||
953 | NULL); | ||
954 | if (rc < 0) | 896 | if (rc < 0) |
955 | break; | 897 | break; |
956 | 898 | ||
957 | rc = be32_to_cpu(cmd.header.out.return_code); | ||
958 | if (rc != TPM2_RC_TESTING) | 899 | if (rc != TPM2_RC_TESTING) |
959 | break; | 900 | break; |
960 | 901 | ||
@@ -1150,7 +1091,7 @@ int tpm2_auto_startup(struct tpm_chip *chip) | |||
1150 | } | 1091 | } |
1151 | 1092 | ||
1152 | if (rc == TPM2_RC_INITIALIZE) { | 1093 | if (rc == TPM2_RC_INITIALIZE) { |
1153 | rc = tpm2_startup(chip, TPM2_SU_CLEAR); | 1094 | rc = tpm_startup(chip); |
1154 | if (rc) | 1095 | if (rc) |
1155 | goto out; | 1096 | goto out; |
1156 | 1097 | ||
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index fe42c4a0d8d1..a4ac63a21d8a 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
@@ -514,11 +514,12 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
514 | goto out; | 514 | goto out; |
515 | } | 515 | } |
516 | 516 | ||
517 | priv->cmd_size = cmd_size; | ||
518 | |||
519 | priv->rsp = priv->cmd; | 517 | priv->rsp = priv->cmd; |
520 | 518 | ||
521 | out: | 519 | out: |
520 | if (!ret) | ||
521 | priv->cmd_size = cmd_size; | ||
522 | |||
522 | crb_go_idle(dev, priv); | 523 | crb_go_idle(dev, priv); |
523 | 524 | ||
524 | return ret; | 525 | return ret; |
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c index de57d4ac8901..aadb7f464076 100644 --- a/drivers/char/tpm/tpm_of.c +++ b/drivers/char/tpm/tpm_of.c | |||
@@ -36,6 +36,9 @@ int tpm_read_log_of(struct tpm_chip *chip) | |||
36 | else | 36 | else |
37 | return -ENODEV; | 37 | return -ENODEV; |
38 | 38 | ||
39 | if (of_property_read_bool(np, "powered-while-suspended")) | ||
40 | chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; | ||
41 | |||
39 | sizep = of_get_property(np, "linux,sml-size", NULL); | 42 | sizep = of_get_property(np, "linux,sml-size", NULL); |
40 | basep = of_get_property(np, "linux,sml-base", NULL); | 43 | basep = of_get_property(np, "linux,sml-base", NULL); |
41 | if (sizep == NULL && basep == NULL) | 44 | if (sizep == NULL && basep == NULL) |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index b14d4aa97af8..7e55aa9ce680 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev) | |||
132 | } | 132 | } |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | #ifdef CONFIG_X86 | ||
136 | #define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 | ||
137 | #define ILB_REMAP_SIZE 0x100 | ||
138 | #define LPC_CNTRL_REG_OFFSET 0x84 | ||
139 | #define LPC_CLKRUN_EN (1 << 2) | ||
140 | |||
141 | static void __iomem *ilb_base_addr; | ||
142 | |||
143 | static inline bool is_bsw(void) | ||
144 | { | ||
145 | return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running | ||
150 | */ | ||
151 | static void tpm_platform_begin_xfer(void) | ||
152 | { | ||
153 | u32 clkrun_val; | ||
154 | |||
155 | if (!is_bsw()) | ||
156 | return; | ||
157 | |||
158 | clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
159 | |||
160 | /* Disable LPC CLKRUN# */ | ||
161 | clkrun_val &= ~LPC_CLKRUN_EN; | ||
162 | iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
163 | |||
164 | /* | ||
165 | * Write any random value on port 0x80 which is on LPC, to make | ||
166 | * sure LPC clock is running before sending any TPM command. | ||
167 | */ | ||
168 | outb(0xCC, 0x80); | ||
169 | |||
170 | } | ||
171 | |||
172 | /** | ||
173 | * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off | ||
174 | */ | ||
175 | static void tpm_platform_end_xfer(void) | ||
176 | { | ||
177 | u32 clkrun_val; | ||
178 | |||
179 | if (!is_bsw()) | ||
180 | return; | ||
181 | |||
182 | clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
183 | |||
184 | /* Enable LPC CLKRUN# */ | ||
185 | clkrun_val |= LPC_CLKRUN_EN; | ||
186 | iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
187 | |||
188 | /* | ||
189 | * Write any random value on port 0x80 which is on LPC, to make | ||
190 | * sure LPC clock is running before sending any TPM command. | ||
191 | */ | ||
192 | outb(0xCC, 0x80); | ||
193 | |||
194 | } | ||
195 | #else | ||
196 | static inline bool is_bsw(void) | ||
197 | { | ||
198 | return false; | ||
199 | } | ||
200 | |||
201 | static void tpm_platform_begin_xfer(void) | ||
202 | { | ||
203 | } | ||
204 | |||
205 | static void tpm_platform_end_xfer(void) | ||
206 | { | ||
207 | } | ||
208 | #endif | ||
209 | |||
135 | static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | 210 | static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, |
136 | u8 *result) | 211 | u8 *result) |
137 | { | 212 | { |
138 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 213 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
139 | 214 | ||
215 | tpm_platform_begin_xfer(); | ||
216 | |||
140 | while (len--) | 217 | while (len--) |
141 | *result++ = ioread8(phy->iobase + addr); | 218 | *result++ = ioread8(phy->iobase + addr); |
219 | |||
220 | tpm_platform_end_xfer(); | ||
221 | |||
142 | return 0; | 222 | return 0; |
143 | } | 223 | } |
144 | 224 | ||
@@ -147,8 +227,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | |||
147 | { | 227 | { |
148 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 228 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
149 | 229 | ||
230 | tpm_platform_begin_xfer(); | ||
231 | |||
150 | while (len--) | 232 | while (len--) |
151 | iowrite8(*value++, phy->iobase + addr); | 233 | iowrite8(*value++, phy->iobase + addr); |
234 | |||
235 | tpm_platform_end_xfer(); | ||
236 | |||
152 | return 0; | 237 | return 0; |
153 | } | 238 | } |
154 | 239 | ||
@@ -156,7 +241,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | |||
156 | { | 241 | { |
157 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 242 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
158 | 243 | ||
244 | tpm_platform_begin_xfer(); | ||
245 | |||
159 | *result = ioread16(phy->iobase + addr); | 246 | *result = ioread16(phy->iobase + addr); |
247 | |||
248 | tpm_platform_end_xfer(); | ||
249 | |||
160 | return 0; | 250 | return 0; |
161 | } | 251 | } |
162 | 252 | ||
@@ -164,7 +254,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) | |||
164 | { | 254 | { |
165 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 255 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
166 | 256 | ||
257 | tpm_platform_begin_xfer(); | ||
258 | |||
167 | *result = ioread32(phy->iobase + addr); | 259 | *result = ioread32(phy->iobase + addr); |
260 | |||
261 | tpm_platform_end_xfer(); | ||
262 | |||
168 | return 0; | 263 | return 0; |
169 | } | 264 | } |
170 | 265 | ||
@@ -172,7 +267,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) | |||
172 | { | 267 | { |
173 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 268 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
174 | 269 | ||
270 | tpm_platform_begin_xfer(); | ||
271 | |||
175 | iowrite32(value, phy->iobase + addr); | 272 | iowrite32(value, phy->iobase + addr); |
273 | |||
274 | tpm_platform_end_xfer(); | ||
275 | |||
176 | return 0; | 276 | return 0; |
177 | } | 277 | } |
178 | 278 | ||
@@ -360,6 +460,11 @@ static int __init init_tis(void) | |||
360 | if (rc) | 460 | if (rc) |
361 | goto err_force; | 461 | goto err_force; |
362 | 462 | ||
463 | #ifdef CONFIG_X86 | ||
464 | if (is_bsw()) | ||
465 | ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, | ||
466 | ILB_REMAP_SIZE); | ||
467 | #endif | ||
363 | rc = platform_driver_register(&tis_drv); | 468 | rc = platform_driver_register(&tis_drv); |
364 | if (rc) | 469 | if (rc) |
365 | goto err_platform; | 470 | goto err_platform; |
@@ -378,6 +483,10 @@ err_pnp: | |||
378 | err_platform: | 483 | err_platform: |
379 | if (force_pdev) | 484 | if (force_pdev) |
380 | platform_device_unregister(force_pdev); | 485 | platform_device_unregister(force_pdev); |
486 | #ifdef CONFIG_X86 | ||
487 | if (is_bsw()) | ||
488 | iounmap(ilb_base_addr); | ||
489 | #endif | ||
381 | err_force: | 490 | err_force: |
382 | return rc; | 491 | return rc; |
383 | } | 492 | } |
@@ -387,6 +496,10 @@ static void __exit cleanup_tis(void) | |||
387 | pnp_unregister_driver(&tis_pnp_driver); | 496 | pnp_unregister_driver(&tis_pnp_driver); |
388 | platform_driver_unregister(&tis_drv); | 497 | platform_driver_unregister(&tis_drv); |
389 | 498 | ||
499 | #ifdef CONFIG_X86 | ||
500 | if (is_bsw()) | ||
501 | iounmap(ilb_base_addr); | ||
502 | #endif | ||
390 | if (force_pdev) | 503 | if (force_pdev) |
391 | platform_device_unregister(force_pdev); | 504 | platform_device_unregister(force_pdev); |
392 | } | 505 | } |
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 631eaa9daf65..a5dfab6adf49 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work) | |||
376 | WARN_ONCE(ret, | 376 | WARN_ONCE(ret, |
377 | "ib_get_cached_subnet_prefix err: %d, this should never happen here\n", | 377 | "ib_get_cached_subnet_prefix err: %d, this should never happen here\n", |
378 | ret); | 378 | ret); |
379 | ib_security_cache_change(dev, i, sp); | 379 | if (!ret) |
380 | ib_security_cache_change(dev, i, sp); | ||
380 | } | 381 | } |
381 | } | 382 | } |
382 | up_read(&lists_rwsem); | 383 | up_read(&lists_rwsem); |
diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c index 3e8c38953912..70ad19c4c73e 100644 --- a/drivers/infiniband/core/security.c +++ b/drivers/infiniband/core/security.c | |||
@@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps, | |||
120 | return 0; | 120 | return 0; |
121 | 121 | ||
122 | if (pps->main.state != IB_PORT_PKEY_NOT_VALID) { | 122 | if (pps->main.state != IB_PORT_PKEY_NOT_VALID) { |
123 | get_pkey_and_subnet_prefix(&pps->main, | 123 | ret = get_pkey_and_subnet_prefix(&pps->main, |
124 | &pkey, | 124 | &pkey, |
125 | &subnet_prefix); | 125 | &subnet_prefix); |
126 | if (ret) | ||
127 | return ret; | ||
126 | 128 | ||
127 | ret = enforce_qp_pkey_security(pkey, | 129 | ret = enforce_qp_pkey_security(pkey, |
128 | subnet_prefix, | 130 | subnet_prefix, |
129 | sec); | 131 | sec); |
132 | if (ret) | ||
133 | return ret; | ||
130 | } | 134 | } |
131 | if (ret) | ||
132 | return ret; | ||
133 | 135 | ||
134 | if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) { | 136 | if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) { |
135 | get_pkey_and_subnet_prefix(&pps->alt, | 137 | ret = get_pkey_and_subnet_prefix(&pps->alt, |
136 | &pkey, | 138 | &pkey, |
137 | &subnet_prefix); | 139 | &subnet_prefix); |
140 | if (ret) | ||
141 | return ret; | ||
138 | 142 | ||
139 | ret = enforce_qp_pkey_security(pkey, | 143 | ret = enforce_qp_pkey_security(pkey, |
140 | subnet_prefix, | 144 | subnet_prefix, |
diff --git a/include/linux/device.h b/include/linux/device.h index 6baa1238f158..723cd54b94da 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -375,6 +375,7 @@ int subsys_virtual_register(struct bus_type *subsys, | |||
375 | * @suspend: Used to put the device to sleep mode, usually to a low power | 375 | * @suspend: Used to put the device to sleep mode, usually to a low power |
376 | * state. | 376 | * state. |
377 | * @resume: Used to bring the device from the sleep mode. | 377 | * @resume: Used to bring the device from the sleep mode. |
378 | * @shutdown: Called at shut-down time to quiesce the device. | ||
378 | * @ns_type: Callbacks so sysfs can detemine namespaces. | 379 | * @ns_type: Callbacks so sysfs can detemine namespaces. |
379 | * @namespace: Namespace of the device belongs to this class. | 380 | * @namespace: Namespace of the device belongs to this class. |
380 | * @pm: The default device power management operations of this class. | 381 | * @pm: The default device power management operations of this class. |
@@ -403,6 +404,7 @@ struct class { | |||
403 | 404 | ||
404 | int (*suspend)(struct device *dev, pm_message_t state); | 405 | int (*suspend)(struct device *dev, pm_message_t state); |
405 | int (*resume)(struct device *dev); | 406 | int (*resume)(struct device *dev); |
407 | int (*shutdown)(struct device *dev); | ||
406 | 408 | ||
407 | const struct kobj_ns_type_operations *ns_type; | 409 | const struct kobj_ns_type_operations *ns_type; |
408 | const void *(*namespace)(struct device *dev); | 410 | const void *(*namespace)(struct device *dev); |