CVE-2026-98595 in Linux
Resumen
por VulDB • 2026-10-19
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
udp: eliminar un socket desconectado de la tabla hash de 4-tuplas
Un socket UDP vinculado a una dirección y puerto específicos mantiene su entrada en la tabla hash de 4-tuplas después de ser desconectado:
sk se vincula a 127.0.0.1:21001 sk se conecta a 127.0.0.2:20001 // registrado en la tabla de 4-tuplas sk se desconecta, connect(AF_UNSPEC) // sigue registrado, el par ahora es 0.0.0.0:0
__udp_disconnect() extrae un socket de esa tabla solo como efecto secundario de ->rehash() o ->unhash(), y omite ->rehash() cuando SOCK_BINDADDR_LOCK está establecido y ->unhash() cuando SOCK_BINDPORT_LOCK está establecido. El commit 6996a2d2d0a6 ("udp: Unhash auto-bound connected sk from 4-tuple hash table when disconnected.") corrigió el mismo estado final para un socket vinculado a comodín, mediante una ruta que este caso no sigue.
La entrada se cuenta independientemente de si algo la consulta o no. hash4_cnt en la ranura hash2 permanece elevada mientras viva el socket, por lo que udp_has_hash4() continúa enviando cada paquete dirigido a esa dirección y puerto primero a través de la búsqueda de 4-tuplas.
En IPv6 también puede ser consultado. __udp_disconnect() no borra sk_v6_daddr, por lo que udp_v6_rehash() registra la entrada bajo el par al que estaba conectado el socket con un dport cero, e inet6_match() compara ese mismo campo: un datagrama del antiguo par con un puerto de origen cero coincide, y se acepta el puerto de origen cero en recepción. En IPv4 el par se borra, por lo que una coincidencia necesitaría también una dirección de origen cero, la cual la capa de enrutamiento rechaza como martiana. El sk_v6_daddr obsoleto es un defecto separado, no abordado aquí; eliminar la entrada cierra esta ruta de todos modos.
La entrada también puede ser reubicada. __udp_disconnect() borra sk_bound_dev_if, por lo que una llamada posterior a SO_BINDTODEVICE activa ->rehash(), y debido a que la dirección de recepción sigue siendo específica, udp_lib_rehash() mueve la entrada en lugar de eliminarla, hacia el cubo al que hash (rcv_saddr, num, 0, 0) apunta -- una función pura de la dirección y puerto, por lo que todos los sockets que alcanzan este estado en una dirección y puerto se agrupan en un solo cubo. El cubo no puede ser elegido desde fuera, ya que udp_ehashfn() está sembrado con un secreto específico del arranque. Este último caso se volvió accesible únicamente con el commit 644f9108f3a5 ("udp: Make rehash4 independent in udp_lib_rehash()"), que movió el manejo de hash4 fuera de una rama que un socket desconectado no sigue; la entrada obsoleta en sí data del commit indicado en Fixes.
Extraiga el socket de la tabla antes de que se ejecute __udp_disconnect(), mientras aún coincide con cómo fue registrado originalmente. Esto también alcanza el caso comodín antes de la rama udp_unhash4() de udp_lib_rehash(), dejando esa rama inaccesible desde udp_disconnect(); su eliminación corresponde a net-next. udp_disconnect() y udp_abort() son las únicas entradas UDP hacia __udp_disconnect(), que es compartido con sockets raw, ping y l2tp que no son struct udp_sock: el obj_size de ping_prot es sizeof(struct inet_sock), por lo que udp_hashed4() en uno de ellos leería más allá de la asignación.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.