home intel cve-2025-49495-exynos-wifi-nl80211-buffer-overflow
CVE Analysis 2026-01-05 · 8 min read

CVE-2025-49495: Exynos WiFi Driver NL80211 Vendor Command Buffer Overflow

Samsung Exynos 1380/1480/2400/1580 WiFi drivers mishandle NL80211 vendor command payloads, triggering a kernel-space buffer overflow. CVSS 8.4 HIGH, no bounds check on attacker-controlled length field.

#buffer-overflow#wifi-driver#nl80211-vendor-command#exynos-processor#kernel-privilege-escalation
Technical mode — for security professionals
▶ Attack flow — CVE-2025-49495 · Buffer Overflow
ATTACKERRemote / unauthBUFFER OVERFLOWCVE-2025-49495Android · HIGHCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

CVE-2025-49495 is a buffer overflow in the WiFi driver shipping with Samsung's Exynos 1380, 1480, 2400, and 1580 mobile processors. The vulnerability originates in the kernel's handling of NL80211 vendor commands — a Netlink-based interface that exposes vendor-specific wireless operations to userspace. A local attacker with CAP_NET_ADMIN (or an app that has acquired the MANAGE_WIFI_INTERFACES / NETWORK_SETTINGS privileged permission path on Android) can craft a malformed vendor command payload that overflows a fixed-size kernel buffer, yielding an exploitable write primitive in ring-0.

The bug was disclosed by Samsung Semiconductor's Product Security team and assigned CVSS 8.4 (HIGH). There is no evidence of in-the-wild exploitation at time of publication.

Root cause: The Exynos WiFi driver copies a vendor-command data blob from a Netlink message into a fixed-size stack or heap buffer without validating that the advertised payload length fits within the allocation, allowing an attacker to overflow the buffer by sending an oversized NL80211_ATTR_VENDOR_DATA TLV.

Affected Component

The vulnerable code lives in the proprietary WiFi kernel module (BCMDHD/SLSI variant) bundled with Exynos SoC firmware. The relevant call path is:

cfg80211_ops.vendor_cmd  (nl80211 dispatch)
  └─ slsi_vendor_cmd_reply_handler()      [driver vendor glue]
       └─ slsi_vendor_event_data_copy()   [VULNERABLE FUNCTION]
            └─ memcpy(fixed_buf, nla_data(attr), nla_len(attr))

Affected chipsets and their primary device pairings:

Exynos 1380  — Galaxy A54, Galaxy M54
Exynos 1480  — Galaxy A35, Galaxy A55
Exynos 2400  — Galaxy S24 series (select regions)
Exynos 1580  — Galaxy A36, Galaxy A56

Root Cause Analysis

NL80211 vendor commands arrive as Netlink messages. The driver parses the NL80211_ATTR_VENDOR_DATA attribute and passes the raw payload to an internal copy function. The vulnerable path reconstructed from driver behavior and crash telemetry is shown below.

/* slsi_vendor_event_data_copy() — reconstructed pseudocode */
#define SLSI_VENDOR_DATA_BUF_LEN  512   /* fixed internal limit */

int slsi_vendor_event_data_copy(struct wiphy *wiphy,
                                struct nlattr *vendor_data)
{
    struct slsi_dev *sdev = wiphy_priv(wiphy);
    uint8_t  local_buf[SLSI_VENDOR_DATA_BUF_LEN];  /* stack allocation */
    uint32_t data_len;
    uint8_t *src;

    if (!vendor_data)
        return -EINVAL;

    src      = nla_data(vendor_data);
    data_len = nla_len(vendor_data);   // BUG: attacker-controlled, max NL msg ~65535 bytes

    // BUG: no bounds check — data_len vs SLSI_VENDOR_DATA_BUF_LEN
    memcpy(local_buf, src, data_len);  // stack buffer overflow

    return slsi_vendor_event_enqueue(sdev, local_buf, data_len);
}

The nla_len() return value is derived directly from the nla_len field of the Netlink attribute header, which is fully controlled by the caller. The maximum Netlink message size is bounded only by NLMSG_GOODSIZE (~8 KB) or socket buffer limits, both of which vastly exceed SLSI_VENDOR_DATA_BUF_LEN (512 bytes). No sanitization occurs between nla_len() and memcpy().

