Skip to contentSkip to conversation

tpm: Clean up TPM space after command failure

RFC PATCH Superseded Jonathan McDowell 2 participants 4 messages Aug 14, 2024 – Aug 16, 2024

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 tpm: Clean up TPM space after command failure

We've been seeing a problem where TPM commands time out, which if they're the last command before the TPM device is closed causes a leak of transient handles. They can be seen and cleaned up (with a flush context) if the /dev/tpm0 device is used instead of /dev/tpmrm0, but it seems like we should be doing this automatically on the transmit error path. Patch below adds a tpm2_flush_space on error to avoid this.

Does this seem reasonable? The other query is whether tpm2_del_space should cleanup the contexts as well, rather than just the sessions.

(Obviously in an ideal world we wouldn't see the timeouts at all, and I'm still trying to work on getting to the bottom of these, which are generally infrequent, but happening enough across our fleet that we were able to observe this handle leak.)

From: Jonathan McDowell <[email protected]>

tpm_dev_transmit prepares the TPM space before attempting command transmission. However if the command fails no rollback of this preparation is done. This can result in transient handles being leaked if the device is subsequently closed with no further commands performed.

Fix this by flushing the space in the event of command transmission failure.

---
 drivers/char/tpm/tpm-dev-common.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/char/tpm/tpm-dev-common.c +2 -0
index 30b4c288c1bb..c3fbbf4d3db7 100644
@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
 
 	if (!ret)
 		ret = tpm2_commit_space(chip, space, buf, &len);
+	else
+		tpm2_flush_space(chip);
 
 out_rc:
 	return ret ? ret : len;
Signature · 1 line
2.46.0
maintainer
#1 lore raw
Quoted 7 lines · Jonathan McDowell

We've been seeing a problem where TPM commands time out, which if they're the last command before the TPM device is closed causes a leak of transient handles. They can be seen and cleaned up (with a flush context) if the /dev/tpm0 device is used instead of /dev/tpmrm0, but it seems like we should be doing this automatically on the transmit error path. Patch below adds a tpm2_flush_space on error to avoid this.

Quoted 7 lines

Does this seem reasonable? The other query is whether tpm2_del_space should cleanup the contexts as well, rather than just the sessions.

(Obviously in an ideal world we wouldn't see the timeouts at all, and I'm still trying to work on getting to the bottom of these, which are generally infrequent, but happening enough across our fleet that we were able to observe this handle leak.)

Seems reasonable without this story ;-) I get that this is here because of query np.

Quoted 8 lines

From: Jonathan McDowell <[email protected]>

tpm_dev_transmit prepares the TPM space before attempting command transmission. However if the command fails no rollback of this preparation is done. This can result in transient handles being leaked if the device is subsequently closed with no further commands performed.

Quoted 4 lines

Fix this by flushing the space in the event of command transmission failure.

I would consider fixes tag for this even! I think it can be classified as a minor bug. I implemented this feature together with James Bottomley so would be nice to get some feedback also from him (as a sanity check)>

Quoted 2 lines

---

Just as a tip: if you put stuff here like supplemental commets the won't get included when the commit is finally applied (also a popular place for change log).

Quoted 8 lines
 drivers/char/tpm/tpm-dev-common.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/char/tpm/tpm-dev-common.c +0 -0
index 30b4c288c1bb..c3fbbf4d3db7 100644

drivers/char/tpm/tpm-dev-common.c static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space, · line 54

Quoted 8 lines
drivers/char/tpm/tpm-dev-common.c +2 -0
@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
 
 	if (!ret)
 		ret = tpm2_commit_space(chip, space, buf, &len);
+	else
+		tpm2_flush_space(chip);
 
 out_rc:
 	return ret ? ret : len;

Can you send v2 with fixes tag and James as cc.

Since you have such a long cover letter you could possibly:

git format-patch -1 -v2 --cover-letter

Then just move that text in front to 00/01.

BR, Jarkko

#2 lore raw

PATCH v2 1/1 tpm: Clean up TPM space after command failure

From: Jonathan McDowell <[email protected]>

tpm_dev_transmit prepares the TPM space before attempting command transmission. However if the command fails no rollback of this preparation is done. This can result in transient handles being leaked if the device is subsequently closed with no further commands performed.

Fix this by flushing the space in the event of command transmission failure.

Fixes 745b361e989a ("tpm: infrastructure for TPM spaces")

---
v2:
- Add 'Fixes:'
- Cc James as one of the original authors
- Add space sanity check in tpm2_flush_space

 drivers/char/tpm/tpm-dev-common.c | 2 ++
 drivers/char/tpm/tpm2-space.c     | 3 +++
 2 files changed, 5 insertions(+)
drivers/char/tpm/tpm-dev-common.c +2 -0
index 30b4c288c1bb..c3fbbf4d3db7 100644
@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
 
 	if (!ret)
 		ret = tpm2_commit_space(chip, space, buf, &len);
+	else
+		tpm2_flush_space(chip);
 
 out_rc:
 	return ret ? ret : len;
drivers/char/tpm/tpm2-space.c +3 -0
index 4892d491da8d..25a66870c165 100644
@@ -169,6 +169,9 @@ void tpm2_flush_space(struct tpm_chip *chip)
 	struct tpm_space *space = &chip->work_space;
 	int i;
 
+	if (!space)
+		return;
+
 	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
 		if (space->context_tbl[i] && ~space->context_tbl[i])
 			tpm2_flush_context(chip, space->context_tbl[i]);
Signature · 1 line
2.46.0
maintainer Reviewed-by on v2 1/1
#3 lore raw
Quoted 40 lines · Jonathan McDowell

From: Jonathan McDowell <[email protected]>

tpm_dev_transmit prepares the TPM space before attempting command transmission. However if the command fails no rollback of this preparation is done. This can result in transient handles being leaked if the device is subsequently closed with no further commands performed.

Fix this by flushing the space in the event of command transmission failure.

Fixes 745b361e989a ("tpm: infrastructure for TPM spaces")

---
v2:
- Add 'Fixes:'
- Cc James as one of the original authors
- Add space sanity check in tpm2_flush_space

 drivers/char/tpm/tpm-dev-common.c | 2 ++
 drivers/char/tpm/tpm2-space.c     | 3 +++
 2 files changed, 5 insertions(+)
drivers/char/tpm/tpm-dev-common.c +2 -0
index 30b4c288c1bb..c3fbbf4d3db7 100644
@@ -47,6 +47,8 @@ static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
 
 	if (!ret)
 		ret = tpm2_commit_space(chip, space, buf, &len);
+	else
+		tpm2_flush_space(chip);
 
 out_rc:
 	return ret ? ret : len;
drivers/char/tpm/tpm2-space.c +0 -0
index 4892d491da8d..25a66870c165 100644

drivers/char/tpm/tpm2-space.c void tpm2_flush_space(struct tpm_chip *chip) · line 177

Quoted 9 lines
drivers/char/tpm/tpm2-space.c +3 -0
@@ -169,6 +169,9 @@ void tpm2_flush_space(struct tpm_chip *chip)
 	struct tpm_space *space = &chip->work_space;
 	int i;
 
+	if (!space)
+		return;
+
 	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
 		if (space->context_tbl[i] && ~space->context_tbl[i])
 			tpm2_flush_context(chip, space->context_tbl[i]);

I'll pick this for 6.12: I think it is a legit fix but not worth of disturbing the in-progress release cycle (which is going almost rc4 already):

Thank you.

BR, Jarkko