5 de enero de 2018

El caos que genera Metldown & Spectre con sus consecuencias.

Confieso que no tenía en mis planes ponerme a escribir durante estas vacaciones de invierno sobre ningún tema profundo, pero el caos que se ha generado con el descubrimiento de los bugs de Metldown y Spectre ha sido lo suficientemente interesante como para sentarse con ellos y dejar la visita a la exposición de Star Wars que hay en la Flag Store de Telefónica Gran Vía para el fin de semana, o para un poco más tarde.

Figura 1: El caos que genera Metldown & Spectre con sus consecuencias.

Si habéis leído sobre los fallos, supongo que ya estaréis más que al día, pero dejadme que haga un pequeño resumen para que sea fácil de entender para todo el mundo en que se basa el fallo, y porque es tan importante desde el punto de vista de la seguridad, y desde el punto de vista de - lo que para mí es crucial - el rendimiento.

Arquitecturas Avanzadas

Si estás estudiando en la Universidad, esto se suele explicar en las asignaturas de Arquitecturas Avanzadas, que es donde lo aprendí yo cuando estuve acabando la Ingeniería Informática. En esa parte de la formación es donde se analizan cómo los microprocesadores aplican técnicas para aprovechar al máximo el paralelismo que ofrece el hardware incluido en los chips. Técnicas como el adelanto de instrucciones, el cómputo de todas las ramas de un instrucción alternativa, o el paralelismo de estructuras secuenciales. Para que os hagáis una idea - resumiendo mucho - supongamos que una teneos una instrucción que dice algo como:
Si A> 10 entonces B=1 de lo contrario B=0
Esto, en un microprocesador sin utilizar toda la potencia del paralelismo llevaría a ejecutar primero la comparación del valor de A y después el movimiento de un valor al registro B.  ¿Sencillo, no? Ahora vamos a complicarlo un poco.
Si f(A)>0 entonces g(B) de lo contrario h(B)
Vale, supongamos ahora una instrucción en la que f(A) tarda 10 segundos, g(B) toma 5 segundos calcular y h(B) 7 segundos su ejecución. En este entorno, una arquitectura tradicional tardaría, como mínimo 15 segundos, y como máximo 17 segundos, luego en media tendríamos un procesador que ejecutaría este programa en 16 segundos.

Pero... ¿y si le añadimos al sistema un módulo de programación especulativa y una caché con el objeto de paralelizar esto? Es decir, supongamos que el microprocesador es capaz de ejecutar f(A), g(B) y h(B) totalmente en paralelo, es decir, que antes de que se termine f(A) ya sabemos el resultado de g(B) y de h(B). El resultado es que el tiempo de ejecución máximo en cualquiera de los casos sería de 10 segundos, lo que nos ha incrementado un 60 % el rendimiento del sistema.

Para conseguir esto, lo que se hace es aprovecharse de dos características del hardware de los microhips. En primer lugar la existencia de puertas lógicas en el chips duplicadas que permiten paralelizar acciones y la segunda de zonas de memoria caché que permiten almacenar los resultados de g(B) y h(B) hasta saber cuál es el resultado que pasa a la memoria principal del programa. 

Por supuesto, no siempre es necesaria una comparación, supongamos ahora que tenemos que ejecutar algo como:
R1=f(A) tarda 5 segundos 
R2=g(A) tarda 8 segundos 
R3=h(A) tarda 4 segundos 
Imprime R1+R2+R3 tarda 1 segundo
En este caso tenemos cuatro instrucciones serializadas, que si se ejecutan secuencialmente harán que el programa tarde 18 segundos en media. Pero... si tenemos hardware de sobra, y no hay dependencia de ninguna función (solo la última instrucción depende del cálculo de las anteriores), podríamos ejecutar en paralelo el cálculo de R1, R2 y R3, lo que haría que el tiempo máximo fuera 8 segundos y luego imprimirlo, con lo que de 18 segundos habríamos pasado a 9, justo la mitad.

¿Y la seguridad?

Aquí viene el programa que ha sido descubierto por Metldown (y en una variación por Spectre). Si cualquier programa pudiera leer cualquier zona de memoria del sistema tendríamos un serio problema. Esto implicaría que cualquier ejecución (por ejemplo un JavaScript que te muestra un anuncio en el navegador) podría ejecutar cualquier cosa en tu sistema - por ejemplo un malware - porque sabría qué direcciones de memoria se van a ejecutar con privilegios dentro del sistema.

Por ello, es necesario establecer mecanismos de protección de la memoria para que cada proceso pueda leer solo su memoria, y que los procesos con altos privilegios puedan guardar los datos sensibles sin que se vean afectados por programas de usuario - como el JavaScript que muestra los anuncios que contaba antes -. 

