
Análise e mitigação da vulnerabilidade Copy Fail (CVE-2026-31431) do kernel Linux, que explora a mutação do cache de páginas via AF_ALG/splice, com verificador de PoC, regras de detecção do auditd e verificação de atualização do kernel.
Este projeto é um miniprojeto que analisa o princípio de funcionamento da vulnerabilidade Copy Fail (CVE-2026-31431) do Linux Kernel e compara o estado antes e depois do patch usando o checker não destrutivo do repositório PoC público.
Não executa exploits reais de modificação de binário setuid ou de /etc/passwd; o foco está na verificação segura da vulnerabilidade com base em um testfile temporário e na análise sob a perspectiva de detecção/mitigação.
O objetivo deste projeto não é simplesmente executar um exploit, mas entender a combinação de estruturas internas que originam a vulnerabilidade do kernel Linux e documentar como identificá-la e respondê-la do ponto de vista operacional.
O escopo do trabalho é o seguinte:
취약점 원리 분석
↓
PoC 코드 구조 분석
↓
비파괴 checker 기반 실습
↓
패치 전후 비교
↓
탐지/완화 방안 정리
Nesta prática, apenas o vulnerable.c do repositório copy-fail-c foi executado.
| Item | Antes do patch | Depois do patch |
|---|---|---|
| OS | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Conta | usuário comum client | usuário comum client |
| checker | vulnerable | vulnerable |
| Método de teste | verificação não destrutiva com base em testfile temporário | re-execução do mesmo checker |
Informações do kernel antes do 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
Informações do kernel depois do 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
Resumo das alterações dos pacotes do 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 é uma vulnerabilidade em que o page cache de arquivos somente leitura pode ser usado como alvo de escrita indevida, quando o caminho de processamento AEAD do AF_ALG do kernel Linux se combina com o comportamento zero-copy do splice().
Os componentes centrais são os seguintes:
| Elemento | Função |
|---|---|
| Linux page cache | Mecanismo do kernel que armazena o conteúdo de arquivos em disco na RAM |
splice() | Chamada de sistema zero-copy que encadeia dados por referência dentro do kernel, sem copiá-los para o espaço do usuário |
AF_ALG | Interface que permite usar a crypto API do kernel Linux como um socket no espaço do usuário |
| Processamento AEAD in-place | Otimização que processa o buffer de entrada e o de saída no mesmo buffer, sem separá-los |
authencesn | Template de crypto no qual ocorre uma escrita scratch de 4 bytes durante o processamento AEAD |
O fluxo central da vulnerabilidade é o seguinte:
읽기 가능한 파일
↓
Linux page cache에 올라감
↓
splice()로 AF_ALG crypto 경로에 page cache reference 전달
↓
AEAD in-place 처리로 입력과 출력 scatterlist가 엮임
↓
authencesn 처리 중 4바이트 scratch write 발생
↓
별도 출력 버퍼가 아니라 page cache에 쓰기 발생
↓
page cache mutation 발생
Ou seja, splice() entrega a referência do page cache, o processamento AEAD in-place entrelaça entrada e saída no mesmo caminho, e authencesn é o que efetivamente realiza a escrita de 4 bytes.
A estrutura do repositório usado na prática é a seguinte:
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
| Arquivo | Função | Uso nesta prática |
|---|---|---|
utils.c, utils.h | Implementação da primitive de mutation do page cache baseada em AF_ALG/splice | Usado na análise e execução do vulnerable |
vulnerable.c | Ferramenta de verificação não destrutiva da vulnerabilidade baseada em testfile temporário | Executado |
exploit.c | Variante de modificação do page cache de binário setuid root | Não executado |
exploit-passwd.c | Variante de modificação do page cache de /etc/passwd | Não executado |
payload.c | Payload executado com privilégios root | Não executado |
Makefile | Automação de build | Apenas o target vulnerable é usado |
nolibc/ | Código substituto de libc leve para construir pequenos payloads ELF estáticos | Apenas análise |
utils.cO núcleo de utils.c é a primitive de mutation do page cache da família patch_chunk(). Essa função conecta o page cache do arquivo alvo ao caminho de processamento de crypto usando AF_ALG e splice(), e verifica se, em kernels vulneráveis, parte do page cache é sobrescrita durante o processamento AEAD.
vulnerable.cvulnerable.c não toca em arquivos reais do sistema. Ele cria um testfile temporário no diretório atual e verifica se o page cache desse arquivo é modificado.
Neste projeto, apenas esse arquivo foi executado.
Antes de realizar a atualização do kernel, foram registrados o OS, o kernel e o estado dos pacotes.
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
Nesta prática, os binários de exploit não foram compilados junto com o make padrão; apenas o target vulnerable foi usado.
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
Resultado da execução antes do patch:

Análise:
exit code 100
→ page cache mutation 확인
→ 패치 전 커널에서 Copy Fail primitive 동작 확인
Após salvar os resultados antes do patch, foi realizada a atualização dos pacotes do Ubuntu.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Após a reinicialização, o kernel foi alterado da seguinte forma:
Before: 6.8.0-53-generic
After : 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
Resultado da execução depois do patch:

Comparação de resultados:
| Item | Antes do patch | Depois do patch |
|---|---|---|
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Resultado do checker | VULNERABLE | authencesn template not registered |
| Exit Code | 100 | 2 |
| Mutação do page cache | Confirmada | o checker não avançou até a etapa de mutation |
| Interpretação | A primitive do Copy Fail funcionou | Falha ao entrar no caminho AEAD/authencesn exigido pelo PoC |
O exit_code=2 após o patch não significa simplesmente "não vulnerável". Precisamente, é o seguinte:
AF_ALG의 authencesn(hmac(sha256),cbc(aes)) template이 등록되어 있지 않아,
checker가 취약 여부를 직접 판정하지 못한 상태