mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-12-18 05:28:36 -07:00
An abort happens in ohci_frame_boundary() when ohci->done is 0 [1].
``` c
static void ohci_frame_boundary(void *opaque)
{
// ...
if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
if (!ohci->done)
abort(); <----------------------------------------- [1]
```
This was reported in https://bugs.launchpad.net/qemu/+bug/1911216/,
https://lists.gnu.org/archive/html/qemu-devel/2021-06/msg03613.html, and
https://gitlab.com/qemu-project/qemu/-/issues/545. I can still reproduce it with
the latest QEMU.
This happends due to crafted ED with putting ISO_TD at physical address 0.
Suppose ed->head & OHCI_DPTR_MASK is 0 [2], and we memset 0 to the phyiscal
memory from 0 to sizeof(ohci_iso_td). Then, starting_frame [3] and frame_count
[4] are both 0. As we can control the value of ohci->frame_number (0 to 0x1f,
suppose 1), we then control the value of relative_frame_number to be 1 [6]. The
control flow goes to [7] where ohci->done is 0. Have returned from
ohci_service_iso_td(), ohci_frame_boundary() will abort() [1].
``` c
static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed)
{
// ...
addr = ed->head & OHCI_DPTR_MASK; // <--------------------- [2]
if (ohci_read_iso_td(ohci, addr, &iso_td)) { // <-------- [3]
// ...
starting_frame = OHCI_BM(iso_td.flags, TD_SF); // <-------- [4]
frame_count = OHCI_BM(iso_td.flags, TD_FC); // <-------- [5]
relative_frame_number = USUB(ohci->frame_number, starting_frame);
// <-------- [6]
if (relative_frame_number < 0) {
return 1;
} else if (relative_frame_number > frame_count) {
// ...
ohci->done = addr; // <-------- [7]
// ...
}
```
As only (afaik) a guest root user can manipulate ED, TD and the physical memory,
this assertion failure is not a security bug.
The idea to fix this issue is to drop ohci_service_iso_td() if ed->head &
OHCI_DPTR_MASK is 0, which is similar to the drop operation for
ohci_service_ed_list() when head is 0. Probably, a similar issue is in
ohci_service_td(). I drop ohci_service_td() if ed->head & OHCI_DPTR_MASK is 0.
Fixes:
|
||
|---|---|---|
| .. | ||
| bus.c | ||
| canokey.c | ||
| canokey.h | ||
| ccid-card-emulated.c | ||
| ccid-card-passthru.c | ||
| ccid.h | ||
| chipidea.c | ||
| combined-packet.c | ||
| core.c | ||
| desc-msos.c | ||
| desc.c | ||
| desc.h | ||
| dev-audio.c | ||
| dev-hid.c | ||
| dev-hub.c | ||
| dev-mtp.c | ||
| dev-network.c | ||
| dev-serial.c | ||
| dev-smartcard-reader.c | ||
| dev-storage-bot.c | ||
| dev-storage-classic.c | ||
| dev-storage.c | ||
| dev-uas.c | ||
| dev-wacom.c | ||
| hcd-dwc2.c | ||
| hcd-dwc2.h | ||
| hcd-dwc3.c | ||
| hcd-ehci-pci.c | ||
| hcd-ehci-sysbus.c | ||
| hcd-ehci.c | ||
| hcd-ehci.h | ||
| hcd-musb.c | ||
| hcd-ohci-pci.c | ||
| hcd-ohci.c | ||
| hcd-ohci.h | ||
| hcd-uhci.c | ||
| hcd-uhci.h | ||
| hcd-xhci-nec.c | ||
| hcd-xhci-pci.c | ||
| hcd-xhci-pci.h | ||
| hcd-xhci-sysbus.c | ||
| hcd-xhci-sysbus.h | ||
| hcd-xhci.c | ||
| hcd-xhci.h | ||
| host-libusb.c | ||
| host.h | ||
| imx-usb-phy.c | ||
| Kconfig | ||
| libhw.c | ||
| meson.build | ||
| pcap.c | ||
| quirks-ftdi-ids.h | ||
| quirks-pl2303-ids.h | ||
| quirks.c | ||
| quirks.h | ||
| redirect.c | ||
| trace-events | ||
| trace.h | ||
| tusb6010.c | ||
| u2f-emulated.c | ||
| u2f-passthru.c | ||
| u2f.c | ||
| u2f.h | ||
| vt82c686-uhci-pci.c | ||
| xen-usb.c | ||
| xlnx-usb-subsystem.c | ||
| xlnx-versal-usb2-ctrl-regs.c | ||