CVE-2026-23342 in Linux Kernel
Resumen
En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta: bpf: Corrige condición de carrera en cpumap en PREEMPT_RT En kernels PREEMPT_RT, la xdp_bulk_queue (bq) por CPU puede ser accedida concurrentemente por múltiples tareas preemptibles en la misma CPU. El código original asume que bq_enqueue() y __cpu_map_flush() se ejecutan atómicamente una con respecto a la otra en la misma CPU, confiando en local_bh_disable() para prevenir la preemption. Sin embargo, en PREEMPT_RT, local_bh_disable() solo llama a migrate_disable() (cuando PREEMPT_RT_NEEDS_BH_LOCK no está configurado) y no deshabilita la preemption, lo que permite que la planificación CFS preempte una tarea durante bq_flush_to_queue(), permitiendo que otra tarea en la misma CPU entre en bq_enqueue() y opere en la misma bq por CPU concurrentemente. Esto conduce a varias condiciones de carrera: 1. Doble __list_del_clearprev(): después de que bq->count se reinicia en bq_flush_to_queue(), una tarea preemptora puede llamar a bq_enqueue() -> bq_flush_to_queue() en la misma bq cuando bq->count alcanza CPU_MAP_BULK_SIZE. Ambas tareas luego llaman a __list_del_clearprev() en el mismo bq->flush_node, la segunda llamada desreferencia el puntero prev que ya había sido establecido a NULL por la primera. 2. Condiciones de carrera de bq->count y bq->q[]: bq_enqueue() concurrente puede corromper la cola de paquetes mientras bq_flush_to_queue() la está procesando. La condición de carrera entre la tarea A (__cpu_map_flush -> bq_flush_to_queue) y la tarea B (bq_enqueue -> bq_flush_to_queue) en la misma CPU: Tarea A (xdp_do_flush) Tarea B (cpu_map_enqueue) ---------------------- ------------------------ bq_flush_to_queue(bq) spin_lock(&q->producer_lock) /* vaciar bq->q[] a ptr_ring */ bq->count = 0 spin_unlock(&q->producer_lock) bq_enqueue(rcpu, xdpf) <-- CFS preempte la Tarea A --> bq->q[bq->count++] = xdpf /* ... más encolamientos hasta llenarse ... */ bq_flush_to_queue(bq) spin_lock(&q->producer_lock) /* vaciar a ptr_ring */ spin_unlock(&q->producer_lock) __list_del_clearprev(flush_node) /* establece flush_node.prev = NULL */ <-- La Tarea A se reanuda --> __list_del_clearprev(flush_node) flush_node.prev->next = ... /* prev es NULL -> kernel oops */ Solucione esto añadiendo un local_lock_t a xdp_bulk_queue y adquiriéndolo en bq_enqueue() y __cpu_map_flush(). Estas rutas ya se ejecutan bajo local_bh_disable(), por lo que se usa local_lock_nested_bh() que en sistemas no-RT es una anotación pura sin sobrecarga, y en PREEMPT_RT proporciona un bloqueo de suspensión por CPU que serializa el acceso a la bq. Para reproducir, inserte un mdelay(100) entre bq->count = 0 y __list_del_clearprev() en bq_flush_to_queue(), luego ejecute el reproductor proporcionado por syzkaller.
Responsable
Linux
Reservar
2026-01-13
Divulgación
2026-03-25
Voces
VulDB provides additional information and datapoints for this CVE:
| ID | Vulnerabilidad | CWE | Exp | Con | CVE |
|---|---|---|---|---|---|
| 353111 | Linux Kernel bpf bq_enqueue denegación de servicio | 476 | No está definido | Arreglo oficial | CVE-2026-23342 |