From nobody Thu Aug 25 17:31:37 2022 X-Original-To: dev-commits-src-all@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 4MD94T6yWVz4b31C; Thu, 25 Aug 2022 17:31:37 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MD94T6W85z3L1r; Thu, 25 Aug 2022 17:31:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1661448697; 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=SnuSLjf1+pvaPAIkbGCcnaDuC6/SXuFQEW1mLNUvlc4=; b=cG5nPWVTBmgE5Qu9zj5Iyhbw6RRHx+zSq8JCq1MYUOVfTAdlRNbiAHHiPqHr3BwqD0seR5 uiOE2FfuJZqu32MmJOIY8NPCCYrNxz7OOCePo6J2/+vqvQ2lIAslMchH63huTSpZPrTeaV Myt9jOOWYzk2/AaQEkZUclhHZ0BOcLg0Ars0Rf688rQOD28wv4gOl9TgUKOV9t1ZWPBOUB csEUaFW0ezUCbT7IEP58rOLUmFav1W3OrnhUkN7MEEVRximrwfRmXNv6zZ4afBahwxHIB3 8rZqbLLlYNUPytFVEsr5rG4ywUkUSwUM5odSQjrU1zr9hj2mvOWqr4iQuNLAqw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4MD94T5cqLzwvD; Thu, 25 Aug 2022 17:31:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 27PHVbtO042497; Thu, 25 Aug 2022 17:31:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 27PHVbZt042496; Thu, 25 Aug 2022 17:31:37 GMT (envelope-from git) Date: Thu, 25 Aug 2022 17:31:37 GMT Message-Id: <202208251731.27PHVbZt042496@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: John Baldwin Subject: git: ecfbefc91e75 - stable/13 - bhyve xhci: Cache the value of MaxPStreams when initializing an endpoint. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: ecfbefc91e75674899b3014ab39720f4a13beca5 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1661448697; 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=SnuSLjf1+pvaPAIkbGCcnaDuC6/SXuFQEW1mLNUvlc4=; b=ZQobsDdLPZXkR1DXnw0ohYomlo1MYmolh1qFPe3OnU2G6qk7tM2UChW5R/J46fDqMYg7r5 ptdMMDLVxxBbZLx77Pfx2g5xQ97zHiSL17J5ny++qTFEmNxbRyFbmzYbMvLcOi4lHVkgjj 607PmW9Rbx/1KcDbRV/PsGq9q/RtWW4pT0ulupg5FpkhoDi0CPrgI9F57/I3ugnLhsiq/C Bal3Rl48WJoqQwS8ODqQ39u6BmHDEJ5Ep2V+MvV/yKMdthm+cTPvzkVm7Knnr/j5zR1Kjy MCOXUcbnU4imFVCru4s+CNsWw3Uti+WpyTVd/PevwWFDP125JV0yZbFyFr3m4w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1661448697; a=rsa-sha256; cv=none; b=BP4VNycX/5jxvx4aSN4rS3tUOgezzZJdDqG1/+N0yvho1Mx3NWu/rmQ3PrmGzDtWDMJ5dc oe1BmIesC7jFRwXOyk0iDbQo19UOxxUphVJ+e/ikCkAy36T1fE5xaWOCBtVcZlxwxLPa2b tFvDxTero9W0QkCam7AtjEa3S/yC4jGvJOa+/5vNWuxTGfj0z9aXAtTP7aXw7Cy4R+OF0H g0zlz8oeuWenwuTDbGmsnb8+V6XYEAJM89JSBsPbYStdkWFbem+uTLLraQDdypcXJ707GI hIcELHNEYqozFs6WlYkkWtoNP6n9ON2MUdIcDi9HDHsFJOzSP+ONpCeoRwp6VQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=ecfbefc91e75674899b3014ab39720f4a13beca5 commit ecfbefc91e75674899b3014ab39720f4a13beca5 Author: John Baldwin AuthorDate: 2022-08-17 17:00:36 +0000 Commit: John Baldwin CommitDate: 2022-08-25 16:35:12 +0000 bhyve xhci: Cache the value of MaxPStreams when initializing an endpoint. This avoids type confusion where a malicious guest could rewrite the MaxPStreams field in an endpoint context after the endpoint was initialized causing the device model to interpret a guest provided address (stored in ep_ringaddr of the "software" endpoint state) as a bhyve host process address (ep_sctx_trbs). It also prevents a malicious guest from triggering overflows of ep_sctx_trbs[] by increasing the number of streams after the endpoint has been initialized. Rather than re-reading the MaxPStreams value out of the endpoint context in guest memory on subsequent operations, cache the value in the software endpoint state. Possibly the device model should raise errors if the value of MaxPStreams changes while an endpoint is running. This approach simply ignores any such changes by the guest. PR: 264294, 264347 Reported by: Robert Morris Reviewed by: markj MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D36181 (cherry picked from commit e7439f6aeb235ba3a7e79818c56a63d066c80854) --- usr.sbin/bhyve/pci_xhci.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c index 1c0cf231a411..7548685fe41d 100644 --- a/usr.sbin/bhyve/pci_xhci.c +++ b/usr.sbin/bhyve/pci_xhci.c @@ -170,6 +170,13 @@ struct pci_xhci_dev_ep { #define ep_tr _ep_trbsctx._epu_tr #define ep_sctx _ep_trbsctx._epu_sctx + /* + * Caches the value of MaxPStreams from the endpoint context + * when an endpoint is initialized and is used to validate the + * use of ep_ringaddr vs ep_sctx_trbs[] as well as the length + * of ep_sctx_trbs[]. + */ + uint32_t ep_MaxPStreams; union { struct pci_xhci_trb_ring _epu_trb; struct pci_xhci_trb_ring *_epu_sctx_trbs; @@ -673,6 +680,7 @@ pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid) devep->ep_tr = XHCI_GADDR(dev->xsc, devep->ep_ringaddr); DPRINTF(("init_ep tr DCS %x", devep->ep_ccs)); } + devep->ep_MaxPStreams = pstreams; if (devep->ep_xfer == NULL) { devep->ep_xfer = malloc(sizeof(struct usb_data_xfer)); @@ -694,9 +702,8 @@ pci_xhci_disable_ep(struct pci_xhci_dev_emu *dev, int epid) ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_DISABLED; devep = &dev->eps[epid]; - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0 && - devep->ep_sctx_trbs != NULL) - free(devep->ep_sctx_trbs); + if (devep->ep_MaxPStreams > 0) + free(devep->ep_sctx_trbs); if (devep->ep_xfer != NULL) { free(devep->ep_xfer); @@ -1156,7 +1163,7 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_softc *sc, uint32_t slot, ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED; - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) == 0) + if (devep->ep_MaxPStreams == 0) ep_ctx->qwEpCtx2 = devep->ep_ringaddr | devep->ep_ccs; DPRINTF(("pci_xhci: reset ep[%u] %08x %08x %016lx %08x", @@ -1177,16 +1184,15 @@ done: static uint32_t pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep, - uint32_t streamid, struct xhci_stream_ctx **osctx) + struct pci_xhci_dev_ep *devep, uint32_t streamid, + struct xhci_stream_ctx **osctx) { struct xhci_stream_ctx *sctx; - uint32_t maxpstreams; - maxpstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep->dwEpCtx0); - if (maxpstreams == 0) + if (devep->ep_MaxPStreams == 0) return (XHCI_TRB_ERROR_TRB); - if (maxpstreams > XHCI_STREAMS_MAX) + if (devep->ep_MaxPStreams > XHCI_STREAMS_MAX) return (XHCI_TRB_ERROR_INVALID_SID); if (XHCI_EPCTX_0_LSA_GET(ep->dwEpCtx0) == 0) { @@ -1195,7 +1201,7 @@ pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep, } /* only support primary stream */ - if (streamid > maxpstreams) + if (streamid > devep->ep_MaxPStreams) return (XHCI_TRB_ERROR_STREAM_TYPE); sctx = XHCI_GADDR(sc, ep->qwEpCtx2 & ~0xFUL) + streamid; @@ -1257,11 +1263,12 @@ pci_xhci_cmd_set_tr(struct pci_xhci_softc *sc, uint32_t slot, } streamid = XHCI_TRB_2_STREAM_GET(trb->dwTrb2); - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0) { + if (devep->ep_MaxPStreams > 0) { struct xhci_stream_ctx *sctx; sctx = NULL; - cmderr = pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx); + cmderr = pci_xhci_find_stream(sc, ep_ctx, devep, streamid, + &sctx); if (sctx != NULL) { assert(devep->ep_sctx != NULL); @@ -1631,7 +1638,7 @@ pci_xhci_update_ep_ring(struct pci_xhci_softc *sc, struct pci_xhci_dev_emu *dev, uint32_t streamid, uint64_t ringaddr, int ccs) { - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { + if (devep->ep_MaxPStreams != 0) { devep->ep_sctx[streamid].qwSctx0 = (ringaddr & ~0xFUL) | (ccs & 0x1); @@ -1942,7 +1949,7 @@ pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot, } /* get next trb work item */ - if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { + if (devep->ep_MaxPStreams != 0) { struct xhci_stream_ctx *sctx; /* @@ -1955,7 +1962,7 @@ pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot, } sctx = NULL; - pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx); + pci_xhci_find_stream(sc, ep_ctx, devep, streamid, &sctx); if (sctx == NULL) { DPRINTF(("pci_xhci: invalid stream %u", streamid)); return;