Spectre y Meltdown: cómo funciona la caché

El año hasta ahora ha estado lleno de noticias sobre Spectre y Meltdown. Estos exploits utilizan características como la ejecución especulativa y el acceso temporal a la memoria. Comúnmente tienen el hecho de que todos los procesadores modernos usan caché para acceder a la memoria más rápido. Todos hemos oído hablar de la caché, pero ¿qué es exactamente y cómo permite que nuestras computadoras funcionen más rápido?

En términos más simples, la caché es una memoria rápida. Las computadoras tienen dos sistemas de almacenamiento: almacenamiento primario (RAM) y almacenamiento secundario (disco duro, SSD). Desde el punto de vista del procesador, la carga de datos o instrucciones de RAM es lenta: la CPU tiene que esperar y no hacer nada durante 100 ciclos o más mientras se cargan los datos. La carga del disco es aún más lenta; se desperdician millones de ciclos. La caché es una pequeña cantidad de memoria muy rápida que se utiliza para almacenar datos e instrucciones a los que se accede con frecuencia. Esto significa que el procesador solo tiene que esperar a que la caché se cargue una vez. Después de eso, se puede acceder a los datos sin esperar.

Una analogía común (aunque antigua) para el caché usa libros para representar datos: si necesita un libro específico para buscar información importante, primero debe revisar los libros en su escritorio (caché). Si su libro no está allí, iría a los libros en sus estantes (RAM). Si esa búsqueda queda vacía, iría a la biblioteca local (disco duro) y miraría el libro. Cuando llegara a casa, guardaba el libro en su escritorio como referencia rápida, no lo devolvía inmediatamente a los estantes de la biblioteca. Así es como funciona la lectura de caché.

Diagrama de Intel Haswell. Tenga en cuenta cuántas propiedades utilizan la caché L3 y el controlador de memoria.

La caché es una propiedad cara

Las primeras computadoras funcionaban tan lentamente que el caché realmente no importaba. La memoria central era muy rápida cuando la velocidad de la CPU se medía en kHz. La primera caché de datos se utilizó en IBM System / 360 Model 85, lanzado en 1968. La documentación de IBM afirmaba que las operaciones de memoria tomarían entre ¼ y ⅓ menos tiempo en comparación con un sistema sin caché de datos.

Ahora, la pregunta obvia es, si el caché es más rápido, ¿por qué no crear una memoria completa desde el caché? Hay dos respuestas a eso. Primero, la caché es más cara que la memoria principal. Generalmente, una caché se construye con una memoria RAM estática, que es mucho más cara que la memoria RAM dinámica utilizada en la memoria principal. La segunda respuesta es lugar, lugar, lugar. Con procesadores funcionando a varios GHz, la caché ahora debe estar en el mismo silicio que el propio procesador. Enviar las señales a través de trazas de PCB llevaría demasiado tiempo.

El núcleo de la CPU generalmente no conoce ni se preocupa por el caché. Toda la gestión y la gestión de la memoria caché la realiza la Unidad de memoria (MMU) o el controlador de memoria caché. Estos son sistemas lógicos complejos que necesitan ejecutarse rápidamente para mantener la CPU cargada con datos e instrucciones.

Caché mapeado directo

La forma más simple de caché se llama caché de asignación directa. El mapa directo significa que cada ubicación de la memoria se asigna a una sola ubicación de caché. En el diagrama hay 4 ranuras de caché. Esto significa que el índice de caché 0 podría contener el índice de memoria 0,4,8 y así sucesivamente. Debido a que un bloque de caché puede contener algunas de las muchas ubicaciones de memoria, el controlador de caché necesita una forma de saber qué memoria hay realmente en el caché. Para manejar esto, cada bloque de caché tiene una etiqueta que contiene las partes superiores de la dirección de memoria almacenada actualmente en el caché.

