All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v3 0/5] RFC: in-kernel resource manager
@ 2017-01-16 13:12 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Jason Gunthorpe, open list

This patch set adds support for TPM spaces that provide a context
for isolating and swapping transient objects. This patch set does
not yet include support for isolating policy and HMAC sessions but
it is trivial to add once the basic approach is settled (and that's
why I created an RFC patch set).

There's a test script for trying out TPM spaces in

  git://git.infradead.org/users/jjs/tpm2-scripts.git

A simple smoke test can be run by

  sudo python -m unittest -v tpm2_smoke.SpaceTest   

v2:
Changed to James' proposal of API. I did not make any other changes
except split core TPM space code its own patch because I want to find
consensus on the API before polishing the corners. Thus, this version
also carries the RFC tag. I have not yet locked in my standpoint whether
ioctl or a device file is a better deal.

v3:
- Check TPM return code in tpm_map_response.
- Reference tracking for /dev/tpms0.
- clear_bit(is_open) was removed from tpm-dev.c. Added it back.
- Use response length as the buffer size limit in tpm2_commit_space.
- This version now passes again my smoke tests.

James Bottomley (2):
  tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c
  tpm2: expose resource manager via a device link /dev/tpms<n>

Jarkko Sakkinen (3):
  tpm: validate TPM 2.0 commands
  tpm: export tpm2_flush_context_cmd
  tpm: infrastructure for TPM spaces

 drivers/char/tpm/Makefile         |   2 +-
 drivers/char/tpm/tpm-chip.c       |  79 +++++++++-
 drivers/char/tpm/tpm-dev-common.c | 145 ++++++++++++++++++
 drivers/char/tpm/tpm-dev.c        | 140 ++---------------
 drivers/char/tpm/tpm-dev.h        |  27 ++++
 drivers/char/tpm/tpm-interface.c  | 100 +++++++++----
 drivers/char/tpm/tpm-sysfs.c      |   2 +-
 drivers/char/tpm/tpm.h            |  56 +++++--
 drivers/char/tpm/tpm2-cmd.c       | 146 ++++++++++++------
 drivers/char/tpm/tpm2-space.c     | 305 ++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpms-dev.c       |  62 ++++++++
 11 files changed, 852 insertions(+), 212 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-dev-common.c
 create mode 100644 drivers/char/tpm/tpm-dev.h
 create mode 100644 drivers/char/tpm/tpm2-space.c
 create mode 100644 drivers/char/tpm/tpms-dev.c

-- 
2.9.3

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 0/5] RFC: in-kernel resource manager
@ 2017-01-16 13:12 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Jason Gunthorpe, open list

This patch set adds support for TPM spaces that provide a context
for isolating and swapping transient objects. This patch set does
not yet include support for isolating policy and HMAC sessions but
it is trivial to add once the basic approach is settled (and that's
why I created an RFC patch set).

There's a test script for trying out TPM spaces in

  git://git.infradead.org/users/jjs/tpm2-scripts.git

A simple smoke test can be run by

  sudo python -m unittest -v tpm2_smoke.SpaceTest   

v2:
Changed to James' proposal of API. I did not make any other changes
except split core TPM space code its own patch because I want to find
consensus on the API before polishing the corners. Thus, this version
also carries the RFC tag. I have not yet locked in my standpoint whether
ioctl or a device file is a better deal.

v3:
- Check TPM return code in tpm_map_response.
- Reference tracking for /dev/tpms0.
- clear_bit(is_open) was removed from tpm-dev.c. Added it back.
- Use response length as the buffer size limit in tpm2_commit_space.
- This version now passes again my smoke tests.

James Bottomley (2):
  tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c
  tpm2: expose resource manager via a device link /dev/tpms<n>

Jarkko Sakkinen (3):
  tpm: validate TPM 2.0 commands
  tpm: export tpm2_flush_context_cmd
  tpm: infrastructure for TPM spaces

 drivers/char/tpm/Makefile         |   2 +-
 drivers/char/tpm/tpm-chip.c       |  79 +++++++++-
 drivers/char/tpm/tpm-dev-common.c | 145 ++++++++++++++++++
 drivers/char/tpm/tpm-dev.c        | 140 ++---------------
 drivers/char/tpm/tpm-dev.h        |  27 ++++
 drivers/char/tpm/tpm-interface.c  | 100 +++++++++----
 drivers/char/tpm/tpm-sysfs.c      |   2 +-
 drivers/char/tpm/tpm.h            |  56 +++++--
 drivers/char/tpm/tpm2-cmd.c       | 146 ++++++++++++------
 drivers/char/tpm/tpm2-space.c     | 305 ++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpms-dev.c       |  62 ++++++++
 11 files changed, 852 insertions(+), 212 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-dev-common.c
 create mode 100644 drivers/char/tpm/tpm-dev.h
 create mode 100644 drivers/char/tpm/tpm2-space.c
 create mode 100644 drivers/char/tpm/tpms-dev.c

-- 
2.9.3


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 1/5] tpm: validate TPM 2.0 commands
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, open list

Check for every TPM 2.0 command that the command code is supported and
the command buffer has at least the length that can contain the header
and the handle area.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm-interface.c | 32 ++++++++++++++++++++++++-
 drivers/char/tpm/tpm.h           | 27 +++++++++++++++++----
 drivers/char/tpm/tpm2-cmd.c      | 51 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 403d332..fe863f2 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -328,6 +328,36 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
 }
 EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
 
+static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
+				 size_t len)
+{
+	const struct tpm_input_header *header = (const void *)cmd;
+	u32 cc;
+	size_t len_min = TPM_HEADER_SIZE;
+	u32 attrs;
+
+	if ((len >= len_min) && (chip->flags & TPM_CHIP_FLAG_TPM2) &&
+	    chip->nr_commands) {
+		cc = be32_to_cpu(header->ordinal);
+		if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+			dev_dbg(&chip->dev, "0x%04x is an invalid command\n",
+				cc);
+			return false;
+		}
+		len_min +=
+			4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0));
+	}
+
+	if (len < len_min) {
+		dev_dbg(&chip->dev,
+			"%s: insufficient command length %zu < %zu\n",
+			__func__, len, len_min);
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * tmp_transmit - Internal kernel interface to transmit TPM commands.
  *
@@ -347,7 +377,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	u32 count, ordinal;
 	unsigned long stop;
 
-	if (bufsiz < TPM_HEADER_SIZE)
+	if (!tpm_validate_command(chip, buf, bufsiz))
 		return -EINVAL;
 
 	if (bufsiz > TPM_BUFSIZE)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9e81865..52d805f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -127,7 +127,12 @@ enum tpm2_permanent_handles {
 };
 
 enum tpm2_capabilities {
-	TPM2_CAP_TPM_PROPERTIES = 6,
+	TPM2_CAP_COMMANDS	= 2,
+	TPM2_CAP_TPM_PROPERTIES	= 6,
+};
+
+enum tpm2_properties {
+	TPM_PT_TOTAL_COMMANDS	= 0x0129,
 };
 
 enum tpm2_startup_types {
@@ -135,6 +140,11 @@ enum tpm2_startup_types {
 	TPM2_SU_STATE	= 0x0001,
 };
 
+enum tpm2_cc_attrs {
+	TPM2_CC_ATTR_CHANDLES	= 25,
+	TPM2_CC_ATTR_RHANDLE	= 28,
+};
+
 #define TPM_VID_INTEL    0x8086
 #define TPM_VID_WINBOND  0x1050
 #define TPM_VID_STM      0x104A
@@ -191,6 +201,9 @@ struct tpm_chip {
 	acpi_handle acpi_dev_handle;
 	char ppi_version[TPM_PPI_VERSION_LEN + 1];
 #endif /* CONFIG_ACPI */
+
+	u32 nr_commands;
+	u32 *cc_attrs_tbl;
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -393,7 +406,8 @@ struct tpm_cmd_t {
  */
 
 enum tpm_buf_flags {
-	TPM_BUF_OVERFLOW	= BIT(0),
+	TPM_BUF_INITIALIZED	= BIT(0),
+	TPM_BUF_OVERFLOW	= BIT(1),
 };
 
 struct tpm_buf {
@@ -419,13 +433,17 @@ static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
 	head->length = cpu_to_be32(sizeof(*head));
 	head->ordinal = cpu_to_be32(ordinal);
 
+	buf->flags = TPM_BUF_INITIALIZED;
+
 	return 0;
 }
 
 static inline void tpm_buf_destroy(struct tpm_buf *buf)
 {
-	kunmap(buf->data_page);
-	__free_page(buf->data_page);
+	if (buf->flags & TPM_BUF_INITIALIZED) {
+		kunmap(buf->data_page);
+		__free_page(buf->data_page);
+	}
 }
 
 static inline u32 tpm_buf_length(struct tpm_buf *buf)
@@ -546,4 +564,5 @@ int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm2_probe(struct tpm_chip *chip);
+bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs);
 #endif
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 201538e..3dce7b7 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1005,7 +1005,10 @@ EXPORT_SYMBOL_GPL(tpm2_probe);
  */
 int tpm2_auto_startup(struct tpm_chip *chip)
 {
+	struct tpm_buf buf;
+	u32 nr_commands;
 	int rc;
+	int i;
 
 	rc = tpm_get_timeouts(chip);
 	if (rc)
@@ -1029,8 +1032,56 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 		}
 	}
 
+	rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
+	if (rc)
+		goto out;
+
+	chip->cc_attrs_tbl = devm_kzalloc(&chip->dev, 4 * nr_commands,
+					  GFP_KERNEL);
+
+	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+	if (rc)
+		goto out;
+
+	tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS);
+	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
+	tpm_buf_append_u32(&buf, nr_commands);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, NULL);
+	if (rc < 0) {
+		tpm_buf_destroy(&buf);
+		goto out;
+	}
+
+	if (nr_commands !=
+	    be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
+		tpm_buf_destroy(&buf);
+		goto out;
+	}
+
+	for (i = 0; i < nr_commands; i++)
+		chip->cc_attrs_tbl[i] = be32_to_cpup(
+			(u32 *)&buf.data[TPM_HEADER_SIZE + 9 + 4 * i]);
+
+	chip->nr_commands = nr_commands;
+	tpm_buf_destroy(&buf);
+
 out:
 	if (rc > 0)
 		rc = -ENODEV;
 	return rc;
 }
+
+bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs)
+{
+	int i;
+
+	for (i = 0; i < chip->nr_commands; i++) {
+		if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0))) {
+			*attrs = chip->cc_attrs_tbl[i];
+			return true;
+		}
+	}
+
+	return false;
+}
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 1/5] tpm: validate TPM 2.0 commands
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: open list, linux-security-module-u79uwXL29TY76Z2rM5mHXA

Check for every TPM 2.0 command that the command code is supported and
the command buffer has at least the length that can contain the header
and the handle area.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/char/tpm/tpm-interface.c | 32 ++++++++++++++++++++++++-
 drivers/char/tpm/tpm.h           | 27 +++++++++++++++++----
 drivers/char/tpm/tpm2-cmd.c      | 51 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 403d332..fe863f2 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -328,6 +328,36 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
 }
 EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
 
+static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
+				 size_t len)
+{
+	const struct tpm_input_header *header = (const void *)cmd;
+	u32 cc;
+	size_t len_min = TPM_HEADER_SIZE;
+	u32 attrs;
+
+	if ((len >= len_min) && (chip->flags & TPM_CHIP_FLAG_TPM2) &&
+	    chip->nr_commands) {
+		cc = be32_to_cpu(header->ordinal);
+		if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+			dev_dbg(&chip->dev, "0x%04x is an invalid command\n",
+				cc);
+			return false;
+		}
+		len_min +=
+			4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0));
+	}
+
+	if (len < len_min) {
+		dev_dbg(&chip->dev,
+			"%s: insufficient command length %zu < %zu\n",
+			__func__, len, len_min);
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * tmp_transmit - Internal kernel interface to transmit TPM commands.
  *
@@ -347,7 +377,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	u32 count, ordinal;
 	unsigned long stop;
 
-	if (bufsiz < TPM_HEADER_SIZE)
+	if (!tpm_validate_command(chip, buf, bufsiz))
 		return -EINVAL;
 
 	if (bufsiz > TPM_BUFSIZE)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9e81865..52d805f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -127,7 +127,12 @@ enum tpm2_permanent_handles {
 };
 
 enum tpm2_capabilities {
-	TPM2_CAP_TPM_PROPERTIES = 6,
+	TPM2_CAP_COMMANDS	= 2,
+	TPM2_CAP_TPM_PROPERTIES	= 6,
+};
+
+enum tpm2_properties {
+	TPM_PT_TOTAL_COMMANDS	= 0x0129,
 };
 
 enum tpm2_startup_types {
@@ -135,6 +140,11 @@ enum tpm2_startup_types {
 	TPM2_SU_STATE	= 0x0001,
 };
 
+enum tpm2_cc_attrs {
+	TPM2_CC_ATTR_CHANDLES	= 25,
+	TPM2_CC_ATTR_RHANDLE	= 28,
+};
+
 #define TPM_VID_INTEL    0x8086
 #define TPM_VID_WINBOND  0x1050
 #define TPM_VID_STM      0x104A
@@ -191,6 +201,9 @@ struct tpm_chip {
 	acpi_handle acpi_dev_handle;
 	char ppi_version[TPM_PPI_VERSION_LEN + 1];
 #endif /* CONFIG_ACPI */
+
+	u32 nr_commands;
+	u32 *cc_attrs_tbl;
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -393,7 +406,8 @@ struct tpm_cmd_t {
  */
 
 enum tpm_buf_flags {
-	TPM_BUF_OVERFLOW	= BIT(0),
+	TPM_BUF_INITIALIZED	= BIT(0),
+	TPM_BUF_OVERFLOW	= BIT(1),
 };
 
 struct tpm_buf {
@@ -419,13 +433,17 @@ static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
 	head->length = cpu_to_be32(sizeof(*head));
 	head->ordinal = cpu_to_be32(ordinal);
 
+	buf->flags = TPM_BUF_INITIALIZED;
+
 	return 0;
 }
 
 static inline void tpm_buf_destroy(struct tpm_buf *buf)
 {
-	kunmap(buf->data_page);
-	__free_page(buf->data_page);
+	if (buf->flags & TPM_BUF_INITIALIZED) {
+		kunmap(buf->data_page);
+		__free_page(buf->data_page);
+	}
 }
 
 static inline u32 tpm_buf_length(struct tpm_buf *buf)
@@ -546,4 +564,5 @@ int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm2_probe(struct tpm_chip *chip);
+bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs);
 #endif
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 201538e..3dce7b7 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1005,7 +1005,10 @@ EXPORT_SYMBOL_GPL(tpm2_probe);
  */
 int tpm2_auto_startup(struct tpm_chip *chip)
 {
+	struct tpm_buf buf;
+	u32 nr_commands;
 	int rc;
+	int i;
 
 	rc = tpm_get_timeouts(chip);
 	if (rc)
@@ -1029,8 +1032,56 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 		}
 	}
 
+	rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL);
+	if (rc)
+		goto out;
+
+	chip->cc_attrs_tbl = devm_kzalloc(&chip->dev, 4 * nr_commands,
+					  GFP_KERNEL);
+
+	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+	if (rc)
+		goto out;
+
+	tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS);
+	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
+	tpm_buf_append_u32(&buf, nr_commands);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, NULL);
+	if (rc < 0) {
+		tpm_buf_destroy(&buf);
+		goto out;
+	}
+
+	if (nr_commands !=
+	    be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
+		tpm_buf_destroy(&buf);
+		goto out;
+	}
+
+	for (i = 0; i < nr_commands; i++)
+		chip->cc_attrs_tbl[i] = be32_to_cpup(
+			(u32 *)&buf.data[TPM_HEADER_SIZE + 9 + 4 * i]);
+
+	chip->nr_commands = nr_commands;
+	tpm_buf_destroy(&buf);
+
 out:
 	if (rc > 0)
 		rc = -ENODEV;
 	return rc;
 }
