
Repository di ricerca per CVE-2025-38502, un accesso out-of-bounds alla memoria locale del cgroup BPF del kernel Linux tramite tail call che consente l'escalation locale dei privilegi.

Abraxas Labs · abraxaslabs.tech · github.com/abraxas · @abraxas_null
Accesso out-of-bounds alla cgroup local storage di BPF del kernel Linux tramite tail call
| CVE | CVE-2025-38502 |
| CWE | CWE-125 — Out-of-bounds Read |
| Vendor | Linux kernel |
| Componente | kernel/bpf/core.c, include/linux/bpf.h (cgroup local storage + tail call) |
| Impatto | Corruzione locale della memoria del kernel; l'escalation di privilegi rientra nello scope su kernel non patchati |
| Vettore di attacco | Locale (AV:L) |
| Privilegi | Bassi (PR:L) — un processo in grado di caricare programmi BPF di tipo CGROUP_SKB (o programmi equivalenti collegati a cgroup) |
| Interazione utente | Nessuna |
| 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 |
| Pubblico | 16 agosto 2025 |
| Fix upstream | abad3d0 in 6.17-rc1; backportato a 6.16.1, 6.12.46, 6.6.105, 6.1.151, 5.15.192 |
Solo per ricerca / uso educativo. Non eseguire, distribuire o utilizzare il materiale presente in questo repository contro qualsiasi host, a meno che tu non abbia esplicita autorizzazione scritta sia dal soggetto che ospita questo repository sia dal proprietario dei sistemi target. Trovato in the wild.
Il nome del file sorgente CVE-2025-3850-Linux-LPE-Abaraxas-Labs.c tronca l'identificatore. Il record pubblicato è CVE-2025-38502. Non esiste alcun CVE Linux CVE-2025-3850.
Lonial ha segnalato che la cgroup BPF local storage può essere acceduta out of bounds attraverso una tail call.
Il verifier eBPF esegue il type-check di ciascun programma in isolamento. A runtime, bpf_get_local_storage() non cerca la map del programma attualmente in esecuzione. Legge il puntatore alla cgroup-storage da current->bpf_ctx → bpf_cg_run_ctx → prog_item->cgroup_storage[]. Quello slot viene riempito dal programma originariamente collegato, non dal programma in cui è stata effettuata la tail call.
Se il programma A (con BPF_MAP_TYPE_CGROUP_STORAGE di dimensione value piccola) effettua una tail call verso il programma B (dimensione value grande), la bpf_get_local_storage() di B restituisce comunque il buffer più piccolo di A. Gli accessi che il verifier aveva consentito sulla map di B finiscono quindi oltre la fine dell'allocazione di A.
Il difetto è stato introdotto in Linux 5.9 da 7d9c342 (bpf: Make cgroup storages shared between programs on the same cgroup). È stato corretto estendendo bpf_map_owner con un storage_cookie[], in modo che le combinazioni di tail call siano accettate solo quando il callee usa le stesse cgroup-storage map del caller, oppure non ne usa alcuna.
Si tratta di un accesso out-of-bounds locale all'heap del kernel. Il punteggio di severità varia tra i vendor perché non concordano se la primitiva sia un "DoS in sola lettura" o una vera e propria corruzione di memoria:
| Fonte | Punteggio | Integrità | Note |
|---|---|---|---|
| kernel.org CNA / cve.org | 7.8 HIGH | Alta | C:H/I:H/A:H — tratta il bug come impatto locale completo |
| NVD | 7.1 HIGH | Nessuna | C:H/I:N/A:H — riservatezza + disponibilità |
| Ubuntu | Medium (7.1) | — | USN-7909 |
| Red Hat | 4.0 LOW | Nessuna | C:N/I:N/A:L — valutato come disponibilità limitata |
| Amazon Linux | 4.0 Medium | Nessuna | stesso vettore di Red Hat |
| SUSE | 6.1 Moderate | Nessuna | alcuni stream SLE 15 marcati WONTFIX |
Cosa significa in pratica:
struct bpf_array spruzzata nello stesso slab/order) possono essere corrotti.map->ops, hijack di un helper, commit_creds / cambio di namespace). È per questo che questo repository etichetta il problema come LPE. Il punteggio più basso di Red Hat riflette la loro valutazione specifica per prodotto, non l'assenza del bug.Il bug non richiede un servizio esposto in rete. È locale. Non richiede una TTY, un helper setuid o l'interazione dell'utente.
Due programmi BPF cgroup, ciascuno con la propria BPF_MAP_TYPE_CGROUP_STORAGE (variante shared, BPF_CGROUP_STORAGE_SHARED):
| Programma | Ruolo | Dimensione value della storage |
|---|---|---|
| A | collegato / caller della tail call | piccola (ad es. compatibile con un dato kmalloc order) |
| B | target della tail call | grande (il verifier consente accessi fino a questa dimensione) |
Il verifier controlla A rispetto alla map di A e B rispetto alla map di B. Entrambi passano.
A runtime l'helper esegue:
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 è la voce dell'array relativa al programma che ha avviato la cgroup run, non al programma attualmente in esecuzione dopo bpf_tail_call. B opera quindi sull'oggetto storage di A.
bpf_cgroup_storage_alloc() dimensiona il buffer di supporto in base alla value_size della map. Il buffer di A è troppo piccolo per gli accessi verificati di B. Il risultato è una classica type-confusion dell'identità della map attraverso un trasferimento di controllo — la stessa famiglia di bug di altre problematiche BPF in cui "l'helper vede una map diversa da quella vista dal verifier".
Il commit 7d9c342 ha reso le cgroup storage condivise tra programmi collegati allo stesso cgroup. È questa condivisione che rende lo slot del run-context un singolo puntatore anziché una ricerca per-programma, ed è il motivo per cui i kernel precedenti alla 5.9 non sono interessati.