Ad

CVE-2026-12366

HIGH CVSS 3.1: 8,8 EPSS 0.12%
Обновлено 26 августа 2026
Zephyr
Параметр Значение
CVSS 8,8 (HIGH)
Тип уязвимости CWE-416 (Использование памяти после освобождения)
Поставщик Zephyr
Публичный эксплойт Нет

Динамический путь удаления объектов ядра Zephyr unref_check() в kernel/userspace/userspace.c освобождает хранилище объекта (k_free(dyn->data)) как только его счетчик ссылок достигает нуля после запуска очистки для каждого типа объекта. Переключатель очистки обрабатывал только K_OBJ_MSGQ и K_OBJ_STACK; случая K_OBJ_TIMER не было. Динамически выделяемый, инициализируемый и активированный k_timer сохраняет свою встроенную структуру _timeout dnode связанной с глобальной очередью таймаута (_timeout_q), поэтому при освобождении хранилища таймера без отмены таймаута в этой очереди остается висячий узел.

Когда таймер истекает в следующий раз, механизм таймаута проходит _timeout_q и вызывает z_timer_expiration_handler() на освобожденном узле, разыменовывая и записывая освобожденную (и повторно используемую) кучу ядра в контексте ядра/ISR. Это детерминированное использование после освобождения, которое не зависит от SMP: узел в очереди просто никогда не отключается в свободное время. Утилизация доступна из непривилегированного пользовательского потока под CONFIG_USERSPACE + CONFIG_DYNAMIC_OBJECTS: поток, который имеет последнее разрешение на такой таймер, удаляет его через системный вызов k_object_release() (или выходя через k_thread_perms_all_clear()) и может активировать сам таймер через системный вызов k_timer_start().

Обработчик free и обработчик срока действия запускаются с привилегиями ядра, в то время как актер является пользовательским потоком, поэтому ошибка представляет собой примитив повреждения памяти с выходом из песочницы, который можно использовать для повышения привилегий. Исправление добавляет функцию k_timer_cleanup() (отменяет тайм-аут и ждет любого текущего обработчика) и вызывает ее для K_OBJ_TIMER перед освобождением.

Показать оригинальное описание (EN)

Zephyr's dynamic kernel-object disposal path unref_check() in kernel/userspace/userspace.c frees an object's storage (k_free(dyn->data)) once its reference count reaches zero, after running a per-object-type cleanup. The cleanup switch handled only K_OBJ_MSGQ and K_OBJ_STACK; there was no K_OBJ_TIMER case. A dynamically-allocated, initialized, and armed k_timer keeps its embedded struct _timeout dnode linked in the global timeout queue (_timeout_q), so freeing the timer storage without cancelling the timeout leaves a dangling node in that queue. When the timer next expires, the timeout machinery walks _timeout_q and invokes z_timer_expiration_handler() on the freed node, dereferencing and writing freed (and reusable) kernel heap in kernel/ISR context. This is a deterministic use-after-free that does not depend on SMP: the queued node is simply never unlinked at free time. The disposal is reachable from an unprivileged user thread under CONFIG_USERSPACE + CONFIG_DYNAMIC_OBJECTS: a thread that holds the last permission on such a timer drops it via the k_object_release() syscall (or by exiting, through k_thread_perms_all_clear()), and can arm the timer itself via the k_timer_start() syscall. The free and the expiration handler run at kernel privilege while the actor is a user thread, so the bug is a sandbox-escape memory-corruption primitive usable for privilege escalation. The fix adds k_timer_cleanup() (cancel the timeout and wait for any in-flight handler) and calls it for K_OBJ_TIMER before freeing.

Характеристики атаки

Способ атаки
Локальный
Нужен локальный доступ
Сложность
Низкая
Легко эксплуатировать
Нужны права
Низкие
Нужны базовые права
Участие пользователя
Не требуется
Не нужно действие пользователя

Последствия

Конфиденциальность
Высокое
Полная утечка данных
Целостность
Высокое
Полная модификация данных
Доступность
Высокое
Полный отказ в обслуживании

Строка CVSS v3.1