+
+bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs)
+{
+	int i;
+
+	for (i = 0; i < chip->nr_commands; i++) {
+		if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0))) {
+			*attrs = chip->cc_attrs_tbl[i];
+			return true;
+		}
+	}
+
+	return false;
+}
-- 
2.9.3


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 2/5] tpm: export tpm2_flush_context_cmd
  2017-01-16 13:12 ` Jarkko Sakkinen
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  -1 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, open list

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm.h      |  2 ++
 drivers/char/tpm/tpm2-cmd.c | 67 ++++++++++++++++++++++-----------------------
 2 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 52d805f..2661c26 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -551,6 +551,8 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
+			    unsigned int flags);
 int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3dce7b7..fd73e2a 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -415,6 +415,38 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = {
 };
 
 /**
+ * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
+ * @chip: TPM chip to use
+ * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
+ *
+ * Return: same as with tpm_transmit_cmd
+ */
+void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
+			    unsigned int flags)
+{
+	struct tpm_buf buf;
+	int rc;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+	if (rc) {
+		dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
+			 handle);
+		return;
+	}
+
+	tpm_buf_append_u32(&buf, handle);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, flags,
+			     "flushing context");
+	if (rc)
+		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
+			 rc);
+
+	tpm_buf_destroy(&buf);
+}
+
+/**
  * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
  *
  * @buf: an allocated tpm_buf instance
@@ -625,39 +657,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 }
 
 /**
- * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
- *
- * @chip: TPM chip to use
- * @handle: the key data in clear and encrypted form
- * @flags: tpm transmit flags
- *
- * Return: Same as with tpm_transmit_cmd.
- */
-static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
-				   unsigned int flags)
-{
-	struct tpm_buf buf;
-	int rc;
-
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
-	if (rc) {
-		dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
-			 handle);
-		return;
-	}
-
-	tpm_buf_append_u32(&buf, handle);
-
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
-			      flags, "flushing context");
-	if (rc)
-		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
-			 rc);
-
-	tpm_buf_destroy(&buf);
-}
-
-/**
  * tpm2_unseal_cmd() - execute a TPM2_Unload command
  *
  * @chip: TPM chip to use
@@ -1047,7 +1046,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
 	tpm_buf_append_u32(&buf, nr_commands);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, NULL);
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, 0, NULL);
 	if (rc < 0) {
 		tpm_buf_destroy(&buf);
 		goto out;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 2/5] tpm: export tpm2_flush_context_cmd
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, open list

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm.h      |  2 ++
 drivers/char/tpm/tpm2-cmd.c | 67 ++++++++++++++++++++++-----------------------
 2 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 52d805f..2661c26 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -551,6 +551,8 @@ static inline void tpm_add_ppi(struct tpm_chip *chip)
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
 int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
+			    unsigned int flags);
 int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3dce7b7..fd73e2a 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -415,6 +415,38 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = {
 };
 
 /**
+ * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
+ * @chip: TPM chip to use
+ * @payload: the key data in clear and encrypted form
+ * @options: authentication values and other options
+ *
+ * Return: same as with tpm_transmit_cmd
+ */
+void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
+			    unsigned int flags)
+{
+	struct tpm_buf buf;
+	int rc;
+
+	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+	if (rc) {
+		dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
+			 handle);
+		return;
+	}
+
+	tpm_buf_append_u32(&buf, handle);
+
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, flags,
+			     "flushing context");
+	if (rc)
+		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
+			 rc);
+
+	tpm_buf_destroy(&buf);
+}
+
+/**
  * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
  *
  * @buf: an allocated tpm_buf instance
@@ -625,39 +657,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 }
 
 /**
- * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
- *
- * @chip: TPM chip to use
- * @handle: the key data in clear and encrypted form
- * @flags: tpm transmit flags
- *
- * Return: Same as with tpm_transmit_cmd.
- */
-static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
-				   unsigned int flags)
-{
-	struct tpm_buf buf;
-	int rc;
-
-	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
-	if (rc) {
-		dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
-			 handle);
-		return;
-	}
-
-	tpm_buf_append_u32(&buf, handle);
-
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
-			      flags, "flushing context");
-	if (rc)
-		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
-			 rc);
-
-	tpm_buf_destroy(&buf);
-}
-
-/**
  * tpm2_unseal_cmd() - execute a TPM2_Unload command
  *
  * @chip: TPM chip to use
@@ -1047,7 +1046,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
 	tpm_buf_append_u32(&buf, nr_commands);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, NULL);
+	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, 0, NULL);
 	if (rc < 0) {
 		tpm_buf_destroy(&buf);
 		goto out;
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 3/5] tpm: infrastructure for TPM spaces
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, Jarkko Sakkinen, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, open list

Added ability to tpm_transmit() to supply a TPM space that contains
mapping from virtual handles to physical handles and backing storage for
swapping transient objects. TPM space is isolated from other users of
the TPM.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/Makefile        |   2 +-
 drivers/char/tpm/tpm-chip.c      |   7 +
 drivers/char/tpm/tpm-dev.c       |   2 +-
 drivers/char/tpm/tpm-interface.c |  55 ++++---
 drivers/char/tpm/tpm-sysfs.c     |   2 +-
 drivers/char/tpm/tpm.h           |  21 ++-
 drivers/char/tpm/tpm2-cmd.c      |  36 ++---
 drivers/char/tpm/tpm2-space.c    | 305 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 385 insertions(+), 45 deletions(-)
 create mode 100644 drivers/char/tpm/tpm2-space.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index a05b1eb..251d0ed 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-		tpm_eventlog.o
+	 tpm_eventlog.o tpm2-space.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index c406343..993b9ae 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -128,6 +128,7 @@ static void tpm_dev_release(struct device *dev)
 	mutex_unlock(&idr_lock);
 
 	kfree(chip->log.bios_event_log);
+	kfree(chip->work_space.context_buf);
 	kfree(chip);
 }
 
@@ -189,6 +190,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	chip->cdev.owner = THIS_MODULE;
 	chip->cdev.kobj.parent = &chip->dev.kobj;
 
+	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!chip->work_space.context_buf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
 	return chip;
 
 out:
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 912ad30..249eeb0 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -144,7 +144,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
 		mutex_unlock(&priv->buffer_mutex);
 		return -EPIPE;
 	}
-	out_size = tpm_transmit(priv->chip, priv->data_buffer,
+	out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
 				sizeof(priv->data_buffer), 0);
 
 	tpm_put_ops(priv->chip);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index fe863f2..ae85aab 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -370,10 +370,11 @@ static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
  *     0 when the operation is successful.
  *     A negative number for system errors (errno).
  */
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
-		     unsigned int flags)
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+		     u8 *buf, size_t bufsiz, unsigned int flags)
 {
-	ssize_t rc;
+	int rc;
+	ssize_t len = 0;
 	u32 count, ordinal;
 	unsigned long stop;
 
@@ -399,10 +400,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	if (chip->dev.parent)
 		pm_runtime_get_sync(chip->dev.parent);
 
+	rc = tpm2_prepare_space(chip, space, ordinal, buf, bufsiz);
+	if (rc)
+		goto out;
+
 	rc = chip->ops->send(chip, (u8 *) buf, count);
 	if (rc < 0) {
 		dev_err(&chip->dev,
-			"tpm_transmit: tpm_send: error %zd\n", rc);
+			"tpm_transmit: tpm_send: error %d\n", rc);
 		goto out;
 	}
 
@@ -435,17 +440,23 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	goto out;
 
 out_recv:
-	rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
-	if (rc < 0)
+	len = chip->ops->recv(chip, (u8 *) buf, bufsiz);
+	if (len < 0) {
 		dev_err(&chip->dev,
-			"tpm_transmit: tpm_recv: error %zd\n", rc);
+			"tpm_transmit: tpm_recv: error %d\n", rc);
+		rc = len;
+		goto out;
+	}
+
+	rc = tpm2_commit_space(chip, space, ordinal, buf, len);
+
 out:
 	if (chip->dev.parent)
 		pm_runtime_put_sync(chip->dev.parent);
 
 	if (!(flags & TPM_TRANSMIT_UNLOCKED))
 		mutex_unlock(&chip->tpm_mutex);
-	return rc;
+	return rc ? rc : len;
 }
 
 /**
@@ -463,14 +474,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
  *     A negative number for system errors (errno).
  *     A positive number for a TPM error.
  */
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd,
-			 size_t len, size_t min_rx_length,
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+			 const void *cmd, size_t len, size_t min_rx_length,
 			 unsigned int flags, const char *desc)
 {
 	const struct tpm_output_header *header;
 	int err;
 
-	len = tpm_transmit(chip, (const u8 *)cmd, len, flags);
+	len = tpm_transmit(chip, space, (void *)cmd, len, flags);
 	if (len <  0)
 		return len;
 	else if (len < TPM_HEADER_SIZE)
@@ -525,9 +536,8 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
 	}
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
 			      TPM_HEADER_SIZE + min_cap_length, 0, desc);
-
 	if (!rc)
 		*cap = tpm_cmd.params.getcap_out.cap;
 	return rc;
@@ -550,7 +560,8 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
 	start_cmd.header.in = tpm_startup_header;
 
 	start_cmd.params.startup_in.startup_type = startup_type;
-	return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
+	return tpm_transmit_cmd(chip, NULL, &start_cmd,
+				TPM_INTERNAL_RESULT_SIZE,
 				TPM_HEADER_SIZE, 0,
 				"attempting to start the TPM");
 }
@@ -696,7 +707,7 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
 	struct tpm_cmd_t cmd;
 
 	cmd.header.in = continue_selftest_header;
-	rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
 			      CONTINUE_SELFTEST_RESULT_SIZE,
 			      0, "continue selftest");
 	return rc;
@@ -717,7 +728,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 
 	cmd.header.in = pcrread_header;
 	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-	rc = tpm_transmit_cmd(chip, &cmd,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd,
 			      READ_PCR_RESULT_SIZE,
 			      READ_PCR_RESULT_SIZE, 0,
 			      "attempting to read a pcr value");
@@ -816,7 +827,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
 	cmd.header.in = pcrextend_header;
 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
-	rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
 			      EXTEND_PCR_RESULT_SIZE, 0,
 			      "attempting extend a PCR value");
 
@@ -921,7 +932,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
 	if (chip == NULL)
 		return -ENODEV;
 
-	rc = tpm_transmit_cmd(chip, cmd, buflen, TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, TPM_HEADER_SIZE,
 			      0, "attempting tpm_cmd");
 
 	tpm_put_ops(chip);
@@ -1024,15 +1035,15 @@ int tpm_pm_suspend(struct device *dev)
 		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
 		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
 		       TPM_DIGEST_SIZE);
-		rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
-				     EXTEND_PCR_RESULT_SIZE, 0,
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
+				      EXTEND_PCR_RESULT_SIZE, 0,
 				      "extending dummy pcr before suspend");
 	}
 
 	/* now do the actual savestate */
 	for (try = 0; try < TPM_RETRY; try++) {
 		cmd.header.in = savestate_header;
-		rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE,
 				      SAVESTATE_RESULT_SIZE, 0, NULL);
 
 		/*
@@ -1116,7 +1127,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 		tpm_cmd.header.in = tpm_getrandom_header;
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &tpm_cmd,
+		err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
 				       TPM_GETRANDOM_RESULT_SIZE + num_bytes,
 				       offsetof(struct tpm_cmd_t,
 				                params.getrandom_out.rng_data),
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index bd0134d..40608105 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -39,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
 	struct tpm_chip *chip = to_tpm_chip(dev);
 
 	tpm_cmd.header.in = tpm_readpubek_header;
-	err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+	err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
 	                       TPM_HEADER_SIZE + 28 + 256,
 			       0, "attempting to read the PUBEK");
 	if (err)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2661c26..45d997f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -90,7 +90,9 @@ enum tpm2_structures {
 };
 
 enum tpm2_return_codes {
+	TPM2_RC_SUCCESS		= 0x0000,
 	TPM2_RC_HASH		= 0x0083, /* RC_FMT1 */
+	TPM2_RC_HANDLE		= 0x008B,
 	TPM2_RC_INITIALIZE	= 0x0100, /* RC_VER1 */
 	TPM2_RC_DISABLED	= 0x0120,
 	TPM2_RC_TESTING		= 0x090A, /* RC_WARN */
@@ -114,6 +116,8 @@ enum tpm2_command_codes {
 	TPM2_CC_CREATE		= 0x0153,
 	TPM2_CC_LOAD		= 0x0157,
 	TPM2_CC_UNSEAL		= 0x015E,
+	TPM2_CC_CONTEXT_LOAD	= 0x0161,
+	TPM2_CC_CONTEXT_SAVE	= 0x0162,
 	TPM2_CC_FLUSH_CONTEXT	= 0x0165,
 	TPM2_CC_GET_CAPABILITY	= 0x017A,
 	TPM2_CC_GET_RANDOM	= 0x017B,
@@ -151,6 +155,11 @@ enum tpm2_cc_attrs {
 
 #define TPM_PPI_VERSION_LEN		3
 
+struct tpm_space {
+	u32 context_tbl[14];
+	u8 *context_buf;
+};
+
 enum tpm_chip_flags {
 	TPM_CHIP_FLAG_TPM2		= BIT(1),
 	TPM_CHIP_FLAG_IRQ		= BIT(2),
@@ -202,6 +211,7 @@ struct tpm_chip {
 	char ppi_version[TPM_PPI_VERSION_LEN + 1];
 #endif /* CONFIG_ACPI */
 
+	struct tpm_space work_space;
 	u32 nr_commands;
 	u32 *cc_attrs_tbl;
 };
@@ -509,9 +519,10 @@ enum tpm_transmit_flags {
 	TPM_TRANSMIT_UNLOCKED	= BIT(0),
 };
 
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
-		     unsigned int flags);
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, size_t len,
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+		     u8 *buf, size_t bufsiz, unsigned int flags);
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+			 const void *cmd, size_t len,
 			 size_t min_tx_length, unsigned int flags,
 			 const char *desc);
 ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
@@ -567,4 +578,8 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm2_probe(struct tpm_chip *chip);
 bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs);
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
+		       u32 cc, u8 *buf, size_t bufsiz);
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+		      u32 cc, u8 *buf, size_t bufsiz);
 #endif
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index fd73e2a..e1c1bbd 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -284,8 +284,9 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 	       sizeof(cmd.params.pcrread_in.pcr_select));
 	cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM2_PCR_READ_OUT_SIZE,
-			      0, "attempting to read a pcr value");
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
+			      TPM2_PCR_READ_OUT_SIZE, 0,
+			      "attempting to read a pcr value");
 	if (rc == 0) {
 		buf = cmd.params.pcrread_out.digest;
 		memcpy(res_buf, buf, TPM_DIGEST_SIZE);
@@ -331,7 +332,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
 	cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
 	memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE, 0,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE, 0,
 			      "attempting extend a PCR value");
 
 	return rc;
@@ -377,7 +378,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 		cmd.header.in = tpm2_getrandom_header;
 		cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+		err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
 				       offsetof(struct tpm2_cmd,
 				                params.getrandom_out.buffer),
 				       0, "attempting get random");
@@ -437,8 +438,8 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
 
 	tpm_buf_append_u32(&buf, handle);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, flags,
-			     "flushing context");
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
+			      flags, "flushing context");
 	if (rc)
 		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
 			 rc);
@@ -556,7 +557,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 	                      TPM_HEADER_SIZE + 4,
 			      0, "sealing data");
 	if (rc)
@@ -641,7 +642,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 			      TPM_HEADER_SIZE + 4, flags, "loading blob");
 	if (!rc)
 		*blob_handle = be32_to_cpup(
@@ -693,7 +694,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 			     options->blobauth /* hmac */,
 			     TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 			      TPM_HEADER_SIZE + 4 + 2, flags, "unsealing");
 	if (rc > 0)
 		rc = -EPERM;
@@ -770,7 +771,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
 			      TPM2_GET_TPM_PT_OUT_SIZE, 0, desc);
 	if (!rc)
 		*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
@@ -805,7 +806,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
 	cmd.header.in = tpm2_startup_header;
 
 	cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
-	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 				0, "attempting to start the TPM");
 }
 
@@ -834,7 +835,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
 	cmd.header.in = tpm2_shutdown_header;
 	cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 			      0, "stopping the TPM");
 
 	/* In places where shutdown command is sent there's no much we can do
@@ -898,7 +899,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
 	cmd.header.in = tpm2_selftest_header;
 	cmd.params.selftest_in.full_test = full;
 
-	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
 			      TPM_HEADER_SIZE, 0, "continue selftest");
 
 	/* At least some prototype chips seem to give RC_TESTING error
@@ -949,8 +950,8 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
 		cmd.params.pcrread_in.pcr_select[1] = 0x00;
 		cmd.params.pcrread_in.pcr_select[2] = 0x00;
 
-		rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
-				      0, NULL);
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
+				      TPM_HEADER_SIZE, 0, NULL);
 		if (rc < 0)
 			break;
 
@@ -983,7 +984,7 @@ int tpm2_probe(struct tpm_chip *chip)
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 			      0, NULL);
 	if (rc <  0)
 		return rc;
@@ -1046,7 +1047,8 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
 	tpm_buf_append_u32(&buf, nr_commands);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, 0, NULL);
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
+			      0, NULL);
 	if (rc < 0) {
 		tpm_buf_destroy(&buf);
 		goto out;
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
new file mode 100644
index 0000000..3708e70
--- /dev/null
+++ b/drivers/char/tpm/tpm2-space.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Authors:
+ * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * This file contains TPM2 protocol implementations of the commands
+ * used by the kernel internally.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gfp.h>
+#include <asm/unaligned.h>
+#include "tpm.h"
+
+enum tpm2_handle_types {
+	TPM2_HT_HMAC_SESSION	= 0x02000000,
+	TPM2_HT_POLICY_SESSION	= 0x03000000,
+	TPM2_HT_TRANSIENT	= 0x80000000,
+};
+
+static void tpm2_flush_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
+		if (space->context_tbl[i] && ~space->context_tbl[i])
+			tpm2_flush_context_cmd(chip, space->context_tbl[i],
+					       TPM_TRANSMIT_UNLOCKED);
+}
+
+struct tpm2_context {
+	__be64 sequence;
+	__be32 saved_handle;
+	__be32 hierarchy;
+	__be16 blob_size;
+} __packed;
+
+static int tpm2_load_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	struct tpm2_context *ctx;
+	struct tpm_buf buf;
+	int i;
+	int j;
+	int rc;
+	u32 s;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (!space->context_tbl[i])
+			continue;
+
+		/* sanity check, should never happen */
+		if (~space->context_tbl[i]) {
+			dev_err(&chip->dev, "context table is inconsistent");
+			return -EFAULT;
+		}
+
+		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+				 TPM2_CC_CONTEXT_LOAD);
+		if (rc)
+			return rc;
+
+		ctx = (struct tpm2_context *)&space->context_buf[j];
+		s = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
+		tpm_buf_append(&buf, &space->context_buf[j], s);
+
+		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+				      TPM_HEADER_SIZE + 4,
+				      TPM_TRANSMIT_UNLOCKED, NULL);
+		if (rc) {
+			dev_warn(&chip->dev, "%s: loading failed with %d\n",
+				 __func__, rc);
+			rc = -EFAULT;
+			goto out_err;
+		}
+
+		space->context_tbl[i] =
+			be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE]);
+
+		j += s;
+
+		tpm_buf_destroy(&buf);
+	}
+
+	return 0;
+
+out_err:
+	tpm_buf_destroy(&buf);
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd, size_t len)
+{
+	struct tpm_space *space = &chip->work_space;
+	unsigned int nr_handles;
+	u32 vhandle;
+	u32 phandle;
+	u32 attrs;
+	int i;
+	int j;
+	int rc;
+
+	if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+		rc = -EINVAL;
+		goto out_err;
+	}
+
+	nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
+
+	for (i = 0; i < nr_handles; i++) {
+		vhandle = be32_to_cpup((__be32 *)&cmd[TPM_HEADER_SIZE + 4 * i]);
+		if ((vhandle & 0xFF000000) != TPM2_HT_TRANSIENT)
+			continue;
+
+		j = 0xFFFFFF - (vhandle & 0xFFFFFF);
+		if (j > ARRAY_SIZE(space->context_tbl) ||
+		    !space->context_tbl[j]) {
+			rc = -EINVAL;
+			goto out_err;
+		}
+
+		phandle = space->context_tbl[j];
+		*((__be32 *)&cmd[TPM_HEADER_SIZE + 4 * i]) =
+			cpu_to_be32(phandle);
+	}
+
+	return 0;
+
+out_err:
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
+		       u32 cc, u8 *buf, size_t bufsiz)
+{
+	int rc;
+
+	if (!space)
+		return 0;
+
+	memcpy(&chip->work_space.context_tbl, &space->context_tbl,
+	       sizeof(space->context_tbl));
+	memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
+
+	rc = tpm2_load_space(chip);
+	if (rc)
+		return rc;
+
+	rc = tpm2_map_command(chip, cc, buf, bufsiz);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int tpm2_map_response(struct tpm_chip *chip, u32 cc, u8 *rsp, size_t len)
+{
+	struct tpm_space *space = &chip->work_space;
+	u32 phandle;
+	u32 vhandle;
+	u32 attrs;
+	u32 return_code = get_unaligned_be32((__be32 *)&rsp[6]);
+	int i;
+	int rc;
+
+	if (return_code != TPM2_RC_SUCCESS)
+		return 0;
+
+	if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+		/* should never happen */
+		dev_err(&chip->dev, "TPM returned a different CC: 0x%04x\n",
+			cc);
+		rc = -EFAULT;
+		goto out_err;
+	}
+
+	if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1))
+		return 0;
+
+	phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]);
+	if ((phandle & 0xFF000000) != TPM2_HT_TRANSIENT)
+		return 0;
+
+	/* Garbage collect a dead context. */
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (space->context_tbl[i] == phandle) {
+			space->context_tbl[i] = 0;
+			break;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
+		if (!space->context_tbl[i])
+			break;
+
+	if (i == ARRAY_SIZE(space->context_tbl)) {
+		dev_warn(&chip->dev, "%s: out of context slots\n", __func__);
+		tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED);
+		rc = -ENOMEM;
+		goto out_err;
+	}
+
+	space->context_tbl[i] = phandle;
+	vhandle = TPM2_HT_TRANSIENT | (0xFFFFFF - i);
+	*(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle);
+
+	return 0;
+
+out_err:
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+static int tpm2_save_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	struct tpm_buf buf;
+	int i;
+	int j;
+	int rc;
+	u32 s;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (!(space->context_tbl[i] && ~space->context_tbl[i]))
+			continue;
+
+		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+				  TPM2_CC_CONTEXT_SAVE);
+		if (rc)
+			return rc;
+
+		tpm_buf_append_u32(&buf, space->context_tbl[i]);
+
+		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+				      TPM_HEADER_SIZE, TPM_TRANSMIT_UNLOCKED,
+				      NULL);
+		if ((rc & TPM2_RC_HANDLE) == TPM2_RC_HANDLE) {
+			space->context_tbl[i] = 0;
+			continue;
+		} else if (rc) {
+			dev_warn(&chip->dev, "%s: saving failed with %d\n",
+				 __func__, rc);
+			rc = -EFAULT;
+			goto out_err;
+		}
+
+		s = tpm_buf_length(&buf) - TPM_HEADER_SIZE;
+		if ((j + s) > PAGE_SIZE) {
+			dev_warn(&chip->dev, "%s: out of backing storage\n",
+				 __func__);
+			rc = -ENOMEM;
+			goto out_err;
+		}
+
+		memcpy(&space->context_buf[j], &buf.data[TPM_HEADER_SIZE], s);
+
+		tpm2_flush_context_cmd(chip, space->context_tbl[i],
+				       TPM_TRANSMIT_UNLOCKED);
+
+		space->context_tbl[i] = ~0;
+
+		j += s;
+
+		tpm_buf_destroy(&buf);
+	}
+
+	return 0;
+out_err:
+	tpm_buf_destroy(&buf);
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+		      u32 cc, u8 *buf, size_t bufsiz)
+{
+	int rc;
+
+	if (!space)
+		return 0;
+
+	rc = tpm2_map_response(chip, cc, buf, bufsiz);
+	if (rc)
+		return rc;
+
+	rc = tpm2_save_space(chip);
+	if (rc)
+		return rc;
+
+	memcpy(&space->context_tbl, &chip->work_space.context_tbl,
+	       sizeof(space->context_tbl));
+	memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
+
+	return 0;
+}
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 3/5] tpm: infrastructure for TPM spaces
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: open list, linux-security-module-u79uwXL29TY76Z2rM5mHXA

Added ability to tpm_transmit() to supply a TPM space that contains
mapping from virtual handles to physical handles and backing storage for
swapping transient objects. TPM space is isolated from other users of
the TPM.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/char/tpm/Makefile        |   2 +-
 drivers/char/tpm/tpm-chip.c      |   7 +
 drivers/char/tpm/tpm-dev.c       |   2 +-
 drivers/char/tpm/tpm-interface.c |  55 ++++---
 drivers/char/tpm/tpm-sysfs.c     |   2 +-
 drivers/char/tpm/tpm.h           |  21 ++-
 drivers/char/tpm/tpm2-cmd.c      |  36 ++---
 drivers/char/tpm/tpm2-space.c    | 305 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 385 insertions(+), 45 deletions(-)
 create mode 100644 drivers/char/tpm/tpm2-space.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index a05b1eb..251d0ed 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-		tpm_eventlog.o
+	 tpm_eventlog.o tpm2-space.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index c406343..993b9ae 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -128,6 +128,7 @@ static void tpm_dev_release(struct device *dev)
 	mutex_unlock(&idr_lock);
 
 	kfree(chip->log.bios_event_log);
+	kfree(chip->work_space.context_buf);
 	kfree(chip);
 }
 
@@ -189,6 +190,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	chip->cdev.owner = THIS_MODULE;
 	chip->cdev.kobj.parent = &chip->dev.kobj;
 
+	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!chip->work_space.context_buf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
 	return chip;
 
 out:
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 912ad30..249eeb0 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -144,7 +144,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
 		mutex_unlock(&priv->buffer_mutex);
 		return -EPIPE;
 	}
-	out_size = tpm_transmit(priv->chip, priv->data_buffer,
+	out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
 				sizeof(priv->data_buffer), 0);
 
 	tpm_put_ops(priv->chip);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index fe863f2..ae85aab 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -370,10 +370,11 @@ static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
  *     0 when the operation is successful.
  *     A negative number for system errors (errno).
  */
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
-		     unsigned int flags)
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+		     u8 *buf, size_t bufsiz, unsigned int flags)
 {
-	ssize_t rc;
+	int rc;
+	ssize_t len = 0;
 	u32 count, ordinal;
 	unsigned long stop;
 
@@ -399,10 +400,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	if (chip->dev.parent)
 		pm_runtime_get_sync(chip->dev.parent);
 
+	rc = tpm2_prepare_space(chip, space, ordinal, buf, bufsiz);
+	if (rc)
+		goto out;
+
 	rc = chip->ops->send(chip, (u8 *) buf, count);
 	if (rc < 0) {
 		dev_err(&chip->dev,
-			"tpm_transmit: tpm_send: error %zd\n", rc);
+			"tpm_transmit: tpm_send: error %d\n", rc);
 		goto out;
 	}
 
@@ -435,17 +440,23 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
 	goto out;
 
 out_recv:
-	rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
-	if (rc < 0)
+	len = chip->ops->recv(chip, (u8 *) buf, bufsiz);
+	if (len < 0) {
 		dev_err(&chip->dev,
-			"tpm_transmit: tpm_recv: error %zd\n", rc);
+			"tpm_transmit: tpm_recv: error %d\n", rc);
+		rc = len;
+		goto out;
+	}
+
+	rc = tpm2_commit_space(chip, space, ordinal, buf, len);
+
 out:
 	if (chip->dev.parent)
 		pm_runtime_put_sync(chip->dev.parent);
 
 	if (!(flags & TPM_TRANSMIT_UNLOCKED))
 		mutex_unlock(&chip->tpm_mutex);
-	return rc;
+	return rc ? rc : len;
 }
 
 /**
@@ -463,14 +474,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
  *     A negative number for system errors (errno).
  *     A positive number for a TPM error.
  */
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd,
-			 size_t len, size_t min_rx_length,
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+			 const void *cmd, size_t len, size_t min_rx_length,
 			 unsigned int flags, const char *desc)
 {
 	const struct tpm_output_header *header;
 	int err;
 
-	len = tpm_transmit(chip, (const u8 *)cmd, len, flags);
+	len = tpm_transmit(chip, space, (void *)cmd, len, flags);
 	if (len <  0)
 		return len;
 	else if (len < TPM_HEADER_SIZE)
@@ -525,9 +536,8 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
 		tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
 	}
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
 			      TPM_HEADER_SIZE + min_cap_length, 0, desc);
-
 	if (!rc)
 		*cap = tpm_cmd.params.getcap_out.cap;
 	return rc;
@@ -550,7 +560,8 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
 	start_cmd.header.in = tpm_startup_header;
 
 	start_cmd.params.startup_in.startup_type = startup_type;
-	return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
+	return tpm_transmit_cmd(chip, NULL, &start_cmd,
+				TPM_INTERNAL_RESULT_SIZE,
 				TPM_HEADER_SIZE, 0,
 				"attempting to start the TPM");
 }
@@ -696,7 +707,7 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
 	struct tpm_cmd_t cmd;
 
 	cmd.header.in = continue_selftest_header;
-	rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
 			      CONTINUE_SELFTEST_RESULT_SIZE,
 			      0, "continue selftest");
 	return rc;
@@ -717,7 +728,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 
 	cmd.header.in = pcrread_header;
 	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
-	rc = tpm_transmit_cmd(chip, &cmd,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd,
 			      READ_PCR_RESULT_SIZE,
 			      READ_PCR_RESULT_SIZE, 0,
 			      "attempting to read a pcr value");
@@ -816,7 +827,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
 	cmd.header.in = pcrextend_header;
 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
-	rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
 			      EXTEND_PCR_RESULT_SIZE, 0,
 			      "attempting extend a PCR value");
 
@@ -921,7 +932,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
 	if (chip == NULL)
 		return -ENODEV;
 
-	rc = tpm_transmit_cmd(chip, cmd, buflen, TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, TPM_HEADER_SIZE,
 			      0, "attempting tpm_cmd");
 
 	tpm_put_ops(chip);
@@ -1024,15 +1035,15 @@ int tpm_pm_suspend(struct device *dev)
 		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
 		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
 		       TPM_DIGEST_SIZE);
-		rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
-				     EXTEND_PCR_RESULT_SIZE, 0,
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
+				      EXTEND_PCR_RESULT_SIZE, 0,
 				      "extending dummy pcr before suspend");
 	}
 
 	/* now do the actual savestate */
 	for (try = 0; try < TPM_RETRY; try++) {
 		cmd.header.in = savestate_header;
-		rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE,
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE,
 				      SAVESTATE_RESULT_SIZE, 0, NULL);
 
 		/*
@@ -1116,7 +1127,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 		tpm_cmd.header.in = tpm_getrandom_header;
 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &tpm_cmd,
+		err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
 				       TPM_GETRANDOM_RESULT_SIZE + num_bytes,
 				       offsetof(struct tpm_cmd_t,
 				                params.getrandom_out.rng_data),
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index bd0134d..40608105 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -39,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
 	struct tpm_chip *chip = to_tpm_chip(dev);
 
 	tpm_cmd.header.in = tpm_readpubek_header;
-	err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+	err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
 	                       TPM_HEADER_SIZE + 28 + 256,
 			       0, "attempting to read the PUBEK");
 	if (err)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2661c26..45d997f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -90,7 +90,9 @@ enum tpm2_structures {
 };
 
 enum tpm2_return_codes {
+	TPM2_RC_SUCCESS		= 0x0000,
 	TPM2_RC_HASH		= 0x0083, /* RC_FMT1 */
+	TPM2_RC_HANDLE		= 0x008B,
 	TPM2_RC_INITIALIZE	= 0x0100, /* RC_VER1 */
 	TPM2_RC_DISABLED	= 0x0120,
 	TPM2_RC_TESTING		= 0x090A, /* RC_WARN */
@@ -114,6 +116,8 @@ enum tpm2_command_codes {
 	TPM2_CC_CREATE		= 0x0153,
 	TPM2_CC_LOAD		= 0x0157,
 	TPM2_CC_UNSEAL		= 0x015E,
+	TPM2_CC_CONTEXT_LOAD	= 0x0161,
+	TPM2_CC_CONTEXT_SAVE	= 0x0162,
 	TPM2_CC_FLUSH_CONTEXT	= 0x0165,
 	TPM2_CC_GET_CAPABILITY	= 0x017A,
 	TPM2_CC_GET_RANDOM	= 0x017B,
@@ -151,6 +155,11 @@ enum tpm2_cc_attrs {
 
 #define TPM_PPI_VERSION_LEN		3
 
+struct tpm_space {
+	u32 context_tbl[14];
+	u8 *context_buf;
+};
+
 enum tpm_chip_flags {
 	TPM_CHIP_FLAG_TPM2		= BIT(1),
 	TPM_CHIP_FLAG_IRQ		= BIT(2),
@@ -202,6 +211,7 @@ struct tpm_chip {
 	char ppi_version[TPM_PPI_VERSION_LEN + 1];
 #endif /* CONFIG_ACPI */
 
+	struct tpm_space work_space;
 	u32 nr_commands;
 	u32 *cc_attrs_tbl;
 };
@@ -509,9 +519,10 @@ enum tpm_transmit_flags {
 	TPM_TRANSMIT_UNLOCKED	= BIT(0),
 };
 
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
-		     unsigned int flags);
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, size_t len,
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+		     u8 *buf, size_t bufsiz, unsigned int flags);
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+			 const void *cmd, size_t len,
 			 size_t min_tx_length, unsigned int flags,
 			 const char *desc);
 ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
@@ -567,4 +578,8 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm2_probe(struct tpm_chip *chip);
 bool tpm2_find_cc_attrs(struct tpm_chip *chip, u32 cc, u32 *attrs);
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
+		       u32 cc, u8 *buf, size_t bufsiz);
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+		      u32 cc, u8 *buf, size_t bufsiz);
 #endif
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index fd73e2a..e1c1bbd 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -284,8 +284,9 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 	       sizeof(cmd.params.pcrread_in.pcr_select));
 	cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM2_PCR_READ_OUT_SIZE,
-			      0, "attempting to read a pcr value");
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
+			      TPM2_PCR_READ_OUT_SIZE, 0,
+			      "attempting to read a pcr value");
 	if (rc == 0) {
 		buf = cmd.params.pcrread_out.digest;
 		memcpy(res_buf, buf, TPM_DIGEST_SIZE);
@@ -331,7 +332,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
 	cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
 	memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE, 0,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE, 0,
 			      "attempting extend a PCR value");
 
 	return rc;
@@ -377,7 +378,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
 		cmd.header.in = tpm2_getrandom_header;
 		cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
 
-		err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+		err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
 				       offsetof(struct tpm2_cmd,
 				                params.getrandom_out.buffer),
 				       0, "attempting get random");
@@ -437,8 +438,8 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
 
 	tpm_buf_append_u32(&buf, handle);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, flags,
-			     "flushing context");
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
+			      flags, "flushing context");
 	if (rc)
 		dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
 			 rc);
@@ -556,7 +557,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 	                      TPM_HEADER_SIZE + 4,
 			      0, "sealing data");
 	if (rc)
@@ -641,7 +642,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 		goto out;
 	}
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 			      TPM_HEADER_SIZE + 4, flags, "loading blob");
 	if (!rc)
 		*blob_handle = be32_to_cpup(
@@ -693,7 +694,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 			     options->blobauth /* hmac */,
 			     TPM_DIGEST_SIZE);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
 			      TPM_HEADER_SIZE + 4 + 2, flags, "unsealing");
 	if (rc > 0)
 		rc = -EPERM;
@@ -770,7 +771,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
 			      TPM2_GET_TPM_PT_OUT_SIZE, 0, desc);
 	if (!rc)
 		*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
@@ -805,7 +806,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
 	cmd.header.in = tpm2_startup_header;
 
 	cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
-	return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 				0, "attempting to start the TPM");
 }
 
@@ -834,7 +835,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
 	cmd.header.in = tpm2_shutdown_header;
 	cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 			      0, "stopping the TPM");
 
 	/* In places where shutdown command is sent there's no much we can do
@@ -898,7 +899,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
 	cmd.header.in = tpm2_selftest_header;
 	cmd.params.selftest_in.full_test = full;
 
-	rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
 			      TPM_HEADER_SIZE, 0, "continue selftest");
 
 	/* At least some prototype chips seem to give RC_TESTING error
@@ -949,8 +950,8 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
 		cmd.params.pcrread_in.pcr_select[1] = 0x00;
 		cmd.params.pcrread_in.pcr_select[2] = 0x00;
 
-		rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
-				      0, NULL);
+		rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
+				      TPM_HEADER_SIZE, 0, NULL);
 		if (rc < 0)
 			break;
 
@@ -983,7 +984,7 @@ int tpm2_probe(struct tpm_chip *chip)
 	cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
 	cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
 
-	rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), TPM_HEADER_SIZE,
 			      0, NULL);
 	if (rc <  0)
 		return rc;
@@ -1046,7 +1047,8 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 	tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
 	tpm_buf_append_u32(&buf, nr_commands);
 
-	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, TPM_HEADER_SIZE, 0, NULL);
+	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, TPM_HEADER_SIZE,
+			      0, NULL);
 	if (rc < 0) {
 		tpm_buf_destroy(&buf);
 		goto out;
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
new file mode 100644
index 0000000..3708e70
--- /dev/null
+++ b/drivers/char/tpm/tpm2-space.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Authors:
+ * Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
+ *
+ * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+ *
+ * This file contains TPM2 protocol implementations of the commands
+ * used by the kernel internally.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gfp.h>
+#include <asm/unaligned.h>
+#include "tpm.h"
+
+enum tpm2_handle_types {
+	TPM2_HT_HMAC_SESSION	= 0x02000000,
+	TPM2_HT_POLICY_SESSION	= 0x03000000,
+	TPM2_HT_TRANSIENT	= 0x80000000,
+};
+
+static void tpm2_flush_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
+		if (space->context_tbl[i] && ~space->context_tbl[i])
+			tpm2_flush_context_cmd(chip, space->context_tbl[i],
+					       TPM_TRANSMIT_UNLOCKED);
+}
+
+struct tpm2_context {
+	__be64 sequence;
+	__be32 saved_handle;
+	__be32 hierarchy;
+	__be16 blob_size;
+} __packed;
+
+static int tpm2_load_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	struct tpm2_context *ctx;
+	struct tpm_buf buf;
+	int i;
+	int j;
+	int rc;
+	u32 s;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (!space->context_tbl[i])
+			continue;
+
+		/* sanity check, should never happen */
+		if (~space->context_tbl[i]) {
+			dev_err(&chip->dev, "context table is inconsistent");
+			return -EFAULT;
+		}
+
+		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+				 TPM2_CC_CONTEXT_LOAD);
+		if (rc)
+			return rc;
+
+		ctx = (struct tpm2_context *)&space->context_buf[j];
+		s = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
+		tpm_buf_append(&buf, &space->context_buf[j], s);
+
+		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+				      TPM_HEADER_SIZE + 4,
+				      TPM_TRANSMIT_UNLOCKED, NULL);
+		if (rc) {
+			dev_warn(&chip->dev, "%s: loading failed with %d\n",
+				 __func__, rc);
+			rc = -EFAULT;
+			goto out_err;
+		}
+
+		space->context_tbl[i] =
+			be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE]);
+
+		j += s;
+
+		tpm_buf_destroy(&buf);
+	}
+
+	return 0;
+
+out_err:
+	tpm_buf_destroy(&buf);
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd, size_t len)
+{
+	struct tpm_space *space = &chip->work_space;
+	unsigned int nr_handles;
+	u32 vhandle;
+	u32 phandle;
+	u32 attrs;
+	int i;
+	int j;
+	int rc;
+
+	if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+		rc = -EINVAL;
+		goto out_err;
+	}
+
+	nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
+
+	for (i = 0; i < nr_handles; i++) {
+		vhandle = be32_to_cpup((__be32 *)&cmd[TPM_HEADER_SIZE + 4 * i]);
+		if ((vhandle & 0xFF000000) != TPM2_HT_TRANSIENT)
+			continue;
+
+		j = 0xFFFFFF - (vhandle & 0xFFFFFF);
+		if (j > ARRAY_SIZE(space->context_tbl) ||
+		    !space->context_tbl[j]) {
+			rc = -EINVAL;
+			goto out_err;
+		}
+
+		phandle = space->context_tbl[j];
+		*((__be32 *)&cmd[TPM_HEADER_SIZE + 4 * i]) =
+			cpu_to_be32(phandle);
+	}
+
+	return 0;
+
+out_err:
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
+		       u32 cc, u8 *buf, size_t bufsiz)
+{
+	int rc;
+
+	if (!space)
+		return 0;
+
+	memcpy(&chip->work_space.context_tbl, &space->context_tbl,
+	       sizeof(space->context_tbl));
+	memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
+
+	rc = tpm2_load_space(chip);
+	if (rc)
+		return rc;
+
+	rc = tpm2_map_command(chip, cc, buf, bufsiz);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int tpm2_map_response(struct tpm_chip *chip, u32 cc, u8 *rsp, size_t len)
+{
+	struct tpm_space *space = &chip->work_space;
+	u32 phandle;
+	u32 vhandle;
+	u32 attrs;
+	u32 return_code = get_unaligned_be32((__be32 *)&rsp[6]);
+	int i;
+	int rc;
+
+	if (return_code != TPM2_RC_SUCCESS)
+		return 0;
+
+	if (!tpm2_find_cc_attrs(chip, cc, &attrs)) {
+		/* should never happen */
+		dev_err(&chip->dev, "TPM returned a different CC: 0x%04x\n",
+			cc);
+		rc = -EFAULT;
+		goto out_err;
+	}
+
+	if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1))
+		return 0;
+
+	phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]);
+	if ((phandle & 0xFF000000) != TPM2_HT_TRANSIENT)
+		return 0;
+
+	/* Garbage collect a dead context. */
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (space->context_tbl[i] == phandle) {
+			space->context_tbl[i] = 0;
+			break;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
+		if (!space->context_tbl[i])
+			break;
+
+	if (i == ARRAY_SIZE(space->context_tbl)) {
+		dev_warn(&chip->dev, "%s: out of context slots\n", __func__);
+		tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED);
+		rc = -ENOMEM;
+		goto out_err;
+	}
+
+	space->context_tbl[i] = phandle;
+	vhandle = TPM2_HT_TRANSIENT | (0xFFFFFF - i);
+	*(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle);
+
+	return 0;
+
+out_err:
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+static int tpm2_save_space(struct tpm_chip *chip)
+{
+	struct tpm_space *space = &chip->work_space;
+	struct tpm_buf buf;
+	int i;
+	int j;
+	int rc;
+	u32 s;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+		if (!(space->context_tbl[i] && ~space->context_tbl[i]))
+			continue;
+
+		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+				  TPM2_CC_CONTEXT_SAVE);
+		if (rc)
+			return rc;
+
+		tpm_buf_append_u32(&buf, space->context_tbl[i]);
+
+		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+				      TPM_HEADER_SIZE, TPM_TRANSMIT_UNLOCKED,
+				      NULL);
+		if ((rc & TPM2_RC_HANDLE) == TPM2_RC_HANDLE) {
+			space->context_tbl[i] = 0;
+			continue;
+		} else if (rc) {
+			dev_warn(&chip->dev, "%s: saving failed with %d\n",
+				 __func__, rc);
+			rc = -EFAULT;
+			goto out_err;
+		}
+
+		s = tpm_buf_length(&buf) - TPM_HEADER_SIZE;
+		if ((j + s) > PAGE_SIZE) {
+			dev_warn(&chip->dev, "%s: out of backing storage\n",
+				 __func__);
+			rc = -ENOMEM;
+			goto out_err;
+		}
+
+		memcpy(&space->context_buf[j], &buf.data[TPM_HEADER_SIZE], s);
+
+		tpm2_flush_context_cmd(chip, space->context_tbl[i],
+				       TPM_TRANSMIT_UNLOCKED);
+
+		space->context_tbl[i] = ~0;
+
+		j += s;
+
+		tpm_buf_destroy(&buf);
+	}
+
+	return 0;
+out_err:
+	tpm_buf_destroy(&buf);
+	tpm2_flush_space(chip);
+	return rc;
+}
+
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+		      u32 cc, u8 *buf, size_t bufsiz)
+{
+	int rc;
+
+	if (!space)
+		return 0;
+
+	rc = tpm2_map_response(chip, cc, buf, bufsiz);
+	if (rc)
+		return rc;
+
+	rc = tpm2_save_space(chip);
+	if (rc)
+		return rc;
+
+	memcpy(&space->context_tbl, &chip->work_space.context_tbl,
+	       sizeof(space->context_tbl));
+	memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
+
+	return 0;
+}
-- 
2.9.3


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 4/5] tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c
  2017-01-16 13:12 ` Jarkko Sakkinen
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  -1 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe, open list

