viernes, 5 de enero de 2018

Meltdown, Spectre y la caché de la muerte.

Estos días se ha hecho pública una vulnerabilidad que se aprovecha de la arquitectura de caché de todos los ordenadores. Posiblemente lo que hayas oído es que todos los ordenadores son vulnerables y que no hay protección posible que eso canta mucho en las noticias y es sensacionalista a tope. Lo malo es que por una vez tienen bastante razón.

Vamos a ver lo que pasa y para ello toca un poco de - ¿rollo patatero? - pues en efecto (macaguenlavozenoff).

Vamos a ir por partes, que la cosa tiene tela (avisados estáis ... ¡huid insensatos!) Por un lado, hay que tener en cuenta una cosa llamada "anillos de ejecución" que se definen en los sistemas operativos, el nivel 0 es el del sistema operativo y es el más privilegiado. Luego van los drives y por último, las aplicaciones, con menos privilegios.


¿Por qué se hace esto? Pues para evitar que se monte el pifostio padre y que una aplicación pueda modificar cosas del sistema operativo o de otras aplicaciones como ocurría en sistemas operativos más antiguos o simplones como el MS-DOS donde todo era accesible por todo y un programa mal hecho (no hay programa infalible) te podía colgar el ordenador o hacer algo peor, meterte un virus. Éstos inicialmente eran para tocar las narices pero ahora, con todos los ordenadores conectados te pueden robar tus datos o utilizar tu ordenador para cosas raras desde minar criptomonedas o cosas peores.

La cuestión es que los UNIX/Linux, el IOS de Apple que está basado en UNIX, Android (basado en Linux) y por fin Windows no permiten el acceso de las aplicaciones a estos niveles, haciéndolos más seguros (Claro que si sigues usando 1234 como password importa tres narices) Últimamente los virus intentan entrar por dos vías:
- Engañando al usuario para que les "eleve" la prioridad y hacer de las suyas,.
- Aprovechando bugs del sistema operativo o de las aplicaciones.

Al final todo esto, con un poco de cabeza, un antivirus y no andando haciendo el indio, más o menos se palía.

Ahora viene la segunda parte (de este rollo, que siempre se te olvida) que va un poco de arquitectura. Resulta que los vendedores de CPUs hablan mucho de cores, GHz pero suelen omitir un pequeño detalle: el acceso a la memoria. Echemos un ojo a esta captura:


La velocidad de la CPU es molona, casi 4 GHZ ... parece un pepinaco de cuidado y lo es. Lo que llama la atención es cuando aparece un campo llamado multiplicador .... ¿qué es eso? A lo mejor debemos retarnos a la era de los 486, cuando había uno con los número 33/66 (yo tuve un 33/100) y eso significaba que mientras que el procesador funcionaba internamente a 66 MHz (si, tres órdenes de magnitud por debajo) el acceso a la memoria funcionaba a la mitad (33 Mhz) Pues con el tiempo, la distancia en velocidad entre las CPUs y la memoria se ha ido incrementando. En este caso te encuentras que la memoria funciona a unos pobres 103 MHz y el multiplicador es nada menos que hasta un x44. No obstante, la memoria también ha evolucionado. Por ejemplo, utiliza ambos flancos en la señal de reloj, lo que convierte la frecuencia en el doble, transfiere varios bits en cada flanco, tiene bastantes bits de ancho de banda, .... En concreto en este caso, la velocidad teórica es de 3605 Mhz (DDR4) pero esa velocidad es sólo cuando transmite ... el problema es cuando hay que ir a buscar el dato que nos encontramos con una cosa llamada latencia que significa que el procesador está parado a la espera de un dato ... y eso pasa mucho más de lo que te piensas.


