(CVE-2025-23096) Samsung Exynos NPU Driver Double Free in IMB Memory Buffer Leading to Privilege Escalation

CVE: CVE-2025-23096

Affected Versions: Samsung Galaxy S24+ (samsung/e2sxxx/e2s:14/UP1A.231005.007/S926BXXS3AXGD:user/release-keys); Samsung Exynos 1280, 2200, 1380, 1480, 2400

CVSS3.1: 7.8 (High) — CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Summary

Product Samsung Exynos NPU Driver
Vendor Samsung
Severity High — a local attacker within untrusted_app SELinux context may exploit this to achieve local privilege escalation
Affected Versions Samsung Galaxy S24+ (Android 14); Exynos 1280, 2200, 1380, 1480, 2400
Tested Versions Samsung Galaxy S24+ (S926BXXS3AXGD)
CVE Identifier CVE-2025-23096
CVE Description A double free in the Samsung Exynos mobile processor NPU driver leads to privilege escalation
CWE Classification(s) CWE-415: Double Free

CVSS3.1 Scoring System

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

Metric Value
Attack Vector (AV) Local
Attack Complexity (AC) Low
Privileges Required (PR) Low
User Interaction (UI) None
Scope (S) Unchanged
Confidentiality (C) High
Integrity (I) High
Availability (A) High

Product Background

The Samsung Galaxy S24+ features a Neural Processing Unit (NPU) integrated into either the Snapdragon 8 Gen 3 or Exynos 2400 chipset depending on the market. The NPU accelerates on-device AI workloads including camera processing, real-time translation, and generative photo editing. The NPU kernel driver is a privileged component that manages session state, memory allocation, and inference buffer management on behalf of userspace applications.

Technical Details

In __prepare_IMB_info, it will assign IMB_mem_buf to session->IMB_mem_buf. If session->IMB_size is quite big, it will goto p_err free the IMB_mem_buf but do not clean the pointer in session.

int __config_session_info(struct npu_session *session)
{
    	IMB_mem_buf = kcalloc(1, sizeof(struct npu_memory_buffer), GFP_KERNEL);
        ...
        ret = __prepare_IMB_info(session, &IMB_av, IMB_mem_buf);
        ...
}
    
int __prepare_IMB_info(struct npu_session *session, struct addr_info **IMB_av, struct npu_memory_buffer *IMB_mem_buf)
{
    ...
	session->IMB_mem_buf = IMB_mem_buf;
	if (session->IMB_size > (NPU_IMB_CHUNK_SIZE * NPU_IMB_CHUNK_MAX_NUM)) {
		...
		goto p_err;
	}
p_err:
	if (likely(IMB_mem_buf))
		kfree(IMB_mem_buf); // [1]

Then it will freed again at __release_imb_mem_buf:

static inline void __release_imb_mem_buf(struct npu_session *session)
{
	struct npu_memory_buffer *ion_mem_buf = session->IMB_mem_buf;
	if (likely(ion_mem_buf)) {
                ...
		session->IMB_mem_buf = NULL;
		kfree(ion_mem_buf);
	}
}

Credit

Billy Jheng Bing-Jhong, Muhammad Alifa Ramdhan and Pan Zhenpeng of STAR Labs SG Pte. Ltd.

Timeline