← Back to Feed CACHED · 2026-10-08 21:37:15 · CACHE_KEY CVE-2025-39964
CVE-2025-39964 · CWE-362 · Disclosed 2025-10-13

Linux Kernel AF_ALG Concurrent-Write Race Condition (Local Privilege Escalation + Container Escape)

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Leaving the front door unlocked for 14 years because nobody tried the handle until now

CVE-2025-39964 is a race condition in the Linux kernel's AF_ALG socket interface — the userspace API for kernel cryptographic operations — present since kernel 2.6.38 (March 2011). When two threads issue concurrent sendmsg() calls on the same AF_ALG socket, the kernel releases the socket lock while waiting for writable buffer space. A second writer can then modify the shared scatter-gather list state, leaving ctx->merge set to true while cur equals zero. The subsequent write dereferences sg[-1], accessing heap memory *before* the intended array. Researchers Muhammad Alifa Ramdhan and Bing-Jhong Billy Jheng of STAR Labs chained this out-of-bounds access into a usercopy oracle, then an arbitrary kernel write primitive, then overwrote core_pattern to obtain root — and demonstrated container escape since containers share the host kernel. Affected versions span 2.6.38 through unpatched builds of every active stable branch. Fixed upstream in commit 1b34cbbf4f01 (September 2025); stable backports landed in 5.10.246, 5.15.195, 6.1.155, 6.6.109, 6.12.50, and 6.16.10.

The vendor CVSS of 7.8 HIGH (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) is technically accurate for a standard local privilege escalation, but it *under-weights* the real-world blast radius. The CVSS vector's S:U (Scope: Unchanged) ignores the proven container-escape path — the scope absolutely changes when a compromised pod pivots to the host node. CISA added CVE-2025-39964 to the KEV catalog on 2026-09-18 citing active exploitation. Public exploit code exists on GitHub (n1k0oowang/CVE-2025-39964_EXP). The AF_ALG module is compiled into most enterprise kernels (CONFIG_CRYPTO_USER_API=y), so the common advice to blacklist the module does not work. Red Hat explicitly confirmed no viable mitigation short of patching. When you combine proven exploitation, public weaponized code, container escape, OT/ICS exposure (Siemens SIMATIC S7-1500 MFP firmware runs a Linux subsystem with this flaw), and the impossibility of mitigation via module blacklist, the vendor's HIGH underestimates the operational reality.

"KEV-listed kernel race gives any local user root + container escape; patch now."
02 · The Attack Path

6 steps from start to impact.

STEP 01

Obtain unprivileged local access

The attacker needs code execution as any unprivileged user on the target Linux host. In containerized environments this means any compromised pod or CI runner — no host-level shell is required. In traditional server deployments this requires a prior foothold via SSH, web-app RCE, or a compromised service account.
Conditions required:
  • Local code execution as any unprivileged user
  • Target kernel is in the affected range (2.6.38 – unpatched)
Where this breaks in practice:
  • Requires prior initial access — not remotely exploitable without a chained entry vector
  • Hardened SSH configurations, MFA, and EDR may prevent or detect the initial foothold
Detection/coverage: EDR / auditd should log new process creation; anomalous user sessions are a baseline detection.
STEP 02

Open an AF_ALG socket and race two writers

The attacker opens a socket with socket(AF_ALG, SOCK_SEQPACKET, 0), binds it to a hash or skcipher algorithm, then spawns two threads issuing sendmsg() concurrently. The kernel releases the socket lock while waiting for buffer space, allowing the second writer to corrupt the scatter-gather list state. The exploit targets the window where ctx->merge is true but cur is zero.
Conditions required:
  • AF_ALG socket family available (compiled in or loadable)
  • Kernel does not carry the fix commit 1b34cbbf4f01
Where this breaks in practice:
  • AF_ALG is compiled directly into RHEL/CentOS/Ubuntu enterprise kernels — cannot be blacklisted
  • Race window is narrow but the STAR Labs exploit demonstrated reliable winning within seconds
  • Some container runtimes with restrictive seccomp profiles (e.g., default Docker profile) may block socket(AF_ALG, …) — but Kubernetes pods with securityContext.seccompProfile: Unconfined or custom profiles allow it
Detection/coverage: Syscall auditing (auditctl -a always,exit -F arch=b64 -S socket -F a0=38) can flag AF_ALG socket creation; Falco rules can detect socket() with AF_ALG domain.
STEP 03

