Страницы

пятница, 25 августа 2017 г.

Блокирование двойного освобождения памяти в ядре Linux

7 августа эксперт Positive Technologies Александр Попов выступил на хакерском фестивале SHA2017 (Still Hacking Anyway). Запись его выступления:



В своем докладе Александр рассказал о уязвимости CVE-2017-2636 в ядре Linux и технике ее эксплуатации для локального повышения привилегий. Многое из его доклада уже было описано в статьях журнала Хакер и в нашем блоге.

В данной статье описаны новые результаты его исследования, затронутые в
выступлении на SHA2017.

Техника эксплуатации двойного освобождения памяти (double free) состоит в том,
что сначала нужно превратить его в ошибку типа "использование после
освобождения" (use-after-free). Обычно это достигается с помощью выделения блока
памяти того же размера между двойным освобождением (отражено на схеме). Данная
техника называется heap spraying.



Однако в случае CVE-2017-2636 освобождаются сразу 13 элементов, причем двойное
освобождение происходит одним из первых. Поэтому вышеописанная техника
оказывается непригодной. Но все-таки Александру удалось привести это состояние
системы к ошибке использования после освобождения. Он воспользовался наивным
поведением SLUB, основного аллокатора ядра Linux.

Оказывается, SLUB-аллокатор не препятствует последовательному двойному
освобождению одного и того же участка памяти. В отличие от него аллокатор libc
выполняет проверку под названием "fasttop", сравнительно дешевую в отношении
производительности. Идея проста: сообщить об ошибке в случае совпадения адреса
освобождаемого элемента с адресом последнего элемента в списке свободных.

Александр Попов добавил аналогичную проверку в функцию set_freepointer()
SLUB-аллокатора и отправил патч в список рассылки ядра Linux (LKML). Патч вызвал оживленное обсуждение.

В этой доработке мейнтейнерам SLUB не понравилось то, что:
  1. данная проверка выполняется на каждом добавлении элемента в список свободных (какие-то накладные расходы все же есть);
  2. данная проверка дублирует отладочный функционал slub_debug;
  3. в случае двойного освобождения памяти происходит паника ядра (предложили опускать повторное добавление элемента в список свободных).
Александр привел свои аргументы:

  1. slub_debug, действительно, предотвращает двойное освобождение памяти, однако по умолчанию не используется дистрибутивами Linux;
  2. когда аллокатор зафиксировал двойное освобождение памяти, серьезная ошибка где-то в ядре Linux уже произошла. Поэтому не стоило бы доверять процессу, в рамках которого это случилось (он может быть эксплойтом).

В итоге при содействии Кейса Кука (Kees Cook) была достигнута договоренность
включить предлагаемую проверку в опцию ядра CONFIG_SLAB_FREELIST_HARDENED.

На данный момент патч Александра принят и находится в ветке linux-next. В скором времени он должен попасть в основную ветку, Linux Kernel mainline.

Комментариев нет:

Отправить комментарий