Skip to content

Commit c659af7

Browse files
stefanbergerJarkko Sakkinen
authored andcommitted
tpm: Check size of response before accessing data
Make sure that we have not received less bytes than what is indicated in the header of the TPM response. Also, check the number of bytes in the response before accessing its data. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com>
1 parent 1d70fe9 commit c659af7

File tree

5 files changed

+123
-51
lines changed

5 files changed

+123
-51
lines changed

drivers/char/tpm/tpm-interface.c

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
423423
* The function extracts tpm out header return code
424424
*
425425
* @chip: TPM chip to use
426-
* @cmd: TPM command buffer
427-
* @len: length of the TPM command
426+
* @buf: TPM command buffer
427+
* @bufsiz: length of the buffer
428+
* @min_rsp_body_length: minimum expected length of response body
428429
* @flags: tpm transmit flags - bitmap
429430
* @desc: command description used in the error message
430431
*
@@ -433,26 +434,35 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
433434
* A negative number for system errors (errno).
434435
* A positive number for a TPM error.
435436
*/
436-
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd,
437-
int len, unsigned int flags, const char *desc)
437+
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf,
438+
size_t bufsiz, size_t min_rsp_body_length,
439+
unsigned int flags, const char *desc)
438440
{
439441
const struct tpm_output_header *header;
440442
int err;
443+
ssize_t len;
441444

442-
len = tpm_transmit(chip, (const u8 *)cmd, len, flags);
445+
len = tpm_transmit(chip, (const u8 *)buf, bufsiz, flags);
443446
if (len < 0)
444447
return len;
445448
else if (len < TPM_HEADER_SIZE)
446449
return -EFAULT;
447450

448-
header = cmd;
451+
header = buf;
452+
if (len != be32_to_cpu(header->length))
453+
return -EFAULT;
449454

450455
err = be32_to_cpu(header->return_code);
451456
if (err != 0 && desc)
452457
dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
453458
desc);
459+
if (err)
460+
return err;
461+
462+
if (len < min_rsp_body_length + TPM_HEADER_SIZE)
463+
return -EFAULT;
454464

455-
return err;
465+
return 0;
456466
}
457467

458468
#define TPM_DIGEST_SIZE 20
@@ -468,7 +478,7 @@ static const struct tpm_input_header tpm_getcap_header = {
468478
};
469479

470480
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
471-
const char *desc)
481+
const char *desc, size_t min_cap_length)
472482
{
473483
struct tpm_cmd_t tpm_cmd;
474484
int rc;
@@ -491,8 +501,8 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
491501
tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
492502
tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
493503
}
494-
rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
495-
desc);
504+
rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
505+
min_cap_length, 0, desc);
496506
if (!rc)
497507
*cap = tpm_cmd.params.getcap_out.cap;
498508
return rc;
@@ -516,7 +526,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
516526

517527
start_cmd.params.startup_in.startup_type = startup_type;
518528
return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
519-
"attempting to start the TPM");
529+
0, "attempting to start the TPM");
520530
}
521531

522532
int tpm_get_timeouts(struct tpm_chip *chip)
@@ -545,7 +555,8 @@ int tpm_get_timeouts(struct tpm_chip *chip)
545555
return 0;
546556
}
547557

548-
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL);
558+
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
559+
sizeof(cap.timeout));
549560
if (rc == TPM_ERR_INVALID_POSTINIT) {
550561
/* The TPM is not started, we are the first to talk to it.
551562
Execute a startup command. */
@@ -554,8 +565,10 @@ int tpm_get_timeouts(struct tpm_chip *chip)
554565
return rc;
555566

556567
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
557-
"attempting to determine the timeouts");
568+
"attempting to determine the timeouts",
569+
sizeof(cap.timeout));
558570
}
571+
559572
if (rc) {
560573
dev_err(&chip->dev,
561574
"A TPM error (%zd) occurred attempting to determine the timeouts\n",
@@ -617,7 +630,8 @@ int tpm_get_timeouts(struct tpm_chip *chip)
617630
chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
618631

619632
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
620-
"attempting to determine the durations");
633+
"attempting to determine the durations",
634+
sizeof(cap.duration));
621635
if (rc)
622636
return rc;
623637

