Kako uporabljati dm-verity v Linuxu: Popoln in praktičen vodnik

  • dm-verity sproti preverja bloke s podpisanim korenskim zgoščevalnim drevesom in s tem zasidra zagonsko verigo zaupanja.
  • Njegova sodobna uvedba združuje veritysetup, systemd-veritysetup, Secure Boot in UKI za zaščito jedra, initramfs in ukazne vrstice.
  • Android uporablja system-as-root in AVB za posredovanje parametrov dm-verity; FEC in reactive politike izboljšujejo robustnost.
  • Nespremenljivi koren zahteva ločevanje zapisljivih podatkov (/var, /home) in načrtovanje posodobitev z uporabo slik ali A/B shem.

dm-verity v Linuxu

Če vas skrbi celovitost vašega sistema, dm-verity je eden ključnih delov ekosistema Linux. za varen zagon in zaznavanje nedovoljenih posegov v pomnilnik. Izvira kot del preslikovalnika naprav v jedru in je zdaj osnova za preverjen zagon v Androidu, OpenWrt in distribucijah, ki iščejo izboljšano varnost.

Daleč od tega, da bi bil abstrakten pojem, dm-verity je konfiguriran in se uporablja z resničnimi orodji, kot sta veritysetup in systemd-veritysetupSproti preverja bloke z uporabo zgoščevalnih dreves in se lahko odzove na poškodbe s politikami, ki segajo od beleženja dogodka do ponovnega zagona ali zrušitve sistema. Oglejmo si to podrobneje, ne da bi pustili odprte konce.

Kaj je dm-verity in zakaj bi vas to lahko zanimalo

Preverjanje integritete z dm-verity

dm-verity je ciljni program za preslikavo naprav v jedru, ki preveri integriteto blokovne naprave med branjem podatkovDeluje tako, da izračuna in preveri zgoščene vrednosti vsakega bloka (običajno 4K) glede na vnaprej izračunano zgoščevalno drevo, običajno z uporabo SHA-256.

Ta zasnova omogoča Datotek ni mogoče tiho spreminjati med ponovnimi zagoni ali med izvajanjemKljučnega pomena je za razširitev zagonske verige zaupanja v operacijski sistem, omejevanje vztrajnosti zlonamerne programske opreme, krepitev varnostnih politik ter zagotavljanje mehanizmov šifriranja in MAC med zagonom.

V sistemu Android (od različice 4.4) in Linuxu na splošno, Zaupanje je zasidrano v korenski zgoščevalni vrednosti drevesa, ki je podpisan in potrjen z javnim ključem, ki se nahaja na zaščiteni lokaciji (npr. na zagonski particiji ali v UKI, podpisanem z varnim zagonom). Razbijanje katerega koli bloka bi zahtevalo razbijanje osnovne kriptografske zgoščene vrednosti.

Preverjanje se izvaja po blokih in na zahtevo: Dodana latenca je minimalna v primerjavi s stroški V/I.Če preverjanje ne uspe, jedro vrne napako V/I in datotečni sistem se zdi poškodovan, kar je pričakovano, kadar podatki niso zanesljivi. Aplikacije se lahko na podlagi svoje tolerance napak odločijo, ali bodo nadaljevale ali ne.

Kako deluje drevo preverjanja interno

Drevo preverjanja je zgrajeno v plasteh. Plast 0 so surovi podatki iz naprave, razdeljeni na 4K bloke; za vsak blok se izračuna zgoščena vrednost SHA-256 (soljena). Te zgoščene vrednosti se nato združijo v plast 1. Plast 1 se nato združi v bloke in ponovno zgošči, da se oblikuje plast 2, in tako naprej, dokler se vse ne prilega enemu bloku: ta blok, ko je zgoščen, ustvari korensko zgoščeno vrednost.

Če katera koli plast ne dokonča natančno bloka, Dopolni se z ničlami, dokler ne doseže 4K da se izognemo dvoumnosti. Skupna velikost drevesa je odvisna od velikosti particije, ki jo preverjamo; v praksi je običajno manjša od 30 MB za tipične sistemske particije.

