19.04.2021

В ядро Linux 5.12 принята подсистема KFence для выявления ошибок при работе с памятью

В состав находящегося в разработке ядра Linux 5.12 включена реализация механизма KFence (Kernel Electric Fence), который проверяет работу с памятью, отлавливая выход за границы буферов, обращения к памяти после освобождения и другие ошибки подобного класса.

Подобная функциональность уже присутствовала в ядре в виде опции сборки KASAN (kernel address sanitizer, использует Address Sanitizer в современных gcc и clang) — однако позиционировалась в основном для отладочного применения. Подсистема KFence отличается от KASAN высокой скоростью работы, что позволяет использовать эту возможность даже на ядрах в рабочих системах.

Применение на рабочих системах даст возможность отлавливать ошибки работы с памятью, которые не проявляются в тестовых запусках и всплывают только на рабочих нагрузках или при длительной работе (при большом uptime). Кроме того, применение KFence на рабочих системах даст возможность существенно увеличить число машин, вовлечённых в проверку работы ядра с памятью.

Минимальные накладные расходы, не зависящие от нагрузки, достигаются в KFence благодаря подстановке страниц защиты (guard pages) в кучу через фиксированные интервалы. После истечения времени очередного интервала защиты KFence через штатную систему распределения памяти (SLAB или SLUB allocator) добавляет очередную страницу защиты из пула объектов KFence, и начинает новый отчёт счётчика времени. Каждый объект KFence размещается в отдельной странице памяти, а страницы памяти по левой и правой границе образуют страницы защиты (guard pages), размер которых выбирается случайно.

Таким образом, страницы с объектами отделяются друг от друга страницами защиты, которые настраиваются на генерацию «page fault» при любом обращении. Для выявления операций записи за границу буфера внутри страниц с объектами дополнительно используются «красные зоны» на основе шаблонов, которые занимают память, не используемую объектами, остающуюся при выравнивании размера страниц памяти.


---+-----------+-----------+-----------+-----------+-----------+--- | xxxxxxxxx | O : | xxxxxxxxx | : O | xxxxxxxxx | | xxxxxxxxx | B : | xxxxxxxxx | : B | xxxxxxxxx | | x GUARD x | J : RED- | x GUARD x | RED- : J | x GUARD x | | xxxxxxxxx | E : ZONE | xxxxxxxxx | ZONE : E | xxxxxxxxx | | xxxxxxxxx | C : | xxxxxxxxx | : C | xxxxxxxxx | | xxxxxxxxx | T : | xxxxxxxxx | : T | xxxxxxxxx |
---+-----------+-----------+-----------+-----------+-----------+---

В случае попытки обращения к области вне границ буфера операция затрагивает страницу защиты, что приводит к генерации «page fault», который перехватывает KFence и выводит в лог данные о выявленной проблеме. По умолчанию KFence не блокирует ошибку и лишь выводит предупреждение в лог, но предусмотрена настройка «panic_on_warn», позволяющая в случае выявления ошибки переводить ядро в состояние краха (panic).

Источник.