
Analisi e mitigazione della vulnerabilità Linux kernel Copy Fail (CVE-2026-31431) che sfrutta la mutazione della cache di pagina AF_ALG/splice, con checker PoC, regole di rilevamento auditd e verifica dell'aggiornamento del kernel.
Questo progetto è un mini-progetto che analizza il principio di funzionamento della vulnerabilità Copy Fail (CVE-2026-31431) del kernel Linux e confronta lo stato prima e dopo la patch utilizzando il checker non distruttivo del repository PoC pubblico.
Non viene eseguito alcun exploit di modifica di binari setuid o di /etc/passwd, ma ci si concentra sulla verifica sicura della vulnerabilità basata su un testfile temporaneo e sull'analisi dal punto di vista del rilevamento e della mitigazione.
L'obiettivo di questo progetto non è semplicemente eseguire un exploit, ma comprendere come una vulnerabilità del kernel Linux si manifesti a causa di una combinazione di strutture interne e come possa essere identificata e affrontata dal punto di vista operativo.
L'ambito di lavoro è il seguente:
Analisi del principio della vulnerabilità
↓
Analisi della struttura del codice PoC
↓
Pratica basata su checker non distruttivo
↓
Confronto prima e dopo la patch
↓
Sintesi delle misure di rilevamento/mitigazione
In questa esercitazione è stato eseguito solo vulnerable.c del repository copy-fail-c.
| Categoria | Prima della patch | Dopo la patch |
|---|---|---|
| SO | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Account | Utente normale client | Utente normale client |
| Checker | vulnerable | vulnerable |
| Modalità di test | Test non distruttivo basato su testfile temporaneo | Esecuzione dello stesso checker |
Informazioni sul kernel prima della patch:
Linux ubuntu-server 6.8.0-53-generic #55-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 17 15:37:52 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Informazioni sul kernel dopo la patch:
Linux ubuntu-server 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Riepilogo delle modifiche ai pacchetti del kernel:
- linux-image-6.8.0-53-generic 6.8.0-53.55
- linux-image-generic 6.8.0-53.55+1
+ linux-image-6.8.0-134-generic 6.8.0-134.134
+ linux-image-generic 6.8.0-134.134
+ linux-generic 6.8.0-134.134
+ linux-headers-generic 6.8.0-134.134
Copy Fail è una vulnerabilità che si verifica quando il percorso di elaborazione AEAD di AF_ALG nel kernel Linux si combina con l'operazione zero-copy di splice(), consentendo che la page cache di un file di sola lettura venga utilizzata come destinazione di scrittura errata.
I componenti chiave sono i seguenti:
| Elemento | Ruolo |
|---|---|
| Linux page cache | Meccanismo del kernel che memorizza nella cache il contenuto dei file su disco nella RAM |
splice() | Syscall zero-copy che collega i dati tramite riferimenti all'interno del kernel senza copiarli nello spazio utente |
AF_ALG | Interfaccia che consente di utilizzare l'API crypto del kernel Linux come un socket dallo spazio utente |
| Elaborazione in-place AEAD | Ottimizzazione che elabora il buffer di input e quello di output nello stesso buffer, senza tenerli separati |
authencesn | Template crypto che genera una scrittura scratch di 4 byte durante l'elaborazione AEAD |
Il flusso principale della vulnerabilità è il seguente:
File leggibile
↓
Caricato nella Linux page cache
↓
Trasmissione del riferimento alla page cache al percorso crypto AF_ALG tramite splice()
↓
L'elaborazione in-place AEAD intreccia gli scatterlist di input e output
↓
Durante l'elaborazione di authencesn si verifica una scrittura scratch di 4 byte
↓
La scrittura avviene non in un buffer di output separato, ma nella page cache
↓
Si verifica una mutazione della page cache
In altre parole, splice() trasmette il riferimento alla page cache, l'elaborazione in-place AEAD intreccia input e output nello stesso percorso, e authencesn provoca la scrittura effettiva di 4 byte.
La struttura del repository utilizzato per l'esercitazione è la seguente.
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
| File | Ruolo | Utilizzo in questa esercitazione |
|---|---|---|
utils.c, utils.h | Implementazione della primitiva di mutazione della page cache basata su AF_ALG/splice | Utilizzato per l'analisi e per eseguire vulnerable |
vulnerable.c | Strumento non distruttivo per verificare la vulnerabilità basato su testfile temporaneo | Eseguito |
exploit.c | Variante di modifica della page cache di un binario setuid root | Non eseguito |
exploit-passwd.c | Variante di modifica della page cache di /etc/passwd | Non eseguito |
payload.c | Payload eseguito con privilegi di root | Non eseguito |
Makefile | Automazione della compilazione | Utilizzato solo per il target vulnerable |
nolibc/ | Codice alternativo leggero a libc per la creazione di payload ELF statici piccoli | Solo analisi |
utils.cIl cuore di utils.c è la primitiva di mutazione della page cache della famiglia patch_chunk(). Questa funzione utilizza AF_ALG e splice() per collegare la page cache del file di destinazione al percorso di elaborazione crypto e, sui kernel vulnerabili, verifica se una parte della page cache viene sovrascritta durante l'elaborazione AEAD.
vulnerable.cvulnerable.c non tocca file di sistema reali. Crea un testfile temporaneo nella directory corrente e verifica se la page cache di quel file viene alterata.
In questo progetto è stato eseguito solo questo file.
Prima di eseguire l'aggiornamento del kernel, sono stati registrati lo stato del SO, del kernel e dei pacchetti.
mkdir -p ~/copyfail-mini/{before,after,logs}
cd ~/copyfail-mini
uname -a | tee before/uname.txt
cat /etc/os-release | tee before/os-release.txt
dpkg -l | grep -E 'linux-image|linux-headers|linux-generic|linux-virtual' | tee before/kernel-package.txt
git clone https://github.com/jihwan77/copy-fail-c.git
cd copy-fail-c
make clean
make vulnerable
In questa esercitazione non è stato eseguito il make predefinito per compilare anche i binari dell'exploit, ma è stato utilizzato solo il target vulnerable.
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
Risultato dell'esecuzione prima della patch:

