CVE-2026-19575
Executive Summary
CVE-2026-19575 is a type-confusion vulnerability (CWE-843) in the Zephyr RTOS user-mode syscall verification layer. The handler z_vrfy_device_deinit() in kernel/device.c validated its dev argument using K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY), which causes k_object_validate() to skip the object-type comparison entirely, allowing any kernel object the calling thread has permission on to be accepted. An unprivileged local user-mode thread can pass a writable thread-stack object, causing z_impl_device_deinit() to treat attacker-controlled bytes as a struct device, yielding an indirect call to an arbitrary address in supervisor mode with high confidentiality, integrity, and availability impact (CVSS 7.8).
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
Zephyr implements a user/kernel separation model (CONFIG_USERSPACE) in which system calls made from user mode are routed through verification handlers prefixed z_vrfy_. These handlers are responsible for validating that the arguments supplied by an untrusted user-mode thread refer to kernel objects of the expected type and to which the calling thread has been granted access, before the corresponding z_impl_ implementation executes in supervisor mode.
In this CVE, the user-mode verification handler for the device_deinit() system call, z_vrfy_device_deinit() in kernel/device.c, validated its dev argument with K_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY). The critical flaw is the use of the wildcard sentinel K_OBJ_ANY for the expected object type. Internally, k_object_validate() short-circuits its type comparison when the requested type is K_OBJ_ANY. Consequently, the validation degraded to a check that the pointer is merely the base address of some kernel object to which the calling thread has been granted permission. The object's actual type was never compared against the expected driver object type. Compounding the problem, K_SYSCALL_OBJ_INIT also skips the initialization-state check that would otherwise ensure the object is in a valid state for the operation.
The vulnerability class is a classic type confusion at a trust boundary: the kernel verification layer accepted a handle of one object class where a different object class was contractually required. Because the check reduced to "is this any granted kernel object," an attacker's user-mode thread can supply a handle to an object whose backing memory is writable from user mode. As the description notes, the most useful such object is a thread stack object — obtained via the k_thread_stack_alloc() syscall or a statically defined K_THREAD_STACK granted to the thread in order to spawn a child user thread. Thread stacks are, by design, writable by the user-mode thread that owns them.
Once the crafted object pointer passes verification, z_impl_device_deinit() executes in supervisor mode and interprets the attacker-written bytes as a struct device. It dereferences the state pointer read out of the object, calls the function pointer read out of ops.deinit, and, on success, writes through state again. This produces three primitives controlled by the attacker: an indirect call to an arbitrary address executed at supervisor privilege, an arbitrary kernel read (through the state pointer dereference), and a constrained single-byte kernel write (the success-path write through state).
It is significant that the sibling handlers z_vrfy_device_init() and z_vrfy_device_is_ready() already used K_OBJ_DRIVER_ANY and were therefore unaffected. This demonstrates that the correct expected-type argument was known and used elsewhere in the same file — the defect is an isolated misuse of K_OBJ_ANY in z_vrfy_device_deinit() rather than a systemic design failure. The attack surface is precisely the device-deinitialization syscall path and is reachable only by a local thread executing in user mode on a build configured with CONFIG_USERSPACE.
Exploitation Scenarios
No public PoC or exploit code is available for CVE-2026-19575 (POC_STATUS: None; no Nuclei template, no public exploit). The following chain is derived strictly from the NVD description and the behavior of the affected code path; it is described at the vulnerability-class level and does not fabricate additional function names or structures beyond those explicitly named.
Reconnaissance / target identification. The attacker requires local code execution as an unprivileged thread running in user mode on a Zephyr build with
CONFIG_USERSPACEenabled. The presence of the user-mode syscall layer and thedevice_deinit()syscall surface is the pre-condition; no remote reconnaissance is involved. The attacker identifies thatdevice_deinit()is callable from user mode and that thread-stack objects writable from user mode are available to the thread (viak_thread_stack_alloc()or a granted staticK_THREAD_STACK).Triggering the specific flaw class. The attacker crafts a region of memory whose contents are laid out to be interpreted as a
struct device. Because the offending handler validated withK_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY), the type confusion permits the attacker to pass a handle to a writable thread-stack object rather than a genuine driver object. Thek_object_validate()short-circuit onK_OBJ_ANYmeans the object-type comparison never occurs, and the initialization-state check is likewise skipped, so the malicious handle is accepted.Payload / execution method at the vulnerability-class level.
z_impl_device_deinit()then treats the attacker-controlled bytes as astruct device. It reads thestatepointer out of the object and dereferences it (the arbitrary kernel read), invokes the function pointer read fromops.deinit(the indirect call executed in supervisor mode), and on the success path writes once throughstate(a single-byte kernel write). By choosing the bytes placed in the writable thread-stack object, the attacker directs theops.deinitfunction-pointer call to an address of their choosing, achieving kernel code execution.Post-exploitation impact. Exploitation gives a local unprivileged thread full kernel code execution, defeating the
CONFIG_USERSPACEisolation boundary entirely. As the description notes, a less precise attempt (for example, a mis-pointed function pointer orstatevalue) yields a crash or limited effect rather than reliable control — but a precisely constructed object yields supervisor-mode code execution plus arbitrary read and a constrained kernel write, sufficient in principle to fully compromise the device.
Impact Assessment
The CVSS 3.1 base score is 7.8 (High) with vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H. The attack vector is Local (AV:L): the attacker must already run code on the device. Complexity is Low (AC:L) because the flaw is a deterministic validation short-circuit reachable through a normal syscall, and the required privileges are Low (PR:L) — an unprivileged user-mode thread is sufficient. No user interaction is required (UI:N). Scope is Unchanged (S:U), yet confidentiality, integrity, and availability impacts are all High (C:H/I:H/A:H), reflecting supervisor-mode code execution, arbitrary kernel read, and the ability to corrupt kernel state.
Business impact is severe for any product built on Zephyr with CONFIG_USERSPACE in which an unprivileged local thread can invoke device_deinit() — for example, multi-tenant on-device workloads, sandboxed application partitions, or devices that expose a user-mode extension/runtime. The isolation boundary that Zephyr's user-mode model is designed to enforce is fully defeated, meaning a compromised or malicious application can pivot to full kernel compromise of the device. Because the primitive includes arbitrary kernel read and an indirect supervisor call, the blast radius extends to the whole platform: secrets, cryptographic material, and any other partition's data may be read; kernel integrity and device availability may be lost. CISA KEV status is NO, there is no known in-the-wild exploitation evidence, and EPSS has not yet scored the CVE, so near-term observed exploitation risk is assessed as latent but high-consequence. There is no published fix (Patch Confidence 0/4) and no vendor workaround, which raises residual risk for deployments that cannot disable the affected syscall.
Detection Guidance
Sigma Rule
title: Zephyr device_deinit Type Confusion Exploitation Attempt
id: 8f2c1a44-9b7e-4d2a-9e11-7c3d5f0a2b61
status: experimental
description: Detects anomalous user-mode invocation of device_deinit syscalls or kernel faults consistent with CVE-2026-19575 type-confusion abuse in Zephyr RTOS.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-19575
author: valtersit.com
date: 2026-01-01
logsource:
product: zephyr
service: kernel
detection:
selection_syscall:
event.action: 'syscall'
event.code|contains: 'device_deinit'
selection_source:
thread.mode: 'user'
selection_fault:
event.type: 'fault'
fault.reason|contains:
- 'invalid object'
- 'no permission'
- 'unsupported'
condition: selection_syscall and selection_source or selection_fault
fields:
- thread.name
- object.type
- device.handle
falsepositives:
- Legitimate drivers deinitializing devices from user-mode granted threads
level: high
tags:
- attack.privilege_escalation
- attack.t1068
- cve.2026-19575
YARA Rule
rule CVE_2026_19575_Zephyr_Device_Deinit_Type_Confusion
{
meta:
description = "Detects artifacts referencing the vulnerable Zephyr device_deinit user-mode verifier and related symbols (CVE-2026-19575)"
author = "valtersit.com"
date = "2026-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-19575"
severity = "high"
strings:
$s1 = "z_vrfy_device_deinit" ascii wide
$s2 = "z_impl_device_deinit" ascii wide
$s3 = "K_SYSCALL_OBJ_INIT" ascii
$s4 = "K_OBJ_ANY" ascii
$s5 = "k_thread_stack_alloc" ascii wide
$s6 = "k_object_validate" ascii wide
condition:
uint32(0) == 0x464C457F or
(2 of ($s1, $s2, $s3, $s4, $s5, $s6))
}
Suricata IDS Rule
alert tcp any any -> any any (msg:"CVE-2026-19575 Zephyr RTOS device_deinit type-confusion indicator in transit"; flow:to_server,established; content:"z_vrfy_device_deinit"; nocase; sid:2026197501; rev:1; reference:cve,2026-19575; reference:url,nvd.nist.gov/vuln/detail/CVE-2026-19575; classtype:attempted-admin; metadata:created_at 2026_01_01, updated_at 2026_01_01;)
alert tcp any any -> any any (msg:"CVE-2026-19575 Zephyr device_deinit symbol reference (k_thread_stack_alloc)"; flow:to_server,established; content:"device_deinit"; nocase; content:"k_thread_stack_alloc"; nocase; distance:0; sid:2026197502; rev:1; reference:cve,2026-19575; classtype:attempted-admin;)
Note: this vulnerability is a local privilege-escalation flaw with no network protocol component; the Suricata rules above only match the named symbols if they appear in monitored traffic (e.g., firmware/OTA image transfer or debug channels) and should be treated as low-fidelity.
Elastic Detection
sequence by process.entity_id
[process where event.action == "syscall" and process.thread.mode == "user"
and process.args : "device_deinit"]
[file where event.action == "fault" and
(file.fault.reason : "invalid object" or file.fault.reason : "no permission")]
Splunk SPL Query
index=zephyr OR index=edge
(sourcetype=zephyr:kernel OR sourcetype=zephyr:syscall)
| search ("device_deinit" OR "z_vrfy_device_deinit" OR "K_SYSCALL_OBJ_INIT" OR "K_OBJ_ANY" OR "k_thread_stack_alloc")
| stats count min(_time) as first_seen max(_time) as last_seen
values(thread.mode) as thread_modes
values(object.type) as object_types
values(fault.reason) as fault_reasons
by host thread.name device.handle
| where thread_modes="user"
| eval risk="high"
| convert ctime(first_seen) ctime(last_seen)
| sort - count
Wazuh OSSEC Rule
<group name="zephyr,cve-2026-19575,">
<rule id="20261975" level="12">
<decoded_as>json</decoded_as>
<field name="event.action">device_deinit</field>
<field name="thread.mode">user</field>
<description>CVE-2026-19575: user-mode thread invoked device_deinit syscall (possible type-confusion privilege escalation)</description>
<mitre>
<id>T1068</id>
</mitre>
</rule>
<rule id="20261976" level="13">
<decoded_as>json</decoded_as>
<field name="fault.reason" type="pcre2">invalid object|no permission|unsupported</field>
<description>CVE-2026-19575: kernel fault consistent with device_deinit type-confusion exploitation</description>
<mitre>
<id>T1068</id>
</mitre>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
- Immediate mitigations.
- Disable or de-scope the exposure: if the affected
device_deinit()syscall is not required by any user-mode application on the device, restrict which threads are granted permission on device objects so that no unprivileged user-mode thread can reach the vulnerable verification path. Zephyr enforces object permission via kernel object grants; removing or minimizing grants on device objects to untrusted threads directly blocks the pre-condition described in this CVE. - Minimize user-mode attack surface: for products that do not require Zephyr user-mode isolation, building without
CONFIG_USERSPACEremoves thez_vrfy_*verification paths entirely, eliminating this attack surface (at the cost of losing the isolation model). - Audit object grants to untrusted threads, in particular any thread that holds writable thread-stack objects (
k_thread_stack_alloc()or granted staticK_THREAD_STACK) and also has device-object permissions, since the description identifies exactly this combination as the exploitation enabler. - Monitor for the detection signals in the previous section (unexpected user-mode
device_deinitinvocations and fault reasons such as invalid object / no permission).
- Patch / upgrade steps.
- No vendor patch or fixed version is currently identified by any tracked source (Patch Sources empty; Vendor Fix N/A). Track the upstream Zephyr project for a fix. The correction is expected to be a one-line change in
z_vrfy_device_deinit()replacingK_SYSCALL_OBJ_INIT(dev, K_OBJ_ANY)with the appropriate expected device/driver object type check matching the sibling handlersz_vrfy_device_init()andz_vrfy_device_is_ready(), which already useK_OBJ_DRIVER_ANY. Because no patch is available, verify any candidate fix by confirming the expected-type argument is no longerK_OBJ_ANYand that the initialization-state check is enforced. - Until an official fix is available, apply the mitigation in step 1 rather than relying on an unverified change.
- Long-term hardening.
- Enforce a policy that wildcard object-type sentinels (
K_OBJ_ANY) are never used inz_vrfy_*verification handlers; each syscall verifier should assert a concrete expected object type. Add static analysis or CI checks to detectK_SYSCALL_OBJ_*invocations usingK_OBJ_ANY. - Adopt least-privilege object-grant design for user-mode threads, so any single verification defect does not immediately yield supervisor-mode control.
- Reuse the correct handler pattern already present in the same file for all device-related syscalls, and add tests exercising cross-type object handles against every user-mode syscall verifier.
References
- NVD — CVE-2026-19575: https://nvd.nist.gov/vuln/detail/CVE-2026-19575
- MITRE CWE-843 (Type Confusion): https://cwe.mitre.org/data/definitions/843.html
- Zephyr Project documentation — User Mode / kernel object (k_object_validate) and system call verification model: https://docs.zephyrproject.org/
- Zephyr Project source — kernel/device.c (
z_vrfy_device_deinit,z_impl_device_deinit): https://github.com/zephyrproject-rtos/zephyr - MITRE ATT&CK T1068 — Exploitation for Privilege Escalation: https://attack.mitre.org/techniques/T1068/
No threat actor campaigns or exploit-in-the-wild evidence are associated with CVE-2026-19575 at this time (CISA KEV: NO; no public PoC; EPSS not yet scored).
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.