On Thu, 9 May 2024 at 01:30, David Hubbard <[email protected]> wrote:
>
> From: Cord Amfmgm <[email protected]>
>
> This changes the ohci validation to not assert if invalid data is fed to the
> ohci controller. The poc in https://bugs.launchpad.net/qemu/+bug/1907042 and
> migrated to bug #303 does the following to feed it a SETUP pid (valid)
> at an EndPt of 1 (invalid - all SETUP pids must be addressed to EndPt 0):
>
>         uint32_t MaxPacket = 64;
>         uint32_t TDFormat = 0;
>         uint32_t Skip = 0;
>         uint32_t Speed = 0;
>         uint32_t Direction = 0;  /* #define OHCI_TD_DIR_SETUP 0 */
>         uint32_t EndPt = 1;
>         uint32_t FuncAddress = 0;
>         ed->attr = (MaxPacket << 16) | (TDFormat << 15) | (Skip << 14)
>                    | (Speed << 13) | (Direction << 11) | (EndPt << 7)
>                    | FuncAddress;
>         ed->tailp = /*TDQTailPntr= */ 0;
>         ed->headp = ((/*TDQHeadPntr= */ &td[0]) & 0xfffffff0)
>                    | (/* ToggleCarry= */ 0 << 1);
>         ed->next_ed = (/* NextED= */ 0 & 0xfffffff0)
>
> qemu-fuzz also caught the same issue in #1510. They are both fixed by this
> patch.
>
> With a tiny OS[1] that boots and executes the poc the repro shows the issue:
>
> * OS that sends USB requests to a USB mass storage device
>   but sends a SETUP with EndPt = 1
> * qemu 6.2.0 (Debian 1:6.2+dfsg-2ubuntu6.19)
> * qemu HEAD (4e66a0854)
> * Actual OHCI controller (hardware)
>
> Command line:
> qemu-system-x86_64 -m 20 \
>  -device pci-ohci,id=ohci \
>  -drive if=none,format=raw,id=d,file=testmbr.raw \
>  -device usb-storage,bus=ohci.0,drive=d \
>  --trace "usb_*" --trace "ohci_*" -D qemu.log
>
> Results are:
>
>  qemu 6.2.0 | qemu HEAD | actual HW
> ------------+-----------+----------------
>  assertion  | assertion | sets stall bit
>
> The assertion message is:
>
> > qemu-system-x86_64: ../../hw/usb/core.c:744: usb_ep_get: Assertion `pid == 
> > USB_TOKEN_IN || pid == USB_TOKEN_OUT' failed.
> > Aborted (core dumped)
>
> Tip: if the flags "-serial pty -serial stdio" are added to the command line
> the poc outputs its USB requests like this:
>
> > Free mem 2M ohci port0 conn FS
> > setup { 80 6 0 1 0 0 8 0 }
> > ED info=80000 { mps=8 en=0 d=0 } tail=c20920
> >   td0 c20880 nxt=c20960 f2000000 setup cbp=c20900 be=c20907       cbp=0 
> > be=c20907
> >   td1 c20960 nxt=c20980 f3140000    in cbp=c20908 be=c2090f       cbp=0 
> > be=c2090f
> >   td2 c20980 nxt=c20920 f3080000   out cbp=0 be=0                 cbp=0 be=0
> >    rx { 12 1 0 2 0 0 0 8 }
> > setup { 0 5 1 0 0 0 0 0 } tx {}
> > ED info=80000 { mps=8 en=0 d=0 } tail=c20880
> >   td0 c20920 nxt=c20960 f2000000 setup cbp=c20900 be=c20907       cbp=0 
> > be=c20907
> >   td1 c20960 nxt=c20880 f3100000    in cbp=0 be=0                 cbp=0 be=0
> > setup { 80 6 0 1 0 0 12 0 }
> > ED info=80081 { mps=8 en=0 d=1 } tail=c20960
> >   td0 c20880 nxt=c209c0 f2000000 setup cbp=c20920 be=c20927
> >   td1 c209c0 nxt=c209e0 f3140000    in cbp=c20928 be=c20939
> >   td2 c209e0 nxt=c20960 f3080000   out cbp=0 be=0qemu-system-x86_64: 
> > ../../hw/usb/core.c:744: usb_ep_get: Assertion `pid == USB_TOKEN_IN || pid 
> > == USB_TOKEN_OUT' failed.
> > Aborted (core dumped)
>
> [1] The OS disk image has been emailed to [email protected], [email protected],
> and [email protected]:
>
> * testBadSetup.img.xz
> * sha256: 045b43f4396de02b149518358bf8025d5ba11091e86458875339fc649e6e5ac6
>
> Signed-off-by: Cord Amfmgm <[email protected]>
> ---
>  hw/usb/hcd-ohci.c   | 5 +++++
>  hw/usb/trace-events | 1 +
>  2 files changed, 6 insertions(+)
>
> diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
> index fc8fc91a1d..acd6016980 100644
> --- a/hw/usb/hcd-ohci.c
> +++ b/hw/usb/hcd-ohci.c
> @@ -927,6 +927,11 @@ static int ohci_service_td(OHCIState *ohci, struct 
> ohci_ed *ed)
>      case OHCI_TD_DIR_SETUP:
>          str = "setup";
>          pid = USB_TOKEN_SETUP;
> +        if (OHCI_BM(ed->flags, ED_EN) > 0) {  /* setup only allowed to ep 0 
> */
> +            trace_usb_ohci_td_bad_pid(str, ed->flags, td.flags);
> +            ohci_die(ohci);
> +            return 1;
> +        }
>          break;
>      default:
>          trace_usb_ohci_td_bad_direction(dir);
> diff --git a/hw/usb/trace-events b/hw/usb/trace-events
> index ed7dc210d3..fd7b90d70c 100644
> --- a/hw/usb/trace-events
> +++ b/hw/usb/trace-events
> @@ -28,6 +28,7 @@ usb_ohci_iso_td_data_overrun(int ret, ssize_t len) 
> "DataOverrun %d > %zu"
>  usb_ohci_iso_td_data_underrun(int ret) "DataUnderrun %d"
>  usb_ohci_iso_td_nak(int ret) "got NAK/STALL %d"
>  usb_ohci_iso_td_bad_response(int ret) "Bad device response %d"
> +usb_ohci_td_bad_pid(const char *s, uint32_t edf, uint32_t tdf) "Bad pid %s: 
> ed.flags 0x%x td.flags 0x%x"
>  usb_ohci_port_attach(int index) "port #%d"
>  usb_ohci_port_detach(int index) "port #%d"
>  usb_ohci_port_wakeup(int index) "port #%d"
> --

For this patch,

Reviewed-by: Peter Maydell <[email protected]>

Are you happy for me to take this patch and apply it to
target-arm.next with the git Author and Signed-off-by:
lines both being "David Hubbard" ? (I think if I understand
our conversation in the other mail thread that that's the
right thing.)

thanks
-- PMM

Reply via email to