Как Cloudflare мгновенно отразила опасную Linux-уязвимость “Copy Fail”

29 апреля 2026 года была публично раскрыта уязвимость локального повышения привилегий в ядре Linux под названием "Copy Fail" (CVE-2026-31431). Команды безопасности и инженерии Cloudflare начали оценивать уязвимость сразу после её раскрытия. Мы проанализировали технику эксплуатации, оценили степень подверженности нашей инфраструктуры риску и подтвердили, что наши существующие поведенческие детекторы могут выявить шаблон атаки в течение нескольких минут.

Воздействия на среду Cloudflare не было, данные клиентов не подвергались риску, и никакие сервисы ни в какой момент не были нарушены. Читайте далее, чтобы узнать, как наша подготовка окупилась.

Предыстория

Наш процесс выпуска ядра Linux

Cloudflare управляет глобальной серверной инфраструктурой Linux огромного масштаба, с дата-центрами, расположенными в 330 городах. Мы поддерживаем собственную сборку ядра Linux на основе версий Long-Term Support (LTS) сообщества для эффективного управления обновлениями в таких масштабах. В любой момент времени мы можем использовать несколько версий LTS из разных серий, таких как 6.12 или 6.18, которые выигрывают от продленных периодов обновления.

Сообщество регулярно объединяет и выпускает обновления безопасности и стабильности, которые запускают автоматическую задачу по генерации новой внутренней сборки ядра примерно каждую неделю. Эти сборки проходят тестирование в наших промежуточных дата-центрах для обеспечения стабильности перед глобальным развертыванием. После успешного выпуска конвейер Edge Reboot Release (ERR) управляет систематическим обновлением и перезагрузкой граничной инфраструктуры по четырехнедельному циклу. Наша инфраструктура управления обычно использует самое последнее ядро, с перезагрузками по расписанию в соответствии с требованиями конкретных рабочих нагрузок.

К тому времени, когда CVE становится общеизвестной, необходимое исправление обычно уже интегрировано в стабильные выпуски Linux LTS в течение нескольких недель. Наши установленные процедуры гарантируют, что мы уже развернули эти патчи.

На момент раскрытия "Copy Fail" большая часть нашей инфраструктуры работала на версии LTS 6.12, в то время как подмножество машин начало переходить на более новую версию LTS 6.18.

Об уязвимости Copy Fail

Чтобы понять историю реагирования, полезно разобраться в самой уязвимости. Подробное описание можно найти в оригинальном посте Xint Code.

AF_ALG и криптографический API ядра

Внутренний криптографический API ядра Linux управляет такими функциями, как kTLS и IPsec. Программы пользовательского пространства получают к нему доступ через семейство сокетов AF_ALG, позволяя непривилегированным процессам запрашивать шифрование или дешифрование. Модуль algif_aead обеспечивает это для шифров Authenticated Encryption with Associated Data (AEAD).

Непривилегированная программа выполняет следующие шаги:

  1. Открывает сокет AF_ALG и привязывается к шаблону AEAD.

  2. Устанавливает ключ и принимает сокет запроса.

  3. Отправляет входные данные через sendmsg() или splice().

  4. Выполняет операцию с помощью recvmsg().

Системный вызов splice() здесь критичен, так как он перемещает данные, передавая ссылки на страничный кеш.

Механика памяти: страничный кеш и криптография на месте

Страничный кеш — это общий системный кеш для содержимого файлов. Изменение страницы, принадлежащей исполняемому файлу с setuid, фактически редактирует эту программу для всех пользователей до тех пор, пока страница не будет вытеснена.

Криптографический API использует списки разброса (scatterlists), которые являются структурами, связывающими различные страницы памяти. В 2017 году algif_aead был оптимизирован для операций на месте (in-place), объединяя целевые страницы и страницы-ссылки. Эта конструкция не имела принудительных мер для предотвращения записи алгоритмами за установленные границы.

Уязвимость: запись за границы

Когда пользователь выполняет recvmsg(), обертка authencesn в ядре выполняет запись 4 байт за пределами легитимной выходной области:

scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);

Используя splice(), атакующий может присоединить страницы страничного кеша целевого файла к списку разброса. Затем запись за границы повреждает закешированный файл, позволяя атакующему контролировать, какой файл изменяется, смещение и конкретные 4 записываемых байта. Это означает, что атакующий может манипулировать следующим с помощью этой эксплуатации:

  • Файл: Любой читаемый файл.

  • Смещение: Настраивается через assoclen и параметры splice.

  • Значение: Контролируется через байты AAD 4–7 в sendmsg().