@@ -668,13 +682,14 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
668682
struct tpm_cmd_t cmd;
669683

670684
cmd.header.in = continue_selftest_header;
671-
rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0,
685+
rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, 0,
672686
"continue selftest");
673687
return rc;
674688
}
675689

676690
#define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
677691
#define READ_PCR_RESULT_SIZE 30
692+
#define READ_PCR_RESULT_BODY_SIZE 20
678693
static const struct tpm_input_header pcrread_header = {
679694
.tag = TPM_TAG_RQU_COMMAND,
680695
.length = cpu_to_be32(14),
@@ -688,7 +703,8 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
688703

689704
cmd.header.in = pcrread_header;
690705
cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
691-
rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, 0,
706+
rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
707+
READ_PCR_RESULT_BODY_SIZE, 0,
692708
"attempting to read a pcr value");
693709

694710
if (rc == 0)
@@ -751,6 +767,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
751767

752768
#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
753769
#define EXTEND_PCR_RESULT_SIZE 34
770+
#define EXTEND_PCR_RESULT_BODY_SIZE 24
754771
static const struct tpm_input_header pcrextend_header = {
755772
.tag = TPM_TAG_RQU_COMMAND,
756773
.length = cpu_to_be32(34),
@@ -786,7 +803,8 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
786803
cmd.header.in = pcrextend_header;
787804
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
788805
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
789-
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0,
806+
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
807+
EXTEND_PCR_RESULT_BODY_SIZE, 0,
790808
"attempting extend a PCR value");
791809

792810
tpm_put_ops(chip);
@@ -890,7 +908,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
890908
if (chip == NULL)
891909
return -ENODEV;
892910

893-
rc = tpm_transmit_cmd(chip, cmd, buflen, 0, "attempting tpm_cmd");
911+
rc = tpm_transmit_cmd(chip, cmd, buflen, 0, 0, "attempting tpm_cmd");
894912

895913
tpm_put_ops(chip);
896914
return rc;
@@ -992,15 +1010,16 @@ int tpm_pm_suspend(struct device *dev)
9921010
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
9931011
memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
9941012
TPM_DIGEST_SIZE);
995-
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0,
1013+
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
1014+
EXTEND_PCR_RESULT_BODY_SIZE, 0,
9961015
"extending dummy pcr before suspend");
9971016
}
9981017

9991018
/* now do the actual savestate */
10001019
for (try = 0; try < TPM_RETRY; try++) {
10011020
cmd.header.in = savestate_header;
10021021
rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0,
1003-
NULL);
1022+
0, NULL);
10041023

