From nobody Fri Sep 18 00:08:56 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hmCf05vhqz6sHqZ for ; Fri, 18 Sep 2026 00:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hmCf05Kscz4bZJ for ; Fri, 18 Sep 2026 00:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690136; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1qI6Bq01jk+ha/SrwSjiGwYf8E4i/CpAGe/HSmsvZtM=; b=grczeGfMsG3AjGZWnHSWvG1uyZD3Zefil8lNsDsX3K5R8N5wyoI0oVb0XsTo4pe3Ceacjo Qsx2e+H4Y07IA+xYYFkRUHE1PPzRLo83+jRS7IvvAdTxYTvLsdQIqTfaD1WZECeR4VGjRT FGDRQHrirabcYdCcs5dlqKnyAuUrNBrOF5XIAR7W0dLCn5CFViPd6r+s2RH23PRWDNo7+E W6WDs7NCeVL7/N4G81HSEiPc4tOWQGolr/GqQjpmWf9XHDxmZYFt/WEKfOztR94kO2rnEL tZrCIxV8f9si6XNCgBxuCD5zwhKO2P4C+62XcU8mB3d2haYu7x443GwpQxNGvQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789690136; b=BRvmb6vWuAQjJqR0kIK9n7cQOGpUEbCcIHDpC6KBPHquluyd79RGj0AXcZr7ONg6eZTqc5 W5S/MV7ajaA+ka3j8PqEQBMa+NXV3y0vafbpm482Pk+KF6KfW6UoYI6yHzPPB5y8COM4y5 RiZ+lp47y7UDSUHoRP6jb5cBwAnOVUY6afemLicqWGryGCLG8KZC09HkAHEx3w3nUBlMnj 6SvTHOuz0r7tGHgWPNNSf3Nwj1Ehyu2oKUYaaR+LJTNqL8GDCRQqwQ4hu6Enc77wX8sNrJ DPGgMcXzjfeeCDPuP5P7yubp5PoI8ISPsGwryNJljdgv0SrnbzoI90C7Cf4ljw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789690136; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1qI6Bq01jk+ha/SrwSjiGwYf8E4i/CpAGe/HSmsvZtM=; b=InM++7W2sMoxkwXuaCfoHnXJNhsIUg/rHcO/7sxEsdiffzwDIGnfC7NhBvAfSZ/lVtn81t lgTTBE58yiHuVVfTtZVx1/jp2GR446hAcjDsY69YLYijqoU3/Vw9ENhSn9DU1JY2BCxyx5 AA4nLat/2ubI0MFPKtaUyuWQ6FDSFFprMg4H+G5M03xiWzs+cgi63uI4wJOZa6zcCI4NmT GF/r57NAAbkgc5/YGsWFYi/QcnINrjaci3PcjC+8xRRoFesqbl+BLQ6FdbPp8RTmxSFqmg ZXA/Cx1SUXb4AWSRx6bnXZirHLFGKxdOvOZt2K1yJ3wsc6EPZrNTXHGUZFNy7Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hmCf04P62zvfJ for ; Fri, 18 Sep 2026 00:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 30d9f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 18 Sep 2026 00:08:56 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 2a77f4d85126 - stable/15 - tpm: Move user copies outside the TPM 1.2 lock List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 2a77f4d8512691f88b2b8173e138da4722e1e06a Auto-Submitted: auto-generated Date: Fri, 18 Sep 2026 00:08:56 +0000 Message-Id: <6aac8118.30d9f.16b6bc20@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=2a77f4d8512691f88b2b8173e138da4722e1e06a commit 2a77f4d8512691f88b2b8173e138da4722e1e06a Author: Kevin Bowling AuthorDate: 2026-08-27 14:01:51 +0000 Commit: Kevin Bowling CommitDate: 2026-09-18 00:08:47 +0000 tpm: Move user copies outside the TPM 1.2 lock The character-device paths held the transaction and lifecycle lock while uiomove() accessed user memory. A user page fault could therefore delay suspend or detach, and a copyout failure occurred while the TPM response was still active. Copy commands into the bounded stack buffer before taking the lock. For reads, validate the response header, buffer the complete response while the lock is held, finish the TPM transaction, and copy it to userspace after unlocking. Use a non-blocking allocation so memory pressure cannot turn response buffering into another lifecycle wait. NetBSD uses the same separation but limits responses to its fixed 1 KiB buffer. Allocate the TPM-advertised response length to preserve the existing FreeBSD support for larger streamed responses. On a ThinkPad T440p with an STMicro TPM 1.2, a PCR read into a 4 KiB userspace buffer returned the expected 30-byte response. A deliberately short five-byte read failed cleanly, relinquished locality zero, and the next PCR read succeeded. Reviewed by: kevans Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59238 (cherry picked from commit 5319035afacceaa267792ec193eb03fa51c972f7) --- sys/dev/tpm/tpm.c | 71 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c index f37ce6955f17..ee886e6ae7f8 100644 --- a/sys/dev/tpm/tpm.c +++ b/sys/dev/tpm/tpm.c @@ -40,6 +40,7 @@ #include #include +MALLOC_DEFINE(M_TPM, "tpm12_buffer", "buffer for TPM 1.2 responses"); #define TPM_BUFSIZ 1024 @@ -1473,13 +1474,14 @@ int tpmread(struct cdev *dev, struct uio *uio, int flags) { struct tpm_softc *sc; - u_int8_t buf[TPM_BUFSIZ], *p; - size_t cnt; - int end_error, len, n, rv; + u_int8_t header[TPM_HDRSIZE], *buf; + size_t cnt, len; + int end_error, rv; sc = TPMSOFTC(dev); if (sc == NULL) return (ENXIO); + buf = NULL; sx_xlock(&sc->sc_lock); if (sc->sc_dying) { @@ -1497,39 +1499,42 @@ tpmread(struct cdev *dev, struct uio *uio, int flags) #ifdef TPM_DEBUG printf("tpmread: getting header\n"); #endif - rv = sc->sc_read(sc, buf, TPM_HDRSIZE, &cnt, 0); + rv = sc->sc_read(sc, header, sizeof(header), &cnt, + TPM_PARAM_SIZE); if (rv != 0) goto end; + if (cnt != sizeof(header)) { + rv = EIO; + goto end; + } - len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5]; + len = be32dec(header + 2); #ifdef TPM_DEBUG - printf("tpmread: len %d, io count %d\n", len, uio->uio_resid); + printf("tpmread: len %zu, io count %zd\n", len, uio->uio_resid); #endif - if (len > uio->uio_resid) { + if (len < sizeof(header) || len > uio->uio_resid || len > INT_MAX) { rv = EIO; #ifdef TPM_DEBUG - printf("tpmread: bad residual io count 0x%x\n", uio->uio_resid); + printf("tpmread: invalid response length %zu\n", len); #endif goto end; } - /* Copy out header. */ - rv = uiomove((caddr_t)buf, cnt, uio); - if (rv != 0) + /* + * Finish the device transaction before touching user memory. Use a + * non-blocking allocation so lifecycle operations are not held up by + * memory pressure while waiting for the transaction lock. + */ + buf = malloc(len, M_TPM, M_NOWAIT); + if (buf == NULL) { + rv = ENOMEM; goto end; + } + memcpy(buf, header, sizeof(header)); - /* Get remaining part of the answer (if anything is left). */ - for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n, - n = sizeof(buf)) { - n = MIN(n, len); -#ifdef TPM_DEBUG - printf("tpmread: n %d len %d\n", n, len); -#endif - rv = sc->sc_read(sc, p, n, NULL, TPM_PARAM_SIZE); - if (rv != 0) - goto end; - p += n; - rv = uiomove((caddr_t)buf, p - buf, uio); + if (len > sizeof(header)) { + rv = sc->sc_read(sc, buf + sizeof(header), + (int)(len - sizeof(header)), NULL, TPM_PARAM_SIZE); if (rv != 0) goto end; } @@ -1540,6 +1545,9 @@ end: rv = end_error; out: sx_xunlock(&sc->sc_lock); + if (rv == 0) + rv = uiomove(buf, (int)len, uio); + free(buf, M_TPM); return (rv); } @@ -1548,11 +1556,19 @@ tpmwrite(struct cdev *dev, struct uio *uio, int flags) { struct tpm_softc *sc; u_int8_t buf[TPM_BUFSIZ]; + ssize_t resid; int end_error, n, rv; sc = TPMSOFTC(dev); if (sc == NULL) return (ENXIO); + + resid = uio->uio_resid; + n = MIN(sizeof(buf), resid); + rv = uiomove(buf, n, uio); + if (rv != 0) + return (rv); + sx_xlock(&sc->sc_lock); if (sc->sc_dying) { rv = ENXIO; @@ -1564,14 +1580,9 @@ tpmwrite(struct cdev *dev, struct uio *uio, int flags) } #ifdef TPM_DEBUG - printf("tpmwrite: io count %d\n", uio->uio_resid); + printf("tpmwrite: io count %d\n", n); #endif - n = MIN(sizeof(buf), uio->uio_resid); - rv = uiomove((caddr_t)buf, n, uio); - if (rv != 0) - goto out; - rv = sc->sc_start(sc, UIO_WRITE); if (rv != 0) goto out; @@ -1583,6 +1594,8 @@ tpmwrite(struct cdev *dev, struct uio *uio, int flags) out: sx_xunlock(&sc->sc_lock); + if (rv != 0) + uio->uio_resid = resid; return (rv); }