Эксплойт, шаг за шагом

How Cloudflare responded to the “Copy Fail” Linux vulnerability

Эксплойт по умолчанию нацелен на /usr/bin/su, setuid-root бинарный файл, присутствующий практически во всех дистрибутивах.

  1. Ссылка на кеш: Откройте /usr/bin/su как O_RDONLY и выполните read() для заполнения страничного кеша. Используйте splice() для файлового дескриптора, чтобы передать эти ссылки на страничный кеш в список разброса криптографического API.

  2. Настройка: Создайте сокет AF_ALG, выполните bind() к authencesn(hmac(sha256),cbc(aes)), установите ключ и примите сокет запроса без необходимости привилегий.

  3. Конструирование записи: Для каждого фрагмента шеллкода из 4 байт:

    • sendmsg() с байтами AAD 4–7, содержащими шеллкод.

    • splice() бинарного файла в канал (pipe), а затем в сокет AF_ALG, чтобы assoclen + cryptlen нацелилось на желаемое смещение в секции .text.

  4. Триггер: recvmsg() инициирует дешифрование. authencesn записывает свои временные данные по целевому смещению в /usr/bin/su в страничном кеше. Хотя функция возвращает -EBADMSG, запись 4 байт теперь находится в глобальном страничном кеше.

  5. Выполнение: Запуск execve("/usr/bin/su") загружает поврежденный страничный кеш. Поскольку бинарный файл является setuid-root, внедренный шеллкод выполняется с привилегиями root.

Исправление вышестоящего репозитория (коммит a664bf3d603d) отменяет оптимизацию на месте 2017 года, устраняя эксплойт.

Как мы отреагировали

Когда уязвимость была раскрыта, параллельно началось несколько направлений работы:

  • Картографирование зоны поражения: Наша команда безопасности совместно с инженерами ядра определила, какие версии ядра уязвимы, и оценила потенциальную подверженность риску.

  • Валидация покрытия: Специалисты по безопасности проанализировали технику эксплойта и подтвердили, что наши существующие поведенческие детекторы могут выявить шаблон атаки во время авторизованной внутренней валидации.

  • Упреждающий поиск угроз: Служба безопасности начала поиск признаков того, что уязвимость была использована до того, как стала публично известна, анализируя логи за последние 48 часов по всему парку.

  • Разработка смягчения: Инженеры ядра приступили к созданию смягчения времени выполнения, которое защитило бы парк без нарушения работы производственных сервисов.

  • Продолжение обновления программного обеспечения: Наши инженерные команды работали над поставкой обновленного ядра Linux, что требовало тщательной перезагрузки и развертывания на всех серверах.

Ни в какой момент времени в ходе этого реагирования не было воздействия на клиентов.

Валидация покрытия детектирования

Одним из первых действий нашей команды безопасности было подтверждение того, что наше существующее обнаружение конечных точек перехватит этот эксплойт. Наши серверы используют поведенческое обнаружение, которое непрерывно отслеживает шаблоны выполнения процессов. Оно не полагается на знание конкретных уязвимостей; оно отслеживает аномальное поведение по всему парку.

Когда наши инженеры в рамках реагирования провели внутреннюю валидацию уязвимости, платформа обнаружения пометила её в течение нескольких минут. Система связала всю цепочку выполнения — начиная с интерпретатора скриптов, проходя через криптографическую подсистему ядра и заканчивая бинарным файлом для повышения привилегий — и пометила её как вредоносную на основе поведенческих шаблонов всего парка.

Это произошло без обновления сигнатур, без изменения правил и без вмешательства человека. Наше поведенческое покрытие существовало до того, как мы написали какую-либо пользовательскую логику для конкретного эксплойта Copy File.

Это подтверждение было важным, потому что означало, что у нас было покрытие до написания правила, специфичного для уязвимости.

Поиск следов эксплуатации

Пока наша инженерная команда переходила к более целенаправленному смягчению, наше расследование в области безопасности шло с момента раскрытия. Это стандартная процедура для любой критической уязвимости.

Наша команда безопасности действует по простому принципу в отношении критических уязвимостей: предполагать компрометацию, пока не доказано обратное. Расследование началось с предположения, что эксплуатация могла произойти до того, как уязвимость стала публичной, и мы систематически работали над подтверждением или опровержением этого.

