
หากคุณกังวลเกี่ยวกับความสมบูรณ์ของระบบของคุณ dm-verity เป็นหนึ่งในส่วนสำคัญของระบบนิเวศ Linux เพื่อบูตอย่างปลอดภัยและตรวจจับการบุกรุกที่เก็บข้อมูล เดิมทีเป็นส่วนหนึ่งของตัวแมปอุปกรณ์ของเคอร์เนล และปัจจุบันเป็นพื้นฐานสำหรับการบูตที่ได้รับการยืนยันใน Android, OpenWrt และดิสทริบิวชันที่ต้องการความปลอดภัยขั้นสูง
ห่างไกลจากการเป็นแนวคิดที่เป็นนามธรรม dm-verity ได้รับการกำหนดค่าและใช้งานด้วยเครื่องมือจริงเช่น veritysetup และ systemd-veritysetupระบบจะตรวจสอบความถูกต้องของบล็อกแบบ on-the-fly โดยใช้แฮชทรี และสามารถตอบสนองต่อการทุจริตได้ด้วยนโยบายต่างๆ ตั้งแต่การบันทึกเหตุการณ์ไปจนถึงการรีบูตหรือการทำให้ระบบล่ม ลองพิจารณาให้ละเอียดขึ้นโดยไม่ปล่อยให้มีข้อผิดพลาดเกิดขึ้น
dm-verity คืออะไร และทำไมคุณถึงต้องสนใจ
dm-verity เป็นเป้าหมายตัวแมปอุปกรณ์ในเคอร์เนลที่ ตรวจสอบความสมบูรณ์ของอุปกรณ์บล็อกขณะอ่านข้อมูลทำงานโดยการคำนวณและตรวจสอบค่าแฮชของแต่ละบล็อก (ปกติคือ 4K) เทียบกับแฮชทรีที่คำนวณไว้ล่วงหน้า โดยทั่วไปจะใช้ SHA-256
การออกแบบนี้ช่วยให้ ไม่สามารถแก้ไขไฟล์อย่างเงียบ ๆ ระหว่างการรีบูตหรือในระหว่างการดำเนินการถือเป็นกุญแจสำคัญในการขยายห่วงโซ่การบูตของความไว้วางใจไปยังระบบปฏิบัติการ จำกัดการคงอยู่ของมัลแวร์ เสริมความแข็งแกร่งให้กับนโยบายความปลอดภัย และรับรองการเข้ารหัสและกลไก MAC ในระหว่างการบูต
บน Android (ตั้งแต่ 4.4) และ Linux โดยทั่วไป ความไว้วางใจถูกยึดโยงกับรากแฮชของต้นไม้ซึ่งลงนามและตรวจสอบความถูกต้องด้วยคีย์สาธารณะที่อยู่ในตำแหน่งที่ได้รับการป้องกัน (เช่น บนพาร์ติชันการบูต หรือใน UKI ที่ลงนาม Secure Boot) การทำลายบล็อกใดๆ จะต้องทำลายแฮชการเข้ารหัสลับพื้นฐานเสียก่อน
การตรวจสอบจะทำโดยบล็อคและตามความต้องการ: ความหน่วงที่เพิ่มขึ้นนั้นน้อยมากเมื่อเทียบกับต้นทุน I/Oหากการตรวจสอบล้มเหลว เคอร์เนลจะส่งข้อผิดพลาด I/O กลับมาและระบบไฟล์จะเสียหาย ซึ่งเป็นเรื่องปกติเมื่อข้อมูลไม่น่าเชื่อถือ แอปสามารถตัดสินใจได้ว่าจะดำเนินการต่อไปหรือไม่โดยพิจารณาจากความทนทานต่อความผิดพลาด
ต้นไม้การตรวจสอบทำงานภายในอย่างไร
ต้นไม้การตรวจสอบถูกสร้างขึ้นเป็นชั้นๆ เลเยอร์ 0 คือข้อมูลดิบจากอุปกรณ์ แบ่งเป็นบล็อกขนาด 4Kแฮช SHA-256 (salted) จะถูกคำนวณสำหรับแต่ละบล็อก จากนั้นแฮชเหล่านี้จะถูกต่อกันเพื่อสร้างเลเยอร์ 1 จากนั้นเลเยอร์ 1 จะถูกจัดกลุ่มเป็นบล็อกและถูกแฮชซ้ำเพื่อสร้างเลเยอร์ 2 และทำเช่นนี้ต่อไปจนกระทั่งทุกอย่างเข้ากันเป็นบล็อกเดียว เมื่อบล็อกนั้นถูกแฮชแล้ว จะสร้างแฮชราก
หากชั้นใดชั้นหนึ่งไม่เสร็จสมบูรณ์พอดี เติมศูนย์จนไปถึง 4K เพื่อหลีกเลี่ยงความคลุมเครือ ขนาดรวมของทรีขึ้นอยู่กับขนาดของพาร์ติชันที่กำลังตรวจสอบ ในทางปฏิบัติ พาร์ติชันระบบทั่วไปมักจะมีขนาดน้อยกว่า 30 MB
กระบวนการทั่วไปคือ: เลือกเกลือแบบสุ่ม แฮชเป็น 4K คำนวณ SHA-256 ด้วยเกลือต่อบล็อก, ต่อกันเพื่อสร้างระดับ เติมศูนย์บนขอบบล็อก และทำซ้ำกับระดับก่อนหน้าจนกว่าจะเหลือแฮชรูทเพียงตัวเดียว แฮชรูทนั้น พร้อมกับเกลือที่ใช้ จะป้อนเข้าสู่ตาราง dm-verity และลายเซ็น
เวอร์ชันและอัลกอริทึมของรูปแบบดิสก์
ฟอร์แมตของบล็อกแฮชบนดิสก์มีเวอร์ชัน เวอร์ชัน 0 เป็นเวอร์ชันดั้งเดิมที่ใช้ใน Chromium OS:เกลือจะถูกเติมในตอนท้ายของกระบวนการแฮช ข้อมูลย่อยจะถูกเก็บไว้อย่างต่อเนื่อง และส่วนที่เหลือของบล็อกจะถูกเติมด้วยศูนย์
La ขอแนะนำเวอร์ชัน 1 สำหรับอุปกรณ์ใหม่:เกลือจะถูกเพิ่มเข้าไปในแฮช และไดเจสต์แต่ละรายการจะถูกเติมด้วยเลขศูนย์จนถึงเลขยกกำลังสอง ซึ่งช่วยปรับปรุงการจัดตำแหน่งและความทนทาน ตาราง dm-verity ยังระบุอัลกอริทึม (เช่น sha1 หรือ sha256) อีกด้วย แม้ว่าเพื่อความปลอดภัยในปัจจุบันจะใช้ sha256 ก็ตาม
ตาราง dm-verity และพารามิเตอร์ที่จำเป็น
ตารางเป้าหมาย dm-verity อธิบาย ข้อมูลอยู่ที่ไหน แฮชทรีอยู่ที่ไหน และจะตรวจสอบได้อย่างไรฟิลด์ตารางทั่วไป:
- dev:อุปกรณ์ที่มีข้อมูลที่ต้องตรวจสอบ (ประเภทเส้นทาง /dev/sdXN หรือ มากกว่า:น้อยกว่า)
- แฮชเดฟ: อุปกรณ์ที่มีแฮชทรี (สามารถเป็นอันเดียวกันได้ ถ้าเป็นเช่นนั้น hash_start จะต้องอยู่นอกช่วงที่ทำเครื่องหมายไว้)
- ขนาดบล็อกข้อมูล: ขนาดบล็อกข้อมูลเป็นไบต์ (เช่น 4096)
- ขนาดบล็อกแฮช: ขนาดบล็อกแฮชเป็นไบต์
- บล็อกข้อมูลจำนวน: จำนวนบล็อกข้อมูลที่สามารถตรวจสอบได้
- แฮช_สตาร์ท_บล็อก: ออฟเซ็ต (ในบล็อก hash_block_size) ไปยังบล็อกรูทของต้นไม้
- ขั้นตอนวิธี:อัลกอริทึมแฮช (เช่น sha256)
- ย่อยอาหาร:การเข้ารหัสเลขฐานสิบหกของแฮชบล็อกรูท (รวมถึงเกลือตามเวอร์ชันรูปแบบ) ค่านี้จะต้องเชื่อถือได้
- เกลือ: เกลือเลขฐานสิบหก
นอกจากนี้แล้วยังมี พารามิเตอร์เสริม มีประโยชน์มากในการปรับพฤติกรรม:
- ละเลยการทุจริต:บันทึกบล็อคที่เสียหาย แต่สามารถอ่านต่อไปได้
- เริ่มใหม่เมื่อเสียหาย: เริ่มการตรวจจับการทุจริตใหม่อีกครั้ง (ไม่เข้ากันได้กับ ignore_corruption และต้องมีการรองรับพื้นที่ผู้ใช้เพื่อหลีกเลี่ยงการวนซ้ำ)
- ตื่นตระหนกเรื่องการทุจริต: : ทำให้เกิดอาการตื่นตระหนกเมื่อตรวจพบการทุจริต (ไม่เข้ากันได้กับเวอร์ชันก่อนหน้า)
- รีสตาร์ท_on_error y ตกใจเมื่อเกิดข้อผิดพลาด: ปฏิกิริยาแบบเดียวกันแต่สำหรับข้อผิดพลาด I/O
- ละเว้นบล็อกศูนย์: ไม่ตรวจสอบบล็อกที่คาดว่าจะเป็นศูนย์และส่งคืนค่าศูนย์
- ใช้_fec_จากอุปกรณ์ + รากเฟค + บล็อกเฟค + เริ่มต้น fec:เปิดใช้งาน Reed–Solomon (FEC) เพื่อกู้คืนข้อมูลเมื่อการตรวจสอบล้มเหลว ข้อมูล แฮช และพื้นที่ FEC จะต้องไม่ทับซ้อนกัน และขนาดบล็อกจะต้องตรงกัน
- ตรวจสอบเกือบครั้งเดียว:ตรวจสอบแต่ละบล็อกของข้อมูลเฉพาะครั้งแรกที่อ่านเท่านั้น (ลดค่าใช้จ่ายในการรักษาความปลอดภัยในการโจมตีแบบสด)
- รากแฮชซิกคีย์คำอธิบาย:การอ้างอิงถึงคีย์ในพวงกุญแจเพื่อตรวจสอบลายเซ็น PKCS7 ของแฮชรูทเมื่อสร้างการแมป (ต้องมีการกำหนดค่าเคอร์เนลที่เหมาะสมและพวงกุญแจที่เชื่อถือได้)
- ลองตรวจสอบในงาน:หากแฮชถูกแคชและขนาด I/O อนุญาต ให้ตรวจสอบครึ่งล่างเพื่อลดเวลาแฝง ปรับด้วย /sys/module/dm_verity/parameters/use_bh_bytes ต่อคลาส I/O
ลายเซ็น เมตาดาต้า และการยึดโยงความน่าเชื่อถือ
เพื่อให้ dm-verity เชื่อถือได้ แฮชรูทจะต้องเชื่อถือได้และมักจะลงนามในระบบปฏิบัติการ Android แบบคลาสสิก คีย์สาธารณะจะรวมอยู่ในพาร์ติชันการบูต ซึ่งได้รับการตรวจสอบจากภายนอกโดยผู้ผลิต ซึ่งจะตรวจสอบลายเซ็นแฮชรูทและรับรองว่าพาร์ติชันระบบไม่ได้ถูกเปลี่ยนแปลง
เมตาดาต้าของ Verity เพิ่มโครงสร้างและการควบคุมเวอร์ชัน บล็อกเมตาข้อมูลประกอบด้วยหมายเลขวิเศษ 0xb001b001 (ไบต์ b0 01 b0 01) เวอร์ชัน (ปัจจุบัน 0) ลายเซ็นตารางใน PKCS1.5 (โดยทั่วไปคือ 256 ไบต์สำหรับ RSA-2048) ความยาวตาราง ตารางนั้นเอง และการเติมศูนย์สูงสุด 32K
ในการใช้งาน Android การตรวจสอบจะขึ้นอยู่กับ fs_mgr และ fstab: เพิ่มเครื่องหมายถูกลงในรายการที่เกี่ยวข้องและวางคีย์ลงใน /boot/verity_key หากหมายเลขวิเศษไม่อยู่ในตำแหน่งที่ควรอยู่ การตรวจสอบจะหยุดลงเพื่อหลีกเลี่ยงการตรวจสอบที่ไม่ถูกต้อง
เริ่มดำเนินการตรวจสอบแล้ว
การป้องกันอยู่ในเคอร์เนล: หากถูกบุกรุกก่อนที่เคอร์เนลจะบูต ผู้โจมตีจะยังคงควบคุมได้นั่นเป็นสาเหตุที่ผู้ผลิตมักจะตรวจสอบแต่ละขั้นตอนอย่างเคร่งครัด: คีย์ที่เขียนไว้ในอุปกรณ์จะตรวจสอบบูตโหลดเดอร์ตัวแรก ซึ่งจะตรวจสอบบูตโหลดเดอร์ตัวถัดไปของแอป และสุดท้ายคือเคอร์เนล
เมื่อตรวจสอบเคอร์เนลแล้ว dm-verity เปิดใช้งานเมื่อติดตั้งอุปกรณ์บล็อกที่ตรวจสอบแล้วแทนที่จะแฮชอุปกรณ์ทั้งหมด (ซึ่งจะช้าและสิ้นเปลืองพลังงาน) ระบบจะตรวจสอบทีละบล็อกเมื่อเข้าถึง ความล้มเหลวจะทำให้เกิดข้อผิดพลาด I/O และบริการและแอปจะตอบสนองตามค่าความคลาดเคลื่อน ซึ่งอาจดำเนินการต่อโดยไม่มีข้อมูลนั้น หรือหยุดทำงานโดยสมบูรณ์
การแก้ไขข้อผิดพลาดล่วงหน้า (FEC)
ตั้งแต่ Android 7.0 FEC (Reed–Solomon) ผสมผสานกับเทคนิคการสาน เพื่อลดพื้นที่และเพิ่มความสามารถในการกู้คืนบล็อกที่เสียหาย วิธีนี้ทำงานร่วมกับ dm-verity: หากการตรวจสอบล้มเหลว ระบบย่อยจะพยายามแก้ไขก่อนที่จะประกาศว่าไม่สามารถกู้คืนได้
ประสิทธิภาพและการเพิ่มประสิทธิภาพ
เพื่อลดผลกระทบ: เปิดใช้งานการเร่งความเร็ว SHA-2 โดย NEON บน ARMv7 และส่วนขยาย SHA-2 บน ARMv8 จากเคอร์เนล ปรับพารามิเตอร์ read-ahead และ prefetch_cluster สำหรับฮาร์ดแวร์ของคุณ โดยทั่วไปแล้ว การตรวจสอบแต่ละบล็อกจะเพิ่มต้นทุน I/O เพียงเล็กน้อย แต่การตั้งค่าเหล่านี้สร้างความแตกต่าง
เริ่มต้นใช้งานบน Linux (systemd, veritysetup) และ Android
บน Linux สมัยใหม่ที่มี systemd dm-verity อนุญาตให้มีการตรวจสอบรูทแบบอ่านอย่างเดียว โดยใช้ veritysetup (ส่วนหนึ่งของ cryptsetup), systemd-veritysetup.generator และ systemd-veritysetup@.service ขอแนะนำให้รวม Secure Boot และ UKI (unified kernel image) ไว้ด้วย แม้ว่าจะไม่ได้บังคับอย่างเคร่งครัดก็ตาม
การเตรียมตัวและการแบ่งพาร์ติชั่นที่แนะนำ
ส่วนหนึ่งของระบบการทำงานและการปรับแต่ง สำรองปริมาณสำหรับแฮชทรี (โดยปกติแล้ว 8-10% ของขนาดรูทก็เพียงพอแล้ว) และพิจารณาแยก /home และ /var ออกจากกันหากต้องการเขียน รูปแบบทั่วไปประกอบด้วย: ESP (สำหรับบูตโหลดเดอร์), XBOOTLDR (สำหรับ UKIs), รูท (มีหรือไม่มีการเข้ารหัส), พาร์ติชัน VERITY และ /home และ /var (ไม่บังคับ)
เป็นรากเหง้า EROFS เป็นทางเลือกที่น่าสนใจมากสำหรับ ext4 หรือ squashfs:ได้รับการออกแบบมาให้อ่านอย่างเดียว มีประสิทธิภาพดีมากบนแฟลช/SSD บีบอัด lz4 ตามค่าเริ่มต้น และใช้กันอย่างแพร่หลายบนโทรศัพท์ Android ที่มี dm-verity
ไฟล์ที่ต้องสามารถเขียนได้
ด้วย root ro โปรแกรมบางตัวคาดหวังว่าจะเขียนถึง /etc หรือระหว่าง initคุณสามารถย้ายไฟล์ไปที่ /var/etc และลิงก์สัญลักษณ์ (symlink) อะไรก็ได้ที่ต้องการเปลี่ยนแปลง (เช่น การเชื่อมต่อ NetworkManager ใน /etc/NetworkManager/system-connections) โปรดทราบว่า systemd-journald จำเป็นต้องมี /etc/machine-id อยู่ในไดเร็กทอรีรูท (ไม่ใช่ลิงก์สัญลักษณ์) เพื่อป้องกันไม่ให้ไฟล์เริ่มต้นทำงานผิดพลาดในช่วงแรก
เพื่อดูว่ามีการเปลี่ยนแปลงอะไรบ้างในการดำเนินการ ใช้ dracut-overlayroot: ซ้อนทับ tmpfs ลงบนรูท และทุกสิ่งที่เขียนจะปรากฏใน /run/overlayroot/u เพิ่มโมดูลลงใน /usr/lib/dracut/modules.d/ รวม overlayroot ไว้ใน dracut และตั้งค่า overlayroot=1 ในบรรทัดเคอร์เนล วิธีนี้จะช่วยให้คุณเห็นสิ่งที่ต้องย้ายไปยัง /var
ตัวอย่างที่เป็นประโยชน์: pacman และ NetworkManager
ในอาร์ชก็สะดวก ย้ายฐานข้อมูล Pacman ไปที่ /usr/lib/pacman เพื่อให้ rootfs ทำการมิเรอร์แพ็กเกจที่ติดตั้งไว้เสมอ จากนั้นเปลี่ยนเส้นทางแคชไปที่ /var/lib/pacman แล้วลิงก์ หากต้องการเปลี่ยนรายการมิเรอร์โดยไม่กระทบกับ root ให้ย้ายไปยัง /var/etc แล้วลิงก์ไป
ด้วย NetworkManager ย้ายการเชื่อมต่อระบบไปที่ /var/etc/NetworkManager และลิงก์จาก /etc/NetworkManager/system-connections วิธีนี้จะทำให้ root ไม่สามารถเปลี่ยนแปลงได้ และคอนฟิกูเรชันจะยังคงทำงานอยู่ ณ ตำแหน่งที่ควรจะสามารถเขียนได้
การสร้างความจริงและการทดสอบ
จากชีวิตและด้วยทุกอย่างสมบูรณ์แบบและติดตั้งใน ro สร้างต้นไม้และ roothash ด้วย รูปแบบ veritysetup: เมื่อรัน มันจะพิมพ์บรรทัด Root Hash ซึ่งคุณสามารถบันทึกลงใน roothash.txt ได้ รันเพื่อทดสอบด้วย veritysetup เปิด root-device root verity-device $(cat roothash.txt) และ mount /dev/mapper/root
หากคุณต้องการ สร้างต้นไม้เป็นไฟล์ก่อน (verity.bin) แล้วเขียนลงในพาร์ติชัน VERITY ชุดผลลัพธ์คือ: อิมเมจรูท, ทรีของ Verity และแฮชรูทที่คุณจะปักหมุดตอนบูต
กำหนดค่าบรรทัดเคอร์เนล
เพิ่มพารามิเตอร์เหล่านี้: systemd.verity=1, roothash=contents_of_roothash.txt, systemd.verity_root_data=ROOT-PATH (เช่น LABEL=OS) และ systemd.verity_root_hash=VERITY-PATH (เช่น LABEL=VERITY) ตั้งค่า systemd.verity_root_options เป็น restart-on-corruption หรือ panic-on-corruption สำหรับนโยบายที่เข้มงวด
ตัวเลือกอื่นที่แนะนำ: ro (หากคุณไม่ได้ใช้ EROFS/squashfs) rd.ฉุกเฉิน=รีบูต y rd.shell=0 (ป้องกันเชลล์ที่ไม่ได้รับอนุญาตหากการบูตล้มเหลว) และ การล็อคดาวน์ = ความลับ เพื่อป้องกันหน่วยความจำเคอร์เนลจากการเข้าถึง
พาร์ติชั่นเสริมด้วยความจริง
ไม่ใช่แค่รากเท่านั้น: คุณสามารถกำหนดการแมปอื่นๆ ได้ใน /etc/veritytab และ systemd-veritysetup@.service จะประกอบมันตอนบูต จำไว้ว่า: การเมาท์ RW พาร์ติชันที่ไม่ใช่ root จะง่ายกว่า และผู้ใช้ root สามารถปิดใช้งาน Verity บนพาร์ติชันเหล่านั้นได้ ดังนั้นค่าความปลอดภัยที่นั่นจึงต่ำกว่า
ความปลอดภัย: Secure Boot, UKI และโมดูลที่ลงนาม
dm-verity ไม่ใช่ยาครอบจักรวาล ลงนามใน UKI และเปิดใช้งาน Secure Boot ด้วยคีย์ของคุณเอง เพื่อป้องกันไม่ให้ใครก็ตามเขียนทับ kernel/initramfs/cmdline (ซึ่งรวมถึง root hash) เครื่องมืออย่าง sbupdate-git หรือ sbctl ช่วยรักษาลายเซ็นอิมเมจและเชนการบูตให้สมบูรณ์
หากคุณเปิดใช้งานการล็อกเคอร์เนลหรือการตรวจสอบลายเซ็นโมดูล DKMS หรือโมดูลนอกต้นไม้ต้องได้รับการลงนาม ไม่เช่นนั้นระบบจะไม่โหลด ลองพิจารณาเคอร์เนลแบบกำหนดเองที่รองรับการลงนามสำหรับไปป์ไลน์ของคุณ (ดูโมดูลเคอร์เนลที่มีลายเซ็น)
การเข้ารหัส TPM และการวัดผล
dm-verity ปกป้องความสมบูรณ์ การไม่เป็นความลับคุณสามารถปล่อยให้ root ไม่ถูกเข้ารหัสได้หากไม่มีข้อมูลลับใดๆ และ boot chain ได้รับการปกป้อง หากคุณใช้ไฟล์คีย์จาก root เพื่อปลดล็อกโวลุ่มอื่นๆ การเข้ารหัสก็เป็นความคิดที่ดี
ด้วย TPM 2.0 systemd-cryptenroll อนุญาตให้ผูกคีย์กับ PCR 0,1,5,7 (เฟิร์มแวร์, ตัวเลือก, GPT, สถานะการบูตแบบปลอดภัย) เพิ่ม rd.luks.options=LUKS_UUID=tpm2-device=auto และตรวจสอบให้แน่ใจว่าได้รวมการรองรับ TPM2 ไว้ใน initramfs แล้ว systemd-boot จะวัด kernel.efi ใน PCR4 ซึ่งมีประโยชน์สำหรับการตรวจสอบความถูกต้องของคีย์หาก UKI หรือ cmdline มีการเปลี่ยนแปลง
รูปแบบการอัปเดตและการปรับใช้งาน
รูทอ่านอย่างเดียวที่ผ่านการตรวจสอบแล้ว ไม่ได้รับการอัปเดตด้วยตัวจัดการแพ็คเกจในรูปแบบดั้งเดิมอุดมคติคือการสร้างภาพใหม่ด้วยเครื่องมือเช่น โครงการ Yocto และเผยแพร่ systemd มี systemd-sysupdate และ systemd-repart สำหรับการดาวน์โหลดและแฟลชอิมเมจที่มีประสิทธิภาพ
อีกกลยุทธ์หนึ่งคือ แผน A/B:คุณเก็บรากไว้สองรากและเวอร์ริตีสองอัน คัดลอกรูทที่ใช้งานอยู่ไปยังรูทที่ไม่ได้ใช้งาน นำการเปลี่ยนแปลงไปใช้ และทำซ้ำเวอร์ริตี สลับกลับมาในการบูตครั้งถัดไป หากคุณใช้ UKI อย่าลืมอัปเดตแฮชรูทในบรรทัด cmd หรือสร้าง UKI ที่ลงชื่อแล้วใหม่
สำหรับการคงอยู่ตามทางเลือก ใช้ OverlayFS บนรูทที่ได้รับการยืนยัน ด้วยไฟล์ส่วนบนใน tmpfs หรือดิสก์ คุณยังสามารถส่ง systemd.volatile=overlay เพื่อการคงอยู่ชั่วคราวได้อีกด้วย Flatpak ช่วยให้ติดตั้งแอปใน /var และ /home ได้อย่างง่ายดายโดยไม่ต้องแตะ /
มีแพ็คเกจอัตโนมัติ (เช่น verity-squash-root ใน AUR) ที่สร้างรูท squashfs และ ลงนาม roothash ด้วยเคอร์เนลและ initramfsช่วยให้คุณเลือกระหว่างโหมด Persistent หรือ Ephemeral และเก็บรักษา rootfs ล่าสุดไว้เป็นข้อมูลสำรอง หมายเหตุ: การเพิ่ม Persistence ให้กับ root ที่ตรวจสอบแล้วมีกรณีการใช้งานที่จำกัด ลองเก็บข้อมูลแอปไว้ในพาร์ติชันแยกต่างหาก
Android: ระบบเป็นรูท, AVB และโอเวอร์เลย์ของผู้ขาย
ตั้งแต่ Android 10 RootFS หยุดการทำงานบนดิสก์ RAM และรวมเข้ากับ system.img (system-as-root) อุปกรณ์ที่เปิดใช้งานด้วย Android 10 จะใช้รูปแบบนี้เสมอและต้องใช้ ramdisk สำหรับ dm-linear BOARD_BUILD_SYSTEM_ROOT_IMAGE ถูกตั้งค่าเป็น false ในบิลด์นี้เพื่อแยกความแตกต่างระหว่างการใช้ ramdisk และการเปิดใช้งาน system.img โดยตรง
Android 10 รวม พาร์ติชันแบบไดนามิกและ init ขั้นแรก ซึ่งจะเปิดใช้งานพาร์ติชันระบบลอจิคัล เคอร์เนลจะไม่เมาท์พาร์ติชันระบบโดยตรงอีกต่อไป OTA เฉพาะระบบจำเป็นต้องใช้การออกแบบระบบในฐานะรูท ซึ่งเป็นข้อบังคับสำหรับอุปกรณ์ Android 10
ไม่มี A/B แยกการกู้คืนออกจากการบูตไม่เหมือนกับ A/B ไม่มีการสำรองข้อมูล boot_a/boot_b ดังนั้นการลบการกู้คืนในระบบที่ไม่ใช่ A/B จะทำให้คุณไม่มีโหมดการกู้คืนหากการอัปเดตการบูตล้มเหลว
เคอร์เนลจะเมาท์ system.img ไปที่ /converity ผ่านสองเส้นทาง: วีบูต 1.0 (แพตช์สำหรับเคอร์เนลเพื่อวิเคราะห์ข้อมูลเมตาของ Android ใน /system และรับพารามิเตอร์ dm-verity; cmdline ประกอบด้วย root=/dev/dm-0, skip_initramfs และ init=/init โดยที่ dm=…) หรือ วีบูต 2.0/เอวีบีโดยที่ bootloader จะรวม libavb อ่านตัวระบุแฮชทรี (ใน vbmeta หรือระบบ) สร้างพารามิเตอร์และส่งไปยังเคอร์เนลใน cmdline พร้อมด้วยการรองรับ FEC และแฟล็กเช่น restart_on_corruption
ด้วยระบบเป็นรูท อย่าใช้ BOARD_ROOT_EXTRA_FOLDERS สำหรับโฟลเดอร์รูทเฉพาะอุปกรณ์: โฟลเดอร์เหล่านี้จะหายไปเมื่อแฟลช GSI กำหนดการติดตั้งเฉพาะภายใต้ /mnt/vendor/ ซึ่ง fs_mgr สร้างขึ้นโดยอัตโนมัติ และอ้างอิงถึง fstab ของโครงสร้างอุปกรณ์
Android อนุญาตให้ โอเวอร์เลย์ของผู้ขายจาก /product/vendor_overlay/: init จะติดตั้งไดเร็กทอรีย่อยใน /vendor ซึ่งตรงตามข้อกำหนดบริบทของ SELinux และการมีอยู่ของ /vendor/ ต้องใช้ CONFIG_OVERLAY_FS=yy บนเคอร์เนลรุ่นเก่า แพตช์ override_creds=off
การใช้งานทั่วไป: ติดตั้งไฟล์ที่คอมไพล์ไว้ล่วงหน้าในอุปกรณ์/ - /การซ้อนทับของผู้ขาย/เพิ่มไฟล์เหล่านี้ลงใน PRODUCT_COPY_FILES โดยใช้ find-copy-subdir-files ไปที่ $(TARGET_COPY_OUT_PRODUCT)/vendor_overlay กำหนดบริบทใน file_contexts สำหรับ etc และ app (เช่น vendor_configs_file และ vendor_app_file) และอนุญาตให้ mounton บนบริบทเหล่านั้นใน init.te ทดสอบด้วย atest vfs_mgr_vendor_overlay_test ใน userdebug
การแก้ไขปัญหา: ข้อความเสียหาย dm-verity บน Android
บนอุปกรณ์ที่มีช่อง A/B ให้เปลี่ยนช่องหรือ การแฟลช vbmeta/boot โดยไม่สอดคล้องกับ roothash ซึ่งอาจก่อให้เกิดคำเตือน: dm-verity corruption, your device is untrusted. คำสั่งเช่น fastboot flash –disable-verity –disable-verification vbmeta vbmeta.img ปิดใช้งานการตรวจสอบ แต่ปล่อยให้ระบบไม่มีการรับประกันความสมบูรณ์ใดๆ
บูตโหลดเดอร์บางตัวรองรับ fastboot oem ปิดใช้งาน dm_verity และสิ่งที่ตรงกันข้ามคือ enable_dm_verity ใช้งานได้กับบางรุ่น แต่ใช้งานไม่ได้กับรุ่นอื่นๆ และอาจต้องใช้เคอร์เนล/magisk ที่มีแฟล็กที่ปรับแต่งแล้ว ใช้งานด้วยความเสี่ยงของคุณเอง: แนวทางปฏิบัติที่รอบคอบคือ จัดตำแหน่งการบูต vbmeta และระบบลงนามหรือสร้างต้นไม้ใหม่และตรวจสอบให้แน่ใจว่าแฮชรูทที่คาดหวังตรงกับที่กำหนดค่าไว้
หากหลังจากคำเตือนแล้วคุณสามารถกดปุ่มเปิด/ปิดเครื่องต่อได้ ระบบจะเริ่มทำงาน แต่ คุณไม่มีห่วงโซ่แห่งความไว้วางใจที่สมบูรณ์อีกต่อไปหากต้องการลบข้อความโดยไม่เสียสละความปลอดภัย ให้คืนค่ารูปภาพที่ลงนามดั้งเดิมหรือสร้างใหม่/ตรวจสอบ vbmeta ด้วยแฮชทรีที่ถูกต้อง แทนที่จะปิดการใช้งาน verity
แพลตฟอร์ม i.MX และ OpenWrt
บน i.MX6 (เช่น sabresd) กำหนดค่าเคอร์เนลด้วยการสนับสนุน DM_VERITY และ FECสร้างทรีด้วย veritysetup จัดเก็บแฮชรูทอย่างปลอดภัย และส่งพารามิเตอร์ที่เหมาะสมในบรรทัด cmd หรือผสานผ่าน initramfs ด้วย systemd-veritysetup หากคุณไม่ได้ใช้ dm-crypt คุณไม่จำเป็นต้องใช้ CAAM สำหรับ verity เพราะเน้นที่ความสมบูรณ์
ใน OpenWrt และใน ระบบ Linux ฝังตัวพร้อม OpenEmbedded, มีความพยายามที่จะรวม dm-verity และ SELinux (งาน Bootlin ได้รับการปรับปรุงด้วยความตั้งใจที่จะรวมการสนับสนุน) เป็นเรื่องที่เหมาะสมอย่างยิ่ง: เราเตอร์และอุปกรณ์เครือข่ายได้รับประโยชน์จากรูทที่ไม่เปลี่ยนแปลง ตรวจสอบแล้ว และผ่านการตรวจสอบ MAC-harded
การสร้างต้นไม้และเมตาข้อมูลด้วยตนเอง (มุมมองโดยละเอียด)
cryptsetup สามารถสร้างต้นไม้ให้คุณได้ แต่ถ้าคุณต้องการทำความเข้าใจรูปแบบ คำจำกัดความบรรทัดตารางแบบย่อมีดังนี้: ชื่อการแมป อุปกรณ์ข้อมูล ขนาดบล็อกข้อมูลและแฮช ขนาดภาพเป็นบล็อกตำแหน่ง hash_start (ภาพบล็อก + 8 ถ้าเชื่อมต่อกัน) รูทแฮช และ salt หลังจากสร้างเลเยอร์ที่เชื่อมต่อกันแล้ว (จากบนลงล่าง ยกเว้นเลเยอร์ 0) คุณจะเขียนทรีลงดิสก์
การแพ็คทุกอย่าง จัดทำตาราง dm-verity ลงนาม (RSA-2048 ทั่วไป) และจัดกลุ่มลายเซ็น+ตารางในข้อมูลเมตา ด้วยส่วนหัวที่มีเวอร์ชันและหมายเลขวิเศษ จากนั้นจะเชื่อมโยงอิมเมจระบบ เมตาดาต้าของ Verity และแฮชทรีเข้าด้วยกัน ใน fstab มันจะทำเครื่องหมาย fs_mgr ว่า verify และใส่คีย์สาธารณะไว้ใน /boot/verity_key เพื่อตรวจสอบลายเซ็น
เพิ่มประสิทธิภาพด้วย เพิ่มความเร็ว SHA-2 ให้กับ CPU ของคุณ และปรับ read-ahead/prefetch_cluster บนฮาร์ดแวร์ ARM ส่วนขยาย NEON SHA-2 (ARMv7) และ SHA-2 (ARMv8) ช่วยลดค่าใช้จ่ายในการตรวจสอบได้อย่างมาก
ในการใช้งานใดๆ โปรดจำไว้ว่า ค่าแฮชรูทต้องได้รับการปกป้องไม่ว่าจะคอมไพล์ลงใน UKI ที่ลงนามแล้ว ลงในพาร์ติชันบูตที่ลงนามแล้ว หรือผ่านการตรวจสอบโดยตัวโหลดบูตโดยใช้ AVB ทุกอย่างหลังจากจุดนั้นจะสืบทอดความน่าเชื่อถือนั้น
เมื่อทำสิ่งทั้งหมดข้างต้นแล้ว dm-verity จะกลายเป็น รากฐานที่มั่นคงสำหรับระบบที่ไม่เปลี่ยนแปลง เคลื่อนที่ได้ และระบบฝังตัวรองรับการอัปเดตธุรกรรม โอเวอร์เลย์การกำหนดค่า และโมเดลความปลอดภัยที่ทันสมัยซึ่งช่วยลดพื้นผิวการโจมตีและป้องกันการคงอยู่โดยไม่กระทบต่อประสิทธิภาพการทำงาน


