
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:
