ผู้ให้บริการเริ่มต้น

กระบวนการ init มีสิทธิ์เกือบไม่จำกัดและใช้สคริปต์อินพุตจากทั้งพาร์ติชันของระบบและผู้ให้บริการเพื่อเริ่มต้นระบบในระหว่างกระบวนการบูต การเข้าถึงนี้ทำให้เกิดช่องโหว่ขนาดใหญ่ในการแยกส่วนระบบ/ผู้ให้บริการของ Treble เนื่องจากสคริปต์ของผู้ให้บริการอาจสั่งให้ init เข้าถึงไฟล์ พร็อพเพอร์ตี้ ฯลฯ ที่ไม่ได้เป็นส่วนหนึ่งของอินเทอร์เฟซไบนารีของแอปพลิเคชัน (ABI) ระบบ-ผู้ให้บริการที่เสถียร

init ของผู้ให้บริการได้รับการออกแบบมาเพื่อปิดช่องโหว่นี้โดยใช้โดเมน vendor_init ของ Security-Enhanced Linux (SELinux) แยกต่างหากเพื่อเรียกใช้คำสั่งที่พบใน /vendor ด้วยสิทธิ์เฉพาะของผู้ให้บริการ

กลไก

init ของผู้ให้บริการจะแยกกระบวนการย่อยของ init ในช่วงต้นของกระบวนการบูตด้วยบริบท SELinux u:r:vendor_init:s0 บริบท SELinux นี้มีสิทธิ์น้อยกว่าบริบท init เริ่มต้นอย่างมาก และการเข้าถึงจะจำกัดไว้ที่ไฟล์ พร็อพเพอร์ตี้ ฯลฯ ที่เป็นของผู้ให้บริการโดยเฉพาะหรือเป็นส่วนหนึ่งของ ABI ระบบ-ผู้ให้บริการที่เสถียร

init จะตรวจสอบสคริปต์แต่ละรายการที่โหลดเพื่อดูว่าเส้นทางเริ่มต้นด้วย /vendor หรือไม่ หากเป็นเช่นนั้น ระบบจะแท็กสคริปต์ด้วยข้อบ่งชี้ว่าต้องเรียกใช้คำสั่งในบริบท init ของผู้ให้บริการ init แต่ละรายการในตัวจะมีการใส่คำอธิบายประกอบด้วยบูลีนที่ระบุว่าต้องเรียกใช้คำสั่งในกระบวนการย่อย init ของผู้ให้บริการหรือไม่

  • คำสั่งส่วนใหญ่ที่เข้าถึงระบบไฟล์จะมีการใส่คำอธิบายประกอบให้เรียกใช้ในกระบวนการย่อย init ของผู้ให้บริการ และจึงอยู่ภายใต้ SEPolicy ของ init ของผู้ให้บริการ
  • คำสั่งส่วนใหญ่ที่ส่งผลต่อสถานะ init ภายใน (เช่น การเริ่มต้นและหยุด บริการ) จะเรียกใช้ภายในกระบวนการ init ปกติ คำสั่งเหล่านี้จะทราบว่าสคริปต์ของผู้ให้บริการกำลังเรียกใช้คำสั่งเพื่อจัดการสิทธิ์ที่ไม่ใช่ SELinux ของตนเอง

ลูปการประมวลผลหลักของ init มีการตรวจสอบว่าหากคำสั่งมีการใส่คำอธิบายประกอบให้เรียกใช้ในกระบวนการย่อยของผู้ให้บริการและมาจากสคริปต์ของผู้ให้บริการ ระบบจะส่งคำสั่งนั้นผ่านการสื่อสารระหว่างกระบวนการ (IPC) ไปยังกระบวนการย่อย init ของผู้ให้บริการ ซึ่งจะเรียกใช้คำสั่งและส่งผลลัพธ์กลับไปยัง init

ใช้ init ของผู้ให้บริการ

init ของผู้ให้บริการจะเปิดใช้โดยค่าเริ่มต้นและข้อจำกัดของ init จะมีผลกับสคริปต์ init ทั้งหมดที่อยู่ในพาร์ติชัน /vendor init ของผู้ให้บริการควรโปร่งใสสำหรับผู้ให้บริการที่สคริปต์ไม่ได้เข้าถึงไฟล์ พร็อพเพอร์ตี้ ฯลฯ ของระบบเท่านั้นอยู่แล้ว

อย่างไรก็ตาม หากคำสั่งในสคริปต์ของผู้ให้บริการละเมิดข้อจำกัดของ init ของผู้ให้บริการ คำสั่งจะล้มเหลว คำสั่งที่ล้มเหลวจะมีบรรทัดในบันทึกของเคอร์เนล (มองเห็นได้ด้วย dmesg) จาก init ที่ระบุว่าล้มเหลว การตรวจสอบ SELinux จะมาพร้อมกับคำสั่งที่ล้มเหลวเนื่องจากนโยบาย SELinux ตัวอย่างข้อผิดพลาดรวมถึงการตรวจสอบ SELinux

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

หากคำสั่งล้มเหลว คุณจะมี 2 ตัวเลือกดังนี้

  • หากคำสั่งล้มเหลวเนื่องจากข้อจำกัดที่ตั้งใจไว้ (เช่น หากคำสั่งเข้าถึงไฟล์หรือพร็อพเพอร์ตี้ของระบบ) คุณต้องนำคำสั่งไปใช้ใหม่ในลักษณะที่ใช้งานได้กับ Treble โดยผ่านอินเทอร์เฟซที่เสถียรเท่านั้น กฎ neverallow จะป้องกันไม่ให้มีการเพิ่มสิทธิ์เข้าถึงไฟล์ระบบที่ไม่ได้เป็นส่วนหนึ่งของ ABI ระบบ-ผู้ให้บริการที่เสถียร
  • หากป้ายกำกับ SELinux เป็นป้ายกำกับใหม่และยังไม่ได้รับสิทธิ์ใน vendor_init.te ของระบบหรือสิทธิ์ที่ยกเว้นผ่านกฎ neverallow ระบบอาจให้สิทธิ์ป้ายกำกับใหม่ใน vendor_init.te เฉพาะอุปกรณ์

สำหรับอุปกรณ์ที่เปิดตัวก่อน Android 9 คุณสามารถข้ามกฎ neverallow ได้โดยเพิ่มแอตทริบิวต์ประเภท data_between_core_and_vendor_violators ลงในไฟล์ vendor_init.te เฉพาะอุปกรณ์

ตำแหน่งโค้ด

ตรรกะส่วนใหญ่สำหรับ IPC ของ init ของผู้ให้บริการอยู่ใน system/core/init/subcontext.cpp

ตารางคำสั่งอยู่ในคลาส BuiltinFunctionMap ใน system/core/init/builtins.cpp และมีคำอธิบายประกอบที่ระบุว่าต้องเรียกใช้คำสั่งในกระบวนการย่อย init ของผู้ให้บริการ หรือไม่

SEPolicy สำหรับ init ของผู้ให้บริการจะแยกอยู่ในไดเรกทอรีส่วนตัว (system/sepolicy/private/vendor_init.te) และสาธารณะ (system/sepolicy/public/vendor_init.te) ใน system/sepolicy