Trigger out-of-bounds heap read via sg[-1]

Once the race is won, subsequent writes dereference sg[-1], reading metadata from the heap object immediately preceding the scatter-gather array. The attacker crafts heap layout (via controlled allocations) so that this preceding object contains attacker-influenced data. This provides a usercopy oracle — the ability to read arbitrary kernel memory by observing what the kernel copies back to userspace.
Conditions required:
  • Successful race condition (Step 2)
  • Heap spray to position controlled data before the sg array
Where this breaks in practice:
  • Kernel heap randomization (SLAB_FREELIST_RANDOM, SLAB_FREELIST_HARDENED) makes layout control harder but not impossible
  • KASLR must be bypassed — the oracle itself provides the leak
Detection/coverage: KASAN (if enabled) would catch the OOB access, but KASAN is not enabled in production kernels.
STEP 04

Achieve arbitrary kernel write primitive

Using the usercopy oracle to defeat KASLR and map kernel memory layout, the attacker constructs a write-what-where primitive through the corrupted scatter-gather metadata. This is the standard kernel-exploit escalation from info-leak + OOB-write to arbitrary write.
Conditions required:
  • Successful heap oracle (Step 3)
  • Knowledge of target kernel's symbol offsets (public for distro kernels)
Where this breaks in practice:
  • Hardcoded offsets in public PoC limit portability — attacker must adapt to target kernel version
  • CONFIG_CFI_CLANG (Control Flow Integrity) on newer kernels can disrupt ROP/JOP chains
STEP 05

Overwrite core_pattern → root shell

The attacker writes a pipe command (e.g., |/tmp/payload) into /proc/sys/kernel/core_pattern, then triggers a segfault in a child process. The kernel executes the payload as root during core dump handling. The STAR Labs exploit demonstrated this path reliably.
Conditions required:
  • Arbitrary kernel write (Step 4)
  • Writable location for payload binary (typically /tmp)
Where this breaks in practice:
  • Systems with fs.suid_dumpable=0 and restricted core dump settings reduce attack surface but do not prevent the core_pattern overwrite via kernel write
  • AppArmor/SELinux *may* block execution of the payload if the policy is restrictive enough — but the kernel write can also disable LSM enforcement
Detection/coverage: File integrity monitoring on /proc/sys/kernel/core_pattern changes; auditd rule on sysctl writes.
STEP 06

Container escape to host (if containerized)

Because the kernel write occurs in the host kernel's address space (containers share the host kernel), the root shell obtained via core_pattern executes in the host's initial PID/mount namespace — not the container's. The attacker has full host root. From a Kubernetes node, lateral movement to other pods and nodes follows standard post-exploitation playbooks.
Conditions required:
  • Target process is inside a container (Docker, containerd, CRI-O)
  • Container runtime does not block AF_ALG via seccomp
Where this breaks in practice:
  • Default Docker seccomp profile *does* block AF_ALG socket creation — but many K8s deployments run with relaxed or no seccomp
  • gVisor or Kata Containers (VM-based isolation) prevent host kernel exploitation entirely
Detection/coverage: Container escape detection via Falco / Sysdig rules monitoring namespace transitions; unexpected processes in host PID namespace.
03 · Compensating Control

