Google continua con su trabajo de trasladar Android a Rust
Desde hace ya varios meses, hemos compartido aquí en el blog algunas de las noticias más destacadas sobre el apoyo y aceptación que ha tenido Rust en los diferentes proyectos y desarrollos, de los cuales muchos de ellos son pesos pesados, dígase Linux, Windows e incluso Android.
A pesar de tener una gran aceptación por parte de los grandes, el cambio hacia Rust no es fácil, ya que incluso para poder ser aceptado como segundo lenguaje de programación en el Kernel de Linux, tuvo que pasar por bastantes cosas para que Linus Torvalds diera el visto bueno.
Para el caso de Google, esto no ha sido una excepción y desde hace ya varios meses, Google ha introducido Rust en muchos de sus proyectos y Android es uno de ellos y en el cual se ha llevado una etapa de migración bastante controlada, pues como parte de sus esfuerzos para fortalecer la seguridad de los componentes de software críticos de la plataforma, ahora Google dio a conocer que ha finalizado con el trabajo de la migración del fimware «Android Virtualization Framework’s protected VM (pVM)» a Rust.
Este firmware es utilizado para organizar el funcionamiento de las máquinas virtuales lanzadas por el hipervisor pVM desde Android. Anteriormente, el firmware se escribía en C y se implementaba sobre el gestor de arranque U-Boot, en cuyo código se encontraron previamente vulnerabilidades causadas por problemas con la memoria.
El hipervisor pVM toma el control en una etapa temprana del arranque y proporciona un aislamiento completo de la memoria de la máquina virtual del entorno del host, evitando el acceso desde el sistema host a las máquinas virtuales protegidas que procesan datos confidenciales. El firmware pvmfm (Firmware de máquina virtual protegida) toma el control inmediatamente después de iniciar la máquina virtual, verifica el entorno generado y decide abortar el inicio si se detectan problemas de integridad o genera un certificado de inicio para el sistema invitado si se confirma la cadena de confianza.
La reescritura de Rust hace que sea más fácil y seguro cumplir con la » regla de dos » de Google para mantener seguros los componentes del sistema Android. De acuerdo con esta regla, cualquier código agregado debe cumplir no más de dos de tres condiciones: trabajar con datos de entrada no validados, usar un lenguaje de programación no seguro (C/C++) y ejecutarse con privilegios elevados. Esta regla implica que el código para procesar datos externos debe reducirse a privilegios mínimos (aislado) o escribirse en un lenguaje de programación seguro. Según las estadísticas de Google, aproximadamente el 70% de todas las vulnerabilidades peligrosas identificadas en Android se deben a errores al trabajar con la memoria.
Entre las dificultades que surgen en el proceso de desarrollo de componentes de bajo nivel como controladores en el lenguaje Rust, se menciona la necesidad de trabajar con punteros en modo inseguro, ya que Rust se crea pensando en el uso de la memoria asignada en el lenguaje Rust.
Entre las desventajas, también cabe destacar la necesidad de una sintaxis mejorada para acceder a campos de estructura e índices de matriz a través de punteros simples sin crear referencias, así como limitaciones en la creación de enlaces seguros sobre operaciones inseguras que pueden causar un comportamiento indefinido y no pueden ser verificadas por el compilador.
Cabe mencionar que el nuevo firmware reescrito en Rust se incluye en Android 14 y las bibliotecas universales creadas durante el proceso de desarrollo del firmware se empaquetan como paquetes y se transfieren a la comunidad de Rust. El tamaño del código resultante en comparación con la versión anterior del firmware pVM que ocupaba 220 kB, el nuevo código ocupa 460 kB, pero se agregaron nuevas funciones a la versión reescrita, gracias a las cuales fue posible deshacerse de algunos otros componentes utilizados durante el arranque.
Como resultado, el tamaño total de todos los componentes antiguos y nuevos del maletero resultó ser comparable. Cabe señalar que cuando el tamaño es más importante que el rendimiento, se pueden lograr resultados comparables a los del lenguaje C habilitando modos de optimización de tamaño adicionales en el compilador, descartando dependencias innecesarias y sin utilizar formateadores de cadenas.
Finalmente si estás interesado en poder conocer más al respecto, puedes consultar los detalles en el siguiente enlace.