Description
The Zephyr kernel validates the k_thread_join() and k_thread_abort() system calls (declared __syscall in include/zephyr/kernel.h) through thread_obj_validate() in kernel/thread.c. Its default switch branch is the access-denied path, taken when k_object_validate() returns -EPERM (the calling user thread was never granted access to the target thread object) or -EBADF (the supplied pointer is not a registered kernel object of the right type). That branch invoked K_OOPS(K_SYSCALL_VERIFY_MSG(ret, "access denied")), but K_SYSCALL_VERIFY_MSG treats a true expression as success; the non-zero error code ret therefore read as "verified OK", the kernel oops was never raised, and control fell through to CODE_UNREACHABLE.

Because k_thread_join() and k_thread_abort() are system calls, an unprivileged user-mode thread (under CONFIG_USERSPACE) can reach this denial path directly by calling either syscall on a thread object it does not own. Instead of the offending thread being cleanly terminated, execution reaches __builtin_unreachable() while running in supervisor mode inside the syscall handler.

On Clang builds CODE_UNREACHABLE emits an illegal-instruction trap, so a user thread can deterministically crash the kernel — a locally triggerable denial of service that escapes the userspace sandbox. On GCC builds the path is undefined behavior: the compiler may drop the return-value handling for thread_obj_validate(), so it can return an undefined bool; if that is false, the caller proceeds into the real k_thread_join()/k_thread_abort() implementation for a thread the user was never authorized to access, an access-control bypass.

The fix changes the verification expression to ret == 0, so a denied (non-zero) result now correctly raises K_OOPS and terminates the offending caller.
Published: 2026-08-18
Score: 6.5 Medium
EPSS: < 1% Very Low
KEV: No
Impact: n/a
Action: n/a
AI Analysis

Impact

A flaw in the Zephyr kernel’s validation of the k_thread_join() and k_thread_abort() system calls causes a returned error code to be misinterpreted as success, allowing the kernel to continue execution along an unintended path. An unprivileged user‑mode thread can invoke these syscalls on a thread object it does not own, leading either to an illegal‑instruction fault on Clang builds or to undefined behavior that may permit the caller to act on another thread’s internals. The effect is a locally triggerable denial of service that bypasses the userspace sandbox and can crash the kernel or expose sensitive functionality.

Affected Systems

The vulnerability affects the Zephyr real‑time operating system as provided by the Zephyr Project. No specific version range is listed in the CNA data, so any release upstream of the commit that introduces this issue and lacking the fix remains vulnerable.

Risk and Exploitability

With a CVSS score of 6.5 the issue is considered moderate in severity. The EPSS score of 0.00148 indicates a very low exploitation probability, and the vulnerability is not listed in the CISA KEV catalog. The attack requires local access by an unprivileged user thread under CONFIG_USERSPACE, making it a local denial of service and privilege‑bypass vector. Exploitation is deterministic on Clang (illegal instruction trap) and unpredictable on GCC due to undefined behavior, but either outcome results in loss of system availability.

Generated by OpenCVE AI on August 21, 2026 at 17:11 UTC.

Remediation

No vendor fix or workaround currently provided.

OpenCVE Recommended Actions

  • Update the Zephyr kernel to a release that includes the patch from commit bd1828652dfc217ba9f3a2221a7499cd8914ed9c, or apply the commit changes directly to the kernel/thread.c source to correct the verification expression.
  • If the system can tolerate it, disable CONFIG_USERSPACE to remove the ability of user‑mode threads to invoke the affected syscalls, thereby preventing the denial of service path.
  • Configure monitoring and logging to detect and alert on unexpected kernel aborts or panics that may be triggered by user threads, aiding rapid response to any attempted exploitation.

Generated by OpenCVE AI on August 21, 2026 at 17:11 UTC.

Tracking

Sign in to view the affected projects.

Advisories

No advisories yet.

History

Tue, 18 Aug 2026 23:15:00 +0000

Type Values Removed Values Added
First Time appeared Zephyrproject
Zephyrproject zephyr
Vendors & Products Zephyrproject
Zephyrproject zephyr

Tue, 18 Aug 2026 21:15:00 +0000

Type Values Removed Values Added
Description The Zephyr kernel validates the k_thread_join() and k_thread_abort() system calls (declared __syscall in include/zephyr/kernel.h) through thread_obj_validate() in kernel/thread.c. Its default switch branch is the access-denied path, taken when k_object_validate() returns -EPERM (the calling user thread was never granted access to the target thread object) or -EBADF (the supplied pointer is not a registered kernel object of the right type). That branch invoked K_OOPS(K_SYSCALL_VERIFY_MSG(ret, "access denied")), but K_SYSCALL_VERIFY_MSG treats a true expression as success; the non-zero error code ret therefore read as "verified OK", the kernel oops was never raised, and control fell through to CODE_UNREACHABLE. Because k_thread_join() and k_thread_abort() are system calls, an unprivileged user-mode thread (under CONFIG_USERSPACE) can reach this denial path directly by calling either syscall on a thread object it does not own. Instead of the offending thread being cleanly terminated, execution reaches __builtin_unreachable() while running in supervisor mode inside the syscall handler. On Clang builds CODE_UNREACHABLE emits an illegal-instruction trap, so a user thread can deterministically crash the kernel — a locally triggerable denial of service that escapes the userspace sandbox. On GCC builds the path is undefined behavior: the compiler may drop the return-value handling for thread_obj_validate(), so it can return an undefined bool; if that is false, the caller proceeds into the real k_thread_join()/k_thread_abort() implementation for a thread the user was never authorized to access, an access-control bypass. The fix changes the verification expression to ret == 0, so a denied (non-zero) result now correctly raises K_OOPS and terminates the offending caller.
Title Broken access-control denial in k_thread_join/k_thread_abort syscall validation in Zephyr kernel
Weaknesses CWE-862
References
Metrics cvssV3_1

{'score': 6.5, 'vector': 'CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H'}


Subscriptions

Zephyrproject Zephyr
cve-icon MITRE

Status: PUBLISHED

Assigner: zephyr

Published:

Updated: 2026-08-19T13:18:03.745Z

Reserved: 2026-06-18T15:22:26.927Z

Link: CVE-2026-12631

cve-icon Vulnrichment

No data.

cve-icon NVD

Status : Awaiting Analysis

Published: 2026-08-18T21:16:33.647

Modified: 2026-08-26T16:59:23.267

Link: CVE-2026-12631

cve-icon Redhat

No data.

cve-icon OpenCVE Enrichment

Updated: 2026-08-21T17:15:05Z

Weaknesses