1
CRITICAL 9.0→IGNORE 0.0
SEVERITY REDUCED
Apply kernel livepatch immediately — KernelCare, Canonical Livepatch, and RHEL kpatch all carry fixes for CVE-2025-39964. Livepatching eliminates the vulnerability without a reboot, making it the fastest path to remediation. Deploy within the noisgate CRITICAL mitigation SLA of ≤3 days. Prioritize Kubernetes nodes, hypervisors, and CI runners.
2
CRITICAL 9.0→HIGH 7.0
SEVERITY REDUCED
Enforce restrictive seccomp profiles on all containers — The default Docker seccomp profile blocks socket(AF_ALG, …). Ensure all Kubernetes pods run with RuntimeDefault or a custom profile that denies AF_ALG socket creation (family 38). This breaks Step 2 of the attack chain inside containers. Does NOT protect host-level processes. Deploy within 3 days on all container runtimes.
3
CRITICAL 9.0→HIGH 7.8
SEVERITY REDUCED
Deploy Falco/auditd rules to detect AF_ALG socket creation — Add a Falco rule or auditd syscall filter for socket() calls with AF_ALG (family=38). This provides detection-in-depth: any process opening an AF_ALG socket on a production server is anomalous in most workloads. Alert and investigate immediately. Deploy within 3 days.
4
CRITICAL 9.0→IGNORE 0.0
SEVERITY REDUCED
Schedule full kernel update with reboot — Apply vendor kernel updates (RHEL errata, Debian DSA-6053-1, Ubuntu USN updates) and reboot. This is the definitive fix. For systems that cannot livepatch, schedule within the noisgate CRITICAL remediation SLA of ≤90 days, but given KEV status, prioritize within days to weeks. Coordinate maintenance windows for OT/ICS (Siemens S7-1500) separately with vendor guidance.
5
CRITICAL 9.0→MEDIUM 5.5
SEVERITY REDUCED
Isolate unpatched Siemens SIMATIC S7-1500 MFP controllers — Siemens has not yet shipped a firmware fix. Restrict network access to affected PLCs per IEC 62443 zone/conduit model. Disable unnecessary Linux subsystem services on the MFP firmware. Monitor for anomalous process execution on the controller. This reduces — but does not eliminate — the risk of local exploitation on the OT device.
What doesn't work
  • Blacklisting the af_alg kernel module — AF_ALG is compiled directly into enterprise kernels (CONFIG_CRYPTO_USER_API=y) on RHEL, CentOS, Ubuntu, Debian, and SUSE. modprobe -r and blacklist entries have no effect. Red Hat explicitly confirmed this.
  • Disabling core dumps (ulimit -c 0) — While the public PoC uses core_pattern overwrite, the arbitrary kernel write primitive can target any kernel data structure. Disabling core dumps blocks one payload delivery method but not the underlying write-what-where capability.
  • Namespace isolation alone — User namespaces do not prevent AF_ALG socket access in most configurations. The vulnerability operates at the kernel level, below namespace boundaries. Only VM-based isolation (gVisor, Kata Containers) provides a real boundary.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed. CISA added CVE-2025-39964 to the KEV catalog on 2026-09-18 citing evidence of active exploitation. Ransomware usage listed as *Unknown*.
Proof-of-ConceptPublic. n1k0oowang/CVE-2025-39964_EXP on GitHub contains exploit.c with a compiled LPE. STAR Labs researchers (Muhammad Alifa Ramdhan, Bing-Jhong Billy Jheng) demonstrated a full root + container escape chain via Google's kernelCTF program ($113,337 bounty). suominen/CVE-2025-39964 tracks distro patch status.
EPSS0.01276 (user-supplied). This is a modest probability reflecting the local-access prerequisite, but EPSS historically lags KEV listings — exploitation is confirmed regardless of the score.
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H → 7.8 HIGH. The S:U (Scope Unchanged) is arguably wrong given proven container escape. Red Hat scored it 7.3 HIGH under their own assessment.
Affected VersionsLinux kernel 2.6.38 (March 2011) through all unpatched branches. That is a 14-year window. Siemens SIMATIC S7-1500 CPU 1518(F)-4 PN/DP MFP firmware V3.1.6 also affected (runs Linux subsystem).
Fixed VersionsUpstream commit 1b34cbbf4f01 (2025-09-16). Stable backports: 5.10.246, 5.15.195, 6.1.155, 6.6.109, 6.12.50, 6.16.10. Debian: bookworm 6.1.187-1, trixie 6.12.111-1. RHEL: errata shipped 2026-09-22 to 2026-09-24 across RHEL 7 ELS–10.
KEV DatesAdded: 2026-09-18. Required action (BOD 26-04): 2026-09-21. Three-day remediation window for FCEB agencies.
Researcher / DiscoveryMuhammad Alifa Ramdhan and Bing-Jhong Billy Jheng of STAR Labs, via Google kernelCTF. Bounty: $113,337.
Scanning / ExposureAF_ALG is compiled into enterprise kernels (CONFIG_CRYPTO_USER_API=y) — not a loadable module. Red Hat confirmed blacklisting is impossible. Every unpatched Linux host in your fleet is exposed if an attacker achieves local access.
OT / ICS ImpactCISA issued ICS advisory ICSA-26-209-04 for Siemens SIMATIC S7-1500 CPU 1518(F)-4 PN/DP MFP. Siemens is preparing fixes; no patch available yet for the PLC firmware.