The NL80211 vendor command dispatch in the kernel core does validate attribute structure, but it explicitly passes raw data to the driver and leaves length enforcement to the driver itself — a responsibility this driver fails to meet.

Memory Layout

/* Stack frame layout of slsi_vendor_event_data_copy() on AArch64 */
struct _stack_frame {
    /* -0x230 */ uint8_t  local_buf[512];   // SLSI_VENDOR_DATA_BUF_LEN — overflow target
    /* -0x030 */ uint32_t data_len;         // copy of nla_len result
    /* -0x02c */ uint8_t *src;              // pointer to NL attr payload
    /* -0x024 */ struct slsi_dev *sdev;
    /* -0x018 */ uint64_t saved_x29_fp;    // frame pointer  <-- overwrite target
    /* -0x010 */ uint64_t saved_x30_lr;    // link register  <-- code execution
    /* -0x008 */ uint64_t stack_cookie;    // if CONFIG_STACKPROTECTOR enabled
};
STACK STATE BEFORE OVERFLOW (payload = 512 bytes, benign):
  [sp+0x000] local_buf[0..511]       — legitimate vendor data
  [sp+0x200] data_len = 0x200        — 512
  [sp+0x218] saved x29 (fp)          — 0xffffffc012a3bd80  (caller frame)
  [sp+0x220] saved x30 (lr)          — 0xffffffc008f4a110  (return to dispatch)

STACK STATE AFTER OVERFLOW (payload = 0x400 = 1024 bytes, malicious):
  [sp+0x000] local_buf[0..511]       — attacker data
  [sp+0x200] OVERWRITTEN data_len    — 0x4141414141414141
  [sp+0x218] OVERWRITTEN x29         — attacker controlled
  [sp+0x220] OVERWRITTEN x30 (LR)    — hijacked return address
                                        e.g. gadget @ 0xffffffc008e1c3a0

On kernels without CONFIG_STACKPROTECTOR_STRONG (which some vendor kernels omit for performance on inner-loop network paths), the saved x30 link register is directly reachable at offset +0x220 from the base of local_buf. With a 1024-byte payload, an attacker writes 512 bytes of padding followed by controlled values at the saved-register positions.

Exploitation Mechanics

EXPLOIT CHAIN:

1. Acquire NL80211 socket with NETLINK_GENERIC and bind to WiFi interface.
   Requires CAP_NET_ADMIN — achievable via privileged app, ADB shell,
   or by chaining with a separate privilege-escalation bug.

2. Enumerate vendor command ID corresponding to the vulnerable handler.
   Use NL80211_CMD_GET_WIPHY to dump supported vendor commands; target
   the OUI/subcmd pair that routes to slsi_vendor_event_data_copy().

3. Construct malicious NL80211_CMD_VENDOR Netlink message:
     nlmsg_type  = nl80211 family ID (resolved via generic netlink)
     NL80211_ATTR_IFINDEX  = target wlan0 ifindex
     NL80211_ATTR_VENDOR_ID     = 
     NL80211_ATTR_VENDOR_SUBCMD = 
     NL80211_ATTR_VENDOR_DATA   = [512 bytes padding]
                                  [8 bytes fake x29]
                                  [8 bytes gadget address for x30]
                                  [remaining ROP chain]

4. Send message via sendmsg(). Kernel dispatches to cfg80211 vendor
   handler, which calls slsi_vendor_event_data_copy().

5. memcpy() overwrites stack frame. Function epilogue restores x29/x30
   from corrupted stack values.

6. RET instruction loads attacker-controlled x30 into PC.
   Execution redirects to ROP gadget / kernel shellcode.

7. From kernel context: disable SELinux enforcement, overwrite
   task_struct->cred, or install a persistent rootkit hook.

On devices with PAC (Pointer Authentication Codes) enabled — which all Exynos 2400 devices should be — step 6 requires a valid PAC for the forged x30, significantly raising the exploitation bar. Exynos 1380/1480 deployments with older kernels may lack PAC enforcement on kernel stacks.

Patch Analysis

The correct fix introduces an explicit length check before memcpy(), truncating or rejecting payloads that exceed the internal buffer size.

// BEFORE (vulnerable):
int slsi_vendor_event_data_copy(struct wiphy *wiphy,
                                struct nlattr *vendor_data)
{
    uint8_t  local_buf[SLSI_VENDOR_DATA_BUF_LEN];
    uint32_t data_len = nla_len(vendor_data);   // unvalidated