Эксплойт оставляет характерный след в журналах ядра при запуске. Мы искали этот след в нашей централизованной инфраструктуре журналирования за 48 часов до публичного раскрытия уязвимости. Если бы кто-то эксплуатировал её до того, как мир узнал о ней, мы бы это увидели.

Мы извлекли журналы доступа затронутых систем и восстановили, кто подключался, когда и какие команды выполнял. Это дало полную криминалистическую картину интерактивной активности на потенциально затронутой инфраструктуре.

Мы проверили, что системные двоичные файлы не были изменены, проверили криптографические хеши на соответствие известным корректным манифестам пакетов, искали механизмы сохранения доступа и аудировали сетевые соединения на предмет чего-либо необычного. Всё было чисто.

Хронология инцидента и влияние

Время (UTC) Событие
2026-04-29 16:00 Copy Fail публично раскрыт.
2026-04-29 ~21:00 Команды безопасности и инженерии начали оценку уязвимости парка и вариантов смягчения до полного объявления процесса реагирования на инциденты.
2026-04-29 22:52 Безопасность подтвердила, что существующее поведенческое обнаружение покрывает шаблон эксплойта Copy Fail. Во время авторизованной внутренней валидации обнаружение отметило активность в течение нескольких минут.
2026-04-29 23:01 Существующее поведенческое обнаружение сгенерировало предупреждение высокого уровня серьезности для активности, похожей на эксплойт, подтвердив покрытие обнаружения для данной техники.
2026-04-29 (вечер) Первая попытка смягчения отправлена в наш промежуточный дата-центр. В процессе развертывания всплыла конфликтующая зависимость; смягчение было откатано. Продуктивные системы не пострадали.
2026-04-29 (ночь) Инженерия разработала программу смягчения bpf-lsm.
2026-04-30 03:14 Объявлен инцидент безопасности для обеспечения кросс-функционального сотрудничества и срочности. Безопасность провела поиск угроз по всему парку на исторических данных, чтобы подтвердить отсутствие вредоносной активности на системах Cloudflare.
2026-04-30 (утро) Инженерия протестировала программу смягчения bpf-lsm и подготовила её к продуктивному использованию.
2026-04-30 14:25 Объявлен инцидент для координации программы смягчения и развертывания исправлений Linux.
2026-04-30 ~17:00 Принято решение: доставить исправленную сборку предыдущей версии LTS через автоматизацию перезагрузки; не ускорять новую LTS; в промежутке положиться на bpf-lsm.
2026-04-30 (день) Конвейер видимости (трассировка eBPF использования сокетов AF_ALG) развернут в масштабах парка. Дает полную картину всех легитимных пользователей AF_ALG.
2026-04-30 (вечер) Программа смягчения bpf-lsm развернута за отдельным шлюзом для полного смягчения парка. Сквозная проверка на ранее уязвимом тестовом узле подтверждает, что эксплойт больше не работает.
2026-05-04 (утро) Автоматизация перезагрузки возобновлена в обычном темпе с исправленным ядром.
2026-05-04 и далее Серверы, которые уже прошли автоматизацию перезагрузки ранее на неделе, были перезагружены вручную для получения исправленного ядра. Неисправленные серверы обновляются по нашей обычной автоматизации перезагрузки.
How Cloudflare responded to the “Copy Fail” Linux vulnerability

Этот график показывает прогресс нашей программы смягчения по мере её прохождения через инфраструктуру.

Как мы смягчили уязвимость?

Из-за длительного времени, необходимого для развертывания исправленного ядра Linux, мы также занялись смягчением этого эксплойта без перезагрузки.

Удаление модуля

Ошибка была в модуле ядра algif_aead. Поэтому простым исправлением было просто удалить этот модуль и запретить его перезагрузку.

Это смягчение именно то, что рекомендует материал Copy Fail, подготовленный исследователями безопасности, которые его выявили.

echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true

К сожалению, удаление модуля повлияло бы на программное обеспечение, использующее крипто-API ядра. Это означало, что нам пришлось разработать более точечное смягчение.

Bpf-lsm

How Cloudflare responded to the “Copy Fail” Linux vulnerability

Мы уже разработали и развернули такой инструмент именно для этого сценария: bpf-lsm. Вместо удаления модуля этот инструмент оставляет его загруженным для легитимных пользователей и использует программу BPF Linux Security Module для запрета перехватчика socket_bind LSM для всех остальных. Это полностью блокирует входную дверь для любых эксплойтов.

