CVE-2026-99050 in Linux
Summary
by MITRE • 10/23/2026
In the Linux kernel, the following vulnerability has been resolved:
gpio: mpsse: fix race when arming the IRQ poll worker
gpio_mpsse_irq_enable() arms the poll worker before publishing it: schedule_work() runs before the worker is added to priv->workers. If gpio_mpsse_disconnect() walks the list in that window it misses the worker, and once disconnect returns, the USB core frees mpsse_priv while the orphaned gpio_mpsse_poll() work keeps accessing it, causing a use-after-free.
Fix this by publishing and arming the worker in one irq_spin critical section. Teardown walks the same list under irq_spin, so a worker found on the list is guaranteed to be armed, and cancel_work_sync() handles it whether it is queued or running.
A worker armed after the disconnect walk would still be missed, so also set a new priv->dying flag under irq_spin before the teardown walk, and check it in the same critical section, freeing it via kfree_rcu() instead when the device is going away, since kfree() would be called with the IRQ core's raw spinlock held and may sleep on PREEMPT_RT. schedule_work() is safe to call with irq_spin held, and the next probe gets a fresh mpsse_priv, so the flag never needs to be cleared.
This issue was found by an in-house static analysis tool.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 10/23/2026
The Linux kernel driver for Microchip MPSSE GPIO devices contains a critical race condition within its interrupt handling mechanism that leads to use-after-free vulnerabilities. This flaw arises from improper synchronization between the initialization of the IRQ poll worker and the device teardown process. Specifically, in the gpio_mpsse_irq_enable function, the system schedules the work item using schedule_work before adding it to the private data structure's list of active workers. This ordering creates a narrow but exploitable window where the driver can be disconnected while the work is pending execution but not yet registered as an active worker. During this interval, if gpio_mpsse_disconnect is invoked, it iterates through the priv->workers list to cancel any outstanding tasks. Because the new worker has not been added to this list yet, the disconnect routine fails to identify and stop it. Consequently, when the USB core subsequently frees the mpsse_priv memory structure upon device removal, the orphaned gpio_mpsse_poll work item remains queued in the kernel's workqueue subsystem. When the scheduler eventually executes this worker, it attempts to access the now-freed private data structure, resulting in a use-after-free condition that can lead to system crashes or potential privilege escalation depending on memory layout and exploitation techniques.
The root cause of this vulnerability is classified under CWE-362, which describes concurrent execution with shared resources without proper synchronization. The technical flaw lies in the lack of atomicity when transitioning from worker creation to registration. By separating the scheduling action from the list insertion, the driver violates the principle that a resource must be fully initialized and registered before it becomes accessible to other threads or interrupt contexts. This specific race condition is further exacerbated by the asynchronous nature of kernel workqueues, which allow tasks to execute independently of the thread that scheduled them. The absence of a critical section encompassing both actions allows the disconnect path to proceed with an incomplete view of active workers. From a threat modeling perspective, this aligns with ATT&CK techniques related to resource manipulation and potential exploitation of memory corruption vulnerabilities in kernel space, where attackers might leverage such races to gain unauthorized access or disrupt system stability by triggering null pointer dereferences or arbitrary code execution through corrupted heap metadata.
To resolve this issue, the fix implements a robust synchronization strategy that ensures atomicity during worker lifecycle management. The primary correction involves publishing and arming the worker within a single critical section protected by irq_spin lock. This guarantees that any thread walking the workers list under the same lock will either see the fully initialized worker or none at all, eliminating the window where an orphaned task could exist outside the tracked list. Furthermore, to handle cases where a work item might be scheduled after the disconnect walk has already begun, a new priv->dying flag is introduced. This flag is set under irq_spin protection prior to initiating the teardown sequence. The worker callback checks this flag within its own critical section context; if the device is in the process of dying, the worker avoids accessing freed memory and instead schedules itself for deferred freeing via kfree_rcu. This approach respects kernel constraints by avoiding sleeping while holding raw spinlocks on PREEMPT_RT configurations, as kfree_rcu allows safe deallocation without blocking. The design leverages Read-Copy-Update semantics to ensure that any ongoing accesses complete before the memory is reclaimed, thereby preventing data corruption and maintaining system integrity during device removal operations.