10051024
/*
10061025
* If the TPM indicates that it is too busy to respond to
@@ -1062,7 +1081,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
10621081
{
10631082
struct tpm_chip *chip;
10641083
struct tpm_cmd_t tpm_cmd;
1065-
u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
1084+
u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength;
10661085
int err, total = 0, retries = 5;
10671086
u8 *dest = out;
10681087

@@ -1085,11 +1104,20 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
10851104

10861105
err = tpm_transmit_cmd(chip, &tpm_cmd,
10871106
TPM_GETRANDOM_RESULT_SIZE + num_bytes,
1107+
offsetof(struct tpm_getrandom_out,
1108+
rng_data),
10881109
0, "attempting get random");
10891110
if (err)
10901111
break;
10911112

10921113
recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
1114+
1115+
rlength = be32_to_cpu(tpm_cmd.header.out.length);
1116+
if (rlength < offsetof(struct tpm_getrandom_out, rng_data) +
1117+
recd) {
1118+
total = -EFAULT;
1119+
break;
1120+
}
10931121
memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
10941122

10951123
dest += recd;

drivers/char/tpm/tpm-sysfs.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "tpm.h"
2222

2323
#define READ_PUBEK_RESULT_SIZE 314
24+
#define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256)
2425
#define TPM_ORD_READPUBEK cpu_to_be32(124)
2526
static const struct tpm_input_header tpm_readpubek_header = {
2627
.tag = TPM_TAG_RQU_COMMAND,
@@ -39,7 +40,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
3940
struct tpm_chip *chip = to_tpm_chip(dev);
4041

4142
tpm_cmd.header.in = tpm_readpubek_header;
42-
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0,
43+
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
44+
READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
4345
"attempting to read the PUBEK");
4446
if (err)
4547
goto out;
@@ -95,7 +97,8 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
9597
struct tpm_chip *chip = to_tpm_chip(dev);
9698

9799
rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap,
98-
"attempting to determine the number of PCRS");
100+
"attempting to determine the number of PCRS",
101+
sizeof(cap.num_pcrs));
99102
if (rc)
100103
return 0;
101104

@@ -120,7 +123,8 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
120123
ssize_t rc;
121124

122125
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
123-
"attempting to determine the permanent enabled state");
126+
"attempting to determine the permanent enabled state",
127+
sizeof(cap.perm_flags));
124128
if (rc)
125129
return 0;
126130

@@ -136,7 +140,8 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,
136140
ssize_t rc;
137141

138142
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
139-
"attempting to determine the permanent active state");
143+
"attempting to determine the permanent active state",
144+
sizeof(cap.perm_flags));
140145
if (rc)
141146
return 0;
142147

@@ -152,7 +157,8 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
152157
ssize_t rc;
153158

154159
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
155-
"attempting to determine the owner state");
160+
"attempting to determine the owner state",
161+
sizeof(cap.owned));
156162
if (rc)
157163
return 0;
158164

@@ -168,7 +174,8 @@ static ssize_t temp_deactivated_show(struct device *dev,
168174
ssize_t rc;
169175

170176
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
171-
"attempting to determine the temporary state");
177+
"attempting to determine the temporary state",
178+
sizeof(cap.stclear_flags));
172179
if (rc)
173180
return 0;
174181

@@ -186,15 +193,17 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
186193
char *str = buf;
187194

188195
rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
189-
"attempting to determine the manufacturer");
196+
"attempting to determine the manufacturer",
197+
sizeof(cap.manufacturer_id));
190198
if (rc)
191199
return 0;
192200
str += sprintf(str, "Manufacturer: 0x%x\n",
193201
be32_to_cpu(cap.manufacturer_id));
194202

195203
/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
196204
rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
197-
"attempting to determine the 1.2 version");
205+
"attempting to determine the 1.2 version",
206+
sizeof(cap.tpm_version_1_2));
198207
if (!rc) {
199208
str += sprintf(str,
200209
"TCG version: %d.%d\nFirmware version: %d.%d\n",
@@ -205,7 +214,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
205214
} else {
206215
/* Otherwise just use TPM_STRUCT_VER */
207216
rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
208-
"attempting to determine the 1.1 version");
217+
"attempting to determine the 1.1 version",
218+
sizeof(cap.tpm_version));
209219
if (rc)
210220
return 0;
211221
str += sprintf(str,

drivers/char/tpm/tpm.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,11 @@ enum tpm_transmit_flags {
493493

494494
ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
495495
unsigned int flags);
496-
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len,
497-
unsigned int flags, const char *desc);
496+
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, size_t bufsiz,
497+
size_t min_rsp_body_len, unsigned int flags,
498+
const char *desc);
498499
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
499-
const char *desc);
500+
const char *desc, size_t min_cap_length);
500501
int tpm_get_timeouts(struct tpm_chip *);
501502
int tpm1_auto_startup(struct tpm_chip *chip);
502503
int tpm_do_selftest(struct tpm_chip *chip);

0 commit comments

Comments
 (0)