From: James Bottomley <James.Bottomley@HansenPartnership.com>

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 drivers/char/tpm/Makefile         |   2 +-
 drivers/char/tpm/tpm-dev-common.c | 145 ++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm-dev.c        | 140 ++++--------------------------------
 drivers/char/tpm/tpm-dev.h        |  27 +++++++
 4 files changed, 187 insertions(+), 127 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-dev-common.c
 create mode 100644 drivers/char/tpm/tpm-dev.h

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 251d0ed..13ff5da 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-	 tpm_eventlog.o tpm2-space.o
+	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c
new file mode 100644
index 0000000..0156562
--- /dev/null
+++ b/drivers/char/tpm/tpm-dev-common.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Copyright (C) 2013 Obsidian Research Corp
+ * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+ *
+ * Device file system interface to the TPM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "tpm.h"
+#include "tpm-dev.h"
+
+static void user_reader_timeout(unsigned long ptr)
+{
+	struct file_priv *priv = (struct file_priv *)ptr;
+
+	schedule_work(&priv->work);
+}
+
+static void timeout_work(struct work_struct *work)
+{
+	struct file_priv *priv = container_of(work, struct file_priv, work);
+
+	mutex_lock(&priv->buffer_mutex);
+	atomic_set(&priv->data_pending, 0);
+	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
+	mutex_unlock(&priv->buffer_mutex);
+}
+
+void tpm_common_open(struct file *file, struct tpm_chip *chip,
+		     struct file_priv *priv)
+{
+	priv->chip = chip;
+	atomic_set(&priv->data_pending, 0);
+	mutex_init(&priv->buffer_mutex);
+	setup_timer(&priv->user_read_timer, user_reader_timeout,
+			(unsigned long)priv);
+	INIT_WORK(&priv->work, timeout_work);
+
+	file->private_data = priv;
+}
+
+ssize_t tpm_common_read(struct file *file, char __user *buf,
+			size_t size, loff_t *off)
+{
+	struct file_priv *priv = file->private_data;
+	ssize_t ret_size;
+	ssize_t orig_ret_size;
+	int rc;
+
+	del_singleshot_timer_sync(&priv->user_read_timer);
+	flush_work(&priv->work);
+	ret_size = atomic_read(&priv->data_pending);
+	if (ret_size > 0) {	/* relay data */
+		orig_ret_size = ret_size;
+		if (size < ret_size)
+			ret_size = size;
+
+		mutex_lock(&priv->buffer_mutex);
+		rc = copy_to_user(buf, priv->data_buffer, ret_size);
+		memset(priv->data_buffer, 0, orig_ret_size);
+		if (rc)
+			ret_size = -EFAULT;
+
+		mutex_unlock(&priv->buffer_mutex);
+	}
+
+	atomic_set(&priv->data_pending, 0);
+
+	return ret_size;
+}
+
+ssize_t tpm_common_write(struct file *file, const char __user *buf,
+			 size_t size, loff_t *off, struct tpm_space *space)
+{
+	struct file_priv *priv = file->private_data;
+	size_t in_size = size;
+	ssize_t out_size;
+
+	/* Cannot perform a write until the read has cleared either via
+	 * tpm_read or a user_read_timer timeout. This also prevents split
+	 * buffered writes from blocking here.
+	 */
+	if (atomic_read(&priv->data_pending) != 0)
+		return -EBUSY;
+
+	if (in_size > TPM_BUFSIZE)
+		return -E2BIG;
+
+	mutex_lock(&priv->buffer_mutex);
+
+	if (copy_from_user
+	    (priv->data_buffer, (void __user *) buf, in_size)) {
+		mutex_unlock(&priv->buffer_mutex);
+		return -EFAULT;
+	}
+
+	/* atomic tpm command send and result receive. We only hold the ops
+	 * lock during this period so that the tpm can be unregistered even if
+	 * the char dev is held open.
+	 */
+	if (tpm_try_get_ops(priv->chip)) {
+		mutex_unlock(&priv->buffer_mutex);
+		return -EPIPE;
+	}
+	out_size = tpm_transmit(priv->chip, space, priv->data_buffer,
+				sizeof(priv->data_buffer), 0);
+
+	tpm_put_ops(priv->chip);
+	if (out_size < 0) {
+		mutex_unlock(&priv->buffer_mutex);
+		return out_size;
+	}
+
+	atomic_set(&priv->data_pending, out_size);
+	mutex_unlock(&priv->buffer_mutex);
+
+	/* Set a timeout by which the reader must come claim the result */
+	mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));
+
+	return in_size;
+}
+
+/*
+ * Called on file close
+ */
+void tpm_common_release(struct file *file, struct file_priv *priv)
+{
+	del_singleshot_timer_sync(&priv->user_read_timer);
+	flush_work(&priv->work);
+	file->private_data = NULL;
+	atomic_set(&priv->data_pending, 0);
+}
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 249eeb0..ebd74ab 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -18,45 +18,15 @@
  *
  */
 #include <linux/slab.h>
-#include <linux/uaccess.h>
-#include "tpm.h"
-
-struct file_priv {
-	struct tpm_chip *chip;
-
-	/* Data passed to and from the tpm via the read/write calls */
-	atomic_t data_pending;
-	struct mutex buffer_mutex;
-
-	struct timer_list user_read_timer;      /* user needs to claim result */
-	struct work_struct work;
-
-	u8 data_buffer[TPM_BUFSIZE];
-};
-
-static void user_reader_timeout(unsigned long ptr)
-{
-	struct file_priv *priv = (struct file_priv *)ptr;
-
-	schedule_work(&priv->work);
-}
-
-static void timeout_work(struct work_struct *work)
-{
-	struct file_priv *priv = container_of(work, struct file_priv, work);
-
-	mutex_lock(&priv->buffer_mutex);
-	atomic_set(&priv->data_pending, 0);
-	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
-	mutex_unlock(&priv->buffer_mutex);
-}
+#include "tpm-dev.h"
 
 static int tpm_open(struct inode *inode, struct file *file)
 {
-	struct tpm_chip *chip =
-		container_of(inode->i_cdev, struct tpm_chip, cdev);
+	struct tpm_chip *chip;
 	struct file_priv *priv;
 
+	chip = container_of(inode->i_cdev, struct tpm_chip, cdev);
+
 	/* It's assured that the chip will be opened just once,
 	 * by the check of is_open variable, which is protected
 	 * by driver_lock. */
@@ -66,100 +36,22 @@ static int tpm_open(struct inode *inode, struct file *file)
 	}
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (priv == NULL) {
-		clear_bit(0, &chip->is_open);
-		return -ENOMEM;
-	}
+	if (priv == NULL)
+		goto out;
 
-	priv->chip = chip;
-	atomic_set(&priv->data_pending, 0);
-	mutex_init(&priv->buffer_mutex);
-	setup_timer(&priv->user_read_timer, user_reader_timeout,
-			(unsigned long)priv);
-	INIT_WORK(&priv->work, timeout_work);
+	tpm_common_open(file, chip, priv);
 
-	file->private_data = priv;
 	return 0;
-}
-
-static ssize_t tpm_read(struct file *file, char __user *buf,
-			size_t size, loff_t *off)
-{
-	struct file_priv *priv = file->private_data;
-	ssize_t ret_size;
-	int rc;
-
-	del_singleshot_timer_sync(&priv->user_read_timer);
-	flush_work(&priv->work);
-	ret_size = atomic_read(&priv->data_pending);
-	if (ret_size > 0) {	/* relay data */
-		ssize_t orig_ret_size = ret_size;
-		if (size < ret_size)
-			ret_size = size;
 
-		mutex_lock(&priv->buffer_mutex);
-		rc = copy_to_user(buf, priv->data_buffer, ret_size);
-		memset(priv->data_buffer, 0, orig_ret_size);
-		if (rc)
-			ret_size = -EFAULT;
-
-		mutex_unlock(&priv->buffer_mutex);
-	}
-
-	atomic_set(&priv->data_pending, 0);
-
-	return ret_size;
+ out:
+	clear_bit(0, &chip->is_open);
+	return -ENOMEM;
 }
 
 static ssize_t tpm_write(struct file *file, const char __user *buf,
 			 size_t size, loff_t *off)
 {
-	struct file_priv *priv = file->private_data;
-	size_t in_size = size;
-	ssize_t out_size;
-
-	/* cannot perform a write until the read has cleared
-	   either via tpm_read or a user_read_timer timeout.
-	   This also prevents splitted buffered writes from blocking here.
-	*/
-	if (atomic_read(&priv->data_pending) != 0)
-		return -EBUSY;
-
-	if (in_size > TPM_BUFSIZE)
-		return -E2BIG;
-
-	mutex_lock(&priv->buffer_mutex);
-
-	if (copy_from_user
-	    (priv->data_buffer, (void __user *) buf, in_size)) {
-		mutex_unlock(&priv->buffer_mutex);
-		return -EFAULT;
-	}
-
-	/* atomic tpm command send and result receive. We only hold the ops
-	 * lock during this period so that the tpm can be unregistered even if
-	 * the char dev is held open.
-	 */
-	if (tpm_try_get_ops(priv->chip)) {
-		mutex_unlock(&priv->buffer_mutex);
-		return -EPIPE;
-	}
-	out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
-				sizeof(priv->data_buffer), 0);
-
-	tpm_put_ops(priv->chip);
-	if (out_size < 0) {
-		mutex_unlock(&priv->buffer_mutex);
-		return out_size;
-	}
-
-	atomic_set(&priv->data_pending, out_size);
-	mutex_unlock(&priv->buffer_mutex);
-
-	/* Set a timeout by which the reader must come claim the result */
-	mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));
-
-	return in_size;
+	return tpm_common_write(file, buf, size, off, NULL);
 }
 
 /*
@@ -169,12 +61,10 @@ static int tpm_release(struct inode *inode, struct file *file)
 {
 	struct file_priv *priv = file->private_data;
 
-	del_singleshot_timer_sync(&priv->user_read_timer);
-	flush_work(&priv->work);
-	file->private_data = NULL;
-	atomic_set(&priv->data_pending, 0);
+	tpm_common_release(file, priv);
 	clear_bit(0, &priv->chip->is_open);
 	kfree(priv);
+
 	return 0;
 }
 
@@ -182,9 +72,7 @@ const struct file_operations tpm_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.open = tpm_open,
-	.read = tpm_read,
+	.read = tpm_common_read,
 	.write = tpm_write,
 	.release = tpm_release,
 };
-
-
diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h
new file mode 100644
index 0000000..ff15cf7
--- /dev/null
+++ b/drivers/char/tpm/tpm-dev.h
@@ -0,0 +1,27 @@
+#ifndef _TPM_DEV_H
+#define _TPM_DEV_H
+
+#include "tpm.h"
+
+struct file_priv {
+	struct tpm_chip *chip;
+
+	/* Data passed to and from the tpm via the read/write calls */
+	atomic_t data_pending;
+	struct mutex buffer_mutex;
+
+	struct timer_list user_read_timer;      /* user needs to claim result */
+	struct work_struct work;
+
+	u8 data_buffer[TPM_BUFSIZE];
+};
+
+void tpm_common_open(struct file *file, struct tpm_chip *chip,
+		     struct file_priv *priv);
+ssize_t tpm_common_read(struct file *file, char __user *buf,
+			size_t size, loff_t *off);
+ssize_t tpm_common_write(struct file *file, const char __user *buf,
+			 size_t size, loff_t *off, struct tpm_space *space);
+void tpm_common_release(struct file *file, struct file_priv *priv);
+
+#endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 4/5] tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe, open list

From: James Bottomley <James.Bottomley@HansenPartnership.com>

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 drivers/char/tpm/Makefile         |   2 +-
 drivers/char/tpm/tpm-dev-common.c | 145 ++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm-dev.c        | 140 ++++--------------------------------
 drivers/char/tpm/tpm-dev.h        |  27 +++++++
 4 files changed, 187 insertions(+), 127 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-dev-common.c
 create mode 100644 drivers/char/tpm/tpm-dev.h

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 251d0ed..13ff5da 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-	 tpm_eventlog.o tpm2-space.o
+	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c
new file mode 100644
index 0000000..0156562
--- /dev/null
+++ b/drivers/char/tpm/tpm-dev-common.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Copyright (C) 2013 Obsidian Research Corp
+ * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+ *
+ * Device file system interface to the TPM
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "tpm.h"
+#include "tpm-dev.h"
+
+static void user_reader_timeout(unsigned long ptr)
+{
+	struct file_priv *priv = (struct file_priv *)ptr;
+
+	schedule_work(&priv->work);
+}
+
+static void timeout_work(struct work_struct *work)
+{
+	struct file_priv *priv = container_of(work, struct file_priv, work);
+
+	mutex_lock(&priv->buffer_mutex);
+	atomic_set(&priv->data_pending, 0);
+	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
+	mutex_unlock(&priv->buffer_mutex);
+}
+
+void tpm_common_open(struct file *file, struct tpm_chip *chip,
+		     struct file_priv *priv)
+{
+	priv->chip = chip;
+	atomic_set(&priv->data_pending, 0);
+	mutex_init(&priv->buffer_mutex);
+	setup_timer(&priv->user_read_timer, user_reader_timeout,
+			(unsigned long)priv);
+	INIT_WORK(&priv->work, timeout_work);
+
+	file->private_data = priv;
+}
+
+ssize_t tpm_common_read(struct file *file, char __user *buf,
+			size_t size, loff_t *off)
+{
+	struct file_priv *priv = file->private_data;
+	ssize_t ret_size;
+	ssize_t orig_ret_size;
+	int rc;
+
+	del_singleshot_timer_sync(&priv->user_read_timer);
+	flush_work(&priv->work);
+	ret_size = atomic_read(&priv->data_pending);
+	if (ret_size > 0) {	/* relay data */
+		orig_ret_size = ret_size;
+		if (size < ret_size)
+			ret_size = size;
+
+		mutex_lock(&priv->buffer_mutex);
+		rc = copy_to_user(buf, priv->data_buffer, ret_size);
+		memset(priv->data_buffer, 0, orig_ret_size);
+		if (rc)
+			ret_size = -EFAULT;
+
+		mutex_unlock(&priv->buffer_mutex);
+	}
+
+	atomic_set(&priv->data_pending, 0);
+
+	return ret_size;
+}
+
+ssize_t tpm_common_write(struct file *file, const char __user *buf,
+			 size_t size, loff_t *off, struct tpm_space *space)
+{
+	struct file_priv *priv = file->private_data;
+	size_t in_size = size;
+	ssize_t out_size;
+
+	/* Cannot perform a write until the read has cleared either via
+	 * tpm_read or a user_read_timer timeout. This also prevents split
+	 * buffered writes from blocking here.
+	 */
+	if (atomic_read(&priv->data_pending) != 0)
+		return -EBUSY;
+
+	if (in_size > TPM_BUFSIZE)
+		return -E2BIG;
+
+	mutex_lock(&priv->buffer_mutex);
+
+	if (copy_from_user
+	    (priv->data_buffer, (void __user *) buf, in_size)) {
+		mutex_unlock(&priv->buffer_mutex);
+		return -EFAULT;
+	}
+
+	/* atomic tpm command send and result receive. We only hold the ops
+	 * lock during this period so that the tpm can be unregistered even if
+	 * the char dev is held open.
+	 */
+	if (tpm_try_get_ops(priv->chip)) {
+		mutex_unlock(&priv->buffer_mutex);
+		return -EPIPE;
+	}
+	out_size = tpm_transmit(priv->chip, space, priv->data_buffer,
+				sizeof(priv->data_buffer), 0);
+
+	tpm_put_ops(priv->chip);
+	if (out_size < 0) {
+		mutex_unlock(&priv->buffer_mutex);
+		return out_size;
+	}
+
+	atomic_set(&priv->data_pending, out_size);
+	mutex_unlock(&priv->buffer_mutex);
+
+	/* Set a timeout by which the reader must come claim the result */
+	mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));
+
+	return in_size;
+}
+
+/*
+ * Called on file close
+ */
+void tpm_common_release(struct file *file, struct file_priv *priv)
+{
+	del_singleshot_timer_sync(&priv->user_read_timer);
+	flush_work(&priv->work);
+	file->private_data = NULL;
+	atomic_set(&priv->data_pending, 0);
+}
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 249eeb0..ebd74ab 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -18,45 +18,15 @@
  *
  */
 #include <linux/slab.h>
-#include <linux/uaccess.h>
-#include "tpm.h"
-
-struct file_priv {
-	struct tpm_chip *chip;
-
-	/* Data passed to and from the tpm via the read/write calls */
-	atomic_t data_pending;
-	struct mutex buffer_mutex;
-
-	struct timer_list user_read_timer;      /* user needs to claim result */
-	struct work_struct work;
-
-	u8 data_buffer[TPM_BUFSIZE];
-};
-
-static void user_reader_timeout(unsigned long ptr)
-{
-	struct file_priv *priv = (struct file_priv *)ptr;
-
-	schedule_work(&priv->work);
-}
-
-static void timeout_work(struct work_struct *work)
-{
-	struct file_priv *priv = container_of(work, struct file_priv, work);
-
-	mutex_lock(&priv->buffer_mutex);
-	atomic_set(&priv->data_pending, 0);
-	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));
-	mutex_unlock(&priv->buffer_mutex);
-}
+#include "tpm-dev.h"
 
 static int tpm_open(struct inode *inode, struct file *file)
 {
-	struct tpm_chip *chip =
-		container_of(inode->i_cdev, struct tpm_chip, cdev);
+	struct tpm_chip *chip;
 	struct file_priv *priv;
 
+	chip = container_of(inode->i_cdev, struct tpm_chip, cdev);
+
 	/* It's assured that the chip will be opened just once,
 	 * by the check of is_open variable, which is protected
 	 * by driver_lock. */
@@ -66,100 +36,22 @@ static int tpm_open(struct inode *inode, struct file *file)
 	}
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (priv == NULL) {
-		clear_bit(0, &chip->is_open);
-		return -ENOMEM;
-	}
+	if (priv == NULL)
+		goto out;
 
-	priv->chip = chip;
-	atomic_set(&priv->data_pending, 0);
-	mutex_init(&priv->buffer_mutex);
-	setup_timer(&priv->user_read_timer, user_reader_timeout,
-			(unsigned long)priv);
-	INIT_WORK(&priv->work, timeout_work);
+	tpm_common_open(file, chip, priv);
 
-	file->private_data = priv;
 	return 0;
-}
-
-static ssize_t tpm_read(struct file *file, char __user *buf,
-			size_t size, loff_t *off)
-{
-	struct file_priv *priv = file->private_data;
-	ssize_t ret_size;
-	int rc;
-
-	del_singleshot_timer_sync(&priv->user_read_timer);
-	flush_work(&priv->work);
-	ret_size = atomic_read(&priv->data_pending);
-	if (ret_size > 0) {	/* relay data */
-		ssize_t orig_ret_size = ret_size;
-		if (size < ret_size)
-			ret_size = size;
 
-		mutex_lock(&priv->buffer_mutex);
-		rc = copy_to_user(buf, priv->data_buffer, ret_size);
-		memset(priv->data_buffer, 0, orig_ret_size);
-		if (rc)
-			ret_size = -EFAULT;
-
-		mutex_unlock(&priv->buffer_mutex);
-	}
-
-	atomic_set(&priv->data_pending, 0);
-
-	return ret_size;
+ out:
+	clear_bit(0, &chip->is_open);
+	return -ENOMEM;
 }
 
 static ssize_t tpm_write(struct file *file, const char __user *buf,
 			 size_t size, loff_t *off)
 {
-	struct file_priv *priv = file->private_data;
-	size_t in_size = size;
-	ssize_t out_size;
-
-	/* cannot perform a write until the read has cleared
-	   either via tpm_read or a user_read_timer timeout.
-	   This also prevents splitted buffered writes from blocking here.
-	*/
-	if (atomic_read(&priv->data_pending) != 0)
-		return -EBUSY;
-
-	if (in_size > TPM_BUFSIZE)
-		return -E2BIG;
-
-	mutex_lock(&priv->buffer_mutex);
-
-	if (copy_from_user
-	    (priv->data_buffer, (void __user *) buf, in_size)) {
-		mutex_unlock(&priv->buffer_mutex);
-		return -EFAULT;
-	}
-
-	/* atomic tpm command send and result receive. We only hold the ops
-	 * lock during this period so that the tpm can be unregistered even if
-	 * the char dev is held open.
-	 */
-	if (tpm_try_get_ops(priv->chip)) {
-		mutex_unlock(&priv->buffer_mutex);
-		return -EPIPE;
-	}
-	out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
-				sizeof(priv->data_buffer), 0);
-
-	tpm_put_ops(priv->chip);
-	if (out_size < 0) {
-		mutex_unlock(&priv->buffer_mutex);
-		return out_size;
-	}
-
-	atomic_set(&priv->data_pending, out_size);
-	mutex_unlock(&priv->buffer_mutex);
-
-	/* Set a timeout by which the reader must come claim the result */
-	mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));
-
-	return in_size;
+	return tpm_common_write(file, buf, size, off, NULL);
 }
 
 /*
@@ -169,12 +61,10 @@ static int tpm_release(struct inode *inode, struct file *file)
 {
 	struct file_priv *priv = file->private_data;
 
-	del_singleshot_timer_sync(&priv->user_read_timer);
-	flush_work(&priv->work);
-	file->private_data = NULL;
-	atomic_set(&priv->data_pending, 0);
+	tpm_common_release(file, priv);
 	clear_bit(0, &priv->chip->is_open);
 	kfree(priv);
+
 	return 0;
 }
 
@@ -182,9 +72,7 @@ const struct file_operations tpm_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.open = tpm_open,
-	.read = tpm_read,
+	.read = tpm_common_read,
 	.write = tpm_write,
 	.release = tpm_release,
 };
-
-
diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h
new file mode 100644
index 0000000..ff15cf7
--- /dev/null
+++ b/drivers/char/tpm/tpm-dev.h
@@ -0,0 +1,27 @@
+#ifndef _TPM_DEV_H
+#define _TPM_DEV_H
+
+#include "tpm.h"
+
+struct file_priv {
+	struct tpm_chip *chip;
+
+	/* Data passed to and from the tpm via the read/write calls */
+	atomic_t data_pending;
+	struct mutex buffer_mutex;
+
+	struct timer_list user_read_timer;      /* user needs to claim result */
+	struct work_struct work;
+
+	u8 data_buffer[TPM_BUFSIZE];
+};
+
+void tpm_common_open(struct file *file, struct tpm_chip *chip,
+		     struct file_priv *priv);
+ssize_t tpm_common_read(struct file *file, char __user *buf,
+			size_t size, loff_t *off);
+ssize_t tpm_common_write(struct file *file, const char __user *buf,
+			 size_t size, loff_t *off, struct tpm_space *space);
+void tpm_common_release(struct file *file, struct file_priv *priv);
+
+#endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, Jarkko Sakkinen, Jason Gunthorpe, open list

From: James Bottomley <James.Bottomley@HansenPartnership.com>

Currently the Resource Manager (RM) is not exposed to userspace.  Make
this exposure via a separate device, which can now be opened multiple
times because each read/write transaction goes separately via the RM.

Concurrency is protected by the chip->tpm_mutex for each read/write
transaction separately.  The TPM is cleared of all transient objects
by the time the mutex is dropped, so there should be no interference
between the kernel and userspace.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 drivers/char/tpm/Makefile        |  2 +-
 drivers/char/tpm/tpm-chip.c      | 72 ++++++++++++++++++++++++++++++++++++++--
 drivers/char/tpm/tpm-interface.c | 13 ++++++--
 drivers/char/tpm/tpm.h           |  6 ++--
 drivers/char/tpm/tpms-dev.c      | 62 ++++++++++++++++++++++++++++++++++
 5 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 drivers/char/tpm/tpms-dev.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 13ff5da..e50d768 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
+	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o tpms-dev.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 993b9ae..5ae3050 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
 static DEFINE_MUTEX(idr_lock);
 
 struct class *tpm_class;
+struct class *tpm_rm_class;
 dev_t tpm_devt;
 
 /**
@@ -132,6 +133,14 @@ static void tpm_dev_release(struct device *dev)
 	kfree(chip);
 }
 
+static void tpm_devrm_release(struct device *dev)
+{
+	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devrm);
+
+	/* release the master device reference */
+	put_device(&chip->dev);
+}
+
 /**
  * tpm_chip_alloc() - allocate a new struct tpm_chip instance
  * @pdev: device to which the chip is associated
@@ -168,27 +177,46 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	chip->dev_num = rc;
 
 	device_initialize(&chip->dev);
+	device_initialize(&chip->devrm);
 
 	chip->dev.class = tpm_class;
 	chip->dev.release = tpm_dev_release;
 	chip->dev.parent = pdev;
 	chip->dev.groups = chip->groups;
 
+	chip->devrm.parent = pdev;
+	chip->devrm.class = tpm_rm_class;
+	chip->devrm.release = tpm_devrm_release;
+	/* get extra reference on main device to hold on
+	 * behalf of devrm.  This holds the chip structure
+	 * while cdevrm is in use.  The corresponding put
+	 * is in the tpm_devrm_release */
+	get_device(&chip->dev);
+
 	if (chip->dev_num == 0)
 		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
 	else
 		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
 
+	chip->devrm.devt =
+		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
+
 	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
 	if (rc)
 		goto out;
+	rc = dev_set_name(&chip->devrm, "tpms%d", chip->dev_num);
+	if (rc)
+		goto out;
 
 	if (!pdev)
 		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
 
 	cdev_init(&chip->cdev, &tpm_fops);
+	cdev_init(&chip->cdevrm, &tpm_rm_fops);
 	chip->cdev.owner = THIS_MODULE;
+	chip->cdevrm.owner = THIS_MODULE;
 	chip->cdev.kobj.parent = &chip->dev.kobj;
+	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
 
 	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!chip->work_space.context_buf) {
@@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	return chip;
 
 out:
+	put_device(&chip->devrm);
 	put_device(&chip->dev);
+	put_device(&chip->devrm);
 	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_alloc);
@@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 			dev_name(&chip->dev), MAJOR(chip->dev.devt),
 			MINOR(chip->dev.devt), rc);
 
-		return rc;
+		goto err_1;
 	}
 
 	rc = device_add(&chip->dev);
@@ -254,16 +284,44 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 			dev_name(&chip->dev), MAJOR(chip->dev.devt),
 			MINOR(chip->dev.devt), rc);
 
-		cdev_del(&chip->cdev);
-		return rc;
+		goto err_2;
+	}
+
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		rc = cdev_add(&chip->cdevrm, chip->devrm.devt, 1);
+	if (rc) {
+		dev_err(&chip->dev,
+			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
+			MINOR(chip->devrm.devt), rc);
+
+		goto err_3;
 	}
 
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		rc = device_add(&chip->devrm);
+	if (rc) {
+		dev_err(&chip->dev,
+			"unable to device_register() %s, major %d, minor %d, err=%d\n",
+			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
+			MINOR(chip->devrm.devt), rc);
+
+		goto err_4;
+	}
 	/* Make the chip available. */
 	mutex_lock(&idr_lock);
 	idr_replace(&dev_nums_idr, chip, chip->dev_num);
 	mutex_unlock(&idr_lock);
 
 	return rc;
+ err_4:
+	cdev_del(&chip->cdevrm);
+ err_3:
+	device_del(&chip->dev);
+ err_2:
+	cdev_del(&chip->cdev);
+ err_1:
+	return rc;
 }
 
 static void tpm_del_char_device(struct tpm_chip *chip)
@@ -271,6 +329,11 @@ static void tpm_del_char_device(struct tpm_chip *chip)
 	cdev_del(&chip->cdev);
 	device_del(&chip->dev);
 
+	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+		cdev_del(&chip->cdevrm);
+		device_del(&chip->devrm);
+	}
+
 	/* Make the chip unavailable. */
 	mutex_lock(&idr_lock);
 	idr_replace(&dev_nums_idr, NULL, chip->dev_num);
@@ -282,6 +345,9 @@ static void tpm_del_char_device(struct tpm_chip *chip)
 		tpm2_shutdown(chip, TPM2_SU_CLEAR);
 	chip->ops = NULL;
 	up_write(&chip->ops_sem);
+	/* will release the devrm reference to the chip->dev unless
+	 * something has cdevrm open */
+	put_device(&chip->devrm);
 }
 
 static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ae85aab..40bf022 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1218,9 +1218,17 @@ static int __init tpm_init(void)
 		return PTR_ERR(tpm_class);
 	}
 
-	rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
+	tpm_rm_class = class_create(THIS_MODULE, "tpms");
+	if (IS_ERR(tpm_rm_class)) {
+		pr_err("couldn't create tpmrm class\n");
+		class_destroy(tpm_class);
+		return PTR_ERR(tpm_rm_class);
+	}
+
+	rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
 	if (rc < 0) {
 		pr_err("tpm: failed to allocate char dev region\n");
+		class_destroy(tpm_rm_class);
 		class_destroy(tpm_class);
 		return rc;
 	}
@@ -1232,7 +1240,8 @@ static void __exit tpm_exit(void)
 {
 	idr_destroy(&dev_nums_idr);
 	class_destroy(tpm_class);
-	unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
+	class_destroy(tpm_rm_class);
+	unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
 }
 
 subsys_initcall(tpm_init);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 45d997f..3346c48 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -173,8 +173,8 @@ struct tpm_chip_seqops {
 };
 
 struct tpm_chip {
-	struct device dev;
-	struct cdev cdev;
+	struct device dev, devrm;
+	struct cdev cdev, cdevrm;
 
 	/* A driver callback under ops cannot be run unless ops_sem is held
 	 * (sometimes implicitly, eg for the sysfs code). ops becomes null
@@ -511,8 +511,10 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
 }
 
 extern struct class *tpm_class;
+extern struct class *tpm_rm_class;
 extern dev_t tpm_devt;
 extern const struct file_operations tpm_fops;
+extern const struct file_operations tpm_rm_fops;
 extern struct idr dev_nums_idr;
 
 enum tpm_transmit_flags {
diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
new file mode 100644
index 0000000..c10b308
--- /dev/null
+++ b/drivers/char/tpm/tpms-dev.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 James.Bottomley@HansenPartnership.com
+ *
+ * GPLv2
+ */
+#include <linux/slab.h>
+#include "tpm-dev.h"
+
+struct tpms_priv {
+	struct file_priv priv;
+	struct tpm_space space;
+};
+
+static int tpms_open(struct inode *inode, struct file *file)
+{
+	struct tpm_chip *chip;
+	struct tpms_priv *priv;
+
+	chip = container_of(inode->i_cdev, struct tpm_chip, cdevrm);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+	priv->space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (priv->space.context_buf == NULL) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+
+	tpm_common_open(file, chip, &priv->priv);
+
+	return 0;
+}
+
+static int tpms_release(struct inode *inode, struct file *file)
+{
+	struct file_priv *fpriv = file->private_data;
+	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
+
+	tpm_common_release(file, fpriv);
+	kfree(priv);
+
+	return 0;
+}
+
+ssize_t tpms_write(struct file *file, const char __user *buf,
+		   size_t size, loff_t *off)
+{
+	struct file_priv *fpriv = file->private_data;
+	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
+
+	return tpm_common_write(file, buf, size, off, &priv->space);
+}
+
+const struct file_operations tpm_rm_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpms_open,
+	.read = tpm_common_read,
+	.write = tpms_write,
+	.release = tpms_release,
+};
+
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-16 13:12   ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 13:12 UTC (permalink / raw)
  To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: open list, James Bottomley, linux-security-module-u79uwXL29TY76Z2rM5mHXA

