Syzbot and KASAN found the following invalid-free bug in
port_over_current_notify():
--------------------------------------------------------------------------
BUG: KASAN: double-free or invalid-free in port_over_current_notify
drivers/usb/core/hub.c:5192 [inline]
BUG: KASAN: double-free or invalid-free in port_event
drivers/usb/core/hub.c:5241 [inline]
BUG: KASAN: double-free or invalid-free in hub_event+0xd97/0x4140
drivers/usb/core/hub.c:5384
CPU: 1 PID: 32710 Comm: kworker/1:3 Not tainted 4.20.0-rc3+ #129
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x244/0x39d lib/dump_stack.c:113
print_address_description.cold.7+0x9/0x1ff mm/kasan/report.c:256
kasan_report_invalid_free+0x64/0xa0 mm/kasan/report.c:336
__kasan_slab_free+0x13a/0x150 mm/kasan/kasan.c:501
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kfree+0xcf/0x230 mm/slab.c:3817
port_over_current_notify drivers/usb/core/hub.c:5192 [inline]
port_event drivers/usb/core/hub.c:5241 [inline]
hub_event+0xd97/0x4140 drivers/usb/core/hub.c:5384
process_one_work+0xc90/0x1c40 kernel/workqueue.c:2153
worker_thread+0x17f/0x1390 kernel/workqueue.c:2296
kthread+0x35a/0x440 kernel/kthread.c:246
ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352
--------------------------------------------------------------------------
The problem is caused by use of a static array to store
environment-string pointers. When the routine is called by multiple
threads concurrently, the pointers from one thread can overwrite those
from another.
The solution is to use an ordinary automatic array instead of a static
array.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: syzbot+98881958e1410ec7e53c@syzkaller.appspotmail.com
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This will clear the USB_PORT_FEAT_C_CONNECTION bit in case of a hub port reset
only if a device is was attached to the hub port before resetting the hub port.
Using a Lenovo T480s attached to the ultra dock it was not possible to detect
some usb-c devices at the dock usb-c ports because the hub_port_reset code
will clear the USB_PORT_FEAT_C_CONNECTION bit after the actual hub port reset.
Using this device combo the USB_PORT_FEAT_C_CONNECTION bit was set between the
actual hub port reset and the clear of the USB_PORT_FEAT_C_CONNECTION bit.
This ends up with clearing the USB_PORT_FEAT_C_CONNECTION bit after the
new device was attached such that it was not detected.
This patch will not clear the USB_PORT_FEAT_C_CONNECTION bit if there is
currently no device attached to the port before the hub port reset.
This will avoid clearing the connection bit for new attached devices.
Signed-off-by: Dennis Wassenberg <dennis.wassenberg@secunet.com>
Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Devices connected under Terminus Technology Inc. Hub (1a40:0101) may
fail to work after the system resumes from suspend:
[ 206.063325] usb 3-2.4: reset full-speed USB device number 4 using xhci_hcd
[ 206.143691] usb 3-2.4: device descriptor read/64, error -32
[ 206.351671] usb 3-2.4: device descriptor read/64, error -32
Info for this hub:
T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=480 MxCh= 4
D: Ver= 2.00 Cls=09(hub ) Sub=00 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=1a40 ProdID=0101 Rev=01.11
S: Product=USB 2.0 Hub
C: #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
Some expirements indicate that the USB devices connected to the hub are
innocent, it's the hub itself is to blame. The hub needs extra delay
time after it resets its port.
Hence wait for extra delay, if the device is connected to this quirky
hub.
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Cc: stable <stable@vger.kernel.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently the allocation of port_dev_path from the call to
kobject_get_path is not being kfree'd, causing a memory leak. Fix
this by kfree'ing this at the end of the function. Add an extra
error exit path to fix one of the early leaks when envp[0] fails
to be allocated.
Detected by CoverityScan, CID#1473771 ("Resource Leak")
Fixes: 201af55da8 ("usb: core: added uevent for over-current")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
The new scheme is required just to support legacy low and full-speed
devices. For high speed devices, it will slower the enumeration speed.
So in this patch we try the "old" enumeration scheme first for high speed
devices, and this is what Windows does since Windows 8.
Signed-off-by: Zeng Tao <prime.zeng@hisilicon.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Reviewed-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
After commit 1cbd53c8cd ("usb: core: introduce per-port over-current
counters") usb ports expose a sysfs value 'over_current_count'
to user space. This value on its own is not very useful as it requires
manual polling.
As a solution, fire a udev event from the usb hub device that specifies
the values 'OVER_CURRENT_PORT' and 'OVER_CURRENT_COUNT' that indicate
the path of the usb port where the over-current event occurred and the
value of 'over_current_count' in sysfs. Additionally, call
sysfs_notify() so the sysfs value supports poll().
Signed-off-by: Jon Flatley <jflat@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Based on USB2.0 Spec Section 11.12.5,
"If a hub has per-port power switching and per-port current limiting,
an over-current on one port may still cause the power on another port
to fall below specific minimums. In this case, the affected port is
placed in the Power-Off state and C_PORT_OVER_CURRENT is set for the
port, but PORT_OVER_CURRENT is not set."
so let's check C_PORT_OVER_CURRENT too for over current condition.
Fixes: 08d1dec6f4 ("usb:hub set hub->change_bits when over-current happens")
Cc: <stable@vger.kernel.org>
Tested-by: Alessandro Antenucci <antenucci@korg.it>
Signed-off-by: Bin Liu <b-liu@ti.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
When a USB device attached to a root-hub port sends a wakeup request
to a sleeping system, we do not report the wakeup event to the PM
core. This is because a system resume involves waking up all
suspended USB ports as quickly as possible; without the normal
USB_RESUME_TIMEOUT delay, the host controller driver doesn't set the
USB_PORT_STAT_C_SUSPEND flag and so usb_port_resume() doesn't realize
that a wakeup request was received.
However, some environments (such as Chrome OS) want to have all wakeup
events reported so they can be ascribed to the appropriate device. To
accommodate these environments, this patch adds a new routine to the
hub driver and a corresponding new HCD method to be used when a root
hub resumes. The HCD method returns a bitmap of ports that have
initiated a wakeup signal but not yet completed resuming. The hub
driver can then report to the PM core that the child devices attached
to these ports initiated a wakeup event.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Suggested-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently, the USB hub core waits for 50 ms after enumerating the
device. This was added to help "some high speed devices" to
enumerate (b789696af8 "[PATCH] USB: relax usbcore reset timings").
On some devices, the time-to-active is important, so we provide
a per-port option to reduce the time to what the USB specification
requires: 10 ms.
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
The "old" enumeration scheme is considerably faster (it takes
~244ms instead of ~356ms to get the descriptor).
It is currently only possible to use the old scheme globally
(/sys/module/usbcore/parameters/old_scheme_first), which is not
desirable as the new scheme was introduced to increase compatibility
with more devices.
However, in our case, we care about time-to-active for a specific
USB device (which we make the firmware for), on a specific port
(that is pogo-pin based: not a standard USB port). This new
sysfs option makes it possible to use the old scheme on a single
port only.
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Some low-speed and full-speed devices (for example, bluetooth)
do not have time to initialize. For them, ETIMEDOUT is a valid error.
We need to give them another try. Otherwise, they will
never be initialized correctly and in dmesg will be messages
"Bluetooth: hci0 command 0x1002 tx timeout" or similars.
Fixes: 264904ccc3 ("usb: retry reset if a device times out")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.pedros@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
USB 3.2 specification adds a Gen XxY notion for USB3 devices where
X is the signaling rate on the wire. Gen 1xY is 5Gbps Superspeed
and Gen 2xY is 10Gbps SuperSpeedPlus. Y is the lane count.
For normal, non inter-chip (SSIC) devies the rx and tx lane count is
symmetric, and the maximum lane count for USB 3.2 devices is 2 (dual-lane).
SSIC devices may have asymmetric lane counts, with up to four
lanes per direction. The USB 3.2 specification doesn't point out
how to use the Gen XxY notion for these devices, so we limit the Gen Xx2
notion to symmertic Dual lane devies.
For other devices just show Gen1 or Gen2
Gen 1 5Gbps
Gen 2 10Gbps
Gen 1x2 10Gbps Dual-lane (USB 3.2)
Gen 2x2 20Gbps Dual-lane (USB 3.2)
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
USB 3.2 specification adds Dual-lane support, doubling the maximum
SuperSpeedPlus data rate from 10Gbps to 20Gbps.
Dual-lane takes into use a second set of rx and tx wires/pins in the
Type-C cable and connector.
Add "rx_lanes" and "tx_lanes" variables to struct usb_device to store
the numer of lanes in use. Number of lanes can be read using the extended
port status hub request that was introduced in USB 3.1.
Extended port status rx and tx lane count are zero based, maximum
lanes supported by non inter-chip (SSIC) USB 3.2 is 2 (dual lane) with
rx and tx lane count symmetric. SSIC devices support asymmetric lanes
up to 4 lanes per direction.
If extended port status is not available then default to one lane.
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
wait_for_connected() wait till a port change status to
USB_PORT_STAT_CONNECTION, but this is not possible if
the port is unpowered. The loop will only exit at timeout.
Such case take place if an over-current incident happen
while system is in S3. Then during resume wait_for_connected()
will wait 2s, which may be noticeable by the user.
Signed-off-by: Dominik Bozek <dominikx.bozek@intel.com>
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
On chromebooks we depend on wakeup count to identify the wakeup source.
But currently USB devices do not increment the wakeup count when they
trigger the remote wake. This patch addresses the same.
Resume condition is reported differently on USB 2.0 and USB 3.0 devices.
On USB 2.0 devices, a wake capable device, if wake enabled, drives
resume signal to indicate a remote wake (USB 2.0 spec section 7.1.7.7).
The upstream facing port then sets C_PORT_SUSPEND bit and reports a
port change event (USB 2.0 spec section 11.24.2.7.2.3). Thus if a port
has resumed before driving the resume signal from the host and
C_PORT_SUSPEND is set, then the device attached to the given port might
be the reason for the last system wakeup. Increment the wakeup count for
the same.
On USB 3.0 devices, a function may signal that it wants to exit from device
suspend by sending a Function Wake Device Notification to the host (USB3.0
spec section 8.5.6.4) Thus on receiving the Function Wake, increment the
wakeup count.
Signed-off-by: Ravi Chandra Sadineni <ravisadineni@chromium.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Print bcdDevice which is used by vendors to identify different versions
of the same product (or different versions of firmware).
Adding this to the logs will be useful for support purposes.
Match the %2x.%02x formatting that's used by lsusb -v for this same value.
Signed-off-by: Benson Leung <bleung@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Currently we warn the user when the root hub lost power after resume,
but the user cannot do anything about it so it should probably be a
notice.
This will reduce the noise in the console during suspend and resume,
which is already quite significant in many systems.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
For some userspace applications information on the number of
over-current conditions at specific USB hub ports is relevant.
In our case we have a series of USB hardware (using the cp210x driver)
which communicates using a proprietary protocol. These devices sometimes
trigger an over-current situation on some hubs. In case of such an
over-current situation the USB devices offer an interface for reducing
the max used power. As these conditions are quite rare and imply
performance reductions of the device we don't want to reduce the max
power always.
Therefore give user-space applications the possibility to react
adequately by introducing an over_current_counter in the usb port struct
which is exported via sysfs.
Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Disabing Latency Tolerance Messaging before port reset is unnecessary.
LTM is automatically disabled at port reset.
If host can't communicate with the device the LTM message will fail, and
the hub driver will unnecessarily do a logical disconnect.
Broken communication is ofter the reason for a reset in the first place.
Additionally we can't guarantee device is in a configured state,
epecially in reset-resume case when root hub lost power.
LTM can't be modified unless device is in a configured state.
Just remove LTM disabling before port reset.
Details about LTM and port reset in USB 3 specification:
USB 3 spec section 9.4.5
"The LTM Enable field can be modified by the SetFeature() and
ClearFeature() requests using the LTM_ENABLE feature selector.
This field is reset to zero when the device is reset."
USB 3 spec section 9.4.1
"The device shall process a Clear Feature (U1_Enable or U2_Enable or
LTM_Enable) only if the device is in the configured state."
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
USB SS and SSP hubs provide wHubDelay values on their hub descriptor
which we should inform the USB Device about.
The USB Specification 3.0 explains, on section 9.4.11, how to
calculate the value and how to issue the request. Note that a
USB_REQ_SET_ISOCH_DELAY is valid on all device states (Default,
Address, Configured), we just *chose* to issue it from Address state
right after successfully fetching the USB Device Descriptor.
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>