Splošni postopek je: izberi naključno sol, zgosti na 4K, izračunaj SHA-256 s soljo na blok, združuje in tvori nivoje, mejo bloka dopolni z ničlami ​​in ponavlja s prejšnjim nivojem, dokler ne ostane en sam korenski zgoščeni niz. Ta korenski zgoščeni niz skupaj z uporabljeno soljo napaja tabelo dm-verity in podpis.

Različice formatov diskov in algoritem

Format zgoščevalnih blokov na disku ima različico. Različica 0 je bila prvotna različica, ki se je uporabljala v Chromium OS.Sol se doda na koncu postopka zgoščevanja, prebavni podatki se shranjujejo neprekinjeno, preostali del bloka pa se dopolni z ničlami.

La Za nove naprave je priporočljiva različica 1.: Sol je dodana na začetek zgoščene vrednosti, vsak prebavni niz pa je dopolnjen z ničlami ​​do potenc dveh, kar izboljša poravnavo in robustnost. Tabela dm-verity določa tudi algoritem (npr. sha1 ali sha256), čeprav se za trenutno varnost uporablja sha256.

dm-verity tabela in bistveni parametri

Ciljna tabela dm-verity opisuje kje so podatki, kje je zgoščevalno drevo in kako to preveritiTipična polja tabele:

  • dev: naprava s podatki, ki jih je treba preveriti (vrsta poti /dev/sdXN ali večja:manjša).
  • hash_dev: naprava z zgoščevalnim drevesom (lahko je enaka; če je tako, mora biti hash_start zunaj označenega območja).
  • velikost_bloka_podatkov: velikost podatkovnega bloka v bajtih (npr. 4096).
  • velikost_zgoščevalnega_bloka: velikost zgoščevalnega bloka v bajtih.
  • število_blokov_podatkov: število preverljivih podatkovnih blokov.
  • blok_začetne_zgoščitve: odmik (v blokih hash_block_size) od korenskega bloka drevesa.
  • algoritem: algoritem zgoščevanja (npr. sha256).
  • prebaviti: šestnajstiško kodiranje zgoščene vrednosti korenskega bloka (vključno s soljo glede na različico formata); tej vrednosti je treba zaupati.
  • solšestnajstiška sol.

Poleg tega obstajajo neobvezni parametri zelo uporabno za prilagajanje vedenja:

  • ignore_corruption: Zapiše poškodovane bloke, vendar omogoči nadaljnje branje.
  • ponovni_ponovni_zagon_ob_korupciji: ponovni zagon ob zaznavi poškodbe (ni združljivo z ignore_corruption in zahteva podporo uporabniškega prostora za preprečevanje zank).
  • panika_zaradi_korupcije: : povzroča paniko pri zaznavanju korupcije (ni združljivo s prejšnjimi različicami).
  • ponovni_ponovni_zagon ob_napaki y panika_ob_napaki: enake reakcije, vendar za napake V/I.
  • ignoriraj_nič_blokov: ne preverja blokov, ki so pričakovani kot ničle, in vrne ničle.
  • uporaba_iz_device + fec_roots + bloki_fec + fec_startOmogočite Reed-Solomonovemu (FEC) protokolu obnovitev podatkov, če preverjanje ne uspe; območja podatkov, zgoščene vrednosti in FEC se ne smejo prekrivati, velikosti blokov pa se morajo ujemati.
  • preveri_največ_enkratPreveri vsak blok podatkov samo ob prvem branju (zmanjša stroške na račun varnosti pri napadih v živo).
  • opis_ključa_podpisa_root_hash: Sklic na ključ v obesku ključev za preverjanje podpisa PKCS7 korenske zgoščene vrednosti pri ustvarjanju preslikave (zahteva ustrezno konfiguracijo jedra in zaupanja vredne obeske ključev).
  • try_verify_in_taskletČe so zgoščene vrednosti predpomnjene in velikost V/I to dopušča, preveri spodnjo polovico, da zmanjša zakasnitev; prilagojeno z /sys/module/dm_verity/parameters/use_bh_bytes na razred V/I.

Podpis, metapodatki in sidranje zaupanja

Da bi bil dm-verity zanesljiv, Korenski zgoščevalni vrednosti je treba zaupati in jo običajno podpisati.V klasičnem Androidu je javni ključ vključen v zagonsko particijo, ki jo zunanje preveri proizvajalec; ta potrdi korenski podpis zgoščene vrednosti in zagotovi, da sistemska particija ni bila spremenjena.

Metapodatki Verity dodajajo strukturo in nadzor različic. Blok metapodatkov vsebuje magično številko 0xb001b001 (bajti b0 01 b0 01), različica (trenutno 0), podpis tabele v PKCS1.5 (običajno 256 bajtov za RSA-2048), dolžina tabele, sama tabela in ničelno zapolnitev do 32K.

V izvedbah Androida je preverjanje odvisno od fs_mgr in fstabDodajanje kljukice ustreznemu vnosu in postavitev ključa v /boot/verity_key. Če magična številka ni tam, kjer bi morala biti, se preverjanje ustavi, da se prepreči preverjanje napačne stvari.

Začetek operacije potrjen

Zaščita je v jedru: Če je ogrožen pred zagonom jedra, napadalec ohrani nadzorZato proizvajalci običajno strogo preverijo vsako stopnjo: ključ, vpisan v napravo, preveri prvi zagonski nalagalnik, ki preveri naslednjega, zagonski nalagalnik aplikacije, in na koncu še jedro.

Z jedrom preverjenim, dm-verity je omogočen pri nameščanju preverjene blokovne naprave.Namesto zgoščevanja celotne naprave (kar bi bilo počasno in bi potratilo energijo), se preverja blok za blokom, ko se do nje dostopa. Napaka povzroči napako V/I, storitve in aplikacije pa se odzovejo glede na svojo toleranco: bodisi nadaljujejo brez teh podatkov bodisi se popolnoma sesujejo.

Popravljanje napak naprej (FEC)

Od Androida 7.0 dalje FEC (Reed-Solomon) je vključen v tehnike prepletanja za zmanjšanje prostora in povečanje možnosti obnovitve poškodovanih blokov. To deluje v povezavi z dm-verity: če preverjanje ne uspe, lahko podsistem poskusi popraviti napako, preden jo razglasi za nepopravljivo.

Zmogljivost in optimizacija

Za zmanjšanje vpliva: Omogoči pospeševanje SHA-2 s strani NEON v ARMv7 in razširitve SHA-2 v ARMv8 iz jedra. Prilagodite parametra branja vnaprej in prefetch_cluster za svojo strojno opremo; preverjanje na blok običajno le malo poveča stroške V/I, vendar te nastavitve bistveno vplivajo.

Uvod v Linux (systemd, veritysetup) in Android

Konfiguriranje dm-verity v Linuxu in Androidu

V sodobnem Linuxu s systemd, dm-verity omogoča preverjen korenski dostop samo za branje z uporabo veritysetup (del cryptsetup), systemd-veritysetup.generator in systemd-veritysetup@.service. Priporočljivo je vključiti Secure Boot in podpisano UKI (poenoteno sliko jedra), čeprav nista nujno potrebna.

Priprava in priporočena razdelitev

Del funkcionalnega in prilagojenega sistema. Rezervirajte prostornino za hash drevo (8–10 % velikosti korenskega direktorija je običajno dovolj) in razmislite o ločitvi /home in /var, če morate pisati. Tipična shema vključuje: ESP (za zagonski nalagalnik), XBOOTLDR (za UKI), root (z ali brez šifriranja), particijo VERITY in po izbiri /home in /var.

Kot korenina, EROFS je zelo zanimiva alternativa za ext4 ali squashfs.Zasnovan je samo za branje, z zelo dobrim delovanjem na bliskovnih/SSD-jih, privzeto uporablja stiskanje lz4 in se pogosto uporablja na telefonih Android z dm-verity.

Datoteke, ki morajo biti zapisljive

Pri root ro nekateri programi pričakujejo pisanje v /etc ali med initPremaknete ga lahko v /var/etc in vanj dodate simbolično povezavo, kar koli je treba spremeniti (npr. povezave NetworkManagerja v /etc/NetworkManager/system-connections). Upoštevajte, da systemd-journald zahteva, da /etc/machine-id obstaja v korenskem imeniku (ne simbolična povezava), da se prepreči prekinitev zgodnjih zagonov.

Če želite izvedeti, katere spremembe se zgodijo pri izvedbi, uporabite dracut-overlayroot: prekrije tmpfs čez korensko mapo in vse zapisano se prikaže v /run/overlayroot/u. Modul dodajte v /usr/lib/dracut/modules.d/, vključite overlayroot v dracut in v vrstici jedra nastavite overlayroot=1; tako boste videli, kaj morate migrirati v /var.

