El 18 de junio de 2026, un matemático llamado Ingo Blechschmidt publicó un hilo en Mastodon que arrancaba así: «Los últimos días he estado metido hasta el cuello en una aventura de depuración fascinante, enormemente gratificante… y al mismo tiempo aterradora.» A continuación reveló un hecho: desde mayo de 2024, cuando se lanzó el kernel Linux 6.9, y durante más de dos años, la clave de descifrado de su disco duro cifrado se quedaba en la memoria RAM cada vez que cerraba la tapa del portátil. No se borraba.
En otras palabras: todo su cifrado completo de disco no había servido de nada.
Días después, el hilo aterrizó en Hacker News, donde escaló hasta 379 puntos y 182 comentarios. Después de leer la discusión entera y los commits del kernel implicados, me di cuenta de que este asunto es bastante más complejo de lo que parece: no se trata de un agujero de seguridad espectacular, sino de algo más inquietante precisamente por no serlo.
Imagen: El cifrado completo de disco en Linux (LUKS) depende de la clave almacenada en memoria para descifrar los datos. Si la clave no se borra, un atacante físico puede extraerla. Fuente: hacknjill.com
Empecemos con una analogía: la contraseña de tu maleta
Para entenderlo no hace falta saber programar. Usemos una analogía cotidiana.
Imagina que tienes una maleta con candado de combinación. Todo lo que lleva dentro está cifrado: quien encuentre la maleta no puede abrirla sin la combinación. Esa combinación (en informática la llamamos «clave») reside normalmente en tu cerebro (en el ordenador: la memoria RAM).
Cada vez que cierras la maleta (el equivalente a «cerrar la tapa del portátil»), lo primero que deberías hacer es borrar la combinación de tu cabeza. Así, aunque alguien robe la maleta mientras no estás, no podrá abrirla. Cuando vuelvas y quieras usarla, introduces de nuevo la combinación.
Esto es exactamente lo que hace la función luksSuspend del estándar LUKS (Linux Unified Key Setup): antes de que el portátil entre en suspensión, borra de la memoria RAM las claves de descifrado. Al despertar, el sistema te pide la contraseña otra vez, la clave se recarga y el disco vuelve a ser accesible.
La lógica es elegante… y crucial. Porque cuando cierras la tapa del portátil, el equipo no se apaga del todo: la RAM sigue recibiendo alimentación y los datos siguen dentro. Si la clave no se ha borrado, cualquiera que te quite el portátil de las manos (sin dejar que se apague) puede, mediante el llamado «ataque de arranque en frío» — que consiste en congelar los chips de memoria, extraerlos y leer los datos, o bien acceder a la RAM directamente a través de puertos Thunderbolt/USB — robar tu clave de cifrado.
Y lo que Ingo Blechschmidt descubrió es que desde mayo de 2024, esa operación de borrado — luksSuspend — había dejado de funcionar. Silenciosamente.
Imagen: Las claves de cifrado se almacenan en los chips de memoria RAM. Si el sistema no las borra al entrar en suspensión, un atacante con acceso físico puede extraerlas directamente. Fuente: sesamedisk.com
Cómo una refactorización 「razonable」 del kernel abrió un agujero de seguridad
Ingo usó git bisect — una herramienta que automatiza la búsqueda del origen de un error en el historial de cambios del código. Así localizó el commit causante: a28d893eb327, titulado «md: port block device access to file» (algo así como «md: migrar el acceso a dispositivos de bloque al modelo de archivos»).
Ese commit no tenía nada de malicioso ni era un error de principiante. Era una refactorización razonable y útil de los desarrolladores del kernel Linux: migrar el subsistema de lectura y escritura de discos de una interfaz antigua a una nueva. Algo parecido a cambiar el cableado de aluminio de tu casa por cobre: en teoría queda «más limpio y más moderno».
El problema fue que la refactorización tocó un mecanismo de bajo nivel aparentemente desconectado: la gestión del ciclo de vida del thread keyring (anillo de claves de hilo).
Conviene explicar qué es un keyring. En el kernel de Linux, las claves de cifrado no se guardan en cualquier esquina de la memoria, sino en una estructura de datos especial llamada «keyring» (anillo de claves). El thread keyring es una variedad particular: está vinculado a un hilo de ejecución del programa. Cuando ese hilo termina, el anillo debe destruirse y, con él, las claves que contiene.
El diseño de luksSuspend dependía exactamente de esa propiedad: cargaba la clave de cifrado del disco en un thread keyring temporal, y cuando el hilo finalizaba, el anillo se destruía automáticamente y la clave desaparecía con él.
La documentación del kernel lo garantiza de forma explícita. Pero la refactorización introducida en la versión 6.9 provocó, por una carambola, que en ciertas circunstancias ese thread keyring no se destruyera. El hilo moría, pero el anillo se quedaba flotando en la memoria como un fantasma — con la clave de descifrado del disco dentro.
Lo más irónico: la reparación costó una sola línea de código.
Sí, una línea. Ingo mandó un parche a la lista de correo del kernel. El cambio es minúsculo: consiste en añadir una llamada de limpieza a determinada estructura. Si sientes curiosidad, la lógica es: añadir un key_put(key) en cierta función del kernel, para que la referencia a la clave que ya no se usa se libere correctamente.
Pero el propio Ingo confiesa en su hilo: «Sin una prueba formal, no me atrevo a afirmar que mi parche sea correcto, ni que no vaya a provocar sus propias interacciones de largo alcance…» Esto solo lo dice un ingeniero de verdad.
Si no llega a ser por la infraestructura de pruebas de NixOS, quizá nunca se habría descubierto
En esta historia hay otro protagonista clave: NixOS.
Para quien no lo conozca, NixOS es una distribución Linux «reproducible»: toda la configuración del sistema se escribe en un único fichero, se gestiona con Git y se puede copiar a otra máquina para reconstruir exactamente el mismo sistema. La comunidad de NixOS invierte en automatización de pruebas como pocas en el ecosistema Linux.
El propio Ingo viene de esa comunidad. Nada más descubrir el fallo, lo primero que hizo fue enviar un PR al repositorio de NixOS con un test automático de integración (PR #532499). Ese test se ejecutará en cada futura actualización del kernel: simula un disco cifrado con LUKS → ejecuta luksSuspend → comprueba si han quedado claves residuales en memoria.
Traducción: mientras arreglaba su propia máquina, se aseguró de que este fallo no volviera jamás.
Y no solo eso. Ingo también mandó otro parche al proyecto cryptsetup (MR #936) para que el comando luksSuspend, cuando falla, deje de fallar «en silencio». Durante dos años, el sistema no borraba la clave y no soltaba ni un aviso; ahora, si el borrado falla, emitirá una advertencia explícita.
Ambos gestos reflejan una mentalidad de ingeniería: si encuentras un problema, añade un test para evitar que reaparezca; si encuentras un fallo silencioso, conviértelo en un fallo ruidoso. Esto representa la buena práctica ingenieril mucho mejor que cualquier alarde técnico.
A quién afecta de verdad: ¿tienes que preocuparte?
Llegados aquí, más de uno se preguntará: yo uso Windows o Mac, esto no va conmigo, ¿no? O: yo tengo un portátil con Linux, ¿debo apagarlo ya?
La respuesta depende del caso.
Primero: este fallo solo afecta a quienes usan distribuciones de la familia Debian (Debian, Ubuntu, Linux Mint y derivadas) y además tienen instalado el paquete cryptsetup-suspend. La función luksSuspend es una extensión desarrollada por la propia comunidad Debian y no forma parte del comportamiento estándar del kernel. Muchas otras distribuciones (la instalación por defecto de Arch Linux, la de Fedora) sencillamente no incluyen esta función; en ellas, la clave de cifrado siempre se queda en RAM durante la suspensión. No es un bug: es el diseño original.
Segundo: incluso estando afectado, el fallo solo se da al «cerrar la tapa» (suspensión). Si apagas el portátil normalmente en lugar de solo cerrar la tapa, la clave sí se borra al apagar. El problema existe únicamente en modo suspend.
Tercero: el ataque exige acceso físico. Un hacker remoto no puede robarte la clave de la RAM a través de la red. Hace falta una persona de carne y hueso que coja tu portátil sin apagar y extraiga la clave mediante arranque en frío, ataque DMA u otras técnicas físicas. Para el ciudadano medio, la amenaza es baja: lo más probable es que quien te robe el portátil quiera venderlo, no hacerle una autopsia forense a la memoria. Pero para abogados, periodistas, disidentes o profesionales que cruzan fronteras con información sensible — los llamados «objetivos de alto valor» — el ataque físico es una amenaza real.
El propio Ingo lo aclaró en HN: «Esto no afecta a quienes usan la configuración estándar, por la sencilla razón de que ellos nunca esperaron que la clave estuviera segura durante la suspensión.» Pero la función se diseñó precisamente para proteger la clave durante la suspensión. Durante dos años, quienes confiaron en ese mecanismo vieron traicionada su confianza.
Una lección más profunda: el riesgo de que las distribuciones parcheen por su cuenta
En el fondo, esta historia tiene dos antagonistas.
El primero es la refactorización del kernel: una limpieza de código hecha con buena intención, que por falta de una comprensión completa de sus efectos colaterales abrió un agujero de seguridad. Es casi una tragedia clásica de la ingeniería de software: el código no era «malo»; sencillamente era demasiado complejo para que nadie pudiera anticipar todas sus interacciones.
El segundo antagonista es más interesante: el riesgo de mantenimiento que acarrean los parches propios de cada distribución.
luksSuspend lo escribió la comunidad de Debian; no es una funcionalidad oficial del kernel upstream. Esto significa que su corrección no está bajo la responsabilidad de Linus Torvalds ni de su equipo de mantenedores. Cuando un mecanismo de bajo nivel del kernel upstream cambia (como el comportamiento del thread keyring en la versión 6.9), ¿alguien comprueba si el parche de Debian sigue siendo compatible? Nadie puede garantizarlo, porque los desarrolladores upstream ni siquiera saben que ese parche existe.
No se trata de decir que las distribuciones no deban crear sus propios parches. Al contrario: muchas de las mejores funcionalidades de Linux nacieron así. Pero este episodio recuerda una realidad que conviene no olvidar: cada parche no integrado en upstream es una deuda técnica — hoy funciona; mañana, al actualizar el kernel, puede romperse. Y si ese parche resulta ser una función de seguridad, su ruptura no cuesta solo una funcionalidad: cuesta la confianza.
Como dice la cita que Ingo recogió en su hilo de Mastodon: «Un argumento técnico presentado por un autor de confianza, difícil de verificar y que se parece a otro argumento que ya se sabe correcto, casi nunca se examina en detalle.» Con el código pasa lo mismo.
Enlaces de referencia
- Hilo original de Ingo Blechschmidt en Mastodon (relato de primera mano del descubridor)
- Discusión en Hacker News (379 puntos / 182 comentarios)
- Commit del kernel que introdujo el fallo: a28d893eb327
- Parche de reparación enviado por Ingo al kernel
- PR de test automático en NixOS (para prevenir la reaparición del fallo)
- Parche de aviso en cryptsetup (MR #936)
- Artículo de análisis de la comunidad Sesame Disk
- Análisis técnico en Hack’n Jill