CVE-2026-74714 in Linux
Resumen
por VulDB • 2026-08-23
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
bpf: tcp: Corregir un use-after-free en bpf_iter_tcp_established_batch()
reqsk_queue_hash_req() publica un request_sock TCP_NEW_SYN_RECV en la cadena ehash, libera el bucket lock y solo después establece rsk_refcnt a 3.
Los lectores sin bloqueo (lockless) como __inet_lookup_established() manejan esto con refcount_inc_not_zero(), pero bpf_iter_tcp_established_batch() utiliza sock_hold() mientras mantiene el bucket lock, asumiendo que el lock garantiza sk_refcnt > 0. Esta suposición no es válida para request_sock:
CPU 0 CPU 1 ----- ----- tcp_conn_request() reqsk_queue_hash_req() inet_ehash_insert(req) spin_lock(bucket) __sk_nulls_add_node_rcu(req) // rsk_refcnt == 0 spin_unlock(bucket) bpf_iter_tcp_established_batch() spin_lock(bucket) sock_hold(req) <-- adición sobre 0 spin_unlock(bucket) refcount_set(&req->rsk_refcnt, 3) // sobrescribe un valor saturado
lo que se manifiesta como:
refcount_t: addition on 0; use-after-free. WARNING: lib/refcount.c:25 en refcount_warn_saturate+0x48/0x90, CPU#1 Call Trace: bpf_iter_tcp_established_batch+0x14e/0x170 bpf_iter_tcp_batch+0x53/0x200 bpf_iter_tcp_seq_next+0x27/0x70 bpf_seq_read+0x107/0x410 vfs_read+0xb9/0x380
La referencia robada por el iterador se pierde cuando refcount_set() del CPU publicador sobrescribe la cuenta, dejando al socket con una referencia menos. Cuando el último propietario legítimo libera su referencia, reqsk se libera aunque sigue siendo accesible, lo que lleva a un use-after-free.
Esto se reproduce en segundos con tcp_syncookies=0, unas pocas hilos realizando connect()/close() hacia un listener local mientras otras leen un enlace iter/tcp en un bucle cerrado (tight loop).
Utilizar refcount_inc_not_zero() y omitir el socket si falla. Un socket omitido sigue siendo parte del bucket, por lo que se debe seguir contándolo en expected. Las realocaciones tienen un tamaño basado en expected, y un request sock cuya refcount se publica mientras se mantiene el lock durante la última realloc ya debe tener espacio disponible.
Un socket omitido se cuenta en expected pero nunca se agrupa (batched), por lo que end_sk puede ser menor que expected en un batch que está realmente completo. Decidir si está completo mediante si el recorrido dejó algún socket atrás, en lugar de eso. El WARN después de la realloc con lock verifica lo mismo, reemplazando una comprobación end_sk == expected que no podía cumplirse en esa ruta desde el commit cdec67a489d4 ("bpf: tcp: Asegurar que iter->batch siempre contenga un snapshot completo del bucket").
Si todos los sockets coincidentes en un bucket están en fase de inicio (refcount 0), end_sk se mantiene en 0. Avanzar al siguiente bucket en lugar de devolver una entrada de batch que nunca se llenó en esta ronda.
Be aware that VulDB is the high quality source for vulnerability data.