Hardware hotplug events on Linux, the gory details
This article meticulously dissects the mechanisms behind detecting hardware hotplug events on Linux, venturing beyond standard libraries like libusb to explore the raw netlink and udev interfaces. It offers a detailed examination of kernel events, udev's rebroadcasting, and the specific binary packet formats and hashing algorithms involved. This deep dive appeals to Linux developers curious about system internals, providing practical C code examples and demystifying an often opaque but crucial aspect of device management.
The Lowdown
Driven by a curiosity to detect USB hotplug events on Linux without relying on libusb, the author embarks on a journey into the less-documented depths of udev and netlink. The investigation reveals how device events are handled at a low level, detailing the communication protocols and data structures involved in kernel-to-userspace and userspace-to-userspace event notification.
- The journey begins by examining
libusb's source code, revealing two primary hotplug backends:linux_netlink.candlinux_udev.c, withudevbeing the strongly recommended choice to prevent race conditions during device setup. - A brief overview of
netlinkis provided, explaining its role as a Linux-specific network protocol for kernel-to-userspace communication, akin to BSD sockets, suitable for kernel-initiated notifications and supporting multicast. - A comprehensive C code example is presented, demonstrating how to open an
AF_NETLINKsocket withNETLINK_KOBJECT_UEVENTprotocol and bind to specific multicast groups (MONITOR_GROUP_KERNELorMONITOR_GROUP_UDEV) to receive events. - Kernel event messages are described as a series of null-terminated strings containing an action, a
sysfsdevice path, and various key-value pairs (e.g.,ACTION=add,DEVPATH,SUBSYSTEM). udevrebroadcast events are also sent vianetlink(usingMONITOR_GROUP_UDEV), but include a proprietary binary header in addition to the null-terminated key-value strings.- The article dissects the
udevpacket format, detailing its magic number (0xfeedcafe), header size, property offsets, andbig-endianfiltering hashes:subsystem_hash(MurmurHash2 ofSUBSYSTEM=),devtype_hash(MurmurHash2 ofDEVTYPE=), andtag_bloom_hi/lo(a 64-bit Bloom filter ofTAG=entries). - Security considerations highlight that
udevmessages are sent with process credentials (pid,uid,gid) and are validated bylibudevto prevent spoofing, whereas kernel messages typically have zeroed credentials.
Ultimately, the article serves as a crucial resource for understanding the intricate, low-level mechanics of hardware hotplug events on Linux, offering practical C code and shedding light on the obscure binary formats and protocols that underpin device management.