
CVE-2025-38502 के लिए शोध रिपॉज़िटरी, जो Linux kernel BPF cgroup local storage में tail calls के माध्यम से out-of-bounds access को सक्षम बनाता है, जिससे local privilege escalation संभव होता है।

Abraxas Labs · abraxaslabs.tech · github.com/abraxas · @abraxas_null
Linux kernel BPF cgroup local storage out-of-bounds access via tail calls
| CVE | CVE-2025-38502 |
| CWE | CWE-125 — Out-of-bounds Read |
| Vendor | Linux kernel |
| Component | kernel/bpf/core.c, include/linux/bpf.h (cgroup local storage + tail calls) |
| Impact | Local kernel memory corruption; privilege escalation is in scope on unpatched kernels |
| Attack vector | Local (AV:L) |
| Privileges | Low (PR:L) — a process that can load BPF programs of type CGROUP_SKB (or equivalent cgroup-attached programs) |
| User interaction | None |
| CVSS 3.1 (kernel.org CNA) | 7.8 HIGH — CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CVSS 3.1 (NVD) | 7.1 HIGH — CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H |
| Public | 16 August 2025 |
| Upstream fix | abad3d0 in 6.17-rc1; backported to 6.16.1, 6.12.46, 6.6.105, 6.1.151, 5.15.192 |
Research / educational use only. Do not run, deploy, or use material in this repository against any host unless you have explicit written permission from both the party hosting this repository and the owner of the target systems. Found in the wild.
The source filename CVE-2025-3850-Linux-LPE-Abaraxas-Labs.c truncates the identifier. The published record is CVE-2025-38502. There is no Linux CVE CVE-2025-3850.
Lonial reported that cgroup BPF local storage can be accessed out of bounds across a tail call.
The eBPF verifier type-checks each program in isolation. At runtime, bpf_get_local_storage() does not look up the currently executing program's map. It reads the cgroup-storage pointer out of current->bpf_ctx → bpf_cg_run_ctx → prog_item->cgroup_storage[]. That slot is filled from the originally attached program, not from the program that was tail-called into.
If program A (small BPF_MAP_TYPE_CGROUP_STORAGE value size) tail-calls program B (large value size), B's bpf_get_local_storage() still returns A's smaller buffer. Accesses the verifier allowed against B's map then walk off the end of A's allocation.
The defect was introduced in Linux 5.9 by 7d9c342 (bpf: Make cgroup storages shared between programs on the same cgroup). It was fixed by extending bpf_map_owner with a storage_cookie[] so tail-call combinations are only accepted when the callee uses the same cgroup-storage maps as the caller, or uses none.
This is a local kernel heap out-of-bounds access. Severity scoring varies by vendor because they disagree on whether the primitive is “read-only DoS” or full memory corruption:
What that means in practice:
struct bpf_array sprayed into the same slab/order) can be corrupted.map->ops, hijack a helper, commit_creds / namespace switch). That is why this tree labels the issue LPE. Red Hat's lower score reflects their product-specific assessment, not the absence of the bug.The bug does not require a network-facing service. It is local. It does not require a TTY, a setuid helper, or user interaction.
Two cgroup BPF programs, each with its own BPF_MAP_TYPE_CGROUP_STORAGE (shared flavor, BPF_CGROUP_STORAGE_SHARED):
| Program | Role | Storage value size |
|---|---|---|
| A | attached / tail-call caller | small (e.g. fits a given kmalloc order) |
| B | tail-call target | large (verifier allows accesses up to this size) |
The verifier checks A against A's map and B against B's map. Both pass.
At run time the helper does:
ctx = container_of(current->bpf_ctx, struct bpf_cg_run_ctx, run_ctx);
storage = ctx->prog_item->cgroup_storage[stype];
if (stype == BPF_CGROUP_STORAGE_SHARED)
ptr = &READ_ONCE(storage->buf)->data[0];
else
ptr = this_cpu_ptr(storage->percpu_buf);
prog_item is the array entry for the program that started the cgroup run, not the program currently executing after bpf_tail_call. B therefore operates on A's storage object.
bpf_cgroup_storage_alloc() sizes the backing buffer from the map's value_size. A's buffer is too small for B's verified accesses. The result is a classic type-confusion of map identity across a control-transfer — the same family of bugs as other BPF “helper sees a different map than the verifier did” issues.
Commit 7d9c342 made cgroup storages shared between programs attached to the same cgroup. That sharing is what makes the run-context slot a single pointer rather than a per-program lookup, and is why kernels before 5.9 are not affected.
BPF_PROG_TEST_RUN on a BPF_PROG_TYPE_CGROUP_SKB program allocates cgroup storage for the duration of the test. That allocation sits on the kernel heap next to whatever else was recently freed in the same size class — including struct bpf_array maps whose value_size was chosen to land in the same kmalloc order. An OOB from the storage buffer can therefore reach bpf_map fields (ops, RCU list, value[]) of a neighbouring array map.
That heap-layout detail is why a “mere OOB read” advisory and an LPE write-up can describe the same CVE.
Introduced: Linux 5.9 (7d9c3427894fe70d1347b4820476bf37736d2ff0)
Unaffected: all kernels before 5.9
One-liner:
/* CVE-2025-38502: affected 5.9–5.15.191, 5.16–6.1.150, 6.2–6.6.104, 6.7–6.12.45, 6.13–6.16.0; fixed in 5.15.192, 6.1.151, 6.6.105, 6.12.46, 6.16.1, 6.17-rc1 */
Still open in some stables: Debian's kernel tracker listed 5.10 upstream-stable / bullseye 5.10 as needed. Do not assume every 5.10.y is patched.
Distro ABI numbers lie. Ubuntu 5.15.0-163 is a patched 5.15 even though 5.15.0 looks older than upstream 5.15.192. Compare the package changelog / USN / DSA / ALAS / RHSA, not uname -r against the table above.
Any distribution that shipped a kernel in the ranges above was in scope until it backported abad3d0 (or the matching stable commit). This is generic BPF code, not a distro-specific patch.
Ubuntu 26.04 / 25.10 are listed not affected (they branched after the fix). Ubuntu 25.04 reached EOL still needed.
A host can match an affected version and still not be reachable. Useful checks:
unprivileged_bpf_disabled=1 is not a complete fix — a user with BPF capability can still hit the bug — but it removes the unprivileged path.
Upstream commit abad3d0bad72a52137e0c350c59542d75ae4f513 (bpf: Fix oob access in cgroup local storage, Daniel Borkmann).
struct bpf_map_owner gains a storage_cookie[] array. On tail-call target update, the kernel now:
bpf_get_local_storage() — require the callee's cgroup-storage maps to be exactly the caller's maps (same cookies).Mismatching value sizes can no longer be composed behind the verifier's back. Each program is still verified alone; the new check is on the edge between them.
Do not cherry-pick the commit onto an arbitrary tree without the surrounding BPF owner/cookie helpers. Use the stable backport for your series.
uname -r
# Compare against the table above, then against your distro advisory —
# Ubuntu/Debian ABI numbers are not upstream stable numbers.
grep -E 'CONFIG_BPF_SYSCALL|CONFIG_CGROUP_BPF' \
/boot/config-$(uname -r) /proc/config.gz 2>/dev/null
sysctl kernel.unprivileged_bpf_disabled
# 0 = unprivileged bpf allowed (widest exposure)
# 1 = disabled after first privileged use, or fully disabled depending on kernel
# 2 = disabled (admin can re-enable)
Confirm the package, not just the version string:
# Debian / Ubuntu
apt changelog linux-image-$(uname -r) 2>/dev/null | grep -i 38502
# RHEL family
rpm -q --changelog kernel | grep -i 38502
A kernel ≥ 6.17, or a stable listed in the “first fixed” column, or a distro package from the advisory table, is the actual close-out.
abad3d0 / the stable equivalent. This is the only complete fix.kernel.unprivileged_bpf_disabled=1 (or 2) to drop unprivileged loaders.CAP_BPF, CAP_PERFMON, and CAP_SYS_ADMIN on untrusted users and containers.seccomp, LSM, or dropping those caps in the runtime).BPF_PROG_TEST_RUN is enough to exercise the allocation path; a local attacker supplies the programs.CVE-2025-38502/
├── README.md
├── banner.png
├── CVE-2025-3850-Linux-LPE-Abaraxas-Labs.c
└── ebpf_lpe.h
| File | What it is |
|---|---|
banner.png | README banner (Abraxas Labs / CVE-2025-38502) |
CVE-2025-3850-Linux-LPE-Abaraxas-Labs.c | Research source recovered in the wild (filename truncates the CVE id) |
ebpf_lpe.h | Shared BPF instruction constructors, map helpers, and kernel-offset macros used by that source |
This directory documents the vulnerability and holds the corresponding research tree. It is not a drop-in exploit kit: kernel gadget symbols (ARRAY_MAP_OPS_OFF, COMMIT_CREDS, …) are compile-time inputs for a specific vmlinux, and running the program against a live kernel is out of scope for this README.
CVE / NVD
Upstream
7d9c342 — bpf: Make cgroup storages shared between programs on the same cgroupabad3d0 — bpf: Fix oob access in cgroup local storageStable backports
Distros
Abraxas Labs — research / authorized testing only
This repository is for research and education.
Do not compile, run, deploy, or otherwise use the code here against any system unless you have explicit written authorization from both the party hosting this repository and the owner of the target. Unauthorized access to computer systems is a crime.
The authors and Abraxas Labs provide this material as-is, with no warranty that it is complete, correct, or safe to execute. Kernel exploitation research can panic a machine, corrupt filesystems, and lose data. You assume that risk.
Found in the wild.
| Source | Score | Integrity | Notes |
|---|
| kernel.org CNA / cve.org | 7.8 HIGH | High | C:H/I:H/A:H — treats the bug as full local impact |
| NVD | 7.1 HIGH | None | C:H/I:N/A:H — confidentiality + availability |
| Ubuntu | Medium (7.1) | — | USN-7909 |
| Red Hat | 4.0 LOW | None | C:N/I:N/A:L — rated as limited availability |
| Amazon Linux | 4.0 Medium | None | same vector as Red Hat |
| SUSE | 6.1 Moderate | None | some SLE 15 streams marked WONTFIX |
| Series | Affected | First fixed |
|---|
| 5.9 – 5.15 | 5.9 through 5.15.191 | 5.15.192 (c1c74584…) |
| 5.16 – 6.1 | 5.16 through 6.1.150 | 6.1.151 (66da7cee…) |
| 6.2 – 6.6 | 6.2 through 6.6.104 | 6.6.105 (7acfa07c…) |
| 6.7 – 6.12 | 6.7 through 6.12.45 | 6.12.46 (41688d1f…) |
| 6.13 – 6.16 | 6.13 through 6.16.0 | 6.16.1 (19341d5c…) |
| mainline | until the fix landed | 6.17-rc1 (abad3d0b…) |
| Distro | Releases / kernels that were in range |
|---|
| Ubuntu | 22.04 LTS (5.15), 24.04 LTS (6.8), 25.04 (EOL still needed). 20.04 HWE 5.15. |
| Debian | 11 bullseye (5.10), 12 bookworm (6.1), 13 trixie (6.12) |
| RHEL 9 / 10, Rocky, Alma, Fedora | RHEL 9 ≈ 5.14; RHEL 10 ≈ 6.12; Fedora rolling 5.9–6.16 |
| SUSE / openSUSE | SLE Micro 5.3/5.4; some SLE 15 streams WONTFIX |
| Amazon Linux 2023 | default kernel and kernel6.12 |
| Amazon Linux 2 extras | 5.10 extra (no fix planned) and 5.15 extra |
| Arch, Gentoo, Tumbleweed | rolling kernels between 5.9 and the 6.16.1 / 6.17-rc1 fix |
| Distro | Fixed package (indicative) | Advisory |
|---|
| Ubuntu 22.04 | linux 5.15.0-163.173 | USN-7909 |
| Ubuntu 24.04 | linux 6.8.0-106.106 | same |
| Debian 12 | linux 6.1.153-1 | DSA-6009-1 |
| Debian 13 | linux 6.12.48-1 | DSA-6008-1 |
| Debian 11 (6.1 backport) | linux-6.1 6.1.153-1~deb11u1 | DLA-4328-1 |
| Amazon Linux 2023 | kernel / kernel6.12, 2025-09-29 | ALAS2023-2025-1210 / 1208 |
| Amazon Linux 2 5.15 extra | 2025-09-29 | ALAS2KERNEL-5.15-2025-091 |
| Condition | Why it matters |
|---|
CONFIG_BPF_SYSCALL=y | bpf(2) must exist |
CONFIG_CGROUP_BPF=y | cgroup-attached programs and cgroup local storage |
kernel.unprivileged_bpf_disabled | 0 allows unprivileged program load; 1/2 require CAP_BPF / CAP_PERFMON / CAP_SYS_ADMIN |
| Lockdown / LSM / seccomp | may block BPF_PROG_LOAD or BPF_PROG_TEST_RUN |
BPF_PROG_TYPE_CGROUP_SKB (or other cgroup program types that carry local storage) | the run context that holds cgroup_storage[] |