Uporabni primeri: pacman in NetworkManager

V Archu je priročno Premaknite bazo podatkov Pacman v /usr/lib/pacman tako da korenski imenik vedno zrcali nameščene pakete. Nato preusmerite predpomnilnik v /var/lib/pacman in ga povežite. Če želite spremeniti seznam zrcalnih datotek, ne da bi se dotaknili korenskega imenika, ga premaknite v /var/etc in ga vseeno povežite.

Z NetworkManagerjem, premaknite sistemske povezave v /var/etc/NetworkManager in povezavo iz /etc/NetworkManager/system-connections. To ohranja koren nespremenljiv in konfiguracijo shranjeno tam, kjer bi morala biti zapisljiva.

Konstrukcija resničnosti in testiranje

Iz živega in z vsem popolnim in nameščenim v ro, ustvarite drevo in roothash z format veritysetupKo se zažene, izpiše vrstico Root Hash, ki jo lahko shranite v datoteko roothash.txt. Za testiranje jo zaženite z ukazom veritysetup open root-device root verity-device $(cat roothash.txt) in mount /dev/mapper/root.

Če želite, najprej ustvari drevo v datoteko (verity.bin) in ga nato zapišite na particijo VERITY. Nastali niz je: korenska slika, drevo verity in korenska zgoščena vrednost, ki jo boste pripeli ob zagonu.

Konfigurirajte vrstico jedra

Dodajte te parametre: systemd.verity=1, roothash=contents_of_roothash.txt, systemd.verity_root_data=ROOT-PATH (npr. LABEL=OS) in systemd.verity_root_hash=VERITY-PATH (npr. LABEL=VERITY). Za stroge pravilnike nastavite systemd.verity_root_options na restart-on-corruption ali panic-on-corruption.

Druge priporočene možnosti: ro (če ne uporabljate EROFS/squashfs), rd.emergency=ponovni zagon y rd.shell=0 (preprečite nepooblaščene lupine, če zagon ne uspe) in zaklepanje = zaupnost za zaščito pomnilnika jedra pred dostopom.

Dodatne predelne stene z Verity

Ne samo korenina: Druge preslikave lahko definirate v /etc/veritytab in systemd-veritysetup@.service jih bo sestavil ob zagonu. Ne pozabite: lažje je RW priklopiti nekorensko particijo, root uporabnik pa lahko na teh particijah onemogoči Verity, zato je varnostna vrednost tam nižja.

Varnost: Secure Boot, UKI in podpisani moduli

dm-verity ni čarobna rešitev. Podpišite UKI in omogočite varen zagon s svojimi ključi da se prepreči, da bi kdo prepisal kernel/initramfs/cmdline (ki vključuje korensko zgoščeno vrednost). Orodja, kot sta sbupdate-git ali sbctl, pomagajo ohranjati podpisane slike in nedotaknjeno zagonsko verigo.

Če omogočite zaklepanje jedra ali preverjanje podpisa modulov, Moduli DKMS ali moduli zunaj drevesa morajo biti podpisani ali pa se ne bodo naložili. Razmislite o jedru po meri s podporo za podpisovanje za vaš cevovod (glejte podpisani moduli jedra).

Šifriranje, TPM in merjenje

dm-verity varuje integriteto, nezaupnostKorenski imenik lahko pustite nešifriran, če ne vsebuje nobenih skrivnosti in je zagonska veriga zaščitena. Če za odklepanje drugih nosilcev podatkov uporabljate ključne datoteke iz korenskega imenika, je dobro, da ga šifrirate.

S TPM 2.0, systemd-cryptenroll omogoča vezavo ključev na PCR 0, 1, 5, 7 (vdelana programska oprema, možnosti, GPT, stanje varnega zagona). Dodajte rd.luks.options=LUKS_UUID=tpm2-device=auto in v initramfs vključite podporo za TPM2. systemd-boot meri kernel.efi v PCR4, kar je uporabno za razveljavitev ključev, če se UKI ali njegova ukazna vrstica spremenita.

Posodobitve in modeli uvajanja

