Исследователи компании Theori раскрыли уязвимость в ядре Linux под кодовым именем Copy Fail (CVE-2026-31431), которая позволяет любому локальному пользователю получить root с помощью Python-скрипта размером 732 байта. Скрипт работает без модификаций на Ubuntu, Amazon Linux, RHEL и SUSE; уязвимость присутствует в ядрах с 2017 года. Оценка CVSS 3.1 — 7.8 (высокая). Исправление принято в основную ветку ядра Linux 1 апреля 2026 года, однако на 30 апреля команды ключевых дистрибутивов ещё не выпустили обновлённое ядро. До его выхода администраторам рекомендуется заблокировать модуль algif_aead.
Что нашли исследователи Theori
Copy Fail — логическая ошибка в криптографическом шаблоне authencesn ядра Linux. По описанию Xint Code Research Team, локальный пользователь без привилегий может выполнить детерминированную контролируемую 4-байтовую запись в страничный кэш любого читаемого файла. Цель эксплойта по умолчанию — /usr/bin/su, исполняемый файл с битом setuid, дающий права root и присутствующий во всех протестированных дистрибутивах. После записи шелл-кода в кэш-копию исполняемого файла вызов execve запускает изменённый код от имени root.
Особенность атаки в том, что файл на диске остаётся неизменным. Модификация существует только в страничном кэше ядра. Стандартные инструменты контроля целостности, сравнивающие контрольные суммы файлов, изменения не обнаружат. При этом любой процесс на хосте, читающий файл, получает заражённую версию из кэша.
В отличие от Dirty Cow (CVE-2016-5195) и Dirty Pipe (CVE-2022-0847), эксплойт не зависит от выигрыша race condition и не требует подбора смещений под конкретное ядро. Один и тот же скрипт сработал на четырёх протестированных конфигурациях:
| Дистрибутив | Ядро |
|---|---|
| Ubuntu 24.04 LTS | 6.17.0-1007-aws |
| Amazon Linux 2023 | 6.18.8-9.213.amzn2023 |
| RHEL 10.1 | 6.12.0-124.45.1.el10_1 |
| SUSE 16 | 6.12.0-160000.9-default |
По данным CERT-EU, ядра Ubuntu 26.04 (Resolute) и более новые не затронуты.
Системы под наибольшим риском
Угроза не сводится к локальному повышению привилегий. Страничный кэш в Linux общий для всего хоста, поэтому атака пересекает границы контейнеров. Атакующий внутри контейнера может изменить кэш-копию исполняемого файла, который читает или запускает хост, и таким образом скомпрометировать узел целиком. Вторая часть исследования Theori будет посвящена побегу из узлов Kubernetes.
Page cache (страничный кэш) — область памяти ядра, где хранятся прочитанные с диска страницы файлов. При обращении к файлу через read, mmap или execve ядро отдаёт данные из кэша, а не с диска. Кэш общий для всех процессов на хосте, включая процессы внутри контейнеров.
Приоритетные цели для применения исправления, по рекомендации исследователей: многопользовательские Linux-серверы, агенты CI, облачные SaaS-платформы, выполняющие пользовательский код, кластеры контейнеров. На обычных рабочих станциях с одним пользователем риск ниже, но сохраняется при наличии локально работающего вредоносного процесса.
Как устроена уязвимость
В цепочке участвуют три компонента ядра, каждый из которых сам по себе работает корректно.
Первый — AF_ALG. Сокетный интерфейс к криптографической подсистеме ядра, доступный непривилегированному пользователю. Через него можно открыть сокет, привязать к нему AEAD-шаблон и выполнять операции шифрования или дешифрования над произвольными данными.
Второй — системный вызов splice(). Передаёт данные между файловыми дескрипторами и каналами без копирования, по ссылке на страницы кэша. Когда пользователь делает splice файла в канал, а затем в AF_ALG-сокет, входная scatterlist сокета содержит прямые ссылки на страницы кэша исходного файла — те самые, что используются при любом read, mmap и execve.
AEAD (Authenticated Encryption with Associated Data) — класс криптографических алгоритмов, которые одновременно шифруют данные и проверяют целостность связанных метаданных (например, заголовков пакетов). Примеры: GCM, CCM, authencesn.
Третий — AEAD-шаблон authencesn, обёртка для протокола IPsec, поддерживающая 64-битные расширенные порядковые номера. При расчёте HMAC шаблон переставляет байты порядкового номера, используя выходной буфер вызывающей стороны как временное место. Конкретно, в функции crypto_authenc_esn_decrypt() выполняется запись 4 байт по смещению assoclen + cryptlen — за пределы законной выходной области.
Ошибка возникает на пересечении компонентов. В 2017 году в algif_aead.c добавили оптимизацию: AEAD-операции стали выполняться in-place, то есть src и dst указывали на одну scatterlist. AAD и шифротекст копировались в выходной буфер пользователя, но страницы тега аутентификации присоединялись по ссылке — те самые страницы кэша из splice. При временной записи за границей выходного буфера, заложенной в логику authencesn, функция scatterwalk_map_and_copy выходила за пределы пользовательского буфера и попадала на присоединённую страницу кэша. В результате 4 байта записывались напрямую в кэш-копию целевого файла. HMAC после этого ожидаемо не сходился, recvmsg возвращал ошибку, однако запись в кэш сохранялась.
Атакующий контролирует три параметра: какой файл атаковать (любой читаемый текущему пользователю), смещение внутри файла (через параметры splice и assoclen) и записываемое 4-байтовое значение (через байты 4—7 AAD).
История бага: три коммита за девять лет
Хронология появления уязвимости охватывает почти десятилетие.
- 2011 год: в ядро добавили шаблон authencesn для поддержки 64-битных порядковых номеров IPsec ESP (коммит a5079d084f8b). Шаблон использовал выходной буфер как временное место. На тот момент это было безопасно: AAD хранилась в отдельной scatterlist, а единственным потребителем был внутренний слой xfrm.
- 2015 год: в AF_ALG добавили поддержку AEAD (модуль algif_aead.c) с splice-путём, доставляющим страницы кэша в крипто-scatterlist. В том же году authencesn перевели на новый AEAD-интерфейс (коммит 104880a6b470). Появилось смещение assoclen + cryptlen, выходящее за границу выходного буфера. Эксплойта пока не было: AF_ALG работал out-of-place, src и dst оставались разными scatterlist.
- 2017 год: в algif_aead.c добавили оптимизацию для in-place-операций (коммит 72548b093ee3). Страницы кэша из splice оказались в той же scatterlist, что и записываемая область. Запись authencesn по смещению assoclen + cryptlen стала попадать в страницы кэша.
Каждое из этих изменений по отдельности было обоснованным; уязвимость возникла на стыке всех трёх и оставалась незамеченной с 2017 года. Обнаружили её исследователи Theori через инструмент Xint Code — AI-сканер, специализирующийся на анализе путей выполнения в ядре. Сканирование криптоподсистемы заняло около часа.
Хронология раскрытия:
| Дата | Событие |
|---|---|
| Отчёт направлен команде безопасности ядра Linux | |
| Патчи предложены и приняты к рассмотрению | |
| Исправление a664bf3d603d принято в основную ветку ядра | |
| Присвоен идентификатор CVE-2026-31431 | |
| Публичное раскрытие, выложен PoC |
Исправление — коммит a664bf3d603d Герберта Сюя. Откатывает оптимизацию 2017 года: AEAD в algif_aead снова работает out-of-place, src и dst разделены, страницы кэша больше не попадают в записываемую scatterlist.
Что делать администраторам сейчас
На 30 апреля 2026 года команды ключевых дистрибутивов ещё не выпустили обновлённое ядро с исправлением (по данным CERT-EU). Команда безопасности Ubuntu распространяет временный обходной приём через пакет kmod, исправленное ядро ожидается отдельным релизом. Аналогично для RHEL, Amazon Linux и SUSE.
Порядок действий:
- Инвентаризация: проверить версии ядра на всех узлах. Затронуты все ядра 4.13 и новее без перенесённого исправления.
- Применить временную меру: заблокировать модуль algif_aead (см. ниже).
- Подписаться на уведомления безопасности дистрибутива и установить исправленное ядро сразу после выхода. Установка требует перезагрузки в новое ядро или использования горячего обновления (kpatch для RHEL, Canonical Livepatch для Ubuntu).
- Приоритет — узлы Kubernetes, агенты CI, многопользовательские серверы и системы, выполняющие недоверенный код.
Временная мера: блокировка модуля algif_aead
Рекомендация исследователей Theori и CERT-EU — запретить загрузку модуля algif_aead через директиву install в modprobe.d и выгрузить его, если он уже загружен.
sudo tee /etc/modprobe.d/disable-algif-aead.conf > /dev/null <<'EOF' # CVE-2026-31431 (Copy Fail) - temporary mitigation install algif_aead /bin/false EOF sudo rmmod algif_aead 2>/dev/null || true
Директива install перехватывает любой вызов загрузки модуля, в том числе автоматический через request_module() при создании AF_ALG-сокета с AEAD-типом. Команда rmmod выгружает модуль из ядра без перезагрузки системы; фрагмент 2>/dev/null || true нужен, чтобы скрипт не завершился ошибкой, если модуль не загружен или удерживается процессом.
Директива blacklist для этой задачи не подходит: она блокирует только автоматическую загрузку при обнаружении устройства, но не загрузку по требованию через request_module(). Без строки install директива blacklist не защищает от эксплуатации Copy Fail.
Блокировка модуля не затрагивает работу dm-crypt/LUKS, kTLS, IPsec/XFRM, OpenSSL, GnuTLS, NSS и SSH. Эти подсистемы используют собственные пути в крипто-API ядра и не зависят от algif_aead. Под удар могут попасть приложения, явно использующие afalg-движок OpenSSL или напрямую открывающие сокеты AF_ALG для AEAD, skcipher или hash-операций. Оценить, кто использует AF_ALG на конкретном хосте, можно командой:
lsof | grep AF_ALG
После выхода исправленного ядра дистрибутива и перезагрузки в новое ядро файл /etc/modprobe.d/disable-algif-aead.conf можно удалить.
Почему Copy Fail опаснее предшественников
Copy Fail отличается от известных уязвимостей ядра тем, что не зависит ни от выигрыша race condition, ни от подгонки эксплойта под конкретное ядро. Один Python-скрипт работает на любой системе с ядром 4.13 и новее без применённого исправления. CVE-2026-31431 переходит из категории «опасно при идеальных условиях» в категорию «опасно всегда, пока есть локальный доступ или контейнер». Администраторам многопользовательских и контейнерных систем стоит применить временную блокировку модуля немедленно и установить исправленное ядро сразу после публикации обновления соответствующим производителем дистрибутива.