El controlador de caché también necesita saber si el caché realmente contiene datos utilizables o basura. Cuando el procesador se inicia por primera vez, todas las ubicaciones de caché serán aleatorias. Sería realmente malo si algunos de estos datos aleatorios se usaran accidentalmente en un cálculo. Esto se trata con un bit válido. Si el bit válido se establece en 0, la ubicación de la caché contiene datos no válidos y se ignora. Si el bit es 1, los datos de la caché son válidos y el controlador de la caché los utilizará. El bit válido se fuerza a cero en el procesador y se puede borrar siempre que el controlador de caché necesite borrar el caché.

Escribir en caché

Hasta ahora me he ocupado de los enfoques de lectura a través de la memoria caché, pero ¿qué pasa con los scripts? El controlador de caché debe asegurarse de que algunos cambios en la memoria del caché también se realicen en la RAM antes de que el caché sea reemplazado por algún nuevo acceso a la memoria. Hay dos formas básicas de hacer esto. Primero es escribir una memoria cada vez que se escribe la caché. Esto se llama caché escrito. La inscripción es segura, pero viene con una penalización rápida. Las lecturas son rápidas, pero las escrituras ocurren con menos rapidez desde la memoria principal. El sistema más popular se llama caché de escritura diferida. En un sistema de reescritura, los cambios se guardan en la caché hasta que se reemplaza esa ubicación. El controlador de caché necesita saber si esto ha sucedido, por lo que se agrega un bit más llamado sucio a la caché.

Los datos de la caché necesitan todos estos datos operativos (la etiqueta, el bit válido, el bit sucio) almacenados en la caché de alta velocidad, lo que aumenta el costo general del sistema de caché.

Caché de asociación

El caché de mapeo directo acelerará los accesos a la memoria, pero el mapeo uno a uno de la memoria al caché es relativamente ineficiente. Es mucho más eficiente permitir que los datos y las instrucciones se almacenen en más de una ubicación.

Una caché totalmente asociada permite precisamente eso: cualquier ubicación de la memoria se puede almacenar en cualquier ubicación de la caché. Esto también significa que la caché debe buscarse en cada acceso a la memoria. Esta función de búsqueda la realiza un comparador de dispositivos. Tal comparador requeriría muchas puertas lógicas y consumiría una gran área física en el chip. El recurso feliz es un caché asociativo establecido. El diagrama muestra una caché asociada con dos modos. Esto significa que cualquier ubicación de la memoria puede ir en una de dos ubicaciones de caché. Esto hace que el comparador de dispositivos sea relativamente simple y rápido. Por ejemplo, la caché Intel Core i7-8700K Nivel 3 es asociativa de 16 vías.

Memoria virtual

Al principio, las computadoras ejecutaban un programa a la vez. Un programador tenía acceso a toda la memoria del sistema y tenía que administrar cómo se usaba esa memoria. Si su programa fuera más grande que el espacio total de RAM del sistema, dependería del desarrollador intercambiar secciones cuando sea necesario. Imagina que tienes que comprobar si printf () está cargado en la memoria cada vez que quieras imprimir algo.

La memoria virtual es la forma en que un sistema operativo trabaja directamente con el procesador MMU para lidiar con esto. La memoria principal está dividida en páginas. Cada página se intercambia según sea necesario. Con memoria barata hoy en día, no tenemos que preocuparnos tanto por cambiar a disco. Sin embargo, la memoria virtual sigue siendo importante para algunos de los otros beneficios que ofrece.

La memoria virtual permite que el sistema operativo ejecute muchos programas a la vez; cada programa tiene su propio espacio de direcciones virtuales, que luego se asigna a las páginas de la memoria física. Este mapeo se almacena en la tabla de páginas, que a su vez reside en la RAM. La tabla de contenido es tan importante que tiene su propia caché especial llamada Translation Appearance Buffer o TLB.

La MMU y el hardware de memoria virtual también funcionan con el sistema operativo para realizar la protección de la memoria; no permita que los programas lean o modifiquen el espacio de memoria de los demás y no permita que nadie estropee el kernel. Esta es la protección que evitan los ataques de Spectre y Meltdown.

En el mundo real

Como puede ver, incluso los sistemas de caché relativamente simples pueden ser difíciles de rastrear. En un procesador moderno como Intel i7-8700K, hay muchas capas de cachés, algunas independientes, otras compartidas entre los núcleos de la CPU. También están los motores de tiempo de ejecución especulativos que extraen datos que podrían usarse de la memoria al caché antes de que un kernel determinado esté listo para ello. Ese motor es la clave de Diffusion.

