Как защитить Docker‑контейнеры от уязвимости CVE‑2026-31431 («Copy Fail»)
В начале 2026 года исследователи опубликовали информацию о новой уязвимости в ядре Linux, получившей идентификатор CVE‑2026-31431 и прозвище «Copy Fail». Дефект находится в подсистеме AF_ALG, отвечающей за криптографические сокеты, и позволяет непривилегированному пользователю выполнять контролируемую запись в страничный кэш. Поскольку кэш страниц используется всеми процессами хоста, атакующий может временно изменять содержимое любого читаемого файла, включая setuid‑бинарники, и thereby получить привилегии root.
Почему уязвимость затрагивает контейнеры
По умолчанию Docker Engine до версии v29.4.3 включал в свои профили сеccomp разрешение на создание сокетов семейства AF_ALG. Это означало, что любой процесс внутри контейнера мог открыть такой сокет и воспользоваться уязвимостью ядра. Поскольку страничный кэш общий для всех контейнеров и самого хоста, последствия выходят за пределы изолированного окружения: изменённые страницы становятся видимыми другим контейнерам, совместно использующим те же образные слои, а также процессам хоста.
Первая попытка: блокировка через seccomp (v29.4.2)
Инженеры Docker сначала попытались закрыть доступ к AF_ALG, добавив в default seccomp‑профиль правило, которое отвергает syscall socket(2) с аргументом AF_ALG. Однако они обнаружили, что на некоторых архитектурах (в том числе в режиме ia32 совместимости) сокеты создаются через устаревший мультиплексор socketcall(2). Seccomp не может inspecting указатели, передаваемые в этом вызове, поэтому полное запрещение socketcall стало необходимым.
Такой широкий блокировщик привёл к поломке сетевой функциональности у множества 32‑битных приложений: старые версии glibc, Go‑runtime для GOARCH=386, а также популярные инструменты вроде SteamCMD и Wine полагаются на socketcall. После выпуска Docker Engine v29.4.2 пользователи начали сообщать о потере сети внутри контейнеров, запускающих подобные бинарники.
Вторая попытка: использование LSM (AppArmor/SELinux) в v29.4.3
Осознав ограничения seccomp, команда перешла к механизмам Linux Security Modules, которые работают на уровне ядра после того, как системный вызов уже обработан, и могут принимать решения на основе реального типа создаваемого сокета.
В релизе v29.4.3 были сделаны следующие изменения:
- Откат полного запрета
socketcallв seccomp‑профиле, чтобы вернуть совместимость с 32‑битными бинарниками. - Добавление правила
deny network algв профиль AppArmor (moby/profiles#22). На системах, где AppArmor включён по умолчанию (Ubuntu, Debian), это блокирует создание AF_ALG‑сокетов независимо от того, через какой syscall (socketилиsocketcall) они запрашиваются. - Интеграция SELinux‑политики в виде CIL‑модуля, который запрещает
alg_socketcreationдля всех доменовcontainer_t. Модуль загружается командойsemodule -i docker-container.cilи требует запуска демона Docker с параметром--selinux-enabled. - Оставление фильтра seccomp, блокирующего
socket(AF_ALG), как дополнительный уровень защиты (defense‑in‑depth) для прямого пути syscalla.
Таким образом, в текущих версиях Docker Engine защита построена на комбинации seccomp (для быстрого пути) и LSM (AppArmor/SELinux) для перехвата путей через socketcall.
Что должен сделать администратор VPS или dedicated‑сервера
Самый надёжный способ устранить угрозу — установить патч яда, предоставляемый дистрибутивом. На момент написания патч уже доступен в Debian (CVE‑2026-31431) и RHEL 9 (RHSB‑2026-002), но ещё не вошёл в основные ветки Ubuntu. Если ваш дистрибутив ещё не выпустил исправление, следуйте этим шагам:
- Обновите Docker Engine до версии v29.4.3 или новее. Достаточно выполнить системную команду перезапуска демона, например
systemctl restart docker; перезагрузка хоста не требуется. - Если обновление ядра невозможно немедленно, можно временно выгрузить модули ответственные за AF_ALG. Добавьте в файл
/etc/modprobe.d/disable-af_alg.confстроки:
После этого выполнитеblacklist af_alg blacklist algif_aeadupdate-initramfs -u(или аналог для вашего дистрибутива) и перезагрузите систему. Этот метод работает только если модули собраны как загружаемые (CONFIG_CRYPTO_USER_API=m). - В качестве дополнительной меры можно задать собственный seccomp‑профиль, который явно запрещает доступ к AF_ALG, оставив остальные правила unchanged. Пример минимального профиля (
block-afalg.json):{ "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [ { "name": "socket", "action": "SCMP_ACT_ERRNO", "args": [ { "index": 0, "value": 38, // AF_ALG "valueTwo": 0, "op": "SCMP_CMP_EQ" } ] } ] }Запустите контейнер, указав этот профиль через параметр--security-opt seccomp=/path/to/block-afalg.jsonили черезdaemon.jsonс опцией"default-seccomp-profile".
Заключение
Уязвимость «Copy Fail» продемонстрировала, насколько важно иметь возможность быстро реагировать на ошибки ядра на уровне рантайма контейнеров. Docker Engine показал, что даже без готового патча ядра можно снизить риск, комбинируя seccomp и LSM‑механизмы. Тем не менее, единственное полное решение — это обновление самого ядра, поэтому администраторы должны следить за выпусками безопасности своих дистрибутивов и применять их как можно скорее. Регулярное обновление Docker Engine остаётся простым и эффективным способом сократить окно уязвимости между публикацией CVE и доступностью патча ядра.