CVE-2026-98595
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
udp: eliminar un socket desconectado de la tabla hash de 4-tupla
Un socket UDP vinculado a una dirección y puerto específicos mantiene su entrada en la tabla hash de 4-tupla después de desconectarse:
__udp_disconnect() extrae un socket de esa tabla solo como efecto secundario de ->rehash() o ->unhash(), y omite ->rehash() cuando se establece SOCK_BINDADDR_LOCK y ->unhash() cuando se establece SOCK_BINDPORT_LOCK. commit 6996a2d2d0a6 ("udp: Unhash auto-bound connected sk from 4-tuple hash table when disconnected.") corrigió el mismo estado final para un socket vinculado con comodín, por una ruta que este no toma.
Leer descripción completaMostrar menos
La entrada se cuenta independientemente de si algo la alcanza. hash4_cnt en el slot hash2 permanece elevado mientras el socket existe, por lo que udp_has_hash4() sigue enviando cada paquete para esa dirección y puerto primero a través de la búsqueda de 4-tupla.
En IPv6 también puede alcanzarse. __udp_disconnect() no limpia sk_v6_daddr, por lo que udp_v6_rehash() registra la entrada bajo el peer al que se conectó el socket con un dport cero, e inet6_match() compara ese mismo campo: un datagrama del peer anterior con un puerto de origen cero coincide, y el puerto de origen cero se acepta al recibir. En IPv4 el peer se limpia, por lo que una coincidencia necesitaría también una dirección de origen cero, que la capa de enrutamiento rechaza como marciana. sk_v6_daddr obsoleto es un defecto separado, no tratado aquí; eliminar la entrada cierra esta ruta de cualquier forma.
La entrada también puede reubicarse. __udp_disconnect() limpia sk_bound_dev_if, por lo que las llamadas posteriores de SO_BINDTODEVICE a ->rehash(), y como la dirección de recepción aún es específica, udp_lib_rehash() mueve la entrada en lugar de eliminarla, hacia el bucket que (rcv_saddr, num, 0, 0) codifica — una función pura de la dirección y el puerto, por lo que cada socket que alcanza este estado en una dirección y puerto se agrupa en un bucket. El bucket no puede elegirse desde fuera, ya que udp_ehashfn() se genera con un secreto por arranque. Este último se hizo alcanzable solo con commit 644f9108f3a5 ("udp: Make rehash4 independent in udp_lib_rehash()"), que movió el manejo hash4 fuera de una rama que un socket desconectado no toma; la entrada obsoleta en sí proviene del commit en Fixes.
Extraer el socket de la tabla antes de que se ejecute __udp_disconnect(), mientras aún coincida con cómo se registró. Esto también alcanza el caso comodín antes de la rama udp_unhash4() de udp_lib_rehash(), dejando esa rama inalcanzable desde udp_disconnect(); su eliminación pertenece a net-next. udp_disconnect() y udp_abort() son los únicos puntos de entrada UDP a __udp_disconnect(), que se comparte con sockets raw, ping y l2tp que no son struct udp_sock: ping_prot.obj_size es sizeof(struct inet_sock), por lo que udp_hashed4() en uno leería más allá de la asignación.
Detalles técnicos trazas, registros y código del informe original
sk se vincula a 127.0.0.1:21001
sk se conecta a 127.0.0.2:20001 // registrado en la tabla de 4-tupla
sk se desconecta, connect(AF_UNSPEC) // aún registrado, peer ahora 0.0.0.0:0Traducción automática del texto original de NVD (en inglés).
CVSS
NVD no ha asignado puntuación CVSS a esta CVE (habitual desde el cambio de política de abril de 2026).
Probabilidad de explotación (EPSS)
- Probabilidad de explotación en los próximos 30 días
- 0.20 %
- Percentil entre todas las CVEs puntuadas
- 9
- Fecha de la puntuación
- 20/10/2026
EPSS (Exploit Prediction Scoring System, de FIRST) estima la probabilidad de que una vulnerabilidad sea explotada en 30 días. Complementa a CVSS (impacto) y a CISA KEV (explotación confirmada).
Tecnologías afectadas (1)
⚠ Inferidas por IA a partir de la descripción — NVD aún no ha analizado esta CVE; no son CPE verificados.
Referencias
JSON original (NVD)
Mostrar
{
"id": "CVE-2026-98595",
"cveTags": [],
"metrics": {},
"affected": [
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"affectedData": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "78c91ae2c6deb5d236a5a93ff2995cdd05514380",
"lessThan": "c21daf37d5ce9a4e234b7c42238ac1e6041e28e4",
"versionType": "git"
},
{
"status": "affected",
"version": "78c91ae2c6deb5d236a5a93ff2995cdd05514380",
"lessThan": "d1b5fd969cc53f29d02b82b05a45135de4a6087a",
"versionType": "git"
},
{
"status": "affected",
"version": "78c91ae2c6deb5d236a5a93ff2995cdd05514380",
"lessThan": "9e95b1a94c9c49b4ba722251bbca2759b9c51737",
"versionType": "git"
}
],
"programFiles": [
"net/ipv4/udp.c"
],
"defaultStatus": "unaffected"
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "6.13"
},
{
"status": "unaffected",
"version": "0",
"lessThan": "6.13",
"versionType": "semver"
},
{
"status": "unaffected",
"version": "6.18.55",
"versionType": "semver",
"lessThanOrEqual": "6.18.*"
},
{
"status": "unaffected",
"version": "7.2.9",
"versionType": "semver",
"lessThanOrEqual": "7.2.*"
},
{
"status": "unaffected",
"version": "7.3",
"versionType": "original_commit_for_fix",
"lessThanOrEqual": "*"
}
],
"programFiles": [
"net/ipv4/udp.c"
],
"defaultStatus": "affected"
}
]
}
],
"published": "2026-10-18T16:17:12.163",
"references": [
{
"url": "https://git.kernel.org/stable/c/9e95b1a94c9c49b4ba722251bbca2759b9c51737",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/c21daf37d5ce9a4e234b7c42238ac1e6041e28e4",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/d1b5fd969cc53f29d02b82b05a45135de4a6087a",
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}
],
"vulnStatus": "Received",
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nudp: remove a disconnected socket from the 4-tuple hash table\n\nA UDP socket bound to a specific address and port keeps its entry in the\n4-tuple hash table after it is disconnected:\n\n sk binds to 127.0.0.1:21001\n sk connects to 127.0.0.2:20001\t// filed in the 4-tuple table\n sk disconnects, connect(AF_UNSPEC)\t// still filed, peer now 0.0.0.0:0\n\n__udp_disconnect() takes a socket out of that table only as a side effect\nof ->rehash() or ->unhash(), and it skips ->rehash() when\nSOCK_BINDADDR_LOCK is set and ->unhash() when SOCK_BINDPORT_LOCK is set.\ncommit 6996a2d2d0a6 (\"udp: Unhash auto-bound connected sk from 4-tuple hash\ntable when disconnected.\") fixed the same end state for a wildcard-bound\nsocket, by a path this one does not take.\n\nThe entry is counted whether or not anything hits it. hash4_cnt on the\nhash2 slot stays raised for as long as the socket lives, so udp_has_hash4()\nkeeps sending every packet for that address and port through the 4-tuple\nlookup first.\n\nOn IPv6 it can also be hit. __udp_disconnect() does not clear sk_v6_daddr,\nso udp_v6_rehash() files the entry under the peer the socket was connected\nto with a zero dport, and inet6_match() compares that same\nfield: a datagram from the former peer with a zero source port matches,\nand source port zero is accepted on receive. On IPv4 the peer is cleared,\nso a match would need a zero source address as well, which the routing\nlayer rejects as martian. The stale sk_v6_daddr is a separate defect, not\naddressed here; removing the entry closes this path either way.\n\nThe entry can also be relocated. __udp_disconnect() clears sk_bound_dev_if,\nso a subsequent SO_BINDTODEVICE calls ->rehash(), and because the receive\naddress is still specific udp_lib_rehash() moves the entry instead of\nremoving it, into the bucket that (rcv_saddr, num, 0, 0) hashes to -- a\npure function of the address and port, so every socket reaching this state\non one address and port collects in one bucket. The bucket cannot be chosen\nfrom outside, as udp_ehashfn() is seeded with a per-boot secret. This last\none became reachable only with commit 644f9108f3a5 (\"udp: Make rehash4\nindependent in udp_lib_rehash()\"), which moved the hash4 handling out of a\nbranch a disconnected socket does not take; the stale entry itself dates\nfrom the commit in Fixes.\n\nTake the socket out of the table before __udp_disconnect() runs, while it\nstill matches how it was filed. This also reaches the wildcard case ahead\nof udp_lib_rehash()'s udp_unhash4() branch, leaving that branch unreachable\nfrom udp_disconnect(); removing it belongs in net-next. udp_disconnect()\nand udp_abort() are the only UDP entries into __udp_disconnect(), which is\nshared with raw, ping and l2tp sockets that are not struct udp_sock:\nping_prot.obj_size is sizeof(struct inet_sock), so udp_hashed4() on one\nwould read past the allocation."
}
],
"lastModified": "2026-10-19T10:19:20.767",
"sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}