CVE-2026-87038: Time-of-check/time-of-use double fetch in the Zephyr i3c_transfer() syscall handler allows kernel-mode control-flow hijack from user mode

Published Nov 4, 2026
·
Updated

The user-mode verification handler for the i3ctransfer() system call, zvrfyi3ctransfer() in drivers/i3c/i3chandlers.c, validated the caller-supplied struct i3cdevicedesc in place instead of snapshotting it. It confirmed only that the descriptor was readable by the calling thread (KSYSCALLMEMORYREAD()), read target->bus once to check it with KSYSCALLOBJ(), and then passed the caller's live pointer down. The implementation zimpli3ctransfer() re-reads target->bus from that user memory and dispatches through it as DEVICEAPIGET(i3c, target->bus)->i3cxfers(...), so the bus that was validated is not necessarily the bus that is used. DEVICEAPIGET() performs no runtime type check outside CONFIGDEVICEAPIASSERT builds.

On a build with CONFIGUSERSPACE 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 i3ctransfer() while the other rewrites the bus field of the descriptor. The window between the check and the use spans the nummsgs validation, the message-array access check, a stack VLA allocation and a memcpy() of up to 32 struct i3cmsg, 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 CONFIGUSERSPACE, or without an I3C driver, are unaffected.

The fix copies the descriptor into a kernel-stack local with kusermodefromcopy(), validates the bus in that copy, and dispatches on the copy, so the validated value is provably the value used.

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Disable CONFIG_USERSPACE; builds without CONFIG_USERSPACE are unaffected by this issue.

    Zephyr userspace CONFIG_USERSPACE = disabled

Event History

Nov 4, 2026
CVE Published
via MITRE·06:09 AM
Data Sourced
via MITRE·06:09 AM
DescriptionSeverityWeakness
Data Sourced
via NVD·06:17 AM
DescriptionSeverityWeakness

Frequently Asked Questions

1

Which systems are potentially exposed?

Exposure requires a build with CONFIG_USERSPACE enabled and an I3C controller driver. A user thread must also have been granted access to an I3C device object.

2

What does an attacker need to exploit this?

The attacker needs local user-mode execution and a second thread in the same memory domain. One thread invokes i3c_transfer() while the other modifies the caller-supplied descriptor's bus field during the validation-to-use window.

3

How can I identify relevant access paths in my application?

Review builds for CONFIG_USERSPACE and I3C controller support, then identify user threads granted I3C device objects. Calls to i3c_transfer() using descriptors writable by another thread in the same memory domain are the relevant race condition.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203