From: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>

Currently the Resource Manager (RM) is not exposed to userspace.  Make
this exposure via a separate device, which can now be opened multiple
times because each read/write transaction goes separately via the RM.

Concurrency is protected by the chip->tpm_mutex for each read/write
transaction separately.  The TPM is cleared of all transient objects
by the time the mutex is dropped, so there should be no interference
between the kernel and userspace.

Signed-off-by: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
---
 drivers/char/tpm/Makefile        |  2 +-
 drivers/char/tpm/tpm-chip.c      | 72 ++++++++++++++++++++++++++++++++++++++--
 drivers/char/tpm/tpm-interface.c | 13 ++++++--
 drivers/char/tpm/tpm.h           |  6 ++--
 drivers/char/tpm/tpms-dev.c      | 62 ++++++++++++++++++++++++++++++++++
 5 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 drivers/char/tpm/tpms-dev.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 13ff5da..e50d768 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
 tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
-	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
+	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o tpms-dev.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
 tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 993b9ae..5ae3050 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
 static DEFINE_MUTEX(idr_lock);
 
 struct class *tpm_class;
+struct class *tpm_rm_class;
 dev_t tpm_devt;
 
 /**
@@ -132,6 +133,14 @@ static void tpm_dev_release(struct device *dev)
 	kfree(chip);
 }
 
+static void tpm_devrm_release(struct device *dev)
+{
+	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devrm);
+
+	/* release the master device reference */
+	put_device(&chip->dev);
+}
+
 /**
  * tpm_chip_alloc() - allocate a new struct tpm_chip instance
  * @pdev: device to which the chip is associated
@@ -168,27 +177,46 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	chip->dev_num = rc;
 
 	device_initialize(&chip->dev);
+	device_initialize(&chip->devrm);
 
 	chip->dev.class = tpm_class;
 	chip->dev.release = tpm_dev_release;
 	chip->dev.parent = pdev;
 	chip->dev.groups = chip->groups;
 
+	chip->devrm.parent = pdev;
+	chip->devrm.class = tpm_rm_class;
+	chip->devrm.release = tpm_devrm_release;
+	/* get extra reference on main device to hold on
+	 * behalf of devrm.  This holds the chip structure
+	 * while cdevrm is in use.  The corresponding put
+	 * is in the tpm_devrm_release */
+	get_device(&chip->dev);
+
 	if (chip->dev_num == 0)
 		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
 	else
 		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
 
+	chip->devrm.devt =
+		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
+
 	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
 	if (rc)
 		goto out;
+	rc = dev_set_name(&chip->devrm, "tpms%d", chip->dev_num);
+	if (rc)
+		goto out;
 
 	if (!pdev)
 		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
 
 	cdev_init(&chip->cdev, &tpm_fops);
+	cdev_init(&chip->cdevrm, &tpm_rm_fops);
 	chip->cdev.owner = THIS_MODULE;
+	chip->cdevrm.owner = THIS_MODULE;
 	chip->cdev.kobj.parent = &chip->dev.kobj;
+	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
 
 	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!chip->work_space.context_buf) {
@@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	return chip;
 
 out:
+	put_device(&chip->devrm);
 	put_device(&chip->dev);
+	put_device(&chip->devrm);
 	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_alloc);
@@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 			dev_name(&chip->dev), MAJOR(chip->dev.devt),
 			MINOR(chip->dev.devt), rc);
 
-		return rc;
+		goto err_1;
 	}
 
 	rc = device_add(&chip->dev);
@@ -254,16 +284,44 @@ static int tpm_add_char_device(struct tpm_chip *chip)
 			dev_name(&chip->dev), MAJOR(chip->dev.devt),
 			MINOR(chip->dev.devt), rc);
 
-		cdev_del(&chip->cdev);
-		return rc;
+		goto err_2;
+	}
+
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		rc = cdev_add(&chip->cdevrm, chip->devrm.devt, 1);
+	if (rc) {
+		dev_err(&chip->dev,
+			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
+			MINOR(chip->devrm.devt), rc);
+
+		goto err_3;
 	}
 
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		rc = device_add(&chip->devrm);
+	if (rc) {
+		dev_err(&chip->dev,
+			"unable to device_register() %s, major %d, minor %d, err=%d\n",
+			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
+			MINOR(chip->devrm.devt), rc);
+
+		goto err_4;
+	}
 	/* Make the chip available. */
 	mutex_lock(&idr_lock);
 	idr_replace(&dev_nums_idr, chip, chip->dev_num);
 	mutex_unlock(&idr_lock);
 
 	return rc;
+ err_4:
+	cdev_del(&chip->cdevrm);
+ err_3:
+	device_del(&chip->dev);
+ err_2:
+	cdev_del(&chip->cdev);
+ err_1:
+	return rc;
 }
 
 static void tpm_del_char_device(struct tpm_chip *chip)
@@ -271,6 +329,11 @@ static void tpm_del_char_device(struct tpm_chip *chip)
 	cdev_del(&chip->cdev);
 	device_del(&chip->dev);
 
+	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+		cdev_del(&chip->cdevrm);
+		device_del(&chip->devrm);
+	}
+
 	/* Make the chip unavailable. */
 	mutex_lock(&idr_lock);
 	idr_replace(&dev_nums_idr, NULL, chip->dev_num);
@@ -282,6 +345,9 @@ static void tpm_del_char_device(struct tpm_chip *chip)
 		tpm2_shutdown(chip, TPM2_SU_CLEAR);
 	chip->ops = NULL;
 	up_write(&chip->ops_sem);
+	/* will release the devrm reference to the chip->dev unless
+	 * something has cdevrm open */
+	put_device(&chip->devrm);
 }
 
 static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ae85aab..40bf022 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1218,9 +1218,17 @@ static int __init tpm_init(void)
 		return PTR_ERR(tpm_class);
 	}
 
-	rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
+	tpm_rm_class = class_create(THIS_MODULE, "tpms");
+	if (IS_ERR(tpm_rm_class)) {
+		pr_err("couldn't create tpmrm class\n");
+		class_destroy(tpm_class);
+		return PTR_ERR(tpm_rm_class);
+	}
+
+	rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
 	if (rc < 0) {
 		pr_err("tpm: failed to allocate char dev region\n");
+		class_destroy(tpm_rm_class);
 		class_destroy(tpm_class);
 		return rc;
 	}
@@ -1232,7 +1240,8 @@ static void __exit tpm_exit(void)
 {
 	idr_destroy(&dev_nums_idr);
 	class_destroy(tpm_class);
-	unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
+	class_destroy(tpm_rm_class);
+	unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
 }
 
 subsys_initcall(tpm_init);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 45d997f..3346c48 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -173,8 +173,8 @@ struct tpm_chip_seqops {
 };
 
 struct tpm_chip {
-	struct device dev;
-	struct cdev cdev;
+	struct device dev, devrm;
+	struct cdev cdev, cdevrm;
 
 	/* A driver callback under ops cannot be run unless ops_sem is held
 	 * (sometimes implicitly, eg for the sysfs code). ops becomes null
@@ -511,8 +511,10 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
 }
 
 extern struct class *tpm_class;
+extern struct class *tpm_rm_class;
 extern dev_t tpm_devt;
 extern const struct file_operations tpm_fops;
+extern const struct file_operations tpm_rm_fops;
 extern struct idr dev_nums_idr;
 
 enum tpm_transmit_flags {
diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
new file mode 100644
index 0000000..c10b308
--- /dev/null
+++ b/drivers/char/tpm/tpms-dev.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org
+ *
+ * GPLv2
+ */
+#include <linux/slab.h>
+#include "tpm-dev.h"
+
+struct tpms_priv {
+	struct file_priv priv;
+	struct tpm_space space;
+};
+
+static int tpms_open(struct inode *inode, struct file *file)
+{
+	struct tpm_chip *chip;
+	struct tpms_priv *priv;
+
+	chip = container_of(inode->i_cdev, struct tpm_chip, cdevrm);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+	priv->space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (priv->space.context_buf == NULL) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+
+	tpm_common_open(file, chip, &priv->priv);
+
+	return 0;
+}
+
+static int tpms_release(struct inode *inode, struct file *file)
+{
+	struct file_priv *fpriv = file->private_data;
+	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
+
+	tpm_common_release(file, fpriv);
+	kfree(priv);
+
+	return 0;
+}
+
+ssize_t tpms_write(struct file *file, const char __user *buf,
+		   size_t size, loff_t *off)
+{
+	struct file_priv *fpriv = file->private_data;
+	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
+
+	return tpm_common_write(file, buf, size, off, &priv->space);
+}
+
+const struct file_operations tpm_rm_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpms_open,
+	.read = tpm_common_read,
+	.write = tpms_write,
+	.release = tpms_release,
+};
+
-- 
2.9.3


------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
  2017-01-16 13:12   ` Jarkko Sakkinen
  (?)
@ 2017-01-16 16:14   ` Jason Gunthorpe
  2017-01-16 17:24     ` Jarkko Sakkinen
  -1 siblings, 1 reply; 57+ messages in thread
From: Jason Gunthorpe @ 2017-01-16 16:14 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: tpmdd-devel, linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, open list

On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:

> @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  	return chip;
>  
>  out:
> +	put_device(&chip->devrm);
>  	put_device(&chip->dev);
> +	put_device(&chip->devrm);
>  	return ERR_PTR(rc);
>  }

Something has gone wrong here..

Jason

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
  2017-01-16 16:14   ` Jason Gunthorpe
@ 2017-01-16 17:24     ` Jarkko Sakkinen
  2017-01-16 17:28       ` [tpmdd-devel] " James Bottomley
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-16 17:24 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: tpmdd-devel, linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, open list

On Mon, Jan 16, 2017 at 09:14:13AM -0700, Jason Gunthorpe wrote:
> On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:
> 
> > @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> >  	return chip;
> >  
> >  out:
> > +	put_device(&chip->devrm);
> >  	put_device(&chip->dev);
> > +	put_device(&chip->devrm);
> >  	return ERR_PTR(rc);
> >  }
> 
> Something has gone wrong here..

Not a big surprise. There were a bunch of these small patches
that I had to squash. Thanks for spotting this.

Funny that I didn't experiece any issues when I run my smoke
tests.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
  2017-01-16 17:24     ` Jarkko Sakkinen
@ 2017-01-16 17:28       ` James Bottomley
  2017-01-17  7:14         ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-16 17:28 UTC (permalink / raw)
  To: Jarkko Sakkinen, Jason Gunthorpe
  Cc: open list, linux-security-module, tpmdd-devel

On Mon, 2017-01-16 at 19:24 +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 16, 2017 at 09:14:13AM -0700, Jason Gunthorpe wrote:
> > On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:
> > 
> > > @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device
> > > *pdev,
> > >  	return chip;
> > >  
> > >  out:
> > > +	put_device(&chip->devrm);
> > >  	put_device(&chip->dev);
> > > +	put_device(&chip->devrm);
> > >  	return ERR_PTR(rc);
> > >  }
> > 
> > Something has gone wrong here..
> 
> Not a big surprise. There were a bunch of these small patches
> that I had to squash. Thanks for spotting this.
> 
> Funny that I didn't experiece any issues when I run my smoke
> tests.

It's the error path in tpm_chip_alloc: it's incredibly hard to trigger,
which is probably why your tests didn't see it.  You basically either
have to be out of kernel memory or out of TPM device numbers.

James

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
  2017-01-16 17:28       ` [tpmdd-devel] " James Bottomley
@ 2017-01-17  7:14         ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-17  7:14 UTC (permalink / raw)
  To: James Bottomley
  Cc: Jason Gunthorpe, open list, linux-security-module, tpmdd-devel

On Mon, Jan 16, 2017 at 09:28:17AM -0800, James Bottomley wrote:
> On Mon, 2017-01-16 at 19:24 +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 16, 2017 at 09:14:13AM -0700, Jason Gunthorpe wrote:
> > > On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:
> > > 
> > > > @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device
> > > > *pdev,
> > > >  	return chip;
> > > >  
> > > >  out:
> > > > +	put_device(&chip->devrm);
> > > >  	put_device(&chip->dev);
> > > > +	put_device(&chip->devrm);
> > > >  	return ERR_PTR(rc);
> > > >  }
> > > 
> > > Something has gone wrong here..
> > 
> > Not a big surprise. There were a bunch of these small patches
> > that I had to squash. Thanks for spotting this.
> > 
> > Funny that I didn't experiece any issues when I run my smoke
> > tests.
> 
> It's the error path in tpm_chip_alloc: it's incredibly hard to trigger,
> which is probably why your tests didn't see it.  You basically either
> have to be out of kernel memory or out of TPM device numbers.

Right, of course.

I have branch for each new patch set version. For v3 the branch is named
as tabrm3. I'll apply all the fixes as separate commits on top of that
branch. Once I'm ready to send a new version, I'll create tabrm4 branch
and squash the fixes.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-16 13:12   ` Jarkko Sakkinen
  (?)
  (?)
@ 2017-01-18 15:01   ` James Bottomley
  2017-01-19 10:49     ` Jarkko Sakkinen
  -1 siblings, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-18 15:01 UTC (permalink / raw)
  To: Jarkko Sakkinen, tpmdd-devel; +Cc: open list, linux-security-module

On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> From: James Bottomley <James.Bottomley@HansenPartnership.com>
> 
> Currently the Resource Manager (RM) is not exposed to userspace. 
>  Make
> this exposure via a separate device, which can now be opened multiple
> times because each read/write transaction goes separately via the RM.
> 
> Concurrency is protected by the chip->tpm_mutex for each read/write
> transaction separately.  The TPM is cleared of all transient objects
> by the time the mutex is dropped, so there should be no interference
> between the kernel and userspace.

There's actually a missing kfree of context_buf on the tpms_release
path as well.  This patch fixes it up.

James

---

commit 778425973c532a0c1ec2b5b2ccd7ff995e2cc9db
Author: James Bottomley <James.Bottomley@HansenPartnership.com>
Date:   Wed Jan 18 09:58:23 2017 -0500

    add missing kfree to tpms_release

diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
index c10b308..6bb687f 100644
--- a/drivers/char/tpm/tpms-dev.c
+++ b/drivers/char/tpm/tpms-dev.c
@@ -37,6 +37,7 @@ static int tpms_release(struct inode *inode, struct file *file)
 	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
 
 	tpm_common_release(file, fpriv);
+	kfree(priv->space.context_buf);
 	kfree(priv);
 
 	return 0;

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-19 10:42     ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-19 10:42 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: linux-security-module, James Bottomley, Peter Huewe,
	Marcel Selhorst, Jason Gunthorpe, open list

I've forgot to put out my review comments about this patch. Please send
me an updated patch and I'll include it to v4. You can choose to send it
also privately because it will go to public review anyway through the
patch set.

I could fix these myself (because they are cosmetic stuff) but I simply
don't have the time at my hand and you are the author so...

Please include also the fixup to remove that leftover put_device. Thank
you.

On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:
> From: James Bottomley <James.Bottomley@HansenPartnership.com>
> 
> Currently the Resource Manager (RM) is not exposed to userspace.  Make
> this exposure via a separate device, which can now be opened multiple
> times because each read/write transaction goes separately via the RM.
> 
> Concurrency is protected by the chip->tpm_mutex for each read/write
> transaction separately.  The TPM is cleared of all transient objects
> by the time the mutex is dropped, so there should be no interference
> between the kernel and userspace.
> 
> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

TPM spaces are not exposed to the user space, which are a tool to
implement a resource manager. This commit message should be rewritten.

> ---
>  drivers/char/tpm/Makefile        |  2 +-
>  drivers/char/tpm/tpm-chip.c      | 72 ++++++++++++++++++++++++++++++++++++++--
>  drivers/char/tpm/tpm-interface.c | 13 ++++++--
>  drivers/char/tpm/tpm.h           |  6 ++--
>  drivers/char/tpm/tpms-dev.c      | 62 ++++++++++++++++++++++++++++++++++
>  5 files changed, 147 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/char/tpm/tpms-dev.c
> 
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 13ff5da..e50d768 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -3,7 +3,7 @@
>  #
>  obj-$(CONFIG_TCG_TPM) += tpm.o
>  tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
> -	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
> +	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o tpms-dev.o
>  tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
>  tpm-$(CONFIG_OF) += tpm_of.o
>  obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 993b9ae..5ae3050 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
>  static DEFINE_MUTEX(idr_lock);
>  
>  struct class *tpm_class;
> +struct class *tpm_rm_class;

tpms_class

