A race condition in the Linux kernel's macintosh input driver has been patched after security tooling discovered a double list insertion bug that can corrupt kernel lists and trigger instability when multiple processes write the same sysctl concurrently.
Background
The vulnerability, tracked as
CVE-2025-68367, lives in the macintosh/mac_hid driver β specifically the sysctl handler that toggles mouse-button emulation, historically exposed via the procfs entries under /proc/sys/dev/mac_hid. The mac_hid driver implements support for emulating additional mouse buttons on older Apple hardware and exposes a small set of sysctl knobs such as
mouse_button_emulation,
mouse_button2_keycode, and
mouse_button3_keycode. Those entries are handled by a custom proc handler named
mac_hid_toggle_emumouse inside drivers/macintosh/mac_hid.c.
The bug was discovered by kernel fuzzing (syzkaller) running against QEMU virtual hardware: two concurrent writers to the emulation sysctl can race. Both writers read the same old value from
valp, then both decide to register an input handler, causing the same handler structure to be added twice to a linked list. The kernel's list debugging detects this and raises a list_add "double add" warning; in the wild this can escalate to corrupted list state and unpredictable kernel behavior β a classic concurrency-induced list corruption.
This defect is not a logic error in the emulation itself but a synchronization gap: an important read (the prior value) was taken outside the critical section guarded by a mutex. The fix applied in the upstream tree moves the read into the mutex-protected region so the path that decides whether to register or unregister the handler observes a consistent state.
Overview of how the bug occurs
The actors: sysctl, mac_hid and input handlers
- The mac_hid driver registers a small sysctl subtree under /proc/sys/dev/mac_hid with entries including mouse_button_emulation.
- The sysctl uses a custom proc handler mac_hid_toggle_emumouse to start or stop emulation at runtime.
- When emulation is enabled, the driver registers an input handler via input_register_handler; when disabled it unregisters that handler.
- A mutex (mac_hid_emumouse_mutex in current sources) exists to protect the start/stop code paths β but the problematic read of the old_val was taken before that mutex was acquired.
The race and the double list_add
- Two processes, A and B, concurrently write to /proc/sys/dev/mac_hid/mouse_button_emulation.
- Both processes call the proc handler. They each read the old_val (which is the current value of the sysctl) before either holds the mutex.
- If the old_val indicates emulation is off, both threads decide they need to start emulation. They then both attempt to register the same input handler.
- The input handler registration adds the handler instance into a global list. Because of the race, the same handler structure gets added twice, producing inconsistent list pointers.
- The kernel's __list_add_valid_or_report code detects the inconsistency and prints the "list_add double add" message; this is a symptom of corrupted list internals and can lead to more serious memory corruption or crashes.
How syzkaller found it
- Syzkaller, the kernel fuzzer aimed at concurrency and syscall coverage, repeatedly exercises kernel paths and often triggers races by scheduling many concurrent syscalls.
- In fuzzing sessions against QEMU with the mac_hid driver enabled, syzkaller generated concurrent writes to the sysctl, producing the list_debug warning and revealing the race.
- The call trace printed in the kernel log pointed straight at mac_hid_toggle_emumouse -> mac_hid_start_emulation -> input_register_handler, revealing the double-add path.
Technical analysis: root cause and the fix
Root cause
The immediate mistake is a classic ordering issue: the code reads configuration state from shared memory (the sysctl variable) outside the protection of the mutex intended to serialize updates. That allows two concurrent writers to make decisions based on stale or identical state and then both perform an action that must be mutually exclusive (registering a singleton handler).
A correct synchronization discipline requires any read-modify-write decision that affects registration or unregistration of shared objects to be performed entirely inside a lock or by using atomic operations that also coordinate registration.
The remediation
The patch implemented in upstream kernel tree performs the simple but effective change: move the read of the old value (
old_val = valp*) inside the mutex-guarded region. That ensures the decision to register/unregister the input handler is based on a state snapshot that is consistent with subsequent modifications. With that ordering, only the first writer will perform registration and subsequent concurrent writers will see the updated value and skip duplicate registration.
This is a minimal, targeted change that eliminates the double-add path without rearchitecting the sysctl or registration mechanics. It follows the common best practice for sysctl handlers: perform read-modify-write sequences under the same lock.
Impact assessment
What can an attacker achieve?
- Local denial-of-service / instability: The most straightforward outcome is kernel warnings and potential instability. A corrupted list can later result in null pointer dereferences, oopses, or kernel panics β all of which equate to local denial of service or system instability.
- Privilege requirements: By design, writing to /proc/sys entries is restricted to privileged users. The procfs entries for mac_hid are created with typical sysctl file permissions. On a standard Linux system, that means only root (or a process with CAP_SYS_ADMIN/CAP_SYSCTL-equivalent privileges) can change those values. This strongly limits remote exploitation unless an attacker already has the ability to execute privileged operations.
- Possible container implications: In containerized environments where the container's root has privileges to write to certain /proc/sys entries visible inside the container, a malicious containerized process might be able to trigger the race. Whether that leads to host compromise depends on kernel and namespace configuration for sysctl and device driver visibility.
- Privilege escalation: There is no public evidence that this specific race has an exploit path that escalates privileges from unprivileged to root. The bug is a concurrency-induced list corruption that more commonly leads to crashes than deterministic arbitrary code execution. Exploiting kernel list corruption into a reliable privilege escalation is non-trivial and would depend on the exact memory layout and subsequent operations. At this time, the safe assessment is that this is primarily a stability/DoS risk rather than a proven privilege-elevation vulnerability.
Severity considerations
- The bug matters because kernel data-structure corruption is dangerous: list corruption often cascades to more serious faults.
- The exploitability is limited by the requirement to write the sysctl, meaning an attacker must have a local privileged context or be inside a privileged container.
- Systems that expose sysctl controls to untrusted code or have misconfigured permissions increase risk.
- Kernel fuzzers continue to be effective at surfacing such concurrency hazards; this is a reminder that even small sysctl handlers must be audited for locking discipline.
Mitigations and recommended actions for administrators
- Update kernels promptly:
- Apply vendor security updates that include the patch for CVE-2025-68367. Most major distributions will ship the fix in their stable kernel updates; prioritize installation on hosts exposed to untrusted local users or containers.
- Restrict write access to affected sysctl:
- Ensure that only trusted administrative users can write /proc/sys/dev/mac_hid/* entries. On most systems the sysctl entries are owned by root with mode 0644; maintain that.
- Review container runtimes and security profiles to prevent untrusted containers from modifying host-visible sysctl entries.
- Temporarily disable the mac_hid module if not required:
- If the mac_hid driver is not needed, unload it:
sudo modprobe -r mac_hid or blacklist it in kernel modules configuration to prevent it from loading.
- Confirm driver use before removal; removing mac_hid will disable the specific emulation feature for affected machines.
- As an emergency measure, disable emulation:
- As root, you can set the emulation sysctl to 0:
echo 0 | sudo tee /proc/sys/dev/mac_hid/mouse_button_emulation β this is a workaround to prevent start paths from running; it won't fix the underlying race but reduces the chance the problematic registration path runs.
- Audit privileged writable sysctls in shared environments:
- On multi-tenant or CI/Crypto-heavy environments, scan for sysctl entries writable by unprivileged or namespace-ambiguous contexts.
- Monitor kernel logs:
- Watch for list_debug warnings and the specific "list_add double add" pattern in dmesg; appearance of that message indicates unhandled list corruption and should trigger immediate investigation.
Developer takeaways: preventing similar races
- Ensure any read-modify-write sequence operating on state that affects registration/unregistration of shared kernel objects is performed under the correct lock.
- When registering global objects (input handlers, device entries, etc., aim for idempotency where registration of an already-registered object is gracefully handled, or ensure canonical ownership so repeated registration is impossible.
- Use kernel list helper functions with appropriate debug checks in development builds and run syzkaller or other fuzzers to stress concurrency paths. The syzkaller finding here demonstrates the value of automated concurrency fuzzing.
- Review sysctl handlers across drivers with the same pattern: if any handler reads a prior value to decide a register/unregister operation, check that the read is within the protected region.
- Consider moving complex manipulation logic out of sysctl handlers into explicit API functions, only exposing a minimal interface via sysctl to reduce error surface.
How to verify if your system is affected
- Check if the mac_hid module is present:
- Run
lsmod | grep mac_hid or modinfo mac_hid as root. If absent and never used, the risk is nil.
- Inspect procfs entries:
- Check for
/proc/sys/dev/mac_hid and the file mouse_button_emulation. On systems where mac_hid is compiled in or loaded as a module, these entries will exist.
- Review kernel logs for the warning signature:
dmesg | grep -E 'list_add double add|__list_add_valid_or_report' will surface the list debug warnings associated with double-add detection.
- Confirm kernel version and vendor advisories:
- Consult your distribution vendor's security advisory page or package tracker for updates that reference CVE-2025-68367 and install the recommended kernel update.
Wider context: why small sysctl handlers matter
This is a case study in how a small and innocuous interface (a single sysctl toggle for mouse emulation) can become the vector for kernel-level instability when concurrency is overlooked. Sysctl handlers are attractive hotspots for races because they provide user-controlled mutations of kernel state and are often written as compact convenience routines. The combination of a small handler and insufficient locking is a classic concurrency pitfall.
Security tooling β notably kernel fuzzers like syzkaller β continue to find precisely these kinds of bugs. The utility of such fuzzers is twofold: they reveal real race conditions under load, and they produce actionable call traces and reproducer manifests enabling maintainers to implement minimal, safe fixes like the one applied here.
Final assessment and recommended timeline
- Patch status: The upstream kernel repositories have accepted a targeted fix that moves the read of the prior value into the mutex-protected section. Distribution vendors and stable kernel trees are expected to backport this fix to supported kernels.
- Urgency: High for systems that allow untrusted privileged access or where containers can alter host sysctls; moderate for typical single-tenant desktop servers where sysctl writes are strictly administrative.
- Action plan (recommended):
- Immediately apply vendor kernel updates once available.
- In the interim, remove or blacklist mac_hid if not required, or set the emulation sysctl to 0.
- Harden container and multi-tenant environments against unexpected sysctl writes.
- Monitor kernel logs for the list_add warning pattern and follow up if observed.
Race conditions in kernel sysctl handlers are subtle because they often require specific timing to reproduce. This patch shows a pragmatic, low-risk fix: enforce the correct lock ordering and eliminate the window where two writers can make inconsistent decisions. Administrators should prioritize updates when available and use this incident to audit similar small handlers across other drivers β race bugs of this type are easy to miss but can have outsized operational impact when triggered.
Source: MSRC
Security Update Guide - Microsoft Security Response Center