HN
Today

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.

11
Score
0
Comments
#4
Highest Rank
4h
on Front Page
First Seen
Mar 5, 7:00 PM
Last Seen
Mar 5, 10:00 PM
Rank Over Time
9644

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.c and linux_udev.c, with udev being the strongly recommended choice to prevent race conditions during device setup.
  • A brief overview of netlink is 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_NETLINK socket with NETLINK_KOBJECT_UEVENT protocol and bind to specific multicast groups (MONITOR_GROUP_KERNEL or MONITOR_GROUP_UDEV) to receive events.
  • Kernel event messages are described as a series of null-terminated strings containing an action, a sysfs device path, and various key-value pairs (e.g., ACTION=add, DEVPATH, SUBSYSTEM).
  • udev rebroadcast events are also sent via netlink (using MONITOR_GROUP_UDEV), but include a proprietary binary header in addition to the null-terminated key-value strings.
  • The article dissects the udev packet format, detailing its magic number (0xfeedcafe), header size, property offsets, and big-endian filtering hashes: subsystem_hash (MurmurHash2 of SUBSYSTEM=), devtype_hash (MurmurHash2 of DEVTYPE=), and tag_bloom_hi/lo (a 64-bit Bloom filter of TAG= entries).
  • Security considerations highlight that udev messages are sent with process credentials (pid, uid, gid) and are validated by libudev to 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.