Tanto Spectre como Meltdown usan caché en un ataque basado en el tiempo. Debido a que el acceso a la caché es mucho más rápido, un atacante puede medir el tiempo de acceso para determinar si la memoria proviene de la RAM o de la caché. Esa información de tiempo se puede usar para leer realmente los datos en la memoria. Es por eso que hace dos semanas se envió un parche de Javascript a los navegadores. Este parche hace que los tiempos de JavaScript integrados sean menos precisos, lo suficiente como para que no valgan la pena para medir el tiempo de acceso a la memoria, lo que protege contra las vulnerabilidades del navegador.

El método simple de rodilla para tratar de mitigar Spectre y Meltdown es deshabilitar los cachés. Esto haría que nuestros sistemas informáticos fueran increíblemente lentos en comparación con las velocidades a las que estamos acostumbrados. Los parches lanzados no son tan extremos, pero cambian la forma en que la CPU trabaja con la caché, especialmente en los cambios de contexto de espacio de usuario a espacio central.

La ruta de datos de la CPU moderna y el diseño de caché es una tarea increíblemente compleja. Los fabricantes de procesadores han acumulado años de datos mediante la simulación y el análisis estadístico de cómo los procesadores mueven los datos para hacer que los sistemas sean rápidos y confiables. Los cambios en algo como el microcódigo del procesador se realizan solo cuando es absolutamente necesario y solo después de miles de horas de prueba. Un cambio hecho rápidamente (sí, seis meses rápido) ya que los chips actuales de Intel y AMD ciertamente tendrán algunos problemas, y eso es exactamente lo que estamos viendo con excelentes resultados y fallas. El lado del software de la solución, como Kernel Page Table Isolation, puede provocar despegues de los TLB, que también ofrecen excelentes resultados para las aplicaciones que a menudo llaman al sistema operativo. Esto explica algunas de las razones por las que el impacto de los cambios depende de la aplicación. Básicamente, todos somos probadores beta.

Sin embargo, hay un lado positivo. La esperanza es que con más tiempo para la investigación y las pruebas por parte de los fabricantes de chips y los proveedores de software, se comprenderán mejor los cambios necesarios y se lanzarán mejores parches.