Giudizio:
exit code 100
→ mutazione della page cache confermata
→ funzionamento della primitiva Copy Fail sul kernel prima della patch
Dopo aver salvato i risultati precedenti alla patch, è stato eseguito l'aggiornamento dei pacchetti Ubuntu.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Dopo il riavvio, il kernel è cambiato come segue.
Prima: 6.8.0-53-generic
Dopo : 6.8.0-134-generic
cd ~/copyfail-mini/copy-fail-c
make clean
make vulnerable
./vulnerable > ../after/vulnerable-output.txt 2>&1
echo "exit_code=$?" >> ../after/vulnerable-output.txt
cat ../after/vulnerable-output.txt
Risultato dell'esecuzione dopo la patch:

Confronto dei risultati:
| Voce | Prima della patch | Dopo la patch |
|---|---|---|
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Risultato del checker | VULNERABLE | authencesn template not registered |
| Exit Code | 100 | 2 |
| Mutazione della page cache | Confermata | Il checker non è arrivato alla fase di mutazione |
| Interpretazione | Funzionamento della primitiva Copy Fail | Impossibilità di entrare nel percorso AEAD/authencesn richiesto dal PoC |
Dopo la patch, exit_code=2 non significa semplicemente "non vulnerabile". Più precisamente:
Il template authencesn(hmac(sha256),cbc(aes)) di AF_ALG non è registrato,
quindi il checker non ha potuto determinare direttamente la vulnerabilità.
Un controllo aggiuntivo ha mostrato che dopo l'aggiornamento di Ubuntu, il caricamento del modulo algif_aead era bloccato.
lsmod | grep -E 'af_alg|algif_aead'
Risultato:
af_alg 32768 0
algif_aead non era caricato.
sudo modprobe algif_aead
Risultato:
modprobe: ERROR: ../libkmod/libkmod-module.c:1084 command_do() Error running install command '/bin/false' for module algif_aead: retcode 1
modprobe: ERROR: could not insert 'algif_aead': Invalid argument
Verifica della configurazione di blocco:
grep -R "algif_aead" /etc/modprobe.d /lib/modprobe.d 2>/dev/null
Risultato:
/etc/modprobe.d/disable-algif_aead.conf:# Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
/etc/modprobe.d/disable-algif_aead.conf:install algif_aead /bin/false
Pertanto, è più corretto interpretare il risultato dopo la patch come segue:
Dopo l'aggiornamento di sicurezza di Ubuntu, il kernel è stato cambiato in 6.8.0-134-generic
ed è stata applicata una mitigazione di blocco del modulo algif_aead basata su kmod.
Di conseguenza, il checker vulnerable di copy-fail-c
non è riuscito a eseguire il bind sul template AF_ALG authencesn(hmac(sha256),cbc(aes)) richiesto dal PoC,
e non è arrivato alla fase di mutazione della page cache.
In altre parole, ciò che è stato verificato in questa esercitazione non è "l'effetto della sola patch del codice del kernel", ma lo stato in cui, dopo l'aggiornamento di sicurezza di Ubuntu, l'aggiornamento del kernel e la mitigazione di blocco del modulo algif_aead hanno impedito al PoC di procedere lungo lo stesso percorso.
Copy Fail può alterare la page cache senza modificare direttamente il file su disco, quindi il rilevamento basato solo sull'hash del file presenta dei limiti. È importante quindi un rilevamento basato sul comportamento delle syscall.
In questa esercitazione, sono state osservate le seguenti syscall utilizzando auditd.
sudo auditctl -a always,exit -F arch=b64 -S socket -F a0=38 -k copyfail_afalg
sudo auditctl -a always,exit -F arch=b64 -S bind -k copyfail_bind
sudo auditctl -a always,exit -F arch=b64 -S splice -k copyfail_splice
sudo auditctl -a always,exit -F arch=b64 -S sendmsg -k copyfail_sendmsg
socket(AF_ALG)Nei log è stato confermato che il processo vulnerable ha creato un socket AF_ALG.
comm=vulnerable
syscall=socket
success=yes
a0=alg
key=copyfail_afalg
bind()Nell'ambiente dopo la patch/mitigazione, il processo vulnerable ha tentato di eseguire il bind sul template authencesn ma ha fallito.
comm=vulnerable
syscall=bind
success=no
exit=ENOENT(No such file or directory)
saddr_fam=alg
key=copyfail_bind
Ciò significa che nell'ambiente dopo la patch, il PoC è riuscito a creare il socket AF_ALG, ma ha fallito nella fase di bind del template authencesn(hmac(sha256),cbc(aes)).
splice() / sendmsg()Dopo la patch, il fallimento nella fase di bind() ha impedito al checker di procedere alle fasi di splice() e sendmsg(). Pertanto, nei log di quelle syscall non è stato osservato un flusso di esecuzione significativo di vulnerable.
In un ambiente operativo, per osservare vulnerabilità del tipo Copy Fail, si può cercare la seguente combinazione di comportamenti.
| Target di rilevamento | Significato |
|---|---|
socket(AF_ALG, ...) | Tentativo di utilizzo dell'API crypto del kernel |
bind() con authencesn | Tentativo di utilizzo del template crypto AEAD/authencesn |
splice() | Trasmissione del riferimento alla page cache del file verso un percorso interno del kernel |
sendmsg() / recvmsg() | Esecuzione di una richiesta crypto AF_ALG |
| Esecuzione di un binario setuid | Possibile cashout per elevazione dei privilegi |
In questa esercitazione, sono stati confermati tramite auditd gli eventi di socket(AF_ALG) e di fallimento di bind().
La risposta più elementare è applicare gli aggiornamenti di sicurezza della distribuzione.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
In questa esercitazione, dopo l'aggiornamento l'ambiente è passato a Ubuntu 24.04.4 / kernel 6.8.0-134-generic.
algif_aeadDopo l'aggiornamento di Ubuntu, è stata confermata la seguente configurazione.
/etc/modprobe.d/disable-algif_aead.conf
install algif_aead /bin/false
Questa configurazione blocca il caricamento del modulo algif_aead, impedendo al PoC di accedere al percorso AEAD di AF_ALG richiesto.
Poiché le applicazioni server generiche potrebbero non utilizzare direttamente AF_ALG molto spesso, la chiamata socket(AF_ALG) può essere utilizzata come punto di rilevamento.
I risultati di questa esercitazione possono essere riassunti come segue.
Prima della patch:
Ubuntu 24.04.2 / kernel 6.8.0-53-generic
vulnerable checker exit code 100
Mutazione della page cache confermata
→ Funzionamento della primitiva Copy Fail confermato
Dopo la patch:
Ubuntu 24.04.4 / kernel 6.8.0-134-generic
vulnerable checker exit code 2
Fallimento del bind del template authencesn
Configurazione di blocco del modulo algif_aead confermata
→ Lo stesso percorso PoC non è arrivato alla fase di mutazione della page cache
Pertanto, la conclusione di questo progetto è la seguente.
Sul kernel prima della patch, la primitiva di mutazione della page cache di Copy Fail era effettivamente funzionante.
Successivamente, applicando l'aggiornamento di sicurezza di Ubuntu, il kernel è stato cambiato in6.8.0-134-genericed è stata applicata una configurazione di blocco del moduloalgif_aead, apparentemente basata sukmod.
Di conseguenza, lo stesso checker non è riuscito a eseguire il bind sul templateauthencesn(hmac(sha256),cbc(aes))richiesto dal PoC, e non è arrivato alla fase di mutazione della page cache.
In altre parole, dai risultati di questa esercitazione non si può affermare che "la patch del codice del kernel di per sé abbia bloccato direttamente la mutazione della page cache", ma ciò che è certo in base ai log e ai risultati finora è che dopo l'aggiornamento di sicurezza di Ubuntu, la mitigazione di blocco del modulo algif_aead è stata applicata e ha bloccato il percorso del PoC.
Ubuntu Security Notice - USN-8226-1: kmod update
https://ubuntu.com/security/notices/USN-8226-1
Ubuntu Blog - Fixes available for CVE-2026-31431 Copy Fail
https://ubuntu.com/blog/copy-fail-vulnerability-fixes-available
Repository PoC copy-fail-c
https://github.com/jihwan77/copy-fail-c
I punti chiave confermati attraverso questo progetto sono i seguenti.
1. Copy Fail è una vulnerabilità del kernel che combina AF_ALG, splice(), elaborazione in-place AEAD, authencesn e page cache.
2. Nell'ambiente Ubuntu 24.04.2 / kernel 6.8.0-53 prima della patch, il checker non distruttivo ha confermato la mutazione della page cache.
3. Nell'ambiente Ubuntu 24.04.4 / kernel 6.8.0-134 dopo la patch, si è verificato un fallimento nella fase di bind di authencesn.
4. Un ulteriore controllo ha rivelato che il caricamento del modulo algif_aead era bloccato dalla configurazione /bin/false.
5. Tramite auditd è stato possibile osservare gli eventi di socket(AF_ALG) e di fallimento di bind.
6. Le contromisure operative possono essere riassunte in: aggiornamento del kernel/pacchetti di sicurezza, limitazione di algif_aead, monitoraggio delle syscall AF_ALG e controllo dei binari setuid.