* [PATCH 1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT
@ 2024-05-09 0:29 David Hubbard
2024-05-20 16:54 ` Peter Maydell
0 siblings, 1 reply; 3+ messages in thread
From: David Hubbard @ 2024-05-09 0:29 UTC (permalink / raw)
To: qemu-devel
Cc: Philippe Mathieu-Daude, Michael Tokarev, Gerd Hoffmann,
Cord Amfmgm
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"
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT
2024-05-09 0:29 [PATCH 1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT David Hubbard
@ 2024-05-20 16:54 ` Peter Maydell
2024-05-20 22:10 ` Cord Amfmgm
0 siblings, 1 reply; 3+ messages in thread
From: Peter Maydell @ 2024-05-20 16:54 UTC (permalink / raw)
To: Cord Amfmgm
Cc: qemu-devel, Philippe Mathieu-Daude, Michael Tokarev,
Gerd Hoffmann
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT
2024-05-20 16:54 ` Peter Maydell
@ 2024-05-20 22:10 ` Cord Amfmgm
0 siblings, 0 replies; 3+ messages in thread
From: Cord Amfmgm @ 2024-05-20 22:10 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Philippe Mathieu-Daude, Michael Tokarev,
Gerd Hoffmann
[-- Attachment #1: Type: text/plain, Size: 5839 bytes --]
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.
[-- Attachment #2: Type: text/html, Size: 7766 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-05-20 22:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-09 0:29 [PATCH 1/2] hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT David Hubbard
2024-05-20 16:54 ` Peter Maydell
2024-05-20 22:10 ` Cord Amfmgm
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).