Es decir, hasta que se encuentre el siguiente vector de ataque.

  • HaxGrrl dice:

    Si bien se informan juntos, los dos números tienen una diferencia muy importante: Split cruza un dominio privilegiado. El diseño de la CPU de Intel significa que el motor especulativo no se molesta en verificar los bits permitidos en el TLB antes de completar. Si lanzara una burbuja de conducto cuando se violaran los permisos, Meltdown sería imposible. Claro, ralentiza la ruta lenta, pero eso ya activará una excepción si realmente se llama. La disolución es un defecto del proyecto.

    Spectre es un exploit aterrador, pero en realidad no es una falla proyectada en la CPU (excepto en el caso de algunas CPU, que también permitirán omitir los bits permitidos). Ninguna arquitectura de CPU importante tiene una MMU destinada a proteger un proceso de sí mismo, por lo que permitir que una aplicación se ataque a sí misma no es un modelo amenazante que se haya considerado mucho. Desafortunadamente, este es el modelo que vemos con secuencias de comandos integradas en los navegadores. Lástima que no tengamos soporte de MMU allí.

    • Gregkennedy dice:

      +1 a Chrome para iniciar pestañas separadas en procesos separados (?), En lugar de como hilos separados o un solo proceso.

      Además, esto también hace que las personas odien a Chrome por comerse toda su RAM como un refrigerio ligero.

      • Megol dice:

        Chrome todavía está abierto a ataques, mientras que es más fácil atacar contra la protección de software (cosas que funcionan en el mismo proceso pero controles secretamente limitados), sin embargo, es posible hacerlo contra otro proceso siempre que compartan recursos (por ejemplo, cachés).

  • Ostraco dice:

    Nada mal. ¿Se pregunta si este ejercicio se puede simular? Ciertamente está enseñando lo complicadas que son las CPU.

  • Megol dice:

    De hecho, las mitigaciones que actualmente utiliza Spectre no se relacionan con el caché, pero disminuyen la posibilidad de que un atacante pueda afectar a la víctima a través del mecanismo de predicción. Esto incluye mucho más difícil de piratear la predicción de rama indirecta (retpoline aprovecha la forma en que la mayoría de los procesadores manejan las funciones de procesamiento, IBRS e IBPB son trucos de microcódigo). Similar a los procesadores que no son x86.

    Para Meltdown tampoco cambia el funcionamiento del caché, pero qué tipo de memoria se mapea visible para los procesos del usuario, si una memoria con datos confidenciales no se mapea en el espacio de direcciones del usuario, no se puede acceder a ella con Meltdown. Sí, implica indirectamente al TLB, que es un caché del mapeo, pero sigue funcionando como siempre. Absolutamente ningún cambio.

    Es probable que las correcciones futuras garanticen que se acceda a las cachés de manera diferente, de modo que las lecturas especulativas no se puedan detectar si se interrumpen. Entonces, los ataques de una rama predictiva realmente no importan (solo pueden reducir el rendimiento). Fusion se solucionará si se verifican los permisos antes de acceder, que ya es el estándar para la mayoría de los diseñadores de procesadores, pero no Intel.

  • Olsen dice:

    Es genial vivir en una época en la que una máquina se llama "motor especulativo".
    Imagínese después de unos años cuando cerramos pilas de curvas de tiempo y otra ciencia ficción tan loca.

    • Ostraco dice:

      Las máquinas de adivinar.

  • daveboltman dice:

    "Esa información de tiempo se puede utilizar para leer realmente los datos en la memoria". - la clave de todo el ataque.

    Sería genial obtener más información sobre cómo esa información de tiempo le permite leer los datos reales. A veces es para saber si la memoria debe leerse o si ya está en la caché (desde el momento), pero ¿cómo revela esto los datos en la memoria?

    • Adam Fabio dice:

      Hola, Dave, el artículo anterior de Mike sobre Spectre y Meltdown trataba algo de esto, pero una de las mejores explicaciones que he visto ha aparecido en los comentarios de [Alan Hightower] compruébalo aquí: https://la-tecnologia.com/2018/01/05/lets-talk-intel-meltdown-and-spectre/#comment-4291735

  • tutudidz dice:

    Para seguir usando la misma arquitectura especulativa, simplemente es necesario actualizar los chips o programas que permiten que los tiempos fluctúen constantemente de manera aleatoria; & o cifra todos los datos a nivel de caché.

    • Paul Baker dice:

      El cifrado es demasiado caro, todo lo suficientemente seguro sería tan lento que borraría la ventaja del caché. La solución completa (una que requeriría un cambio en los dados) es hacer una comparación gamma en la dirección que se conjetura (antes de que la ejecución conjetural sea una entrada conjetural). Si la dirección solicitada no está en el rango de memoria asignado para el proceso, la búsqueda especulativa no ocurre. Sin ejecución especulativa = sin ejecución especulativa.

    • Megol dice:

      La sincronización aleatoria no es una solución válida y sería mucho más difícil que tú (y yo antes de considerarlo). Tendría que inyectar tanto ruido que la ejecución especulativa estaría oculta, por lo que eliminarlo por completo sería una mejor opción.

      Cifrar los datos almacenados en caché o la memoria tampoco haría nada, ya que el ataque Spectre realiza un proceso con acceso para leer los datos. Si un programa no puede leer sus datos privados, simplemente no puede funcionar.

  • Greenaum dice:

    Aburrido como una mierda, pero supongo que ayuda mucho al SEO. De todos modos, sobre tus perros, ¿qué razas obtendrías?

  • marctmiller dice:

    ¿Cómo acceder al anillo -3 en minix?

    • elail dice:

      solicite una sección de la NSA dentro de Intel HeadQuarter ...

Matías Jiménez
Matías Jiménez

Deja una respuesta

Tu dirección de correo electrónico no será publicada.