Preverjen korenski imenik samo za branje Ne posodablja se z upraviteljem paketov na tradicionalen način.Idealno je ustvariti nove slike z orodji, kot so projekt Yocto in jih objavite. Systemd ima systemd-sysupdate in systemd-repart za robustno nalaganje in programiranje slik.

Druga strategija je A/B shemaObdržite dva korena in dve verités. Kopirajte aktivni koren v neaktivni koren, uporabite spremembe in ponovite verités. Ob naslednjem zagonu preklopite nazaj. Če uporabljate UKI, ne pozabite posodobiti zgoščene vrednosti korena v vrstici cmd ali ponovno zgraditi podpisanega UKI.

Za neobvezno vztrajnost, uporabite OverlayFS na preverjenem korenu z zgornjim v tmpfs ali disku. Za začasno ohranitev lahko posredujete tudi systemd.volatile=overlay. Flatpak olajša namestitev aplikacij v /var in /home brez dotikanja /.

Obstajajo avtomatizirani paketi (npr. verity-squash-root v AUR), ki gradijo korenski imenik squashfs in podpišite korensko zgoščeno datoteko z jedrom in initramfs, kar vam omogoča izbiro med trajnim ali začasnim načinom in ohranjanje najnovejših korenskih datotek kot varnostne kopije. Opomba: dodajanje trajnosti preverjeni korenski datoteki ima ozke primere uporabe; poskusite shraniti podatke aplikacij na ločenih particijah.

Android: sistem kot koren, AVB in prekrivni elementi prodajalcev

Od Androida 10 dalje RootFS preneha delovati na RAM disku in se integrira s system.img. (system-as-root). Naprave, ki se zaženejo z Androidom 10, vedno uporabljajo to shemo in za dm-linear potrebujejo ramdisk. BOARD_BUILD_SYSTEM_ROOT_IMAGE je v tej gradnji nastavljen na false, da se razlikuje med uporabo ramdiska in neposredno aktivacijo system.img.

Vključuje Android 10 dinamične particije in inicializacija prve stopnje ki aktivira logično sistemsko particijo; jedro je ne priklopi več neposredno. OTA-ji, ki so namenjeni samo sistemu, zahtevajo zasnovo »sistem kot koren«, kar je obvezno v napravah Android 10.

V nobenem A/B, ločite obnovitev od zagonaZa razliko od A/B ni varnostne kopije boot_a/boot_b, zato lahko odstranitev obnovitve v ne-A/B pusti način za obnovitev, če posodobitev zagona ne uspe.

Jedro priklopi datoteko system.img v /converity prek dveh poti: vboot 1.0 (popravki za jedro za razčlenjevanje metapodatkov Androida v /system in izpeljavo parametrov dm-verity; ukazna vrstica vključuje root=/dev/dm-0, skip_initramfs in init=/init z dm=…) ali vboot 2.0/AVB, kjer zagonski nalagalnik integrira libavb, prebere deskriptor hashtree (v vbmeta ali system), sestavi parametre in jih posreduje jedru v ukazni vrstici, s podporo za FEC in zastavicami, kot je restart_on_corruption.

S sistemom kot korenom, Ne uporabljajte BOARD_ROOT_EXTRA_FOLDERS za korenske mape, specifične za napravo: te bodo izginile pri bliskovni namestitvi GSI. Določite specifične priklope v /mnt/vendor/ , ki jih fs_mgr ustvari samodejno, in se nanje sklicujejo v datoteki fstab drevesa naprav.

Android omogoča prekrivanje prodajalca iz /product/vendor_overlay/: init bo v /vendor namestil poddirektorije, ki ustrezajo zahtevam konteksta SELinux in obstoju /vendor/ Zahteva CONFIG_OVERLAY_FS=yy, na starejših jedrih pa popravek override_creds=off.

Tipična izvedba: namesti predkompilirane datoteke v napravo/ / /prekrivanje_prevzemnika/, jih dodajte v PRODUCT_COPY_FILES z ukazom find-copy-subdir-files v $(TARGET_COPY_OUT_PRODUCT)/vendor_overlay, definirajte kontekste v file_contexts za etc in app (npr. vendor_configs_file in vendor_app_file) in dovolite mounton na teh kontekstih v init.te. Preizkusite z atest vfs_mgr_vendor_overlay_test v userdebug.

