Az Android platform kritikus szoftverkomponenseinek biztonságának megerősítése érdekében a Google újraírta a pvmfm firmware-t a Rust nyelven, amelyet a pVM hypervisor által indított virtuális gépek működtetésére használnak az Android Virtualization Framework keretein belül. A firmware korábban C nyelven íródott és az U-Boot bootloaderre épült, amelyben korábban memóriakezelési problémák miatt találtak sebezhetőségeket.
A Rust nyelvre újraírt firmware az Android 14 része, és a firmware fejlesztése során létrehozott általános könyvtárakat crate-csomagok formájában átadták a Rust közösségnek. Például közzétették az smccc csomagot az ARM PSCI (Power State Coordination Interface) interfészek és az SMCCC (SMC Calling Convention) hívások támogatására, valamint az aarch64-paging csomagot a memóriaoldal-táblák kezelésére. Emellett a meglévő virtio-drivers csomag hibáinak kijavításán és funkcionalitásának bővítésén is dolgoztak a VirtIO illesztőprogramok megvalósításával. Az Android platform mellett a fent említett csomagokat az Oak projekt is használja, amely biztonságos környezetekben (TEE, Trusted Execution Environment) történő adatátvitel, tárolás és feldolgozás komponenseit fejleszti.
A pVM hypervisor a betöltés korai szakaszában kapja meg az irányítást, és teljes memóriaizolációt biztosít. virtuális gépekhez és egy host-környezetet, megakadályozva, hogy a host-rendszer hozzáférjen a védett virtuális gépekhez, ahol bizalmas adatokat dolgoznak fel. A pvmfm (Protected Virtual Machine Firmware) firmware azonnal a virtuális gép elindítása után kapja meg az irányítást, ellenőrzi a létrejött környezetet, és döntést hoz a betöltés sürgősségi megszakításáról, ha a integritással kapcsolatos problémákat észlel, vagy generálja a guest rendszer boot tanúsítványát, ha megerősíti a bizalmi láncot.
A Rust nyelvre való átírás lehetővé teszi a Google által alkalmazott „két szabály” egyszerűbb és biztonságosabb betartását, amely a Android rendszerkomponenseinek biztonságát hivatott fenntartani. E szabály értelmében minden hozzáadott kódnak legfeljebb két feltételnek kell megfelelnie a három közül: nem ellenőrzött bemenetek kezelése, nem biztonságos programozási nyelv használata (C/C++) és emelt jogosultságú végrehajtás. E szabályból következik, hogy a külső adatok feldolgozására szánt kódnak vagy minimális jogosultságúra kell korlátozódnia (izolálva), vagy biztonságos programozási nyelven kell íródnia. A Google statisztikái szerint az Android összes kritikus sebezhetőségének körülbelül 70%-át a memóriakezelési hibák okozzák.
A Rust a memória biztonságos kezelésére összpontosít, és lehetővé teszi a sebezhetőségek kockázatának csökkentését, amelyek olyan problémák miatt merülhetnek fel, mint például a memória kiszabadítása utáni hivatkozások és a puffertúllépés. A Rustban a memória biztonságos kezelése a fordítás során történik, ami magában foglalja a hivatkozások ellenőrzését, az objektumok tulajdonlásának nyomon követését és az objektumok élettartamának figyelembevételét (láthatósági tartomány), valamint a memóriahozzáférés helyességének értékelését a kód végrehajtása közben. A Rust olyan eszközöket is biztosít, amelyek megvédik a számjegyek túlfutásától, kötelezővé teszi a változók értékeinek inicializálását használat előtt, jobb hibakezelést kínál a standard könyvtárban, alkalmazza a változók alapértelmezett immutabilitását (változatlanságát), és erős statikus típuskészítést kínál a logikai hibák minimalizálása érdekében.
A Rust nyelven történő alacsony szintű komponensek, például illesztőprogramok fejlesztése során felmerülő nehézségek között említjük a nyers pointerek unsafe módban való kezelésének szükségességét, mivel a Rust a programban lefoglalt memória használatára figyelemmel készült, és a hardver fölötti rétegek nélküli kód esetén a megosztott memória és az MMIO elérésére van szükség. Jelenleg a Rust nyers pointerekkel való munkavégzése kívánnivalót hagy maga után, de a helyzetnek javulnia kell a offset_of, slice_ptr_get és slice_ptr_len makrók támogatásának stabilizálása után.
Ami a hátrányokat illeti, figyelmet érdemel a struktúrák mezőihez és a tömbök indexeihez való hozzáféréshez szükséges javított szintaxis iránti igény, amely nyers mutatók használatával valósul meg, anélkül hogy hivatkozásokat kéne létrehozni, valamint a biztonságos burkolatok létrehozásának korlátai az olyan unsafe műveletek felett, amelyek előre nem látható viselkedést okozhatnak és nem ellenőrizhetők a fordító által. Például az ilyen burkolatok nem hozhatók létre a memóriapeszélytáblákkal végzett műveletekhez, mivel az oldalak leképezése a program egyik részében hatással lehet a másik részeire.
Ami a keletkező kód méretét illeti, a régi pVM firmware 220 kB-ot fogyasztott, míg az új 460 kB, de a felújított változat új lehetőségeket tartalmaz, amelyek révén sikerült megszabadulni néhány más alkatrész használatától a betöltés során. Ennek eredményeként az összes régi és új betöltő komponens összmérete összehasonlítható lett. Megjegyzik, hogy amikor a méret fontosabb, mint a teljesítmény, a C nyelvhez hasonló eredmények érhetők el, ha a fordítóban különböző méretoptimalizáló módokat aktiválunk, elhagyjuk a felesleges függőségeket és nem használunk karakterlánc-formázási eszközöket.
Továbbá említésre kerül egy megbízható alkalmazások (Trusted Application) indításának megvalósításánál végzett munka, amelyeket Rust nyelven írtak, a Trusty operációs rendszerben, amely TEE környezetet (Trusted Execution Environment) biztosít Android számára, párhuzamosan futva az Androiddal ugyanazon a processzoron, egy elkülönített, izolált környezetben. A Trusty már a Pixel eszközökben is használatban van, és már használ Rust-ot könyvtárakban és rendszerkomponensekben (a kernel C nyelven marad).
Forrás: opennet.ru