¿Cómo podemos paliar esto? -- pero ¿acaso te piensas que nos importa? -- Pues de varias maneras (incluso todas a la vez):
- Aumentando el número de cores, lo que permite hacer cosas en paralelo.La potencia del procesador equivale al número de GHz por el número de cores.
- Aumentando el número de threads por core, lo que hace que si un thread está en espera, el otro pueda que haga algo. En este caso, mi CPU no tiene Hyperthreading, pero en otras el aumento aparente es aproximadamente un 30-40% del rendimiento de la CPU. En procesadores con más threads como los SPARC, es mayor.
- Metiendo entre la memoria principal y los registros de la CPU diversas capas de memorias, cada vez más lentas pero cada vez mayores. En este caso, cada core dispone de dos cachés muy rápidas y pequeñas, de 32 KBytes cada una, una para datos y otra para código (una especie de arquitectura tipo Harvard que contrasta con el resto de la máquina, que en Von Newman) luego una segunda caché (por core) de 256 KB que mezcla datos y código y por último, una caché de L3 compartida por todos los cores de 6 MBytes que es la mayor y más lenta, pero aún así, más rápida que la memoria principal. Al último nivel de caché (en este caso la L3) se la conoce como Last Level Caché (LLC) y es el tamaño de caché que se publicita.


¿Hasta aquí todo claro? (pues seguro que lo complica) Con el fin de optimizar el rendimiento de la CPU las cachés no sólo van cargando datos a medida que se piden exclusivamente, se carga un bloque adyacente de manera que si el dato que se pide a continuación está en ese bloque (suele pasar) ya lo tienes en la caché. Es decir, la CPU va como a tirones: procesa lo que hay en la caché hasta que se queda sin datos y los vuelve a buscar a la memoria, cuando los tiene, los procesa de nuevo.

Pues resulta que las instrucciones no se ejecutan sin más, sino que primero se decodifican, se cargan los datos y luego se operan. Al final, una sola instrucción implica varios ciclos de CPU pero resulta que en realidad, las CPUs son capaces de de ejecutar una o más instrucciones por ciclo ¿cómo? Pues por medio de pipelines que ejecutan estas fases en paralelo: una decodifica instrucciones, otra carga parámetros, otras operan, ..... Pues para rizar el rizo y con la ayuda del compilador, no solo hacen eso sino que son capaces de predecir el comportamiento del programa en hilos ... es decir, pueden ejecutar el IF y el ELSE a la vez y en función del resultado, aprovechar la rama de ejecución ya calculada y descartar la mala ¡la leche! ¿no?  De hecho es capaz de ejecutar las instrucciones de manera desordenada (o lo que es lo mismo, de una manera distinta a la que fueron escritas) para optimizar los recursos y luego ordenar los resultados. Por supuesto, para ello cada procesador precisa un compilador especialmente diseñado para él

Pues toda esta parafernalia que ha costado más de una década desarrollar al nivel actual es la causante de los problemas que han aparecido recientemente. Al parecer incluso el CEO de Intel ha vendido todas las acciones que ha podido de su compañía, quedándose tan solo con las mínimas exigidas para el puesto cosa que le puede costar las cárcel por uso de información privilegiada. En España le meterían de CEO en una empresa del IBEX 35.

Lo que ha aparecido son básicamente dos vulnerabilidades:


Intenta hacer un acceso a un área de memoria restringida. El nivel de protección del Sistema Operativo y del HW se lo impide, pero consigue aprovechar una debilidad de las CPUs Intel y acceder a cualquier posición de memoria protegida. Este problema se mitiga con un parche que si no ha salido saldrá ya conocido como KPTI (Kernel Table Page Isolation) o KAISER que mueve las tablas de memoria del Kernel. Lo malo es que al parecer puede ralentizar bastante los ordenadores, en especial los que se hacen uso intensivo de los cambios de contexto (cambios de nivel en los anillos) que son las nubes, equipos virtualizados, etc. Pero mejor que permitir que desde una VM se acceda a otra ¿no? Yo no descartaría que en futuro aparezcan variantes de Meltdown que busquen otros datos aparte de las tablas de memoria. De momento, sólo afecta a CPUs Intel.


