home intel cve-2025-52519-exynos-issimian-driver-infoleak
CVE Analysis 2026-01-05 · 8 min read

CVE-2025-52519: Exynos issimian Driver Input Validation Flaw Leaks Kernel Memory

The issimian camera device driver on Exynos 1330–2500 fails to validate user-space ioctl input, enabling unprivileged kernel memory disclosure and local DoS via a malformed request.

#kernel-memory-disclosure#input-validation-flaw#device-driver-exploit#android-camera-subsystem#exynos-processor
Technical mode — for security professionals
▶ Vulnerability overview — CVE-2025-52519 · Information Disclosure
ATTACKERAndroidINFORMATION DISCCVE-2025-52519HIGHSYSTEM COMPROMISEDNo confirmed exploits

Vulnerability Overview

CVE-2025-52519 is an information disclosure and denial-of-service vulnerability residing in the issimian camera device driver shipped with Samsung's Exynos Mobile Processor and Wearable Processor line. The driver — part of the ISP (Image Signal Processor) subsystem surfaced to userspace via a /dev/ character device node — fails to sanitize attacker-controlled fields passed through ioctl() before using them to index into or copy from kernel-managed camera configuration structures. A local unprivileged process (any app with camera permission, or AID_CAMERA group membership) can trigger the path.

CVSS 7.1 (HIGH): AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H — local read, no user interaction, high confidentiality impact, high availability impact.

Affected silicon: Exynos 1330, 1380, 1480, 1580, 2400, 2500.

Affected Component

The vulnerable driver is issimian, a Samsung-proprietary kernel module that acts as the userspace-facing front-end for the Exynos camera ISP pipeline. It exposes a character device (typically /dev/is_sensor or a vendor-specific node under /dev/camera/) and processes a set of vendor-defined ioctl commands. The driver is compiled into the Exynos GKI kernel image and runs in kernel context (EL1 on ARMv8).

The specific subsystem path is: Userspace camera HAL → /dev/isXissimian_ioctl() → ISP control plane.

Root Cause Analysis

The driver's ioctl dispatch handler copies a user-supplied control structure into a kernel-side buffer and then uses unvalidated fields from that structure — specifically a buf_index and a length field — to read back ISP pipeline state into a user-provided output buffer. Neither the index nor the length is range-checked before use.


/* issimian_ioctl() dispatch — simplified decompilation, Exynos 2400 kernel */

#define ISSIMIAN_IOC_GET_BUF_INFO  _IOWR('I', 0x1F, struct issimian_buf_req)

struct issimian_buf_req {
    uint32_t  buf_index;   /* user-controlled: index into internal buf table   */
    uint32_t  length;      /* user-controlled: bytes to copy back to userspace */
    uint64_t  out_addr;    /* user-controlled: destination user pointer        */
    uint32_t  reserved[4];
};

long issimian_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct issimian_dev     *idev  = filp->private_data;
    struct issimian_buf_req  req;

    if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
        return -EFAULT;

    switch (cmd) {
    case ISSIMIAN_IOC_GET_BUF_INFO: {
        struct issimian_buf_entry *entry;

        // BUG: buf_index is never checked against idev->buf_table_count
        entry = &idev->buf_table[req.buf_index];

        // BUG: req.length is never checked; can request up to UINT32_MAX bytes
        //      entry->kva may point anywhere in the kernel virtual address space
        if (copy_to_user((void __user *)req.out_addr,
                         entry->kva,          /* kernel virt addr from table */
                         req.length))         /* attacker-controlled size    */
            return -EFAULT;

        return 0;
    }
    /* ... other cases ... */
    }
}

Two distinct bugs compose the vulnerability:

  1. OOB table read: req.buf_index is used directly as an array subscript into idev->buf_table[] without being bounded by idev->buf_table_count. An out-of-range index walks past the allocated table into adjacent kernel heap objects, and the kva field read from that corrupted-view entry is an arbitrary kernel pointer.
  2. Unbounded copy_to_user: Even with a valid index, req.length is not capped against the actual buffer size stored in the entry. An attacker sets length to a large value to dump kernel memory beyond the intended region.
Root cause: issimian_ioctl() uses the caller-supplied buf_index and length fields from a user-copied structure directly in a copy_to_user() call without bounds-checking either value against the driver's internal buffer table dimensions or the associated allocation size.

Memory Layout


idev->buf_table (kmalloc'd slab, 8 entries × sizeof(issimian_buf_entry)):

  idx  offset    kva                  size      flags
  ---- --------- -------------------- --------- -----
  [0]  +0x000    0xffffffc012a40000   0x10000   VALID
  [1]  +0x028    0xffffffc012a50000   0x10000   VALID
  ...
  [7]  +0x0E0    0xffffffc012ab0000   0x10000   VALID
                                                       <-- table ends here
  [8]  +0x108    [ADJACENT HEAP OBJ]               <-- OOB: buf_index=8
       +0x108    kva field reads from adjacent slab chunk's data bytes
                 → kva may resolve to a kernel text/stack/secret pointer

COPY_TO_USER WITH req.length = 0x40000 (256 KB), entry[1] size = 0x10000:
  legitimate region:  0xffffffc012a50000 – 0xffffffc012a60000
  disclosed region:   0xffffffc012a50000 – 0xffffffc012a90000
                                          ^^^^^^^^^^^^^^^^^^^
                                          128 KB of unintended kernel heap

Struct Layout


struct issimian_buf_entry {
    /* +0x00 */ void        *kva;       // kernel virtual address of buffer
    /* +0x08 */ dma_addr_t   iova;      // IOMMU-mapped device address
    /* +0x10 */ size_t       size;      // allocated size in bytes
    /* +0x18 */ uint32_t     flags;     // VALID | MAPPED | SHARED
    /* +0x1C */ uint32_t     fd;        // dmabuf fd backing this entry
    /* +0x20 */ struct list_head node;  // linked into idev->buf_list
};  // sizeof = 0x28 (40 bytes)

struct issimian_dev {
    /* +0x000 */ struct device        *dev;
    /* +0x008 */ struct cdev           cdev;
    /* +0x060 */ struct mutex          lock;
    /* +0x0A0 */ struct issimian_buf_entry *buf_table;  // pointer to slab array
    /* +0x0A8 */ uint32_t              buf_table_count; // BUG: never checked vs req.buf_index
    /* +0x0AC */ uint32_t              state;
    /* ... */
};

Exploitation Mechanics


EXPLOIT CHAIN — Information Disclosure Path:

1. Open /dev/is_sensor (requires AID_CAMERA or camera permission)

2. Call ISSIMIAN_IOC_INIT_BUF (or equivalent) to establish a minimal
   buf_table with 2 entries, forcing a predictable small kmalloc-64
   allocation for buf_table.

3. Spray the kmalloc-64 slab with objects containing known-value headers
   (e.g., open 32 dummy dmabuf fds) to position a target object
   immediately after buf_table in the same slab cache.

4. Submit ISSIMIAN_IOC_GET_BUF_INFO with:
     req.buf_index = 8          // walks 8×0x28 = 0x140 bytes past table start
     req.length    = 0x28       // read one fake entry's worth of data
     req.out_addr  = user_buf   // writable user buffer

5. Read back 40 bytes: the kva field at offset +0x00 of the adjacent
   heap object now lands in user_buf[0..7]. This is a raw kernel pointer
   (KASLR slide recovery if it points to a module or kernel text mapping).

6. Issue a second ioctl with:
     req.buf_index = 1          // valid index
     req.length    = 0x40000    // 256 KB >> actual allocation of 0x10000
     req.out_addr  = user_buf2

   Dumps 256 KB of contiguous kernel heap starting at entry[1]->kva,
   disclosing slab metadata, adjacent allocation contents, and potentially
   credential structures (struct cred) or page-table entries in the heap.

DENIAL OF SERVICE PATH:
7. Set req.buf_index to a value whose resolved kva lands on a non-mapped
   or read-faulting kernel address. copy_to_user faults inside kernel
   context without a fixup entry registered → BUG() / panic.

Patch Analysis

The fix introduces two independent bounds checks before the copy_to_user call, and promotes the critical fields to signed comparisons to prevent integer wraparound confusion.


// BEFORE (vulnerable — no bounds checks):
long issimian_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct issimian_buf_entry *entry;

    if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
        return -EFAULT;

    entry = &idev->buf_table[req.buf_index];          // OOB possible

    if (copy_to_user((void __user *)req.out_addr,
                     entry->kva,
                     req.length))                     // unbounded
        return -EFAULT;
    return 0;
}

