Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 May 2022 16:43:24 +0000
From:      bugzilla-noreply@freebsd.org
To:        virtualization@FreeBSD.org
Subject:   [Bug 264294] guest can trick bhyve xhci into reading through a guest-controlled pointer
Message-ID:  <bug-264294-27103@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D264294

            Bug ID: 264294
           Summary: guest can trick bhyve xhci into reading through a
                    guest-controlled pointer
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: bhyve
          Assignee: virtualization@FreeBSD.org
          Reporter: rtm@lcs.mit.edu

The second union in Bhyve's struct pci_xhci_dev_ep causes these two
fields to occupy the same memory:

#define ep_ringaddr     _ep_trb_rings._epu_trb.ringaddr
#define ep_sctx_trbs    _ep_trb_rings._epu_sctx_trbs

Which of the two bhyve's pci_xhci.c uses depends on whether the guest
configures the number of streams to be non-zero. Bhyve interprets one
as a guest address that must be checked and mapped before each use,
and the other as a host address that can be used directly with no
checking. In the former case, the guest provides the value; in the
latter, Bhyve.

The number of streams is determined by bits in ep_ctx->dwEpCtx0, which
lives in guest memory. So it's possible for the guest to tell byhve's
xhci to configure an endpoint with the number of streams set to zero,
which causes pci_xhci_init_ep() to set devep->ep_ringaddr to a
guest-provided value XYZ (assumed to be an address in guest memory,
but can be anything the guest wants). Later, the guest can change
ep_ctx->dwEpCtx0 to indicate multiple streams, and write to an xhci
doorbell register, causing Byhyve's pci_xhci_device_doorbell() to
execute:

                sctx_tr =3D &devep->ep_sctx_trbs[streamid];
                ringaddr =3D sctx_tr->ringaddr;

which interprets devep->ep_sctx_trbs as a *host* pointer. But those
bits contain the guest-provided value XYZ previously written there by
pci_xhci_init_ep(). So "sctx_tr->ringaddr" will dereference a pointer
provided by the guest, without any checks.

I have a modified FreeBSD guest that makes Bhyve crash due to this
bug.

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-264294-27103>