Live › vulnerability › CVE-2026-79979
Go to dashboardOn arm64 builds with user mode and demand paging, the MMU invalidates TLB entries using the wrong ASID, so a user thread keeps access to a physical frame after the kernel evicts and reuses it. A user-mode thread can then read or write supervisor data, another memory domain's partition, or another thread's stack.
Summary written from the sources below. Check the originals before acting.
First seen by InfraStack 2026-10-23 21:57 UTC. All times on this page are UTC.
Only arm64 Zephyr builds that enable both user mode (CONFIG_USERSPACE) and demand paging (CONFIG_DEMAND_PAGING) with an active backing store. Builds without demand paging, or on other architectures, are not exposed by this description.
No product ranges from the sources yet.
CONFIG_USERSPACE and CONFIG_DEMAND_PAGING enabled in the kernel configuration (.config or prj.conf) for an arm64 targetinvalidate_tlb_page() to TLBI VAAE1{IS} (fixed version: unknown in sources)CONFIG_DEMAND_PAGING on arm64 builds that use user mode (workaround implied by the exploitation conditions)Each row is the first time that source carried this signal. The analyst’s rows are its own findings.
The arm64 MMU backend invalidates a single virtual address from the TLB with invalidate_tlb_page() in arch/arm64/core/mmu.c, which issued TLBI VAE1{IS} with an operand of virt >> 12. That operand encodes the ASID in bits [63:48], so the invalidation only ever matched ASID 0 (the kernel page tables) and global entries. Memory domains, however, are allocated ASIDs starting at 1 in arch_mem_domain_init(), and every domain-private leaf created by private_map() is mapped with MT_NG, i.e. non-global. A domain's cached translation therefore survived the invalidation.
All callers of invalidate_tlb_page() are demand-paging paths. When the eviction algorithm reclaims a frame, page_frame_prepare_locked() in kernel/mmu.c calls arch_mem_page_out(), which marks the kernel leaf invalid, propagates the invalid descriptor into every domain via sync_domains(), and then flushes only ASID 0. do_page_fault() immediately reuses the very same page frame for the incoming mapping through arch_mem_page_in(). A user thread that had already touched the evicted page — a k_mem_partition added with arch_mem_domain_partition_add(), or its own stack mapped by map_thread_stack() — retains a valid EL0 read/write translation to that physical frame under its own ASID.
Unprivileged code running in a user thread can drive memory pressure to force eviction and then keep accessing the stale address, obtaining read and write access to whatever the kernel subsequently placed in that frame: supervisor data, another memory domain's partition, or another thread's stack. This defeats the isolation that CONFIG_USERSPACE is meant to enforce, allowing information disclosure and memory corruption up to full compromise of the system.
The fix switches the implementation to TLBI VAAE1{IS}, which matches every ASID and both global and non-global entries, so no domain-tagged translation survives a page out, dirty-bit update or access-flag clear. Exploitation requires an arm64 build with both CONFIG_USERSPACE and CONFIG_DEMAND_PAGING enabled, an active backing store, and at least one demand-paged page that is also privately mapped into a user memory domain. The same commit additionally stops globalize_table() from stripping EL0 permission and non-global attributes off domain-private leaves during paging synchronization, which previously caused user threads to lose access to their own partitions and stacks.
This page as .md · .json · in your agent: get_signal("CVE-2026-79979")
NVD data is provided by NIST and is public domain · EPSS scores by FIRST, used with attribution. Posts quoted belong to their authors.