В подсистеме динамических объектов пользовательского пространства Zephyr функция thread_idx_alloc() в файле kernel/userspace/userspace.c выделила новый индекс разрешений потока из глобального битового изображения _thread_idx_map[] без сохранения lists_lock. В системах SMP два потока пользовательского режима, одновременно вызывающие системный вызов k_object_alloc(K_OBJ_THREAD), могут наблюдать за одним и тем же младшим свободным битом, выполнять одно и то же неатомарное RMW для его очистки и возвращать идентичный tidx. Двум вновь созданным объектам K_OBJ_THREAD затем назначается один и тот же thread_id, поэтому два пользовательских потока псевдонимируют одну битовую позицию в битовом поле perms[] каждого объекта ядра: любое последующее предоставление доступа к объекту ядра одному потоку является неявным предоставлением другому, что устраняет изоляцию ACL пользовательского пространства.
Вторичное окно потери обновлений между разблокированным &=~BIT() в alloc и заблокированным |= BIT() в thread_idx_free() также может привести к утечке записей из пула индексов потоков. Дефект доступен из любого потока пользовательского режима через неограниченный __syscall k_object_alloc и ограничен CONFIG_USERSPACE, CONFIG_DYNAMIC_OBJECTS и CONFIG_SMP. Уязвимость появилась, когда в 2018 году был добавлен индекс разрешений для каждого потока, и он присутствует во всех выпусках до версии 4.4.0 включительно.
Исправлено путем удержания lists_lock в растровом изображении RMW и очистки разрешений (и встраивания обхода obj_list, который ранее взял саму блокировку).
Показать оригинальное описание (EN)
In Zephyr's userspace dynamic-objects subsystem, thread_idx_alloc() in kernel/userspace/userspace.c allocated a new thread permission index from the global _thread_idx_map[] bitmap without holding lists_lock. On SMP systems, two user-mode threads invoking the k_object_alloc(K_OBJ_THREAD) syscall concurrently can both observe the same low free bit, perform the same non-atomic RMW to clear it, and return the identical tidx. The two newly created K_OBJ_THREAD objects are then assigned the same thread_id, so the two user threads alias a single bit position in every kernel object's perms[] bitfield: any subsequent grant of access on a kernel object to one thread is implicitly a grant to the other, defeating userspace ACL isolation. A secondary lost-update window between the unlocked &=~BIT() in alloc and the locked |= BIT() in thread_idx_free() can also leak entries from the thread-index pool. The defect is reachable from any user-mode thread via the unrestricted __syscall k_object_alloc and is gated on CONFIG_USERSPACE, CONFIG_DYNAMIC_OBJECTS, and CONFIG_SMP. The flaw was introduced when the per-thread permission index was added in 2018 and is present in every release up to and including v4.4.0. Fixed by holding lists_lock across the bitmap RMW and the permissions clear (and inlining the obj_list traversal that previously took the lock itself).
Характеристики атаки
Последствия
Строка CVSS v3.1