Esta es una vulnerabilidad peor porque afecta as todos los procesadores y arquitecturas (Apple, Android, Windows, Linux, ...) y es debida a que las cachés son compartidas por todos los procesos que corren en un ordenador y en los ordenadores modernos, procesos, lo que se dicen procesos, corren un montón (en la imagen de abajo puedes ver una captura de lo que hay en mi PC ahora mismo y no tengo precisamente muchas cosas abiertas pero procesos, dice que hay 205 corriendo) El tema es que Spectre juega con el sistema de predicción, forzando la ejecución de código privilegiado en entornos no privilegiados. Es la más complicada porque no tiene prevención (al menos ahora) y con un simple javascript pueden acceder a datos que se encuentren en el mismo servidor (aunque pensándolo bien, en entornos multiprocesador sólo se podrían acceder a VMs que corrieran en el mismo procesador e incluso, en los mismo cores, eso va a depender si está en L3 o en L2/L1) La cuestión es que la cosa tiene mala solución. Lo bueno de Spectre es que es muy complicado el sacarle partido de manera maliciosa ahora mismo ... pero todo llegará.


Y para terminar ¿qué afectación vamos a tener? Pues lo grandes servidores de nubes, públicas o privadas van a tener un problema serio de vulnerabilidad y de hecho, ya se están intentando proteger, aunque sea a costa de perder un porcentaje importante de sus prestaciones (se habla de hasta un 30%) El cambio de arquitectura y CPUs a corto plazo es irrealizable, a medio ... pues ya veremos. Se irán paliando poco a poco estos problemas, se incorporarán mecanismos de seguridad en la caché y poco a poco se irán sustituyendo los ordenadores vulnerables (hoy, 5 de enero de 2018 son todos) pero dudo que antes de una década haya desaparecido esta amenaza completamente. el tema no es tanto producir chips como el desarrollar, probar y reemplazar una arquitectura que ha estado evolucionando por más de una década.

Teóricamente los ordenadores domésticos son menos "interesantes" a la hora de infectarlos porque ya está el malware habitual, pero yo no me confiaría demasiado.

A saber de quién será la voz en off.
Felices fiestas que me voy de celebración.


2 comentarios:

Unknown dijo...

Hola, buenos días,

Muy buen artículo que explica las vulnerabilidades de forma clara y hasta "donde hay que saber", que más es peligroso.

Me gustaría saber si estas vulnerabilidades afectan a otras tecnologías como MIPS, POWER, y sobre todo SPARC, porque todo lo que he leído dice que no pero con la boca pequeña, vamos, que no lo deja claro.

Jesus dijo...

Interesante pregunta.

No he visto nada al respeto, sólo algún comentario que al parecer también ocurre en POWER (IBM) pero de SPARC o MIPS no he visto nada.

Meltdown parece que sólo ocurre en procesadores Intel, pero en teoría, SPECTRE si funciona en ARM, que son procesadores RISC, como los SPARC.

Aquí dice que sí son vulnerables a SPECTRE:

https://www.reddit.com/r/hardware/comments/7o2kjr/are_power_and_sparc_cpus_also_vulnerable_to_the/

Pero aquí dice lo contrario de las T-Series.

https://www.linuxadictos.com/especial-meltdown-spectre-lo-necesitas-saber-estos-problemas.html

Así, que no puedo responder a la pregunta. Lo único cierto es que el ataque de SPECTRE es muy complicado, con lo que el tamaño del parque de SPARC supongo que reducirá el riesgo. Es más interesante atacar muchos ordenadores con Intel que pueden tener información interesante como password, códigos de tarjetas o similares que ordeandores corporativos bien protegidos.

Saludos


Saludos

Armaduras.

He de reconocer que últimamente no me estiro demasiado en el tema bloguero este. Tampoco voy a molestarme en hacer propósito de enmienda so...