☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
OP-TEE logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 7.8 🐛 CWE-416
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-40290

CVE-2026-40290 Use After Free in Op-Tee
📅 PUBLISHED: 2026-06-03 18:16 UTC 🔄 UPDATED: 2026-10-02 19:29 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.21%
👁️
0.21% probability
5.2× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1203
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: Finland License: Open Source
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
7.8
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-40290 is a critical Use-After-Free (UAF) race condition vulnerability in the OP-TEE (Open Portable Trusted Execution Environment) software, specifically within its FF-A (Firmware Framework for Arm A-profile) shared memory teardown logic. This vulnerability affects OP-TEE versions 3.16.0 through 4.10.0 when configured as an SPMC (Secure Partition Manager Core) for S-EL0 Secure Partitions (SPs), enabled via the CFG_SECURE_PARTITION=y build flag.

The core issue lies in the sp_mem_remove() function, which is responsible for freeing shared memory entries. This function fails to acquire the global sp_mem_lock mutex before performing free() operations on the smem->receivers and smem->regions lists. Concurrently, other code paths like sp_mem_get_receiver() iterate over these same lists without any locking, while sp_mem_is_shared() iterates with the lock but is not serialized against the unprotected free() in sp_mem_remove(). This creates a race condition where one thread can free a memory object while another thread is still using it, leading to a Use-After-Free condition.

Successful exploitation could allow an attacker with local access to a non-secure Linux kernel to corrupt the TEE's memory, potentially leading to privilege escalation within the TrustZone environment, information disclosure, or denial of service. The vulnerability has a CVSS score of 7.8 (High) and is currently unpatched in affected versions. The fix is available in OP-TEE version 4.11.0.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

OP-TEE is a critical component in the Arm TrustZone ecosystem, used in many embedded and mobile devices. As an open-source project, its supply chain is managed through GitHub and the OP-TEE build system. The vulnerability is introduced in the source code and affects all downstream users who build OP-TEE with the vulnerable configuration. Organizations using OP-TEE as part of their product's secure boot chain or trusted execution environment should treat this as a high-priority supply chain risk. The lack of a public exploit or PoC does not diminish the risk, as the race condition is well-documented and could be weaponized by sophisticated threat actors.

CVSS Breakdown & Threat Level

CVSS Score: 7.8 (High) Vector: CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H

  • Attack Vector (AV): Local (L) - The attacker must have local access to the system.
  • Attack Complexity (AC): High (H) - Exploitation requires precise timing to win the race condition.
  • Privileges Required (PR): Low (L) - The attacker needs low-level privileges (e.g., user-level access to the non-secure OS).
  • User Interaction (UI): None (N) - No user interaction is required beyond the attacker's own actions.
  • Scope (S): Unchanged (U) - The vulnerability affects only the TEE component.
  • Confidentiality (C): High (H) - Potential to read sensitive TEE memory.
  • Integrity (I): High (H) - Potential to corrupt TEE memory.
  • Availability (A): High (H) - Potential to crash the TEE.

Threat Level: High. The vulnerability allows for privilege escalation within the TrustZone environment, which is a critical security boundary. While the attack complexity is high, the potential impact is severe.

Deep Dive & Mechanics

The vulnerability is a classic Use-After-Free (UAF) race condition in the shared memory management subsystem of OP-TEE's FF-A implementation. The FF-A specification defines how software components in the secure and non-secure worlds communicate via shared memory. In OP-TEE, when configured as an SPMC, it manages shared memory regions for Secure Partitions (SPs) running at S-EL0.

The key data structures involved are:

  • struct sp_mem: Represents a shared memory descriptor.
  • struct sp_mem_receiver: Represents a receiver of the shared memory.
  • struct sp_mem_map_region: Represents a mapped region of the shared memory.

These structures are stored in linked lists: smem->receivers and smem->regions.

The vulnerable function sp_mem_remove() is called to tear down a shared memory descriptor. It iterates over the receivers and regions lists and frees each entry. However, it does not acquire the global sp_mem_lock mutex before doing so.

// Vulnerable code path in sp_mem_remove()
void sp_mem_remove(struct sp_mem *smem)
{
    // ... (no lock acquisition)
    while (receiver) {
        next = SLIST_NEXT(receiver, link);
        free(receiver);  // UAF: freed without lock
        receiver = next;
    }
    while (region) {
        next = SLIST_NEXT(region, link);
        free(region);  // UAF: freed without lock
        region = next;
    }
    // ...
}