Sources.

  1. CISA KEV Catalog Entry
  2. CybersecurityNews — 14-Year-Old Linux Kernel Flaw
  3. Debian Security Tracker
  4. Red Hat CVE Page
  5. TuxCare — CISA KEV Linux Kernel Trio
  6. n1k0oowang Exploit Code (GitHub)
  7. CISA ICS Advisory — Siemens SIMATIC S7-1500
  8. CloudLinux Patch Status
05 · The Call

Final Verdict
↑ UPGRADED to CRITICAL (9.0/10)

Why this verdict

  • Active exploitation confirmed. CISA KEV listing on 2026-09-18 with evidence of in-the-wild use overrides any friction-based downgrade. When exploitation is confirmed, theoretical barriers are moot — someone is already landing this chain.
  • Public weaponized exploit code. The n1k0oowang GitHub repo provides compiled exploit code, and STAR Labs published detailed research. The bar for attacker adoption is low — compile, adapt offsets for target distro kernel, run.
  • Container escape transforms blast radius from host to fleet. The CVSS vector's S:U is incorrect for containerized environments. A compromised pod → host root → node takeover → lateral to other pods/nodes. In Kubernetes clusters, one exploited container can cascade to full cluster compromise.
  • Role multiplier: The affected component is the Linux kernel itself. 100% of Linux hosts run it. High-value roles include: (1) Kubernetes nodes — container escape gives fleet-scale blast radius, chain succeeds, outcome is cluster takeover; (2) KVM hypervisors — guest-to-host escape path if guest has AF_ALG access, outcome is hypervisor compromise; (3) CI/CD runners — any build job can escalate, outcome is supply-chain pivot; (4) OT/ICS controllers — Siemens SIMATIC S7-1500 MFP runs affected Linux kernel, outcome is operational/safety impact. The kernel is canonically a high-value-role component (≥10% of installs ARE the high-value role), setting a CRITICAL floor.
  • No viable mitigation short of patching. AF_ALG is compiled in, not a module. Red Hat explicitly stated no mitigation meets their criteria. You cannot reduce exposure without patching the kernel or deploying a livepatch.
  • 14-year exposure window. Every kernel since 2.6.38 (2011) is affected. The installed base of vulnerable hosts across enterprise Linux fleets is effectively universal for anyone not running the September 2025+ stable backports.

Why not higher?

A 9.0 is already near the top of the scale. A 10.0 would require unauthenticated remote exploitation without user interaction. This vulnerability requires local access (AV:L) — even in containerized environments, the attacker must first achieve code execution inside a container. The race condition, while reliable, is not instant and requires a compiled exploit adapted to the target kernel version's symbol offsets.

Why not lower?

Despite the local-access prerequisite, downgrading below CRITICAL would ignore three hard facts: (1) CISA has confirmed active exploitation — the chain works in production, (2) the affected component is the kernel itself with no scope boundary protecting the host from container compromise, and (3) there is no compensating control that reduces exposure without a kernel update. A HIGH rating would imply defenders have 30 days for mitigation, which contradicts the KEV's 3-day action window and the reality of confirmed exploitation.

06 · Verification

Crowdsourced verification payload.

Run this script on each target Linux host as root (or with sudo). It checks whether the running kernel version is in the patched range. Invoke with: sudo bash check_cve_2025_39964.sh. No arguments required. Returns exit code 0 for PATCHED, 1 for VULNERABLE, 2 for UNKNOWN.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/bin/bash
# CVE-2025-39964 Checker — AF_ALG concurrent-write race condition
# Checks running kernel version against known-fixed stable branches.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

KERNEL=$(uname -r)
VERSION=$(echo "$KERNEL" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')

if [ -z "$VERSION" ]; then
  echo "UNKNOWN — could not parse kernel version from: $KERNEL"
  exit 2
fi

MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3)

# version_gte: returns 0 if $1.$2.$3 >= $4.$5.$6
version_gte() {
  local a1=$1 a2=$2 a3=$3 b1=$4 b2=$5 b3=$6
  if (( a1 > b1 )); then return 0; fi
  if (( a1 < b1 )); then return 1; fi
  if (( a2 > b2 )); then return 0; fi
  if (( a2 < b2 )); then return 1; fi
  if (( a3 >= b3 )); then return 0; fi
  return 1
}