>  dev_t tpm_devt;
>  
>  /**
> @@ -132,6 +133,14 @@ static void tpm_dev_release(struct device *dev)
>  	kfree(chip);
>  }
>  
> +static void tpm_devrm_release(struct device *dev)

tpms_release

> +{
> +	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devrm);
> +
> +	/* release the master device reference */
> +	put_device(&chip->dev);
> +}
> +
>  /**
>   * tpm_chip_alloc() - allocate a new struct tpm_chip instance
>   * @pdev: device to which the chip is associated
> @@ -168,27 +177,46 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  	chip->dev_num = rc;
>  
>  	device_initialize(&chip->dev);
> +	device_initialize(&chip->devrm);

chip->devs (well you probably get the iea, not going to comment every
possible instance)

>  
>  	chip->dev.class = tpm_class;
>  	chip->dev.release = tpm_dev_release;
>  	chip->dev.parent = pdev;
>  	chip->dev.groups = chip->groups;
>  
> +	chip->devrm.parent = pdev;
> +	chip->devrm.class = tpm_rm_class;
> +	chip->devrm.release = tpm_devrm_release;
> +	/* get extra reference on main device to hold on
> +	 * behalf of devrm.  This holds the chip structure
> +	 * while cdevrm is in use.  The corresponding put
> +	 * is in the tpm_devrm_release */
> +	get_device(&chip->dev);
> +
>  	if (chip->dev_num == 0)
>  		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
>  	else
>  		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
>  
> +	chip->devrm.devt =
> +		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
> +
>  	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
>  	if (rc)
>  		goto out;
> +	rc = dev_set_name(&chip->devrm, "tpms%d", chip->dev_num);
> +	if (rc)
> +		goto out;
>  
>  	if (!pdev)
>  		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
>  
>  	cdev_init(&chip->cdev, &tpm_fops);
> +	cdev_init(&chip->cdevrm, &tpm_rm_fops);
>  	chip->cdev.owner = THIS_MODULE;
> +	chip->cdevrm.owner = THIS_MODULE;
>  	chip->cdev.kobj.parent = &chip->dev.kobj;
> +	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
>  
>  	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
>  	if (!chip->work_space.context_buf) {
> @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  	return chip;
>  
>  out:
> +	put_device(&chip->devrm);
>  	put_device(&chip->dev);
> +	put_device(&chip->devrm);
>  	return ERR_PTR(rc);
>  }
>  EXPORT_SYMBOL_GPL(tpm_chip_alloc);
> @@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
>  			MINOR(chip->dev.devt), rc);
>  
> -		return rc;
> +		goto err_1;
>  	}
>  
>  	rc = device_add(&chip->dev);
> @@ -254,16 +284,44 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
>  			MINOR(chip->dev.devt), rc);
>  
> -		cdev_del(&chip->cdev);
> -		return rc;
> +		goto err_2;
> +	}
> +
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		rc = cdev_add(&chip->cdevrm, chip->devrm.devt, 1);
> +	if (rc) {
> +		dev_err(&chip->dev,
> +			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> +			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
> +			MINOR(chip->devrm.devt), rc);
> +
> +		goto err_3;
>  	}
>  
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		rc = device_add(&chip->devrm);
> +	if (rc) {
> +		dev_err(&chip->dev,
> +			"unable to device_register() %s, major %d, minor %d, err=%d\n",
> +			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
> +			MINOR(chip->devrm.devt), rc);
> +
> +		goto err_4;
> +	}
>  	/* Make the chip available. */
>  	mutex_lock(&idr_lock);
>  	idr_replace(&dev_nums_idr, chip, chip->dev_num);
>  	mutex_unlock(&idr_lock);
>  
>  	return rc;
> + err_4:
> +	cdev_del(&chip->cdevrm);
> + err_3:
> +	device_del(&chip->dev);
> + err_2:
> +	cdev_del(&chip->cdev);
> + err_1:
> +	return rc;
>  }
>  
>  static void tpm_del_char_device(struct tpm_chip *chip)
> @@ -271,6 +329,11 @@ static void tpm_del_char_device(struct tpm_chip *chip)
>  	cdev_del(&chip->cdev);
>  	device_del(&chip->dev);
>  
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> +		cdev_del(&chip->cdevrm);
> +		device_del(&chip->devrm);
> +	}
> +
>  	/* Make the chip unavailable. */
>  	mutex_lock(&idr_lock);
>  	idr_replace(&dev_nums_idr, NULL, chip->dev_num);
> @@ -282,6 +345,9 @@ static void tpm_del_char_device(struct tpm_chip *chip)
>  		tpm2_shutdown(chip, TPM2_SU_CLEAR);
>  	chip->ops = NULL;
>  	up_write(&chip->ops_sem);
> +	/* will release the devrm reference to the chip->dev unless
> +	 * something has cdevrm open */
> +	put_device(&chip->devrm);
>  }
>  
>  static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index ae85aab..40bf022 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -1218,9 +1218,17 @@ static int __init tpm_init(void)
>  		return PTR_ERR(tpm_class);
>  	}
>  
> -	rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
> +	tpm_rm_class = class_create(THIS_MODULE, "tpms");
> +	if (IS_ERR(tpm_rm_class)) {
> +		pr_err("couldn't create tpmrm class\n");
> +		class_destroy(tpm_class);
> +		return PTR_ERR(tpm_rm_class);
> +	}
> +
> +	rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
>  	if (rc < 0) {
>  		pr_err("tpm: failed to allocate char dev region\n");
> +		class_destroy(tpm_rm_class);
>  		class_destroy(tpm_class);
>  		return rc;
>  	}
> @@ -1232,7 +1240,8 @@ static void __exit tpm_exit(void)
>  {
>  	idr_destroy(&dev_nums_idr);
>  	class_destroy(tpm_class);
> -	unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
> +	class_destroy(tpm_rm_class);
> +	unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
>  }
>  
>  subsys_initcall(tpm_init);
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 45d997f..3346c48 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -173,8 +173,8 @@ struct tpm_chip_seqops {
>  };
>  
>  struct tpm_chip {
> -	struct device dev;
> -	struct cdev cdev;
> +	struct device dev, devrm;
> +	struct cdev cdev, cdevrm;

Again cosmetic stuff (or more like nitpicking) but I would like have one
declaration per line.

>  	/* A driver callback under ops cannot be run unless ops_sem is held
>  	 * (sometimes implicitly, eg for the sysfs code). ops becomes null
> @@ -511,8 +511,10 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
>  }
>  
>  extern struct class *tpm_class;
> +extern struct class *tpm_rm_class;
>  extern dev_t tpm_devt;
>  extern const struct file_operations tpm_fops;
> +extern const struct file_operations tpm_rm_fops;
>  extern struct idr dev_nums_idr;
>  
>  enum tpm_transmit_flags {
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> new file mode 100644
> index 0000000..c10b308
> --- /dev/null
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (C) 2017 James.Bottomley@HansenPartnership.com
> + *
> + * GPLv2
> + */
> +#include <linux/slab.h>
> +#include "tpm-dev.h"
> +
> +struct tpms_priv {
> +	struct file_priv priv;
> +	struct tpm_space space;
> +};
> +
> +static int tpms_open(struct inode *inode, struct file *file)
> +{
> +	struct tpm_chip *chip;
> +	struct tpms_priv *priv;
> +
> +	chip = container_of(inode->i_cdev, struct tpm_chip, cdevrm);
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (priv == NULL)
> +		return -ENOMEM;
> +	priv->space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> +	if (priv->space.context_buf == NULL) {
> +		kfree(priv);
> +		return -ENOMEM;
> +	}
> +
> +	tpm_common_open(file, chip, &priv->priv);
> +
> +	return 0;
> +}
> +
> +static int tpms_release(struct inode *inode, struct file *file)
> +{
> +	struct file_priv *fpriv = file->private_data;
> +	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> +	tpm_common_release(file, fpriv);
> +	kfree(priv);
> +
> +	return 0;
> +}
> +
> +ssize_t tpms_write(struct file *file, const char __user *buf,
> +		   size_t size, loff_t *off)
> +{
> +	struct file_priv *fpriv = file->private_data;
> +	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> +	return tpm_common_write(file, buf, size, off, &priv->space);
> +}
> +
> +const struct file_operations tpm_rm_fops = {
> +	.owner = THIS_MODULE,
> +	.llseek = no_llseek,
> +	.open = tpms_open,
> +	.read = tpm_common_read,
> +	.write = tpms_write,
> +	.release = tpms_release,
> +};
> +
> -- 
> 2.9.3
> 

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-19 10:42     ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-19 10:42 UTC (permalink / raw)
  To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: open list, James Bottomley, linux-security-module-u79uwXL29TY76Z2rM5mHXA

I've forgot to put out my review comments about this patch. Please send
me an updated patch and I'll include it to v4. You can choose to send it
also privately because it will go to public review anyway through the
patch set.

I could fix these myself (because they are cosmetic stuff) but I simply
don't have the time at my hand and you are the author so...

Please include also the fixup to remove that leftover put_device. Thank
you.

On Mon, Jan 16, 2017 at 03:12:11PM +0200, Jarkko Sakkinen wrote:
> From: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> 
> Currently the Resource Manager (RM) is not exposed to userspace.  Make
> this exposure via a separate device, which can now be opened multiple
> times because each read/write transaction goes separately via the RM.
> 
> Concurrency is protected by the chip->tpm_mutex for each read/write
> transaction separately.  The TPM is cleared of all transient objects
> by the time the mutex is dropped, so there should be no interference
> between the kernel and userspace.
> 
> Signed-off-by: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>

TPM spaces are not exposed to the user space, which are a tool to
implement a resource manager. This commit message should be rewritten.

> ---
>  drivers/char/tpm/Makefile        |  2 +-
>  drivers/char/tpm/tpm-chip.c      | 72 ++++++++++++++++++++++++++++++++++++++--
>  drivers/char/tpm/tpm-interface.c | 13 ++++++--
>  drivers/char/tpm/tpm.h           |  6 ++--
>  drivers/char/tpm/tpms-dev.c      | 62 ++++++++++++++++++++++++++++++++++
>  5 files changed, 147 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/char/tpm/tpms-dev.c
> 
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 13ff5da..e50d768 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -3,7 +3,7 @@
>  #
>  obj-$(CONFIG_TCG_TPM) += tpm.o
>  tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
> -	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o
> +	 tpm_eventlog.o tpm2-space.o tpm-dev-common.o tpms-dev.o
>  tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
>  tpm-$(CONFIG_OF) += tpm_of.o
>  obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 993b9ae..5ae3050 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
>  static DEFINE_MUTEX(idr_lock);
>  
>  struct class *tpm_class;
> +struct class *tpm_rm_class;

tpms_class

>  dev_t tpm_devt;
>  
>  /**
> @@ -132,6 +133,14 @@ static void tpm_dev_release(struct device *dev)
>  	kfree(chip);
>  }
>  
> +static void tpm_devrm_release(struct device *dev)

tpms_release

> +{
> +	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devrm);
> +
> +	/* release the master device reference */
> +	put_device(&chip->dev);
> +}
> +
>  /**
>   * tpm_chip_alloc() - allocate a new struct tpm_chip instance
>   * @pdev: device to which the chip is associated
> @@ -168,27 +177,46 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  	chip->dev_num = rc;
>  
>  	device_initialize(&chip->dev);
> +	device_initialize(&chip->devrm);

chip->devs (well you probably get the iea, not going to comment every
possible instance)

>  
>  	chip->dev.class = tpm_class;
>  	chip->dev.release = tpm_dev_release;
>  	chip->dev.parent = pdev;
>  	chip->dev.groups = chip->groups;
>  
> +	chip->devrm.parent = pdev;
> +	chip->devrm.class = tpm_rm_class;
> +	chip->devrm.release = tpm_devrm_release;
> +	/* get extra reference on main device to hold on
> +	 * behalf of devrm.  This holds the chip structure
> +	 * while cdevrm is in use.  The corresponding put
> +	 * is in the tpm_devrm_release */
> +	get_device(&chip->dev);
> +
>  	if (chip->dev_num == 0)
>  		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
>  	else
>  		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
>  
> +	chip->devrm.devt =
> +		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
> +
>  	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
>  	if (rc)
>  		goto out;
> +	rc = dev_set_name(&chip->devrm, "tpms%d", chip->dev_num);
> +	if (rc)
> +		goto out;
>  
>  	if (!pdev)
>  		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
>  
>  	cdev_init(&chip->cdev, &tpm_fops);
> +	cdev_init(&chip->cdevrm, &tpm_rm_fops);
>  	chip->cdev.owner = THIS_MODULE;
> +	chip->cdevrm.owner = THIS_MODULE;
>  	chip->cdev.kobj.parent = &chip->dev.kobj;
> +	chip->cdevrm.kobj.parent = &chip->devrm.kobj;
>  
>  	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
>  	if (!chip->work_space.context_buf) {
> @@ -199,7 +227,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
>  	return chip;
>  
>  out:
> +	put_device(&chip->devrm);
>  	put_device(&chip->dev);
> +	put_device(&chip->devrm);
>  	return ERR_PTR(rc);
>  }
>  EXPORT_SYMBOL_GPL(tpm_chip_alloc);
> @@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
>  			MINOR(chip->dev.devt), rc);
>  
> -		return rc;
> +		goto err_1;
>  	}
>  
>  	rc = device_add(&chip->dev);
> @@ -254,16 +284,44 @@ static int tpm_add_char_device(struct tpm_chip *chip)
>  			dev_name(&chip->dev), MAJOR(chip->dev.devt),
>  			MINOR(chip->dev.devt), rc);
>  
> -		cdev_del(&chip->cdev);
> -		return rc;
> +		goto err_2;
> +	}
> +
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		rc = cdev_add(&chip->cdevrm, chip->devrm.devt, 1);
> +	if (rc) {
> +		dev_err(&chip->dev,
> +			"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> +			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
> +			MINOR(chip->devrm.devt), rc);
> +
> +		goto err_3;
>  	}
>  
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		rc = device_add(&chip->devrm);
> +	if (rc) {
> +		dev_err(&chip->dev,
> +			"unable to device_register() %s, major %d, minor %d, err=%d\n",
> +			dev_name(&chip->devrm), MAJOR(chip->devrm.devt),
> +			MINOR(chip->devrm.devt), rc);
> +
> +		goto err_4;
> +	}
>  	/* Make the chip available. */
>  	mutex_lock(&idr_lock);
>  	idr_replace(&dev_nums_idr, chip, chip->dev_num);
>  	mutex_unlock(&idr_lock);
>  
>  	return rc;
> + err_4:
> +	cdev_del(&chip->cdevrm);
> + err_3:
> +	device_del(&chip->dev);
> + err_2:
> +	cdev_del(&chip->cdev);
> + err_1:
> +	return rc;
>  }
>  
>  static void tpm_del_char_device(struct tpm_chip *chip)
> @@ -271,6 +329,11 @@ static void tpm_del_char_device(struct tpm_chip *chip)
>  	cdev_del(&chip->cdev);
>  	device_del(&chip->dev);
>  
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> +		cdev_del(&chip->cdevrm);
> +		device_del(&chip->devrm);
> +	}
> +
>  	/* Make the chip unavailable. */
>  	mutex_lock(&idr_lock);
>  	idr_replace(&dev_nums_idr, NULL, chip->dev_num);
> @@ -282,6 +345,9 @@ static void tpm_del_char_device(struct tpm_chip *chip)
>  		tpm2_shutdown(chip, TPM2_SU_CLEAR);
>  	chip->ops = NULL;
>  	up_write(&chip->ops_sem);
> +	/* will release the devrm reference to the chip->dev unless
> +	 * something has cdevrm open */
> +	put_device(&chip->devrm);
>  }
>  
>  static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index ae85aab..40bf022 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -1218,9 +1218,17 @@ static int __init tpm_init(void)
>  		return PTR_ERR(tpm_class);
>  	}
>  
> -	rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
> +	tpm_rm_class = class_create(THIS_MODULE, "tpms");
> +	if (IS_ERR(tpm_rm_class)) {
> +		pr_err("couldn't create tpmrm class\n");
> +		class_destroy(tpm_class);
> +		return PTR_ERR(tpm_rm_class);
> +	}
> +
> +	rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
>  	if (rc < 0) {
>  		pr_err("tpm: failed to allocate char dev region\n");
> +		class_destroy(tpm_rm_class);
>  		class_destroy(tpm_class);
>  		return rc;
>  	}
> @@ -1232,7 +1240,8 @@ static void __exit tpm_exit(void)
>  {
>  	idr_destroy(&dev_nums_idr);
>  	class_destroy(tpm_class);
> -	unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
> +	class_destroy(tpm_rm_class);
> +	unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
>  }
>  
>  subsys_initcall(tpm_init);
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 45d997f..3346c48 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -173,8 +173,8 @@ struct tpm_chip_seqops {
>  };
>  
>  struct tpm_chip {
> -	struct device dev;
> -	struct cdev cdev;
> +	struct device dev, devrm;
> +	struct cdev cdev, cdevrm;

Again cosmetic stuff (or more like nitpicking) but I would like have one
declaration per line.

>  	/* A driver callback under ops cannot be run unless ops_sem is held
>  	 * (sometimes implicitly, eg for the sysfs code). ops becomes null
> @@ -511,8 +511,10 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
>  }
>  
>  extern struct class *tpm_class;
> +extern struct class *tpm_rm_class;
>  extern dev_t tpm_devt;
>  extern const struct file_operations tpm_fops;
> +extern const struct file_operations tpm_rm_fops;
>  extern struct idr dev_nums_idr;
>  
>  enum tpm_transmit_flags {
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> new file mode 100644
> index 0000000..c10b308
> --- /dev/null
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (C) 2017 James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org
> + *
> + * GPLv2
> + */
> +#include <linux/slab.h>
> +#include "tpm-dev.h"
> +
> +struct tpms_priv {
> +	struct file_priv priv;
> +	struct tpm_space space;
> +};
> +
> +static int tpms_open(struct inode *inode, struct file *file)
> +{
> +	struct tpm_chip *chip;
> +	struct tpms_priv *priv;
> +
> +	chip = container_of(inode->i_cdev, struct tpm_chip, cdevrm);
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (priv == NULL)
> +		return -ENOMEM;
> +	priv->space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> +	if (priv->space.context_buf == NULL) {
> +		kfree(priv);
> +		return -ENOMEM;
> +	}
> +
> +	tpm_common_open(file, chip, &priv->priv);
> +
> +	return 0;
> +}
> +
> +static int tpms_release(struct inode *inode, struct file *file)
> +{
> +	struct file_priv *fpriv = file->private_data;
> +	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> +	tpm_common_release(file, fpriv);
> +	kfree(priv);
> +
> +	return 0;
> +}
> +
> +ssize_t tpms_write(struct file *file, const char __user *buf,
> +		   size_t size, loff_t *off)
> +{
> +	struct file_priv *fpriv = file->private_data;
> +	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> +	return tpm_common_write(file, buf, size, off, &priv->space);
> +}
> +
> +const struct file_operations tpm_rm_fops = {
> +	.owner = THIS_MODULE,
> +	.llseek = no_llseek,
> +	.open = tpms_open,
> +	.read = tpm_common_read,
> +	.write = tpms_write,
> +	.release = tpms_release,
> +};
> +
> -- 
> 2.9.3
> 

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-18 15:01   ` James Bottomley
@ 2017-01-19 10:49     ` Jarkko Sakkinen
  2017-01-19 12:19       ` James Bottomley
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-19 10:49 UTC (permalink / raw)
  To: James Bottomley; +Cc: tpmdd-devel, open list, linux-security-module

On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley wrote:
> On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > 
> > Currently the Resource Manager (RM) is not exposed to userspace. 
> >  Make
> > this exposure via a separate device, which can now be opened multiple
> > times because each read/write transaction goes separately via the RM.
> > 
> > Concurrency is protected by the chip->tpm_mutex for each read/write
> > transaction separately.  The TPM is cleared of all transient objects
> > by the time the mutex is dropped, so there should be no interference
> > between the kernel and userspace.
> 
> There's actually a missing kfree of context_buf on the tpms_release
> path as well.  This patch fixes it up.

Can you send me a fresh version of the whole patch so that I can include
to v4 that includes also changes that I requested in my recent comments
+ all the fixes?

/Jarkko

> 
> James
> 
> ---
> 
> commit 778425973c532a0c1ec2b5b2ccd7ff995e2cc9db
> Author: James Bottomley <James.Bottomley@HansenPartnership.com>
> Date:   Wed Jan 18 09:58:23 2017 -0500
> 
>     add missing kfree to tpms_release
> 
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> index c10b308..6bb687f 100644
> --- a/drivers/char/tpm/tpms-dev.c
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -37,6 +37,7 @@ static int tpms_release(struct inode *inode, struct file *file)
>  	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
>  
>  	tpm_common_release(file, fpriv);
> +	kfree(priv->space.context_buf);
>  	kfree(priv);
>  
>  	return 0;
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-19 10:49     ` Jarkko Sakkinen
@ 2017-01-19 12:19       ` James Bottomley
  2017-01-20 13:39         ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-19 12:19 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: tpmdd-devel, open list, linux-security-module

[-- Attachment #1: Type: text/plain, Size: 1118 bytes --]

On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley wrote:
> > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > 
> > > Currently the Resource Manager (RM) is not exposed to userspace. 
> > >  Make this exposure via a separate device, which can now be 
> > > opened multiple times because each read/write transaction goes 
> > > separately via the RM.
> > > 
> > > Concurrency is protected by the chip->tpm_mutex for each 
> > > read/write transaction separately.  The TPM is cleared of all 
> > > transient objects by the time the mutex is dropped, so there 
> > > should be no interference between the kernel and userspace.
> > 
> > There's actually a missing kfree of context_buf on the tpms_release
> > path as well.  This patch fixes it up.
> 
> Can you send me a fresh version of the whole patch so that I can 
> include to v4 that includes also changes that I requested in my 
> recent comments + all the fixes?

Sure, I think the attached is basically it

James

[-- Attachment #2: Type: application/mbox, Size: 9092 bytes --]

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-19 12:19       ` James Bottomley
@ 2017-01-20 13:39         ` Jarkko Sakkinen
  2017-01-20 21:05             ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-20 13:39 UTC (permalink / raw)
  To: James Bottomley; +Cc: tpmdd-devel, open list, linux-security-module

On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley wrote:
> > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > > 
> > > > Currently the Resource Manager (RM) is not exposed to userspace. 
> > > >  Make this exposure via a separate device, which can now be 
> > > > opened multiple times because each read/write transaction goes 
> > > > separately via the RM.
> > > > 
> > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > read/write transaction separately.  The TPM is cleared of all 
> > > > transient objects by the time the mutex is dropped, so there 
> > > > should be no interference between the kernel and userspace.
> > > 
> > > There's actually a missing kfree of context_buf on the tpms_release
> > > path as well.  This patch fixes it up.
> > 
> > Can you send me a fresh version of the whole patch so that I can 
> > include to v4 that includes also changes that I requested in my 
> > recent comments + all the fixes?
> 
> Sure, I think the attached is basically it
> 
> James

Thank you!

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-20 21:05             ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-20 21:05 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley wrote:
> > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> > > > > 
> > > > > Currently the Resource Manager (RM) is not exposed to userspace. 
> > > > >  Make this exposure via a separate device, which can now be 
> > > > > opened multiple times because each read/write transaction goes 
> > > > > separately via the RM.
> > > > > 
> > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > read/write transaction separately.  The TPM is cleared of all 
> > > > > transient objects by the time the mutex is dropped, so there 
> > > > > should be no interference between the kernel and userspace.
> > > > 
> > > > There's actually a missing kfree of context_buf on the tpms_release
> > > > path as well.  This patch fixes it up.
> > > 
> > > Can you send me a fresh version of the whole patch so that I can 
> > > include to v4 that includes also changes that I requested in my 
> > > recent comments + all the fixes?
> > 
> > Sure, I think the attached is basically it
> > 
> > James
> 
> Thank you!

'tabrm4' branch has been now rebased. It's now on top of master branch
that contains Stefan's latest patch (min body length check) that I've
reviewed and tested. It also contains your updated /dev/tpms patch.

I guess the 5 commits that are there now are such that we have fairly
good consensus, don't we? If so, can I add your reviewed-by and
tested-by to my commits and vice versa?

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-20 21:05             ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-20 21:05 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley wrote:
> > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > From: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> > > > > 
> > > > > Currently the Resource Manager (RM) is not exposed to userspace. 
> > > > >  Make this exposure via a separate device, which can now be 
> > > > > opened multiple times because each read/write transaction goes 
> > > > > separately via the RM.
> > > > > 
> > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > read/write transaction separately.  The TPM is cleared of all 
> > > > > transient objects by the time the mutex is dropped, so there 
> > > > > should be no interference between the kernel and userspace.
> > > > 
> > > > There's actually a missing kfree of context_buf on the tpms_release
> > > > path as well.  This patch fixes it up.
> > > 
> > > Can you send me a fresh version of the whole patch so that I can 
> > > include to v4 that includes also changes that I requested in my 
> > > recent comments + all the fixes?
> > 
> > Sure, I think the attached is basically it
> > 
> > James
> 
> Thank you!

'tabrm4' branch has been now rebased. It's now on top of master branch
that contains Stefan's latest patch (min body length check) that I've
reviewed and tested. It also contains your updated /dev/tpms patch.

I guess the 5 commits that are there now are such that we have fairly
good consensus, don't we? If so, can I add your reviewed-by and
tested-by to my commits and vice versa?

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-20 21:05             ` Jarkko Sakkinen
  (?)
@ 2017-01-21 19:28             ` James Bottomley
  2017-01-22 14:49                 ` Jarkko Sakkinen
  -1 siblings, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-21 19:28 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > wrote:
> > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > From: James Bottomley <
> > > > > > James.Bottomley@HansenPartnership.com>
> > > > > > 
> > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > userspace. 
> > > > > >  Make this exposure via a separate device, which can now be
> > > > > > opened multiple times because each read/write transaction
> > > > > > goes 
> > > > > > separately via the RM.
> > > > > > 
> > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > all 
> > > > > > transient objects by the time the mutex is dropped, so
> > > > > > there 
> > > > > > should be no interference between the kernel and userspace.
> > > > > 
> > > > > There's actually a missing kfree of context_buf on the
> > > > > tpms_release
> > > > > path as well.  This patch fixes it up.
> > > > 
> > > > Can you send me a fresh version of the whole patch so that I
> > > > can 
> > > > include to v4 that includes also changes that I requested in my
> > > > recent comments + all the fixes?
> > > 
> > > Sure, I think the attached is basically it
> > > 
> > > James
> > 
> > Thank you!
> 
> 'tabrm4' branch has been now rebased. It's now on top of master
> branch
> that contains Stefan's latest patch (min body length check) that I've
> reviewed and tested. It also contains your updated /dev/tpms patch.
> 
> I guess the 5 commits that are there now are such that we have fairly
> good consensus, don't we? If so, can I add your reviewed-by and
> tested-by to my commits and vice versa?

Did you actually test it?  It doesn't work for me.  The bisected fault
commit is this one (newly introduced into the tabrm4 branch)

commit 9b7f4252655228c8d0b86e1492cc7fb3feaa5686
Author: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date:   Thu Jan 19 07:19:12 2017 -0500

    tpm: Check size of response before accessing data
 
The specific problem is that our min_rsp_length in
tpm_{load,save}_context includes a header size and the check this
introduces does the check is against the body size, meaning the load
fails because tpm_transmit_cmd thinks the response is too short.

The patch to fix this is below.

James

---
commit 480f2bb484f5a7e6100c6b0d1c79f72a05a0ca88
Author: James Bottomley <James.Bottomley@HansenPartnership.com>
Date:   Sat Jan 21 11:26:24 2017 -0800

    fix tpm_transmit_cmd min response size problem

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 4b5c714..3237d7c 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -53,7 +53,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
 	tpm_buf_append(&tbuf, &buf[*offset], body_size);
 
 	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE,
-			      TPM_HEADER_SIZE + 4, TPM_TRANSMIT_UNLOCKED, "load context");
+			      4, TPM_TRANSMIT_UNLOCKED, "load context");
 	if ((rc & TPM2_RC_HANDLE) == TPM2_RC_HANDLE) {
 		rc = -ENOENT;
 		tpm_buf_destroy(&tbuf);
@@ -89,7 +89,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
 
 	tpm_buf_append_u32(&tbuf, handle);
 
-	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, TPM_HEADER_SIZE,
+	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0,
 			      TPM_TRANSMIT_UNLOCKED, NULL);
 	if (rc < 0) {
 		dev_warn(&chip->dev, "%s: saving failed with a system error %d\n",

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-21 20:38               ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-21 20:38 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > wrote:
> > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > From: James Bottomley <
> > > > > > James.Bottomley@HansenPartnership.com>
> > > > > > 
> > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > userspace. 
> > > > > >  Make this exposure via a separate device, which can now be
> > > > > > opened multiple times because each read/write transaction
> > > > > > goes 
> > > > > > separately via the RM.
> > > > > > 
> > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > all 
> > > > > > transient objects by the time the mutex is dropped, so
> > > > > > there 
> > > > > > should be no interference between the kernel and userspace.
> > > > > 
> > > > > There's actually a missing kfree of context_buf on the
> > > > > tpms_release
> > > > > path as well.  This patch fixes it up.
> > > > 
> > > > Can you send me a fresh version of the whole patch so that I
> > > > can 
> > > > include to v4 that includes also changes that I requested in my
> > > > recent comments + all the fixes?
> > > 
> > > Sure, I think the attached is basically it
> > > 
> > > James
> > 
> > Thank you!
> 
> 'tabrm4' branch has been now rebased. It's now on top of master 
> branch that contains Stefan's latest patch (min body length check) 
> that I've reviewed and tested. It also contains your updated
> /dev/tpms patch.
> 
> I guess the 5 commits that are there now are such that we have fairly
> good consensus, don't we? If so, can I add your reviewed-by and
> tested-by to my commits and vice versa?

It looks like there's another problem: you need a continue after the
transient object is garbage collected otherwise the code falls through,
does a flush which fails and then adds a ~0 as the handle meaning we'll
have a mismatch between the saved contexts and the handles.

James

---

commit 0da3f83ce889379bd1741a11b07a30818a223924
Author: James Bottomley <James.Bottomley@HansenPartnership.com>
Date:   Sat Jan 21 12:19:06 2017 -0800

    continue after lazy reclaim

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 8713d7f..9d87537 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -288,9 +288,10 @@ static int tpm2_save_space(struct tpm_chip *chip)
 		rc = tpm2_save_context(chip, space->context_tbl[i],
 				       space->context_buf, PAGE_SIZE,
 				       &offset);
-		if (rc == -ENOENT)
+		if (rc == -ENOENT) {
 			space->context_tbl[i] = 0;
-		else if (rc) {
+			continue;
+		} else if (rc) {
 			tpm2_flush_space(chip);
 			return rc;
 		}

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-21 20:38               ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-21 20:38 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > wrote:
> > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > From: James Bottomley <
> > > > > > James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> > > > > > 
> > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > userspace. 
> > > > > >  Make this exposure via a separate device, which can now be
> > > > > > opened multiple times because each read/write transaction
> > > > > > goes 
> > > > > > separately via the RM.
> > > > > > 
> > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > all 
> > > > > > transient objects by the time the mutex is dropped, so
> > > > > > there 
> > > > > > should be no interference between the kernel and userspace.
> > > > > 
> > > > > There's actually a missing kfree of context_buf on the
> > > > > tpms_release
> > > > > path as well.  This patch fixes it up.
> > > > 
> > > > Can you send me a fresh version of the whole patch so that I
> > > > can 
> > > > include to v4 that includes also changes that I requested in my
> > > > recent comments + all the fixes?
> > > 
> > > Sure, I think the attached is basically it
> > > 
> > > James
> > 
> > Thank you!
> 
> 'tabrm4' branch has been now rebased. It's now on top of master 
> branch that contains Stefan's latest patch (min body length check) 
> that I've reviewed and tested. It also contains your updated
> /dev/tpms patch.
> 
> I guess the 5 commits that are there now are such that we have fairly
> good consensus, don't we? If so, can I add your reviewed-by and
> tested-by to my commits and vice versa?

It looks like there's another problem: you need a continue after the
transient object is garbage collected otherwise the code falls through,
does a flush which fails and then adds a ~0 as the handle meaning we'll
have a mismatch between the saved contexts and the handles.

James

---

commit 0da3f83ce889379bd1741a11b07a30818a223924
Author: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
Date:   Sat Jan 21 12:19:06 2017 -0800

    continue after lazy reclaim

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 8713d7f..9d87537 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -288,9 +288,10 @@ static int tpm2_save_space(struct tpm_chip *chip)
 		rc = tpm2_save_context(chip, space->context_tbl[i],
 				       space->context_buf, PAGE_SIZE,
 				       &offset);
-		if (rc == -ENOENT)
+		if (rc == -ENOENT) {
 			space->context_tbl[i] = 0;
-		else if (rc) {
+			continue;
+		} else if (rc) {
 			tpm2_flush_space(chip);
 			return rc;
 		}

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-22 14:49                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 14:49 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sat, Jan 21, 2017 at 11:28:55AM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > > wrote:
> > > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > > From: James Bottomley <
> > > > > > > James.Bottomley@HansenPartnership.com>
> > > > > > > 
> > > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > > userspace. 
> > > > > > >  Make this exposure via a separate device, which can now be
> > > > > > > opened multiple times because each read/write transaction
> > > > > > > goes 
> > > > > > > separately via the RM.
> > > > > > > 
> > > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > > all 
> > > > > > > transient objects by the time the mutex is dropped, so
> > > > > > > there 
> > > > > > > should be no interference between the kernel and userspace.
> > > > > > 
> > > > > > There's actually a missing kfree of context_buf on the
> > > > > > tpms_release
> > > > > > path as well.  This patch fixes it up.
> > > > > 
> > > > > Can you send me a fresh version of the whole patch so that I
> > > > > can 
> > > > > include to v4 that includes also changes that I requested in my
> > > > > recent comments + all the fixes?
> > > > 
> > > > Sure, I think the attached is basically it
> > > > 
> > > > James
> > > 
> > > Thank you!
> > 
> > 'tabrm4' branch has been now rebased. It's now on top of master
> > branch
> > that contains Stefan's latest patch (min body length check) that I've
> > reviewed and tested. It also contains your updated /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> Did you actually test it?  It doesn't work for me.  The bisected fault
> commit is this one (newly introduced into the tabrm4 branch)
> 
> commit 9b7f4252655228c8d0b86e1492cc7fb3feaa5686
> Author: Stefan Berger <stefanb@linux.vnet.ibm.com>
> Date:   Thu Jan 19 07:19:12 2017 -0500
> 
>     tpm: Check size of response before accessing data
>  
> The specific problem is that our min_rsp_length in
> tpm_{load,save}_context includes a header size and the check this
> introduces does the check is against the body size, meaning the load
> fails because tpm_transmit_cmd thinks the response is too short.
> 
> The patch to fix this is below.
> 
> James

I noticed the same thing last night. Sorry about that. It's now been
fixed. I did test it but somehow what went to my remote tree does not
have matching contents so I screwed something up at some point.

/Jarkko

> 
> ---
> commit 480f2bb484f5a7e6100c6b0d1c79f72a05a0ca88
> Author: James Bottomley <James.Bottomley@HansenPartnership.com>
> Date:   Sat Jan 21 11:26:24 2017 -0800
> 
>     fix tpm_transmit_cmd min response size problem
> 
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 4b5c714..3237d7c 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -53,7 +53,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
>  	tpm_buf_append(&tbuf, &buf[*offset], body_size);
>  
>  	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE,
> -			      TPM_HEADER_SIZE + 4, TPM_TRANSMIT_UNLOCKED, "load context");
> +			      4, TPM_TRANSMIT_UNLOCKED, "load context");
>  	if ((rc & TPM2_RC_HANDLE) == TPM2_RC_HANDLE) {
>  		rc = -ENOENT;
>  		tpm_buf_destroy(&tbuf);
> @@ -89,7 +89,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
>  
>  	tpm_buf_append_u32(&tbuf, handle);
>  
> -	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, TPM_HEADER_SIZE,
> +	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0,
>  			      TPM_TRANSMIT_UNLOCKED, NULL);
>  	if (rc < 0) {
>  		dev_warn(&chip->dev, "%s: saving failed with a system error %d\n",
> 
> 
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-22 14:49                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 14:49 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Sat, Jan 21, 2017 at 11:28:55AM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > > wrote:
> > > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > > From: James Bottomley <
> > > > > > > James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> > > > > > > 
> > > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > > userspace. 
> > > > > > >  Make this exposure via a separate device, which can now be
> > > > > > > opened multiple times because each read/write transaction
> > > > > > > goes 
> > > > > > > separately via the RM.
> > > > > > > 
> > > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > > all 
> > > > > > > transient objects by the time the mutex is dropped, so
> > > > > > > there 
> > > > > > > should be no interference between the kernel and userspace.
> > > > > > 
> > > > > > There's actually a missing kfree of context_buf on the
> > > > > > tpms_release
> > > > > > path as well.  This patch fixes it up.
> > > > > 
> > > > > Can you send me a fresh version of the whole patch so that I
> > > > > can 
> > > > > include to v4 that includes also changes that I requested in my
> > > > > recent comments + all the fixes?
> > > > 
> > > > Sure, I think the attached is basically it
> > > > 
> > > > James
> > > 
> > > Thank you!
> > 
> > 'tabrm4' branch has been now rebased. It's now on top of master
> > branch
> > that contains Stefan's latest patch (min body length check) that I've
> > reviewed and tested. It also contains your updated /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> Did you actually test it?  It doesn't work for me.  The bisected fault
> commit is this one (newly introduced into the tabrm4 branch)
> 
> commit 9b7f4252655228c8d0b86e1492cc7fb3feaa5686
> Author: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> Date:   Thu Jan 19 07:19:12 2017 -0500
> 
>     tpm: Check size of response before accessing data
>  
> The specific problem is that our min_rsp_length in
> tpm_{load,save}_context includes a header size and the check this
> introduces does the check is against the body size, meaning the load
> fails because tpm_transmit_cmd thinks the response is too short.
> 
> The patch to fix this is below.
> 
> James

I noticed the same thing last night. Sorry about that. It's now been
fixed. I did test it but somehow what went to my remote tree does not
have matching contents so I screwed something up at some point.

/Jarkko

> 
> ---
> commit 480f2bb484f5a7e6100c6b0d1c79f72a05a0ca88
> Author: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> Date:   Sat Jan 21 11:26:24 2017 -0800
> 
>     fix tpm_transmit_cmd min response size problem
> 
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 4b5c714..3237d7c 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -53,7 +53,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
>  	tpm_buf_append(&tbuf, &buf[*offset], body_size);
>  
>  	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE,
> -			      TPM_HEADER_SIZE + 4, TPM_TRANSMIT_UNLOCKED, "load context");
> +			      4, TPM_TRANSMIT_UNLOCKED, "load context");
>  	if ((rc & TPM2_RC_HANDLE) == TPM2_RC_HANDLE) {
>  		rc = -ENOENT;
>  		tpm_buf_destroy(&tbuf);
> @@ -89,7 +89,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
>  
>  	tpm_buf_append_u32(&tbuf, handle);
>  
> -	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, TPM_HEADER_SIZE,
> +	rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0,
>  			      TPM_TRANSMIT_UNLOCKED, NULL);
>  	if (rc < 0) {
>  		dev_warn(&chip->dev, "%s: saving failed with a system error %d\n",
> 
> 
> 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-22 14:49                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 14:49 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sat, Jan 21, 2017 at 12:38:56PM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > > wrote:
> > > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > > From: James Bottomley <
> > > > > > > James.Bottomley@HansenPartnership.com>
> > > > > > > 
> > > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > > userspace. 
> > > > > > >  Make this exposure via a separate device, which can now be
> > > > > > > opened multiple times because each read/write transaction
> > > > > > > goes 
> > > > > > > separately via the RM.
> > > > > > > 
> > > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > > all 
> > > > > > > transient objects by the time the mutex is dropped, so
> > > > > > > there 
> > > > > > > should be no interference between the kernel and userspace.
> > > > > > 
> > > > > > There's actually a missing kfree of context_buf on the
> > > > > > tpms_release
> > > > > > path as well.  This patch fixes it up.
> > > > > 
> > > > > Can you send me a fresh version of the whole patch so that I
> > > > > can 
> > > > > include to v4 that includes also changes that I requested in my
> > > > > recent comments + all the fixes?
> > > > 
> > > > Sure, I think the attached is basically it
> > > > 
> > > > James
> > > 
> > > Thank you!
> > 
> > 'tabrm4' branch has been now rebased. It's now on top of master 
> > branch that contains Stefan's latest patch (min body length check) 
> > that I've reviewed and tested. It also contains your updated
> > /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> It looks like there's another problem: you need a continue after the
> transient object is garbage collected otherwise the code falls through,
> does a flush which fails and then adds a ~0 as the handle meaning we'll
> have a mismatch between the saved contexts and the handles.
> 
> James

Oops, my bad. It's now fixed. Thank you!

/Jarkko

> 
> ---
> 
> commit 0da3f83ce889379bd1741a11b07a30818a223924
> Author: James Bottomley <James.Bottomley@HansenPartnership.com>
> Date:   Sat Jan 21 12:19:06 2017 -0800
> 
>     continue after lazy reclaim
> 
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 8713d7f..9d87537 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -288,9 +288,10 @@ static int tpm2_save_space(struct tpm_chip *chip)
>  		rc = tpm2_save_context(chip, space->context_tbl[i],
>  				       space->context_buf, PAGE_SIZE,
>  				       &offset);
> -		if (rc == -ENOENT)
> +		if (rc == -ENOENT) {
>  			space->context_tbl[i] = 0;
> -		else if (rc) {
> +			continue;
> +		} else if (rc) {
>  			tpm2_flush_space(chip);
>  			return rc;
>  		}

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-22 14:49                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 14:49 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Sat, Jan 21, 2017 at 12:38:56PM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > On Fri, Jan 20, 2017 at 03:39:14PM +0200, Jarkko Sakkinen wrote:
> > > On Thu, Jan 19, 2017 at 07:19:40AM -0500, James Bottomley wrote:
> > > > On Thu, 2017-01-19 at 12:49 +0200, Jarkko Sakkinen wrote:
> > > > > On Wed, Jan 18, 2017 at 10:01:03AM -0500, James Bottomley
> > > > > wrote:
> > > > > > On Mon, 2017-01-16 at 15:12 +0200, Jarkko Sakkinen wrote:
> > > > > > > From: James Bottomley <
> > > > > > > James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> > > > > > > 
> > > > > > > Currently the Resource Manager (RM) is not exposed to
> > > > > > > userspace. 
> > > > > > >  Make this exposure via a separate device, which can now be
> > > > > > > opened multiple times because each read/write transaction
> > > > > > > goes 
> > > > > > > separately via the RM.
> > > > > > > 
> > > > > > > Concurrency is protected by the chip->tpm_mutex for each 
> > > > > > > read/write transaction separately.  The TPM is cleared of
> > > > > > > all 
> > > > > > > transient objects by the time the mutex is dropped, so
> > > > > > > there 
> > > > > > > should be no interference between the kernel and userspace.
> > > > > > 
> > > > > > There's actually a missing kfree of context_buf on the
> > > > > > tpms_release
> > > > > > path as well.  This patch fixes it up.
> > > > > 
> > > > > Can you send me a fresh version of the whole patch so that I
> > > > > can 
> > > > > include to v4 that includes also changes that I requested in my
> > > > > recent comments + all the fixes?
> > > > 
> > > > Sure, I think the attached is basically it
> > > > 
> > > > James
> > > 
> > > Thank you!
> > 
> > 'tabrm4' branch has been now rebased. It's now on top of master 
> > branch that contains Stefan's latest patch (min body length check) 
> > that I've reviewed and tested. It also contains your updated
> > /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> It looks like there's another problem: you need a continue after the
> transient object is garbage collected otherwise the code falls through,
> does a flush which fails and then adds a ~0 as the handle meaning we'll
> have a mismatch between the saved contexts and the handles.
> 
> James

Oops, my bad. It's now fixed. Thank you!

/Jarkko

> 
> ---
> 
> commit 0da3f83ce889379bd1741a11b07a30818a223924
> Author: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> Date:   Sat Jan 21 12:19:06 2017 -0800
> 
>     continue after lazy reclaim
> 
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> index 8713d7f..9d87537 100644
> --- a/drivers/char/tpm/tpm2-space.c
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -288,9 +288,10 @@ static int tpm2_save_space(struct tpm_chip *chip)
>  		rc = tpm2_save_context(chip, space->context_tbl[i],
>  				       space->context_buf, PAGE_SIZE,
>  				       &offset);
> -		if (rc == -ENOENT)
> +		if (rc == -ENOENT) {
>  			space->context_tbl[i] = 0;
> -		else if (rc) {
> +			continue;
> +		} else if (rc) {
>  			tpm2_flush_space(chip);
>  			return rc;
>  		}

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-20 21:05             ` Jarkko Sakkinen
                               ` (2 preceding siblings ...)
  (?)
@ 2017-01-22 17:49             ` James Bottomley
  2017-01-22 18:48               ` James Bottomley
  2017-01-22 20:24                 ` Jarkko Sakkinen
  -1 siblings, 2 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-22 17:49 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> 'tabrm4' branch has been now rebased. It's now on top of master
> branch
> that contains Stefan's latest patch (min body length check) that I've
> reviewed and tested. It also contains your updated /dev/tpms patch.
> 
> I guess the 5 commits that are there now are such that we have fairly
> good consensus, don't we? If so, can I add your reviewed-by and
> tested-by to my commits and vice versa?

We're still failing my test_transients.  This is the full python of the
test case:


    def test_transients(self):
        k = self.open_transients()
        self.c.flush_context(k[0])
        self.c.change_auth(self.c.SRK, k[1], None, pwd1)
        ...

It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's the
same problem Ken complained about: TPM2_FlushContext doesn't have a
declared handle area so we don't translate the handle being sent down. 
 We have to fix this either by intercepting the flush and manually
translating the context, or by being dangerously clever and marking
flush as a command which takes one handle.

James

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 17:49             ` [tpmdd-devel] " James Bottomley
@ 2017-01-22 18:48               ` James Bottomley
  2017-01-22 20:30                 ` Jarkko Sakkinen
  2017-01-22 20:24                 ` Jarkko Sakkinen
  1 sibling, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-22 18:48 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > 'tabrm4' branch has been now rebased. It's now on top of master
> > branch that contains Stefan's latest patch (min body length check) 
> > that I've reviewed and tested. It also contains your updated
> > /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have 
> > fairly good consensus, don't we? If so, can I add your reviewed-by 
> > and tested-by to my commits and vice versa?
> 
> We're still failing my test_transients.  This is the full python of 
> the test case:
> 
> 
>     def test_transients(self):
>         k = self.open_transients()
>         self.c.flush_context(k[0])
>         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
>         ...
> 
> It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's 
> the same problem Ken complained about: TPM2_FlushContext doesn't have 
> a declared handle area so we don't translate the handle being sent
> down.  We have to fix this either by intercepting the flush and 
> manually translating the context, or by being dangerously clever and 
> marking flush as a command which takes one handle.

This is what the dangerously clever fix looks like.  With this and a
few other changes, my smoke tests now pass.

James

---

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index f54226d..d5517f1 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1053,9 +1053,16 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 		goto out;
 	}
 
-	for (i = 0; i < nr_commands; i++)
-		chip->cc_attrs_tbl[i] = be32_to_cpup(
-			(u32 *)&buf.data[TPM_HEADER_SIZE + 9 + 4 * i]);
+	for (i = 0; i < nr_commands; i++) {
+		u32 attr = be32_to_cpup((u32 *)&buf.data[TPM_HEADER_SIZE +
+							 9 + 4 * i]);
+		if ((attr & GENMASK(15,0)) == TPM2_CC_FLUSH_CONTEXT)
+			/* Warning: dangerous cleverness here.
+			 * Mark flush as taking a handle argument so
+			 * it gets correctly translated */
+			attr |= 1 << TPM2_CC_ATTR_CHANDLES;
+		chip->cc_attrs_tbl[i] = attr;
+	}
 
 	chip->nr_commands = nr_commands;
 	tpm_buf_destroy(&buf);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-22 20:24                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 20:24 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, Jan 22, 2017 at 09:49:02AM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > 'tabrm4' branch has been now rebased. It's now on top of master
> > branch
> > that contains Stefan's latest patch (min body length check) that I've
> > reviewed and tested. It also contains your updated /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> We're still failing my test_transients.  This is the full python of the
> test case:
> 
> 
>     def test_transients(self):
>         k = self.open_transients()
>         self.c.flush_context(k[0])
>         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
>         ...
> 
> It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's the
> same problem Ken complained about: TPM2_FlushContext doesn't have a
> declared handle area so we don't translate the handle being sent down. 
>  We have to fix this either by intercepting the flush and manually
> translating the context, or by being dangerously clever and marking
> flush as a command which takes one handle.

I'll add interception of flush to the next patch set version.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-22 20:24                 ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 20:24 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Sun, Jan 22, 2017 at 09:49:02AM -0800, James Bottomley wrote:
> On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > 'tabrm4' branch has been now rebased. It's now on top of master
> > branch
> > that contains Stefan's latest patch (min body length check) that I've
> > reviewed and tested. It also contains your updated /dev/tpms patch.
> > 
> > I guess the 5 commits that are there now are such that we have fairly
> > good consensus, don't we? If so, can I add your reviewed-by and
> > tested-by to my commits and vice versa?
> 
> We're still failing my test_transients.  This is the full python of the
> test case:
> 
> 
>     def test_transients(self):
>         k = self.open_transients()
>         self.c.flush_context(k[0])
>         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
>         ...
> 
> It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's the
> same problem Ken complained about: TPM2_FlushContext doesn't have a
> declared handle area so we don't translate the handle being sent down. 
>  We have to fix this either by intercepting the flush and manually
> translating the context, or by being dangerously clever and marking
> flush as a command which takes one handle.

I'll add interception of flush to the next patch set version.

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 18:48               ` James Bottomley
@ 2017-01-22 20:30                 ` Jarkko Sakkinen
  2017-01-22 21:01                   ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 20:30 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > 'tabrm4' branch has been now rebased. It's now on top of master
> > > branch that contains Stefan's latest patch (min body length check) 
> > > that I've reviewed and tested. It also contains your updated
> > > /dev/tpms patch.
> > > 
> > > I guess the 5 commits that are there now are such that we have 
> > > fairly good consensus, don't we? If so, can I add your reviewed-by 
> > > and tested-by to my commits and vice versa?
> > 
> > We're still failing my test_transients.  This is the full python of 
> > the test case:
> > 
> > 
> >     def test_transients(self):
> >         k = self.open_transients()
> >         self.c.flush_context(k[0])
> >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> >         ...
> > 
> > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's 
> > the same problem Ken complained about: TPM2_FlushContext doesn't have 
> > a declared handle area so we don't translate the handle being sent
> > down.  We have to fix this either by intercepting the flush and 
> > manually translating the context, or by being dangerously clever and 
> > marking flush as a command which takes one handle.
> 
> This is what the dangerously clever fix looks like.  With this and a
> few other changes, my smoke tests now pass.
> 
> James

I don't want to be clever here. I will rather intercept the body and
try to keep the core code simple and easy to understand.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 20:30                 ` Jarkko Sakkinen
@ 2017-01-22 21:01                   ` Jarkko Sakkinen
  2017-01-22 21:04                     ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 21:01 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > 'tabrm4' branch has been now rebased. It's now on top of master
> > > > branch that contains Stefan's latest patch (min body length check) 
> > > > that I've reviewed and tested. It also contains your updated
> > > > /dev/tpms patch.
> > > > 
> > > > I guess the 5 commits that are there now are such that we have 
> > > > fairly good consensus, don't we? If so, can I add your reviewed-by 
> > > > and tested-by to my commits and vice versa?
> > > 
> > > We're still failing my test_transients.  This is the full python of 
> > > the test case:
> > > 
> > > 
> > >     def test_transients(self):
> > >         k = self.open_transients()
> > >         self.c.flush_context(k[0])
> > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > >         ...
> > > 
> > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's 
> > > the same problem Ken complained about: TPM2_FlushContext doesn't have 
> > > a declared handle area so we don't translate the handle being sent
> > > down.  We have to fix this either by intercepting the flush and 
> > > manually translating the context, or by being dangerously clever and 
> > > marking flush as a command which takes one handle.
> > 
> > This is what the dangerously clever fix looks like.  With this and a
> > few other changes, my smoke tests now pass.
> > 
> > James
> 
> I don't want to be clever here. I will rather intercept the body and
> try to keep the core code simple and easy to understand.

It came out quite clean actually.

I just encapsulated handle mapping and have this in the beginning of
tpm2_map_command:

if (cc == TPM2_CC_FLUSH_CONTEXT)
	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);

I think this documents better what is actually going on than tinkering
cc_attr_tbl.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 21:01                   ` Jarkko Sakkinen
@ 2017-01-22 21:04                     ` Jarkko Sakkinen
  2017-01-22 21:36                       ` James Bottomley
  0 siblings, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-22 21:04 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > 'tabrm4' branch has been now rebased. It's now on top of master
> > > > > branch that contains Stefan's latest patch (min body length check) 
> > > > > that I've reviewed and tested. It also contains your updated
> > > > > /dev/tpms patch.
> > > > > 
> > > > > I guess the 5 commits that are there now are such that we have 
> > > > > fairly good consensus, don't we? If so, can I add your reviewed-by 
> > > > > and tested-by to my commits and vice versa?
> > > > 
> > > > We're still failing my test_transients.  This is the full python of 
> > > > the test case:
> > > > 
> > > > 
> > > >     def test_transients(self):
> > > >         k = self.open_transients()
> > > >         self.c.flush_context(k[0])
> > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > >         ...
> > > > 
> > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.  It's 
> > > > the same problem Ken complained about: TPM2_FlushContext doesn't have 
> > > > a declared handle area so we don't translate the handle being sent
> > > > down.  We have to fix this either by intercepting the flush and 
> > > > manually translating the context, or by being dangerously clever and 
> > > > marking flush as a command which takes one handle.
> > > 
> > > This is what the dangerously clever fix looks like.  With this and a
> > > few other changes, my smoke tests now pass.
> > > 
> > > James
> > 
> > I don't want to be clever here. I will rather intercept the body and
> > try to keep the core code simple and easy to understand.
> 
> It came out quite clean actually.
> 
> I just encapsulated handle mapping and have this in the beginning of
> tpm2_map_command:
> 
> if (cc == TPM2_CC_FLUSH_CONTEXT)
> 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> 
> I think this documents better what is actually going on than tinkering
> cc_attr_tbl.
> 
> /Jarkko

Actually what you suggested is much better idea because it will also
take care of validation. I'm still going to keep tpm2_map_to_phandle
because it makes the code flow a lot cleaner and probably sessions
have to anyway make it even more complicated.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 21:04                     ` Jarkko Sakkinen
@ 2017-01-22 21:36                       ` James Bottomley
  2017-01-23 14:09                         ` Jarkko Sakkinen
  0 siblings, 1 reply; 57+ messages in thread
From: James Bottomley @ 2017-01-22 21:36 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > 'tabrm4' branch has been now rebased. It's now on top of
> > > > > > master
> > > > > > branch that contains Stefan's latest patch (min body length
> > > > > > check) 
> > > > > > that I've reviewed and tested. It also contains your
> > > > > > updated
> > > > > > /dev/tpms patch.
> > > > > > 
> > > > > > I guess the 5 commits that are there now are such that we
> > > > > > have 
> > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > reviewed-by 
> > > > > > and tested-by to my commits and vice versa?
> > > > > 
> > > > > We're still failing my test_transients.  This is the full
> > > > > python of 
> > > > > the test case:
> > > > > 
> > > > > 
> > > > >     def test_transients(self):
> > > > >         k = self.open_transients()
> > > > >         self.c.flush_context(k[0])
> > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > >         ...
> > > > > 
> > > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.
> > > > >   It's 
> > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > doesn't have 
> > > > > a declared handle area so we don't translate the handle being
> > > > > sent
> > > > > down.  We have to fix this either by intercepting the flush
> > > > > and 
> > > > > manually translating the context, or by being dangerously
> > > > > clever and 
> > > > > marking flush as a command which takes one handle.
> > > > 
> > > > This is what the dangerously clever fix looks like.  With this
> > > > and a
> > > > few other changes, my smoke tests now pass.
> > > > 
> > > > James
> > > 
> > > I don't want to be clever here. I will rather intercept the body
> > > and
> > > try to keep the core code simple and easy to understand.
> > 
> > It came out quite clean actually.
> > 
> > I just encapsulated handle mapping and have this in the beginning
> > of
> > tpm2_map_command:
> > 
> > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> > 
> > I think this documents better what is actually going on than
> > tinkering
> > cc_attr_tbl.
> > 
> > /Jarkko
> 
> Actually what you suggested is much better idea because it will also
> take care of validation.

Yes, that's why it's clever ... I'm just always wary of clever code
because of the Kernighan principle.

>  I'm still going to keep tpm2_map_to_phandle because it makes the 
> code flow a lot cleaner and probably sessions have to anyway make it
> even more complicated.

OK, there's one more thing that seems to be causing problems: when
tpm2_save_context fails because the handle no longer exists (like it's
been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
session code does seem to return TPM_RC_HANDLE under some
circumstances).

James

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-22 21:36                       ` James Bottomley
@ 2017-01-23 14:09                         ` Jarkko Sakkinen
  2017-01-23 16:14                             ` James Bottomley
  2017-01-23 16:58                           ` [tpmdd-devel] " Jarkko Sakkinen
  0 siblings, 2 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-23 14:09 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > 'tabrm4' branch has been now rebased. It's now on top of
> > > > > > > master
> > > > > > > branch that contains Stefan's latest patch (min body length
> > > > > > > check) 
> > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > updated
> > > > > > > /dev/tpms patch.
> > > > > > > 
> > > > > > > I guess the 5 commits that are there now are such that we
> > > > > > > have 
> > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > reviewed-by 
> > > > > > > and tested-by to my commits and vice versa?
> > > > > > 
> > > > > > We're still failing my test_transients.  This is the full
> > > > > > python of 
> > > > > > the test case:
> > > > > > 
> > > > > > 
> > > > > >     def test_transients(self):
> > > > > >         k = self.open_transients()
> > > > > >         self.c.flush_context(k[0])
> > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > >         ...
> > > > > > 
> > > > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.
> > > > > >   It's 
> > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > doesn't have 
> > > > > > a declared handle area so we don't translate the handle being
> > > > > > sent
> > > > > > down.  We have to fix this either by intercepting the flush
> > > > > > and 
> > > > > > manually translating the context, or by being dangerously
> > > > > > clever and 
> > > > > > marking flush as a command which takes one handle.
> > > > > 
> > > > > This is what the dangerously clever fix looks like.  With this
> > > > > and a
> > > > > few other changes, my smoke tests now pass.
> > > > > 
> > > > > James
> > > > 
> > > > I don't want to be clever here. I will rather intercept the body
> > > > and
> > > > try to keep the core code simple and easy to understand.
> > > 
> > > It came out quite clean actually.
> > > 
> > > I just encapsulated handle mapping and have this in the beginning
> > > of
> > > tpm2_map_command:
> > > 
> > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> > > 
> > > I think this documents better what is actually going on than
> > > tinkering
> > > cc_attr_tbl.
> > > 
> > > /Jarkko
> > 
> > Actually what you suggested is much better idea because it will also
> > take care of validation.
> 
> Yes, that's why it's clever ... I'm just always wary of clever code
> because of the Kernighan principle.
> 
> >  I'm still going to keep tpm2_map_to_phandle because it makes the 
> > code flow a lot cleaner and probably sessions have to anyway make it
> > even more complicated.
> 
> OK, there's one more thing that seems to be causing problems: when
> tpm2_save_context fails because the handle no longer exists (like it's
> been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> session code does seem to return TPM_RC_HANDLE under some
> circumstances).
> 
> James

What is your way for reproducing this issue? Just want to add
a test case for my smoke test suite so that I can verify that
the issue is fixed once I've fixed it.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-23 16:14                             ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-23 16:14 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, 2017-01-23 at 16:09 +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > wrote:
> > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > wrote:
> > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > 'tabrm4' branch has been now rebased. It's now on top
> > > > > > > > of
> > > > > > > > master
> > > > > > > > branch that contains Stefan's latest patch (min body
> > > > > > > > length
> > > > > > > > check) 
> > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > updated
> > > > > > > > /dev/tpms patch.
> > > > > > > > 
> > > > > > > > I guess the 5 commits that are there now are such that
> > > > > > > > we
> > > > > > > > have 
> > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > reviewed-by 
> > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > 
> > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > python of 
> > > > > > > the test case:
> > > > > > > 
> > > > > > > 
> > > > > > >     def test_transients(self):
> > > > > > >         k = self.open_transients()
> > > > > > >         self.c.flush_context(k[0])
> > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > >         ...
> > > > > > > 
> > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > TPM_RC_VALUE.
> > > > > > >   It's 
> > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > doesn't have 
> > > > > > > a declared handle area so we don't translate the handle
> > > > > > > being
> > > > > > > sent
> > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > flush
> > > > > > > and 
> > > > > > > manually translating the context, or by being dangerously
> > > > > > > clever and 
> > > > > > > marking flush as a command which takes one handle.
> > > > > > 
> > > > > > This is what the dangerously clever fix looks like.  With
> > > > > > this
> > > > > > and a
> > > > > > few other changes, my smoke tests now pass.
> > > > > > 
> > > > > > James
> > > > > 
> > > > > I don't want to be clever here. I will rather intercept the
> > > > > body
> > > > > and
> > > > > try to keep the core code simple and easy to understand.
> > > > 
> > > > It came out quite clean actually.
> > > > 
> > > > I just encapsulated handle mapping and have this in the
> > > > beginning
> > > > of
> > > > tpm2_map_command:
> > > > 
> > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > 	return tpm2_map_to_phandle(space,
> > > > &cmd[TPM_HEADER_SIZE]);
> > > > 
> > > > I think this documents better what is actually going on than
> > > > tinkering
> > > > cc_attr_tbl.
> > > > 
> > > > /Jarkko
> > > 
> > > Actually what you suggested is much better idea because it will
> > > also
> > > take care of validation.
> > 
> > Yes, that's why it's clever ... I'm just always wary of clever code
> > because of the Kernighan principle.
> > 
> > >  I'm still going to keep tpm2_map_to_phandle because it makes the
> > > code flow a lot cleaner and probably sessions have to anyway make
> > > it
> > > even more complicated.
> > 
> > OK, there's one more thing that seems to be causing problems: when
> > tpm2_save_context fails because the handle no longer exists (like
> > it's
> > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > session code does seem to return TPM_RC_HANDLE under some
> > circumstances).
> > 
> > James
> 
> What is your way for reproducing this issue? Just want to add
> a test case for my smoke test suite so that I can verify that
> the issue is fixed once I've fixed it.


It's the test_handle_clearing test in tpm2_sessions_smoke.py.  It's
probably easier if I publish the current state of my mods to your tpm2
-scripts, so here they are:

http://git.kernel.org/cgit/linux/kernel/git/jejb/tpm2-scripts.git/

James

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-23 16:14                             ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-23 16:14 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Mon, 2017-01-23 at 16:09 +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > wrote:
> > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > wrote:
> > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > 'tabrm4' branch has been now rebased. It's now on top
> > > > > > > > of
> > > > > > > > master
> > > > > > > > branch that contains Stefan's latest patch (min body
> > > > > > > > length
> > > > > > > > check) 
> > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > updated
> > > > > > > > /dev/tpms patch.
> > > > > > > > 
> > > > > > > > I guess the 5 commits that are there now are such that
> > > > > > > > we
> > > > > > > > have 
> > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > reviewed-by 
> > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > 
> > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > python of 
> > > > > > > the test case:
> > > > > > > 
> > > > > > > 
> > > > > > >     def test_transients(self):
> > > > > > >         k = self.open_transients()
> > > > > > >         self.c.flush_context(k[0])
> > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > >         ...
> > > > > > > 
> > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > TPM_RC_VALUE.
> > > > > > >   It's 
> > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > doesn't have 
> > > > > > > a declared handle area so we don't translate the handle
> > > > > > > being
> > > > > > > sent
> > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > flush
> > > > > > > and 
> > > > > > > manually translating the context, or by being dangerously
> > > > > > > clever and 
> > > > > > > marking flush as a command which takes one handle.
> > > > > > 
> > > > > > This is what the dangerously clever fix looks like.  With
> > > > > > this
> > > > > > and a
> > > > > > few other changes, my smoke tests now pass.
> > > > > > 
> > > > > > James
> > > > > 
> > > > > I don't want to be clever here. I will rather intercept the
> > > > > body
> > > > > and
> > > > > try to keep the core code simple and easy to understand.
> > > > 
> > > > It came out quite clean actually.
> > > > 
> > > > I just encapsulated handle mapping and have this in the
> > > > beginning
> > > > of
> > > > tpm2_map_command:
> > > > 
> > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > 	return tpm2_map_to_phandle(space,
> > > > &cmd[TPM_HEADER_SIZE]);
> > > > 
> > > > I think this documents better what is actually going on than
> > > > tinkering
> > > > cc_attr_tbl.
> > > > 
> > > > /Jarkko
> > > 
> > > Actually what you suggested is much better idea because it will
> > > also
> > > take care of validation.
> > 
> > Yes, that's why it's clever ... I'm just always wary of clever code
> > because of the Kernighan principle.
> > 
> > >  I'm still going to keep tpm2_map_to_phandle because it makes the
> > > code flow a lot cleaner and probably sessions have to anyway make
> > > it
> > > even more complicated.
> > 
> > OK, there's one more thing that seems to be causing problems: when
> > tpm2_save_context fails because the handle no longer exists (like
> > it's
> > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > session code does seem to return TPM_RC_HANDLE under some
> > circumstances).
> > 
> > James
> 
> What is your way for reproducing this issue? Just want to add
> a test case for my smoke test suite so that I can verify that
> the issue is fixed once I've fixed it.


It's the test_handle_clearing test in tpm2_sessions_smoke.py.  It's
probably easier if I publish the current state of my mods to your tpm2
-scripts, so here they are:

http://git.kernel.org/cgit/linux/kernel/git/jejb/tpm2-scripts.git/

James





------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-23 14:09                         ` Jarkko Sakkinen
  2017-01-23 16:14                             ` James Bottomley
@ 2017-01-23 16:58                           ` Jarkko Sakkinen
  2017-01-23 21:42                               ` Jarkko Sakkinen
  1 sibling, 1 reply; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-23 16:58 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > 'tabrm4' branch has been now rebased. It's now on top of
> > > > > > > > master
> > > > > > > > branch that contains Stefan's latest patch (min body length
> > > > > > > > check) 
> > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > updated
> > > > > > > > /dev/tpms patch.
> > > > > > > > 
> > > > > > > > I guess the 5 commits that are there now are such that we
> > > > > > > > have 
> > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > reviewed-by 
> > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > 
> > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > python of 
> > > > > > > the test case:
> > > > > > > 
> > > > > > > 
> > > > > > >     def test_transients(self):
> > > > > > >         k = self.open_transients()
> > > > > > >         self.c.flush_context(k[0])
> > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > >         ...
> > > > > > > 
> > > > > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.
> > > > > > >   It's 
> > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > doesn't have 
> > > > > > > a declared handle area so we don't translate the handle being
> > > > > > > sent
> > > > > > > down.  We have to fix this either by intercepting the flush
> > > > > > > and 
> > > > > > > manually translating the context, or by being dangerously
> > > > > > > clever and 
> > > > > > > marking flush as a command which takes one handle.
> > > > > > 
> > > > > > This is what the dangerously clever fix looks like.  With this
> > > > > > and a
> > > > > > few other changes, my smoke tests now pass.
> > > > > > 
> > > > > > James
> > > > > 
> > > > > I don't want to be clever here. I will rather intercept the body
> > > > > and
> > > > > try to keep the core code simple and easy to understand.
> > > > 
> > > > It came out quite clean actually.
> > > > 
> > > > I just encapsulated handle mapping and have this in the beginning
> > > > of
> > > > tpm2_map_command:
> > > > 
> > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> > > > 
> > > > I think this documents better what is actually going on than
> > > > tinkering
> > > > cc_attr_tbl.
> > > > 
> > > > /Jarkko
> > > 
> > > Actually what you suggested is much better idea because it will also
> > > take care of validation.
> > 
> > Yes, that's why it's clever ... I'm just always wary of clever code
> > because of the Kernighan principle.
> > 
> > >  I'm still going to keep tpm2_map_to_phandle because it makes the 
> > > code flow a lot cleaner and probably sessions have to anyway make it
> > > even more complicated.
> > 
> > OK, there's one more thing that seems to be causing problems: when
> > tpm2_save_context fails because the handle no longer exists (like it's
> > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > session code does seem to return TPM_RC_HANDLE under some
> > circumstances).
> > 
> > James
> 
> What is your way for reproducing this issue? Just want to add
> a test case for my smoke test suite so that I can verify that
> the issue is fixed once I've fixed it.

Right. Too easy. Sorry about this. I'll push a fix for this to
tabrm4 branch.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-23 21:42                               ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-23 21:42 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > > 'tabrm4' branch has been now rebased. It's now on top of
> > > > > > > > > master
> > > > > > > > > branch that contains Stefan's latest patch (min body length
> > > > > > > > > check) 
> > > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > > updated
> > > > > > > > > /dev/tpms patch.
> > > > > > > > > 
> > > > > > > > > I guess the 5 commits that are there now are such that we
> > > > > > > > > have 
> > > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > > reviewed-by 
> > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > 
> > > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > > python of 
> > > > > > > > the test case:
> > > > > > > > 
> > > > > > > > 
> > > > > > > >     def test_transients(self):
> > > > > > > >         k = self.open_transients()
> > > > > > > >         self.c.flush_context(k[0])
> > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > > >         ...
> > > > > > > > 
> > > > > > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.
> > > > > > > >   It's 
> > > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > > doesn't have 
> > > > > > > > a declared handle area so we don't translate the handle being
> > > > > > > > sent
> > > > > > > > down.  We have to fix this either by intercepting the flush
> > > > > > > > and 
> > > > > > > > manually translating the context, or by being dangerously
> > > > > > > > clever and 
> > > > > > > > marking flush as a command which takes one handle.
> > > > > > > 
> > > > > > > This is what the dangerously clever fix looks like.  With this
> > > > > > > and a
> > > > > > > few other changes, my smoke tests now pass.
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > I don't want to be clever here. I will rather intercept the body
> > > > > > and
> > > > > > try to keep the core code simple and easy to understand.
> > > > > 
> > > > > It came out quite clean actually.
> > > > > 
> > > > > I just encapsulated handle mapping and have this in the beginning
> > > > > of
> > > > > tpm2_map_command:
> > > > > 
> > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> > > > > 
> > > > > I think this documents better what is actually going on than
> > > > > tinkering
> > > > > cc_attr_tbl.
> > > > > 
> > > > > /Jarkko
> > > > 
> > > > Actually what you suggested is much better idea because it will also
> > > > take care of validation.
> > > 
> > > Yes, that's why it's clever ... I'm just always wary of clever code
> > > because of the Kernighan principle.
> > > 
> > > >  I'm still going to keep tpm2_map_to_phandle because it makes the 
> > > > code flow a lot cleaner and probably sessions have to anyway make it
> > > > even more complicated.
> > > 
> > > OK, there's one more thing that seems to be causing problems: when
> > > tpm2_save_context fails because the handle no longer exists (like it's
> > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > > session code does seem to return TPM_RC_HANDLE under some
> > > circumstances).
> > > 
> > > James
> > 
> > What is your way for reproducing this issue? Just want to add
> > a test case for my smoke test suite so that I can verify that
> > the issue is fixed once I've fixed it.
> 
> Right. Too easy. Sorry about this. I'll push a fix for this to
> tabrm4 branch.

1. I pushed a fix to the repository.
2. My smoke test suite has a test case for flushing a context now.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-23 21:42                               ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-23 21:42 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley wrote:
> > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > > 'tabrm4' branch has been now rebased. It's now on top of
> > > > > > > > > master
> > > > > > > > > branch that contains Stefan's latest patch (min body length
> > > > > > > > > check) 
> > > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > > updated
> > > > > > > > > /dev/tpms patch.
> > > > > > > > > 
> > > > > > > > > I guess the 5 commits that are there now are such that we
> > > > > > > > > have 
> > > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > > reviewed-by 
> > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > 
> > > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > > python of 
> > > > > > > > the test case:
> > > > > > > > 
> > > > > > > > 
> > > > > > > >     def test_transients(self):
> > > > > > > >         k = self.open_transients()
> > > > > > > >         self.c.flush_context(k[0])
> > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > > >         ...
> > > > > > > > 
> > > > > > > > It's failing at self.c.flush_context(k[0]) with TPM_RC_VALUE.
> > > > > > > >   It's 
> > > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > > doesn't have 
> > > > > > > > a declared handle area so we don't translate the handle being
> > > > > > > > sent
> > > > > > > > down.  We have to fix this either by intercepting the flush
> > > > > > > > and 
> > > > > > > > manually translating the context, or by being dangerously
> > > > > > > > clever and 
> > > > > > > > marking flush as a command which takes one handle.
> > > > > > > 
> > > > > > > This is what the dangerously clever fix looks like.  With this
> > > > > > > and a
> > > > > > > few other changes, my smoke tests now pass.
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > I don't want to be clever here. I will rather intercept the body
> > > > > > and
> > > > > > try to keep the core code simple and easy to understand.
> > > > > 
> > > > > It came out quite clean actually.
> > > > > 
> > > > > I just encapsulated handle mapping and have this in the beginning
> > > > > of
> > > > > tpm2_map_command:
> > > > > 
> > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > 	return tpm2_map_to_phandle(space, &cmd[TPM_HEADER_SIZE]);
> > > > > 
> > > > > I think this documents better what is actually going on than
> > > > > tinkering
> > > > > cc_attr_tbl.
> > > > > 
> > > > > /Jarkko
> > > > 
> > > > Actually what you suggested is much better idea because it will also
> > > > take care of validation.
> > > 
> > > Yes, that's why it's clever ... I'm just always wary of clever code
> > > because of the Kernighan principle.
> > > 
> > > >  I'm still going to keep tpm2_map_to_phandle because it makes the 
> > > > code flow a lot cleaner and probably sessions have to anyway make it
> > > > even more complicated.
> > > 
> > > OK, there's one more thing that seems to be causing problems: when
> > > tpm2_save_context fails because the handle no longer exists (like it's
> > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > > session code does seem to return TPM_RC_HANDLE under some
> > > circumstances).
> > > 
> > > James
> > 
> > What is your way for reproducing this issue? Just want to add
> > a test case for my smoke test suite so that I can verify that
> > the issue is fixed once I've fixed it.
> 
> Right. Too easy. Sorry about this. I'll push a fix for this to
> tabrm4 branch.

1. I pushed a fix to the repository.
2. My smoke test suite has a test case for flushing a context now.

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-23 22:16                                 ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-23 22:16 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > > wrote:
> > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > > wrote:
> > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > wrote:
> > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen
> > > > > > > > > wrote:
> > > > > > > > > > 'tabrm4' branch has been now rebased. It's now on
> > > > > > > > > > top of
> > > > > > > > > > master
> > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > body length
> > > > > > > > > > check) 
> > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > your
> > > > > > > > > > updated
> > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > 
> > > > > > > > > > I guess the 5 commits that are there now are such
> > > > > > > > > > that we
> > > > > > > > > > have 
> > > > > > > > > > fairly good consensus, don't we? If so, can I add
> > > > > > > > > > your
> > > > > > > > > > reviewed-by 
> > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > 
> > > > > > > > > We're still failing my test_transients.  This is the
> > > > > > > > > full
> > > > > > > > > python of 
> > > > > > > > > the test case:
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > >     def test_transients(self):
> > > > > > > > >         k = self.open_transients()
> > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None,
> > > > > > > > > pwd1)
> > > > > > > > >         ...
> > > > > > > > > 
> > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > TPM_RC_VALUE.
> > > > > > > > >   It's 
> > > > > > > > > the same problem Ken complained about:
> > > > > > > > > TPM2_FlushContext
> > > > > > > > > doesn't have 
> > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > handle being
> > > > > > > > > sent
> > > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > > flush
> > > > > > > > > and 
> > > > > > > > > manually translating the context, or by being
> > > > > > > > > dangerously
> > > > > > > > > clever and 
> > > > > > > > > marking flush as a command which takes one handle.
> > > > > > > > 
> > > > > > > > This is what the dangerously clever fix looks like. 
> > > > > > > >  With this
> > > > > > > > and a
> > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > 
> > > > > > > > James
> > > > > > > 
> > > > > > > I don't want to be clever here. I will rather intercept
> > > > > > > the body
> > > > > > > and
> > > > > > > try to keep the core code simple and easy to understand.
> > > > > > 
> > > > > > It came out quite clean actually.
> > > > > > 
> > > > > > I just encapsulated handle mapping and have this in the
> > > > > > beginning
> > > > > > of
> > > > > > tpm2_map_command:
> > > > > > 
> > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > 
> > > > > > I think this documents better what is actually going on
> > > > > > than
> > > > > > tinkering
> > > > > > cc_attr_tbl.
> > > > > > 
> > > > > > /Jarkko
> > > > > 
> > > > > Actually what you suggested is much better idea because it
> > > > > will also
> > > > > take care of validation.
> > > > 
> > > > Yes, that's why it's clever ... I'm just always wary of clever
> > > > code
> > > > because of the Kernighan principle.
> > > > 
> > > > >  I'm still going to keep tpm2_map_to_phandle because it makes
> > > > > the 
> > > > > code flow a lot cleaner and probably sessions have to anyway
> > > > > make it
> > > > > even more complicated.
> > > > 
> > > > OK, there's one more thing that seems to be causing problems:
> > > > when
> > > > tpm2_save_context fails because the handle no longer exists
> > > > (like it's
> > > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE
> > > > (the
> > > > session code does seem to return TPM_RC_HANDLE under some
> > > > circumstances).
> > > > 
> > > > James
> > > 
> > > What is your way for reproducing this issue? Just want to add
> > > a test case for my smoke test suite so that I can verify that
> > > the issue is fixed once I've fixed it.
> > 
> > Right. Too easy. Sorry about this. I'll push a fix for this to
> > tabrm4 branch.
> 
> 1. I pushed a fix to the repository.

I don't think the fix is right; this is what you now have

	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
{

That should be

} else if (rc == TPM2_RC_REFERENCE_H0)

because the 0x9XX return codes don't have any parameter information
that needs stripping and (rc & TPM2_RC_REFERENCE_H0) ==
TPM2_RC_REFERENCE_H0)  will match any error code that has bits 11, 8
and 5 set.

I think the handle check was wrong too, it should have been

if (rc & 0xff) == TPM2_RC_HANDLE)

Because all you need to do is strip off the parameter information

James

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-23 22:16                                 ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-23 22:16 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > > wrote:
> > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > > wrote:
> > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > wrote:
> > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen
> > > > > > > > > wrote:
> > > > > > > > > > 'tabrm4' branch has been now rebased. It's now on
> > > > > > > > > > top of
> > > > > > > > > > master
> > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > body length
> > > > > > > > > > check) 
> > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > your
> > > > > > > > > > updated
> > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > 
> > > > > > > > > > I guess the 5 commits that are there now are such
> > > > > > > > > > that we
> > > > > > > > > > have 
> > > > > > > > > > fairly good consensus, don't we? If so, can I add
> > > > > > > > > > your
> > > > > > > > > > reviewed-by 
> > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > 
> > > > > > > > > We're still failing my test_transients.  This is the
> > > > > > > > > full
> > > > > > > > > python of 
> > > > > > > > > the test case:
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > >     def test_transients(self):
> > > > > > > > >         k = self.open_transients()
> > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None,
> > > > > > > > > pwd1)
> > > > > > > > >         ...
> > > > > > > > > 
> > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > TPM_RC_VALUE.
> > > > > > > > >   It's 
> > > > > > > > > the same problem Ken complained about:
> > > > > > > > > TPM2_FlushContext
> > > > > > > > > doesn't have 
> > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > handle being
> > > > > > > > > sent
> > > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > > flush
> > > > > > > > > and 
> > > > > > > > > manually translating the context, or by being
> > > > > > > > > dangerously
> > > > > > > > > clever and 
> > > > > > > > > marking flush as a command which takes one handle.
> > > > > > > > 
> > > > > > > > This is what the dangerously clever fix looks like. 
> > > > > > > >  With this
> > > > > > > > and a
> > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > 
> > > > > > > > James
> > > > > > > 
> > > > > > > I don't want to be clever here. I will rather intercept
> > > > > > > the body
> > > > > > > and
> > > > > > > try to keep the core code simple and easy to understand.
> > > > > > 
> > > > > > It came out quite clean actually.
> > > > > > 
> > > > > > I just encapsulated handle mapping and have this in the
> > > > > > beginning
> > > > > > of
> > > > > > tpm2_map_command:
> > > > > > 
> > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > 
> > > > > > I think this documents better what is actually going on
> > > > > > than
> > > > > > tinkering
> > > > > > cc_attr_tbl.
> > > > > > 
> > > > > > /Jarkko
> > > > > 
> > > > > Actually what you suggested is much better idea because it
> > > > > will also
> > > > > take care of validation.
> > > > 
> > > > Yes, that's why it's clever ... I'm just always wary of clever
> > > > code
> > > > because of the Kernighan principle.
> > > > 
> > > > >  I'm still going to keep tpm2_map_to_phandle because it makes
> > > > > the 
> > > > > code flow a lot cleaner and probably sessions have to anyway
> > > > > make it
> > > > > even more complicated.
> > > > 
> > > > OK, there's one more thing that seems to be causing problems:
> > > > when
> > > > tpm2_save_context fails because the handle no longer exists
> > > > (like it's
> > > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE
> > > > (the
> > > > session code does seem to return TPM_RC_HANDLE under some
> > > > circumstances).
> > > > 
> > > > James
> > > 
> > > What is your way for reproducing this issue? Just want to add
> > > a test case for my smoke test suite so that I can verify that
> > > the issue is fixed once I've fixed it.
> > 
> > Right. Too easy. Sorry about this. I'll push a fix for this to
> > tabrm4 branch.
> 
> 1. I pushed a fix to the repository.

I don't think the fix is right; this is what you now have

	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
{

That should be

} else if (rc == TPM2_RC_REFERENCE_H0)

because the 0x9XX return codes don't have any parameter information
that needs stripping and (rc & TPM2_RC_REFERENCE_H0) ==
TPM2_RC_REFERENCE_H0)  will match any error code that has bits 11, 8
and 5 set.

I think the handle check was wrong too, it should have been

if (rc & 0xff) == TPM2_RC_HANDLE)

Because all you need to do is strip off the parameter information

James



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
@ 2017-01-24 12:03                               ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-24 12:03 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, Jan 23, 2017 at 08:14:55AM -0800, James Bottomley wrote:
> On Mon, 2017-01-23 at 16:09 +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > wrote:
> > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > > 'tabrm4' branch has been now rebased. It's now on top
> > > > > > > > > of
> > > > > > > > > master
> > > > > > > > > branch that contains Stefan's latest patch (min body
> > > > > > > > > length
> > > > > > > > > check) 
> > > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > > updated
> > > > > > > > > /dev/tpms patch.
> > > > > > > > > 
> > > > > > > > > I guess the 5 commits that are there now are such that
> > > > > > > > > we
> > > > > > > > > have 
> > > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > > reviewed-by 
> > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > 
> > > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > > python of 
> > > > > > > > the test case:
> > > > > > > > 
> > > > > > > > 
> > > > > > > >     def test_transients(self):
> > > > > > > >         k = self.open_transients()
> > > > > > > >         self.c.flush_context(k[0])
> > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > > >         ...
> > > > > > > > 
> > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > TPM_RC_VALUE.
> > > > > > > >   It's 
> > > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > > doesn't have 
> > > > > > > > a declared handle area so we don't translate the handle
> > > > > > > > being
> > > > > > > > sent
> > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > flush
> > > > > > > > and 
> > > > > > > > manually translating the context, or by being dangerously
> > > > > > > > clever and 
> > > > > > > > marking flush as a command which takes one handle.
> > > > > > > 
> > > > > > > This is what the dangerously clever fix looks like.  With
> > > > > > > this
> > > > > > > and a
> > > > > > > few other changes, my smoke tests now pass.
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > I don't want to be clever here. I will rather intercept the
> > > > > > body
> > > > > > and
> > > > > > try to keep the core code simple and easy to understand.
> > > > > 
> > > > > It came out quite clean actually.
> > > > > 
> > > > > I just encapsulated handle mapping and have this in the
> > > > > beginning
> > > > > of
> > > > > tpm2_map_command:
> > > > > 
> > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > 	return tpm2_map_to_phandle(space,
> > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > 
> > > > > I think this documents better what is actually going on than
> > > > > tinkering
> > > > > cc_attr_tbl.
> > > > > 
> > > > > /Jarkko
> > > > 
> > > > Actually what you suggested is much better idea because it will
> > > > also
> > > > take care of validation.
> > > 
> > > Yes, that's why it's clever ... I'm just always wary of clever code
> > > because of the Kernighan principle.
> > > 
> > > >  I'm still going to keep tpm2_map_to_phandle because it makes the
> > > > code flow a lot cleaner and probably sessions have to anyway make
> > > > it
> > > > even more complicated.
> > > 
> > > OK, there's one more thing that seems to be causing problems: when
> > > tpm2_save_context fails because the handle no longer exists (like
> > > it's
> > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > > session code does seem to return TPM_RC_HANDLE under some
> > > circumstances).
> > > 
> > > James
> > 
> > What is your way for reproducing this issue? Just want to add
> > a test case for my smoke test suite so that I can verify that
> > the issue is fixed once I've fixed it.
> 
> 
> It's the test_handle_clearing test in tpm2_sessions_smoke.py.  It's
> probably easier if I publish the current state of my mods to your tpm2
> -scripts, so here they are:
> 
> http://git.kernel.org/cgit/linux/kernel/git/jejb/tpm2-scripts.git/

Thanks. I think you can use also this list to send updates to my
test scripts in future.

> James

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-24 12:03                               ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-24 12:03 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Mon, Jan 23, 2017 at 08:14:55AM -0800, James Bottomley wrote:
> On Mon, 2017-01-23 at 16:09 +0200, Jarkko Sakkinen wrote:
> > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > wrote:
> > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley wrote:
> > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen wrote:
> > > > > > > > > 'tabrm4' branch has been now rebased. It's now on top
> > > > > > > > > of
> > > > > > > > > master
> > > > > > > > > branch that contains Stefan's latest patch (min body
> > > > > > > > > length
> > > > > > > > > check) 
> > > > > > > > > that I've reviewed and tested. It also contains your
> > > > > > > > > updated
> > > > > > > > > /dev/tpms patch.
> > > > > > > > > 
> > > > > > > > > I guess the 5 commits that are there now are such that
> > > > > > > > > we
> > > > > > > > > have 
> > > > > > > > > fairly good consensus, don't we? If so, can I add your
> > > > > > > > > reviewed-by 
> > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > 
> > > > > > > > We're still failing my test_transients.  This is the full
> > > > > > > > python of 
> > > > > > > > the test case:
> > > > > > > > 
> > > > > > > > 
> > > > > > > >     def test_transients(self):
> > > > > > > >         k = self.open_transients()
> > > > > > > >         self.c.flush_context(k[0])
> > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None, pwd1)
> > > > > > > >         ...
> > > > > > > > 
> > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > TPM_RC_VALUE.
> > > > > > > >   It's 
> > > > > > > > the same problem Ken complained about: TPM2_FlushContext
> > > > > > > > doesn't have 
> > > > > > > > a declared handle area so we don't translate the handle
> > > > > > > > being
> > > > > > > > sent
> > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > flush
> > > > > > > > and 
> > > > > > > > manually translating the context, or by being dangerously
> > > > > > > > clever and 
> > > > > > > > marking flush as a command which takes one handle.
> > > > > > > 
> > > > > > > This is what the dangerously clever fix looks like.  With
> > > > > > > this
> > > > > > > and a
> > > > > > > few other changes, my smoke tests now pass.
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > I don't want to be clever here. I will rather intercept the
> > > > > > body
> > > > > > and
> > > > > > try to keep the core code simple and easy to understand.
> > > > > 
> > > > > It came out quite clean actually.
> > > > > 
> > > > > I just encapsulated handle mapping and have this in the
> > > > > beginning
> > > > > of
> > > > > tpm2_map_command:
> > > > > 
> > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > 	return tpm2_map_to_phandle(space,
> > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > 
> > > > > I think this documents better what is actually going on than
> > > > > tinkering
> > > > > cc_attr_tbl.
> > > > > 
> > > > > /Jarkko
> > > > 
> > > > Actually what you suggested is much better idea because it will
> > > > also
> > > > take care of validation.
> > > 
> > > Yes, that's why it's clever ... I'm just always wary of clever code
> > > because of the Kernighan principle.
> > > 
> > > >  I'm still going to keep tpm2_map_to_phandle because it makes the
> > > > code flow a lot cleaner and probably sessions have to anyway make
> > > > it
> > > > even more complicated.
> > > 
> > > OK, there's one more thing that seems to be causing problems: when
> > > tpm2_save_context fails because the handle no longer exists (like
> > > it's
> > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE (the
> > > session code does seem to return TPM_RC_HANDLE under some
> > > circumstances).
> > > 
> > > James
> > 
> > What is your way for reproducing this issue? Just want to add
> > a test case for my smoke test suite so that I can verify that
> > the issue is fixed once I've fixed it.
> 
> 
> It's the test_handle_clearing test in tpm2_sessions_smoke.py.  It's
> probably easier if I publish the current state of my mods to your tpm2
> -scripts, so here they are:
> 
> http://git.kernel.org/cgit/linux/kernel/git/jejb/tpm2-scripts.git/

Thanks. I think you can use also this list to send updates to my
test scripts in future.

> James

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-23 22:16                                 ` James Bottomley
  (?)
@ 2017-01-25 13:40                                 ` Jarkko Sakkinen
  2017-01-25 13:42                                   ` Jarkko Sakkinen
  2017-01-27  0:29                                     ` James Bottomley
  -1 siblings, 2 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-25 13:40 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > wrote:
> > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > > > wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > > > wrote:
> > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > wrote:
> > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen
> > > > > > > > > > wrote:
> > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now on
> > > > > > > > > > > top of
> > > > > > > > > > > master
> > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > body length
> > > > > > > > > > > check) 
> > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > your
> > > > > > > > > > > updated
> > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > 
> > > > > > > > > > > I guess the 5 commits that are there now are such
> > > > > > > > > > > that we
> > > > > > > > > > > have 
> > > > > > > > > > > fairly good consensus, don't we? If so, can I add
> > > > > > > > > > > your
> > > > > > > > > > > reviewed-by 
> > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > 
> > > > > > > > > > We're still failing my test_transients.  This is the
> > > > > > > > > > full
> > > > > > > > > > python of 
> > > > > > > > > > the test case:
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > >     def test_transients(self):
> > > > > > > > > >         k = self.open_transients()
> > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None,
> > > > > > > > > > pwd1)
> > > > > > > > > >         ...
> > > > > > > > > > 
> > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > >   It's 
> > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > doesn't have 
> > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > handle being
> > > > > > > > > > sent
> > > > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > > > flush
> > > > > > > > > > and 
> > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > dangerously
> > > > > > > > > > clever and 
> > > > > > > > > > marking flush as a command which takes one handle.
> > > > > > > > > 
> > > > > > > > > This is what the dangerously clever fix looks like. 
> > > > > > > > >  With this
> > > > > > > > > and a
> > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > 
> > > > > > > > > James
> > > > > > > > 
> > > > > > > > I don't want to be clever here. I will rather intercept
> > > > > > > > the body
> > > > > > > > and
> > > > > > > > try to keep the core code simple and easy to understand.
> > > > > > > 
> > > > > > > It came out quite clean actually.
> > > > > > > 
> > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > beginning
> > > > > > > of
> > > > > > > tpm2_map_command:
> > > > > > > 
> > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > 
> > > > > > > I think this documents better what is actually going on
> > > > > > > than
> > > > > > > tinkering
> > > > > > > cc_attr_tbl.
> > > > > > > 
> > > > > > > /Jarkko
> > > > > > 
> > > > > > Actually what you suggested is much better idea because it
> > > > > > will also
> > > > > > take care of validation.
> > > > > 
> > > > > Yes, that's why it's clever ... I'm just always wary of clever
> > > > > code
> > > > > because of the Kernighan principle.
> > > > > 
> > > > > >  I'm still going to keep tpm2_map_to_phandle because it makes
> > > > > > the 
> > > > > > code flow a lot cleaner and probably sessions have to anyway
> > > > > > make it
> > > > > > even more complicated.
> > > > > 
> > > > > OK, there's one more thing that seems to be causing problems:
> > > > > when
> > > > > tpm2_save_context fails because the handle no longer exists
> > > > > (like it's
> > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE
> > > > > (the
> > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > circumstances).
> > > > > 
> > > > > James
> > > > 
> > > > What is your way for reproducing this issue? Just want to add
> > > > a test case for my smoke test suite so that I can verify that
> > > > the issue is fixed once I've fixed it.
> > > 
> > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > tabrm4 branch.
> > 
> > 1. I pushed a fix to the repository.
> 
> I don't think the fix is right; this is what you now have
> 
> 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> {
> 
> That should be
> 
> } else if (rc == TPM2_RC_REFERENCE_H0)

Right I see your point.

And yes, also for RC_HANDLE the error handling was done incorrectly.  It
should be masked like you said with 0xff to catch error number and the F
flag (bit 7).

As it is format zero error code it should be fine to check without any
mask.

Thanks for noting this. It is easy to shoot yourself into foot when
there's lot of stuff packed :-)

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-25 13:40                                 ` [tpmdd-devel] " Jarkko Sakkinen
@ 2017-01-25 13:42                                   ` Jarkko Sakkinen
  2017-01-27  0:29                                     ` James Bottomley
  1 sibling, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-25 13:42 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Wed, Jan 25, 2017 at 03:40:04PM +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> > On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > > wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > > > > wrote:
> > > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > > > > wrote:
> > > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > > wrote:
> > > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen
> > > > > > > > > > > wrote:
> > > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now on
> > > > > > > > > > > > top of
> > > > > > > > > > > > master
> > > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > > body length
> > > > > > > > > > > > check) 
> > > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > > your
> > > > > > > > > > > > updated
> > > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > > 
> > > > > > > > > > > > I guess the 5 commits that are there now are such
> > > > > > > > > > > > that we
> > > > > > > > > > > > have 
> > > > > > > > > > > > fairly good consensus, don't we? If so, can I add
> > > > > > > > > > > > your
> > > > > > > > > > > > reviewed-by 
> > > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > > 
> > > > > > > > > > > We're still failing my test_transients.  This is the
> > > > > > > > > > > full
> > > > > > > > > > > python of 
> > > > > > > > > > > the test case:
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > >     def test_transients(self):
> > > > > > > > > > >         k = self.open_transients()
> > > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None,
> > > > > > > > > > > pwd1)
> > > > > > > > > > >         ...
> > > > > > > > > > > 
> > > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > > >   It's 
> > > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > > doesn't have 
> > > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > > handle being
> > > > > > > > > > > sent
> > > > > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > > > > flush
> > > > > > > > > > > and 
> > > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > > dangerously
> > > > > > > > > > > clever and 
> > > > > > > > > > > marking flush as a command which takes one handle.
> > > > > > > > > > 
> > > > > > > > > > This is what the dangerously clever fix looks like. 
> > > > > > > > > >  With this
> > > > > > > > > > and a
> > > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > > 
> > > > > > > > > > James
> > > > > > > > > 
> > > > > > > > > I don't want to be clever here. I will rather intercept
> > > > > > > > > the body
> > > > > > > > > and
> > > > > > > > > try to keep the core code simple and easy to understand.
> > > > > > > > 
> > > > > > > > It came out quite clean actually.
> > > > > > > > 
> > > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > > beginning
> > > > > > > > of
> > > > > > > > tpm2_map_command:
> > > > > > > > 
> > > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > > 
> > > > > > > > I think this documents better what is actually going on
> > > > > > > > than
> > > > > > > > tinkering
> > > > > > > > cc_attr_tbl.
> > > > > > > > 
> > > > > > > > /Jarkko
> > > > > > > 
> > > > > > > Actually what you suggested is much better idea because it
> > > > > > > will also
> > > > > > > take care of validation.
> > > > > > 
> > > > > > Yes, that's why it's clever ... I'm just always wary of clever
> > > > > > code
> > > > > > because of the Kernighan principle.
> > > > > > 
> > > > > > >  I'm still going to keep tpm2_map_to_phandle because it makes
> > > > > > > the 
> > > > > > > code flow a lot cleaner and probably sessions have to anyway
> > > > > > > make it
> > > > > > > even more complicated.
> > > > > > 
> > > > > > OK, there's one more thing that seems to be causing problems:
> > > > > > when
> > > > > > tpm2_save_context fails because the handle no longer exists
> > > > > > (like it's
> > > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE
> > > > > > (the
> > > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > > circumstances).
> > > > > > 
> > > > > > James
> > > > > 
> > > > > What is your way for reproducing this issue? Just want to add
> > > > > a test case for my smoke test suite so that I can verify that
> > > > > the issue is fixed once I've fixed it.
> > > > 
> > > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > > tabrm4 branch.
> > > 
> > > 1. I pushed a fix to the repository.
> > 
> > I don't think the fix is right; this is what you now have
> > 
> > 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> > {
> > 
> > That should be
> > 
> > } else if (rc == TPM2_RC_REFERENCE_H0)
> 
> Right I see your point.
> 
> And yes, also for RC_HANDLE the error handling was done incorrectly.  It
> should be masked like you said with 0xff to catch error number and the F
> flag (bit 7).
> 
> As it is format zero error code it should be fine to check without any
> mask.
> 
> Thanks for noting this. It is easy to shoot yourself into foot when
> there's lot of stuff packed :-)
> 
> /Jarkko

I think I actually add a helper to tpm.h to get the error number.

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via    a device link /dev/tpms<n>
  2017-01-23 22:16                                 ` James Bottomley
  (?)
  (?)
@ 2017-01-25 20:23                                 ` Jarkko Sakkinen
  -1 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-25 20:23 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen wrote:
> > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley wrote:
> > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > wrote:
> > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko Sakkinen
> > > > > > > wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James Bottomley
> > > > > > > > wrote:
> > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > wrote:
> > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko Sakkinen
> > > > > > > > > > wrote:
> > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now on
> > > > > > > > > > > top of
> > > > > > > > > > > master
> > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > body length
> > > > > > > > > > > check) 
> > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > your
> > > > > > > > > > > updated
> > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > 
> > > > > > > > > > > I guess the 5 commits that are there now are such
> > > > > > > > > > > that we
> > > > > > > > > > > have 
> > > > > > > > > > > fairly good consensus, don't we? If so, can I add
> > > > > > > > > > > your
> > > > > > > > > > > reviewed-by 
> > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > 
> > > > > > > > > > We're still failing my test_transients.  This is the
> > > > > > > > > > full
> > > > > > > > > > python of 
> > > > > > > > > > the test case:
> > > > > > > > > > 
> > > > > > > > > > 
> > > > > > > > > >     def test_transients(self):
> > > > > > > > > >         k = self.open_transients()
> > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1], None,
> > > > > > > > > > pwd1)
> > > > > > > > > >         ...
> > > > > > > > > > 
> > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > >   It's 
> > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > doesn't have 
> > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > handle being
> > > > > > > > > > sent
> > > > > > > > > > down.  We have to fix this either by intercepting the
> > > > > > > > > > flush
> > > > > > > > > > and 
> > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > dangerously
> > > > > > > > > > clever and 
> > > > > > > > > > marking flush as a command which takes one handle.
> > > > > > > > > 
> > > > > > > > > This is what the dangerously clever fix looks like. 
> > > > > > > > >  With this
> > > > > > > > > and a
> > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > 
> > > > > > > > > James
> > > > > > > > 
> > > > > > > > I don't want to be clever here. I will rather intercept
> > > > > > > > the body
> > > > > > > > and
> > > > > > > > try to keep the core code simple and easy to understand.
> > > > > > > 
> > > > > > > It came out quite clean actually.
> > > > > > > 
> > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > beginning
> > > > > > > of
> > > > > > > tpm2_map_command:
> > > > > > > 
> > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > 
> > > > > > > I think this documents better what is actually going on
> > > > > > > than
> > > > > > > tinkering
> > > > > > > cc_attr_tbl.
> > > > > > > 
> > > > > > > /Jarkko
> > > > > > 
> > > > > > Actually what you suggested is much better idea because it
> > > > > > will also
> > > > > > take care of validation.
> > > > > 
> > > > > Yes, that's why it's clever ... I'm just always wary of clever
> > > > > code
> > > > > because of the Kernighan principle.
> > > > > 
> > > > > >  I'm still going to keep tpm2_map_to_phandle because it makes
> > > > > > the 
> > > > > > code flow a lot cleaner and probably sessions have to anyway
> > > > > > make it
> > > > > > even more complicated.
> > > > > 
> > > > > OK, there's one more thing that seems to be causing problems:
> > > > > when
> > > > > tpm2_save_context fails because the handle no longer exists
> > > > > (like it's
> > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not TPM_RC_HANDLE
> > > > > (the
> > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > circumstances).
> > > > > 
> > > > > James
> > > > 
> > > > What is your way for reproducing this issue? Just want to add
> > > > a test case for my smoke test suite so that I can verify that
> > > > the issue is fixed once I've fixed it.
> > > 
> > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > tabrm4 branch.
> > 
> > 1. I pushed a fix to the repository.
> 
> I don't think the fix is right; this is what you now have
> 
> 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> {
> 
> That should be
> 
> } else if (rc == TPM2_RC_REFERENCE_H0)
> 
> because the 0x9XX return codes don't have any parameter information
> that needs stripping and (rc & TPM2_RC_REFERENCE_H0) ==
> TPM2_RC_REFERENCE_H0)  will match any error code that has bits 11, 8
> and 5 set.
> 
> I think the handle check was wrong too, it should have been
> 
> if (rc & 0xff) == TPM2_RC_HANDLE)
> 
> Because all you need to do is strip off the parameter information
> 
> James

Can you check if it is now what you would expect? There's now
a helper called tpm2_rc_value(). I also created tabrm5 branch
where everything is nicely squashed together...

/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-27  0:29                                     ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-27  0:29 UTC (permalink / raw)
  To: Jarkko Sakkinen; +Cc: linux-security-module, tpmdd-devel, open list

On Wed, 2017-01-25 at 15:40 +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> > On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen
> > > > wrote:
> > > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley
> > > > > wrote:
> > > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > > wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko
> > > > > > > > Sakkinen
> > > > > > > > wrote:
> > > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James
> > > > > > > > > Bottomley
> > > > > > > > > wrote:
> > > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > > wrote:
> > > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko
> > > > > > > > > > > Sakkinen
> > > > > > > > > > > wrote:
> > > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now
> > > > > > > > > > > > on
> > > > > > > > > > > > top of
> > > > > > > > > > > > master
> > > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > > body length
> > > > > > > > > > > > check) 
> > > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > > your
> > > > > > > > > > > > updated
> > > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > > 
> > > > > > > > > > > > I guess the 5 commits that are there now are
> > > > > > > > > > > > such
> > > > > > > > > > > > that we
> > > > > > > > > > > > have 
> > > > > > > > > > > > fairly good consensus, don't we? If so, can I
> > > > > > > > > > > > add
> > > > > > > > > > > > your
> > > > > > > > > > > > reviewed-by 
> > > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > > 
> > > > > > > > > > > We're still failing my test_transients.  This is
> > > > > > > > > > > the
> > > > > > > > > > > full
> > > > > > > > > > > python of 
> > > > > > > > > > > the test case:
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > >     def test_transients(self):
> > > > > > > > > > >         k = self.open_transients()
> > > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1],
> > > > > > > > > > > None,
> > > > > > > > > > > pwd1)
> > > > > > > > > > >         ...
> > > > > > > > > > > 
> > > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > > >   It's 
> > > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > > doesn't have 
> > > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > > handle being
> > > > > > > > > > > sent
> > > > > > > > > > > down.  We have to fix this either by intercepting
> > > > > > > > > > > the
> > > > > > > > > > > flush
> > > > > > > > > > > and 
> > > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > > dangerously
> > > > > > > > > > > clever and 
> > > > > > > > > > > marking flush as a command which takes one
> > > > > > > > > > > handle.
> > > > > > > > > > 
> > > > > > > > > > This is what the dangerously clever fix looks like.
> > > > > > > > > >  With this
> > > > > > > > > > and a
> > > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > > 
> > > > > > > > > > James
> > > > > > > > > 
> > > > > > > > > I don't want to be clever here. I will rather
> > > > > > > > > intercept
> > > > > > > > > the body
> > > > > > > > > and
> > > > > > > > > try to keep the core code simple and easy to
> > > > > > > > > understand.
> > > > > > > > 
> > > > > > > > It came out quite clean actually.
> > > > > > > > 
> > > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > > beginning
> > > > > > > > of
> > > > > > > > tpm2_map_command:
> > > > > > > > 
> > > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > > 
> > > > > > > > I think this documents better what is actually going on
> > > > > > > > than
> > > > > > > > tinkering
> > > > > > > > cc_attr_tbl.
> > > > > > > > 
> > > > > > > > /Jarkko
> > > > > > > 
> > > > > > > Actually what you suggested is much better idea because
> > > > > > > it
> > > > > > > will also
> > > > > > > take care of validation.
> > > > > > 
> > > > > > Yes, that's why it's clever ... I'm just always wary of
> > > > > > clever
> > > > > > code
> > > > > > because of the Kernighan principle.
> > > > > > 
> > > > > > >  I'm still going to keep tpm2_map_to_phandle because it
> > > > > > > makes
> > > > > > > the 
> > > > > > > code flow a lot cleaner and probably sessions have to
> > > > > > > anyway
> > > > > > > make it
> > > > > > > even more complicated.
> > > > > > 
> > > > > > OK, there's one more thing that seems to be causing
> > > > > > problems:
> > > > > > when
> > > > > > tpm2_save_context fails because the handle no longer exists
> > > > > > (like it's
> > > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not
> > > > > > TPM_RC_HANDLE
> > > > > > (the
> > > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > > circumstances).
> > > > > > 
> > > > > > James
> > > > > 
> > > > > What is your way for reproducing this issue? Just want to add
> > > > > a test case for my smoke test suite so that I can verify that
> > > > > the issue is fixed once I've fixed it.
> > > > 
> > > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > > tabrm4 branch.
> > > 
> > > 1. I pushed a fix to the repository.
> > 
> > I don't think the fix is right; this is what you now have
> > 
> > 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> > {
> > 
> > That should be
> > 
> > } else if (rc == TPM2_RC_REFERENCE_H0)
> 
> Right I see your point.
> 
> And yes, also for RC_HANDLE the error handling was done incorrectly. 
>  It should be masked like you said with 0xff to catch error number 
> and the F flag (bit 7).
> 
> As it is format zero error code it should be fine to check without 
> any mask.
> 
> Thanks for noting this. It is easy to shoot yourself into foot when
> there's lot of stuff packed :-)

OK, I've rebased and retested to tabrm5.  Apart from the obvious
introduced bug into the last patch (fix below if you need it)
everything works, so you can add my tested and reviewed bys.

James

---

commit b63aa4b3a5dce31cbc874fa32bd7252b62f55813
Author: James Bottomley <James.Bottomley@HansenPartnership.com>
Date:   Thu Jan 26 08:43:55 2017 -0800

    fix compile failure

diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
index 5030f8c..5720885 100644
--- a/drivers/char/tpm/tpms-dev.c
+++ b/drivers/char/tpm/tpms-dev.c
@@ -39,7 +39,7 @@ static int tpms_release(struct inode *inode, struct file *file)
 	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
 
 	tpm_common_release(file, fpriv);
-	tpm2_del_space(&priv->space):
+	tpm2_del_space(&priv->space);
 	kfree(priv);
 
 	return 0; 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-27  0:29                                     ` James Bottomley
  0 siblings, 0 replies; 57+ messages in thread
From: James Bottomley @ 2017-01-27  0:29 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Wed, 2017-01-25 at 15:40 +0200, Jarkko Sakkinen wrote:
> On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> > On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen
> > > > wrote:
> > > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley
> > > > > wrote:
> > > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > > wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko
> > > > > > > > Sakkinen
> > > > > > > > wrote:
> > > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James
> > > > > > > > > Bottomley
> > > > > > > > > wrote:
> > > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > > wrote:
> > > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko
> > > > > > > > > > > Sakkinen
> > > > > > > > > > > wrote:
> > > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now
> > > > > > > > > > > > on
> > > > > > > > > > > > top of
> > > > > > > > > > > > master
> > > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > > body length
> > > > > > > > > > > > check) 
> > > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > > your
> > > > > > > > > > > > updated
> > > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > > 
> > > > > > > > > > > > I guess the 5 commits that are there now are
> > > > > > > > > > > > such
> > > > > > > > > > > > that we
> > > > > > > > > > > > have 
> > > > > > > > > > > > fairly good consensus, don't we? If so, can I
> > > > > > > > > > > > add
> > > > > > > > > > > > your
> > > > > > > > > > > > reviewed-by 
> > > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > > 
> > > > > > > > > > > We're still failing my test_transients.  This is
> > > > > > > > > > > the
> > > > > > > > > > > full
> > > > > > > > > > > python of 
> > > > > > > > > > > the test case:
> > > > > > > > > > > 
> > > > > > > > > > > 
> > > > > > > > > > >     def test_transients(self):
> > > > > > > > > > >         k = self.open_transients()
> > > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1],
> > > > > > > > > > > None,
> > > > > > > > > > > pwd1)
> > > > > > > > > > >         ...
> > > > > > > > > > > 
> > > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > > >   It's 
> > > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > > doesn't have 
> > > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > > handle being
> > > > > > > > > > > sent
> > > > > > > > > > > down.  We have to fix this either by intercepting
> > > > > > > > > > > the
> > > > > > > > > > > flush
> > > > > > > > > > > and 
> > > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > > dangerously
> > > > > > > > > > > clever and 
> > > > > > > > > > > marking flush as a command which takes one
> > > > > > > > > > > handle.
> > > > > > > > > > 
> > > > > > > > > > This is what the dangerously clever fix looks like.
> > > > > > > > > >  With this
> > > > > > > > > > and a
> > > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > > 
> > > > > > > > > > James
> > > > > > > > > 
> > > > > > > > > I don't want to be clever here. I will rather
> > > > > > > > > intercept
> > > > > > > > > the body
> > > > > > > > > and
> > > > > > > > > try to keep the core code simple and easy to
> > > > > > > > > understand.
> > > > > > > > 
> > > > > > > > It came out quite clean actually.
> > > > > > > > 
> > > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > > beginning
> > > > > > > > of
> > > > > > > > tpm2_map_command:
> > > > > > > > 
> > > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > > 
> > > > > > > > I think this documents better what is actually going on
> > > > > > > > than
> > > > > > > > tinkering
> > > > > > > > cc_attr_tbl.
> > > > > > > > 
> > > > > > > > /Jarkko
> > > > > > > 
> > > > > > > Actually what you suggested is much better idea because
> > > > > > > it
> > > > > > > will also
> > > > > > > take care of validation.
> > > > > > 
> > > > > > Yes, that's why it's clever ... I'm just always wary of
> > > > > > clever
> > > > > > code
> > > > > > because of the Kernighan principle.
> > > > > > 
> > > > > > >  I'm still going to keep tpm2_map_to_phandle because it
> > > > > > > makes
> > > > > > > the 
> > > > > > > code flow a lot cleaner and probably sessions have to
> > > > > > > anyway
> > > > > > > make it
> > > > > > > even more complicated.
> > > > > > 
> > > > > > OK, there's one more thing that seems to be causing
> > > > > > problems:
> > > > > > when
> > > > > > tpm2_save_context fails because the handle no longer exists
> > > > > > (like it's
> > > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not
> > > > > > TPM_RC_HANDLE
> > > > > > (the
> > > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > > circumstances).
> > > > > > 
> > > > > > James
> > > > > 
> > > > > What is your way for reproducing this issue? Just want to add
> > > > > a test case for my smoke test suite so that I can verify that
> > > > > the issue is fixed once I've fixed it.
> > > > 
> > > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > > tabrm4 branch.
> > > 
> > > 1. I pushed a fix to the repository.
> > 
> > I don't think the fix is right; this is what you now have
> > 
> > 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> > {
> > 
> > That should be
> > 
> > } else if (rc == TPM2_RC_REFERENCE_H0)
> 
> Right I see your point.
> 
> And yes, also for RC_HANDLE the error handling was done incorrectly. 
>  It should be masked like you said with 0xff to catch error number 
> and the F flag (bit 7).
> 
> As it is format zero error code it should be fine to check without 
> any mask.
> 
> Thanks for noting this. It is easy to shoot yourself into foot when
> there's lot of stuff packed :-)

OK, I've rebased and retested to tabrm5.  Apart from the obvious
introduced bug into the last patch (fix below if you need it)
everything works, so you can add my tested and reviewed bys.

James

---

commit b63aa4b3a5dce31cbc874fa32bd7252b62f55813
Author: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
Date:   Thu Jan 26 08:43:55 2017 -0800

    fix compile failure

diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
index 5030f8c..5720885 100644
--- a/drivers/char/tpm/tpms-dev.c
+++ b/drivers/char/tpm/tpms-dev.c
@@ -39,7 +39,7 @@ static int tpms_release(struct inode *inode, struct file *file)
 	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
 
 	tpm_common_release(file, fpriv);
-	tpm2_del_space(&priv->space):
+	tpm2_del_space(&priv->space);
 	kfree(priv);
 
 	return 0; 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [tpmdd-devel] [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-27  6:45                                       ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-27  6:45 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-security-module, tpmdd-devel, open list

On Thu, Jan 26, 2017 at 04:29:02PM -0800, James Bottomley wrote:
> On Wed, 2017-01-25 at 15:40 +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> > > On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley
> > > > > > wrote:
> > > > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > > > wrote:
> > > > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko
> > > > > > > > > Sakkinen
> > > > > > > > > wrote:
> > > > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James
> > > > > > > > > > Bottomley
> > > > > > > > > > wrote:
> > > > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > > > wrote:
> > > > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko
> > > > > > > > > > > > Sakkinen
> > > > > > > > > > > > wrote:
> > > > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now
> > > > > > > > > > > > > on
> > > > > > > > > > > > > top of
> > > > > > > > > > > > > master
> > > > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > > > body length
> > > > > > > > > > > > > check) 
> > > > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > > > your
> > > > > > > > > > > > > updated
> > > > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > I guess the 5 commits that are there now are
> > > > > > > > > > > > > such
> > > > > > > > > > > > > that we
> > > > > > > > > > > > > have 
> > > > > > > > > > > > > fairly good consensus, don't we? If so, can I
> > > > > > > > > > > > > add
> > > > > > > > > > > > > your
> > > > > > > > > > > > > reviewed-by 
> > > > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > > > 
> > > > > > > > > > > > We're still failing my test_transients.  This is
> > > > > > > > > > > > the
> > > > > > > > > > > > full
> > > > > > > > > > > > python of 
> > > > > > > > > > > > the test case:
> > > > > > > > > > > > 
> > > > > > > > > > > > 
> > > > > > > > > > > >     def test_transients(self):
> > > > > > > > > > > >         k = self.open_transients()
> > > > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1],
> > > > > > > > > > > > None,
> > > > > > > > > > > > pwd1)
> > > > > > > > > > > >         ...
> > > > > > > > > > > > 
> > > > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > > > >   It's 
> > > > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > > > doesn't have 
> > > > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > > > handle being
> > > > > > > > > > > > sent
> > > > > > > > > > > > down.  We have to fix this either by intercepting
> > > > > > > > > > > > the
> > > > > > > > > > > > flush
> > > > > > > > > > > > and 
> > > > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > > > dangerously
> > > > > > > > > > > > clever and 
> > > > > > > > > > > > marking flush as a command which takes one
> > > > > > > > > > > > handle.
> > > > > > > > > > > 
> > > > > > > > > > > This is what the dangerously clever fix looks like.
> > > > > > > > > > >  With this
> > > > > > > > > > > and a
> > > > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > > > 
> > > > > > > > > > > James
> > > > > > > > > > 
> > > > > > > > > > I don't want to be clever here. I will rather
> > > > > > > > > > intercept
> > > > > > > > > > the body
> > > > > > > > > > and
> > > > > > > > > > try to keep the core code simple and easy to
> > > > > > > > > > understand.
> > > > > > > > > 
> > > > > > > > > It came out quite clean actually.
> > > > > > > > > 
> > > > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > > > beginning
> > > > > > > > > of
> > > > > > > > > tpm2_map_command:
> > > > > > > > > 
> > > > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > > > 
> > > > > > > > > I think this documents better what is actually going on
> > > > > > > > > than
> > > > > > > > > tinkering
> > > > > > > > > cc_attr_tbl.
> > > > > > > > > 
> > > > > > > > > /Jarkko
> > > > > > > > 
> > > > > > > > Actually what you suggested is much better idea because
> > > > > > > > it
> > > > > > > > will also
> > > > > > > > take care of validation.
> > > > > > > 
> > > > > > > Yes, that's why it's clever ... I'm just always wary of
> > > > > > > clever
> > > > > > > code
> > > > > > > because of the Kernighan principle.
> > > > > > > 
> > > > > > > >  I'm still going to keep tpm2_map_to_phandle because it
> > > > > > > > makes
> > > > > > > > the 
> > > > > > > > code flow a lot cleaner and probably sessions have to
> > > > > > > > anyway
> > > > > > > > make it
> > > > > > > > even more complicated.
> > > > > > > 
> > > > > > > OK, there's one more thing that seems to be causing
> > > > > > > problems:
> > > > > > > when
> > > > > > > tpm2_save_context fails because the handle no longer exists
> > > > > > > (like it's
> > > > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not
> > > > > > > TPM_RC_HANDLE
> > > > > > > (the
> > > > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > > > circumstances).
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > What is your way for reproducing this issue? Just want to add
> > > > > > a test case for my smoke test suite so that I can verify that
> > > > > > the issue is fixed once I've fixed it.
> > > > > 
> > > > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > > > tabrm4 branch.
> > > > 
> > > > 1. I pushed a fix to the repository.
> > > 
> > > I don't think the fix is right; this is what you now have
> > > 
> > > 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> > > {
> > > 
> > > That should be
> > > 
> > > } else if (rc == TPM2_RC_REFERENCE_H0)
> > 
> > Right I see your point.
> > 
> > And yes, also for RC_HANDLE the error handling was done incorrectly. 
> >  It should be masked like you said with 0xff to catch error number 
> > and the F flag (bit 7).
> > 
> > As it is format zero error code it should be fine to check without 
> > any mask.
> > 
> > Thanks for noting this. It is easy to shoot yourself into foot when
> > there's lot of stuff packed :-)
> 
> OK, I've rebased and retested to tabrm5.  Apart from the obvious
> introduced bug into the last patch (fix below if you need it)
> everything works, so you can add my tested and reviewed bys.
> 
> James
> 
> ---
> 
> commit b63aa4b3a5dce31cbc874fa32bd7252b62f55813
> Author: James Bottomley <James.Bottomley@HansenPartnership.com>
> Date:   Thu Jan 26 08:43:55 2017 -0800
> 
>     fix compile failure
> 
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> index 5030f8c..5720885 100644
> --- a/drivers/char/tpm/tpms-dev.c
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -39,7 +39,7 @@ static int tpms_release(struct inode *inode, struct file *file)
>  	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
>  
>  	tpm_common_release(file, fpriv);
> -	tpm2_del_space(&priv->space):
> +	tpm2_del_space(&priv->space);
>  	kfree(priv);
>  
>  	return 0; 
> 

Thanks. It should be now OK.


/Jarkko

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
@ 2017-01-27  6:45                                       ` Jarkko Sakkinen
  0 siblings, 0 replies; 57+ messages in thread
From: Jarkko Sakkinen @ 2017-01-27  6:45 UTC (permalink / raw)
  To: James Bottomley
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, open list

On Thu, Jan 26, 2017 at 04:29:02PM -0800, James Bottomley wrote:
> On Wed, 2017-01-25 at 15:40 +0200, Jarkko Sakkinen wrote:
> > On Mon, Jan 23, 2017 at 02:16:37PM -0800, James Bottomley wrote:
> > > On Mon, 2017-01-23 at 23:42 +0200, Jarkko Sakkinen wrote:
> > > > On Mon, Jan 23, 2017 at 06:58:23PM +0200, Jarkko Sakkinen wrote:
> > > > > On Mon, Jan 23, 2017 at 04:09:42PM +0200, Jarkko Sakkinen
> > > > > wrote:
> > > > > > On Sun, Jan 22, 2017 at 01:36:28PM -0800, James Bottomley
> > > > > > wrote:
> > > > > > > On Sun, 2017-01-22 at 23:04 +0200, Jarkko Sakkinen wrote:
> > > > > > > > On Sun, Jan 22, 2017 at 11:01:07PM +0200, Jarkko Sakkinen
> > > > > > > > wrote:
> > > > > > > > > On Sun, Jan 22, 2017 at 10:30:55PM +0200, Jarkko
> > > > > > > > > Sakkinen
> > > > > > > > > wrote:
> > > > > > > > > > On Sun, Jan 22, 2017 at 10:48:12AM -0800, James
> > > > > > > > > > Bottomley
> > > > > > > > > > wrote:
> > > > > > > > > > > On Sun, 2017-01-22 at 09:49 -0800, James Bottomley
> > > > > > > > > > > wrote:
> > > > > > > > > > > > On Fri, 2017-01-20 at 23:05 +0200, Jarkko
> > > > > > > > > > > > Sakkinen
> > > > > > > > > > > > wrote:
> > > > > > > > > > > > > 'tabrm4' branch has been now rebased. It's now
> > > > > > > > > > > > > on
> > > > > > > > > > > > > top of
> > > > > > > > > > > > > master
> > > > > > > > > > > > > branch that contains Stefan's latest patch (min
> > > > > > > > > > > > > body length
> > > > > > > > > > > > > check) 
> > > > > > > > > > > > > that I've reviewed and tested. It also contains
> > > > > > > > > > > > > your
> > > > > > > > > > > > > updated
> > > > > > > > > > > > > /dev/tpms patch.
> > > > > > > > > > > > > 
> > > > > > > > > > > > > I guess the 5 commits that are there now are
> > > > > > > > > > > > > such
> > > > > > > > > > > > > that we
> > > > > > > > > > > > > have 
> > > > > > > > > > > > > fairly good consensus, don't we? If so, can I
> > > > > > > > > > > > > add
> > > > > > > > > > > > > your
> > > > > > > > > > > > > reviewed-by 
> > > > > > > > > > > > > and tested-by to my commits and vice versa?
> > > > > > > > > > > > 
> > > > > > > > > > > > We're still failing my test_transients.  This is
> > > > > > > > > > > > the
> > > > > > > > > > > > full
> > > > > > > > > > > > python of 
> > > > > > > > > > > > the test case:
> > > > > > > > > > > > 
> > > > > > > > > > > > 
> > > > > > > > > > > >     def test_transients(self):
> > > > > > > > > > > >         k = self.open_transients()
> > > > > > > > > > > >         self.c.flush_context(k[0])
> > > > > > > > > > > >         self.c.change_auth(self.c.SRK, k[1],
> > > > > > > > > > > > None,
> > > > > > > > > > > > pwd1)
> > > > > > > > > > > >         ...
> > > > > > > > > > > > 
> > > > > > > > > > > > It's failing at self.c.flush_context(k[0]) with
> > > > > > > > > > > > TPM_RC_VALUE.
> > > > > > > > > > > >   It's 
> > > > > > > > > > > > the same problem Ken complained about:
> > > > > > > > > > > > TPM2_FlushContext
> > > > > > > > > > > > doesn't have 
> > > > > > > > > > > > a declared handle area so we don't translate the
> > > > > > > > > > > > handle being
> > > > > > > > > > > > sent
> > > > > > > > > > > > down.  We have to fix this either by intercepting
> > > > > > > > > > > > the
> > > > > > > > > > > > flush
> > > > > > > > > > > > and 
> > > > > > > > > > > > manually translating the context, or by being
> > > > > > > > > > > > dangerously
> > > > > > > > > > > > clever and 
> > > > > > > > > > > > marking flush as a command which takes one
> > > > > > > > > > > > handle.
> > > > > > > > > > > 
> > > > > > > > > > > This is what the dangerously clever fix looks like.
> > > > > > > > > > >  With this
> > > > > > > > > > > and a
> > > > > > > > > > > few other changes, my smoke tests now pass.
> > > > > > > > > > > 
> > > > > > > > > > > James
> > > > > > > > > > 
> > > > > > > > > > I don't want to be clever here. I will rather
> > > > > > > > > > intercept
> > > > > > > > > > the body
> > > > > > > > > > and
> > > > > > > > > > try to keep the core code simple and easy to
> > > > > > > > > > understand.
> > > > > > > > > 
> > > > > > > > > It came out quite clean actually.
> > > > > > > > > 
> > > > > > > > > I just encapsulated handle mapping and have this in the
> > > > > > > > > beginning
> > > > > > > > > of
> > > > > > > > > tpm2_map_command:
> > > > > > > > > 
> > > > > > > > > if (cc == TPM2_CC_FLUSH_CONTEXT)
> > > > > > > > > 	return tpm2_map_to_phandle(space,
> > > > > > > > > &cmd[TPM_HEADER_SIZE]);
> > > > > > > > > 
> > > > > > > > > I think this documents better what is actually going on
> > > > > > > > > than
> > > > > > > > > tinkering
> > > > > > > > > cc_attr_tbl.
> > > > > > > > > 
> > > > > > > > > /Jarkko
> > > > > > > > 
> > > > > > > > Actually what you suggested is much better idea because
> > > > > > > > it
> > > > > > > > will also
> > > > > > > > take care of validation.
> > > > > > > 
> > > > > > > Yes, that's why it's clever ... I'm just always wary of
> > > > > > > clever
> > > > > > > code
> > > > > > > because of the Kernighan principle.
> > > > > > > 
> > > > > > > >  I'm still going to keep tpm2_map_to_phandle because it
> > > > > > > > makes
> > > > > > > > the 
> > > > > > > > code flow a lot cleaner and probably sessions have to
> > > > > > > > anyway
> > > > > > > > make it
> > > > > > > > even more complicated.
> > > > > > > 
> > > > > > > OK, there's one more thing that seems to be causing
> > > > > > > problems:
> > > > > > > when
> > > > > > > tpm2_save_context fails because the handle no longer exists
> > > > > > > (like it's
> > > > > > > been flushed) it returns TPM_RC_REFERENCE_H0 not
> > > > > > > TPM_RC_HANDLE
> > > > > > > (the
> > > > > > > session code does seem to return TPM_RC_HANDLE under some
> > > > > > > circumstances).
> > > > > > > 
> > > > > > > James
> > > > > > 
> > > > > > What is your way for reproducing this issue? Just want to add
> > > > > > a test case for my smoke test suite so that I can verify that
> > > > > > the issue is fixed once I've fixed it.
> > > > > 
> > > > > Right. Too easy. Sorry about this. I'll push a fix for this to
> > > > > tabrm4 branch.
> > > > 
> > > > 1. I pushed a fix to the repository.
> > > 
> > > I don't think the fix is right; this is what you now have
> > > 
> > > 	} else if ((rc & TPM2_RC_REFERENCE_H0) == TPM2_RC_REFERENCE_H0)
> > > {
> > > 
> > > That should be
> > > 
> > > } else if (rc == TPM2_RC_REFERENCE_H0)
> > 
> > Right I see your point.
> > 
> > And yes, also for RC_HANDLE the error handling was done incorrectly. 
> >  It should be masked like you said with 0xff to catch error number 
> > and the F flag (bit 7).
> > 
> > As it is format zero error code it should be fine to check without 
> > any mask.
> > 
> > Thanks for noting this. It is easy to shoot yourself into foot when
> > there's lot of stuff packed :-)
> 
> OK, I've rebased and retested to tabrm5.  Apart from the obvious
> introduced bug into the last patch (fix below if you need it)
> everything works, so you can add my tested and reviewed bys.
> 
> James
> 
> ---
> 
> commit b63aa4b3a5dce31cbc874fa32bd7252b62f55813
> Author: James Bottomley <James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
> Date:   Thu Jan 26 08:43:55 2017 -0800
> 
>     fix compile failure
> 
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> index 5030f8c..5720885 100644
> --- a/drivers/char/tpm/tpms-dev.c
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -39,7 +39,7 @@ static int tpms_release(struct inode *inode, struct file *file)
>  	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
>  
>  	tpm_common_release(file, fpriv);
> -	tpm2_del_space(&priv->space):
> +	tpm2_del_space(&priv->space);
>  	kfree(priv);
>  
>  	return 0; 
> 

