Time-of-check/time-of-use double fetch in the Zephyr i3c_transfer() syscall handler allows kernel-mode control-flow hijack from user mode
Affects Zephyr builds with CONFIG_USERSPACE and an I3C controller driver, from 3.2.0 before 4.3.2 and from 4.4.0 before 4.5.0. Fixed in 4.3.2 and 4.5.0.
Written by anthropic/claude-haiku-5.5 from the sources below. Verify against them.
- Exploited
- No known exploitation
- Fix
- Fixed in 4.3.2, 4.5.0
- Who is exposed
- Specific setups only
Do first: Check whether your setup matches what the bug needs. Build has CONFIG_USERSPACE and an I3C controller driver Affected versions are >= 3.2.0 and < 4.3.2, and >= 4.4.0 and < 4.5.0
- Exploitation?/40Exploitation: unknown (data gap). No CISA SSVC exploitation rating yet
- Exposure5/25Specific setups only
- Reach?/20Reach: unknown (data gap). No tracked technology or package matched
- Severity7/10CVSS 7.0
- No patch0/5No signal
What would change the score
- Would score about 62 if added to CISA KEV
- Would score about 57 if CISA's SSVC rates exploitation active
- Would score about 22 if CISA's SSVC rates it automatable
CVE-2026-87038 is not in CISA's Known Exploited Vulnerabilities (KEV) catalog. No public exploit code is tracked. It is rated CVSS 7.0 (high) and affects zephyr; fixed in 4.3.2 and 4.5.0.
- Last modified
- Where the record stands: published, rejected by its publisher, or superseded by another id.What do these mean? →
- Published
- Whether CISA lists it in its Known Exploited Vulnerabilities catalog: proof that attackers are using it.What do these mean? →
- Not listed in CISA KEV
- FIRST's estimate of the chance attackers exploit it in the next 30 days, updated daily.What do these mean? →
- 0.09% · 0th percentile
- A 0-100 score for how much a CVE matters across the industry: exploitation, exposure, how widely the software is used, severity and whether a fix exists.What do these mean? →
- 12/100 · provisional
- How many real-world setups can hit the bug, from the vendor's advisory and CISA data. It does not know your setup.What do these mean? →
- Specific setups only
- Fix
- Fixed in 4.3.2, 4.5.0
- Whether working attack code is public (Exploit-DB, Metasploit, Nuclei or GitHub). Public code makes attacks easier.What do these mean? →
- None on Exploit-DB, Metasploit or GitHub
Summary
The user-mode verification handler for the i3c_transfer() system call, z_vrfy_i3c_transfer() in drivers/i3c/i3c_handlers.c, validated the caller-supplied struct i3c_device_desc in place instead of snapshotting it. It confirmed only that the descriptor was readable by the calling thread (K_SYSCALL_MEMORY_READ()), read target->bus once to check it with K_SYSCALL_OBJ(), and then passed the caller's live pointer down. The implementation z_impl_i3c_transfer() re-reads target->bus from that user memory and dispatches through it as DEVICE_API_GET(i3c, target->bus)->i3c_xfers(...), so the bus that was validated is not necessarily the bus that is used. DEVICE_API_GET() performs no runtime type check outside CONFIG_DEVICE_API_ASSERT builds. On a build with CONFIG_USERSPACE and an I3C controller driver, a user thread that has been granted an I3C device object can exploit this with a second thread in the same memory domain: one thread calls i3c_transfer() while the other rewrites the bus field of the descriptor. The window between the check and the use spans the num_msgs validation, the message-array access check, a stack VLA allocation and a memcpy() of up to 32 struct i3c_msg, so the race is repeatable and can simply be retried until it lands. When the substitution succeeds, the kernel dereferences an attacker-chosen pointer as a struct device, loads a function pointer from the attacker-controlled api table and calls it in supervisor mode with attacker-influenced arguments. This yields kernel-mode code execution from an unprivileged user thread — a complete escape of the userspace memory-protection sandbox; lesser outcomes are an arbitrary two-level kernel read or a kernel fault. Builds without CONFIG_USERSPACE, or without an I3C driver, are unaffected. The fix copies the descriptor into a kernel-stack local with k_usermode_from_copy(), validates the bus in that copy, and dispatches on the copy, so the validated value is provably the value used.
What to do
Check whether your setup matches what the bug needs.
Build has CONFIG_USERSPACE and an I3C controller driver Affected versions are >= 3.2.0 and < 4.3.2, and >= 4.4.0 and < 4.5.0Upgrade to a fixed version: 4.3.2, 4.5.0.
Timeline
- CVE published
- First seen by cve.now
Affected versions
- zephyr
From 3.2.0 · fixed in 4.3.2; From 4.4.0 · fixed in 4.5.0
Evidence 2
- Advisory
- Patch
Corrections
None so far.
Something wrong on this page? Report an error. Every fix is listed here.
Questions about CVE-2026-87038
Is CVE-2026-87038 being exploited?
It is not in CISA's Known Exploited Vulnerabilities catalog, and CISA's SSVC assessment does not mark exploitation as active. That does not mean it has not been attacked: vendors and researchers can report attacks before CISA lists them. No public exploit code is tracked.Source: cve.now feed data
What does this mean?
The i3c_transfer() syscall handler reads a value supplied from user mode twice, once to check it and once to use it. A user thread can change the value between those two reads, so the check no longer holds. The advisory says this can lead to kernel-mode code execution from an unprivileged user thread, escaping the userspace memory-protection sandbox. Lesser outcomes it lists are an arbitrary two-level kernel read or a kernel fault.Source: github.com
Which versions are affected by CVE-2026-87038?
zephyr: from 3.2.0 before 4.3.2; from 4.4.0 before 4.5.0.Source: cve.now feed data
Am I affected, and how do I check?
Zephyr versions from 3.2.0 before 4.3.2, and from 4.4.0 before 4.5.0. The bug needs a build with CONFIG_USERSPACE enabled and an I3C controller driver. To check a build, look at the Zephyr version it was built from and at whether CONFIG_USERSPACE and an I3C controller driver are set in its configuration.Source: github.com
How do I fix CVE-2026-87038?
Upgrade to Zephyr 4.3.2 if you are on the 4.3 line, or to 4.5.0 if you are on the 4.4 line. The facts give no workaround, so the fixed releases are the only stated remedy.Source: github.com