CVE-2026-19595: Zephyr RTIO syscall verifier validates output parameters for read instead of write access

Published Oct 19, 2026
·
Updated

The user-mode syscall verifier zvrfyrtiocqegetmempoolbuffer() in subsys/rtio/rtiosyscalls.c validated its two output parameters, buff and bufflen, with KSYSCALLMEMORYREAD() rather than KSYSCALLMEMORYWRITE(). Both are pure out-parameters: zimplrtiocqegetmempoolbuffer() stores the mempool buffer address and its length through them. The distinction is enforced by every architecture validator — archbuffervalidate() on RISC-V PMP explicitly accepts the global romregion/rodataregion for reads only, and the ARM MPU validators accept PROURO and PRWURO regions for reads only — so a read-validated pointer is not necessarily writable by the calling thread.

An unprivileged user-mode thread that has been granted access to an RTIO context (rtioaccessgrant()) can invoke the rtiocqegetmempoolbuffer() syscall with buff/bufflen pointing at memory it may read but not write, and with a completion-queue entry whose flags field it fully controls (only RTIOCQEFLAGMEMPOOLBUFFER in flags[7:0] is required; flags[19:8] and flags[31:20] supply the block index and count). The kernel then performs a pointer-sized and a 4-byte store through those addresses while running in supervisor mode. Reaching the store requires CONFIGUSERSPACE together with CONFIGRTIOSYSMEMBLOCKS, the configuration behind RTIODEFINEWITHMEMPOOL; without the latter the implementation returns -ENOTSUP and writes nothing.

Two outcomes follow. If the target lies in a memory-domain partition declared KMEMPARTITIONPRWURO (privileged read-write, user read-only), the kernel-mode store succeeds and deposits partly attacker-chosen values into memory the memory domain had marked read-only for that thread, bypassing the partition's write protection. If the target lies in globally readable but unwritable memory such as .text/.rodata in flash, the store faults in kernel mode; the fault is delivered to zfatalerror() and the default ksysfatalerrorhandler() halts or reboots the device, giving an unprivileged thread a reliable full denial of service.

The read-permission check does bound the damage: the address must still be readable by the calling thread, so kernel-private memory cannot be targeted and no confidential data is disclosed. The fix replaces both checks with KSYSCALLMEMORYWRITE(), so a thread lacking write permission is terminated by KOOPS before the implementation runs; the cqe argument correctly remains read-validated.

Affected Software

1 affected component
Zephyr Project Zephyr

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Disable CONFIG_RTIO_SYS_MEM_BLOCKS when RTIO mempool support is not required; without it, rtio_cqe_get_mempool_buffer() returns -ENOTSUP and writes nothing.

    Zephyr RTIO CONFIG_RTIO_SYS_MEM_BLOCKS = disabled
  2. Compensating control

    In z_vrfy_rtio_cqe_get_mempool_buffer(), validate both output parameters, buff and buff_len, with K_SYSCALL_MEMORY_WRITE() instead of K_SYSCALL_MEMORY_READ(); retain read validation for the cqe argument.

Event History

Oct 19, 2026
CVE Published
via MITRE·10:49 PM
Data Sourced
via MITRE·10:49 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·11:17 PM
DescriptionSeverityWeakness

Frequently Asked Questions

1

Which deployments are exposed?

Exposure requires user-mode threads and an RTIO context that has been granted to an unprivileged thread with rtio_access_grant(). The issue is relevant where such a thread can invoke rtio_cqe_get_mempool_buffer() and supply pointers to memory it can read but is not permitted to write.

2

What does an attacker need to control to trigger the unsafe writes?

The attacker needs access to an RTIO completion-queue entry whose flags field they fully control. RTIO_CQE_FLAG_MEMPOOL_BUFFER must be set in flags[7:0], while flags[19:8] provide the block index and flags[31:20] provide the block count.

3

What writes occur if exploitation succeeds?

The kernel stores a mempool buffer address through buff and its length through buff_len. These are a pointer-sized store and a 4-byte store, respectively, to addresses that passed read validation but may be read-only for the calling thread.

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