gpio: mpsse: fix race when arming the IRQ poll worker
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.
- Products
- Kernel
- Affected versions
- Not specified
- Fixed versions
- 6.18.57, 7.2.11
- CVEs
- CVE-2026-99050
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 5 Nov 2026, 00:02 UTC · Revision 1
Source evidence
gpio: mpsse: fix race when arming the IRQ poll worker
core-osv · Original sourcePublished 23 Oct 2026, 12:22 UTC
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.
osv:CVE-2026-99050
Kernel
Fixed versions: 6.18.57, 7.2.11
Complete source record
{
"id": "2902534e05416be7348303c6dd0130239cbbbe1d74364b3b41a1144ea1c08608",
"url": "https://osv.dev/vulnerability/CVE-2026-99050",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "gpio: mpsse: fix race when arming the IRQ poll worker",
"summary": "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.",
"evidence": "osv:CVE-2026-99050",
"products": [
{
"name": {
"value": "Kernel",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "6.18.57",
"evidence": "/affected/1/ranges"
},
{
"value": "7.2.11",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "CVE-2026-99050",
"aliases": [
"CVE-2026-99050"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
}
],
"affected": [
{
"ranges": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "472d900c8bcac301ae0e40fdca7db799bd989ff5"
},
{
"fixed": "76390ac0bca7e5058b7482eb4d951c3bda5df812"
}
]
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "179ef1127d7a4f09f0e741fa9f30b8a8e7886271"
},
{
"fixed": "c0071ee496e1228976c72b096f529503222708a0"
},
{
"fixed": "7efa1a1953cd6b20b23a3524d5b4b81789c6ef25"
}
]
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "6.18.6"
},
{
"fixed": "6.18.57"
}
]
}
],
"versions": [
"v6.18.56",
"v6.18.55",
"v6.18.54",
"v6.18.53",
"v6.18.52",
"v6.18.51",
"v6.18.50",
"v6.18.49",
"v6.18.48",
"v6.18.47",
"v6.18.46",
"v6.18.45",
"v6.18.44",
"v6.18.43",
"v6.18.42",
"v6.18.41",
"v6.18.40",
"v6.18.39",
"v6.18.38",
"v6.18.37",
"v6.18.36",
"v6.18.35",
"v6.18.34",
"v6.18.33",
"v6.18.32",
"v6.18.31",
"v6.18.30",
"v6.18.29",
"v6.18.28",
"v6.18.27",
"v6.18.26",
"v6.18.25",
"v6.18.24",
"v6.18.23",
"v6.18.22",
"v6.18.21",
"v6.18.20",
"v6.18.19",
"v6.18.18",
"v6.18.17",
"v6.18.16",
"v6.18.15",
"v6.18.14",
"v6.18.13",
"v6.18.12",
"v6.18.11",
"v6.18.10",
"v6.18.9",
"v6.18.8",
"v6.18.7",
"v6.18.6"
],
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-99050.json"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "0"
},
{
"fixed": "6.18.57"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.19.0"
},
{
"fixed": "7.2.11"
}
]
}
],
"package": {
"name": "Kernel",
"ecosystem": "Linux"
},
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-99050.json"
}
}
],
"modified": "2026-10-28T02:30:40.509520774Z",
"provider": "osv",
"references": [
"https://git.kernel.org/stable/c/76390ac0bca7e5058b7482eb4d951c3bda5df812",
"https://git.kernel.org/stable/c/7efa1a1953cd6b20b23a3524d5b4b81789c6ef25",
"https://git.kernel.org/stable/c/c0071ee496e1228976c72b096f529503222708a0",
"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/99xxx/CVE-2026-99050.json",
"https://nvd.nist.gov/vuln/detail/CVE-2026-99050",
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
],
"provider_metadata": {
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/99xxx/CVE-2026-99050.json"
}
},
"related_cves": [
{
"value": "CVE-2026-99050",
"evidence": "/id"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 508221,
"published_at": "2026-10-23T12:22:29.204+00:00"
}