Un simple error tipográfico en el kernel de FreeBSD permitía a cualquier usuario obtener privilegios de roo

Un simple error tipográfico en el kernel de FreeBSD permitía a cualquier usuario obtener privilegios de roo

El error se activaba antes de que el sistema tuviera tiempo de protegerse.

image

En FreeBSD cerraron la vulnerabilidad CVE-2026-45250 en la llamada al sistema setcred(2). El error estaba en el código del núcleo y permitía a un usuario local común provocar un pánico del núcleo o, en algunos sistemas, elevar privilegios a root. El problema se activaba antes de la comprobación de los permisos del proceso que llamaba, por lo que no se requerían permisos administrativos para ejecutar el código vulnerable.

El equipo de seguridad de FreeBSD publicó el boletín FreeBSD-SA-26:18.setcred y preparó correcciones para las ramas soportadas. FreeBSD 14.3 debe actualizarse a 14.3-RELEASE-p14, FreeBSD 14.4 a 14.4-RELEASE-p5, FreeBSD 15.0 a 15.0-RELEASE-p9. Las correcciones también se incorporaron a las ramas stable/14 y stable/15.

La llamada al sistema setcred(2) se introdujo por primera vez en FreeBSD 14.3-RELEASE. Es necesaria para programas privilegiados que deben en un solo paso establecer el conjunto completo de privilegios de un proceso: los identificadores reales, efectivos y guardados de usuario y de grupo, la lista de grupos suplementarios y la etiqueta de control de acceso obligatorio (MAC). Esta llamada sustituye varias operaciones separadas como setuid(2), setgid(2) y setgroups(2).

La vulnerabilidad surgió al procesar la lista de grupos suplementarios. En la función kern_setcred_copyin_supp_groups() el núcleo debía copiar desde el espacio de usuario un arreglo de identificadores de grupo. Pero en el cálculo del tamaño se usó no el tamaño del elemento gid_t, sino el tamaño de un puntero. En sistemas de 64 bits un puntero ocupa 8 bytes, y gid_t 4 bytes. Debido a esa diferencia el núcleo pudo escribir en el búfer el doble de datos de los esperados.

En forma simplificada el problema se reducía a la expresión sizeof(*groups). En el lugar correspondiente ésta devolvía el tamaño del puntero, aunque el código debía tener en cuenta el tamaño del identificador de grupo. Cuando la memoria se asignaba dinámicamente, el exceso no provocaba desbordamiento. Pero en la ruta con el búfer en la pila del núcleo los datos sobrepasaban los límites del arreglo local.

El desbordamiento del búfer en la pila del núcleo es peligroso porque corrompe datos con los que trabaja el propio sistema operativo. En el caso más simple el sistema cae con un pánico del núcleo y requiere reinicio. En una variante más grave el atacante puede afectar la ejecución posterior del código en el núcleo y obtener privilegios de superusuario.

El orden de las operaciones es especialmente importante. El núcleo primero copiaba la lista de grupos proporcionada por el usuario y solo después comprobaba si el proceso tenía derecho a cambiar los privilegios. Por eso la vulnerabilidad podía ser activada por cualquier usuario local. Ese escenario es peligroso para servidores con cuentas de usuario normales, entornos jail, infraestructura de contenedores o servicios que, tras un compromiso aislado, conceden al atacante acceso limitado al sistema.

Los investigadores llamaron a la vulnerabilidad FatGid y describieron una explotación local funcional para FreeBSD 14.3 y 14.4 en la arquitectura amd64. Según sus datos, obtener root es posible incluso con las protecciones SMAP y SMEP habilitadas. Estos mecanismos de las CPU x86 impiden que el núcleo acceda a la memoria de usuario y ejecute código desde el espacio de usuario. Normalmente dificultan la explotación de errores en el núcleo, pero en este caso los investigadores hallaron un camino a través de estructuras del núcleo ya cargadas.

No es conveniente reproducir la cadena de explotación detallada en un texto informativo. Incluye desplazamientos concretos, estructuras internas del núcleo, la preparación de objetos falsos en memoria y el salto a través del código de un módulo cargado. Para los administradores es más importante el riesgo práctico: en FreeBSD 14.3 y 14.4 sin actualizar el error puede convertir un acceso local con pocos privilegios en el control total del sistema.

Una variante de explotación está relacionada con el módulo zfs.ko. En sistemas FreeBSD con un pool ZFS dicho módulo suele estar cargado, por lo que la condición parece realista para muchos servidores. No obstante, la vulnerabilidad no reside en ZFS sino en la implementación de setcred(2). El módulo ZFS en el escenario descrito se empleó como parte de la cadena que permitía sortear las protecciones de hardware activadas.

FreeBSD 15.0 también recibió la corrección. Allí el error original en el código estaba presente, pero las zonas adyacentes del núcleo diferían de FreeBSD 14.4. Según los investigadores, la cadena que conocían no convertía el desbordamiento en obtención de root en esa rama. Sin embargo, un usuario local común aún podía provocar un pánico del núcleo, por lo que la actualización para FreeBSD 15.0 también es importante.

La historia de la corrección no fue del todo habitual. En la rama principal de FreeBSD el código erróneo desapareció ya en noviembre de 2025 tras la reescritura de setcred(), pero el mensaje del commit no mencionaba el desbordamiento de búfer. Un boletín de seguridad separado apareció más tarde, ya junto con las correcciones para las versiones soportadas.

Los usuarios deben verificar la versión y el nivel de correcciones de su sistema. Si FreeBSD 14.3 es anterior a 14.3-RELEASE-p14, FreeBSD 14.4 es anterior a 14.4-RELEASE-p5 o FreeBSD 15.0 es anterior a 15.0-RELEASE-p9, es necesario actualizar y reiniciar el sistema. El método de actualización depende del tipo de instalación: en algunos sistemas se usa freebsd-update, en otros los paquetes del sistema base o la actualización desde el código fuente según la instrucción de FreeBSD.

Las ramas FreeBSD 13.x y anteriores no se ven afectadas por este error, porque no contienen setcred(2). La rama main ya no incluye el código vulnerable. Para servidores de producción el paso principal es sencillo: aplicar la corrección, reiniciar con el nuevo núcleo y revisar por separado los sistemas que tienen usuarios locales, entornos jail o servicios con privilegios limitados.