Concurrently, other functions access these lists:

  • sp_mem_get_receiver() iterates the receivers list without any lock.
  • sp_mem_is_shared() iterates the regions list while holding the lock, but the lock does not protect against the unprotected free() in sp_mem_remove().

The race condition unfolds as follows:

  1. Thread A calls sp_mem_get_receiver() and obtains a pointer to a struct sp_mem_receiver from the list.
  2. Thread B calls sp_mem_remove() on the same smem object, frees the receiver entry that Thread A is pointing to.
  3. Thread A resumes and dereferences the now-freed pointer, causing a Use-After-Free.

This can lead to arbitrary code execution if the freed memory is reallocated by an attacker-controlled object.

Vulnerable vs. Patched Code

Vulnerable Code (versions 3.16.0 to 4.10.0):

In core/arch/arm/kernel/sp_mem.c, the sp_mem_remove() function does not acquire sp_mem_lock:

void sp_mem_remove(struct sp_mem *smem)
{
    struct sp_mem_receiver *receiver;
    struct sp_mem_receiver *next_receiver;
    struct sp_mem_map_region *region;
    struct sp_mem_map_region *next_region;

    // Missing: mutex_lock(&sp_mem_lock);

    receiver = SLIST_FIRST(&smem->receivers);
    while (receiver) {
        next_receiver = SLIST_NEXT(receiver, link);
        free(receiver);
        receiver = next_receiver;
    }

    region = SLIST_FIRST(&smem->regions);
    while (region) {
        next_region = SLIST_NEXT(region, link);
        free(region);
        region = next_region;
    }

    // Missing: mutex_unlock(&sp_mem_lock);
}

Patched Code (version 4.11.0):

The fix adds proper locking around the free() operations:

void sp_mem_remove(struct sp_mem *smem)
{
    struct sp_mem_receiver *receiver;
    struct sp_mem_receiver *next_receiver;
    struct sp_mem_map_region *region;
    struct sp_mem_map_region *next_region;

    mutex_lock(&sp_mem_lock);  // Lock acquired

    receiver = SLIST_FIRST(&smem->receivers);
    while (receiver) {
        next_receiver = SLIST_NEXT(receiver, link);
        free(receiver);
        receiver = next_receiver;
    }

    region = SLIST_FIRST(&smem->regions);
    while (region) {
        next_region = SLIST_NEXT(region, link);
        free(region);
        region = next_region;
    }

    mutex_unlock(&sp_mem_lock);  // Lock released
}

The patch ensures that all modifications to the receivers and regions lists are serialized under the global sp_mem_lock, preventing the race condition.

Exploitation & Lab Setup

Red Team (Exploitation)

Prerequisites:

  • Local access to a system running OP-TEE with CFG_SECURE_PARTITION=y (versions 3.16.0 to 4.10.0).
  • Ability to create and run threads in the non-secure world.
  • Knowledge of the TEE's shared memory allocation patterns.

Exploitation Strategy:

The goal is to trigger the race condition between sp_mem_get_receiver() and sp_mem_remove(). Since no public exploit exists, a custom exploit would need to:

  1. Spray the heap: Allocate many shared memory descriptors to increase the chance of a race.
  2. Create two threads:
    • Thread A: Continuously calls a function that invokes sp_mem_get_receiver() (e.g., by repeatedly sharing memory and querying receivers).
    • Thread B: Continuously calls a function that invokes sp_mem_remove() (e.g., by repeatedly releasing shared memory).
  3. Win the race: When Thread A obtains a pointer to a receiver entry, Thread B frees it. Thread A then dereferences the dangling pointer.
  4. Post-exploitation: After the UAF, the attacker can attempt to reallocate the freed memory with a controlled object (e.g., a fake struct sp_mem_receiver) to hijack control flow or leak sensitive data.

Example pseudo-code for the race trigger:

// Thread A: Constantly queries receivers
void *thread_a(void *arg) {
    while (1) {
        struct sp_mem *smem = get_shared_mem();
        struct sp_mem_receiver *rec = sp_mem_get_receiver(smem, target_id);
        if (rec) {
            // Use rec->some_field (UAF here)
            volatile uint32_t val = rec->some_field;
        }
    }
    return NULL;
}

// Thread B: Constantly removes shared memory
void *thread_b(void *arg) {
    while (1) {
        struct sp_mem *smem = get_shared_mem();
        sp_mem_remove(smem);
    }
    return NULL;
}

Note: Exploitation is non-trivial due to the high attack complexity and the need for precise timing.

Blue Team (Defense & Detection)

