Guglo reverkis la pvmfm-firmvaron uzatan en Android en Rust.

Kiel parto de siaj klopodoj plifortigi la sekurecon de kritikaj programaraj komponantoj de la platformo Android, Google reskribis la firmvaron pvmfm, uzatan por funkciigi virtualajn maŝinojn lanĉitajn de la hipervizoro pVM el la Android Virtualization Framework, en Rust. Antaŭe, la firmvaro estis skribita en C kaj efektivigita sur la startigilo U-Boot, kies kodo antaŭe estis trovita enhavanta vundeblecojn kaŭzitajn de memorproblemoj.

La firmvaro reverkita en Rust estas inkluzivita en Android 14, kaj la universalaj bibliotekoj kreitaj dum la firmvara disvolviĝo estis pakitaj kiel kestaj pakaĵoj kaj donacitaj al la Rust-komunumo. Ekzemple, la pakaĵo smccc estis publikigita por subteni la interfacojn PSCI (Power State Coordination Interface) de ARM kaj la alvokojn SMCCC (SMC Calling Convention), same kiel la pakaĵon aarch64-paging por manipuli memorpaĝajn tabelojn. Oni ankaŭ laboris por ripari cimojn kaj vastigi la funkciojn de la ekzistanta pakaĵo virtio-drivers, kiu efektivigas VirtIO-pelilojn. Aldone al la Android-platformo, ĉi tiuj pakaĵoj ankaŭ estas uzataj en la projekto Oak, kiu disvolvas komponantojn por sendi, stoki kaj prilabori datumojn en fidindaj ekzekutmedioj (TEE).

La pVM-hipervizoro prenas kontrolon frue en la startprocezo kaj provizas plenan memorizolaĵon. virtualaj maŝinoj kaj la gastiganta medio, malhelpante la gastigan sistemon aliri protektitajn virtualajn maŝinojn kie sentemaj datumoj estas prilaborataj. La pvmfm (Protektita Virtuala Maŝina Firmvaro) firmvaro prenas kontrolon tuj post kiam la virtuala maŝino startas, kontrolas la kreitan medion, kaj decidas ĉu ĉesigi la startigon se integrecproblemoj estas detektitaj aŭ generas startigan atestilon por la gasta sistemo se la ĉeno de fido estas konfirmita.

Refaktorigo en Rust ebligas pli simplan kaj pli sekuran plenumon de la "regulo de du", kiun Google uzas por konservi la sekurecon de la komponantoj de la Android-sistemo. Ĉi tiu regulo deklaras, ke ĉiu aldonita kodo devas plenumi ne pli ol du el tri kondiĉoj: pritrakti nefidindan enigon, uzi nesekuran programlingvon (C/C++), kaj plenumi kun pli altaj privilegioj. Ĉi tiu regulo ankaŭ implicas, ke kodo pritraktanta eksterajn datumojn devas esti aŭ reduktita al minimumaj privilegioj (izolita) aŭ skribita en sekura programlingvo. Laŭ statistikoj de Google, proksimume 70% de ĉiuj danĝeraj vundeblecoj identigitaj en Android estas kaŭzitaj de memoradministraj eraroj.

Rust fokusiĝas al memorsekureco kaj reduktas la riskon de vundeblecoj kaŭzitaj de problemoj kiel uzo-post-liberigo kaj bufro-troŝarĝoj. Rust certigas memorsekurecon dum kompilado per referenckontrolado, spurado de objekta proprieto, kaj objekta vivdaŭro (ampleksa) kontado, same kiel per validigo de memoraliro dum rultempo. Rust ankaŭ provizas protekton kontraŭ entjeraj troŝarĝoj, postulas devigan inicialigon de variablovaloroj antaŭ uzo, pli bone traktas erarojn en la norma biblioteko, efektivigas la koncepton de neŝanĝeblaj referencoj kaj variabloj defaŭlte, kaj ofertas fortan statikan tajpadon por minimumigi logikajn erarojn.

Unu malfacilaĵo renkontata dum disvolvado de malaltnivelaj komponantoj kiel peliloj en Rust estas la bezono pritrakti nudajn montrilojn en nesekura reĝimo. Rust estas desegnita konsiderante program-asignitan memoron, dum kodo funkcianta sen aparataraj interkovroj devas aliri komunan memoron kaj MMIO. La kapabloj de Rust pritrakti nudajn montrilojn nuntempe lasas multe por deziri, sed tio devus pliboniĝi post kiam subteno por la makrooj offset_of, slice_ptr_get, kaj slice_ptr_len stabiliĝos.

Aliaj rimarkindaj mankoj inkluzivas la bezonon de plibonigita sintakso por aliri strukturajn kampojn kaj tabelajn indeksojn per simplaj montriloj sen krei referencojn, same kiel limigojn en kreado de sekuraj envolvaĵoj por nesekuraj operacioj, kiuj povas kaŭzi nedifinitan konduton kaj ne povas esti kontrolitaj de la kompililo. Ekzemple, tiajn envolvaĵojn ne eblas krei por operacioj kun memorpaĝaj tabeloj, ĉar paĝmapado en unu parto de la programo povas influi aliajn partojn.

Rilate al la rezulta kodgrandeco, la malnova pVM-firmvara versio okupis 220 KB, dum la nova okupis 460 KB. Tamen, la reskribita versio aldonis novajn funkciojn, kiuj permesis al ni forigi iujn aliajn komponantojn uzatajn dum la startigo. Rezulte, la tuta grandeco de ĉiuj malnovaj kaj novaj startigaj komponantoj estis komparebla. Rimarkinde, kiam grandeco estas pli grava ol rendimento, rezultoj kompareblaj al tiuj en C povas esti atingitaj per ebligado de pliaj grandec-optimumigaj reĝimoj en la kompililo, forigante nenecesajn dependecojn, kaj ne uzante ĉenformatajn ilojn.

Krome, oni daŭrigas la laboron por ebligi la lanĉon de fidindaj aplikaĵoj skribitaj en Rust en la operaciumo Trusty, kiu provizas Fidindan Ekzekutan Medion (TEE) por Android, kiu funkcias paralele kun Android sur la sama procesoro en aparta, izolita medio. Trusty estas uzata en Pixel-aparatoj kaj jam uzas Rust en bibliotekoj kaj sistemaj komponantoj (la kerno restas en C).

fonto: opennet.ru

Aldoni komenton