The Linux kernel's mac_hid driver, a small piece of code that emulates mouse buttons on vintage Apple hardware, harbored a subtle but dangerous race condition. When multiple processes simultaneously tweaked a system control setting, the kernel could corrupt its own internal lists and crash. The vulnerability, tracked as CVE-2025-68367, was discovered by the automated kernel fuzzer syzkaller and has already been patched upstream. Here's what every Linux user, administrator, and developer needs to know—and exactly what to do about it.
What Actually Happened
At the heart of the issue is a very specific scenario: two programs write to /proc/sys/dev/mac_hid/mouse_button_emulation at exactly the same time. This sysctl entry, managed by the mac_hid driver, toggles whether the kernel will emulate additional mouse buttons for old Apple input devices. When emulation is switched on, the driver registers an input handler with the kernel's input subsystem; when switched off, it unregisters that handler.
The problem: the code that decided whether to register or unregister the handler read the current emulation state before acquiring a mutex that was supposed to protect the entire operation. Two racing writers could both see that emulation was off, both conclude they needed to start it, and both then call input_register_handler() for the same handler object. Because the kernel's input handler list does not expect duplicate entries, this resulted in a "double add"—the same structure being inserted twice into a linked list, corrupting the list's pointers.
Kernel debugging machinery immediately detects such corruption and prints a list_add double add warning. In the best case, that's a noisy kernel log. In the worst case, the mangled list leads to null pointer dereferences, memory corruption, or outright kernel panics. The fix, committed to the upstream Linux source tree, is a one-liner: the read of the old value is moved inside the mutex-protected region, so the decision to (un)register is based on a consistent state.
How a Double-Add Corrupts the Kernel
To understand the practical danger, it helps to peer briefly under the hood. The Linux kernel maintains many doubly-linked lists for bookkeeping—here, the global list of registered input handlers. Each list node contains next and prev pointers. When you add a node to a list, the kernel updates four pointers: the new node's next and prev, and the next of the preceding node and prev of the following node. If the same node is added twice without an intervening removal, the list becomes circular or points to freed memory. Subsequent operations that traverse the list can then follow corrupted pointers into la-la land, causing wild memory accesses and unpredictable behavior.
The list_add helper has a debug check (__list_add_valid_or_report) that verifies the new node's pointers aren't already pointing at something, which is what triggers the warning. However, if that check is compiled out or if the corruption occurs in a non-debug kernel, the system may simply crash or silently corrupt memory, leading to much harder-to-diagnose failures.
Who Is Really at Risk?
Before panic sets in, let's be clear about the exposure. The mac_hid driver is a niche module: it's only relevant on systems with old Apple hardware that need mouse button emulation. Most modern Linux desktops, laptops, and servers won't have it loaded—you can check with lsmod | grep mac_hid. If the module isn't present, you are not vulnerable.
Even if the module is loaded, writing to the sysctl entry requires root privileges (or the CAP_SYS_ADMIN capability). This means an unprivileged attacker cannot casually trigger the race; they must already have elevated access. That turns this into a "local privilege is required" vulnerability, which dramatically lowers its severity for typical single-user systems.
However, risk climbs rapidly in shared or containerized environments. If a container's root has write access to host sysctl entries—a configuration that varies by container runtime and sysctl namespace policies—a malicious containerized process could exploit the race to crash the host kernel. For CI/CD pipelines, multi-tenant servers, or cloud instances where containers run with elevated privileges, this becomes a more pressing concern.
Also note: while there is no public proof-of-concept for privilege escalation, kernel list corruption has historically been exploitable under the right memory layout. Administrators should treat the bug as a stability and denial-of-service risk primarily, but not rule out the possibility of sophisticated local attacks.
If You Manage Servers or Containers, Read This
The greatest danger is to hosts running untrusted containers with any kind of sysctl write access, or systems where multiple administrative users compete for the same resource. Here the race is not theoretical: syzkaller triggered it by simply firing concurrent sysctl writes at a QEMU virtual machine. Any environment where automation scripts, orchestration tools, or malicious actors can bang on /proc/sys/dev/mac_hid/mouse_button_emulation in parallel could see a crash.
Production servers that never load the mac_hid module are not affected. For everything else, the urgency is moderate-to-high: apply the fix when your distribution releases it, and in the meantime, remove or disable the module.
The Root Cause: A Read Outside the Lock
The bug is a textbook concurrency mistake. The relevant function, mac_hid_toggle_emumouse in drivers/macintosh/mac_hid.c, contains a mutex (mac_hid_emumouse_mutex) that serializes start/stop operations. The sequence was:
- Read current value of
mouse_button_emulationfrom memory. - Acquire mutex.
- If the value changed to "on" and it was off, call
mac_hid_start_emulation(). - If it changed to "off" and it was on, call
mac_hid_stop_emulation(). - Update the stored value.
- Release mutex.
Two threads executing step 1 could both read 0 (off). Both acquire the mutex in turn, both see that they need to start emulation, and both call the start function—which calls input_register_handler—a classic TOCTOU (time-of-check to time-of-use) race.
The fix moves the read (step 1) inside the critical section (after step 2), so the first thread will set the value to 1 while holding the mutex, and the second thread will see that emulation is already on and skip registration. It's a minimal, safe change that follows long-standing kernel locking discipline.
Steps to Take Right Now
For every Linux user
- Open a terminal and run: lsmod | grep mac_hid. If nothing appears, breathe easy—the driver isn't active.
- If you do see mac_hid, note that the risk is real only if you have untrusted users sharing the machine.
For system administrators
- Apply vendor patches immediately. Major distributions will backport the fix to their supported stable kernels. Watch your distro's security advisory channels for a kernel update that references CVE-2025-68367. Apply them as part of your routine patching cycle—prioritize hosts that run containers or have multiple administrative accounts.
- Check if the module is loaded: lsmod | grep mac_hid. If it is, and you have no old Apple hardware in need of button emulation, remove it: sudo modprobe -r mac_hid. To prevent it from reloading on boot, blacklist it: add blacklist mac_hid to a file in /etc/modprobe.d/.
- As a temporary workaround (if you can't unload the module immediately), disable the emulation sysctl: echo 0 | sudo tee /proc/sys/dev/mac_hid/mouse_button_emulation. This won't fix the race, but it reduces the chance the vulnerable code path is entered.
- Review container and sysctl access. Audit your container runtimes: do any containers have writable /proc/sys/dev/mac_hid/ entries? Check sysctl namespace configurations and security policies (e.g., AppArmor, SELinux) to deny write access to this sysctl subtree for untrusted workloads.
- Monitor kernel logs. Watch for list_add double add warnings via dmesg -w or your log aggregation system. If you see this message, a kernel list corruption has already occurred; investigate immediately and schedule a reboot after patching.
For developers and kernel tinkerers
- If you maintain any kernel driver that uses sysctl handlers, audit your read-modify-write sequences. The rule is ironclad: any decision that leads to registration or unregistration of global objects must be made inside the lock that protects that registration.
- Consider using higher-level abstractions (e.g., device_register/device_unregister with proper reference counting) to make double-adds impossible by design. The input handler in this case was a singleton; making registration idempotent—where a second call is a no-op—would have neutered the race.
- Run syzkaller or a similar concurrency fuzzer against your driver. The fact that this bug was found by automated fuzzing is a testament to the value of such tooling. Integrate it into your CI pipeline if feasible.
A Developer’s Perspective on Preventing Races
The mac_hid race is a cautionary example for anyone writing kernel code, but its lesson applies broadly to systems programming. When shared state is modified based on a condition that can change between the check and the action, you need atomicity. The kernel offers many tools: mutexes, spinlocks, RCU, and atomic operations. Choosing the right one and placing it correctly is essential.
This bug also highlights a common blind spot: sysctl handlers often feel like quick, lightweight toggles, so developers may not imagine concurrent writes as a realistic threat. But with automation, container orchestration, and fuzzers all hitting these interfaces, concurrency is no longer an edge case. The fix is so simple that it's almost embarrassing—but that's often true of the most impactful security flaws.
What to Watch Next
The upstream patch is already merged, and distribution kernels will carry it shortly. For most users, the story ends with a regularly scheduled kernel update. However, this incident reinforces a trend: automated kernel fuzzing is surfacing more and more subtle concurrency bugs in even the most obscure drivers. The Linux community's swift response and the minimal nature of the fix are encouraging, but expect more CVEs of this ilk to appear.
Stay informed through your distribution's security announcements, schedule routine kernel updates, and keep an eye on your kernel logs for early warning signs. In the unlikely event that you still rely on mac_hid for vintage Apple peripherals, the patched driver will keep working exactly as before—just without the risk of a double-add crash.
The takeaway is clear: small drivers can have big bugs, and even a mouse setting can bring down a server. Patch early, audit often, and never assume a sysctl handler is too trivial to attack.