lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 16 Jan 2021 02:22:39 +0100
From:   Lino Sanfilippo <>
        Lino Sanfilippo <>
Subject: [PATCH 2/4] tpm: fix reference counting for struct tpm_chip

From: Lino Sanfilippo <>

Commit 8979b02aaf1d ("tpm: Fix reference count to main device") tried to
fix a reference count issue which prevented the tpm_chip structure from
being freed in case that no TPM2 was used. The fix was to only get an extra
reference for chip->dev in case of TPM2 which is indicated by the
Unfortunately this flag is never set, and thus the extra reference is not
taken even in the TPM2 case. This results in a refcount underflow in case
that the device file /dev/tpmrm* is used to write data after the tpm_chip
has been unregistered (e.g if the /dev/tpmrm* file has been opened before
and not yet closed at the time the chip was unregistered.)

Also the error path (label "out") in tpm_chip_alloc() results in such an
underflow, since the dev reference is put twice (one time directly and the
second time by the call of tpm_devs_release() due to the put of

Fix the described issues by taking the extra reference unconditionally and
installing an additional resource management action handler which puts
chip->devs. Releasing chip->devs eventually results in the call of
tpm_devs_release() which then releases the extra reference to chip->dev.

Since we now actually take that extra reference, adjust users of
tpm_chip_alloc() like VTPM proxy and FTPM tee to release it indirectly by
putting the reference of chip->devs.

Fixes: 8979b02aaf1d ("tpm: Fix reference count to main device")
Signed-off-by: Lino Sanfilippo <>
 drivers/char/tpm/tpm-chip.c       | 11 +++++++++--
 drivers/char/tpm/tpm_ftpm_tee.c   |  2 ++
 drivers/char/tpm/tpm_vtpm_proxy.c |  1 +
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index e242d2e..596824c 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -360,8 +360,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 	 * while cdevs is in use.  The corresponding put
 	 * is in the tpm_devs_release (TPM2 only)
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		get_device(&chip->dev);
+	get_device(&chip->dev);
 	if (chip->dev_num == 0)
 		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
@@ -425,12 +424,20 @@ struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
 	if (rc)
 		goto put_dev;
+	rc = devm_add_action_or_reset(pdev,
+				      (void (*)(void *)) put_device,
+				      &chip->devs);
+	if (rc)
+		goto put_devs;
 	dev_set_drvdata(pdev, chip);
 	return chip;
+	put_device(&chip->devs);
 	return ERR_PTR(rc);
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c
index 2ccdf8a..82858c2 100644
--- a/drivers/char/tpm/tpm_ftpm_tee.c
+++ b/drivers/char/tpm/tpm_ftpm_tee.c
@@ -286,6 +286,7 @@ static int ftpm_tee_probe(struct device *dev)
+	put_device(&pvt_data->chip->devs);
@@ -318,6 +319,7 @@ static int ftpm_tee_remove(struct device *dev)
 	/* frees chip */
+	put_device(&pvt_data->chip->devs);
 	/* Free the shared memory pool */
diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c
index 91c772e3..97b60f8 100644
--- a/drivers/char/tpm/tpm_vtpm_proxy.c
+++ b/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -520,6 +520,7 @@ static struct proxy_dev *vtpm_proxy_create_proxy_dev(void)
 static inline void vtpm_proxy_delete_proxy_dev(struct proxy_dev *proxy_dev)
+	put_device(&proxy_dev->chip->devs);
 	put_device(&proxy_dev->chip->dev); /* frees chip */

Powered by blists - more mailing lists