
Ako ste zabrinuti za integritet svog sustava, dm-verity je jedan od ključnih dijelova Linux ekosustava. za sigurno pokretanje i otkrivanje neovlaštenih promjena u pohrani. Nastao je kao dio mapera uređaja u kernelu, a sada je osnova za provjereno pokretanje u Androidu, OpenWrt-u i distribucijama koje traže poboljšanu sigurnost.
Daleko od toga da je apstraktan pojam, dm-verity se konfigurira i koristi s pravim alatima poput veritysetup i systemd-veritysetupValidira blokove u hodu koristeći hash stabla i može reagirati na oštećenje politikama koje se kreću od zapisivanja događaja do ponovnog pokretanja ili rušenja sustava. Pogledajmo to pobliže, bez ostavljanja ikakvih nedovršenih pitanja.
Što je dm-verity i zašto bi vas to moglo zanimati
dm-verity je cilj mapiranja uređaja u kernelu koji provjerava integritet blokovskog uređaja dok se podaci čitajuRadi tako da izračunava i provjerava hashove svakog bloka (obično 4K) u odnosu na unaprijed izračunato hash stablo, obično koristeći SHA-256.
Ovaj dizajn omogućuje Datoteke se ne mogu tiho mijenjati između ponovnih pokretanja ili tijekom izvršavanjaKljučno je za proširenje lanca povjerenja u pokretanju operacijskog sustava, ograničavanje perzistencije zlonamjernog softvera, jačanje sigurnosnih politika i osiguranje mehanizama šifriranja i MAC adrese tijekom pokretanja.
Na Androidu (od verzije 4.4) i Linuxu općenito, Povjerenje je usidreno u korijenskom hashu stabla, koji je potpisan i validiran javnim ključem koji se nalazi na zaštićenoj lokaciji (npr. na boot particiji ili u Secure Boot-potpisanom UKI-ju). Probijanje bilo kojeg bloka zahtijevalo bi probijanje temeljnog kriptografskog hash-a.
Verifikacija se vrši blokovno i na zahtjev: Dodana latencija je minimalna u usporedbi s I/O troškovimaAko provjera ne uspije, kernel vraća I/O pogrešku i datotečni sustav izgleda oštećeno, što se očekuje kada su podaci nepouzdani. Aplikacije mogu odlučiti hoće li nastaviti ili ne na temelju svoje tolerancije na pogreške.
Kako stablo provjere funkcionira interno
Stablo provjere izgrađeno je u slojevima. Sloj 0 su sirovi podaci s uređaja, podijeljeni u blokove od 4K; SHA-256 (salted) hash se izračunava za svaki blok. Ti hashovi se zatim spajaju kako bi se formirao sloj 1. Sloj 1 se zatim grupira u blokove i ponovno hashira kako bi se formirao sloj 2 i tako dalje dok se sve ne stane u jedan blok: taj blok, kada se hashira, proizvodi korijenski hash.
Ako bilo koji sloj ne dovrši blok u potpunosti, Dopunjuje se nulama dok ne dostigne 4K kako bi se izbjegla dvosmislenost. Ukupna veličina stabla ovisi o veličini particije koja se provjerava; u praksi je obično manja od 30 MB za tipične sistemske particije.
Opći postupak je sljedeći: odaberite slučajnu sol, hashirajte na 4K, izračunajte SHA-256 sa soli po bloku, spaja se kako bi formirao razine, popunjava granicu bloka nulama i ponavlja se s prethodnom razinom dok ne ostane jedan korijenski hash. Taj korijenski hash, zajedno s korištenom soli, hrani dm-verity tablicu i potpis.
Verzije formata diska i algoritam
Format hash blokova na disku ima verziju. Verzija 0 bila je originalna verzija korištena u Chromium OS-u.Sol se dodaje na kraju procesa hashiranja, sažeci se pohranjuju kontinuirano, a ostatak bloka se dopunjuje nulama.
La Verzija 1 se preporučuje za nove uređajeSalt se dodaje na početak hash-a, a svaki sažetak se nadopunjuje nulama do potencija dva, poboljšavajući poravnanje i robusnost. dm-verity tablica također specificira algoritam (npr. sha1 ili sha256), iako se za trenutnu sigurnost koristi sha256.
dm-verity tablica i bitni parametri
Ciljna tablica dm-verity opisuje gdje se nalaze podaci, gdje se nalazi hash stablo i kako to provjeritiTipična polja tablice:
- devuređaj s podacima koje treba provjeriti (tip puta /dev/sdXN ili veći:manji).
- hash_dev: uređaj s hash stablom (može biti isti; ako je tako, hash_start mora biti izvan označenog raspona).
- veličina bloka podataka: veličina bloka podataka u bajtovima (npr. 4096).
- veličina_bloka_hash-a: veličina hash bloka u bajtovima.
- broj_blokova_podataka: broj provjerljivih blokova podataka.
- hash_start_block: pomak (u blokovima hash_block_size) u odnosu na korijenski blok stabla.
- algoritam: algoritam za hashiranje (npr. sha256).
- probavitiheksadecimalno kodiranje hash-a korijenskog bloka (uključujući sol prema verziji formata); ovoj vrijednosti treba vjerovati.
- solheksadecimalna sol.
Osim toga, postoje opcionalni parametri vrlo korisno za prilagodbu ponašanja:
- ignoriraj_korupciju: Zapisuje oštećene blokove, ali dopušta nastavak čitanja.
- ponovno_pokretanje_pri_korupciji: ponovno pokretanje nakon otkrivanja korupcije (nije kompatibilno s ignore_corruption i zahtijeva podršku korisničkog prostora kako bi se izbjegle petlje).
- panika_zbog_korupcije: : uzrokuje paniku prilikom otkrivanja korupcije (nije kompatibilno s prethodnim verzijama).
- ponovno_pokretanje_pri_pogrešci y panika_zbog_pogreškeiste reakcije, ali za I/O pogreške.
- ignoriraj_nula_blokova: ne provjerava blokove koji se očekuju kao nule i vraća nule.
- korištenje_fec_from_device + fec_roots + fec_blokovi + fec_startOmogućite Reed-Solomonu (FEC) za oporavak podataka kada provjera ne uspije; područja podataka, hash-a i FEC-a ne smiju se preklapati, a veličine blokova moraju se podudarati.
- provjeri_najviše_jednomProvjerava svaki blok podataka samo prvi put kada se čita (smanjuje opterećenje nauštrb sigurnosti kod napada uživo).
- opis_root_hash_sign_key-a: Referenca na ključ u privjesku ključeva za validaciju PKCS7 potpisa korijenskog hash-a prilikom stvaranja mapiranja (zahtijeva odgovarajuću konfiguraciju jezgre i pouzdane privjeske ključeva).
- try_verify_in_taskletAko su hashevi predmemorirani i veličina I/O-a to dopušta, provjerava donju polovicu kako bi se smanjila latencija; podešava se s /sys/module/dm_verity/parameters/use_bh_bytes po I/O klasi.
Potpis, metapodaci i usidravanje povjerenja
Da bi dm-verity bio pouzdan, Root hash mora biti pouzdan i obično potpisanU klasičnom Androidu, javni ključ je uključen u boot particiju, koju eksterno provjerava proizvođač; on potvrđuje potpis root hash-a i osigurava da sistemska particija nije promijenjena.
Verity metapodaci dodaju strukturu i kontrolu verzija. Blok metapodataka uključuje magični broj 0xb001b001 (bajtovi b0 01 b0 01), verzija (trenutno 0), potpis tablice u PKCS1.5 (obično 256 bajtova za RSA-2048), duljina tablice, sama tablica i nula popunjavanja do 32K.
U Android implementacijama, provjera se oslanja na fs_mgr i fstabDodavanje kvačice odgovarajućem unosu i postavljanje ključa u /boot/verity_key. Ako magični broj nije tamo gdje bi trebao biti, provjera se zaustavlja kako bi se izbjegla provjera pogrešne stvari.
Početak operacije potvrđen
Zaštita se nalazi u jezgri: Ako je kompromitirano prije pokretanja kernela, napadač zadržava kontroluZato proizvođači obično strogo validiraju svaku fazu: ključ ugrađen u uređaj provjerava prvi bootloader, koji provjerava sljedeći, bootloader aplikacije, i na kraju, kernel.
S provjerenom kernelom, dm-verity je omogućen prilikom montiranja verificiranog blokovnog uređajaUmjesto hashiranja cijelog uređaja (što bi bilo sporo i trošilo energiju), provjerava se blok po blok dok mu se pristupa. Kvar uzrokuje I/O pogrešku, a usluge i aplikacije reagiraju prema svojoj toleranciji: ili nastavljaju bez tih podataka ili se potpuno ruše.
Ispravljanje pogrešaka unaprijed (FEC)
Od Androida 7.0, FEC (Reed-Solomon) je ugrađen s tehnikama ispreplitanja kako bi se smanjio prostor i povećala mogućnost oporavka oštećenih blokova. To funkcionira zajedno s dm-verity: ako provjera ne uspije, podsustav može pokušati ispraviti prije nego što je proglasi nepopravljivom.
Izvedba i optimizacija
Za smanjenje utjecaja: Omogući SHA-2 ubrzanje pomoću NEON-a na ARMv7 i SHA-2 proširenja na ARMv8 iz kernela. Prilagodite parametre unaprijednog čitanja i prefetch_cluster za svoj hardver; provjera po bloku obično malo doprinosi troškovima ulazno/izlaznih operacija, ali ove postavke čine razliku.
Početak rada na Linuxu (systemd, veritysetup) i Androidu
Na modernom Linuxu sa systemd-om, dm-verity omogućuje verificirani root samo za čitanje korištenjem veritysetup-a (dio cryptsetup-a), systemd-veritysetup.generator i systemd-veritysetup@.service. Preporučuje se uključivanje Secure Boot-a i potpisane UKI (unified kernel image), iako nisu strogo obavezni.
Priprema i preporučeno particioniranje
Dio funkcionalnog i prilagođenog sustava. Rezervirajte volumen za hash stablo (8–10% veličine root direktorija je obično dovoljno) i razmislite o odvajanju /home i /var direktorija ako trebate pisati. Tipična shema uključuje: ESP (za bootloader), XBOOTLDR (za UKI-je), root (sa ili bez enkripcije), VERITY particiju i opcionalno /home i /var.
Kao korijen, EROFS je vrlo zanimljiva alternativa za ext4 ili squashfsDizajniran je samo za čitanje, s vrlo dobrim performansama na flash/SSD-u, lz4 kompresijom prema zadanim postavkama i široko se koristi na Android telefonima s dm-verityjem.
Datoteke koje moraju biti zapisive
S root ro, neki programi očekuju pisanje u /etc ili tijekom init-aMožete ga premjestiti u /var/etc i simbolički povezati sve što treba promijeniti (npr. veze NetworkManagera u /etc/NetworkManager/system-connections). Imajte na umu da systemd-journald zahtijeva da /etc/machine-id postoji u korijenskom direktoriju (ne simbolička veza) kako bi se izbjeglo rano pokretanje.
Da biste saznali koje se promjene u izvršenju događaju, koristite dracut-overlayroot: prekriva tmpfs preko korijena, a sve što je zapisano pojavljuje se u /run/overlayroot/u. Dodajte modul u /usr/lib/dracut/modules.d/, uključite overlayroot u dracut i postavite overlayroot=1 u liniji kernela; na taj način ćete vidjeti što migrirati u /var.
Korisni primjeri: pacman i NetworkManager
U Archu je zgodno Premjestite Pacman bazu podataka u /usr/lib/pacman tako da rootfs uvijek zrcali instalirane pakete. Zatim preusmjerite predmemoriju na /var/lib/pacman i povežite je. Za promjenu mirrorlista bez dodirivanja korijena, premjestite je u /var/etc i svejedno povežite.
S NetworkManagerom, premjesti sistemske veze u /var/etc/NetworkManager i vezu iz /etc/NetworkManager/system-connections. To održava korijen nepromjenjivim, a konfiguraciju aktivnom tamo gdje bi trebala biti dostupna za pisanje.
Konstrukcija istinitosti i testiranje
Iz uživo i sa svim savršenim i montiranim u ro, stvorite stablo i roothash s format veritysetup-aPrilikom pokretanja, ispisuje liniju Root Hash, koju možete spremiti u roothash.txt. Pokrenite ga za testiranje s veritysetup open root-device root verity-device $(cat roothash.txt) i mount /dev/mapper/root.
Ako želite, prvo generira stablo u datoteku (verity.bin) i zatim ga zapišite na VERITY particiju. Rezultirajući skup je: korijenska slika, verity stablo i korijenski hash koji ćete zapisati prilikom pokretanja.
Konfigurirajte liniju kernela
Dodajte ove parametre: systemd.verity=1, roothash=contents_of_roothash.txt, systemd.verity_root_data=ROOT-PATH (npr. LABEL=OS) i systemd.verity_root_hash=VERITY-PATH (npr. LABEL=VERITY). Postavite systemd.verity_root_options na restart-on-corruption ili panic-on-corruption za stroge politike.
Druge preporučene opcije: ro (ako ne koristite EROFS/squashfs), rd.emergency=ponovno pokretanje y rd.ljuska=0 (sprečavanje neovlaštenih ljuski ako pokretanje ne uspije) i zaključavanje=povjerljivost kako bi se zaštitila memorija kernela od pristupa.
Dodatne pregrade s Verityjem
Ne samo korijen: Možete definirati druga mapiranja u /etc/veritytab i systemd-veritysetup@.service će ih sastaviti prilikom pokretanja. Zapamtite: lakše je RW montirati particiju koja nije root, a root korisnik može onemogućiti Verity na tim particijama, pa je sigurnosna vrijednost tamo niža.
Sigurnost: Secure Boot, UKI i potpisani moduli
dm-verity nije čarobni štapić. Potpišite UKI i omogućite Secure Boot vlastitim ključevima kako bi se spriječilo da itko prepiše kernel/initramfs/cmdline (što uključuje root hash). Alati poput sbupdate-git ili sbctl pomažu u održavanju potpisanih slika i netaknutog lanca pokretanja.
Ako omogućite zaključavanje kernela ili provjeru potpisa modula, DKMS ili moduli izvan stabla moraju biti potpisani ili se neće učitati. Razmislite o prilagođenoj jezgri s podrškom za potpisivanje za vaš cjevovod (pogledajte potpisane module jezgre).
Šifriranje, TPM i mjerenje
dm-verity štiti integritet, ne-povjerljivostMožete ostaviti root nešifriranim ako ne sadrži nikakve tajne i ako je lanac pokretanja zaštićen. Ako koristite ključne datoteke iz roota za otključavanje drugih volumena, dobra je ideja šifrirati ga.
S TPM-om 2.0, systemd-cryptenroll omogućuje vezanje ključeva na PCR-ove 0,1,5,7 (firmware, opcije, GPT, status sigurnog pokretanja). Dodajte rd.luks.options=LUKS_UUID=tpm2-device=auto i obavezno uključite podršku za TPM2 u initramfs. systemd-boot mjeri kernel.efi u PCR4, korisno za poništavanje ključeva ako se UKI ili njegov cmdline promijene.
Ažuriranja i modeli implementacije
Potvrđeni korijen samo za čitanje Ne ažurira se upraviteljem paketa na tradicionalan način.Idealno je izgraditi nove slike alatima poput projekt Yocto i objavite ih. systemd ima systemd-sysupdate i systemd-repart za robusno preuzimanje i fleširanje slika.
Druga strategija je A/B shemaZadržavate dva korijena i dva verityja. Kopirajte aktivni korijen u neaktivni korijen, primijenite promjene i ponovite verity. Vratite se pri sljedećem pokretanju. Ako koristite UKI, ne zaboravite ažurirati root hash u cmd retku ili ponovno izgraditi potpisani UKI.
Za opcionalnu perzistenciju, koristite OverlayFS na verificiranom korijenu s gornjim u tmpfs-u ili disku. Također možete proslijediti systemd.volatile=overlay za privremenu perzistenciju. Flatpak olakšava instaliranje aplikacija u /var i /home bez dodirivanja /.
Postoje automatizirani paketi (npr. verity-squash-root u AUR-u) koji grade korijenski direktorij squashfs-a i potpišite roothash s kernelom i initramfs-om, što vam omogućuje odabir između trajnog ili kratkotrajnog načina rada i čuvanje najnovijih rootfs datoteka kao sigurnosne kopije. Napomena: dodavanje trajnosti na provjereni root ima uske slučajeve upotrebe; pokušajte pohraniti podatke aplikacije na zasebne particije.
Android: sustav kao root, AVB i preklapanja dobavljača
Od Androida 10, RootFS prestaje raditi na RAM disku i integrira se sa system.img. (system-as-root). Uređaji koji se pokreću s Androidom 10 uvijek koriste ovu shemu i zahtijevaju ramdisk za dm-linear. BOARD_BUILD_SYSTEM_ROOT_IMAGE je postavljen na false u ovoj verziji kako bi se razlikovalo korištenje ramdiska od izravne aktivacije system.img.
Uključuje Android 10 dinamičke particije i init prve faze što aktivira logičku sistemsku particiju; kernel je više ne montira izravno. OTA-ovi samo za sustav zahtijevaju dizajn sustava kao root, što je obavezno na Android 10 uređajima.
Ni u jednom A/B, odvojite oporavak od pokretanjaZa razliku od A/B, ne postoji sigurnosna kopija boot_a/boot_b, pa uklanjanje oporavka u ne-A/B može vas ostaviti bez načina oporavka ako ažuriranje pokretanja ne uspije.
Jezgra montira system.img u /converity putem dvije putanje: vboot 1.0 (zakrpe za kernel za parsiranje Android metapodataka u /system i izvođenje dm-verity parametara; cmdline uključuje root=/dev/dm-0, skip_initramfs i init=/init s dm=…) ili vboot 2.0/AVB, gdje bootloader integrira libavb, čita deskriptor hashtree-a (u vbmeta ili system), konstruira parametre i prosljeđuje ih kernelu u cmdlineu, s FEC podrškom i oznakama poput restart_on_corruption.
Sa sustavom kao korijenom, Ne koristite BOARD_ROOT_EXTRA_FOLDERS za korijenske mape specifične za uređaj: one će nestati prilikom flashanja GSI-ja. Definirajte specifične nosače pod /mnt/vendor/ , koje fs_mgr automatski stvara, i referenciraju ih u fstab stabla uređaja.
Android omogućuje preklapanje dobavljača iz /product/vendor_overlay/: init će montirati u /vendor poddirektorije koje zadovoljavaju SELinux kontekstne zahtjeve i postojanje /vendor/ Zahtijeva CONFIG_OVERLAY_FS=yy, na starijim jezgrama, zakrpu override_creds=off.
Tipična implementacija: instalira prethodno kompajlirane datoteke u uređaj/ / /prekrivanje_dobavljača/, dodajte ih u PRODUCT_COPY_FILES s find-copy-subdir-files u $(TARGET_COPY_OUT_PRODUCT)/vendor_overlay, definirajte kontekste u file_contexts za etc i app (npr. vendor_configs_file i vendor_app_file) i dopustite montiranje na tim kontekstima u init.te. Testirajte s atest vfs_mgr_vendor_overlay_test u userdebug.
Rješavanje problema: poruka o oštećenju dm-verity na Androidu
Na uređajima s A/B utorima, promijenite utore ili Flashanje vbmeta/boot bez konzistentnosti s roothashom Ovo može pokrenuti upozorenje: dm-verity oštećenje, vaš uređaj nije pouzdan. Naredbe poput fastboot flash –disable-verity –disable-verification vbmeta vbmeta.img onemogućuju provjeru, ali ostavljaju sustav bez ikakvih jamstava integriteta.
Neki bootloaderi podržavaju fastboot oem disable_dm_verity i njegova suprotnost, enable_dm_verity. Radi na nekim modelima, ali ne na drugima; i može zahtijevati kernel/magisk s prilagođenim zastavicama. Koristite na vlastitu odgovornost: razuman postupak je poravnaj boot, vbmeta i system, potpišite ili regenerirajte stablo i provjerite odgovara li očekivani korijenski hash konfiguriranom.
Ako nakon upozorenja možete nastaviti pritiskati tipku za napajanje, sustav se pokreće, ali više nemaš netaknut lanac povjerenjaZa uklanjanje poruke bez žrtvovanja sigurnosti, vratite originalne potpisane slike ili ponovno izgradite/provjerite vbmeta s ispravnim hashtreeom, umjesto da onemogućujete verity.
i.MX i OpenWrt platforme
Na i.MX6 (npr. sabresd), konfigurirajte kernel s DM_VERITY i FEC podrškom, generirajte stablo s veritysetup-om, sigurno pohranite korijenski hash i proslijedite odgovarajuće parametre u cmd liniji ili integrirajte putem initramfs-a sa systemd-veritysetup-om. Ako ne koristite dm-crypt, ne trebate CAAM za verity; fokus je na integritetu.
U OpenWrtu i u ugrađeni Linux sustavi s OpenEmbedded-om, Postoje napori za integraciju dm-verityja i SELinuxa (Bootlin poslovi revidirani s namjerom uključivanja podrške). To je prirodno uklapanje: usmjerivači i mrežna oprema imaju koristi od nepromjenjivog, provjerenog i MAC-ojačanog korijena.
Ručna izrada stabla i metapodataka (detaljan prikaz)
cryptsetup može generirati stablo za vas, ali ako radije razumijete format, definicija kompaktne tablice uključuje: naziv mapiranja, podatkovni uređaj, veličine podatkovnih blokova i hash-a, veličina slike u blokovima, hash_start position (slika bloka + 8 ako je spojeno), root hash i sol. Nakon generiranja spojenih slojeva (od vrha do dna, isključujući sloj 0), stablo se zapisuje na disk.
Da sve spakiram, sastaviti dm-verity tablicu, potpisati je (tipično RSA-2048) i grupirati tablicu potpisa+u metapodacima s verzijskim zaglavljem i magičnim brojem. Zatim spaja sliku sustava, verity metapodatke i hash stablo. U fstab-u označava fs_mgr kao verify i stavlja javni ključ u /boot/verity_key za validaciju potpisa.
Optimiziraj s SHA-2 ubrzanja za vaš CPU i prilagodite unaprijed čitanje/prefetch_cluster. Na ARM hardveru, NEON SHA-2 (ARMv7) i SHA-2 proširenja (ARMv8) značajno smanjuju opterećenje provjere.
Prilikom bilo kakvog raspoređivanja, imajte na umu da Vrijednost korijenskog hash-a mora biti zaštićena: bilo da je kompiliran u potpisani UKI, u potpisanu boot particiju ili validiran od strane bootloadera pomoću AVB-a. Sve nakon te točke nasljeđuje to povjerenje.
Uz sve navedeno, dm-verity postaje čvrst temelj za nepromjenjive, mobilne i ugrađene sustave, podržavajući transakcijska ažuriranja, konfiguracijske slojeve i moderni sigurnosni model koji smanjuje površinu napada i sprječava upornost bez žrtvovanja performansi.


