
Анализ и смягчение уязвимости Copy Fail (CVE-2026-31431) ядра Linux, эксплуатирующей мутацию кэша страниц через AF_ALG/splice, с проверкой PoC, правилами обнаружения auditd и проверкой обновлений ядра.
Данный проект представляет собой мини-проект по анализу принципа действия уязвимости Copy Fail (CVE-2026-31431) ядра Linux, а также сравнению состояния до и после применения патча с помощью неразрушающего проверщика из публичного PoC-репозитория.
Фактическая эксплуатация setuid-бинарников или подмена /etc/passwd не производилась; основное внимание уделено безопасной проверке уязвимости на основе временного testfile, а также анализу с точки зрения обнаружения и смягчения последствий.
Цель этого проекта — не просто выполнение эксплойта, а понимание того, какая комбинация внутренних структур ядра Linux приводит к возникновению уязвимости, и как её можно выявить и нейтрализовать с эксплуатационной точки зрения.
Область работ следующая:
Анализ принципа уязвимости
↓
Анализ структуры PoC-кода
↓
Практика с неразрушающим проверщиком
↓
Сравнение до и после патча
↓
Обобщение мер обнаружения/смягчения
В ходе данной практики выполнялся только файл vulnerable.c из репозитория .
copy-fail-c| Раздел | До патча | После патча |
|---|---|---|
| ОС | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Ядро | 6.8.0-53-generic | 6.8.0-134-generic |
| Учётная запись | Обычный пользователь client | Обычный пользователь client |
| Проверщик | vulnerable | vulnerable |
| Метод тестирования | Неразрушающая проверка на основе временного testfile | Повторный запуск того же проверщика |
Информация о ядре до патча:
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
Информация о ядре после патча:
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
Краткое описание изменений пакетов ядра:
- 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 — это уязвимость, возникающая при сочетании пути обработки AEAD через AF_ALG в ядре Linux с zero-copy операцией splice(), в результате чего страничный кеш (page cache) файла, доступного только для чтения, может быть ошибочно использован в качестве цели для записи.
Ключевые компоненты:
| Компонент | Роль |
|---|---|
| Страничный кеш Linux | Механизм ядра, кэширующий содержимое дисковых файлов в ОЗУ |
splice() | Zero-copy системный вызов, связывающий данные внутри ядра через ссылки без копирования в пользовательское пространство |
AF_ALG | Интерфейс, позволяющий использовать криптографический API ядра Linux из пользовательского пространства наподобие сокета |
| In-place обработка AEAD | Оптимизация, при которой входной и выходной буферы не разделяются, а обработка ведётся в одном буфере |
authencesn | Криптографический шаблон, в котором при обработке AEAD возникает запись 4 байт scratch |
Ключевой поток уязвимости:
Файл, доступный для чтения
↓
Попадает в страничный кеш Linux
↓
Через splice() ссылка на страничный кеш передаётся в криптографический путь AF_ALG
↓
In-place обработка AEAD связывает входной и выходной scatterlist
↓
При обработке authencesn возникает запись 4 байт scratch
↓
Запись происходит не в отдельный выходной буфер, а в страничный кеш
↓
Происходит мутация страничного кеша
То есть splice() передаёт ссылку на страничный кеш, in-place обработка AEAD связывает вход и выход по одному пути, а authencesn фактически осуществляет запись 4 байт.
Структура репозитория, использованного в практике, следующая:
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
| Файл | Роль | Использование в данной практике |
|---|---|---|
utils.c, utils.h | Реализация примитива мутации страничного кеша на основе AF_ALG/splice | Использованы для анализа и запуска vulnerable |
vulnerable.c | Инструмент неразрушающей проверки уязвимости на основе временного testfile | Выполнен |
exploit.c | Вариант подмены страничного кеша setuid root-бинарника | Не выполнялся |
exploit-passwd.c | Вариант подмены страничного кеша /etc/passwd | Не выполнялся |
payload.c | Полезная нагрузка, выполняемая с правами root | Не выполнялся |
Makefile | Автоматизация сборки | Использована только цель vulnerable |
nolibc/ | Лёгкая замена libc для сборки небольших статических ELF payload | Только анализ |
utils.cЯдро utils.c — это примитив мутации страничного кеша из серии patch_chunk(). Эта функция подключает страничный кеш целевого файла к пути криптографической обработки с помощью AF_ALG и splice(), и в уязвимом ядре проверяет, перезаписывается ли часть страничного кеша во время обработки AEAD.
vulnerable.cvulnerable.c не затрагивает реальные системные файлы. Он создаёт временный testfile в текущем каталоге и проверяет, происходит ли мутация его страничного кеша.
В данном проекте выполнялся только этот файл.
Перед обновлением ядра были зафиксированы состояние ОС, ядра и пакетов.
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
В данной практике не использовалась сборка всех эксплойтов через make по умолчанию; использовалась только цель vulnerable.
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
Результат выполнения до патча:

