Выявлены две новые уязвимости в подсистеме eBPF, позволяющей запускать обработчики внутри ядра Linux в специальной виртуальной машине с JIT. Обе уязвимость дают возможность выполнить свой код с правами ядра, вне изолированной виртуальной машины eBPF. Информацию о проблемах опубликовала команда Zero Day Initiative, проводящая соревнования Pwn2Own, в ходе которых в этом году были продемонстрированы три атаки на Ubuntu Linux, в которых использовались ранее неизвестные уязвимости (связаны ли уявзимости в eBPF с данными атаками не сообщается).
- CVE-2021-3490 – уязвимость вызвана отсутствием проверки выхода за границу 32-разрядных значений при выполнения битовых операций AND, OR и XOR в eBPF ALU32. Атакующий может воспользоваться данной ошибкой для чтения и записи данных вне границ выделенного буфера. Проблема с операций XOR проявляется начиная с версии ядра 5.7-rc1, а AND и OR – начиная с выпуска 5.10-rc1.
- CVE-2021-3489 – уязвимость вызвана ошибкой в реализации кольцевого буфера и связана с тем, что функция bpf_ringbuf_reserve не проверяла возможность того, что размер выделенной области памяти может оказаться меньше фактического размера кольцевого буфера ringbuf. Проблема проявляется начиная с выпуска 5.8-rc1.
Статус исправления уязвимостей в дистрибутивах можно проследить на данных страницах: Ubuntu, Debian, RHEL, Fedora, SUSE, Arch). Исправления также доступны в виде патчей (CVE-2021-3489, CVE-2021-3490). Возможность эксплуатации проблемы зависит от доступности пользователю системного вызова eBPF. Например, в конфигурации по умолчанию в RHEL для эксплуатации уязвимости требуется наличие у пользователя прав CAP_SYS_ADMIN.
Отдельно можно отметить ещё одну уязвимость в ядре Linux – CVE-2021-32606, позволяющую локальному пользователю поднять свои привилегии до уровня root. Проблема проявляется начиная с ядра Linux 5.11 и вызвана состоянием гонки в реализации протокола CAN ISOTP, которое даёт возможность изменить параметры привязки к сокету из-за отсутствия установки должных блокировок в функции isotp_setsockopt() при обработке флага CAN_ISOTP_SF_BROADCAST.
После закрытия сокета ISOTP продолжает действовать привязка к сокету получателя, который может продолжить использовать связанные с сокетом структуры после освобождения связанной с ними памяти (use-after-free из-за обращения при вызове isotp_rcv() к уже освобождённой структуре isotp_sock). Через манипуляции с данными можно добиться переопределения указателя на функцию sk_error_report() и выполнить свой код на уровне ядра.