echo "Kernel: $KERNEL (parsed: $MAJOR.$MINOR.$PATCH)"
echo "CVE: CVE-2025-39964 — AF_ALG concurrent-write race"
echo "Fix commit: 1b34cbbf4f01 (upstream 2025-09-16)"
echo "---"

# Fixed stable versions:
#   5.10.246, 5.15.195, 6.1.155, 6.6.109, 6.12.50, 6.16.10
# Kernels < 2.6.38 are NOT affected (feature did not exist).
# Kernels >= 6.17-rc7 / 6.17+ carry the fix.

if version_gte $MAJOR $MINOR $PATCH 6 17 0; then
  echo "PATCHED — kernel $VERSION is >= 6.17 (fix merged in 6.17-rc7)"
  exit 0
elif (( MAJOR == 6 && MINOR == 16 )); then
  if version_gte $MAJOR $MINOR $PATCH 6 16 10; then
    echo "PATCHED — kernel $VERSION is >= 6.16.10"
    exit 0
  fi
elif (( MAJOR == 6 && MINOR == 12 )); then
  if version_gte $MAJOR $MINOR $PATCH 6 12 50; then
    echo "PATCHED — kernel $VERSION is >= 6.12.50"
    exit 0
  fi
elif (( MAJOR == 6 && MINOR == 6 )); then
  if version_gte $MAJOR $MINOR $PATCH 6 6 109; then
    echo "PATCHED — kernel $VERSION is >= 6.6.109"
    exit 0
  fi
elif (( MAJOR == 6 && MINOR == 1 )); then
  if version_gte $MAJOR $MINOR $PATCH 6 1 155; then
    echo "PATCHED — kernel $VERSION is >= 6.1.155"
    exit 0
  fi
elif (( MAJOR == 5 && MINOR == 15 )); then
  if version_gte $MAJOR $MINOR $PATCH 5 15 195; then
    echo "PATCHED — kernel $VERSION is >= 5.15.195"
    exit 0
  fi
elif (( MAJOR == 5 && MINOR == 10 )); then
  if version_gte $MAJOR $MINOR $PATCH 5 10 246; then
    echo "PATCHED — kernel $VERSION is >= 5.10.246"
    exit 0
  fi
fi

# Check if kernel predates the vulnerable code (< 2.6.38)
if (( MAJOR < 2 )) || { (( MAJOR == 2 )) && (( MINOR < 6 )); } || \
   { (( MAJOR == 2 )) && (( MINOR == 6 )) && (( PATCH < 38 )); }; then
  echo "PATCHED — kernel $VERSION predates AF_ALG (introduced in 2.6.38)"
  exit 0
fi

# Check for distro-patched kernels (RHEL, Debian, Ubuntu often backport)
# Look for the actual fix in the kernel config/source
if [ -f /boot/config-$(uname -r) ]; then
  # If CONFIG_CRYPTO_USER_API is not set, AF_ALG is not available
  if ! grep -q 'CONFIG_CRYPTO_USER_API=y' /boot/config-$(uname -r) 2>/dev/null && \
     ! grep -q 'CONFIG_CRYPTO_USER_API=m' /boot/config-$(uname -r) 2>/dev/null; then
    echo "PATCHED — AF_ALG (CONFIG_CRYPTO_USER_API) is not enabled in this kernel"
    exit 0
  fi
fi

# Check for distro errata markers
if command -v rpm &>/dev/null; then
  RPM_KERNEL=$(rpm -q kernel-$(uname -r) 2>/dev/null || rpm -q kernel-core-$(uname -r) 2>/dev/null || true)
  if [ -n "$RPM_KERNEL" ]; then
    echo "NOTE: RPM kernel package: $RPM_KERNEL"
    echo "Check vendor errata (RHSA/ELSA/ALSA) for CVE-2025-39964 fix status."
  fi
elif command -v dpkg &>/dev/null; then
  DEB_KERNEL=$(dpkg -l 'linux-image-*' 2>/dev/null | grep "$(uname -r)" | awk '{print $2, $3}' || true)
  if [ -n "$DEB_KERNEL" ]; then
    echo "NOTE: Debian/Ubuntu kernel: $DEB_KERNEL"
    echo "Check DSA-6053-1 / DLA-4379-1 / USN advisories for fix status."
  fi
fi

echo "VULNERABLE — kernel $VERSION does not match any known-fixed stable version"
echo "Action: Apply vendor kernel update or livepatch immediately (KEV-listed, active exploitation)."
exit 1