Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

Vulnerabilidad en kernel de Linux (CVE-2025-37772)

Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
01/05/2025
Última modificación:
02/05/2025

Descripción

En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: RDMA/cma: Se corrige el fallo de la cola de trabajo en cma_netevent_work_handler. La estructura rdma_cm_id tiene el miembro "struct work_struct net_work", que se reutiliza para encolar cma_netevent_work_handler()s en cma_wq. El fallo [1] puede ocurrir si se realizan varias llamadas a cma_netevent_callback() en rápida sucesión, lo que encola aún más cma_netevent_work_handler()s para el mismo rdma_cm_id, sobrescribiendo cualquier elemento de trabajo previamente en cola que se haya programado para ejecutarse. Es decir, no hay garantía de que el elemento de trabajo en cola se ejecute entre dos llamadas sucesivas a cma_netevent_callback() y el segundo INIT_WORK sobrescribiría el primer elemento de trabajo (para el mismo rdma_cm_id), a pesar de obtener id_table_lock durante la encola. Además, el análisis drgn [2] indica que es probable que el elemento de trabajo se haya sobrescrito. Para solucionarlo, mueva INIT_WORK() a __rdma_create_id(), de modo que no compita con ninguna queue_work() existente ni con su subproceso de trabajo. [1] Pila de fallos recortada: =============================================== ERROR: desreferencia de puntero NULL del núcleo, dirección: 000000000000008 kworker/u256:6 ... 6.12.0-0... Cola de trabajo: cma_netevent_work_handler [rdma_cm] (rdma_cm) RIP: 0010:process_one_work+0xba/0x31a Seguimiento de llamadas: worker_thread+0x266/0x3a0 kthread+0xcf/0x100 ret_from_fork+0x31/0x50 ret_from_fork_asm+0x1a/0x30 ============================================= [2] drgn crash analysis: >>> trace = prog.crashed_thread().stack_trace() >>> trace (0) crash_setup_regs (./arch/x86/include/asm/kexec.h:111:15) (1) __crash_kexec (kernel/crash_core.c:122:4) (2) panic (kernel/panic.c:399:3) (3) oops_end (arch/x86/kernel/dumpstack.c:382:3) ... (8) process_one_work (kernel/workqueue.c:3168:2) (9) process_scheduled_works (kernel/workqueue.c:3310:3) (10) worker_thread (kernel/workqueue.c:3391:4) (11) kthread (kernel/kthread.c:389:9) Line workqueue.c:3168 for this kernel version is in process_one_work(): 3168 strscpy(worker->desc, pwq->wq->name, WORKER_DESC_LEN); >>> trace[8]["work"] *(struct work_struct *)0xffff92577d0a21d8 = { .data = (atomic_long_t){ .counter = (s64)536870912, <=== Note }, .entry = (struct list_head){ .next = (struct list_head *)0xffff924d075924c0, .prev = (struct list_head *)0xffff924d075924c0, }, .func = (work_func_t)cma_netevent_work_handler+0x0 = 0xffffffffc2cec280, } Suspicion is that pwq is NULL: >>> trace[8]["pwq"] (struct pool_workqueue *) In process_one_work(), pwq is assigned from: struct pool_workqueue *pwq = get_work_pwq(work); and get_work_pwq() is: static struct pool_workqueue *get_work_pwq(struct work_struct *work) { unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) return work_struct_pwq(data); else return NULL; } WORK_STRUCT_PWQ is 0x4: >>> print(repr(prog['WORK_STRUCT_PWQ'])) Object(prog, 'enum work_flags', value=4) But work->data is 536870912 which is 0x20000000. So, get_work_pwq() returns NULL and we crash in process_one_work(): 3168 strscpy(worker->desc, pwq->wq->name, WORKER_DESC_LEN); =============================================

Impacto