Re: [PATCH] tpm: tpm2-space: Resize session and context buffers dynamically

2020-06-25 Thread Jarkko Sakkinen
On Thu, Jun 25, 2020 at 08:13:09AM -0400, Stefan Berger wrote:
> On 6/25/20 12:24 AM, Jarkko Sakkinen wrote:
> > Re-allocate context and session buffers when needed. Scale them in page
> > increments so that the reallocation is only seldomly required, and thus
> > causes minimal stress to the system. Add a static maximum limit of four
> > pages for buffer sizes.
> > 
> > Cc: James Bottomley 
> > Suggested-by: Stefan Berger 
> > Signed-off-by: Jarkko Sakkinen 
> > ---
> > Tested only for compilation.
> >   drivers/char/tpm/tpm2-space.c | 80 ---
> >   include/linux/tpm.h   |  6 ++-
> >   2 files changed, 59 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> > index 982d341d8837..acb9e82bf9e8 100644
> > --- a/drivers/char/tpm/tpm2-space.c
> > +++ b/drivers/char/tpm/tpm2-space.c
> > @@ -15,6 +15,8 @@
> >   #include 
> >   #include "tpm.h"
> > +#define TPM2_SPACE_MAX_BUFFER_SIZE (4 * PAGE_SIZE)
> 
> PAGE_SIZE is 64k on ppc64. Rather use 4 * 4096?

Better to then just put it as 16384.

/Jarkko


Re: [PATCH] tpm: tpm2-space: Resize session and context buffers dynamically

2020-06-25 Thread Stefan Berger

On 6/25/20 12:24 AM, Jarkko Sakkinen wrote:

Re-allocate context and session buffers when needed. Scale them in page
increments so that the reallocation is only seldomly required, and thus
causes minimal stress to the system. Add a static maximum limit of four
pages for buffer sizes.

Cc: James Bottomley 
Suggested-by: Stefan Berger 
Signed-off-by: Jarkko Sakkinen 
---
Tested only for compilation.
  drivers/char/tpm/tpm2-space.c | 80 ---
  include/linux/tpm.h   |  6 ++-
  2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 982d341d8837..acb9e82bf9e8 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -15,6 +15,8 @@
  #include 
  #include "tpm.h"
  
+#define TPM2_SPACE_MAX_BUFFER_SIZE	(4 * PAGE_SIZE)


PAGE_SIZE is 64k on ppc64. Rather use 4 * 4096?


Rest looks good.



+
  enum tpm2_handle_types {
TPM2_HT_HMAC_SESSION= 0x0200,
TPM2_HT_POLICY_SESSION  = 0x0300,
@@ -47,9 +49,12 @@ int tpm2_init_space(struct tpm_space *space)
space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (space->session_buf == NULL) {
kfree(space->context_buf);
+   space->context_buf = NULL;
return -ENOMEM;
}
  
+	space->context_size = PAGE_SIZE;

+   space->session_size = PAGE_SIZE;
return 0;
  }
  
@@ -116,11 +121,13 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,

return 0;
  }
  
-static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,

-unsigned int buf_size, unsigned int *offset)
+static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 **buf,
+unsigned int *buf_size, unsigned int *offset)
  {
-   struct tpm_buf tbuf;
+   unsigned int new_buf_size;
unsigned int body_size;
+   struct tpm_buf tbuf;
+   void *new_buf;
int rc;
  
  	rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);

@@ -131,31 +138,48 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 
handle, u8 *buf,
  
  	rc = tpm_transmit_cmd(chip, , 0, NULL);

if (rc < 0) {
-   dev_warn(>dev, "%s: failed with a system error %d\n",
-__func__, rc);
-   tpm_buf_destroy();
-   return -EFAULT;
+   rc = -EFAULT;
+   goto err;
} else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
-   tpm_buf_destroy();
-   return -ENOENT;
+   rc = -ENOENT;
+   goto out;
} else if (rc) {
-   dev_warn(>dev, "%s: failed with a TPM error 0x%04X\n",
-__func__, rc);
-   tpm_buf_destroy();
-   return -EFAULT;
+   rc = -EFAULT;
+   goto err;
}
  
  	body_size = tpm_buf_length() - TPM_HEADER_SIZE;

-   if ((*offset + body_size) > buf_size) {
-   dev_warn(>dev, "%s: out of backing storage\n", __func__);
-   tpm_buf_destroy();
-   return -ENOMEM;
+   /* We grow the buffer in page increments. */
+   new_buf_size = PFN_UP(*offset + body_size);
+
+   if (new_buf_size > TPM2_SPACE_MAX_BUFFER_SIZE) {
+   rc = -ENOMEM;
+   goto err;
}
  
-	memcpy([*offset], [TPM_HEADER_SIZE], body_size);

+   if (new_buf_size > *buf_size) {
+   new_buf = krealloc(*buf, new_buf_size, GFP_KERNEL);
+   if (!new_buf) {
+   rc = -ENOMEM;
+   goto err;
+   }
+
+   *buf = new_buf;
+   *buf_size = new_buf_size;
+   }
+
+   memcpy(*buf + *offset, [TPM_HEADER_SIZE], body_size);
*offset += body_size;
+
+out:
tpm_buf_destroy();
-   return 0;
+   return rc;
+
+err:
+   dev_warn(>dev, "%s: ret=%d\n", __func__, rc);
+
+   tpm_buf_destroy();
+   return rc;
  }
  
  void tpm2_flush_space(struct tpm_chip *chip)

@@ -311,8 +335,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct 
tpm_space *space, u8 *cmd,
   sizeof(space->context_tbl));
