git: 084f245a8514 - main - tpm: Tie exclusive-open cleanup to the file lifetime

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Fri, 30 Oct 2026 22:04:32 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=084f245a8514e89a506e43efd1a7ed44ffdbb5eb

commit 084f245a8514e89a506e43efd1a7ed44ffdbb5eb
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-18 12:16:54 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-30 22:03:58 +0000

    tpm: Tie exclusive-open cleanup to the file lifetime
    
    Use a cdevpriv destructor to abort an unfinished TPM 1.2 transaction and
    release exclusive-open ownership. Register it before setting TPM_OPEN so
    a failed registration leaves the device available. The last reference to
    the successful open triggers cleanup, including after dup() or fork().
    
    Suggested by:   kevans
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
    Differential Revision:  https://reviews.freebsd.org/D59812
---
 sys/dev/tpm/tpm.c | 34 ++++++++++++----------------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c
index 2880c69cf85c..42c31ba75518 100644
--- a/sys/dev/tpm/tpm.c
+++ b/sys/dev/tpm/tpm.c
@@ -139,15 +139,14 @@ int tpm_enabled;
 	((struct tpm_softc *)dev->si_drv1)
 
 d_open_t	tpmopen;
-d_close_t	tpmclose;
 d_read_t	tpmread;
 d_write_t	tpmwrite;
 d_ioctl_t	tpmioctl;
+static d_priv_dtor_t tpm_dtor;
 
 static struct cdevsw tpm_cdevsw = {
 	.d_version =	D_VERSION,
 	.d_open =	tpmopen,
-	.d_close =	tpmclose,
 	.d_read =	tpmread,
 	.d_write =	tpmwrite,
 	.d_ioctl =	tpmioctl,
@@ -404,7 +403,8 @@ tpm_detach(device_t dev)
 
 	/*
 	 * Prevent new methods from touching the transport.  Do not hold the
-	 * lock while destroy_dev() drains methods already waiting for it.
+	 * lock while destroy_dev() drains methods and cdevpriv destructors
+	 * which also acquire it.
 	 */
 	if (sc->sc_cdev != NULL) {
 		destroy_dev(sc->sc_cdev);
@@ -1659,36 +1659,26 @@ tpmopen(struct cdev *dev, int flag, int mode, struct thread *td)
 	else if (sc->sc_suspend != 0 || (sc->sc_flags & TPM_OPEN) != 0)
 		error = EBUSY;
 	else {
-		sc->sc_flags |= TPM_OPEN;
-		error = 0;
+		error = devfs_set_cdevpriv(sc, tpm_dtor);
+		if (error == 0)
+			sc->sc_flags |= TPM_OPEN;
 	}
 	sx_xunlock(&sc->sc_lock);
 
 	return (error);
 }
 
-int
-tpmclose(struct cdev *dev, int flag, int mode, struct thread *td)
+static void
+tpm_dtor(void *arg)
 {
 	struct tpm_softc *sc;
-	int error;
-
-	sc = TPMSOFTC(dev);
-	if (sc == NULL)
-		return (ENXIO);
 
+	sc = arg;
 	sx_xlock(&sc->sc_lock);
-	if ((sc->sc_flags & TPM_OPEN) == 0)
-		error = EINVAL;
-	else {
-		if (sc->sc_init == tpm_tis12_init)
-			tpm_tis12_abort(sc);
-		sc->sc_flags &= ~TPM_OPEN;
-		error = 0;
-	}
+	if (sc->sc_init == tpm_tis12_init)
+		tpm_tis12_abort(sc);
+	sc->sc_flags &= ~TPM_OPEN;
 	sx_xunlock(&sc->sc_lock);
-
-	return (error);
 }
 
 int