libusb: fix crash in hid_enumerate() caused by a stale device handle #526
No reviewers
Labels
No labels
3rdparty
Android
API
Author does not respond
bsd
bug
build system/CI
ci-virtual-device
CMake
Contributions Welcome
Core
dependencies
device-specific
documentation
don't_merge
duplicate
enhancement
Example
Haiku
hidraw
hotplug
info required
invalid
libusb
macOS
Misc
Not an issue
question
Release
Test
Test GUI
Windows
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-libusb/hidapi!526
Loading…
Reference in a new issue
No description provided.
Delete branch "fix-stale-device-handle"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When hid_enumerate() iterates over the device list, it's possible that libusb_open() fails. If this occurs on the next round after a successful libusb_open() call, create_device_info_for_device() is passed the previous iteration's already closed device handle.
Fix the crash by setting the handle to NULL after libusb_close().
FYI: I reworded the commit message slightly, hence the force-push.
This may or may not be useful, but here's a backtrace from gdb. To be honest I didn't find this nearly as helpful as sprinkling a few printfs in
hid_enumerate(), which is how I found this bug in the end.The logic is pretty obvious when reading through
hid_enumerate()and looking at what happens with thehandlevariable. The root cause is not cleaning up the value ofhandleafterlibusb_close(), and the more immediate cause is the fact thatlibusb_open()won't modify the destination variable on failure. These two combined lead to the situation where a stale handle may slip through the cracks.Now when I look at the fix, my though - how come no one had hit this one until now?
Thanks!
Human brains are to blame, they're always causing stuff like this. :)
I think it went unnoticed because it seems to only show up when
libusb_open()fails,libusb_open()succeeds on iteration N, then on iteration N+1 it fails. If you only get failures on every round the pointer staysNULLuntil the end, and if the last N rounds are a streak of successfullibusb_open()calls it also won't crash even if some of the first ones failed.