Thanks. It should be now OK.


/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n>
       [not found]                                 ` <1485209797.2534.29.camel-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
@ 2017-01-27 22:01                                   ` Ken Goldman
  0 siblings, 0 replies; 57+ messages in thread
From: Ken Goldman @ 2017-01-27 22:01 UTC (permalink / raw)
  To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 1/23/2017 5:16 PM, James Bottomley wrote:
>
> because the 0x9XX return codes don't have any parameter information
> that needs stripping and (rc & TPM2_RC_REFERENCE_H0) ==
> TPM2_RC_REFERENCE_H0)  will match any error code that has bits 11, 8
> and 5 set.
>
> I think the handle check was wrong too, it should have been
>
> if (rc & 0xff) == TPM2_RC_HANDLE)
>
> Because all you need to do is strip off the parameter information

This is just FYI ...

The TPM feature that adds parameter or handle numbers to the return code 
is optional.  So, masking them out is OK, but don't do anything that 
requires that 3 bit field to be accurate.






------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2017-01-27 22:01 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-16 13:12 [PATCH RFC v3 0/5] RFC: in-kernel resource manager Jarkko Sakkinen
2017-01-16 13:12 ` Jarkko Sakkinen
2017-01-16 13:12 ` [PATCH RFC v3 1/5] tpm: validate TPM 2.0 commands Jarkko Sakkinen
2017-01-16 13:12   ` Jarkko Sakkinen
2017-01-16 13:12 ` [PATCH RFC v3 2/5] tpm: export tpm2_flush_context_cmd Jarkko Sakkinen
2017-01-16 13:12   ` Jarkko Sakkinen
2017-01-16 13:12 ` [PATCH RFC v3 3/5] tpm: infrastructure for TPM spaces Jarkko Sakkinen
2017-01-16 13:12   ` Jarkko Sakkinen
2017-01-16 13:12 ` [PATCH RFC v3 4/5] tpm: split out tpm-dev.c into tpm-dev.c and tpm-common-dev.c Jarkko Sakkinen
2017-01-16 13:12   ` Jarkko Sakkinen
2017-01-16 13:12 ` [PATCH RFC v3 5/5] tpm2: expose resource manager via a device link /dev/tpms<n> Jarkko Sakkinen
2017-01-16 13:12   ` Jarkko Sakkinen
2017-01-16 16:14   ` Jason Gunthorpe
2017-01-16 17:24     ` Jarkko Sakkinen
2017-01-16 17:28       ` [tpmdd-devel] " James Bottomley
2017-01-17  7:14         ` Jarkko Sakkinen
2017-01-18 15:01   ` James Bottomley
2017-01-19 10:49     ` Jarkko Sakkinen
2017-01-19 12:19       ` James Bottomley
2017-01-20 13:39         ` Jarkko Sakkinen
2017-01-20 21:05           ` Jarkko Sakkinen
2017-01-20 21:05             ` Jarkko Sakkinen
2017-01-21 19:28             ` [tpmdd-devel] " James Bottomley
2017-01-22 14:49               ` Jarkko Sakkinen
2017-01-22 14:49                 ` Jarkko Sakkinen
2017-01-21 20:38             ` [tpmdd-devel] " James Bottomley
2017-01-21 20:38               ` James Bottomley
2017-01-22 14:49               ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-22 14:49                 ` Jarkko Sakkinen
2017-01-22 17:49             ` [tpmdd-devel] " James Bottomley
2017-01-22 18:48               ` James Bottomley
2017-01-22 20:30                 ` Jarkko Sakkinen
2017-01-22 21:01                   ` Jarkko Sakkinen
2017-01-22 21:04                     ` Jarkko Sakkinen
2017-01-22 21:36                       ` James Bottomley
2017-01-23 14:09                         ` Jarkko Sakkinen
2017-01-23 16:14                           ` James Bottomley
2017-01-23 16:14                             ` James Bottomley
2017-01-24 12:03                             ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-24 12:03                               ` Jarkko Sakkinen
2017-01-23 16:58                           ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-23 21:42                             ` Jarkko Sakkinen
2017-01-23 21:42                               ` Jarkko Sakkinen
2017-01-23 22:16                               ` [tpmdd-devel] " James Bottomley
2017-01-23 22:16                                 ` James Bottomley
2017-01-25 13:40                                 ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-25 13:42                                   ` Jarkko Sakkinen
2017-01-27  0:29                                   ` James Bottomley
2017-01-27  0:29                                     ` James Bottomley
2017-01-27  6:45                                     ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-27  6:45                                       ` Jarkko Sakkinen
2017-01-25 20:23                                 ` [tpmdd-devel] " Jarkko Sakkinen
     [not found]                                 ` <1485209797.2534.29.camel-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
2017-01-27 22:01                                   ` Ken Goldman
2017-01-22 20:24               ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-22 20:24                 ` Jarkko Sakkinen
2017-01-19 10:42   ` Jarkko Sakkinen
2017-01-19 10:42     ` Jarkko Sakkinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.