lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CACF_Uwo2jZ2duXm_B6GdcLd3yPr0+CJ0sCBTDRqwkuX_KF81Ug@mail.gmail.com>
Date: Tue, 22 Jul 2025 23:59:40 +0200
From: Marco Tormento <mtormento80@...il.com>
To: Alan Stern <stern@...land.harvard.edu>
Cc: gregkh@...uxfoundation.org, linux-usb@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH] USB: hub: Move typec deattach before children
 disconnections in usb_disconnect()

On Tue, 22 Jul 2025 at 05:05, Alan Stern <stern@...land.harvard.edu> wrote:
>
> On Tue, Jul 22, 2025 at 01:18:25AM +0200, Marco Tormento wrote:
> > On Mon, 21 Jul 2025 at 03:21, Alan Stern <stern@...land.harvard.edu> wrote:
> > > I'm not a typec expert; in fact I know practically nothing about it.
> > > Nevertheless, this sounds strange.  The recursive usb_disconnect() calls
> > > should affect the connectors to the monitor's children and the monitor's
> > > own ports, not the connector or port on the monitor's parent hub.
> >
> > What you wrote makes total sense, let me add some detail though.
> > When I plug the monitor to the thunderbolt port, 3 usb hubs pop up, but only 2
> > are backed by XHCI Host Controllers: usb3 and usb4.
>
> I don't know what you mean when you say "backed by".  usb3 and usb4 are
> the two root hubs of the xHCI host controller.  usb3-1 is an internal
> hub (presumably built into the monitor) attached to the usb3 root hub.

Mine was a failed attempt at expressing what you wrote :-).
My understanding is that usb3 and usb4 root hubs are somehow part of the
thunderbolt controller, because they are not brought up if I plug the monitor
into the other typec port.

> > typec port0: bound usb3-port1 (ops connector_ops [usbcore])
> > typec port0: bound usb4-port1 (ops connector_ops [usbcore])
> > typec port1: bound usb3-port2 (ops connector_ops [usbcore])
> > typec port1: bound usb4-port2 (ops connector_ops [usbcore])
>
> Why are the usb3 port connectors getting bound at this point rather than
> when usb3 was registered?

Not sure, but maybe this is a consequence of the fact usb4 is on a shared hcd of
usb3 pci device? See the stack traces below.

> > When I unplug the monitor though, usb 3-1 is not processed as part of
> > hub_disconnect_children() of usb3 hub, as I would expect.
>
> Are you sure about this?  How did you reach that conclusion?

I checked the stack traces of usb_disconnect().

usb 3-1 is triggered by hub_event():

usb 3-1: [usb_disconnect] debugging()
...cut...
Workqueue: usb_hub_wq hub_event [usbcore]
Call Trace:
 <TASK>
 dump_stack_lvl+0x5d/0x80
 usb_disconnect+0x38/0x2f4 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
 hub_event.cold+0x73e/0xc50 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
...cut

usb4 is not:

usb usb4: [usb_disconnect] debugging()
...cut...
Workqueue: kacpi_hotplug acpi_hotplug_work_fn
Call Trace:
 <TASK>
 dump_stack_lvl+0x5d/0x80
 usb_disconnect+0x38/0x2f4 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_remove_hcd.cold+0xc6/0x1bb [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 xhci_pci_remove+0x6a/0xd0 [xhci_pci 89d1427fd34e7648221e69cd90b20ad6e1fd2fd6]
 pci_device_remove+0x47/0xc0
...cut

usb3 is a little bit different compared to usb4, it has a call to
usb_hcd_pci_remove():

usb usb3: [usb_disconnect] debugging()
...cut...
Workqueue: kacpi_hotplug acpi_hotplug_work_fn
Call Trace:
 <TASK>
 dump_stack_lvl+0x5d/0x80
 usb_disconnect+0x38/0x2f4 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_remove_hcd.cold+0xc6/0x1bb [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_hcd_pci_remove+0x7a/0x110 [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 xhci_pci_remove+0x89/0xd0 [xhci_pci 89d1427fd34e7648221e69cd90b20ad6e1fd2fd6]
 pci_device_remove+0x47/0xc0
...cut

There's a branch in xhci_pci_remove() on xhci->shared_hcd being valid.

So it seems:
- xhci_pci_remove() is called
- xhci->shared_hcd is valid so usb_remove_hcd() is called which triggers usb4
  usb_disconnect()
- usb_hcd_pci_remove() is then called which does a lot of stuff + calls
  usb_remove_hcd() which triggers usb3 usb_disconnect()

No idea what this shared hcd implies, by the way.

I also got this stack trace of the port unbinding, which happens
in typec_aggregate_unbind() in the usb4 usb_disconnect() trace:

usb usb4: [hub_disconnect] debugging
usb usb4-port2: [usb_hub_remove_port_device] debugging: port 1
...cut...
Workqueue: kacpi_hotplug acpi_hotplug_work_fn
Call Trace:
 <TASK>
 dump_stack_lvl+0x5d/0x80
 typec_aggregate_unbind+0x12/0x30 [typec
6de6f75aa8c9f6a0a8c73a05ed9c668a2b7634cf]
 component_del+0xb8/0x150
 usb_hub_remove_port_device+0xf8/0x115 [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 hub_disconnect+0x95/0x160 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_unbind_interface+0xb6/0x1ef [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 ? kernfs_remove_by_name_ns+0xbe/0xe0
 device_release_driver_internal+0x19e/0x200
 bus_remove_device+0xc2/0x130
 device_del+0x160/0x3d0
 ? kobject_put+0xa2/0x200
 usb_disable_device+0xf4/0x220 [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_disconnect+0x117/0x2f4 [usbcore d46dddc5902949f0a284aff7ecf8d6e861774323]
 usb_remove_hcd.cold+0xc6/0x1bb [usbcore
d46dddc5902949f0a284aff7ecf8d6e861774323]
 xhci_pci_remove+0x6a/0xd0 [xhci_pci 89d1427fd34e7648221e69cd90b20ad6e1fd2fd6]
 pci_device_remove+0x47/0xc0
...cut...
 </TASK>
typec port1: [connector_unbind] unbinding connector from usb4-port2
typec port1: [connector_unbind] unbinding connector from usb3-port2

> > Maybe usb 3-1 should be disconnected as a child of usb3, but even in that case
> > we would still end up in the same situation because it's usb4 disconnection that
> > is doing the unbinding.
> > Since there's no dependency between usb3 and usb4 they can be
> > disconnected in any order and it's just a matter of luck as it is right now.
>
> That last sentence is totally wrong.  usb3 and usb4 are closely
> connected, since they represent logical components of the same xHCI
> controller, and they will always be unregistered in the same order.
> usb3 is the USB-2 root hub (the one connected to the physical wires
> carrying the USB-2 low/full/high-speed signals), and usb4 is the USB-3
> root hub (the one connected to the physical wires carrying the USB-3
> SuperSpeed and SuperSpeedPlus signals).

That makes a lot of sense.
Unfortunately I realized this could be the order half an hour after having
pressed "send"...
Thank you for the explanation!

> This still leaves the puzzle about why the typec things are handled this
> way.  In particular, if connector_unbind undoes the binding of the typec
> ports that happened when usb4 was registered, then what action is
> typec_unregister_partner supposed to undo, and when was it supposed to
> happen?  As a general rule, disconnection and unregistration actions
> take place in the reverse order of the corresponding connection and
> registration actions.
>
> Questions like this are best directed at the maintainers of the
> USB-4/Thunderbolt and typec subsystems.

Should I just cc them here or should I open a new thread with them?

Marco Tormento

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