Message ID | 20240509002916.138802-1-dmamfmgm@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT | expand |
On Thu, 9 May 2024 at 01:30, David Hubbard <dmamfmgm@gmail.com> wrote: > > From: Cord Amfmgm <dmamfmgm@gmail.com> > > 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 philmd@linaro.org, mjt@tls.msk.ru, > and kraxel@redhat.com: > > * testBadSetup.img.xz > * sha256: 045b43f4396de02b149518358bf8025d5ba11091e86458875339fc649e6e5ac6 > > Signed-off-by: Cord Amfmgm <dmamfmgm@gmail.com> > --- > 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 <peter.maydell@linaro.org> 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
On Mon, May 20, 2024 at 11:55 AM Peter Maydell <peter.maydell@linaro.org> wrote: > On Thu, 9 May 2024 at 01:30, David Hubbard <dmamfmgm@gmail.com> wrote: > > > > From: Cord Amfmgm <dmamfmgm@gmail.com> > > > > 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 philmd@linaro.org, > mjt@tls.msk.ru, > > and kraxel@redhat.com: > > > > * testBadSetup.img.xz > > * sha256: > 045b43f4396de02b149518358bf8025d5ba11091e86458875339fc649e6e5ac6 > > > > Signed-off-by: Cord Amfmgm <dmamfmgm@gmail.com> > > --- > > 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 <peter.maydell@linaro.org> > > 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 > For this patch (the SETUP pid validation), I am happy if you take the patch and apply it with Author and Signed-off-by set to "David Hubbard." Please go ahead.
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"