| From 6c4e79d99e6f42b79040f1a33cd4018f5425030b Mon Sep 17 00:00:00 2001 |
| From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Date: Fri, 3 Jul 2020 01:55:59 +0300 |
| Subject: tpm: Unify the mismatching TPM space buffer sizes |
| |
| From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| |
| commit 6c4e79d99e6f42b79040f1a33cd4018f5425030b upstream. |
| |
| The size of the buffers for storing context's and sessions can vary from |
| arch to arch as PAGE_SIZE can be anything between 4 kB and 256 kB (the |
| maximum for PPC64). Define a fixed buffer size set to 16 kB. This should be |
| enough for most use with three handles (that is how many we allow at the |
| moment). Parametrize the buffer size while doing this, so that it is easier |
| to revisit this later on if required. |
| |
| Cc: stable@vger.kernel.org |
| Reported-by: Stefan Berger <stefanb@linux.ibm.com> |
| Fixes: 745b361e989a ("tpm: infrastructure for TPM spaces") |
| Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> |
| Tested-by: Stefan Berger <stefanb@linux.ibm.com> |
| Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/tpm/tpm-chip.c | 9 ++------- |
| drivers/char/tpm/tpm.h | 5 ++++- |
| drivers/char/tpm/tpm2-space.c | 26 ++++++++++++++++---------- |
| drivers/char/tpm/tpmrm-dev.c | 2 +- |
| include/linux/tpm.h | 1 + |
| 5 files changed, 24 insertions(+), 19 deletions(-) |
| |
| --- a/drivers/char/tpm/tpm-chip.c |
| +++ b/drivers/char/tpm/tpm-chip.c |
| @@ -386,13 +386,8 @@ struct tpm_chip *tpm_chip_alloc(struct d |
| chip->cdev.owner = THIS_MODULE; |
| chip->cdevs.owner = THIS_MODULE; |
| |
| - chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| - if (!chip->work_space.context_buf) { |
| - rc = -ENOMEM; |
| - goto out; |
| - } |
| - chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| - if (!chip->work_space.session_buf) { |
| + rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE); |
| + if (rc) { |
| rc = -ENOMEM; |
| goto out; |
| } |
| --- a/drivers/char/tpm/tpm.h |
| +++ b/drivers/char/tpm/tpm.h |
| @@ -59,6 +59,9 @@ enum tpm_addr { |
| |
| #define TPM_TAG_RQU_COMMAND 193 |
| |
| +/* TPM2 specific constants. */ |
| +#define TPM2_SPACE_BUFFER_SIZE 16384 /* 16 kB */ |
| + |
| struct stclear_flags_t { |
| __be16 tag; |
| u8 deactivated; |
| @@ -228,7 +231,7 @@ unsigned long tpm2_calc_ordinal_duration |
| int tpm2_probe(struct tpm_chip *chip); |
| int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip); |
| int tpm2_find_cc(struct tpm_chip *chip, u32 cc); |
| -int tpm2_init_space(struct tpm_space *space); |
| +int tpm2_init_space(struct tpm_space *space, unsigned int buf_size); |
| void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space); |
| void tpm2_flush_space(struct tpm_chip *chip); |
| int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, |
| --- a/drivers/char/tpm/tpm2-space.c |
| +++ b/drivers/char/tpm/tpm2-space.c |
| @@ -38,18 +38,21 @@ static void tpm2_flush_sessions(struct t |
| } |
| } |
| |
| -int tpm2_init_space(struct tpm_space *space) |
| +int tpm2_init_space(struct tpm_space *space, unsigned int buf_size) |
| { |
| - space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| + space->context_buf = kzalloc(buf_size, GFP_KERNEL); |
| if (!space->context_buf) |
| return -ENOMEM; |
| |
| - space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| + space->session_buf = kzalloc(buf_size, GFP_KERNEL); |
| if (space->session_buf == NULL) { |
| kfree(space->context_buf); |
| + /* Prevent caller getting a dangling pointer. */ |
| + space->context_buf = NULL; |
| return -ENOMEM; |
| } |
| |
| + space->buf_size = buf_size; |
| return 0; |
| } |
| |
| @@ -311,8 +314,10 @@ int tpm2_prepare_space(struct tpm_chip * |
| sizeof(space->context_tbl)); |
| memcpy(&chip->work_space.session_tbl, &space->session_tbl, |
| sizeof(space->session_tbl)); |
| - memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE); |
| - memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE); |
| + memcpy(chip->work_space.context_buf, space->context_buf, |
| + space->buf_size); |
| + memcpy(chip->work_space.session_buf, space->session_buf, |
| + space->buf_size); |
| |
| rc = tpm2_load_space(chip); |
| if (rc) { |
| @@ -492,7 +497,7 @@ static int tpm2_save_space(struct tpm_ch |
| continue; |
| |
| rc = tpm2_save_context(chip, space->context_tbl[i], |
| - space->context_buf, PAGE_SIZE, |
| + space->context_buf, space->buf_size, |
| &offset); |
| if (rc == -ENOENT) { |
| space->context_tbl[i] = 0; |
| @@ -509,9 +514,8 @@ static int tpm2_save_space(struct tpm_ch |
| continue; |
| |
| rc = tpm2_save_context(chip, space->session_tbl[i], |
| - space->session_buf, PAGE_SIZE, |
| + space->session_buf, space->buf_size, |
| &offset); |
| - |
| if (rc == -ENOENT) { |
| /* handle error saving session, just forget it */ |
| space->session_tbl[i] = 0; |
| @@ -557,8 +561,10 @@ int tpm2_commit_space(struct tpm_chip *c |
| sizeof(space->context_tbl)); |
| memcpy(&space->session_tbl, &chip->work_space.session_tbl, |
| sizeof(space->session_tbl)); |
| - memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE); |
| - memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE); |
| + memcpy(space->context_buf, chip->work_space.context_buf, |
| + space->buf_size); |
| + memcpy(space->session_buf, chip->work_space.session_buf, |
| + space->buf_size); |
| |
| return 0; |
| out: |
| --- a/drivers/char/tpm/tpmrm-dev.c |
| +++ b/drivers/char/tpm/tpmrm-dev.c |
| @@ -21,7 +21,7 @@ static int tpmrm_open(struct inode *inod |
| if (priv == NULL) |
| return -ENOMEM; |
| |
| - rc = tpm2_init_space(&priv->space); |
| + rc = tpm2_init_space(&priv->space, TPM2_SPACE_BUFFER_SIZE); |
| if (rc) { |
| kfree(priv); |
| return -ENOMEM; |
| --- a/include/linux/tpm.h |
| +++ b/include/linux/tpm.h |
| @@ -96,6 +96,7 @@ struct tpm_space { |
| u8 *context_buf; |
| u32 session_tbl[3]; |
| u8 *session_buf; |
| + u32 buf_size; |
| }; |
| |
| struct tpm_bios_log { |