
Обнаружение и устранение CVE-2026-31431 (Copy Fail) в системах Linux.
CLI на Python без зависимостей, который проверяет, выглядит ли Linux-хост подверженным CVE-2026-31431 («Copy Fail») без запуска эксплойта. Он также может применить консервативное временное смягчение, когда затронутый компонент загружается как модуль ядра. Поддерживает Debian/Ubuntu, RHEL/Rocky/AlmaLinux, Fedora и SUSE.
pip install copyfail-guard
copyfail-guard
CVE-2026-31431 — это логическая ошибка в интерфейсе ядра algif_aead (AF_ALG AEAD socket),
которая позволяет непривилегированному локальному пользователю выполнить контролируемую запись 4 байт
в page cache любого читаемого файла, что приводит к повышению привилегий до root.
CVSS 7.8, присутствует с ядра 4.14, исправлена в стабильных выпусках начиная с апреля 2026 года.
Существует публичный эксплойт, и уязвимость внесена в CISA KEV.
Некоторые проверки уязвимостей сводятся к «запусти эксплойт и посмотри, сработает ли он». Это не лучшая идея на production-хостах. copyfail-guard использует подход без эксплойта. Он не пытается вызвать ошибку, изменить setuid-бинарники или доказать эксплуатируемость. Вместо этого он проверяет состояние хоста (версию ядра, статус загрузки модуля, конфигурацию modprobe) и сообщает, выглядит ли машина подверженной.
fix намеренно минимален — он не вызывает ваш менеджер пакетов.
Постоянное устранение требует обновления ядра через обычный механизм обновления вашего дистрибутива.
pip install copyfail-guard
Или запустите напрямую из клонированного репозитория без установки:
PYTHONPATH=src python3 -m copyfail_guard detect
copyfail-guard [--json] [--dry-run] [--quiet] [detect | fix | reset]
$ copyfail-guard
[copyfail-guard] CVE-2026-31431 (Copy Fail) — УЯЗВИМ
Дистрибутив: Ubuntu 24.04.1 LTS (семейство debian)
Ядро: 6.8.0-50-generic (ветка 6.12, исправлено в 6.12.85)
Модуль: algif_aead — загружен как .ko
Смягчение: отсутствует
Рекомендуемые действия:
1. Примените смягчение сейчас:
sudo copyfail-guard fix
2. Обновите ядро для постоянного исправления:
Обновите ядро на этой системе до 6.12.85 или новее (до той версии,
которую поставляет ваш дистрибутив после интеграции исправления CVE-2026-31431), затем перезагрузитесь.
Всегда сначала просматривайте результат с помощью --dry-run перед применением:
$ sudo copyfail-guard --dry-run fix
[copyfail-guard] fix (dry-run) — OK
[ ok ] Предварительные проверки (Linux, хост, root)
[skip] Будет записана блокировка modprobe [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf]
[skip] Будет предпринята попытка выгрузить algif_aead (сейчас не загружен) [algif_aead]
[skip] Будет добавлена запись аудита [/var/log/copyfail-guard.log]
$ sudo copyfail-guard fix
[copyfail-guard] fix — OK
[ ok ] Предварительные проверки (Linux, хост, root)
[ ok ] Записана блокировка modprobe [/etc/modprobe.d/cve-2026-31431-copyfail-guard.conf]
[ ok ] Выгружен algif_aead [algif_aead]
[ ok ] Добавлена запись аудита [/var/log/copyfail-guard.log]
Следующий шаг для постоянного исправления:
Обновите ядро до версии с исправлением CVE-2026-31431, используя
обычный механизм обновления вашего дистрибутива, затем перезагрузитесь.
Если модуль в данный момент используется, шаг выгрузки может завершиться неудачей. В этом случае постоянное правило modprobe всё равно может быть установлено успешно, и copyfail-guard сообщит о сбое выгрузки как о записи действия с предупреждением, а не будет делать вид, что модуль был удалён.
--json выводит структурированный документ в stdout, подходящий для jq, Ansible или SOAR-конвейеров:
$ copyfail-guard --json | jq .verdict
"vulnerable"
$ copyfail-guard --json | jq '{verdict, kernel: .kernel.patched_threshold}'
{
"verdict": "vulnerable",
"kernel": "6.12.85"
}
После обновления до исправленного ядра используйте подкоманду reset, чтобы удалить
правило modprobe, установленное командой fix:
$ sudo copyfail-guard --dry-run reset
[copyfail-guard] reset (dry-run) — OK
[skip] Будет удалён /etc/modprobe.d/cve-2026-31431-copyfail-guard.conf
$ sudo copyfail-guard reset
[copyfail-guard] reset — OK
[ ok ] Удалён /etc/modprobe.d/cve-2026-31431-copyfail-guard.conf
Перезагрузитесь, чтобы algif_aead снова мог загрузиться при необходимости.
reset идемпотентен — если файл уже отсутствует, он завершается с кодом 0 и сообщением
«нечего делать». Затем перезагрузитесь.
Контейнеры. fix отказывается работать внутри контейнера, потому что /proc/modules
отражает ядро хоста, но контейнер не имеет полномочий загружать или выгружать
модули. Запускайте copyfail-guard непосредственно на хосте.
Встроенный algif_aead. Некоторые ядра компилируют algif_aead непосредственно в
образ (CONFIG_CRYPTO_USER_API_AEAD=y). Смягчение через modprobe неэффективно в
такой конфигурации; единственное решение — обновление ядра. detect сообщает
unmitigable_builtin в этом случае. Запуск fix всё равно установит правило modprobe
(которое предотвращает загрузку любой сосуществующей загружаемой копии), но встроенный
экземпляр не затрагивается — обновление ядра и перезагрузка являются единственным реальным решением.
blacklist против install … /bin/false. Обе директивы блокируют обычную
автозагрузку, но install algif_aead /bin/false сильнее, потому что она также
блокирует обычные явные вызовы modprobe algif_aead. Достаточно привилегированный
администратор всё равно может обойти политику modprobe, например, используя
низкоуровневые инструменты загрузки модулей или специальные флаги modprobe. copyfail-guard всегда
устанавливает более сильную форму. Если в вашей системе уже есть обычная директива
blacklist, инструмент сообщает mitigated, но выводит примечание с рекомендацией обновления.
SELinux/AppArmor. Записи в /etc/modprobe.d/ на RHEL обычно наследуют
system_u:object_r:modules_conf_t:s0 от родительского каталога, поэтому ручная
переназначение метки обычно не требуется для файла, который записывает copyfail-guard.
initramfs. algif_aead обычно не включается в загрузочный образ в основных
дистрибутивах, поэтому copyfail-guard не запускает update-initramfs -u или
dracut -f после установки правила modprobe. Если ваш дистрибутив или локальная
сборка включает algif_aead в initramfs, следуйте рекомендациям вашего дистрибутива
по ядру/модулям.
Apache 2.0 — см. LICENSE.
| Подкоманда | Действие |
|---|
detect | Объединяет пять сигналов (версия ядра, /proc/modules, modules.builtin, modules.dep, конфигурация modprobe) в один из шести вердиктов |
fix | Атомарно записывает правило modprobe install algif_aead /bin/false и пытается выгрузить algif_aead |
reset | Удаляет правило modprobe, установленное командой fix (выполнять после обновления до исправленного ядра) |
| Код | Значение |
|---|
0 | Безопасно — вердикт patched, mitigated или not_applicable; или шаг постоянного исправления выполнен успешно |
1 | Уязвим — вердикт vulnerable или unmitigable_builtin |
2 | Ошибка — состояние не удалось определить, предусловие отклонено или шаг постоянного исправления завершился неудачей |
| Вердикт | Описание |
|---|
patched | Запущенное ядро имеет версию не ниже исправленной |
mitigated | Ядро уязвимо, но algif_aead заблокирован конфигурацией modprobe |
not_applicable | Ядро уязвимо, но algif_aead отсутствует на этой системе |
vulnerable | Ядро уязвимо, модуль загружаем, смягчение отсутствует |
unmitigable_builtin | algif_aead скомпилирован в образ ядра — смягчение через modprobe неэффективно; требуется обновление ядра |
unknown | Версию ядра не удалось распознать, или она вне оцениваемого диапазона |