Пока-пока, mitigations=off
Давно работаю с Linux, но почти в то же время познакомился и с FreeBSD, где make buildworld и make buildkernel — едва ли не местный вариант «Hello, World!». Так что самостоятельная сборка ядра для меня никогда не была чем-то необычным.
Поначалу меня, конечно, больше интересовала производительность.
Но примерно за год до всего этого LLM-индуцированного CVE-безумия, когда я начал активно использовать self-hosted сервисы, мои приоритеты окончательно сместились от производительности к безопасности. Образно говоря, эпоха mitigations=off окончательно канула в Лету. Напротив, приоритетными стали механизмы защиты, уже предусмотренные самими разработчиками ядра, но далеко не всегда включённые по умолчанию.
Я попросил ChatGPT оценить, насколько полезным оказался мой набор настроек применительно к CVE-2026-98432.
Немного о самой уязвимости
В основе CVE лежит race condition при обработке TCP handshake. Ядро сохраняет IPv4 options из входящего SYN в отдельно выделенном участке памяти, на который ссылается ireq->ireq_opt.
При определённом порядке обработки пакетов разными CPU один поток исполнения может продолжать читать эти данные, пока другой уже освободил соответствующую память через kfree().
Получается классический use-after-free (UAF). Если освобождённый участок успел достаться другому объекту, содержимое памяти может оказаться совсем не тем, которое ожидает сетевой стек. Отсюда возможность утечки данных и дальнейшей эксплуатации повреждения памяти.
Закономерно, что мне стало интересно: а насколько мои настройки усложняют эксплуатацию этой ошибки ещё до установки исправления?
Что оказалось включено
CONFIG_RANDOM_KMALLOC_CACHES=y
Пожалуй, самое интересное в данном случае. Обычные kmalloc-выделения распределяются между 16 наборами кэшей. Выбор зависит от адреса вызывающего кода и случайного seed, заданного при загрузке.
Атакующему уже недостаточно подобрать выделение подходящего размера: нужно ещё добиться попадания в тот же slab-кэш, что и уязвимый объект.
Это осложняет heap spraying и целенаправленное повторное использование освобождённой памяти. Впрочем, изоляция не абсолютна: возможны коллизии, а выделения из одного и того же call site обычно попадают в один кэш.
CONFIG_SLAB_FREELIST_RANDOM=y
Рандомизирует порядок свободных объектов при создании новых slab-страниц. Это усложняет предсказание их размещения и последующего повторного использования.
Важно, что речь не о перемешивании при каждом kmalloc() или kfree(). Поэтому влияние на уже подготовленный heap ограничено.
CONFIG_SLAB_FREELIST_HARDENED=y
Добавляет защиту метаданных freelist, затрудняя атаки, в которых повреждение этих метаданных используется для управления последующими выделениями памяти.
Это не защита непосредственно от UAF, но дополнительное препятствие для некоторых вариантов развития атаки после повреждения heap.
slab_nomerge
Запрещает объединение совместимых slab-кэшей. В результате объекты разных специализированных кэшей сложнее разместить в одной области памяти для cross-cache exploitation.
Однако обычные kmalloc-выделения по-прежнему могут совместно использовать generic-кэши. Здесь как раз становится интересным сочетание с CONFIG_RANDOM_KMALLOC_CACHES.
И что в итоге?
Разумеется, ни одна из этих настроек не исправляет саму гонку. Уязвимый код остаётся достижимым, и use-after-free по-прежнему возможен.
Но между «вызвать UAF» и «превратить его в удалённое выполнение кода с правами root» лежит немалый путь. И некоторые из перечисленных механизмов способны существенно осложнить отдельные его этапы.
Насколько всё это помешало бы конкретному эксплойту Anthropic, неизвестно: его код и подробности heap exploitation не опубликованы. Но и считать подобный hardening бесполезным оснований нет. Я бы даже сказал, что при таких раскладах, нужно использовать всё, что можно.