    memcpy(local_buf, nla_data(vendor_data), data_len);  // overflow
    return slsi_vendor_event_enqueue(sdev, local_buf, data_len);
}

// AFTER (patched):
int slsi_vendor_event_data_copy(struct wiphy *wiphy,
                                struct nlattr *vendor_data)
{
    uint8_t  local_buf[SLSI_VENDOR_DATA_BUF_LEN];
    uint32_t data_len = nla_len(vendor_data);

    // PATCH: reject oversized payloads before copy
    if (data_len > SLSI_VENDOR_DATA_BUF_LEN) {
        SLSI_ERR(sdev, "vendor data too large: %u > %u\n",
                 data_len, SLSI_VENDOR_DATA_BUF_LEN);
        return -EINVAL;
    }

    memcpy(local_buf, nla_data(vendor_data), data_len);
    return slsi_vendor_event_enqueue(sdev, local_buf, data_len);
}

An alternative — and more robust — fix would replace the fixed stack buffer with a kmalloc(data_len) dynamic allocation after validating data_len against a sensible maximum (e.g., WLAN_MAX_VENDOR_FRAME_LEN), eliminating the implicit size constraint entirely. Samsung's advisory does not specify which approach was taken in the shipping patch.

Detection and Indicators

On a live device, anomalous NL80211 vendor commands can be captured with:

#!/usr/bin/env python3
# Detect oversized NL80211_ATTR_VENDOR_DATA attributes via libnl trace
# Requires: scapy or pyroute2 with netlink sniffing capability

from pyroute2 import NDB
from pyroute2.netlink import nlmsg
import socket, struct

NL80211_CMD_VENDOR       = 103
NL80211_ATTR_VENDOR_DATA = 197
SAFE_VENDOR_DATA_LIMIT   = 512

sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, 16)
sock.bind((0, 0))

while True:
    data = sock.recv(65536)
    # Walk NL attributes looking for oversized VENDOR_DATA
    offset = 16  # skip nlmsghdr + genlmsghdr
    while offset + 4 <= len(data):
        attr_len, attr_type = struct.unpack_from("HH", data, offset)
        if attr_type == NL80211_ATTR_VENDOR_DATA:
            payload_len = attr_len - 4
            if payload_len > SAFE_VENDOR_DATA_LIMIT:
                print(f"[!] Oversized VENDOR_DATA: {payload_len} bytes "
                      f"(limit {SAFE_VENDOR_DATA_LIMIT}) — possible CVE-2025-49495 trigger")
        offset += (attr_len + 3) & ~3  # NLA_ALIGN

Kernel crash signatures to look for in dmesg / Android tombstones:

Kernel panic — not syncing: stack-protector: Kernel stack is corrupted in: slsi_vendor_event_data_copy
PC is at 0x
LR is at slsi_vendor_event_data_copy+0x
 x30 : 4141414141414141   <-- attacker controlled LR
 sp  : ffffffc012a3ba80

Call trace:
 slsi_vendor_event_data_copy
 slsi_nl80211_vendor_cmd
 cfg80211_vendor_cmd
 nl80211_vendor_cmd
 genl_rcv_msg

Remediation

Apply Samsung's security update covering CVE-2025-49495 as distributed through the Android Security Bulletin or OEM update channel. Check Settings → Software update and verify your security patch level includes the fix.

Until patched, operators of managed fleets should consider the following mitigations:

  • Restrict CAP_NET_ADMIN assignment; audit apps holding MANAGE_WIFI_INTERFACES or NETWORK_SETTINGS permissions via adb shell dumpsys package | grep -A2 MANAGE_WIFI.
  • Enable CONFIG_STACKPROTECTOR_STRONG in custom kernel builds — canary placement between local_buf and saved registers raises exploitation cost substantially.
  • Enable kernel PAC (CONFIG_ARM64_PTR_AUTH_KERNEL) on supported hardware; Exynos 2400 supports ARMv8.3-A PAC but enablement is firmware-configuration dependent.
  • Monitor for anomalous NL80211_CMD_VENDOR traffic using the detection script above or equivalent eBPF tracepoint on nl80211_vendor_cmd.
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 →