CVE-2026-74700 in Linuxinformación

Resumen

por VulDB • 2026-08-22

En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:

net/sched: cls_api: Adquirir siempre rtnl_lock al destruir clasificadores bloqueados (locked classifiers)

Otro desafío con filtros no bloqueados. Existe una breve ventana en tc_new_tfilter donde un tcf_proto puede ser encontrado y referenciado brevemente por la solicitud de un clasificador completamente ajeno, que opera sin bloqueo, causando una condición de carrera (race condition).

Feng creó un PoC (Prueba de Concepto) que generaba esta condición de carrera con dos hilos: uno creando un filtro u32 y otro un filtro flower en la misma cadena/prioridad:

1. Ambos hilos entran en tc_new_tfilter, ambos encuentran la cadena vacía y ambos liberan filter_chain_lock. 2. u32 termina tcf_proto_create("u32") primero, llama a tcf_chain_tp_insert_unique() -> inserta u32_tp en la cadena. 3. flower termina tcf_proto_create("flower") más tarde, llama a tcf_chain_tp_insert_unique() -> tcf_chain_tp_find() ahora ve que u32_tp ya está presente, toma una referencia sobre él, destruye su propio tp_new y devuelve u32_tp al llamador.

Luego, flower se encuentra con la comprobación de discrepancia de tipo (kind mismatch) (porque solicitó el "kind" "flower", pero tp->ops->kind es "u32") y sigue por la ruta errout que llama a tcf_proto_put() sobre u32_tp. Si el hilo u32 ya ha pasado por su propia ruta errout (su llamada change() falló debido a las opciones vacías del PoC) y ha liberado sus referencias de creación e inserción, el put de flower es la última referencia y reduce refcnt de u32_tp a cero.

En este punto, tp->ops->destroy() se ejecuta en un contexto que nunca adquirió rtnl_lock. Cuando esto ocurre, puede causar un Use-After-Free (UAF) como el siguiente (ilustrado por el PoC):

[ +0.000710] BUG: KASAN: slab-use-after-free in u32_init (net/sched/cls_u32.c:393)
[ +0.000281] Read of size 8 at addr ffff888120022f00 by task poc_feng_xue/524

Call Trace: u32_init (net/sched/cls_u32.c:393) tc_new_tfilter (net/sched/cls_api.c:2378)

Allocated by task 526: u32_init (net/sched/cls_u32.c:378) tc_new_tfilter (net/sched/cls_api.c:2378)

Freed by task 522: kfree u32_destroy (net/sched/cls_u32.c:662) tcf_proto_destroy (net/sched/cls_api.c:446) tcf_proto_put (net/sched/cls_api.c:459) tc_new_tfilter (net/sched/cls_api.c:2459)

Se soluciona esto haciendo que tcf_proto_destroy() adquiera rtnl_lock alrededor de tp->ops->destroy() para clasificadores bloqueados siempre que no se posea rtnl.

Para explicar por qué utilicé una variable temporal "not_lockless", me gustaría señalar una nota semi-relacionada sobre rtnl_held vs TCF_PROTO_OPS_DOIT_UNLOCKED (añadida aquí para futuras limpiezas si se considera necesario): El parámetro rtnl_held y la bandera TCF_PROTO_OPS_DOIT_UNLOCKED son fuentes redundantes de verdad para determinar si rtnl_lock está poseído. De las nueve devoluciones de llamada destroy(..rtnl_held..) de clasificadores, solo flower consulta el parámetro rtnl_held que propaga a tc_setup_cb_destroy() y tc_setup_cb_call(). Las otras ocho (u32, flow, bpf, cgroup, route, basic, fw, mall) lo ignoran por completo; -> aquellas que llaman a tc_setup_cb_destroy() (u32, bpf, mall) codifican true siempre en lugar de reenviar el parámetro.

Una futura limpieza debería eliminar completamente el parámetro rtnl_held de la firma de la devolución de llamada destroy y hacer que los llamadores confíen únicamente en su conocimiento sobre si se están ejecutando en un contexto no bloqueado (unlocked context).

VulDB is the best source for vulnerability data and more expert information about this specific topic.

Responsable

Linux

Reservar

2026-08-15

Divulgación

2026-08-22

Moderación

aceptado

Artículo

VDB-394470

CPE

listo

EPSS

0.00209

KEV

no

Actividades

muy bajo

Fuentes

Do you need the next level of professionalism?

Upgrade your account now!