Android มีการติดตั้งใช้งานอ้างอิงของคอมโพเนนต์ทั้งหมดที่จำเป็นต่อการ ติดตั้งใช้งานเฟรมเวิร์กการจำลองการทำงานแบบเสมือนของ Android ปัจจุบันการใช้งานนี้ จำกัดเฉพาะ ARM64 หน้านี้จะอธิบายสถาปัตยกรรมของเฟรมเวิร์ก
ฉากหลัง
สถาปัตยกรรม Arm อนุญาตให้มีระดับข้อยกเว้นได้สูงสุด 4 ระดับ โดยระดับข้อยกเว้น 0 (EL0) มีสิทธิ์น้อยที่สุด และระดับข้อยกเว้น 3 (EL3) มีสิทธิ์มากที่สุด ส่วนที่ใหญ่ที่สุดของฐานของโค้ด Android (คอมโพเนนต์ทั้งหมดใน User Space) ทำงานที่ EL0 ส่วนที่เหลือซึ่งโดยทั่วไปเรียกว่า "Android" คือเคอร์เนล Linux ซึ่ง ทำงานที่ EL1
เลเยอร์ EL2 ช่วยให้สามารถใช้ไฮเปอร์ไวเซอร์ที่ช่วยแยก หน่วยความจำและอุปกรณ์เป็น pVM แต่ละรายการที่ EL1/EL0 โดยมีการรับประกันความลับ และความสมบูรณ์ที่เข้มงวด
ไฮเปอร์ไวเซอร์
เครื่องเสมือนที่ใช้เคอร์เนลที่ได้รับการปกป้อง (pKVM) สร้างขึ้นบน ไฮเปอร์ไวเซอร์ KVM ของ Linux ซึ่งได้รับการขยายความสามารถในการจำกัดการเข้าถึงเพย์โหลด ที่ทำงานในเครื่องเสมือนของแขกที่ทำเครื่องหมายว่า "ได้รับการปกป้อง" ในขณะที่สร้าง
KVM/arm64 รองรับโหมดการดำเนินการที่แตกต่างกันไปตามความพร้อมใช้งานของ
ฟีเจอร์ CPU บางอย่าง ได้แก่ ส่วนขยายโฮสต์การจำลองเสมือน (VHE) (ARMv8.1
ขึ้นไป) ในโหมดใดโหมดหนึ่งที่เรียกว่าโหมดที่ไม่ใช่ VHE ระบบจะแยกโค้ดไฮเปอร์ไวเซอร์ออกจากอิมเมจเคอร์เนลระหว่างการบูตและติดตั้งที่ EL2 ในขณะที่เคอร์เนลเองจะทำงานที่ EL1 แม้ว่าจะเป็นส่วนหนึ่งของโค้ดเบสของ Linux แต่คอมโพเนนต์ EL2 ของ KVM เป็นคอมโพเนนต์ขนาดเล็กที่รับผิดชอบ
การสลับระหว่าง EL1 หลายรายการ คอมโพเนนต์ไฮเปอร์ไวเซอร์ได้รับการคอมไพล์ด้วย
Linux แต่จะอยู่ในส่วนหน่วยความจำเฉพาะที่แยกต่างหากของvmlinux
อิมเมจ pKVM ใช้ประโยชน์จากการออกแบบนี้โดยการขยายโค้ดไฮเปอร์ไวเซอร์ด้วยฟีเจอร์ใหม่ๆ
ที่ช่วยให้สามารถจำกัดเคอร์เนลโฮสต์ Android และพื้นที่ผู้ใช้
รวมถึงจำกัดการเข้าถึงหน่วยความจำของโฮสต์ไปยังหน่วยความจำของแขกและไฮเปอร์ไวเซอร์
โมดูลของผู้ให้บริการ pKVM
โมดูลผู้ให้บริการ pKVM เป็นโมดูลเฉพาะฮาร์ดแวร์ที่มีฟังก์ชันการทำงานเฉพาะอุปกรณ์ เช่น ไดรเวอร์หน่วยจัดการหน่วยความจำอินพุต/เอาต์พุต (IOMMU) โมดูลเหล่านี้ช่วยให้คุณพอร์ตฟีเจอร์ด้านความปลอดภัยที่ต้องใช้สิทธิ์เข้าถึงระดับข้อยกเว้น 2 (EL2) ไปยัง pKVM ได้
ดูวิธีติดตั้งใช้งานและโหลดโมดูลของผู้ให้บริการ pKVM ได้ที่ ติดตั้งใช้งานโมดูลของผู้ให้บริการ pKVM
ขั้นตอนการเปิดเครื่อง
รูปภาพต่อไปนี้แสดงขั้นตอนการบูต pKVM
- Bootloader จะเข้าสู่เคอร์เนลทั่วไปที่ EL2
- เคอร์เนลทั่วไปจะตรวจพบว่ากำลังทำงานที่ EL2 และลดสิทธิ์ของตัวเองเป็น EL1 ขณะที่ pKVM และโมดูลจะยังคงทำงานที่ EL2 ต่อไป นอกจากนี้ ระบบจะโหลดโมดูลของผู้ให้บริการ pKVM ในเวลานี้ด้วย
- เคอร์เนลทั่วไปจะบูตตามปกติ โดยโหลดไดรเวอร์อุปกรณ์ที่จำเป็นทั้งหมดจนกว่าจะถึงพื้นที่ผู้ใช้ ตอนนี้ pKVM พร้อมใช้งานและจัดการตารางหน้าของระยะที่ 2
กระบวนการบูตเชื่อถือ Bootloader ในการรักษาความสมบูรณ์ของอิมเมจเคอร์เนล เฉพาะในช่วงต้นของการบูต เมื่อเคอร์เนลถูกลดสิทธิ์ ไฮเปอร์ไวเซอร์จะไม่ถือว่าเคอร์เนลเป็นสิ่งที่เชื่อถือได้อีกต่อไป และไฮเปอร์ไวเซอร์จะต้องรับผิดชอบในการปกป้องตัวเองแม้ว่าเคอร์เนลจะถูกบุกรุกก็ตาม
การมีเคอร์เนล Android และไฮเปอร์ไวเซอร์ในอิมเมจไบนารีเดียวกันช่วยให้ มีอินเทอร์เฟซการสื่อสารที่เชื่อมโยงกันอย่างใกล้ชิดระหว่างทั้ง 2 อย่าง การเชื่อมต่อที่แน่นแฟ้นนี้ช่วยให้มั่นใจได้ว่าคอมโพเนนต์ทั้ง 2 รายการจะได้รับการอัปเดตแบบอะตอม ซึ่งช่วยลดความจำเป็นในการรักษาอินเทอร์เฟซระหว่างคอมโพเนนต์ทั้ง 2 ให้เสถียร และมอบความยืดหยุ่นอย่างมากโดยไม่กระทบต่อความสามารถในการบำรุงรักษาในระยะยาว การเชื่อมต่อที่แน่นแฟ้น ยังช่วยให้เพิ่มประสิทธิภาพได้เมื่อทั้ง 2 องค์ประกอบทำงานร่วมกัน โดยไม่ส่งผลต่อการรับประกันความปลอดภัยที่ไฮเปอร์ไวเซอร์มอบให้
นอกจากนี้ การนำ GKI มาใช้ในระบบนิเวศของ Android ยังช่วยให้สามารถ ติดตั้งไฮเปอร์ไวเซอร์ pKVM ในอุปกรณ์ Android ในไบนารีเดียวกันกับ เคอร์เนลได้โดยอัตโนมัติ
การป้องกันการเข้าถึงหน่วยความจำ CPU
สถาปัตยกรรม Arm ระบุหน่วยจัดการหน่วยความจำ (MMU) ที่แบ่งออกเป็น 2 ขั้นตอน ที่เป็นอิสระ ซึ่งทั้ง 2 ขั้นตอนนี้สามารถใช้เพื่อใช้การแปลที่อยู่ และการควบคุมการเข้าถึงส่วนต่างๆ ของหน่วยความจำได้ MMU ระยะที่ 1 ควบคุมโดย EL1 และอนุญาตให้มีการแปลที่อยู่ระดับแรก MMU ระยะที่ 1 ใช้โดย Linux เพื่อจัดการพื้นที่ที่อยู่เสมือนที่จัดให้แก่กระบวนการในพื้นที่ผู้ใช้แต่ละกระบวนการ และพื้นที่ที่อยู่เสมือนของตัวเอง
MMU ขั้นที่ 2 ควบคุมโดย EL2 และช่วยให้สามารถใช้การแปลที่อยู่ครั้งที่ 2 กับที่อยู่เอาต์พุตของ MMU ขั้นที่ 1 ซึ่งส่งผลให้ได้ที่อยู่จริง (PA) ไฮเปอร์ไวเซอร์สามารถใช้การแปลระยะที่ 2 เพื่อ ควบคุมและแปลการเข้าถึงหน่วยความจำจาก VM ของแขกทั้งหมด ดังที่แสดงในรูปที่ 2 เมื่อเปิดใช้การแปลทั้ง 2 ขั้นตอน ที่อยู่เอาต์พุตของ ขั้นตอนที่ 1 จะเรียกว่าที่อยู่จริงระดับกลาง (IPA) หมายเหตุ: ระบบจะแปลที่อยู่เสมือน (VA) เป็น IPA แล้วจึงแปลเป็น PA
ในอดีต KVM จะทำงานโดยเปิดใช้การแปลระยะที่ 2 ขณะเรียกใช้แขกรับเชิญ และปิดใช้ระยะที่ 2 ขณะเรียกใช้เคอร์เนล Linux ของโฮสต์ สถาปัตยกรรมนี้ช่วยให้การเข้าถึงหน่วยความจำจาก MMU ระดับ 1 ของโฮสต์ผ่าน MMU ระดับ 2 ได้ จึงทำให้โฮสต์เข้าถึงหน้าหน่วยความจำของแขกได้โดยไม่มีข้อจำกัด ในทางกลับกัน pKVM จะเปิดใช้การป้องกันระยะที่ 2 แม้ในบริบทของโฮสต์ และให้ไฮเปอร์ไวเซอร์เป็นผู้รับผิดชอบในการปกป้องหน้าหน่วยความจำของแขก แทนโฮสต์
KVM ใช้การแปลที่อยู่ที่ระยะที่ 2 อย่างเต็มที่เพื่อใช้การแมป IPA/PA ที่ซับซ้อนสำหรับแขก ซึ่งสร้างภาพลวงตาของหน่วยความจำที่ต่อเนื่องสำหรับแขกแม้ว่าจะมีการกระจายทางกายภาพก็ตาม อย่างไรก็ตาม การใช้ MMU ระดับ 2 สำหรับโฮสต์จะจำกัดไว้ที่การควบคุมการเข้าถึงเท่านั้น โฮสต์สเตจ 2 จะ แมปข้อมูลประจำตัวเพื่อให้มั่นใจว่าหน่วยความจำที่อยู่ติดกันในพื้นที่ IPA ของโฮสต์ จะอยู่ติดกันในพื้นที่ PA สถาปัตยกรรมนี้ช่วยให้ใช้การแมปขนาดใหญ่ในตารางหน้าเว็บได้ และช่วยลดแรงกดดันใน Translation Lookaside Buffer (TLB) เนื่องจาก PA จัดทำดัชนีการจับคู่ข้อมูลประจำตัวได้ จึงใช้ โฮสต์ระยะที่ 2 เพื่อติดตามการเป็นเจ้าของหน้าเว็บในตารางหน้าเว็บโดยตรงด้วย
การป้องกันการเข้าถึงหน่วยความจำโดยตรง (DMA)
ดังที่อธิบายไว้ก่อนหน้านี้ การยกเลิกการแมปหน้าผู้เข้าชมจากโฮสต์ Linux ในตารางหน้า CPU เป็นขั้นตอนที่จำเป็นแต่ไม่เพียงพอสำหรับการปกป้องหน่วยความจำของแขกรับเชิญ pKVM ยังต้องป้องกันการเข้าถึงหน่วยความจำที่ทำโดยอุปกรณ์ที่รองรับ DMA ภายใต้การควบคุมของเคอร์เนลโฮสต์ และความเป็นไปได้ของการโจมตี DMA ที่เริ่มต้นโดยโฮสต์ที่เป็นอันตราย เพื่อป้องกันไม่ให้อุปกรณ์ดังกล่าวเข้าถึงหน่วยความจำของแขกรับเชิญ pKVM จึงต้องใช้ฮาร์ดแวร์หน่วยจัดการหน่วยความจำอินพุต/เอาต์พุต (IOMMU) สำหรับอุปกรณ์ที่รองรับ DMA ทุกเครื่องในระบบ ดังที่แสดงในรูปที่ 3
อย่างน้อยที่สุด ฮาร์ดแวร์ IOMMU จะมีวิธีการให้และเพิกถอน สิทธิ์เข้าถึงแบบอ่าน/เขียนสำหรับอุปกรณ์ไปยังหน่วยความจำจริงที่ระดับความละเอียดของหน้า อย่างไรก็ตาม ฮาร์ดแวร์ IOMMU นี้จำกัดการใช้อุปกรณ์ใน pVM เนื่องจากฮาร์ดแวร์ดังกล่าวถือว่ามี ระยะที่ 2 ที่มีการแมปข้อมูลประจำตัว
เพื่อให้มั่นใจว่าเครื่องเสมือนจะแยกกันอยู่ ธุรกรรมหน่วยความจำที่สร้างขึ้นใน นามของเอนทิตีต่างๆ ต้องแยกแยะได้โดย IOMMU เพื่อให้ใช้ชุดตารางหน้าเว็บที่ เหมาะสมสำหรับการแปลได้
นอกจากนี้ การลดปริมาณโค้ดเฉพาะ SoC ที่ EL2 ยังเป็นกลยุทธ์สำคัญ ในการลดฐานการประมวลผลที่เชื่อถือได้ (TCB) โดยรวมของ pKVM และขัดต่อ การรวมไดรเวอร์ IOMMU ไว้ในไฮเปอร์ไวเซอร์ เพื่อลดปัญหานี้ โฮสต์ที่ EL1 มีหน้าที่รับผิดชอบงานการจัดการ IOMMU เสริม เช่น การจัดการพลังงาน การเริ่มต้น และการจัดการการขัดจังหวะ (หากมี)
อย่างไรก็ตาม การให้โฮสต์ควบคุมสถานะของอุปกรณ์จะทำให้มีข้อกำหนดเพิ่มเติม ในอินเทอร์เฟซการเขียนโปรแกรมของฮาร์ดแวร์ IOMMU เพื่อให้มั่นใจว่า การตรวจสอบสิทธิ์จะไม่ถูกข้ามด้วยวิธีอื่น เช่น การรีเซ็ตอุปกรณ์
IOMMU มาตรฐานที่ได้รับการสนับสนุนอย่างดีสำหรับอุปกรณ์ Arm ซึ่งทำให้ทั้งการแยกและการกำหนดโดยตรงเป็นไปได้คือสถาปัตยกรรมหน่วยจัดการหน่วยความจำของระบบ (SMMU) ของ Arm สถาปัตยกรรมนี้เป็นโซลูชันอ้างอิงที่แนะนำ
การเป็นเจ้าของความทรงจำ
ในเวลาที่บูต ระบบจะถือว่าโฮสต์เป็นเจ้าของหน่วยความจำทั้งหมดที่ไม่ใช่ไฮเปอร์ไวเซอร์ และ ไฮเปอร์ไวเซอร์จะติดตามหน่วยความจำดังกล่าว เมื่อสร้าง pVM โฮสต์จะบริจาคหน้าหน่วยความจำเพื่อให้บูตได้ และไฮเปอร์ไวเซอร์จะเปลี่ยนสิทธิ์การเป็นเจ้าของหน้าเหล่านั้นจากโฮสต์ไปยัง pVM ดังนั้น ไฮเปอร์ไวเซอร์จึงกำหนดข้อจำกัดการควบคุมการเข้าถึงในตารางหน้าของโฮสต์ในระยะที่ 2 เพื่อป้องกันไม่ให้เข้าถึงหน้าเว็บอีกครั้ง ซึ่งจะช่วยรักษาความลับให้กับแขกรับเชิญ
การสื่อสารระหว่างโฮสต์และแขกรับเชิญเกิดขึ้นได้จากการแชร์หน่วยความจำที่ควบคุม ระหว่างกัน ระบบอนุญาตให้แขกแชร์บางหน้าของตนเองกลับไปให้ โฮสต์โดยใช้ไฮเปอร์คอล ซึ่งจะสั่งให้ไฮเปอร์ไวเซอร์ทำการแมปหน้าเหล่านั้นใหม่ ในตารางหน้าของโฮสต์ในระยะที่ 2 ในทำนองเดียวกัน การสื่อสารของโฮสต์กับ TrustZone จะเป็นไปได้ด้วยการแชร์หน่วยความจำและ/หรือการดำเนินการยืม ซึ่งทั้งหมดนี้ได้รับการตรวจสอบและควบคุมอย่างใกล้ชิดโดย pKVM โดยใช้ข้อกำหนดของเฟรมเวิร์กเฟิร์มแวร์สำหรับ Arm (FF-A)
เนื่องจากข้อกำหนดด้านหน่วยความจำของ pVM อาจเปลี่ยนแปลงไปตามกาลเวลา จึงมี Hypercall ซึ่งช่วยให้สามารถสละสิทธิ์การเป็นเจ้าของหน้าเว็บที่ระบุซึ่งเป็นของผู้เรียก กลับไปยังโฮสต์ได้ ในทางปฏิบัติ ไฮเปอร์คอลนี้ใช้ กับโปรโตคอลบอลลูน virtio เพื่ออนุญาตให้ VMM ขอหน่วยความจำ จาก pVM และให้ pVM แจ้ง VMM เกี่ยวกับหน้าที่ถูกปล่อย ในลักษณะที่ควบคุมได้
ไฮเปอร์ไวเซอร์มีหน้าที่ติดตามความเป็นเจ้าของหน้าหน่วยความจำทั้งหมดในระบบ รวมถึงติดตามว่ามีการแชร์หรือให้ยืมแก่เอนทิตีอื่นๆ หรือไม่ การติดตามสถานะส่วนใหญ่ นี้ทำโดยใช้ข้อมูลเมตาที่แนบมากับตารางหน้าของโฮสต์และแขกรับเชิญใน ระยะที่ 2 โดยใช้บิตที่สงวนไว้ในรายการตารางหน้า (PTE) ซึ่ง ตามชื่อที่แนะนำไว้คือสงวนไว้สำหรับการใช้งานซอฟต์แวร์
โฮสต์ต้องตรวจสอบว่าไม่ได้พยายามเข้าถึงหน้าเว็บที่ไฮเปอร์ไวเซอร์ทำให้เข้าถึงไม่ได้ การเข้าถึงโฮสต์อย่างผิดกฎหมายจะทำให้ไฮเปอร์ไวเซอร์แทรกข้อยกเว้นแบบซิงโครนัส ลงในโฮสต์ ซึ่งอาจ ส่งผลให้งานในพื้นที่ผู้ใช้ที่รับผิดชอบได้รับสัญญาณ SEGV หรือเคอร์เนลของโฮสต์ ขัดข้อง เพื่อป้องกันการเข้าถึงโดยไม่ตั้งใจ เคอร์เนลของโฮสต์จะทำให้หน้าที่แชร์กับผู้เข้าร่วม ไม่มีสิทธิ์ในการสลับหรือผสาน
การจัดการการขัดจังหวะและตัวจับเวลา
การขัดจังหวะเป็นส่วนสำคัญของวิธีที่แขกรับเชิญโต้ตอบกับอุปกรณ์ และสำหรับการสื่อสารระหว่าง CPU ซึ่งการขัดจังหวะระหว่างโปรเซสเซอร์ (IPI) เป็น กลไกการสื่อสารหลัก โมเดล KVM คือการมอบหมายการจัดการอินเทอร์รัปต์เสมือนทั้งหมดให้กับโฮสต์ใน EL1 ซึ่งมีลักษณะเป็นส่วนที่ไม่น่าเชื่อถือของไฮเปอร์ไวเซอร์เพื่อจุดประสงค์ดังกล่าว
pKVM มีการจำลองตัวควบคุมการขัดจังหวะทั่วไปเวอร์ชัน 3 (GICv3) เต็มรูปแบบ โดยอิงตามโค้ด KVM ที่มีอยู่ ตัวจับเวลาและ IPI จะ ได้รับการจัดการเป็นส่วนหนึ่งของโค้ดการจำลองที่ไม่น่าเชื่อถือนี้
การรองรับ GICv3
อินเทอร์เฟซระหว่าง EL1 กับ EL2 ต้องตรวจสอบว่าโฮสต์ EL1 มองเห็นสถานะการขัดจังหวะทั้งหมด รวมถึงสำเนาของรีจิสเตอร์ไฮเปอร์ไวเซอร์ที่เกี่ยวข้องกับการขัดจังหวะ โดยปกติแล้ว การมองเห็นนี้จะทำได้โดยใช้รีเจียนหน่วยความจำที่ใช้ร่วมกัน ซึ่งมี 1 รีเจียนต่อ CPU เสมือน (vCPU)
สามารถลดความซับซ้อนของโค้ดการสนับสนุนรันไทม์ของรีจิสทรีระบบเพื่อรองรับเฉพาะรีจิสทรีการขัดจังหวะที่สร้างโดยซอฟต์แวร์ (SGIR) และการดักจับรีจิสทรีการขัดจังหวะการปิดใช้งาน (DIR) สถาปัตยกรรมกำหนดให้รีจิสเตอร์เหล่านี้ ต้องดักจับไปยัง EL2 เสมอ ขณะที่การดักจับอื่นๆ นั้นจนถึงตอนนี้มีประโยชน์ ในการลดผลกระทบจากข้อผิดพลาดเท่านั้น ส่วนอื่นๆ จะได้รับการจัดการในฮาร์ดแวร์
ในฝั่ง MMIO ทุกอย่างจะได้รับการจำลองที่ EL1 โดยใช้โครงสร้างพื้นฐานปัจจุบันทั้งหมดใน KVM ซ้ำ สุดท้ายนี้ Wait for Interrupt (WFI) จะส่งต่อไปยัง EL1 เสมอ เนื่องจากนี่เป็นหนึ่งใน Primitive การจัดกำหนดการพื้นฐานที่ KVM ใช้
การรองรับตัวจับเวลา
ต้องเปิดเผยค่าตัวเปรียบเทียบสำหรับตัวจับเวลาเสมือนต่อ EL1 ในแต่ละ การดักจับ WFI เพื่อให้ EL1 สามารถแทรกการขัดจังหวะตัวจับเวลาขณะที่ vCPU ถูกบล็อก ระบบจะจำลองตัวจับเวลาจริงทั้งหมด และส่งต่อการดักจับทั้งหมดไปยัง EL1
การจัดการ MMIO
หากต้องการสื่อสารกับโปรแกรมตรวจสอบเครื่องเสมือน (VMM) และจำลอง GIC ต้องส่งต่อการดักจับ MMIO กลับไปยังโฮสต์ใน EL1 เพื่อการจัดลำดับความสำคัญเพิ่มเติม pKVM ต้องมีสิ่งต่อไปนี้
- IPA และขนาดของการเข้าถึง
- ข้อมูลในกรณีของการเขียน
- Endianness ของ CPU ณ จุดที่ดักจับ
นอกจากนี้ ระบบจะส่งต่อกับดักที่มีรีจิสเตอร์อเนกประสงค์ (GPR) เป็นแหล่งที่มา/ปลายทางโดยใช้รีจิสเตอร์เสมือนการโอนแบบนามธรรม
อินเทอร์เฟซสำหรับผู้เข้าร่วม
แขกรับเชิญสามารถสื่อสารกับแขกรับเชิญที่ได้รับการปกป้องได้โดยใช้การผสมผสานระหว่าง Hypercall และการเข้าถึงหน่วยความจำไปยังรีเจียนที่ดักไว้ Hypercall จะแสดงตามมาตรฐาน SMCCC โดยมีช่วงที่สงวนไว้สำหรับการจัดสรรของผู้ให้บริการโดย KVM Hypercall ต่อไปนี้มีความสำคัญเป็นพิเศษ ต่อแขกรับเชิญของ pKVM
Hypercall ทั่วไป
- PSCI มีกลไกมาตรฐานสำหรับแขกในการควบคุมวงจรของ vCPU รวมถึงการออนไลน์ การออฟไลน์ และการปิดระบบ
- TRNG มีกลไกมาตรฐานสำหรับแขกในการขอเอนโทรปีจาก pKVM ซึ่งส่งต่อการเรียกไปยัง EL3 กลไกนี้มีประโยชน์อย่างยิ่ง ในกรณีที่ไม่สามารถเชื่อถือโฮสต์ให้จำลองเครื่องสร้างตัวเลขสุ่มฮาร์ดแวร์ (RNG) ได้
Hypercall ของ pKVM
- การแชร์ความทรงจำกับโฮสต์ ในตอนแรก โฮสต์จะเข้าถึงหน่วยความจำของแขกไม่ได้ แต่จำเป็นต้องมีสิทธิ์เข้าถึงของโฮสต์สำหรับการสื่อสารหน่วยความจำที่ใช้ร่วมกันและสำหรับอุปกรณ์ Paravirtualized ที่ใช้บัฟเฟอร์ที่ใช้ร่วมกัน Hypercall สำหรับการแชร์และยกเลิกการแชร์หน้าเว็บกับโฮสต์ช่วยให้แขกตัดสินใจได้ว่า จะให้ส่วนใดของหน่วยความจำเข้าถึงได้สำหรับ Android ที่เหลือโดยไม่ต้อง มีการแฮนด์เชค
- การส่งคืนหน่วยความจำไปยังโฮสต์ โดยปกติแล้ว หน่วยความจำของแขกทั้งหมดจะเป็นของแขกจนกว่าจะถูกทำลาย สถานะนี้อาจไม่เพียงพอสำหรับ VM ที่มีอายุการใช้งานยาวนาน
ซึ่งมีข้อกำหนดด้านหน่วยความจำที่แตกต่างกันไปตามกาลเวลา
relinquish
Hypercall ช่วยให้ระบบปฏิบัติการ Guest โอนความเป็นเจ้าของหน้าเว็บกลับไปยัง โฮสต์ได้อย่างชัดเจนโดยไม่ต้องสิ้นสุดการทำงานของ Guest - การดักจับการเข้าถึงหน่วยความจำไปยังโฮสต์ โดยปกติแล้ว หากแขกรับเชิญ KVM เข้าถึง ที่อยู่ที่ไม่ได้สอดคล้องกับรีเจียนหน่วยความจำที่ถูกต้อง เธรด vCPU จะออกจากโฮสต์ และโดยทั่วไปแล้วการเข้าถึงจะใช้สำหรับ MMIO และ จำลองโดย VMM ในพื้นที่ผู้ใช้ เพื่ออำนวยความสะดวกในการจัดการนี้ pKVM ต้องโฆษณารายละเอียดเกี่ยวกับข้อบกพร่อง คำสั่ง เช่น ที่อยู่ พารามิเตอร์รีจิสเตอร์ และเนื้อหาที่อาจมี กลับไปยังโฮสต์ ซึ่งอาจเปิดเผยข้อมูลที่ละเอียดอ่อนโดยไม่ตั้งใจ จากแขกที่ได้รับการปกป้องหากไม่ได้คาดการณ์การดักจับ pKVM จะแก้ปัญหานี้ โดยถือว่าข้อบกพร่องเหล่านี้เป็นข้อบกพร่องร้ายแรง เว้นแต่แขกจะเคย ออกไฮเปอร์คอลเพื่อระบุช่วง IPA ที่มีข้อบกพร่องเป็นช่วงที่ ได้รับอนุญาตให้ดักจับกลับไปยังโฮสต์ โซลูชันนี้เรียกว่าการป้องกัน MMIO
อุปกรณ์ I/O เสมือน (virtio)
Virtio เป็นมาตรฐานยอดนิยมแบบพกพาและมีเสถียรภาพสำหรับการใช้งานและ การโต้ตอบกับอุปกรณ์ที่ใช้ Paravirtualization อุปกรณ์ส่วนใหญ่ที่แสดงต่อแขกรับเชิญที่ได้รับการปกป้องจะใช้ virtio นอกจากนี้ Virtio ยังเป็นรากฐานของการใช้งาน vsock ที่ใช้สำหรับการสื่อสารระหว่างแขกรับเชิญที่ได้รับการปกป้องกับส่วนอื่นๆ ของ Android
โดยทั่วไปแล้ว VMM จะติดตั้งใช้งานอุปกรณ์ Virtio ในพื้นที่ผู้ใช้ของโฮสต์ ซึ่งจะสกัดกั้นการเข้าถึงหน่วยความจำที่ดักจับจากแขกไปยังอินเทอร์เฟซ MMIO ของอุปกรณ์ Virtio และจำลองลักษณะการทำงานที่คาดไว้ การเข้าถึง MMIO มีค่าใช้จ่ายค่อนข้างสูงเนื่องจากการเข้าถึงอุปกรณ์แต่ละครั้งต้องมีการเดินทางไปกลับ ไปยัง VMM และกลับมา ดังนั้นการโอนข้อมูลจริงส่วนใหญ่ระหว่าง อุปกรณ์และแขกจึงเกิดขึ้นโดยใช้ชุด virtqueue ในหน่วยความจำ สมมติฐานหลักของ virtio คือโฮสต์สามารถเข้าถึงหน่วยความจำของแขกได้โดยพลการ สมมติฐานนี้ เห็นได้ชัดในการออกแบบ Virtqueue ซึ่งอาจมีพอยน์เตอร์ไปยัง บัฟเฟอร์ในแขกที่การจำลองอุปกรณ์ตั้งใจจะเข้าถึงโดยตรง
แม้ว่าไฮเปอร์คอลที่อธิบายไว้ก่อนหน้านี้เกี่ยวกับการแชร์หน่วยความจำจะใช้เพื่อ แชร์บัฟเฟอร์ข้อมูล virtio จากแขกไปยังโฮสต์ได้ แต่การแชร์นี้ จำเป็นต้องดำเนินการที่ระดับความละเอียดของหน้า และอาจทำให้มีการเปิดเผยข้อมูลมากกว่าที่จำเป็น หากขนาดบัฟเฟอร์น้อยกว่าขนาดของหน้า แต่จะกำหนดค่าให้ระบบจัดสรรทั้ง Virtqueue และบัฟเฟอร์ข้อมูลที่เกี่ยวข้องจากหน้าต่างหน่วยความจำที่ใช้ร่วมกันแบบคงที่ โดยจะคัดลอก (ส่งต่อ) ข้อมูลไปยังและจากหน้าต่างตามที่จำเป็น
การโต้ตอบกับ TrustZone
แม้ว่าแขกรับเชิญจะโต้ตอบกับ TrustZone โดยตรงไม่ได้ แต่ผู้จัดจะต้องยังคงสามารถออกการเรียก SMC ไปยังโลกที่ปลอดภัยได้ การเรียกเหล่านี้สามารถระบุ บัฟเฟอร์หน่วยความจำที่กำหนดที่อยู่จริงซึ่งโฮสต์เข้าถึงไม่ได้ เนื่องจากโดยทั่วไปแล้วซอฟต์แวร์ที่ปลอดภัยจะไม่ทราบถึงการเข้าถึงบัฟเฟอร์ โฮสต์ที่เป็นอันตรายจึงอาจใช้บัฟเฟอร์นี้เพื่อทำการโจมตีแบบ Confused Deputy (คล้ายกับการโจมตี DMA) pKVM จะดักจับการเรียก SMC ทั้งหมดของโฮสต์ไปยัง EL2 และทำหน้าที่เป็นพร็อกซีระหว่างโฮสต์กับ Secure Monitor ที่ EL3 เพื่อป้องกันการโจมตีดังกล่าว
ระบบจะส่งต่อการเรียก PSCI จากโฮสต์ไปยังเฟิร์มแวร์ EL3 โดยมีการแก้ไขน้อยที่สุด โดยเฉพาะอย่างยิ่ง จุดแรกเข้าสำหรับ CPU ที่ออนไลน์หรือ กลับมาทำงานต่อจากโหมดพักจะได้รับการเขียนใหม่เพื่อให้ติดตั้งตารางหน้าของระยะที่ 2 ที่ EL2 ก่อนที่จะกลับไปยังโฮสต์ที่ EL1 ในระหว่างการบูต pKVM จะบังคับใช้ การป้องกันนี้
สถาปัตยกรรมนี้ขึ้นอยู่กับ SoC ที่รองรับ PSCI ซึ่งควรใช้ TF-A เวอร์ชันล่าสุด เป็นเฟิร์มแวร์ EL3
เฟรมเวิร์กเฟิร์มแวร์สำหรับ Arm (FF-A) จะกำหนดมาตรฐานการโต้ตอบระหว่างโลกปกติและโลกที่ปลอดภัย โดยเฉพาะอย่างยิ่งเมื่อมีไฮเปอร์ไวเซอร์ที่ปลอดภัย ส่วนสำคัญของ ข้อกำหนดจะกำหนดกลไกสำหรับการแชร์หน่วยความจำกับโลกที่ปลอดภัย โดยใช้ทั้งรูปแบบข้อความทั่วไปและรูปแบบสิทธิ์ที่กำหนดไว้อย่างดีสำหรับ หน้าเว็บพื้นฐาน พร็อกซี pKVM จะส่งต่อข้อความ FF-A เพื่อให้แน่ใจว่าโฮสต์ ไม่ได้พยายามแชร์หน่วยความจำกับฝั่งที่ปลอดภัยซึ่งไม่มี สิทธิ์เพียงพอ
สถาปัตยกรรมนี้อาศัยซอฟต์แวร์โลกที่ปลอดภัยซึ่งบังคับใช้โมเดลการเข้าถึงหน่วยความจำ เพื่อให้มั่นใจว่าแอปที่เชื่อถือได้และซอฟต์แวร์อื่นๆ ที่ทำงานในโลกที่ปลอดภัยจะเข้าถึงหน่วยความจำได้ก็ต่อเมื่อโลกที่ปลอดภัยเป็นเจ้าของหน่วยความจำนั้นแต่เพียงผู้เดียว หรือมีการแชร์หน่วยความจำนั้นกับโลกที่ปลอดภัยอย่างชัดเจนโดยใช้ FF-A ในระบบที่มี S-EL2 การบังคับใช้โมเดลการเข้าถึงหน่วยความจำควร ดำเนินการโดย Secure Partition Manager Core (SPMC) เช่น Hafnium ซึ่งดูแลตารางหน้าในระยะที่ 2 สำหรับโลกที่ปลอดภัย ในระบบที่ไม่มี S-EL2 TEE จะบังคับใช้โมเดลการเข้าถึงหน่วยความจำผ่านตารางหน้าของสเตจ 1 แทน
หากการเรียก SMC ไปยัง EL2 ไม่ใช่การเรียก PSCI หรือข้อความที่กำหนดไว้ใน FF-A ระบบจะส่งต่อ SMC ที่ไม่ได้จัดการไปยัง EL3 สมมติฐานคือเฟิร์มแวร์ที่ปลอดภัย (ซึ่งต้องเชื่อถือได้) สามารถจัดการ SMC ที่ไม่ได้จัดการได้อย่างปลอดภัย เนื่องจากเฟิร์มแวร์เข้าใจข้อควรระวังที่จำเป็นในการรักษาการแยก pVM
โปรแกรมตรวจสอบเครื่องเสมือน
crosvm เป็นโปรแกรมตรวจสอบเครื่องเสมือน (VMM) ที่เรียกใช้เครื่องเสมือนผ่านอินเทอร์เฟซ KVM ของ Linux สิ่งที่ทำให้ crosvm แตกต่างคือการมุ่งเน้น ด้านความปลอดภัยด้วยการใช้ภาษาโปรแกรม Rust และแซนด์บ็อกซ์รอบๆ อุปกรณ์เสมือนเพื่อปกป้องเคอร์เนลของโฮสต์ ดูข้อมูลเพิ่มเติมเกี่ยวกับ crosvm ได้ในเอกสารประกอบอย่างเป็นทางการที่นี่
ตัวอธิบายไฟล์และ ioctl
KVM จะแสดงอุปกรณ์อักขระ /dev/kvm
ให้กับพื้นที่ผู้ใช้ด้วย ioctl ที่ประกอบกันเป็น KVM API ioctls อยู่ในหมวดหมู่ต่อไปนี้
- การค้นหา ioctl ของระบบและการตั้งค่าแอตทริบิวต์ส่วนกลางที่มีผลต่อทั้งระบบย่อย KVM และสร้าง pVM
- ioctls ของ VM จะค้นหาและตั้งค่าแอตทริบิวต์ที่สร้าง CPU เสมือน (vCPU) และ อุปกรณ์ รวมถึงมีผลต่อ pVM ทั้งหมด เช่น การรวมเลย์เอาต์หน่วยความจำและ จำนวน CPU เสมือน (vCPU) และอุปกรณ์
- ioctl ของ vCPU จะค้นหาและตั้งค่าแอตทริบิวต์ที่ควบคุมการทำงานของ CPU เสมือนเดียว
- Device ioctls จะค้นหาและตั้งค่าแอตทริบิวต์ที่ควบคุมการทำงานของ อุปกรณ์เสมือนเครื่องเดียว
กระบวนการ crosvm แต่ละรายการจะเรียกใช้เครื่องเสมือน 1 อินสแตนซ์ กระบวนการนี้
ใช้ ioctl ของระบบ KVM_CREATE_VM
เพื่อสร้างตัวอธิบายไฟล์ VM ที่ใช้
ออก ioctl ของ pVM ได้ KVM_CREATE_VCPU
หรือ KVM_CREATE_DEVICE
ioctl
ใน VM FD จะสร้าง vCPU/อุปกรณ์และแสดงตัวอธิบายไฟล์ที่ชี้ไปยัง
ทรัพยากรใหม่ คุณสามารถใช้ ioctl ใน vCPU หรืออุปกรณ์ FD เพื่อควบคุมอุปกรณ์
ที่สร้างขึ้นโดยใช้ ioctl ใน VM FD สำหรับ vCPU ซึ่งรวมถึง
งานสำคัญในการเรียกใช้โค้ดของแขก
ภายใน crosvm จะลงทะเบียนตัวอธิบายไฟล์ของ VM กับเคอร์เนลโดยใช้epoll
อินเทอร์เฟซที่ทริกเกอร์ขอบ จากนั้นเคอร์เนลจะแจ้งให้ crosvm ทราบทุกครั้งที่มีเหตุการณ์ใหม่ที่รอดำเนินการในตัวอธิบายไฟล์
pKVM เพิ่มความสามารถใหม่ KVM_CAP_ARM_PROTECTED_VM
ซึ่งใช้เพื่อ
รับข้อมูลเกี่ยวกับสภาพแวดล้อม pVM และตั้งค่าโหมดที่ได้รับการปกป้องสำหรับ VM ได้
crosvm จะใช้ความสามารถนี้ในระหว่างการสร้าง pVM หากมีการส่งแฟล็ก --protected-vm
เพื่อค้นหาและจองหน่วยความจำในปริมาณที่เหมาะสมสำหรับ
เฟิร์มแวร์ pVM แล้วจึงเปิดใช้โหมดที่ได้รับการปกป้อง
การจัดสรรหน่วยความจำ
หน้าที่หลักอย่างหนึ่งของ VMM คือการจัดสรรหน่วยความจำของ VM และ การจัดการเลย์เอาต์หน่วยความจำของ VM โดย crosvm สร้าง เลย์เอาต์หน่วยความจำแบบคงที่ซึ่งอธิบายคร่าวๆ ไว้ในตารางด้านล่าง
FDT ในโหมดปกติ | PHYS_MEMORY_END - 0x200000
|
พื้นที่ว่าง | ...
|
Ramdisk | ALIGN_UP(KERNEL_END, 0x1000000)
|
ฟองสบู่แตก | 0x80080000
|
Bootloader | 0x80200000
|
FDT ในโหมด BIOS | 0x80000000
|
ฐานหน่วยความจำจริง | 0x80000000
|
เฟิร์มแวร์ pVM | 0x7FE00000
|
หน่วยความจำอุปกรณ์ | 0x10000 - 0x40000000
|
หน่วยความจำจริงจะได้รับการจัดสรรด้วย mmap
และหน่วยความจำจะได้รับการบริจาคให้กับ VM เพื่อ
สร้างภูมิภาคหน่วยความจำที่เรียกว่า memslots ด้วย KVM_SET_USER_MEMORY_REGION
ioctl ดังนั้น หน่วยความจำ pVM ของแขกรับเชิญทั้งหมดจึง
เชื่อมโยงกับอินสแตนซ์ crosvm ที่จัดการหน่วยความจำดังกล่าว และอาจส่งผลให้
กระบวนการถูกปิด (สิ้นสุด VM) หากโฮสต์เริ่มมีหน่วยความจำว่างไม่เพียงพอ
เมื่อหยุด VM ไฮเปอร์ไวเซอร์จะล้างหน่วยความจำโดยอัตโนมัติและส่งคืนไปยังเคอร์เนลของโฮสต์
ภายใต้ KVM ปกติ VMM จะยังคงมีสิทธิ์เข้าถึงหน่วยความจำของแขกรับเชิญทั้งหมด เมื่อใช้ pKVM ระบบจะยกเลิกการแมปหน่วยความจำของเครื่องเสมือนจากพื้นที่ที่อยู่จริงของโฮสต์เมื่อมีการบริจาค ให้กับเครื่องเสมือน ข้อยกเว้นเพียงอย่างเดียวคือหน่วยความจำที่แขกรับเชิญแชร์กลับมาอย่างชัดเจน เช่น สำหรับอุปกรณ์ Virtio
ระบบจะไม่แมปภูมิภาค MMIO ในพื้นที่ที่อยู่ของเครื่องเสมือน ระบบจะดักการเข้าถึงรีเจียนเหล่านี้ โดยแขกรับเชิญและส่งผลให้เกิดเหตุการณ์ I/O ใน FD ของ VM กลไกนี้ใช้เพื่อติดตั้งใช้งานอุปกรณ์เสมือน ในโหมดที่ได้รับการปกป้อง แขกรับเชิญ ต้องรับทราบว่าระบบจะใช้ภูมิภาคของพื้นที่ที่อยู่สำหรับ MMIO โดยใช้ ไฮเปอร์คอล เพื่อลดความเสี่ยงที่ข้อมูลจะรั่วไหลโดยไม่ตั้งใจ
การตั้งเวลา
CPU เสมือนแต่ละรายการจะแสดงด้วยเธรด POSIX และกำหนดเวลาโดยตัวกำหนดเวลา Linux ของโฮสต์
เธรดจะเรียก KVM_RUN
ioctl ใน vCPU FD ซึ่งส่งผลให้
ไฮเปอร์ไวเซอร์เปลี่ยนไปใช้บริบท vCPU ของแขก ตัวกำหนดเวลาโฮสต์
จะพิจารณาเวลาที่ใช้ในบริบทของแขกเป็นเวลาที่ใช้โดยเธรด vCPU ที่เกี่ยวข้อง
KVM_RUN
จะแสดงเมื่อมีเหตุการณ์ที่ VMM ต้องจัดการ เช่น I/O, สิ้นสุดการขัดจังหวะ หรือ vCPU หยุดทำงาน VMM จัดการ
เหตุการณ์และเรียกใช้ KVM_RUN
อีกครั้ง
ในระหว่าง KVM_RUN
ตัวกำหนดเวลาระดับโฮสต์จะยังคงขัดจังหวะเธรดได้ ยกเว้น
การเรียกใช้โค้ดไฮเปอร์ไวเซอร์ EL2 ซึ่งขัดจังหวะไม่ได้ pVM ของแขกรับเชิญ
ไม่มีกลไกในการควบคุมลักษณะการทำงานนี้
เนื่องจากมีการกำหนดเวลาเธรด vCPU ทั้งหมดเหมือนกับงานในพื้นที่ผู้ใช้อื่นๆ จึง ขึ้นอยู่กับกลไก QoS มาตรฐานทั้งหมด กล่าวคือ แต่ละเธรด vCPU สามารถ เชื่อมโยงกับ CPU จริง วางไว้ใน cpusets เพิ่มประสิทธิภาพหรือจำกัดโดยใช้ การหน่วงการใช้งาน เปลี่ยนนโยบายลำดับความสำคัญ/การจัดกำหนดการ และอื่นๆ
อุปกรณ์เสมือน
crosvm รองรับอุปกรณ์หลายอย่าง ซึ่งรวมถึงอุปกรณ์ต่อไปนี้
- virtio-blk สำหรับอิมเมจดิสก์แบบคอมโพสิต แบบอ่านอย่างเดียวหรืออ่าน/เขียน
- vhost-vsock สำหรับการสื่อสารกับโฮสต์
- virtio-pci เป็นการรับส่ง virtio
- นาฬิกาแบบเรียลไทม์ (RTC) pl030
- UART 16550a สำหรับการสื่อสารแบบอนุกรม
เฟิร์มแวร์ pVM
เฟิร์มแวร์ pVM (pvmfw) เป็นโค้ดแรกที่ pVM ดำเนินการ ซึ่งคล้ายกับ ROM สำหรับการบูตของอุปกรณ์จริง เป้าหมายหลักของ pvmfw คือการเริ่มต้น การบูตที่ปลอดภัยและรับค่าลับที่ไม่ซ้ำกันของ pVM pvmfw ไม่ได้จำกัดการใช้งาน กับระบบปฏิบัติการใดๆ เช่น Microdroid ตราบใดที่ crosvm รองรับระบบปฏิบัติการนั้นและมีการลงนามอย่างถูกต้อง
ไบนารี pvmfw จะจัดเก็บไว้ในพาร์ติชันแฟลชที่มีชื่อเดียวกันและจะ อัปเดตโดยใช้ OTA
การเปิดเครื่องอุปกรณ์
ระบบจะเพิ่มลำดับขั้นตอนต่อไปนี้ลงในขั้นตอนการบูตของ อุปกรณ์ที่เปิดใช้ pKVM
- Android Bootloader (ABL) จะโหลด pvmfw จากพาร์ติชันลงในหน่วยความจำและ ยืนยันอิมเมจ
- ABL จะรับข้อมูลลับของ Device Identifier Composition Engine (DICE) (ตัวระบุอุปกรณ์แบบรวม (CDI) และห่วงโซ่ใบรับรอง DICE) จาก Root of Trust
- ABL จะได้รับ CDI ที่จำเป็นสำหรับ pvmfw และผนวกเข้ากับไบนารี pvmfw
- ABL จะเพิ่มโหนด
linux,pkvm-guest-firmware-memory
reserved memory region ลงใน DT ซึ่งอธิบายตำแหน่งและขนาดของไบนารี pvmfw และ ข้อมูลลับที่ได้มาจากขั้นตอนก่อนหน้า - ABL จะส่งต่อการควบคุมไปยัง Linux และ Linux จะเริ่มต้น pKVM
- pKVM จะยกเลิกการแมปภูมิภาคหน่วยความจำ pvmfw จากตารางหน้าของระยะที่ 2 ของโฮสต์ และ ปกป้องจากโฮสต์ (และแขกรับเชิญ) ตลอดระยะเวลาที่อุปกรณ์ทำงาน
หลังจากเปิดเครื่องอุปกรณ์แล้ว Microdroid จะเริ่มทำงานตามขั้นตอนในส่วนลำดับการบูตของเอกสารMicrodroid
การบูต pVM
เมื่อสร้าง pVM, crosvm (หรือ VMM อื่น) ต้องสร้าง memslot ที่มีขนาดใหญ่เพียงพอ เพื่อให้ไฮเปอร์ไวเซอร์ป้อนข้อมูลด้วยอิมเมจ pvmfw นอกจากนี้ VMM ยัง ถูกจำกัดในรายการรีจิสเตอร์ที่สามารถตั้งค่าเริ่มต้นได้ (x0-x14 สำหรับ vCPU หลัก และไม่มีสำหรับ vCPU รอง) รีจิสเตอร์ที่เหลือจะ สงวนไว้และเป็นส่วนหนึ่งของ ABI ของไฮเปอร์ไวเซอร์-pvmfw
เมื่อเรียกใช้ pVM ไฮเปอร์ไวเซอร์จะส่งต่อการควบคุม vCPU หลัก
ไปยัง pvmfw ก่อน เฟิร์มแวร์คาดหวังว่า crosvm จะโหลดเคอร์เนลที่ลงนาม AVB
ซึ่งอาจเป็น Bootloader หรืออิมเมจอื่นๆ และ FDT ที่ไม่ได้ลงนามลงในหน่วยความจำที่
ออฟเซ็ตที่รู้จัก pvmfw จะตรวจสอบลายเซ็น AVB และหากสำเร็จ
จะสร้าง Device Tree ที่เชื่อถือได้จาก FDT ที่ได้รับ ล้างข้อมูลลับจาก
หน่วยความจำ และแยกไปยังจุดแรกเข้าของเพย์โหลด หากขั้นตอนการยืนยันขั้นตอนใดขั้นตอนหนึ่งไม่สำเร็จ เฟิร์มแวร์จะออก SYSTEM_RESET
ไฮเปอร์คอล PSCI
ระหว่างการบูต ระบบจะจัดเก็บข้อมูลเกี่ยวกับอินสแตนซ์ pVM ไว้ในพาร์ติชัน (อุปกรณ์ virtio-blk) และเข้ารหัสด้วยข้อมูลลับของ pvmfw เพื่อให้แน่ใจว่า หลังจากการรีบูต ระบบจะจัดสรรข้อมูลลับให้กับอินสแตนซ์ที่ถูกต้อง