Уязвимость в ядре Linux, затрагивающая сетевой протокол CAN BCM

В ядре Linux выявлена уязвимость (CVE-2021-3609), позволяющая локальному пользователю поднять свои привилегии в системе. Проблема вызвана состоянием гонки в реализации протокола CAN BCM и проявляется в выпусках ядра Linux с 2.6.25 по 5.13-rc6. В дистрибутивах проблема пока остаётся неисправленной (RHEL, Fedora, Debian, Ubuntu, SUSE, Arch).

Выявивший уязвимость исследователь смог подготовить эксплоит для получения прав root на системах с ядрами Linux 5.4 и новее, в том числе показана возможность успешного проведения атаки в Ubuntu 20.04.02 LTS. Не исключена возможность переработки эксплоита и для работы с более старыми ядрами (в ядре 5.4 код CAN BCM (net/can/bcm.c) был переведён с hrtimer_tasklet на HRTIMER_MODE_SOFT).

Протокол CAN BCM позволяет зарегистрировать собственный обработчик сообщений, поступающих через шину CAN (controller area network), и прикрепить его к определённому сетевому сокету. При поступлении входящего сообщения вызывается функция bcm_rx_handler(). Атакующий может воспользоваться состоянием гонки и добиться закрытия сетевого сокета одновременно с выполнением bcm_rx_handler(). При закрытии сокета вызывается функция bcm_release(), в которой освобождается память, выделенная для структур bcm_op и
bcm_sock, которые продолжают использоваться в ещё выполняемом обработчике bcm_rx_handler(). Возникает ситуация, приводящая к обращению к уже освобождённому блоку памяти (use-after-free).

Атака сводится к открытию двух сокетов CAN BCM и привязке их к интерфейсу vcan. В первом сокете выполняется вызов sendmsg() с флагом RX_SETUP для настройки обработчика поступающих сообщений CAN, а во втором сокете совершается вызов sendmsg() для отправки сообщения в первый сокет. После поступления сообщения срабатывает вызов bcm_rx_handler(), а атакующий подбирает нужный момент и закрывает первый сокет, что приводит к запуску bcm_release() и освобождению структур bcm_op и bcm_sock, хотя работа bcm_rx_handler() ещё не завершена.

Через манипуляции с содержимым bcm_sock атакующий может переопределить указатель на функцию sk->sk_data_ready(sk), перенаправить выполнение и при помощи приёмов возвратно-ориентированного программирования (ROP – Return-Oriented Programming) организовать перезапись параметра modprobe_path и добиться выполнения своего кода с правами root. При использовании техники ROP атакующий не пытается разместить свой код в памяти, а оперирует уже имеющимися в загруженных библиотеках кусками машинных инструкций, завершающихся инструкцией возврата управления (как правило, это окончания библиотечных функций). Работа эксплоита сводится к построению цепочки вызовов подобных блоков (“гаджетов”) для получения нужной функциональности.


Для атаки требуется наличие доступа для создания сокетов CAN и настроенный сетевой интерфейс vcan. Необходимые для совершения атаки полномочия могут быть получены непривилегированным пользователем в контейнерах, создаваемых в системах с включённой поддержкой пространств имён идентификаторов пользователей (user namespaces). Например, user namespaces по умолчанию включён в Ubuntu и Fedora, но не активирован в Debian и RHEL.

Release. Ссылка here.