GhostLock: el bug que vivió 15 años dentro de cada Linux y nadie lo había visto

GhostLock: el bug que vivió 15 años dentro de cada Linux y nadie lo había visto

GhostLock: el bug que vivió 15 años dentro de cada Linux y nadie lo había visto

Llevo años leyendo writeups de vulnerabilidades y muy pocos me dejan esa sensación de ¿cómo diablos nadie vio esto antes?. El de GhostLock (CVE-2026-43499), publicado esta semana por los muchachos de Nebula Security Research (VEGA Lab), es uno de ellos. Es un bug en el kernel Linux que lleva escondido desde la versión 2.6.39, o sea, desde el 2011. Cinco años de mi vida profesional usando Linux todos los días, y resulta que había una puerta trasera a root escondida en mi propio sistema. Piénsenlo un segundo.

Qué es GhostLock, en simple

El bug vive en rtmutex.c, el código que maneja los mutexes de prioridad heredada (PI). Esos mutexes se usan cuando una tarea de alta prioridad tiene que esperar a una de baja, y el kernel le «presta» la prioridad para que no se produzca un priority inversion. El detalle técnico es elegante y a la vez aterrador: una función llamada remove_waiter() fue escrita pensando en un solo caso de uso — un hilo que se bloquea solo y después se limpia — pero terminó siendo reutilizada por un camino distinto del código (rt_mutex_start_proxy_lock) donde el que llama a la limpieza no es el hilo dueño del waiter, sino otro distinto.

Cuando se produce un -EDEADLK (un deadlock detectado), remove_waiter limpia el puntero equivocado: borra pi_blocked_on del thread que pidió el requeue, no del thread que estaba durmiendo de verdad. El thread dormido se queda con un puntero colgando (dangling pointer) hacia su propio stack frame, que se libera cuando vuelve a userspace. Cualquier llamada posterior a la cadena PI sigue ese puntero muerto. Traducido a la pega: escala de privilegios local a root con un 97% de estabilidad, escape de contenedores incluido, sin necesitar capabilities ni namespaces.

Por qué me importa — y te debería importar a ti

Si eres de los que administran servidores Linux en producción, esto te toca directo. No es un exploit de nicho para un concurso de hackers. Google pagó US$92.337 en el programa kernelCTF por la cadena completa, lo que te dice la calidad del trabajo. La buena noticia: el parche ya está en Linux 7.1 (3bfdc63936dd) y se está distribuyendo hacia los LTS. La mala: cualquier distro que no se haya actualizado después de abril del 2026 sigue siendo vulnerable. Ubuntu, Debian, RHEL, Arch, Alpine… todas, sin excepción, durante 15 años.

Lo que más me deja pensando es cómo lockdep — el detector de problemas de locking del kernel — no lo pescó. Lockdep verifica que tomes el pi_lock correcto, pero no a quién pertenece. El bug existía en una zona gris que ninguna herramienta automatizada cubría. Me hace ruido porque nosotros mismos, en changanas de auditoría, solemos confiar ciegamente en los analizadores estáticos. A veces el diablo está en los supuestos del análisis, no en el código mismo.

Lo que tienes que hacer hoy

No te asustes, pero tampoco te quedes quieto. Si manejas infraestructura, la lista corta es:

  • Verificar versión del kernel. uname -r y compararla con el commit del fix.
  • Aplicar el último LTS disponible de tu distro, sin postergar.
  • En contenedores, recordar que el escape de contenedor está en el menú, no es teórico. seccomp y AppArmor/SELinux siguen ayudando a mitigar la superficie, pero el patch al kernel es lo único que cierra la puerta.

Y si trabajas con futex PI en código propio (sabés quién eres, equipos de sistemas distribuidos y RT): revisa los callbacks de rollback, asume que current no siempre es quien tú crees. La lección de GhostLock es, en el fondo, la misma de siempre en C: la duración de un objeto en stack no es lo mismo que la duración lógica que tu helper asume. Después de 15 años, alguien finalmente lo miró con calma. Que no te toque a ti descubrir el próximo.

Fuente de inspiración: IonStack part II: GhostLock, a stack-UAF that has existed in ALL Linux distributions for 15 years

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *