
Proof-of-concept exploit per CVE-2026-31431, un'escalation dei privilegi locale nel kernel Linux tramite scrittura nella page cache di AF_ALG, che consente di ottenere i privilegi di root sulle principali distribuzioni.
algif_aead ("Copy Fail")
Autore: Van Glenndon Enad
Scoperta Originale: Theori / Xint Code Research Team (Taeyang Lee)
Pubblicato: 29 aprile 2026
Gravità: Alta
Punteggio CVSS v3.1: 7.8
Vettore CVSS v3.1: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-787 (Scrittura Fuori dai Limiti), CWE-269 (Gestione Impropria dei Privilegi)
CVE-2026-31431, soprannominata pubblicamente "Copy Fail," è una vulnerabilità di escalation locale dei privilegi (LPE) ad alta gravità nel modulo algif_aead del kernel Linux — l'interfaccia di cifratura AEAD dell'API crittografica userspace del kernel (AF_ALG). Il difetto ha origine da un'ottimizzazione delle prestazioni (operazione in-place) introdotta nel 2017 tramite il commit 72548b093ee3, che ha inavvertitamente consentito di inserire pagine di file supportate dalla page cache nello scatterlist di destinazione scrivibile durante un'operazione crittografica AEAD.
Combinando tre sottosistemi del kernel — i socket AF_ALG, la chiamata di sistema splice() e il comportamento di scrittura scratch dell'algoritmo authencesn — un utente locale non privilegiato può eseguire una scrittura controllata di 4 byte nella page cache di qualsiasi file leggibile. Prendendo di mira un binario setuid come /usr/bin/su, questa scrittura corrompe l'immagine eseguibile in memoria senza modificare il file su disco, aggirando così gli strumenti di integrità dei file su disco. L'escalation di privilegi risultante a root è deterministica — nessuna condizione di gara, nessun offset del kernel specifico per distribuzione e nessun privilegio speciale richiesto. Uno sfruttamento PoC Python di 732 byte rilasciato pubblicamente fornisce shell root su Ubuntu, Amazon Linux, RHEL e SUSE in una singola esecuzione non modificata.
| Componente | Dettagli |
|---|---|
| Sottosistema Interessato | crypto/algif_aead.c — interfaccia AEAD AF_ALG del kernel Linux |
| Vulnerabilità Introdotta | Kernel Linux 4.14 (2017), commit 72548b093ee38a6d4f2a19e6ef1948ae05c181f7 |
| Versioni Corrette | 6.18.22, 6.19.12, 7.0 |
| Commit di Correzione | a664bf3d603dc3bdcf9ae47cc21e0daec706d7a5 |
| Distribuzioni Verificate | Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, SUSE 16 |
| Implicitamente Interessate | Debian, Arch, Fedora, Rocky, AlmaLinux, Oracle Linux e qualsiasi distribuzione che esegua un kernel non corretto compilato dal 2017 |
La vulnerabilità è stata silenziosamente presente in ogni distribuzione Linux mainstream per quasi nove anni. Secondo Theori, AF_ALG è abilitato nella configurazione del kernel predefinita di praticamente ogni distribuzione, il che significa che non sono necessari flag di compilazione o configurazioni speciali affinché un sistema sia vulnerabile.
Il kernel Linux espone primitive crittografiche allo spazio utente tramite l'interfaccia socket AF_ALG (crypto/algif_aead.c). Nel 2017, è stata integrata un'ottimizzazione delle prestazioni che consentiva a algif_aead di eseguire operazioni AEAD in-place — riutilizzando il buffer di memoria sorgente come destinazione — per evitare copie di dati non necessarie.
Il difetto emerge quando lo spazio utente fornisce input al socket AF_ALG tramite la chiamata di sistema splice(). In questo caso, le pagine inserite nello scatterlist sorgente sono pagine della page cache — memoria condivisa gestita dal kernel che supporta il file sottoposto a splice. A causa dell'ottimizzazione in-place che imposta req->src = req->dst, queste pagine della page cache finiscono nello scatterlist di destinazione scrivibile. L'algoritmo authencesn esegue successivamente una scrittura scratch a dst[assoclen + cryptlen], che si risolve in un offset all'interno di quelle pagine della page cache — scrivendo di fatto dati controllati dall'attaccante nell'immagine in memoria del file sottoposto a splice.
Poiché la page cache è condivisa sull'intero host, inclusi i container, una scrittura da un processo influisce sulle pagine memorizzate nella cache di quel file per ogni processo e container sullo stesso kernel.
La modifica incriminata in algif_aead.c ha impostato req->src = req->dst e ha concatenato le pagine tag dallo scatterlist sorgente nello scatterlist di output tramite sg_chain():
/* ottimizzazione in-place del 2017 — commit 72548b093ee3 */
req->src = req->dst; /* sorgente == destinazione */
sg_chain(dst, n + 1, src_tag); /* pagine tag concatenate in dst scrivibile */
Quando splice() viene utilizzato per fornire un file al socket, le pagine dello scatterlist sono supportate dalla page cache, non da memoria anonima privata. Concatenarle nello scatterlist dst scrivibile viola il presupposto che la destinazione sia memoria privata scrivibile.
authencesnIl template authencesn scrive un valore scratch del numero di sequenza (seqno_lo, byte 4–7 dell'AAD) a dst[assoclen + cryptlen]. Poiché dst ora contiene pagine della page cache del file sottoposto a splice, questa scrittura atterra a un offset controllato dall'attaccante all'interno dell'immagine in memoria del file:
/* scrittura scratch authencesn — offset determinato da assoclen + cryptlen */
scatterwalk_map_and_copy(seqno, dst,
req->assoclen + req->cryptlen,
sizeof(seqno), 1); /* scrive nella page cache */
I 4 byte scritti corrispondono a seqno_lo, che l'attaccante controlla tramite il payload AAD inviato tramite sendmsg().
Socket AF_ALG (SOCK_SEQPACKET)
│
│ splice() — consegna pagine supportate da file nel socket
▼
Ottimizzazione in-place algif_aead
│ req->src = req->dst
│ le pagine della page cache finiscono nello scatterlist scrivibile
▼
Scrittura scratch authencesn
│ scrive seqno_lo a dst[assoclen + cryptlen]
│ = 4 byte scelti dall'attaccante a un offset del file scelto dall'attaccante
▼
Corruzione della page cache (nessuna modifica su disco)
La correzione (a664bf3d603d) annulla completamente l'ottimizzazione in-place — algif_aead ora opera sempre out-of-place, allocando un buffer di destinazione separato. Poiché sorgente e destinazione ora provengono da mapping diversi, le pagine della page cache in src non possono mai essere raggiunte dal percorso di scrittura dst.