Оценка:
exit code 100
→ подтверждена мутация страничного кеша
→ на ядре до патча примитив Copy Fail работает
После сохранения результатов до патча было выполнено обновление пакетов Ubuntu.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
После перезагрузки ядро изменилось следующим образом:
До: 6.8.0-53-generic
После: 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
Результат выполнения после патча:

Сравнение результатов:
| Пункт | До патча | После патча |
|---|---|---|
| Ядро | 6.8.0-53-generic | 6.8.0-134-generic |
| Результат проверщика | VULNERABLE | authencesn template not registered |
| Код завершения | 100 | 2 |
| Мутация страничного кеша | Подтверждена | Проверщик не дошёл до стадии мутации |
| Интерпретация | Примитив Copy Fail работает | Не удалось войти в путь AEAD/authencesn, требуемый PoC |
Код завершения exit_code=2 после патча не означает просто "не уязвимо". Точнее это:
Шаблон authencesn(hmac(sha256),cbc(aes)) в AF_ALG не зарегистрирован,
поэтому проверщик не смог напрямую определить уязвимость
Дополнительная проверка показала, что после обновления Ubuntu загрузка модуля algif_aead была заблокирована.
lsmod | grep -E 'af_alg|algif_aead'
Результат:
af_alg 32768 0
algif_aead не загружен.
sudo modprobe algif_aead
Результат:
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
Проверка настройки блокировки:
grep -R "algif_aead" /etc/modprobe.d /lib/modprobe.d 2>/dev/null
Результат:
/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
Таким образом, результат после патча следует интерпретировать следующим образом:
После обновления безопасности Ubuntu ядро было изменено на 6.8.0-134-generic,
и применена мера смягчения — блокировка модуля algif_aead на уровне kmod.
В результате проверщик уязвимости copy-fail-c не смог привязаться
к требуемому PoC шаблону AF_ALG: authencesn(hmac(sha256),cbc(aes)),
и стадия мутации страничного кеша не была достигнута.
То есть в данной практике наблюдался не только эффект патча самого кода ядра, но и применение блокировки модуля algif_aead в рамках обновления безопасности Ubuntu, что заблокировало прохождение того же PoC-пути.
Copy Fail позволяет изменять страничный кеш без прямого изменения файлов на диске, поэтому простое обнаружение на основе хешей файлов имеет ограничения. Важно обнаружение на основе поведения системных вызовов.
В данной практике с помощью 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)В логах подтверждено создание сокета AF_ALG процессом vulnerable.
comm=vulnerable
syscall=socket
success=yes
a0=alg
key=copyfail_afalg
bind()В среде после патча/смягчения процесс vulnerable попытался выполнить bind к шаблону authencesn, но потерпел неудачу.
comm=vulnerable
syscall=bind
success=no
exit=ENOENT(No such file or directory)
saddr_fam=alg
key=copyfail_bind
Это означает, что в среде после патча PoC смог создать сокет AF_ALG, но не смог выполнить привязку к шаблону authencesn(hmac(sha256),cbc(aes)).
splice() / sendmsg()После патча проверщик не дошёл до стадии bind(), поэтому не смог перейти к вызовам splice() и sendmsg(). Следовательно, в логах этих системных вызовов значимый поток выполнения vulnerable не наблюдался.
При наблюдении за уязвимостями типа Copy Fail в операционной среде можно увидеть следующую комбинацию действий:
| Цель обнаружения | Значение |
|---|---|
socket(AF_ALG, ...) | Попытка использования криптографического API ядра |
bind() с authencesn | Попытка использования криптографического шаблона AEAD/authencesn |
splice() | Передача ссылки на страничный кеш файла во внутренний путь ядра |
sendmsg() / recvmsg() | Выполнение криптографического запроса AF_ALG |
| Запуск setuid-бинарника | Возможность повышения привилегий |
В данной практике с помощью auditd были подтверждены события socket(AF_ALG) и сбой bind().
Самый основной ответ — применение обновлений безопасности дистрибутива.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
В данной практике после обновления среда изменилась на Ubuntu 24.04.4 / ядро 6.8.0-134-generic.
algif_aeadПосле обновления Ubuntu была обнаружена следующая настройка:
/etc/modprobe.d/disable-algif_aead.conf
install algif_aead /bin/false
Эта настройка блокирует загрузку модуля algif_aead, предотвращая вход в путь AF_ALG AEAD, необходимый для PoC.
Обычные серверные приложения редко используют AF_ALG напрямую, поэтому вызов socket(AF_ALG) может служить точкой обнаружения.
Результаты данной практики можно обобщить следующим образом:
До патча:
Ubuntu 24.04.2 / ядро 6.8.0-53-generic
проверщик vulnerable — код завершения 100
подтверждена мутация страничного кеша
→ примитив Copy Fail работает
После патча:
Ubuntu 24.04.4 / ядро 6.8.0-134-generic
проверщик vulnerable — код завершения 2
сбой привязки шаблона authencesn
подтверждена настройка блокировки модуля algif_aead
→ тот же путь PoC не дошёл до стадии мутации страничного кеша
Таким образом, вывод проекта следующий:
На ядре до патча примитив мутации страничного кеша Copy Fail действительно работал. После применения обновления безопасности Ubuntu ядро было изменено на
6.8.0-134-generic, и была применена настройка блокировки модуляalgif_aead, по-видимому, на уровнеkmod. В результате проверщик не смог выполнить привязку к требуемому шаблонуauthencesn(hmac(sha256),cbc(aes))AF_ALG, и не дошёл до стадии мутации страничного кеша.
То есть, по результатам данной практики, нельзя утверждать, что "патч самого кода ядра напрямую заблокировал мутацию страничного кеша", но на основании имеющихся логов и результатов можно с уверенностью сказать: после обновления безопасности Ubuntu была применена мера смягчения в виде блокировки модуля algif_aead, которая заблокировала путь 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
copy-fail-c PoC repository
https://github.com/jihwan77/copy-fail-c
Ключевые моменты, подтверждённые в ходе данного проекта:
1. Copy Fail — это уязвимость ядра, сочетающая AF_ALG, splice(), in-place обработку AEAD, authencesn и страничный кеш.
2. В среде до патча Ubuntu 24.04.2 / ядро 6.8.0-53 неразрушающий проверщик подтвердил мутацию страничного кеша.
3. В среде после патча Ubuntu 24.04.4 / ядро 6.8.0-134 произошёл сбой на этапе привязки authencesn.
4. Дополнительная проверка показала, что загрузка модуля algif_aead заблокирована настройкой /bin/false.
5. С помощью auditd удалось наблюдать события socket(AF_ALG) и сбой bind.
6. Операционные меры реагирования включают обновление ядра/пакетов безопасности, ограничение algif_aead, мониторинг системных вызовов AF_ALG и проверку setuid-бинарников.