// AFTER (patched):
long issimian_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct issimian_buf_entry *entry;

    if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
        return -EFAULT;

    /* FIX 1: validate index against table bounds */
    if (req.buf_index >= idev->buf_table_count)
        return -EINVAL;

    entry = &idev->buf_table[req.buf_index];

    /* FIX 2: clamp requested length to actual allocation size */
    if (req.length > entry->size)
        return -EINVAL;

    if (copy_to_user((void __user *)req.out_addr,
                     entry->kva,
                     req.length))
        return -EFAULT;
    return 0;
}

The patch is structurally minimal: two early-return guards. Samsung's advisory does not reference an internal bug ID for this specific check, but the pattern matches the standard Exynos ISP driver hardening seen in the May 2025 security bulletin pushed to Galaxy S24/S25 series (Exynos 2400/2500) and Galaxy A-series (Exynos 1380/1480).

Detection and Indicators

On a device running a vulnerable kernel, the following can indicate exploitation attempts:

  • Kernel log (dmesg): An exploited OOB read producing a page fault inside copy_to_user from a bad kva appears as Unable to handle kernel paging request at virtual address with PC in __arch_copy_to_user / arm64_copy_to_user_alias.
  • Audit log (/proc/kmsg): Repeated ISSIMIAN_IOC_GET_BUF_INFO ioctls from a non-system UID against /dev/is_sensor without preceding camera session establishment.
  • SELinux denials: On a correctly labeled system, avc: denied { ioctl } for the specific command code 0x491F from untrusted app domains; absence of such denials from a process that should not reach the node.

CRASH SIGNATURE (DoS path, unpatched kernel):
  Unable to handle kernel paging request at virtual address ffff800041414141
  Mem abort info:
    ESR = 0x0000000096000004
    EC = 0x25: DABT (current EL), IL = 32 bits
    SET = 0, FnV = 0
    EA = 0, S1PTW = 0
  Data abort info:
    ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
    CM = 0, WnR = 0, TnD = 0, TagAccess = 0
  pc : __arch_copy_to_user+0x68/0x1c0
  lr : issimian_ioctl+0x21c/0x4a0 [issimian]
  Call trace:
   __arch_copy_to_user+0x68/0x1c0
   issimian_ioctl+0x21c/0x4a0 [issimian]
   __arm64_sys_ioctl+0xac/0x100
   invoke_syscall+0x54/0x130

Remediation

Apply Samsung's May 2025 Android Security Maintenance Release (SMR-MAY-2025) for all affected Exynos-based Galaxy devices. No workaround is available short of revoking camera access for untrusted applications via SELinux policy, which is not a complete mitigation for privileged callers.

  • Galaxy S24 / S24+ / S24 Ultra (Exynos 2400): SMR-MAY-2025, build suffix S92*BXXU* or later.
  • Galaxy A35 / A55 (Exynos 1480): SMR-MAY-2025, build suffix A*56B* or later.
  • Galaxy Watch series (Exynos 1330 wearable variant): Firmware update via Galaxy Wearable app, May 2025 bundle.

Kernel module developers shipping custom ISP drivers should audit all ioctl handlers that accept a user-supplied index into any kernel-managed array: the index must be checked strictly against the array's runtime count using an unsigned comparison before any dereference, and any length field must be clamped to the associated object's recorded size before passing to copy_to_user or memcpy.

CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// RELATED RESEARCH
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →