In het kader van het versterken van de beveiliging van kritisch belangrijke softwarecomponenten van het Android-platform heeft Google de pvmfm-firmware herschreven in de programmeertaal Rust. Deze firmware wordt gebruikt voor het beheer van virtuele machines die worden uitgevoerd door de hypervisor pVM binnen het Android Virtualization Framework. Voorheen was de firmware geschreven in de programmeertaal C en geïmplementeerd boven de U-Boot bootloader, waarin eerder kwetsbaarheden zijn gevonden die voortkwamen uit problemen met het geheugenbeheer.
De herschreven firmware in Rust is opgenomen in Android 14, en de universele bibliotheken die tijdens het ontwikkelingsproces van de firmware zijn gemaakt, zijn verpakt als crate-pakketten en aan de Rust-gemeenschap overgedragen. Bijvoorbeeld, het gepubliceerde pakket smccc ter ondersteuning van de ARM-interfaces PSCI (Power State Coordination Interface) en SMCCC (SMC Calling Convention) aanroepen, en het pakket aarch64-paging voor het manipuleren van geheugenpagina-tabellen. Daarnaast is er gewerkt aan het oplossen van fouten en het uitbreiden van de functionaliteit van het bestaande pakket virtio-drivers met de implementatie van VirtIO-stuurprogramma's. Naast het Android-platform worden deze pakketten ook gebruikt in het Oak-project, dat componenten ontwikkelt voor het verzenden, opslaan en verwerken van gegevens in beveiligde omgevingen (TEE, Trusted Execution Environment).
De pVM-hypervisor krijgt vroeg in de opstartfase de controle en zorgt voor volledige geheugenisolatie virtuele machines en hostomgeving, waardoor het niet mogelijk is voor het hostsysteem om toegang te krijgen tot beveiligde virtuele machines waarin gevoelige gegevens worden verwerkt. De pvmfm-firmware (Protected Virtual Machine Firmware) krijgt de controle onmiddellijk na de opstart van de virtuele machine, voert een controle uit op de gevormde omgeving en neemt een beslissing over de noodstop van het opstartproces in geval van problemen met de integriteit, of genereert een opstartcertificaat voor het gast-systeem in het geval de vertrouwensketen wordt bevestigd.
Herwerking in de Rust-taal maakt het mogelijk om eenvoudiger en veiliger te voldoen aan de "twee-regels" die door Google zijn toegepast voor het waarborgen van de veiligheid van systeemcomponenten in Android. Volgens deze regel mag elke toegevoegde code niet aan meer dan twee van de drie voorwaarden voldoen: werken met niet-gevalideerde invoer, gebruik maken van een onveilige programmeertaal (C/C++) en uitvoeren met verhoogde rechten. Dit betekent dat code voor het verwerken van externe gegevens ofwel tot minimale rechten (geïsoleerd) moet worden beperkt, ofwel in een veilige programmeertaal moet worden geschreven. Volgens statistieken van Google zijn ongeveer 70% van alle gevaarlijke kwetsbaarheden die in Android zijn ontdekt, het gevolg van fouten bij het werken met geheugen.
Rust is gefocust op veilige geheugenbewerking en kan het risico op kwetsbaarheden verminderen die voortkomen uit problemen zoals toegang tot geheugen na vrijgave en buffer overflow. Veilige geheugenbewerking in Rust wordt tijdens de compilatie gegarandeerd door middel van referentiecontrole, eigendomstracking van objecten en het in aanmerking nemen van de levensduur van objecten (scope), evenals door de validatie van geheugen toegankelijkheid tijdens de uitvoering van de code. Rust biedt ook middelen ter bescherming tegen gehele getal overloop, vereist dat variabelen verplicht worden geïnitialiseerd voordat ze worden gebruikt, behandelt fouten beter in de standaardbibliotheek, hanteert het concept van onveranderlijke (immutable) referenties en variabelen standaard, en biedt sterke statische typisatie om logische fouten te minimaliseren.
Een van de moeilijkheden die zich voordoen bij de ontwikkeling van low-level componenten zoals stuurprogramma's in de Rust-taal, is de noodzaak om met ruwe pointers te werken in 'unsafe' modus, aangezien Rust is ontworpen met het oog op het gebruik van geheugen dat binnen het programma is toegewezen. In code die werkt zonder een laag bovenop de hardware, moet men interageren met gedeeld geheugen en MMIO. Momenteel laten de mogelijkheden van Rust voor het werken met ruwe pointers te wensen over, maar de situatie zou moeten verbeteren na de stabilisatie van de ondersteuning voor de macro's offset_of, slice_ptr_get en slice_ptr_len.
Een van de nadelen is ook de noodzaak van een verbeterde syntaxis voor de toegang tot velden van structuren en arrays via blote pointers zonder het maken van referenties, evenals de beperkingen bij het creëren van veilige wrappers voor onveilige operaties, die onbepaald gedrag kunnen veroorzaken en niet door de compiler kunnen worden geverifieerd. Bijvoorbeeld, dergelijke wrappers kunnen niet worden gemaakt voor operaties met paginatabellen in het geheugen, omdat de mapping van pagina's in een deel van een programma invloed kan hebben op andere delen.
Wat betreft de grootte van de resulterende code, de oude versie van de pVM-firmware nam 220 kB in beslag, terwijl de nieuwe 460 kB is. Echter, in de herschreven versie zijn nieuwe functies toegevoegd, waardoor het mogelijk werd om af te zien van sommige andere componenten die tijdens het opstarten werden gebruikt. Uiteindelijk bleek de totale grootte van alle oude en nieuwe opstartcomponenten vergelijkbaar te zijn. Opgemerkt wordt dat wanneer de grootte belangrijker is dan de prestaties, vergelijkbare resultaten die met de programmeertaal C zijn behaald, ook bereikt kunnen worden door extra optimalisatiemodi voor grootte in de compiler in te schakelen, onnodige afhankelijkheden weg te laten en geen stringformattering te gebruiken.
Daarnaast wordt gewerkt aan de implementatie van de mogelijkheid om betrouwbare applicaties (Trusted Application) geschreven in de programmeertaal Rust uit te voeren in het Trusty-besturingssysteem, dat een TEE-omgeving (Trusted Execution Environment) voor Android biedt, die parallel met Android op dezelfde processor in een aparte geïsoleerde omgeving draait. Trusty wordt gebruikt in Pixel-apparaten en maakt al gebruik van Rust in bibliotheken en systeemcomponenten (de kernel blijft in C).
Bron: opennet.ru