memcpy(>work_space.session_tbl, >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->context_size);
+   memcpy(chip->work_space.session_buf, space->session_buf,
+  space->session_size);
  
  	rc = tpm2_load_space(chip);

if (rc) {
@@ -492,7 +518,8 @@ static int tpm2_save_space(struct tpm_chip *chip)
continue;
  
  		rc = tpm2_save_context(chip, space->context_tbl[i],

-  

Re: [PATCH] tpm: tpm2-space: Resize session and context buffers dynamically

2020-06-24 Thread Jarkko Sakkinen
On Thu, Jun 25, 2020 at 07:24:20AM +0300, Jarkko Sakkinen wrote:
> Re-allocate context and session buffers when needed. Scale them in page
> increments so that the reallocation is only seldomly required, and thus
> causes minimal stress to the system. Add a static maximum limit of four
> pages for buffer sizes.
> 
> Cc: James Bottomley 
> Suggested-by: Stefan Berger 
> Signed-off-by: Jarkko Sakkinen 

I'd actually consider

#define TPM2_SPACE_DEFAULT_BUFFER_SIZE  PAGE_SIZE
#define TPM2_SPACE_MAX_BUFFER_SIZE  (4 * PAGE_SIZE)

/JQ4KKO


[PATCH] tpm: tpm2-space: Resize session and context buffers dynamically

2020-06-24 Thread Jarkko Sakkinen
Re-allocate context and session buffers when needed. Scale them in page
increments so that the reallocation is only seldomly required, and thus
causes minimal stress to the system. Add a static maximum limit of four
pages for buffer sizes.

Cc: James Bottomley 
Suggested-by: Stefan Berger 
Signed-off-by: Jarkko Sakkinen 
---
Tested only for compilation.
 drivers/char/tpm/tpm2-space.c | 80 ---
 include/linux/tpm.h   |  6 ++-
 2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 982d341d8837..acb9e82bf9e8 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -15,6 +15,8 @@
 #include 
 #include "tpm.h"
 
+#define TPM2_SPACE_MAX_BUFFER_SIZE (4 * PAGE_SIZE)
+
 enum tpm2_handle_types {
TPM2_HT_HMAC_SESSION= 0x0200,
TPM2_HT_POLICY_SESSION  = 0x0300,
@@ -47,9 +49,12 @@ int tpm2_init_space(struct tpm_space *space)
space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (space->session_buf == NULL) {
kfree(space->context_buf);
+   space->context_buf = NULL;
return -ENOMEM;
}
 
+   space->context_size = PAGE_SIZE;
+   space->session_size = PAGE_SIZE;
return 0;
 }
 
@@ -116,11 +121,13 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 
*buf,
return 0;
 }
 
-static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
-unsigned int buf_size, unsigned int *offset)
+static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 **buf,
+unsigned int *buf_size, unsigned int *offset)
 {
-   struct tpm_buf tbuf;
+   unsigned int new_buf_size;
unsigned int body_size;
+   struct tpm_buf tbuf;
+   void *new_buf;
int rc;
 
rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
@@ -131,31 +138,48 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 
handle, u8 *buf,
 
rc = tpm_transmit_cmd(chip, , 0, NULL);
if (rc < 0) {
-   dev_warn(>dev, "%s: failed with a system error %d\n",
-__func__, rc);
-   tpm_buf_destroy();
-   return -EFAULT;
+   rc = -EFAULT;
+   goto err;
} else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
-   tpm_buf_destroy();
-   return -ENOENT;
+   rc = -ENOENT;
+   goto out;
} else if (rc) {
-   dev_warn(>dev, "%s: failed with a TPM error 0x%04X\n",
-__func__, rc);
-   tpm_buf_destroy();
-   return -EFAULT;
+   rc = -EFAULT;
+   goto err;
}
 
body_size = tpm_buf_length() - TPM_HEADER_SIZE;
-   if ((*offset + body_size) > buf_size) {
-   dev_warn(>dev, "%s: out of backing storage\n", __func__);
-   tpm_buf_destroy();
-   return -ENOMEM;
+   /* We grow the buffer in page increments. */
+   new_buf_size = PFN_UP(*offset + body_size);
+
+   if (new_buf_size > TPM2_SPACE_MAX_BUFFER_SIZE) {
+   rc = -ENOMEM;
+   goto err;
}
 
-   memcpy([*offset], [TPM_HEADER_SIZE], body_size);
+   if (new_buf_size > *buf_size) {
+   new_buf = krealloc(*buf, new_buf_size, GFP_KERNEL);
+   if (!new_buf) {
+   rc = -ENOMEM;
+   goto err;
+   }
+
+   *buf = new_buf;
+   *buf_size = new_buf_size;
+   }
+
+   memcpy(*buf + *offset, [TPM_HEADER_SIZE], body_size);
*offset += body_size;
+
+out:
tpm_buf_destroy();
-   return 0;
+   return rc;
+
+err:
+   dev_warn(>dev, "%s: ret=%d\n", __func__, rc);
+
+   tpm_buf_destroy();
+   return rc;
 }
 
 void tpm2_flush_space(struct tpm_chip *chip)
@@ -311,8 +335,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct 
tpm_space *space, u8 *cmd,
   sizeof(space->context_tbl));
memcpy(>work_space.session_tbl, >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->context_size);
+   memcpy(chip->work_space.session_buf, space->session_buf,
+  space->session_size);
 
rc = tpm2_load_space(chip);
if (rc) {
@@ -492,7 +518,8 @@ static int tpm2_save_space(struct tpm_chip *chip)
continue;
 
rc = tpm2_save_context(chip, space->context_tbl[i],
-  space->context_buf, PAGE_SIZE,
+  >context_buf,
+