El 2 de abril de 2026 se publicó CVE-2026-23414, un fallo en el subsistema Kernel TLS (kTLS) del kernel Linux que filtra memoria del sistema cada vez que una operación de descifrado asíncrono falla a medio camino. La cola interna async_hold, encargada de retener los socket buffers cifrados mientras el motor AEAD opera sobre sus datos, no se purga en todos los caminos de error — los buffers quedan huérfanos y la memoria del kernel se va consumiendo silenciosamente bajo cualquier carga TLS sostenida.
El bug afecta a seis ramas estables del kernel (6.1, 6.6, 6.12, 6.18, 6.19 y la 7.0 todavía en release candidates), tiene clasificación CWE-401 (Missing Release of Memory after Effective Lifetime), y trae consigo una discrepancia de CVSS interesante entre NIST y kernel.org que vale la pena entender antes de decidir cuán urgente es parchearlo en producción.
La discrepancia CVSS: 5.5 medio vs 7.5 alto
NIST y la CNA del kernel.org publicaron puntajes distintos para el mismo CVE:
Fuente
Score
Vector
NIST NVD
5.5 MEDIUM
AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
kernel.org CNA
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
La diferencia clave está en AV (Attack Vector) y PR (Privileges Required):
- NIST lo modela como ataque local con privilegios necesarios (AV:L/PR:L) — un usuario en el sistema con permisos para crear sockets kTLS.
- kernel.org lo modela como ataque de red sin autenticación (AV:N/PR:N) — cualquier endpoint que pueda iniciar conexiones TLS contra un servicio que use kTLS, repetidamente, hasta agotar memoria.
Las dos lecturas son válidas. Si tu nginx, HAProxy o cualquier middleware con TLS offload al kernel está expuesto a internet, el modelo CNA es el correcto: un atacante remoto puede provocar el camino de error sin credenciales y agotar tu RAM con tráfico de tasa moderada. Si tu carga kTLS está en una red interna detrás de mTLS o VPN, el modelo NIST es más realista.
En ambos modelos la confidencialidad e integridad permanecen intactas (C:N/I:N) — esto no roba datos ni inyecta nada. El impacto es denial of service por agotamiento de memoria (A:H).
Qué es kTLS y por qué importa
kTLS es la implementación de TLS dentro del kernel que se introdujo en Linux 4.13 y permite offload del cifrado/descifrado al kernel en lugar de hacerlo en userspace con OpenSSL/GnuTLS. La ventaja: cuando un servidor manda un archivo grande sobre TLS, el kernel cifra y manda en una sola operación zero-copy (sendfile()), evitando los context switches kernel-userspace que dominan la latencia en cargas alta concurrencia.
Quién usa kTLS hoy:
- Nginx desde la 1.21.4 con ssl_conf_command Options KTLS;
- HAProxy vía tune.kTLS auto
- Netflix (origen del feature, lo usa para entregar 800 Gbps de video por nodo)
- Servicios que usan AF_KTLS vía setsockopt(fd, SOL_TLS, TLS_TX/TLS_RX, ...)
- Aceleradores de F5 BIG-IP, Mellanox ConnectX, hardware offload TLS en NICs modernas
Si tu stack no incluye nada de eso, el bug no te toca. Si tenés kTLS activado en producción, vale la pena leer el resto.
Versiones afectadas
Según el registro NVD:
Rama
Versiones vulnerables
6.1 (LTS)
6.1.158 → 6.1.167
6.6 (LTS)
6.6.114 → 6.6.130
6.12 (LTS)
6.12.55 → 6.12.79
6.18
6.18.0 → 6.18.20
6.19
6.19.0 → 6.19.10
7.0
RC1 → RC7
Las primeras versiones parchadas se incluyen en los seis commits estables que listamos al final.
El fallo en detalle: cómo se filtra la memoria
El subsistema TLS del kernel mantiene una cola interna llamada async_hold (en struct tls_sw_context_rx) que pin-ea los socket buffers (skbs) de entrada cifrados mientras el motor AEAD del kernel opera asincrónicamente sobre los datos a través de scatterlists. La idea es: al recibir un record TLS, no podés liberar el skb hasta que la operación AEAD termine porque el hardware o el módulo crypto sigue leyendo memoria desde ahí.
El flujo normal es:
- tls_decrypt_sg() recibe un record TLS y arma scatterlists hacia el motor AEAD
- Si la decryption va a ser asíncrona, llama tls_strp_msg_hold() que clona skbs y los agrega a async_hold
- Cuando el AEAD termina, tls_decrypt_async_wait() espera el callback y libera los skbs
El bug aparece cuando tls_strp_msg_hold() falla a la mitad, después de haber agregado algunos skbs clonados a la cola pero antes de terminar todo el setup. En ese escenario:
- El path de error sale sin purgar async_hold
- tls_decrypt_async_wait() solo limpia la cola si llega un callback exitoso
- tls_sw_recvmsg() solo flushea cuando un record completo se procesó en modo «fully-async» — condición que no necesariamente se cumple después de la falla
- Los skbs clonados quedan stranded en async_hold indefinidamente
Cada conexión TLS que dispare la condición de falla suma bytes al leak. En workloads de alta concurrencia con TLS frecuentemente reciclado (por ejemplo, mTLS service mesh con conexiones cortas, HTTPS API gateway con clientes flaky), el leak es lineal con el tráfico fallido y puede consumir memoria del kernel en horas o días según el rate.
El fix
El parche oficial en el árbol stable centraliza la limpieza moviendo __skb_queue_purge(&ctx->async_hold) directamente dentro de tls_decrypt_async_wait(). Con eso, todos los call sites garantizan la liberación:
- El drain path de recvmsg()
- El fallback -EBUSY en tls_do_decryption()
- Las operaciones batch de read_sock()
Los seis commits que lo arreglan a través de las ramas estables son:
SHA
Rama destino
2dcf324855c34e7f934ce978aa19b645a8f3ee71
mainline / 7.0
6dc11e0bd0a5466bcc76d275c09e5537bd0597dd
6.19 stable
84a8335d8300576f1b377ae24abca1d9f197807f
6.18 stable
9f557c7eae127b44d2e863917dc986a4b6cb1269
6.12 stable
fd8037e1f18ca5336934d0e0e7e1a4fe097e749d
6.6 stable
ac435be7c7613eb13a5a8ceb5182e10b50c9ce87
6.1 stable
Verificá en tu kernel con:
# Ver versión exacta
uname -r
# Buscar el patch específico (si tenés sources)
git -C /usr/src/linux log --grep="Purge async_hold in tls_decrypt_async_wait" --oneline
# Ver cambelog del paquete kernel
apt changelog linux-image-$(uname -r) 2>/dev/null | grep -i "23414\|async_hold" | head
rpm -q --changelog kernel | grep -i "23414\|async_hold" | head
Cómo mitigar mientras parcheás
Si no podés reboot ya, las opciones interim son:
1. Deshabilitar kTLS y caer a OpenSSL userspace. En Nginx:
# Comentá o quitá la línea:
# ssl_conf_command Options KTLS;
Y en HAProxy:
global
tune.kTLS off
El costo es perder ~30-40 % de throughput TLS en bulk transfer, pero quedás fuera del leak path completamente.
2. Bloquear creación de sockets kTLS vía LSM/seccomp. Si tenés workloads no confiables corriendo en el mismo host (containers de terceros), una política SELinux/AppArmor que deniegue setsockopt(SOL_TLS, ...) cierra el vector local del modelo NIST.
3. Memory monitoring + auto-restart. Para servicios stateless (gateway, proxy), un MemoryMax= en el unit de systemd con Restart=on-failure evita que el leak tumbe el host completo:
[Service]
MemoryMax=4G
Restart=on-failure
RestartSec=5s
No es una solución, pero compra tiempo.
Qué dejan estos casos
CVE-2026-23414 no es Copy Fail (sin RCE, sin escalada de privilegios), pero es exactamente el tipo de falla que aparece en producción semanas después de pasar QA: memory leaks que no se notan en tests de carga corta, se acumulan en horas de tráfico real, y terminan tirando un servicio justo cuando menos lo esperás. La forma de fix — centralizar la liberación de recursos en un único punto en lugar de duplicar la limpieza en cada call site — es el patrón clásico que evita esta familia entera de bugs.
Para sysadmins de servicios TLS-heavy, la lectura es clara: identificá si usás kTLS, parcheá si lo hacés, y si no podés parchear hoy, considera apagar kTLS hasta el upgrade. La pérdida de performance es preferible a un OOM kill silencioso de tu API gateway un viernes a la noche.
Para developers de subsistemas crypto del kernel: cualquier código que mantenga buffers vivos durante operaciones asíncronas es un candidato a este patrón de leak. Los reviews de patches en linux-crypto y netdev van a tener una nueva regla para citar la próxima vez que alguien proponga tls_strp_msg_hold() versión 2.
Fuentes
- CVE-2026-23414 — NVD
- CVE-2026-23414 — GitHub Advisory Database (GHSA-8fgp-q3pf-q3rh)
- CVE-2026-23414 — stack.watch análisis técnico
- CVE-2026-23414 — SentinelOne vulnerability database
- Linux kernel TLS documentation
- Tenable — CVE-2026-23414
- Wiz — CVE-2026-23414 Impact, Exploitability, and Mitigation Steps
Top comments (0)