Odpravljanje težav: sporočilo o poškodbi dm-verity v sistemu Android

Na napravah z režami A/B zamenjajte reže ali Utripanje vbmeta/boot brez doslednosti roothash-a To lahko sproži opozorilo: dm-verity corruption, your device is undelful. Ukazi, kot je fastboot flash –disable-verity –disable-verification vbmeta vbmeta.img, onemogočijo preverjanje, vendar sistem pustijo brez kakršnih koli zagotovil za integriteto.

Nekateri zagonski nalagalniki podpirajo fastboot oem disable_dm_verity in njegovo nasprotje, enable_dm_verity. Deluje na nekaterih modelih, na drugih pa ne; in morda zahteva kernel/magisk s prilagojenimi zastavicami. Uporabljate ga na lastno odgovornost: preudaren potek dejanja je poravnaj zagon, vbmeta in sistem, podpišite ali regenerirajte drevo in zagotovite, da se pričakovana zgoščena vrednost korena ujema s konfigurirano.

Če po opozorilu lahko še naprej pritiskate gumb za vklop, se sistem zažene, vendar nimate več nedotaknjene verige zaupanjaČe želite sporočilo odstraniti, ne da bi pri tem žrtvovali varnost, obnovite originalne podpisane slike ali ponovno zgradite/preverite vbmeta s pravilnim hashtree-om, namesto da onemogočite verity.

Platformi i.MX in OpenWrt

Na i.MX6 (npr. sabresd), konfigurirajte jedro s podporo za DM_VERITY in FEC, ustvarite drevo z veritysetup, varno shranite korensko zgoščeno vrednost in v ukazno vrstico posredujte ustrezne parametre ali integrirajte prek initramfs s systemd-veritysetup. Če ne uporabljate dm-crypt, za verity ne potrebujete CAAM; poudarek je na integriteti.

V OpenWrtu in v vgrajeni sistemi Linux z OpenEmbedded, Obstajajo prizadevanja za integracijo dm-verity in SELinuxa (Opravila Bootlin so bila spremenjena z namenom vključitve podpore). To je naravno ujemanje: usmerjevalniki in omrežna oprema imajo koristi od nespremenljivega, preverjenega in MAC-trdega korena.

Ročna izdelava drevesa in metapodatkov (podroben pogled)

cryptsetup lahko ustvari drevo namesto vas, če pa raje razumete format, definicija vrstice kompaktne tabele vključuje: ime preslikave, podatkovna naprava, velikosti podatkovnih blokov in zgoščevalne vrednosti, velikost slike v blokih, začetna vrednost hash_start (slika bloka + 8, če je združena), zgoščena vrednost korena in sol. Po generiranju združenih plasti (od zgoraj navzdol, razen plasti 0) drevo zapišete na disk.

Da vse spakiram, sestavi tabelo dm-verity, jo podpiši (tipično RSA-2048) in združi tabelo podpisov+v metapodatkih z različicirano glavo in magičnim številom. Nato združi sistemsko sliko, metapodatke verity in zgoščevalno drevo. V datoteki fstab označi fs_mgr kot verify in namesti javni ključ v /boot/verity_key za preverjanje podpisa.

Optimiziraj z SHA-2 pospeški za vaš procesor in prilagodite branje vnaprej/prefetch_cluster. Na strojni opremi ARM razširitve NEON SHA-2 (ARMv7) in SHA-2 (ARMv8) znatno zmanjšajo stroške preverjanja.

Pri vsaki uvedbi ne pozabite, da korenska zgoščena vrednost mora biti zaščitena: ne glede na to, ali je preveden v podpisan UKI, v podpisano zagonsko particijo ali potrjen s strani zagonskega nalagalnika z uporabo AVB. Vse po tej točki podeduje to zaupanje.

Z vsem zgoraj navedenim postane dm-verity trdna podlaga za nespremenljive, mobilne in vgrajene sisteme, ki podpira transakcijske posodobitve, konfiguracijske prekrivne sloje in sodoben varnostni model, ki zmanjšuje površino napadov in preprečuje vztrajnost, ne da bi pri tem žrtvoval zmogljivost.

Kaj je projekt Yocto?
Povezani članek:
Kaj je projekt Yocto: Popoln vodnik za vgrajene sisteme