Detection Strategy:

  1. Monitor for race condition indicators: Look for crashes or panics in the TEE that involve sp_mem_remove() or sp_mem_get_receiver().
  2. Audit shared memory operations: Log all calls to sp_mem_remove() and sp_mem_get_receiver() and look for temporal anomalies (e.g., a receiver being accessed after a remove call).
  3. Use AddressSanitizer (ASan): If running in a debug environment, enable ASan to detect UAF conditions during testing.
  4. Static analysis: Run static analysis tools (e.g., Clang Static Analyzer) on the OP-TEE source code to identify missing locks.

Mitigation Steps:

  1. Immediate: Upgrade to OP-TEE version 4.11.0 or later.
  2. Workaround: If upgrade is not possible, disable CFG_SECURE_PARTITION=y if not required.
  3. Compile-time checks: Enable thread sanitizer (TSan) during development to catch race conditions.
  4. Runtime monitoring: Implement monitoring of TEE crashes and correlate with shared memory operations.

Indicators of Compromise (IOCs)

  • System Logs:
    • TEE panic messages containing references to sp_mem_remove, sp_mem_get_receiver, or sp_mem_is_shared.
    • Kernel oops messages from the non-secure world indicating a crash in the TEE driver.
  • Memory Artifacts:
    • Corrupted struct sp_mem_receiver or struct sp_mem_map_region objects in TEE memory dumps.
    • Unexpected pointers in freed memory regions.
  • Behavioral:
    • Unusual number of shared memory allocation/deallocation operations.
    • Repeated TEE crashes or resets.
  • Network (if applicable):
    • No direct network IOCs, as this is a local vulnerability.

Detection Engineering

YARA Rule

rule CVE_2026_40290_OP_TEE_UAF {
    meta:
        description = "Detects vulnerable OP-TEE binary with missing lock in sp_mem_remove"
        author = "Valters IT"
        date = "2025-04-10"
        cve = "CVE-2026-40290"
        hash = "sha256:target_binary_hash"
    strings:
        $func_sp_mem_remove = "sp_mem_remove" ascii wide
        $func_sp_mem_get_receiver = "sp_mem_get_receiver" ascii wide
        $func_sp_mem_is_shared = "sp_mem_is_shared" ascii wide
        $lock_func = "mutex_lock" ascii wide
        $unlock_func = "mutex_unlock" ascii wide
    condition:
        $func_sp_mem_remove and $func_sp_mem_get_receiver and $func_sp_mem_is_shared and
        not ($lock_func and $unlock_func)
}

Sigma Rule

title: CVE-2026-40290 - OP-TEE UAF Race Condition in sp_mem_remove
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects potential exploitation of CVE-2026-40290 by monitoring TEE crashes related to shared memory operations.
author: Valters IT
date: 2025-04-10
logsource:
    product: linux
    service: syslog
detection:
    selection:
        - "sp_mem_remove"
        - "sp_mem_get_receiver"
        - "sp_mem_is_shared"
        - "UAF"
        - "use-after-free"
    condition: selection
falsepositives:
    - Legitimate TEE crashes due to other bugs
level: high

Suricata Rule

alert ip any any -> any any (msg:"CVE-2026-40290 - OP-TEE UAF Race Condition"; content:"sp_mem_remove"; content:"sp_mem_get_receiver"; distance:0; within:100; classtype:attempted-admin; sid:1000001; rev:1;)

Remediation & Mitigation

Immediate Actions:

  1. Upgrade OP-TEE: Update to version 4.11.0 or later, which contains the fix.
  2. Disable Feature: If upgrade is not possible, disable CFG_SECURE_PARTITION=y in the build configuration to remove the vulnerable code path.
  3. Patch Verification: After upgrading, verify that the sp_mem_remove() function now acquires sp_mem_lock before freeing entries.

Long-term Measures:

  1. Code Review: Conduct a thorough code review of all shared memory operations in OP-TEE to ensure proper locking.
  2. Static Analysis: Integrate static analysis tools (e.g., Coverity, Clang Static Analyzer) into the CI/CD pipeline to detect missing locks.
  3. Dynamic Analysis: Use ThreadSanitizer (TSan) and AddressSanitizer (ASan) during testing to catch race conditions and UAF bugs.
  4. Security Training: Educate developers on concurrency pitfalls and secure coding practices for TEE environments.

Workarounds:

  • If the system cannot be upgraded, consider using a different TEE implementation or isolating the vulnerable component.
  • Implement runtime monitoring to detect and respond to TEE crashes.

Valters IT

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-40290/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.