Xtensa MMU userspace: uninitialized thread page-table pointer leads to out-of-bounds supervisor-mode writes
Affects Zephyr 3.6.0 up to 4.3.2 and 4.4.0 up to 4.5.0 on Xtensa builds with CONFIG_XTENSA_MMU and CONFIG_USERSPACE that use dynamically allocated kernel objects. 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_XTENSA_MMU enabled Build has CONFIG_USERSPACE and dynamically allocated kernel objects The recycled heap bytes at the thread's page-table pointer offset are non-zero
- Last modified
- 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? →
- 13/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
- 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 Xtensa MMU userspace port never initialized the per-thread page-table pointer thread->arch.ptables during thread setup, while arch_mem_domain_thread_add() in arch/xtensa/core/ptables.c uses a non-NULL value of that field as its "this thread is migrating from another memory domain" predicate. For a thread whose struct k_thread backing memory is not zeroed, the field holds stale data and the kernel takes the migration branch, passing that stale value to reset_region() as the base of a level-1 page table. The equivalent field on x86 is explicitly cleared in z_x86_userspace_prepare_thread() for exactly this reason; the Xtensa port adopted the predicate without the initialization.
The condition is reachable from an unprivileged user-mode thread on a build with CONFIG_XTENSA_MMU, CONFIG_USERSPACE and dynamically allocated kernel objects. k_object_alloc(K_OBJ_THREAD) is a system call and allocates the thread object from the caller's resource pool without zeroing it, and the k_thread_create() verifier accepts such an object while forcing the K_USER option, so the migration branch is taken whenever the recycled heap bytes at that offset are non-zero. Because a user thread can also allocate, fill and free other kernel objects from the same heap, the stale bytes are groomable rather than merely random.
Walking the bogus table in region_map_update() performs an unguarded index into l2_page_tables_counter[], may copy from and write through the attacker-influenceable level-1 base in dup_l2_table_if_needed(), and finally writes a page-table entry through a second pointer read out of that memory — once per page of the new thread's stack. The result is out-of-bounds reads and writes executed in supervisor mode, ranging from an immediate kernel panic (observed as Xtensa EXCAUSE 13 on Intel ADSP DSP firmware with user threads) to corruption of kernel memory and escape from the user-mode sandbox.
cve.now Index
- Exploitation?/40Unknown. No CISA SSVC exploitation rating yet
- Exposure5/25Specific setups only
- Reach?/20Unknown. No tracked technology or package matched
- Severity7.8/10CVSS 7.8
- No patch0/5No signal
What would change the score
- Would score about 63 if added to CISA KEV
- Would score about 58 if CISA's SSVC rates exploitation active
- Would score about 23 if CISA's SSVC rates it automatable
What to do
Check whether your setup matches what the bug needs.
Build has CONFIG_XTENSA_MMU enabled Build has CONFIG_USERSPACE and dynamically allocated kernel objects The recycled heap bytes at the thread's page-table pointer offset are non-zeroUpgrade to a fixed version: 4.3.2, 4.5.0.
Timeline
- CVE published
- First seen by cve.now
Affected versions
- zephyr
From 3.6.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-90586
Is CVE-2026-90586 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?
A thread's page-table pointer is not initialized, so the kernel can read a value left over in recycled heap memory. When those bytes are non-zero, the kernel takes a wrong branch and reads or writes memory out of bounds in supervisor mode. The impact ranges from an immediate kernel panic to corruption of kernel memory and escape from the user-mode sandbox.Source: github.com
Which versions are affected by CVE-2026-90586?
zephyr: from 3.6.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 3.6.0 before 4.3.2, and 4.4.0 before 4.5.0. The bug needs a build with CONFIG_XTENSA_MMU enabled, CONFIG_USERSPACE enabled, and dynamically allocated kernel objects. Check the Zephyr version in use and the values of these configuration options in the build.Source: github.com
How do I fix CVE-2026-90586?
Upgrade to Zephyr 4.3.2 or 4.5.0, matching your release branch. The facts list no workaround, so upgrading is the only listed fix.Source: github.com