Para que esto sea posible, es necesario que la memoria de los procesos esté protegida desde el microprocesador, y ningún programa que se ejecute en el procesador acceda a zonas de memoria protegida o de otro proceso. Para ello hay varios mecanismos de protección, pero dos fundamentales. Uno que prohibe acceder a zonas de memoria y otro que aleatoriza la carga de direcciones en memoria, el famoso ASLR (Address Space Layout Randomization) que en el Kernel del sistema operativo se llama KASLR.

Perdonad por la simplificación al extremo de los mecanismos de protección, pero para entender cómo funciona Meltdown es suficiente. Si quieres saber mucho más, tus libros son, sin duda, Linux Exploiting y Máxima Seguridad en Windows. Imaginemos ahora un programa que hace algo como:
A=R1 
B=(A+0)*A
Como se puede ver, en este caso las instrucciones no "deberían" ser paralelizables, pero tal y como funciona el microprocesador sí que lo es, al menos parcialmente. Imaginemos que R1 es un registro protegido que va a hacer que salte una excepción, que va a ser tratada por un código de error que evitará que el programa se siga ejecutando por un intento de violación del espacio de memoria protegida. Eso debería implicar que la instrucción con el cómputo de B no se debería ejecutar, pero lo cierto es que el mecanismo de Programación Especulativa que paraleliza las instrucciones paraleliza también el tratamiento el error con el cálculo de B, por lo que en la caché del microprocesador se encuentra B calculado.

Esto es un grave problema de seguridad, ya que la caché del microprocesador no es una zona de memoria protegida, lo que hace que cualquier programa de usuario pudiera volcar valores como R1 de zonas de memoria que no debería ver.... y por eso ...Meltdown.

¿Cómo arreglarlo?

Hacer un buen arreglo de este fallo implica tomar muchas decisiones nuevas. Analizar los "corner cases" o poner nuevas medidas de protección a la caché del microprocesador. Esto se puede hacer a nivel de software - con el kernel de los sistemas operativos - o a nivel de hardware - lo que  implica el rediseño del funcionamiento de los microprocesadores y la nueva toma de decisiones -. Y nada es fácil ni gratis.

Si hablamos de que Intel (afectado por Meltdown y Spectre) o AMD y ARM (afectados por Spectre) tuvieran que cambiar el funcionamiento de la Programación Especulativa haciendo cambios para meter controles de seguridad en estos casos, implicaría que los chips en almacén, los chips en fábricas, los contratos firmados de entrega, etcétera, se verían afectados, por lo que costarían muchos dólares, y eso es malo para el negocio, eso es malo para la acción, eso es malo para tu dinero si tienes acciones de esas compañías.

Pero tendrán que arreglarlo en futuros diseños de sus chips.

Eso sí, mientras tanto, la solución es que lo arregle el SO, poniendo controles por encima. Controles que pueden ser o bien anular la Programación Especulativa (imposible desde el punto de vista de rendimiento) o bien empezar a poner controles de seguridad mucho más exhaustivos (rendimiento afectado también, pero se puede ir afinando).

Si no se ponen parches, cualquier programa podría acceder al Kernel del sistema en el core del microchip y ejecutar lo que le diera la gana. Imaginad que un JavaScript de un navegador llega al microprocesador hardware en un equipo en un datacenter de Cloud. Y desde allí puede ver todas las máquinas virtuales, todos los procesos que corren por encima e infectarlo con un software de características de gusano para que esos equipos hagan lo mismo. 

Lo que llevaría a que un entorno de Cloud se pudiera convertir en un problema para todas las máquinas, así que hay que parchear sí o sí. Y eso es malo para el negocio. Eso es malo para la acción. Eso es malo para tu dinero si tienes acciones allí.

Todos los fabricantes tienen que parchear. Google, Microsoft, Amazon, Apple, etcétera, y deben hacerlo para todos los sistemas operativos, y luego, todas las empresas deben actualizar el software..pero....

¿Qué va a suceder con el rendimiento?

Pues que todo va a ir un poco más lento - y a veces mucho más lento -. Al tener que ponerse medidas de seguridad en la Programación Especulativa, vamos a ejecutar más instrucciones, se van a paralelizar menos y cuando tengamos procesos complejos, pues la cosa puede ir muuucho más lenta.

Puede que los procesos de Machine Learning, los procesos de Inteligencia Artificial basados en Redes Neuronales en algoritmos de Deep Learning, cálculos en SGDB de alto rendimiento (Que aprovechan al máximo las optimizaciones del microprocesador), o muchos sistemas, vayan lentas.

Pero es que si no, la seguridad de un automóvil, o un sistema SCADA, o de un avión, se ven comprometidas por estos fallos de seguridad, que afectan al corazón de la seguridad de las arquitecturas tecnológicas que usamos hoy en día. Las próximas semanas, aún seguiremos viendo muuuchas noticias al respecto. Os iré contando.

Saludos Malignos!



☛ El artículo completo original de noreply@blogger.com (Chema Alonso) lo puedes ver aquí

No hay comentarios.:

Publicar un comentario