Черновик программы eBPF был собран за ночь. На следующее утро члены команды подхватили его, провели валидацию и подготовили к продуктивному использованию. Программа довольно проста. При каждом вызове socket_bind:

  1. Если семейство сокетов не AF_ALG, пропустить вызов без изменений.

  2. Если семейство AF_ALG, проверить путь вызывающего двоичного файла по списку разрешенных двоичных файлов, которые мы знаем как легитимных пользователей.

  3. Если двоичный файл находится в списке разрешенных, разрешить привязку. В противном случае — запретить.

Чтобы проверить смягчение на данной машине без эксплуатации, материал Copy Fail дает однострочную команду:

python3 -c 'import socket; s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0); s.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));'

На смягченной машине вы получите PermissionError: [Errno 1] Operation not permitted (или FileNotFoundError, в зависимости от того, какое смягчение активно) вместо успешной привязки.

Развертывание

Перед включением контроля мы проверили, что наш известный внутренний сервис является единственным легитимным пользователем AF_ALG чтобы избежать случайных простоев. Мы использовали prometheus-ebpf-exporter для перехвата системного вызова socket() и отслеживания использования AF_ALG по двоичным файлам по всему парку. Это не потребовало изменений ядра и предоставило агрегированные данные от сотен тысяч серверов в течение нескольких часов. Результаты подтвердили, что идентифицированный сервис действительно является единственным легитимным пользователем.

Таким образом, развертывание bpf-lsm было намеренно выполнено в два этапа:

  1. Сначала получить видимость. Отправить конфигурацию ebpf-exporter, управляемую salt. Подтвердить на уровне метрик, что известный сервис фактически единственный, кто создает сокеты AF_ALG.

  2. Затем применить контроль. Отправить программу bpf-lsm за отдельным шлюзом контроля.

Параллельно стал доступен обратный порт для большинства наших версий LTS, и наша внутренняя автоматизация собрала исправленное ядро на его основе.

Мы начали тестирование исправленного ядра в наших промежуточных дата-центрах как можно скорее, а затем возобновили более длительный процесс перезагрузки, чтобы полностью исправить наш парк.

Устранение последствий и дальнейшие шаги

Хотя мы были готовы к этому сценарию, в Cloudflare мы всегда учимся и совершенствуемся. Ключевые области, которые мы определили для улучшения:

  • Улучшение видимости зависимостей от API ядра. Мы проведем обзор использования подсистем ядра в продуктивных сервисах, чтобы можно было быстро смягчать эксплойты без нарушения работы сервисов.

  • Улучшение смягчения во время выполнения. bpf-lsm — ценный инструмент для смягчения, но мы хотим сделать его еще лучше. Это включает изучение более быстрых развертываний, лучших сценариев действий, а также улучшение журналирования и видимости инструмента.

  • Сокращение поверхности атаки ядра Linux. Проверить и проаудировать нашу конфигурацию ядра. Активно выявлять неиспользуемые модули или функции, чтобы удалить их из нашей сборки полностью.

Заключение

Уязвимость "Copy Fail" стала для нас уникальной проблемой. Несмотря на нашу практику развертывания обновлений патчей Linux каждые две недели, мы оставались уязвимыми, потому что исправление из основной ветки, выпущенное месяц назад, еще не было перенесено в нашу основную линию ядра. Несмотря на это, мы смогли развернуть исправленные ядра в течение нескольких часов после выпуска бэкпорта. В промежутке bpf-lsm предоставил точечное смягчение без перезагрузки, которое защитило наш парк машин. Хотя наша первоначальная попытка отключить проблемный модуль не удалась, она произошла безопасно в нашей внутренней тестовой среде, а не в продакшене, что позволило нам выявить эту зависимость.

К концу развертывания каждая машина в нашем парке была защищена либо исправленным ядром, либо программой bpf-lsm, блокирующей уязвимый путь кода для бинарных файлов, не входящих в белый список. Никакого влияния на клиентов в ходе этого инцидента не было, и мы взяли на себя обязательства по дальнейшей работе, описанной выше, чтобы ускорить нашу реакцию и улучшить видимость в следующий раз, когда произойдет нечто подобное. Ответственное раскрытие информации работает, инструменты внутриядерной видимости окупаются именно в такие моменты, а bpf-lsm продолжает оставаться одним из самых полезных примитивов для смягчения последствий во время выполнения ядра.