Reptar: la vulnerabilidad FSRM/REX en CPUs Intel
(lock.cmpxchg8b.com)- En algunos procesadores Intel, si
rep movsy un prefijorex.rduplicado coinciden con la optimización FSRM, la CPU puede entrar en un estado de “glitch” fuera de las reglas normales - La causa está en la decodificación laxa de prefijos de x86 y en que un prefijo
rexque en principio no debería tener efecto en instrucciones con operandos implícitos comomovsbtermina tomando una ruta de optimización específica - El pipeline de verificación de Google descubrió en agosto de 2023 resultados impredecibles con esta combinación, y observó saltos inesperados, ignorar saltos incondicionales y anomalías en el registro del puntero de instrucción de
xsaveycall - Si varios núcleos activan el mismo bug al mismo tiempo, pueden producirse machine check exception y bloqueo del sistema; además, se reproduce incluso dentro de una VM invitada sin privilegios, lo que lo vuelve importante para entornos en la nube
- Intel publicó una actualización de microcódigo para los procesadores afectados; si no es posible actualizar, se pueden desactivar las fast strings desde
IA32_MISC_ENABLE, aunque con una gran pérdida de rendimiento
Prefijos x86 y rep movsb
rep movsbes una forma idiomática en x86 de mover memoria: si se configuran origen, destino, dirección y contador, el procesador se encarga de la copia repetida- La instrucción real es
movsb, yrepes un prefijo (prefix) que modifica esa instrucción para que se repita varias veces - La decodificación de instrucciones x86 es relativamente laxa, así que los prefijos sin efecto o en conflicto normalmente se ignoran
- Los compiladores pueden usar estos prefijos duplicados para rellenar una sola instrucción hasta el límite de alineación deseado
rex,vexyevexson prefijos que cambian la forma en que se decodifica la instrucción siguiente
La combinación problemática del prefijo rex
- i386 tenía 8 registros de propósito general, así que bastaban 3 bits para especificar un registro, pero x86-64 tiene 16 y necesita bits adicionales
- El prefijo
rexproporciona bits extra que la siguiente instrucción puede usar al codificar operandos- Suele escribirse como
rex.rxb, donde los bitsb,x,rywpueden activarse opcionalmente
- Suele escribirse como
movsbno declara operandos en la instrucción, sino que todos son implícitos, por lo que los bitsrexderex.rxb rep movsbno deberían significar nada- Normalmente el procesador ignora en silencio este tipo de prefijos
rex, pero en sistemas que soportan fast short repeat move esta combinación deriva en la vulnerabilidad
FSRM y procesadores afectados
- FSRM es una función introducida en Ice Lake para compensar las limitaciones de ERMS al manejar cadenas cortas
- ERMS (enhanced repeat move/store) permite que el microcódigo gestione la alineación de búferes y escrituras amplias para acelerar el código tradicional con
rep movsb- Su costo inicial de configuración es alto, por lo que no encaja bien con cadenas muy cortas
- FSRM está diseñado para procesar más rápido movimientos cortos de 128 bytes o menos
- Puede comprobarse el soporte con la bandera
fsrmen la líneaflagsde/proc/cpuinfo - Ejemplos de procesadores que incluyen FSRM:
- Ice Lake
- Rocket Lake
- Tiger Lake
- Raptor Lake
- Alder Lake
- Sapphire Rapids
- Esta lista no es exhaustiva; para la lista completa hay que consultar el advisory de Intel INTEL-SA-00950
Descubrimiento y reproducción
- El pipeline de verificación de Google ejecuta dos formas de programas generados aleatoriamente con la técnica Oracle Serialization y luego compara si el estado final es el mismo
- La explicación relacionada está en el artículo anterior Oracle Serialization
- En agosto de 2023, al añadir un prefijo
rex.rduplicado arep movsoptimizado con FSRM, aparecieron resultados impredecibles - Los comportamientos anómalos observados fueron:
- saltos hacia ubicaciones inesperadas
- ignorar saltos incondicionales
- el puntero de instrucción no se registra correctamente en instrucciones
xsaveocall - el depurador reporta estados imposibles
- Si varios núcleos activan el mismo bug, el procesador puede reportar machine check exception y detenerse
- También puede reproducirse dentro de una VM invitada sin privilegios, por lo que es un problema de seguridad importante para proveedores de nube
- Las herramientas de reproducción y materiales de investigación están publicados en el security research repository de Google
- También se ofrece un mirror local de la herramienta
icebreaken icebreak.tar.gz
- También se ofrece un mirror local de la herramienta
icebreakintenta reproducir el problema especificando pares de núcleos distintos- En sistemas no afectados, no debería haber salida, como si fuera un bucle infinito
- En sistemas afectados, cada reproducción exitosa imprime un
. - En núcleos hermanos SMT puede observarse una bifurcación aleatoria
- En núcleos hermanos SMP del mismo paquete puede observarse un machine check
- Si no se especifican dos núcleos distintos, puede hacer falta un hammer thread
Posible causa e impacto observado
- Como el comportamiento del microcódigo en sistemas modernos no es público, la causa raíz solo puede tratarse como una teoría basada en observaciones
- La CPU se divide a grandes rasgos en frontend y backend
- El frontend obtiene y decodifica instrucciones para generar μops
- El backend ejecuta instrucciones fuera de orden, guarda resultados en el ROB (reorder buffer) y luego los retira
- Este bug parece hacer que el frontend calcule mal el tamaño de la instrucción
movsb, provocando un estado en el que entradas posteriores del ROB quedan asociadas con direcciones incorrectas - En ese estado aparece una situación de confusión donde el puntero de instrucción se calcula mal
- El sistema puede recuperarse finalmente a un estado internamente coherente, pero los resultados intermedios pueden ser incorrectos
- Si varios núcleos SMT o SMP entran a la vez en este estado, puede dañarse suficiente estado microarquitectónico como para forzar un machine check
- Puede corromper el estado del sistema lo suficiente como para provocar un machine check, y se ha observado interferencia entre hilos durante la ejecución de procesos programados en núcleos hermanos SMT
- No está confirmado si esa corrupción puede controlarse con la precisión suficiente como para lograr una escalada de privilegios
Cómo responder
- Intel publicó microcódigo actualizado para todos los procesadores afectados en INTEL-SA-00950
- Es posible que el sistema operativo o el proveedor del BIOS ya ofrezcan la actualización
- Si no se puede actualizar, pueden desactivarse las fast strings mediante el registro específico por modelo
IA32_MISC_ENABLE - Desactivar fast strings provoca una gran caída de rendimiento, así que no debería usarse salvo que sea realmente necesario
Material relacionado sobre bugs de CPU
- Google publica los bugs de CPU que encuentra, y algunos valen la pena incluso si no tienen impacto de seguridad
- Material de ejemplo
- movlps just doesn’t work: un caso en el que
movlpsno funciona - registers can sometimes roll back: un caso en el que los registros vuelven a un valor anterior
- movlps just doesn’t work: un caso en el que
1 comentarios
Opiniones de Hacker News
Artículo relacionado: https://cloud.google.com/blog/products/identity-security/goo...
Contenido tomado de https://news.ycombinator.com/item?id=38268043, pero los comentarios se fusionaron aquí
Leer este artículo me hizo darme cuenta de lo poco que sé sobre el hardware en el que corre mi software
Dice que “los prefijos permiten activar o desactivar funciones para cambiar el comportamiento de las instrucciones”, y me pregunto por qué se necesita un “prefijo” para activar y desactivar funciones
¿Es para cambiar funciones dinámicamente sin entrar al BIOS?
El prefijo REP es el más común; sirve para hacer que la misma instrucción se repita una cantidad variable de veces
La cantidad de repeticiones se toma del registro CX, y permite hacer muy breves bucles comunes, como mover objetos desde memoria
La función memcpy a menudo se inserta inline como una sola instrucción REP MOVS y, si hace falta, con una instrucción que copia el contador a CX
El prefijo REX también es bastante común porque los programas de 64 bits manejan con frecuencia valores y direcciones de 64 bits
Ningún prefijo alterna algo configurable globalmente mediante el BIOS ni nada parecido; todos solo especifican qué debe hacer la siguiente instrucción
Los modos de direccionamiento poco usados llevan un “prefijo de segmento” que hace usar un segmento distinto de DS, y el prefijo “REX” de x86_64 agregó bits a los campos de registros para poder usar 16 registros de propósito general
De forma similar, el prefijo “LOCK”, aunque su especificación original era deficiente, hace que algunas operaciones de memoria sean atómicas respecto del resto del sistema, por ejemplo para implementar compare-and-set con “LOCK CMPXCHG”
Otras arquitecturas de CPU también expresan estas operaciones, pero normalmente las encajan dentro del espacio de instrucciones existente, lo que requiere más bits para representar todas las instrucciones
El prefijo “REP”, que es el problemático aquí, es casi una excepción: es un prefijo de repetición de microcódigo heredado desde tiempos antiguos
Aun así, representa operaciones que hoy siguen siendo sensibles al rendimiento, como memset/memmove, por lo que a los fabricantes de CPU les vale la pena seguir optimizándolo, y este bug parece haber surgido en ese proceso
El mayor problema es que “aprovechó eficientemente” el espacio de codificación de instrucciones
Más tarde, cuando aparecieron nuevas instrucciones y, peor aún, registros adicionales, tuvieron que meter como fuera nuevas variantes de instrucciones, y la forma de hacerlo fue agregar prefijos
Cada vez que se extendía el conjunto de instrucciones, se excavaba una parte del espacio de opcodes para meter a la fuerza un nuevo prefijo
Por lo que Intel propuso este año otra forma nueva, parece que esta tendencia seguirá
Al ver el proceso de diagnóstico, me acordé de lo que pasó cuando qemu se encontró con repz ret: https://repzret.org/p/repzret/
Creo que las reglas de HN deberían prohibir títulos como este
No te dicen en absoluto de qué trata el enlace, y la URL más bien confunde todavía más
Si el título no tiene significado, creo que quien publica debería agregar una breve explicación
Ya he visto que, cuando el título incluye demasiado contexto, la gente no hace clic en el enlace y en los comentarios solo pule sus propios intereses, como si reaccionara a un tuit
HN elige un punto medio que fomenta la curiosidad intelectual y hacer clic en el enlace
Aunque uno se niegue a hacer clic por el título ambiguo, al menos termina respondiendo a quienes sí hicieron clic, y eso me parece mejor que en otros lugares de internet
Las publicaciones que no ofrecen suficiente recompensa como para justificar un título ambiguo e ingenioso, a diferencia de esta, se caen de la portada
El artículo está muy bien escrito
Sé muy poco de programación en assembly y del conjunto de instrucciones de Intel, y también casi nada de microarquitectura, pero pude seguir la explicación y siento que entendí a grandes rasgos qué está pasando aquí
Me pregunto si alguien sabe si las CPU de AMD también están afectadas
Si el problema realmente es que el procesador se confunde con la longitud de las instrucciones, me parece impresionante que pueda corregirse con microcódigo sin una gran pérdida de rendimiento
Mi intuición podría estar totalmente equivocada, pero habría pensado que el cálculo de la longitud de instrucciones se sintetiza directamente con compuertas lógicas
Pensándolo de nuevo, tal vez el decodificador de uOP está bien a nivel de hardware, y una rutina de copia optimizada en microcódigo está intentando inferir algo que no es cierto sobre el flujo de uOP
Por ejemplo, algo como “ah, esto es rep mov, así que para el bucle basta con retroceder dos uOP”
No creo que el equipo de CPU de Intel vaya a revelar los detalles
No sé bien qué son “ERMS” y “FSRM”, y casi no parece haber buen material en Google.
Me pregunto si son solo flags de CPUID que indican que
rep movsbpuede usarse con el máximo rendimiento en lugar de una implementación optimizada dememcpycon SSE, o si son alguna codificación o prefijo especial que hace más rápido arep movsb.Si es lo segundo, no entiendo por qué sería necesario ni cómo se aprovecha FSRM.
Parece que ERMS era una alternativa más barata a AVX, y FSRM era una versión mejor para bloques cortos.
“Las versiones de bajo costo de procesadores posteriores, como los Kaby Lake Celeron y Pentium lanzados en 2017, no tienen AVX para copias rápidas de memoria, pero sí tienen Enhanced REP MOVSB.
Además, algunas arquitecturas móviles y de bajo consumo de Intel lanzadas a partir de 2018 no estaban basadas en SkyLake, pero copiaban aproximadamente el doble de bytes por ciclo de CPU con REP MOVSB que las microarquitecturas de generaciones anteriores”.
“Antes de Fast Short REP MOV(FSRM) de la microarquitectura Ice Lake, Enhanced REP MOVSB(ERMSB) solo era más rápido que una copia con AVX o con registros de propósito general cuando el tamaño del bloque era de al menos 256 bytes.
En bloques de menos de 64 bytes, el costo interno de arranque de ERMSB era alto, de unos 35 ciclos, por lo que era mucho más lento; la función FSRM tenía como objetivo hacer rápidos también los bloques de menos de 128 bytes”.
[1] https://stackoverflow.com/a/43837564
[2] http://www.intel.com/content/dam/www/public/us/en/documents/...
La selección y planificación óptima de instrucciones puede hacerse de forma estática en tiempo de compilación, o de forma dinámica en tiempo de ejecución eligiendo una de varias funciones de biblioteca, o mediante JIT.
Para detectar en tiempo de ejecución qué planificación de instrucciones es óptima, hay que conocer la CPU real.
Se podría tener una tabla de todos los modelos de CPU, pero también se le puede preguntar al sistema operativo si la CPU en ejecución implementa esa optimización.
Linux necesitó un parche para poder informar que la CPU implementaba esa optimización.
https://www.phoronix.com/news/Intel-5.6-FSRM-Memmove
Vi que el aviso de Intel [1] dice lo siguiente.
Intel agradece a los empleados de Intel que descubrieron internamente este problema, y también agradece a los empleados de Google que lo reportaron.
[1] https://www.intel.com/content/www/us/en/security-center/advi...
También vale la pena consultar el aviso de Intel con la descripción del impacto: https://www.intel.com/content/www/us/en/security-center/advi...
“En algunos procesadores Intel(R), una secuencia de instrucciones del procesador puede provocar un comportamiento inesperado, lo que podría permitir que un usuario autenticado, mediante acceso local, habilite una escalada de privilegios, divulgación de información o denegación de servicio”.
Konrad Magnusson, del equipo de Victoria 3 de Paradox Interactive, encontró algo relacionado con esto y mimalloc: https://github.com/microsoft/mimalloc/issues/807
No sé si está completamente relacionado, pero existe la posibilidad.