A new vulnerability tracked as CVE-2024-26934 was recently resolved in the Linux kernel’s USB system. This flaw concerns a potential deadlock in the usb_deauthorize_interface() function. While subtle, the issue could have serious effects on system stability, especially for servers and embedded devices relying on USB hot-plugging. In this post, we'll break down the bug, show relevant code, explain how the vulnerability could be triggered, and guide you to further references.

Background: What's Affected?

The vulnerability affects the Linux kernel USB subsystem, particularly the handling of sysfs attribute writes for USB interface deauthorization. The problematic code lives in drivers/usb/core/sysfs.c.

Device Locking:

When deauthorizing a USB interface through sysfs, the kernel code grabs a lock on the parent USB device.

Sysfs Attribute Callbacks:

If a process is removing the USB interface (because, for example, the device is unplugged or reconfigured), it waits for sysfs callbacks (like ours) to finish.

Classic Deadlock:

If one process holds the lock and is waiting for sysfs to finish, and another holds the sysfs callback and is waiting for the lock, they each end up waiting for each other: *deadlock*.

You could trigger this deadlock with two simultaneous actions

- User writes to /sys/bus/usb/devices/.../authorized to deauthorize (calls callback holding lock).
- At the same time, system removes the USB device (waits for callback to finish, but callback is waiting for lock held by the removal thread).

Vulnerable Code Snippet

static ssize_t interface_authorized_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
{
    ...
    usb_deauthorize_interface(usbif);
    ....
}

void usb_deauthorize_interface(struct usb_interface *usbif)
{
    struct usb_device *udev = interface_to_usbdev(usbif);

    /* THIS LOCK CAN CAUSE DEADLOCK! */
    usb_lock_device(udev);
    ...
    usb_unlock_device(udev);
}

Here, the callback function acquires a device lock *not* on the immediate object but on its parent. In a removal context, this rises to a classic lock inversion deadlock.

Patch Excerpt

static ssize_t interface_authorized_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
{
    sysfs_break_active_protection(attr);

    ...
    usb_deauthorize_interface(usbif);
    ....
}

See the full fix here:
- Linux kernel commit (torvalds/linux)
- LKML Patch Discussion

Local Denial of Service (DoS):

By exploiting this deadlock, a local user with write access to the authorized sysfs file could cause a hung process or system, potentially freezing user-space USB-related tasks.

Exploit Example (Concept)

# Terminal 1: Deauthorize the interface
echo  > /sys/bus/usb/devices/1-1:1./authorized

# Terminal 2 (simultaneously): Remove device (simulate unplug/re-plug)
echo  > /sys/bus/usb/devices/1-1/remove

# If unlucky, system could deadlock!

Note: Actual exploitation is tricky and requires good timing, but the potential for system freeze is real.

Linux Kernel Commit for CVE-2024-26934:

git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f8b979e41670071effc72dc6df3f68aefd810c2

Linux Kernel Mailing List Patch:

lore.kernel.org/all/20240208022954.3256751-1-gregkh@linuxfoundation.org/

Conclusion

CVE-2024-26934 highlights how delicate the kernel locking model is, especially in systems with complex device handling like USB hot-plug. The subtle nature of the bug could lead to hard-to-diagnose system freezes. If you run Linux with USB devices, especially in a multi-user or dynamic environment, *upgrade now* to stay safe!


*This writeup is exclusive and written for clarity, based on upstream Linux kernel code and mailing list references. For further technical details, consult the original patch links.*

Timeline

Published on: 05/01/2024 06:15:08 UTC
Last modified on: 08/02/2024 00:21:05 UTC