ความเข้ากันได้ของนโยบาย

บทความนี้อธิบายวิธีที่ Android จัดการปัญหาความเข้ากันได้ของนโยบายกับ OTA ของแพลตฟอร์ม ซึ่งการตั้งค่า SELinux ของแพลตฟอร์มใหม่อาจแตกต่างจากการตั้งค่า SELinux ของผู้ให้บริการเดิม

การออกแบบนโยบาย SELinux ตาม Treble จะพิจารณาความแตกต่างแบบไบนารีระหว่างนโยบายแพลตฟอร์มกับผู้ให้บริการ รูปแบบนี้จะซับซ้อนขึ้นหากพาร์ติชันของผู้ให้บริการสร้างการพึ่งพา เช่น platform < vendor < oem

ใน Android 8.0 ขึ้นไป นโยบาย SELinux ทั่วโลกจะแบ่งออกเป็นคอมโพเนนต์แบบส่วนตัวและแบบสาธารณะ คอมโพเนนต์สาธารณะประกอบด้วยนโยบายและโครงสร้างพื้นฐานที่เกี่ยวข้อง ซึ่งรับประกันว่าพร้อมใช้งานสำหรับเวอร์ชันแพลตฟอร์ม นโยบายนี้จะแสดงต่อผู้เขียนนโยบายของผู้ให้บริการเพื่อให้ผู้ให้บริการสร้างไฟล์นโยบายของผู้ให้บริการได้ ซึ่งเมื่อรวมกับนโยบายที่แพลตฟอร์มให้ไว้แล้ว จะเป็นนโยบายที่ใช้งานได้อย่างเต็มรูปแบบสำหรับอุปกรณ์

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

Android จะจัดการการแมประหว่างประเภทที่เฉพาะเจาะจงซึ่งส่งออกในนโยบายแพลตฟอร์มกับแอตทริบิวต์เวอร์ชันที่เกี่ยวข้องสำหรับแพลตฟอร์มแต่ละเวอร์ชัน วิธีนี้ช่วยให้มั่นใจได้ว่าเมื่อติดป้ายกำกับออบเจ็กต์ด้วยประเภทหนึ่งๆ จะไม่ละเมิดลักษณะการทำงานที่รับประกันโดยนโยบายสาธารณะของแพลตฟอร์มในเวอร์ชันก่อนหน้า การแมปนี้ได้รับการดูแลรักษาโดยอัปเดตไฟล์การแมปสำหรับ เวอร์ชันแพลตฟอร์มแต่ละเวอร์ชันอยู่เสมอ ซึ่งจะเก็บข้อมูลการเป็นสมาชิกแอตทริบิวต์สำหรับประเภทต่างๆ ที่ส่งออกไว้ในนโยบายสาธารณะ

การเป็นเจ้าของและการติดป้ายกำกับวัตถุ

เมื่อปรับแต่งนโยบายใน Android 8.0 ขึ้นไป คุณต้องกําหนดการเป็นเจ้าของอย่างชัดเจนสําหรับออบเจ็กต์แต่ละรายการเพื่อแยกนโยบายแพลตฟอร์มและนโยบายของผู้ให้บริการ ตัวอย่างเช่น หากผู้ให้บริการติดป้ายกํากับ /dev/foo แล้วแพลตฟอร์มติดป้ายกํากับ /dev/foo ใน OTA ครั้งถัดไป ระบบจะแสดงลักษณะการทํางานที่ไม่มีการกําหนด สําหรับ SELinux ปัญหานี้จะแสดงเป็นความขัดแย้งในการติดป้ายกํากับ โหนดอุปกรณ์จะมีได้เพียงป้ายกำกับเดียว ซึ่งจะแสดงผลเป็นป้ายกำกับที่ใช้ล่าสุด ผลที่เกิดขึ้นมีดังนี้

  • กระบวนการที่จำเป็นต้องมีสิทธิ์เข้าถึงป้ายกำกับที่ใช้ไม่สำเร็จจะเสียสิทธิ์เข้าถึงทรัพยากร
  • กระบวนการที่ได้รับสิทธิ์เข้าถึงไฟล์อาจหยุดทำงานเนื่องจากมีการสร้างโหนดอุปกรณ์ที่ไม่ถูกต้อง

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

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

การกำหนดพื้นที่ชื่อประเภท/แอตทริบิวต์

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

type foo, domain;  type vendor_foo, domain;

สิทธิ์การเป็นเจ้าของพร็อพเพอร์ตี้ของระบบและป้ายกำกับกระบวนการ

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

ประเภทพร็อพเพอร์ตี้ คำนำหน้าที่ใช้ได้
พร็อพเพอร์ตี้การควบคุม ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
read-writable vendor.
อ่านอย่างเดียว ro.vendor.
ro.boot.
ro.hardware.
ถาวร persist.vendor.

ผู้ให้บริการสามารถใช้ ro.boot.* (ซึ่งมาจากเคอร์เนล cmdline) และ ro.hardware.* (พร็อพเพอร์ตี้ที่เกี่ยวข้องกับฮาร์ดแวร์อย่างชัดเจน) ต่อไปได้

บริการทั้งหมดของเวนเดอร์ในไฟล์ init rc ควรมี vendor. for services in init rc files of non-system partitions ระบบจะใช้กฎที่คล้ายกันกับป้ายกำกับ SELinux สำหรับพร็อพเพอร์ตี้ของผู้ให้บริการ (vendor_สำหรับพร็อพเพอร์ตี้ของผู้ให้บริการ)

การเป็นเจ้าของไฟล์

การป้องกันการทับซ้อนของไฟล์เป็นเรื่องยาก เนื่องจากทั้งนโยบายแพลตฟอร์มและนโยบายของผู้ให้บริการมักกำหนดป้ายกำกับสำหรับระบบไฟล์ทั้งหมด ต่างจากการตั้งชื่อประเภท การจัดสรรพื้นที่ชื่อของไฟล์นั้นไม่เหมาะที่จะใช้เนื่องจากมีไฟล์จำนวนมากที่สร้างโดยเคอร์เนล หากต้องการหลีกเลี่ยงข้อขัดแย้งเหล่านี้ ให้ทําตามคําแนะนําการตั้งชื่อสำหรับระบบไฟล์ในส่วนนี้ สำหรับ Android 8.0 คำแนะนำเหล่านี้เป็นเพียงคำแนะนำที่ไม่มีการดำเนินการทางเทคนิค ในอนาคต ชุดทดสอบของผู้ให้บริการ (VTS) จะบังคับใช้คําแนะนําเหล่านี้

ระบบ (/system)

เฉพาะภาพระบบเท่านั้นที่ต้องระบุป้ายกำกับสำหรับคอมโพเนนต์ /system ผ่าน file_contexts, service_contexts ฯลฯ หากเพิ่มป้ายกำกับสำหรับคอมโพเนนต์ /system ในนโยบาย /vendor การอัปเดต OTA เฉพาะเฟรมเวิร์กอาจไม่สามารถทำได้

ผู้ให้บริการ (/vendor)

นโยบาย SELinux ของ AOSP ติดป้ายกำกับบางส่วนของvendorพาร์ติชันที่แพลตฟอร์มโต้ตอบด้วยอยู่แล้ว ซึ่งช่วยให้สามารถเขียนกฎ SELinux สำหรับกระบวนการของแพลตฟอร์มเพื่อพูดคุยและ/หรือเข้าถึงบางส่วนของvendorพาร์ติชันได้ ตัวอย่าง

เส้นทาง /vendor ป้ายกำกับที่แพลตฟอร์มระบุ กระบวนการของแพลตฟอร์มจะขึ้นอยู่กับป้ายกํากับ
/vendor(/.*)? vendor_file ไคลเอ็นต์ HAL ทั้งหมดในเฟรมเวิร์ก, ueventd ฯลฯ
/vendor/framework(/.*)? vendor_framework_file dex2oat, appdomain ฯลฯ
/vendor/app(/.*)? vendor_app_file dex2oat, installd, idmap ฯลฯ
/vendor/overlay(/.*) vendor_overlay_file system_server, zygote, idmap ฯลฯ

คุณจึงต้องปฏิบัติตามกฎที่เฉพาะเจาะจง (บังคับใช้ผ่าน neverallows) เมื่อติดป้ายกำกับไฟล์เพิ่มเติมในพาร์ติชัน vendor ดังนี้

  • vendor_file ต้องเป็นป้ายกำกับเริ่มต้นสำหรับไฟล์ทั้งหมดในพาร์ติชัน vendor นโยบายแพลตฟอร์มกำหนดให้ต้องดำเนินการนี้เพื่อเข้าถึงการใช้งาน HAL แบบส่งผ่าน
  • exec_types ใหม่ทั้งหมดที่เพิ่มในพาร์ติชัน vendor ผ่าน SEPolicy ของผู้ให้บริการต้องมีแอตทริบิวต์ vendor_file_type ซึ่งบังคับใช้ผ่าน neverallows
  • หลีกเลี่ยงการติดป้ายกำกับไฟล์ที่ไม่ใช่ exec_types ในพาร์ติชัน vendor เพื่อไม่ให้เกิดความขัดแย้งกับการอัปเดตแพลตฟอร์ม/เฟรมเวิร์กในอนาคต
  • ไลบรารีทั้งหมดที่ต้องพึ่งพาสำหรับ HAL ของกระบวนการเดียวกันที่ AOSP ระบุต้องติดป้ายกํากับเป็น same_process_hal_file.

Procfs (/proc)

ไฟล์ใน /proc อาจมีป้ายกำกับโดยใช้เฉพาะป้ายกำกับ genfsconเท่านั้น ใน Android 7.0 ทั้งนโยบายแพลตฟอร์มและผู้ให้บริการใช้ genfscon เพื่อติดป้ายกำกับไฟล์ใน procfs

คําแนะนํา: ป้ายกํากับนโยบายแพลตฟอร์ม /proc เท่านั้น หากกระบวนการ vendor จำเป็นต้องเข้าถึงไฟล์ใน /proc ที่ตอนนี้ติดป้ายกำกับด้วยป้ายกำกับเริ่มต้น (proc) นโยบายของผู้ให้บริการไม่ควรติดป้ายกำกับกระบวนการเหล่านั้นอย่างชัดเจน แต่ควรใช้ประเภท proc ทั่วไปเพื่อเพิ่มกฎสำหรับโดเมนของผู้ให้บริการแทน ซึ่งจะช่วยให้การอัปเดตแพลตฟอร์มรองรับอินเทอร์เฟซเคอร์เนลในอนาคตที่แสดงผ่าน procfs และติดป้ายกำกับอย่างชัดเจนตามต้องการ

Debugfs (/sys/kernel/debug)

Debugfs สามารถติดป้ายกำกับได้ทั้ง file_contexts และ genfscon ใน Android 7.0 ถึง Android 10 จะมีทั้งป้ายกำกับแพลตฟอร์มและป้ายกำกับผู้ให้บริการ debugfs

ใน Android 11 คุณจะเข้าถึงหรือต่อเชื่อม debugfs ในอุปกรณ์เวอร์ชันที่ใช้งานจริงไม่ได้ ผู้ผลิตอุปกรณ์ควรนํา debugfs ออก

Tracefs (/sys/kernel/debug/tracing)

Tracefs สามารถติดป้ายกำกับได้ทั้ง file_contexts และ genfscon ใน Android 7.0 เฉพาะป้ายกำกับแพลตฟอร์มเท่านั้นที่จะแสดง tracefs

คําแนะนํา: มีเพียงแพลตฟอร์มเท่านั้นที่สามารถติดป้ายกํากับ tracefs

Sysfs (/sys)

ไฟล์ใน /sys อาจติดป้ายกำกับโดยใช้ทั้ง file_contexts และ genfscon ใน Android 7.0 ทั้งแพลตฟอร์มและผู้ให้บริการใช้ genfscon เพื่อติดป้ายกำกับไฟล์ใน sysfs

คําแนะนํา: แพลตฟอร์มอาจติดป้ายกํากับsysfs โหนดที่ไม่ได้เจาะจงอุปกรณ์ ไม่เช่นนั้น เฉพาะผู้ให้บริการเท่านั้นที่จะติดป้ายกำกับไฟล์ได้

tmpfs (/dev)

ไฟล์ใน /dev อาจติดป้ายกำกับใน file_contexts ใน Android 7.0 ทั้งไฟล์ป้ายกำกับแพลตฟอร์มและผู้ให้บริการจะอยู่ที่นี่

คําแนะนํา: ผู้ให้บริการอาจติดป้ายกํากับเฉพาะไฟล์ใน/dev/vendor (เช่น /dev/vendor/foo, /dev/vendor/socket/bar)

Rootfs (/)

ไฟล์ใน / อาจติดป้ายกำกับใน file_contexts ใน Android 7.0 ทั้งไฟล์ป้ายกำกับแพลตฟอร์มและผู้ให้บริการจะอยู่ที่นี่

คําแนะนํา: มีเพียงระบบเท่านั้นที่จะติดป้ายกํากับไฟล์ใน / ได้

ข้อมูล (/data)

ระบบจะติดป้ายกำกับข้อมูลโดยใช้ file_contexts และ seapp_contexts

คําแนะนํา: ไม่อนุญาตให้ติดป้ายกำกับผู้ให้บริการภายนอก /data/vendor เฉพาะแพลตฟอร์มเท่านั้นที่สามารถติดป้ายกำกับส่วนอื่นๆ ของ /data

เวอร์ชันป้ายกำกับ Genfs

ตั้งแต่วันที่ ระดับ API ของผู้ให้บริการ 202504 เป็นต้นไป ป้ายกำกับ SELinux รุ่นใหม่ที่กำหนดด้วย genfscon ใน system/sepolicy/compat/plat_sepolicy_genfs_{ver}.cil จะเป็นตัวเลือกสำหรับพาร์ติชันของผู้ให้บริการรุ่นเก่า ซึ่งจะช่วยให้พาร์ติชันของผู้ให้บริการรุ่นเก่าใช้ SEPolicy ที่มีอยู่ต่อไปได้ การดำเนินการนี้ควบคุมโดยตัวแปร Makefile BOARD_GENFS_LABELS_VERSION ซึ่งจัดเก็บอยู่ใน /vendor/etc/selinux/genfs_labels_version.txt

ตัวอย่าง

  • ใน API ของผู้ให้บริการระดับ 202404 โหนด /sys/class/udc จะมีป้ายกำกับเป็น sysfs โดยค่าเริ่มต้น
  • ตั้งแต่ API ระดับ 202504 เป็นต้นไป /sys/class/udc จะมีป้ายกำกับว่า sysfs_udc

อย่างไรก็ตาม พาร์ติชันของผู้ให้บริการที่ใช้ API ระดับ 202404 อาจใช้ /sys/class/udc อยู่ ไม่ว่าจะใช้ป้ายกํากับ sysfs เริ่มต้นหรือป้ายกํากับเฉพาะผู้ให้บริการ การติดป้ายกํากับ /sys/class/udc เป็น sysfs_udc โดยไม่มีเงื่อนไขอาจทําให้เกิดความเข้ากันไม่ได้กับพาร์ติชันของผู้ให้บริการเหล่านี้ การเลือก BOARD_GENFS_LABELS_VERSION จะทำให้แพลตฟอร์มใช้ป้ายกำกับและสิทธิ์ก่อนหน้าสำหรับพาร์ติชันของผู้ให้บริการเดิมต่อไป

BOARD_GENFS_LABELS_VERSION มากกว่าหรือเท่ากับระดับ API ของผู้ให้บริการได้ ตัวอย่างเช่น พาร์ติชันของผู้ให้บริการที่ใช้ API ระดับ 202404 สามารถตั้งค่า BOARD_GENFS_LABELS_VERSION เป็น 202504 เพื่อใช้ป้ายกำกับใหม่ที่เปิดตัวในปี 202504 ดูรายการ ป้ายกำกับ genfs สำหรับ 202504 โดยเฉพาะ

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

แอตทริบิวต์ความเข้ากันได้

นโยบาย SELinux คือการโต้ตอบระหว่างประเภทแหล่งที่มาและเป้าหมายสําหรับคลาสออบเจ็กต์และสิทธิ์ที่เฉพาะเจาะจง ออบเจ็กต์ทุกรายการ (กระบวนการ ไฟล์ ฯลฯ) ที่ได้รับผลกระทบจากนโยบาย SELinux อาจมีเพียงประเภทเดียว แต่ประเภทนั้นอาจมีแอตทริบิวต์หลายรายการ

นโยบายส่วนใหญ่เขียนขึ้นโดยอิงตามประเภทที่มีอยู่ ดังนี้

allow source_type target_type:target_class permission(s);

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

File_contexts:
/sys/A   u:object_r:sysfs:s0
Platform: allow p_domain sysfs:class perm;
Vendor: allow v_domain sysfs:class perm;

อาจเปลี่ยนเป็น

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

แม้ว่านโยบายของผู้ให้บริการจะยังคงเหมือนเดิม แต่ v_domain จะเสียสิทธิ์เข้าถึงเนื่องจากไม่มีนโยบายสำหรับ sysfs_A ประเภทใหม่

การกําหนดนโยบายในแง่ของแอตทริบิวต์ช่วยให้เรากําหนดประเภทออบเจ็กต์พื้นฐานซึ่งมีแอตทริบิวต์ที่สอดคล้องกับนโยบายสําหรับทั้งแพลตฟอร์มและรหัสผู้ให้บริการได้ ซึ่งทําได้กับทุกประเภทเพื่อสร้างattribute-policy ที่มีประสิทธิภาพโดยที่ไม่ต้องการใช้ประเภทที่เฉพาะเจาะจง ในทางปฏิบัติแล้ว ขั้นตอนนี้จำเป็นเฉพาะกับส่วนของนโยบายที่ทับซ้อนกันระหว่างแพลตฟอร์มและผู้ให้บริการ ซึ่งมีการกําหนดและระบุเป็นนโยบายสาธารณะของแพลตฟอร์มที่สร้างขึ้นเป็นส่วนหนึ่งของนโยบายของผู้ให้บริการ

การกําหนดนโยบายสาธารณะเป็นแอตทริบิวต์ที่มีเวอร์ชันจะบรรลุเป้าหมายความเข้ากันได้ของนโยบาย 2 ประการ ดังนี้

  • ตรวจสอบว่าโค้ดของผู้ให้บริการยังคงทำงานต่อไปได้หลังจากอัปเดตแพลตฟอร์ม ซึ่งทำได้โดยการเพิ่มแอตทริบิวต์ไปยังประเภทที่เฉพาะเจาะจงสำหรับออบเจ็กต์ที่สอดคล้องกับออบเจ็กต์ที่โค้ดของผู้ให้บริการใช้อยู่ ซึ่งจะรักษาสิทธิ์เข้าถึงไว้
  • ความสามารถในการเลิกใช้งานนโยบาย ซึ่งทำได้โดยการแบ่งชุดนโยบายออกเป็นแอตทริบิวต์ที่นําออกได้ทันทีที่ระบบไม่รองรับเวอร์ชันที่เกี่ยวข้องอีกต่อไป การพัฒนาจะยังดำเนินต่อไปในแพลตฟอร์มได้ โดยที่นโยบายเก่าจะยังคงอยู่ในนโยบายของผู้ให้บริการและจะถูกนำออกโดยอัตโนมัติเมื่อ/หากมีการอัปเกรด

ความสามารถในการเขียนนโยบาย

Android 8.0 มีการแมประหว่างประเภทนโยบายสาธารณะของแพลตฟอร์มกับแอตทริบิวต์ของนโยบายเพื่อบรรลุเป้าหมายที่ไม่จำเป็นต้องมีความรู้เกี่ยวกับการเปลี่ยนแปลงเวอร์ชันที่เฉพาะเจาะจงสำหรับการพัฒนานโยบาย ประเภท foo แมปกับแอตทริบิวต์ foo_vN โดยที่ N คือเวอร์ชันที่กำหนดเป้าหมาย vN สอดคล้องกับตัวแปรบิลด์ PLATFORM_SEPOLICY_VERSION และมีรูปแบบเป็น MM.NN โดยที่ MM สอดคล้องกับหมายเลข SDK ของแพลตฟอร์ม และ NN เป็นเวอร์ชันเฉพาะของนโยบายความปลอดภัยของแพลตฟอร์ม

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

นโยบายสาธารณะของแพลตฟอร์มที่ส่งออกเป็น allow source_foo target_bar:class perm; จะรวมอยู่ในนโยบายของผู้ขาย ในระหว่างการคอมไพล์ (ซึ่งรวมถึงเวอร์ชันที่เกี่ยวข้อง) ระบบจะเปลี่ยนรูปแบบนโยบายที่จะส่งไปยังส่วนที่เป็นของผู้ให้บริการของอุปกรณ์ (แสดงใน Common Intermediate Language (CIL) ที่เปลี่ยนรูปแบบแล้ว) ดังนี้

 (allow source_foo_vN target_bar_vN (class (perm)))

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

ความแตกต่างของนโยบาย

การสร้างแอตทริบิวต์โดยอัตโนมัติโดยการเพิ่ม _vN ต่อท้ายแอตทริบิวต์แต่ละประเภทจะไม่ทํางานหากไม่มีการแมปแอตทริบิวต์กับประเภทต่างๆ ในความแตกต่างของเวอร์ชัน Android จะเก็บรักษาการแมประหว่างเวอร์ชันสำหรับแอตทริบิวต์และการแมปประเภทกับแอตทริบิวต์เหล่านั้น ซึ่งทำได้ในไฟล์การแมปที่กล่าวถึงข้างต้นโดยใช้คำสั่ง เช่น (CIL)

(typeattributeset foo_vN (foo))

การอัปเกรดแพลตฟอร์ม

ส่วนต่อไปนี้แสดงรายละเอียดสถานการณ์การอัปเกรดแพลตฟอร์ม

ประเภทเดียวกัน

สถานการณ์นี้เกิดขึ้นเมื่อออบเจ็กต์ไม่เปลี่ยนป้ายกำกับในเวอร์ชันนโยบาย ซึ่งจะเหมือนกันสำหรับประเภทแหล่งที่มาและเป้าหมาย และสามารถดูได้กับ /dev/binder ที่มีป้ายกำกับ binder_device ในรุ่นทั้งหมด ซึ่งจะแสดงในนโยบายที่แปลงแล้วดังนี้

binder_device_v1 … binder_device_vN

เมื่ออัปเกรดจาก v1v2 นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้

type binder_device; -> (type binder_device) (in CIL)

ในไฟล์การแมป v1 (CIL)

(typeattributeset binder_device_v1 (binder_device))

ในไฟล์การแมป v2 (CIL) ให้ทำดังนี้

(typeattributeset binder_device_v2 (binder_device))

ในนโยบายผู้ให้บริการ v1 (CIL)

(typeattribute binder_device_v1)
(allow binder_device_v1 )

ในนโยบายผู้ให้บริการ v2 (CIL)

(typeattribute binder_device_v2)
(allow binder_device_v2 )
ประเภทใหม่

สถานการณ์นี้เกิดขึ้นเมื่อแพลตฟอร์มเพิ่มประเภทใหม่ ซึ่งอาจเกิดขึ้นเมื่อเพิ่มฟีเจอร์ใหม่หรือระหว่างการทำให้นโยบายเข้มงวด

  • ฟีเจอร์ใหม่ เมื่อประเภทติดป้ายกำกับออบเจ็กต์ที่ไม่มีอยู่ก่อนหน้านี้ (เช่น กระบวนการบริการใหม่) โค้ดของผู้ให้บริการก่อนหน้านี้ไม่ได้โต้ตอบกับออบเจ็กต์ดังกล่าวโดยตรง จึงไม่มีนโยบายที่เกี่ยวข้อง แอตทริบิวต์ใหม่ซึ่งสอดคล้องกับประเภทนั้นไม่มีแอตทริบิวต์ในเวอร์ชันก่อนหน้า จึงไม่จำเป็นต้องมีรายการในไฟล์การแมปที่กำหนดเป้าหมายเป็นเวอร์ชันนั้น
  • การทำให้นโยบายมีความปลอดภัยมากขึ้น เมื่อประเภทแสดงถึงนโยบายการเพิ่มความเข้มงวด แอตทริบิวต์ประเภทใหม่ต้องลิงก์กลับไปยังเชนแอตทริบิวต์ที่สอดคล้องกับแอตทริบิวต์ก่อนหน้า (คล้ายกับตัวอย่างก่อนหน้านี้ที่เปลี่ยน /sys/A จาก sysfs เป็น sysfs_A) โค้ดของผู้ให้บริการใช้กฎที่เปิดใช้การเข้าถึง sysfs และต้องรวมกฎนั้นไว้เป็นแอตทริบิวต์ของประเภทใหม่

เมื่ออัปเกรดจาก v1v2 นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้

type sysfs_A; -> (type sysfs_A) (in CIL)
type sysfs; (type sysfs) (in CIL)

ในไฟล์การแมป v1 (CIL)

(typeattributeset sysfs_v1 (sysfs sysfs_A))

ในไฟล์การแมป v2 (CIL) ให้ทำดังนี้

(typeattributeset sysfs_v2 (sysfs))
(typeattributeset sysfs_A_v2 (sysfs_A))

ในนโยบายผู้ให้บริการ v1 (CIL)

(typeattribute sysfs_v1)
(allow  sysfs_v1 )

ในนโยบายผู้ให้บริการ v2 (CIL)

(typeattribute sysfs_A_v2)
(allow  sysfs_A_v2 )
(typeattribute sysfs_v2)
(allow  sysfs_v2 )
ประเภทที่นําออก

สถานการณ์ (ที่พบไม่บ่อย) นี้เกิดขึ้นเมื่อนำประเภทออก ซึ่งอาจเกิดขึ้นเมื่อออบเจ็กต์พื้นฐานมีลักษณะดังนี้

  • ยังคงอยู่แต่ได้รับป้ายกำกับอื่น
  • ถูกนำออกโดยแพลตฟอร์ม

ในระหว่างการผ่อนปรนนโยบาย ระบบจะนำประเภทหนึ่งออกและให้ป้ายกำกับอื่นที่มีอยู่แล้วกับออบเจ็กต์ที่ติดป้ายกำกับประเภทนั้น ซึ่งแสดงถึงการผสานการแมปแอตทริบิวต์: รหัสของผู้ให้บริการต้องยังคงเข้าถึงออบเจ็กต์พื้นฐานได้ด้วยแอตทริบิวต์ที่เคยมี แต่ตอนนี้ระบบส่วนที่เหลือต้องเข้าถึงออบเจ็กต์ดังกล่าวได้ด้วยแอตทริบิวต์ใหม่

หากแอตทริบิวต์ที่เปลี่ยนไปเป็นแอตทริบิวต์ใหม่ การติดป้ายกำกับใหม่จะเหมือนกับในกรณีที่เป็นประเภทใหม่ ยกเว้นในกรณีที่ใช้ป้ายกำกับที่มีอยู่ การเพิ่มแอตทริบิวต์เดิมเป็นประเภทใหม่จะทำให้ออบเจ็กต์อื่นๆ ที่ติดป้ายกำกับประเภทนี้ด้วยเข้าถึงได้ใหม่ ซึ่งโดยพื้นฐานแล้วคือสิ่งที่แพลตฟอร์มทำและถือว่าเป็นการแลกเปลี่ยนที่ยอมรับได้เพื่อรักษาความเข้ากันได้

(typeattribute sysfs_v1)
(allow  sysfs_v1 )

ตัวอย่างเวอร์ชัน 1: การยุบประเภท (การนำ sysfs_A ออก)

เมื่ออัปเกรดจาก v1v2 นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้

type sysfs; (type sysfs) (in CIL)

ในไฟล์การแมป v1 (CIL)

(typeattributeset sysfs_v1 (sysfs))
(type sysfs_A) # in case vendors used the sysfs_A label on objects
(typeattributeset sysfs_A_v1 (sysfs sysfs_A))

ในไฟล์การแมป v2 (CIL) ให้ทำดังนี้

(typeattributeset sysfs_v2 (sysfs))

ในนโยบายผู้ให้บริการ v1 (CIL)

(typeattribute sysfs_A_v1)
(allow  sysfs_A_v1 )
(typeattribute sysfs_v1)
(allow  sysfs_v1 )

ในนโยบายผู้ให้บริการ v2 (CIL)

(typeattribute sysfs_v2)
(allow  sysfs_v2 )

ตัวอย่างเวอร์ชัน 2: การนำออกทั้งหมด (ประเภท foo)

เมื่ออัปเกรดจาก v1v2 นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้

# nothing - we got rid of the type

ในไฟล์การแมป v1 (CIL)

(type foo) #needed in case vendors used the foo label on objects
(typeattributeset foo_v1 (foo))

ในไฟล์การแมป v2 (CIL) ให้ทำดังนี้

# nothing - get rid of it

ในนโยบายผู้ให้บริการ v1 (CIL)

(typeattribute foo_v1)
(allow foo )
(typeattribute sysfs_v1)
(allow sysfs_v1 )

ในนโยบายผู้ให้บริการ v2 (CIL)

(typeattribute sysfs_v2)
(allow sysfs_v2 )
ชั้นเรียน/สิทธิ์ใหม่

สถานการณ์นี้เกิดขึ้นเมื่อการอัปเกรดแพลตฟอร์มมีการใช้คอมโพเนนต์นโยบายใหม่ซึ่งไม่มีในเวอร์ชันก่อนหน้า ตัวอย่างเช่น เมื่อ Android เพิ่มservicemanagerตัวจัดการออบเจ็กต์ที่สร้างสิทธิ์เพิ่ม ค้นหา และแสดงรายการ โปรแกรมเดรัมของบริษัทที่ต้องการลงทะเบียนกับservicemanagerสิทธิ์ที่จําเป็นจะใช้งานไม่ได้ ใน Android 8.0 เฉพาะนโยบายแพลตฟอร์มเท่านั้นที่จะเพิ่มคลาสและสิทธิ์ใหม่ได้

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

allow {domain -coredomain} *:new_class perm;

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

นำชั้นเรียน/สิทธิ์ออกแล้ว

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

การปรับแต่งของผู้ให้บริการสำหรับประเภทใหม่/ที่ติดป้ายกำกับใหม่

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

เนื่องจากนโยบายของผู้ให้บริการเป็นนโยบายที่เก่าที่สุดในอุปกรณ์เสมอ คุณจึงไม่จำเป็นต้องแปลงประเภทผู้ให้บริการทั้งหมดเป็นแอตทริบิวต์ในนโยบายโดยอัตโนมัติ แพลตฟอร์มไม่ได้ใช้ข้อมูลที่มีป้ายกำกับในนโยบายของผู้ให้บริการเนื่องจากแพลตฟอร์มไม่มีข้อมูลเกี่ยวกับข้อมูลดังกล่าว อย่างไรก็ตาม แพลตฟอร์มจะระบุแอตทริบิวต์และประเภทสาธารณะที่ใช้เพื่อโต้ตอบกับออบเจ็กต์ที่ติดป้ายกำกับด้วยประเภทเหล่านี้ (เช่น domain, sysfs_type ฯลฯ) หากต้องการให้แพลตฟอร์มโต้ตอบกับออบเจ็กต์เหล่านี้อย่างถูกต้องต่อไป คุณต้องใช้แอตทริบิวต์และประเภทอย่างเหมาะสม และอาจต้องเพิ่มกฎที่เฉพาะเจาะจงลงในโดเมนที่ปรับแต่งได้ (เช่น init)

การเปลี่ยนแปลงแอตทริบิวต์สําหรับ Android 9

อุปกรณ์ที่อัปเกรดเป็น Android 9 สามารถใช้แอตทริบิวต์ต่อไปนี้ได้ แต่อุปกรณ์ที่เปิดตัวด้วย Android 9 จะใช้ไม่ได้

แอตทริบิวต์ผู้ละเมิด

Android 9 มีแอตทริบิวต์ที่เกี่ยวข้องกับโดเมนต่อไปนี้

  • data_between_core_and_vendor_violators แอตทริบิวต์สำหรับโดเมนทั้งหมดที่ละเมิดข้อกำหนดในการไม่แชร์ไฟล์ตามเส้นทางระหว่าง vendor และ coredomains กระบวนการของแพลตฟอร์มและผู้ให้บริการไม่ควรใช้ไฟล์บนดิสก์เพื่อสื่อสาร (ABI ไม่เสถียร) คําแนะนํา
    • รหัสผู้ให้บริการควรใช้ /data/vendor
    • ระบบไม่ควรใช้ /data/vendor
  • แอตทริบิวต์ system_executes_vendor_violators สำหรับโดเมนของระบบทั้งหมด (ยกเว้น init และ shell domains) ที่ละเมิดข้อกำหนดในการไม่เรียกใช้ไบนารีของผู้ให้บริการ การดำเนินการกับไบนารีของผู้ให้บริการมี API ที่ไม่เสถียร แพลตฟอร์มไม่ควรเรียกใช้ไบนารีของผู้ให้บริการโดยตรง คําแนะนํา
    • แพลตฟอร์มที่ต้องใช้ไบนารีของผู้ให้บริการต้องอยู่หลัง HAL ของ HIDL

      หรือ

    • coredomains ที่ต้องการเข้าถึงไบนารีของผู้ให้บริการควรย้ายไปยังพาร์ติชันของผู้ให้บริการและจึงจะหยุดเป็น coredomain

แอตทริบิวต์ที่ไม่น่าเชื่อถือ

แอปที่ไม่น่าเชื่อถือซึ่งโฮสต์โค้ดที่ไม่รู้จักไม่ควรมีสิทธิ์เข้าถึงบริการ HwBinder ยกเว้นบริการที่ถือว่าปลอดภัยเพียงพอสำหรับการเข้าถึงจากแอปดังกล่าว (ดูบริการที่ปลอดภัยด้านล่าง) สาเหตุหลัก 2 ประการมีดังนี้

  1. เซิร์ฟเวอร์ HwBinder จะไม่ตรวจสอบสิทธิ์ไคลเอ็นต์เนื่องจากปัจจุบัน HIDL ไม่ได้เปิดเผยข้อมูล UID ของผู้เรียก แม้ว่า HIDL จะแสดงข้อมูลดังกล่าว แต่บริการ HwBinder จำนวนมากจะทำงานในระดับที่ต่ำกว่าแอป (เช่น HAL) หรือต้องไม่อาศัยข้อมูลประจำตัวของแอปเพื่อขอสิทธิ์ ดังนั้น เพื่อเป็นการป้องกันไว้ก่อน ระบบจะถือว่าบริการ HwBinder ทั้งหมดถือว่าลูกค้าทุกรายได้รับสิทธิ์อย่างเท่าเทียมกันในการดําเนินการต่างๆ ที่บริการเสนอ
  2. เซิร์ฟเวอร์ HAL (ชุดย่อยของบริการ HwBinder) มีโค้ดที่มีอัตราการเกิดปัญหาด้านความปลอดภัยสูงกว่าคอมโพเนนต์ system/core และมีสิทธิ์เข้าถึงเลเยอร์ล่างของสแต็ก (ไปจนถึงระดับฮาร์ดแวร์) จึงเพิ่มโอกาสในการหลบเลี่ยงรูปแบบการรักษาความปลอดภัยของ Android

บริการตู้เซฟ

บริการที่ปลอดภัย ได้แก่

  • same_process_hwservice. บริการเหล่านี้ (ตามคำจำกัดความ) จะทำงานในกระบวนการของไคลเอ็นต์ จึงมีสิทธิ์เข้าถึงเช่นเดียวกับโดเมนไคลเอ็นต์ที่กระบวนการทำงาน
  • coredomain_hwservice บริการเหล่านี้ไม่มีความเสี่ยงที่เชื่อมโยงกับเหตุผลที่ 2
  • hal_configstore_ISurfaceFlingerConfigs บริการนี้ออกแบบมาเพื่อการใช้งานโดยโดเมนใดก็ได้โดยเฉพาะ
  • hal_graphics_allocator_hwservice นอกจากนี้ surfaceflinger Binder Service ยังให้บริการการดำเนินการเหล่านี้ด้วย ซึ่งแอปได้รับอนุญาตให้เข้าถึง
  • hal_omx_hwservice. นี่คือบริการ mediacodec Binder เวอร์ชัน HwBinder ซึ่งแอปได้รับอนุญาตให้เข้าถึง
  • hal_codec2_hwservice ซึ่งเป็นhal_omx_hwserviceเวอร์ชันใหม่

แอตทริบิวต์ที่ใช้งานได้

hwservices ทั้งหมดที่ไม่ถือว่าปลอดภัยจะมีแอตทริบิวต์ untrusted_app_visible_hwservice เซิร์ฟเวอร์ HAL ที่เกี่ยวข้องมีแอตทริบิวต์ untrusted_app_visible_halserver อุปกรณ์ที่เปิดตัวด้วย Android 9 ต้องไม่ใช้แอตทริบิวต์ untrusted

คำแนะนำ

  • แอปที่ไม่น่าเชื่อถือควรสื่อสารกับบริการระบบที่สื่อสารกับ HIDL HAL ของผู้ให้บริการแทน ตัวอย่างเช่น แอปสามารถสื่อสารกับ binderservicedomain จากนั้น mediaserver (ซึ่งเป็น binderservicedomain) จะสื่อสารกับ hal_graphics_allocator

    หรือ

  • แอปที่ต้องการเข้าถึง vendor HAL โดยตรงควรมีโดเมนนโยบายความปลอดภัยที่ระบุโดยผู้ให้บริการของตนเอง

การทดสอบแอตทริบิวต์ไฟล์

Android 9 มีการทดสอบเวลาสร้างเพื่อให้มั่นใจว่าไฟล์ทั้งหมดในตำแหน่งที่เจาะจงมีแอตทริบิวต์ที่เหมาะสม (เช่น ไฟล์ทั้งหมดในsysfsมีแอตทริบิวต์ sysfs_type ที่จำเป็น)

นโยบายสาธารณะของแพลตฟอร์ม

นโยบายสาธารณะของแพลตฟอร์มเป็นหัวใจสำคัญของการปฏิบัติตามรูปแบบสถาปัตยกรรม Android 8.0 โดยไม่ต้องรักษาการรวมนโยบายแพลตฟอร์มจากเวอร์ชัน 1 และ 2 ไว้ ผู้ให้บริการรายย่อยจะเห็นนโยบายแพลตฟอร์มชุดย่อยซึ่งมีประเภทและแอตทริบิวต์ที่ใช้ได้ รวมถึงกฎเกี่ยวกับประเภทและแอตทริบิวต์เหล่านั้น ซึ่งจะกลายเป็นส่วนหนึ่งของนโยบายของผู้ให้บริการรายย่อย (นั่นคือ vendor_sepolicy.cil)

ระบบจะแปลประเภทและกฎในนโยบายที่ผู้ให้บริการสร้างขึ้นเป็น attribute_vN โดยอัตโนมัติ เพื่อให้ประเภททั้งหมดที่แพลตฟอร์มระบุเป็นแอตทริบิวต์ที่มีเวอร์ชัน (แต่แอตทริบิวต์จะไม่มีเวอร์ชัน) แพลตฟอร์มมีหน้าที่รับผิดชอบในการแมปประเภทที่เฉพาะเจาะจงที่ระบุไว้ในแอตทริบิวต์ที่เหมาะสม เพื่อให้นโยบายของผู้ให้บริการทำงานต่อไปได้และรวมกฎที่ระบุไว้สำหรับเวอร์ชันหนึ่งๆ ไว้ด้วย การรวมนโยบายสาธารณะของแพลตฟอร์มและนโยบายของผู้ให้บริการเป็นไปตามเป้าหมายรูปแบบสถาปัตยกรรม Android 8.0 ในการอนุญาตให้สร้างแพลตฟอร์มและผู้ให้บริการอิสระ

การแมปกับเชนแอตทริบิวต์

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

การรักษาเป้าหมายในการซ่อนข้อมูลเวอร์ชันจากผู้เขียนนโยบายหมายความว่าจะต้องสร้างแอตทริบิวต์เวอร์ชันและกำหนดแอตทริบิวต์เหล่านั้นให้กับประเภทที่เหมาะสมโดยอัตโนมัติ ในกรณีทั่วไปของประเภทแบบคงที่ การดำเนินการนี้จะตรงไปตรงมา นั่นคือ type_foo จะแมปกับ type_foo_v1

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

การอัปเกรดเวอร์ชัน

แพลตฟอร์ม Android จะเผยแพร่เวอร์ชัน sepolicy เมื่อมีการแยกสาขารุ่นใหม่ออกเพื่อความสะดวก ดังที่อธิบายไว้ข้างต้น หมายเลขเวอร์ชันจะอยู่ใน PLATFORM_SEPOLICY_VERSION และมีรูปแบบเป็น MM.nn โดยที่ MM สอดคล้องกับค่า SDK และ nn เป็นค่าส่วนตัวที่จัดเก็บไว้ใน /platform/system/sepolicy. เช่น 19.0 สำหรับ Kitkat, 21.0 สำหรับ Lollipop, 22.0 สำหรับ Lollipop-MR1, 23.0 สำหรับ Marshmallow, 24.0 สำหรับ Nougat, 25.0 สำหรับ Nougat-MR1, 26.0 สำหรับ Oreo, 27.0 สำหรับ Oreo-MR1 และ 28.0 สำหรับ Android 9 Uprev ไม่ได้เป็นจํานวนเต็มเสมอไป ตัวอย่างเช่น หากการอัปเกรด MR เป็นเวอร์ชันหนึ่งๆ จำเป็นต้องมีการเปลี่ยนแปลงที่เข้ากันไม่ได้ใน system/sepolicy/public แต่ไม่ใช่การอัปเกรด API เวอร์ชันของ sepolicy นั้นอาจเป็น vN.1 เวอร์ชันที่อยู่ในสาขาการพัฒนาคือ 10000.0 ที่จะไม่เคยใช้ในอุปกรณ์ที่พร้อมจำหน่าย

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

ผลกระทบต่อประสิทธิภาพของแอตทริบิวต์หลายรายการ

ตามที่อธิบายไว้ใน https://github.com/SELinuxProject/cil/issues/9 การกําหนดแอตทริบิวต์จํานวนมากให้กับประเภทหนึ่งๆ จะทําให้เกิดปัญหาด้านประสิทธิภาพในกรณีที่แคชนโยบายไม่พบ

ปัญหานี้ได้รับการยืนยันว่าเป็นปัญหาใน Android เราจึงทำการเปลี่ยนแปลงใน Android 8.0 เพื่อนำแอตทริบิวต์ที่คอมไพเลอร์นโยบายเพิ่มลงในนโยบายออก รวมถึงนำแอตทริบิวต์ที่ไม่ได้ใช้ออก การเปลี่ยนแปลงเหล่านี้ช่วยแก้ปัญหาการถดถอยของประสิทธิภาพ

นโยบายสาธารณะสำหรับระบบ_ext และผลิตภัณฑ์

ตั้งแต่ Android 11 เป็นต้นไป ระบบจะอนุญาตให้พาร์ติชัน system_ext และ product ส่งออกประเภทสาธารณะที่กําหนดไปยังพาร์ติชันของผู้ให้บริการ เช่นเดียวกับนโยบายสาธารณะของแพลตฟอร์ม ผู้ให้บริการจะใช้ประเภทและกฎที่แปลเป็นแอตทริบิวต์เวอร์ชันโดยอัตโนมัติ เช่น จาก type เป็น type_N โดยที่ N คือเวอร์ชันของแพลตฟอร์มที่ใช้สร้างพาร์ติชันของผู้ให้บริการ

เมื่อพาร์ติชัน system_ext และ product อิงตามแพลตฟอร์มเวอร์ชันเดียวกัน N ระบบบิลด์จะสร้างไฟล์การแมปพื้นฐานสำหรับ system_ext/etc/selinux/mapping/N.cil และ product/etc/selinux/mapping/N.cil ซึ่งมีข้อมูลการจับคู่ข้อมูลประจำตัวจาก type ไปยัง type_N ผู้ให้บริการสามารถเข้าถึง type โดยใช้แอตทริบิวต์เวอร์ชัน type_N

ในกรณีที่มีการอัปเดตเฉพาะพาร์ติชัน system_ext และ product เช่น จาก N เป็น N+1 (หรือเวอร์ชันที่ใหม่กว่า) ขณะที่ผู้ให้บริการยังใช้ N อยู่ ผู้ให้บริการอาจเสียสิทธิ์เข้าถึงพาร์ติชัน system_ext และ product ประเภทนั้น พาร์ติชัน system_ext และ product ควรมีไฟล์การแมปจากประเภทที่เฉพาะเจาะจงไปยังแอตทริบิวต์ type_N เพื่อป้องกันไม่ให้ระบบเสียหาย พาร์ทเนอร์แต่ละรายมีหน้าที่รับผิดชอบในการดูแลรักษาไฟล์การแมป หากต้องการรองรับNผู้ให้บริการที่มีพาร์ติชัน N+1 (หรือใหม่กว่า) system_ext และ product

พาร์ทเนอร์ต้องดำเนินการต่อไปนี้

  1. คัดลอกไฟล์การแมปฐานที่สร้างขึ้นจากพาร์ติชัน N system_ext และ product ไปยังต้นไม้แหล่งที่มา
  2. แก้ไขไฟล์การแมปตามต้องการ
  3. ติดตั้งไฟล์การแมปลงในพาร์ติชัน system_ext และ product ของ N+1 (หรือเวอร์ชันที่ใหม่กว่า)

ตัวอย่างเช่น สมมติว่า N system_ext มีประเภทแบบสาธารณะ 1 ประเภทชื่อ foo_type จากนั้น system_ext/etc/selinux/mapping/N.cil ในพาร์ติชัน N system_ext จะมีลักษณะดังนี้

(typeattributeset foo_type_N (foo_type))
(expandtypeattribute foo_type_N true)
(typeattribute foo_type_N)

หากเพิ่ม bar_type ลงใน N+1 system_ext และหากควรจับคู่ bar_type กับ foo_type สำหรับผู้ให้บริการ N N.cil จะอัปเดตได้จาก

(typeattributeset foo_type_N (foo_type))

สู่

(typeattributeset foo_type_N (foo_type bar_type))

จากนั้นติดตั้งลงในพาร์ติชัน N+1 system_ext ผู้ให้บริการ N จะเข้าถึง foo_type และ bar_type ของ N+1 ext ได้ต่อไป

การติดป้ายกำกับบริบท SELinux

ระบบจะสร้างไฟล์บริบท SELinux แยกกันเพื่อแยกความแตกต่างระหว่างนโยบายความปลอดภัยของแพลตฟอร์มและนโยบายความปลอดภัยของผู้ให้บริการ

บริบทของไฟล์

Android 8.0 เปิดตัวการเปลี่ยนแปลงต่อไปนี้สำหรับ file_contexts

  • file_contexts จะไม่มีอยู่ในรูปแบบไบนารีเพื่อหลีกเลี่ยงภาระงานเพิ่มเติมในการคอมไพล์ในอุปกรณ์ระหว่างการบูต แต่จะเป็นไฟล์ข้อความนิพจน์ทั่วไปที่อ่านได้ เช่น {property, service}_contexts (เช่น ไฟล์ก่อนเวอร์ชัน 7.0)
  • file_contexts จะแบ่งออกเป็น 2 ไฟล์ ดังนี้
    • plat_file_contexts
      • แพลตฟอร์ม Android file_context ที่ไม่มีป้ายกำกับเฉพาะอุปกรณ์ ยกเว้นการติดป้ายกำกับบางส่วนของพาร์ติชัน /vendor ที่ต้องติดป้ายกำกับอย่างถูกต้องเพื่อให้ไฟล์ sepolicy ทำงานได้อย่างถูกต้อง
      • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/plat_file_contexts ในอุปกรณ์ และ init ต้องโหลดไว้ตั้งแต่เริ่มต้นพร้อมกับผู้ให้บริการ file_context
    • vendor_file_contexts
      • file_context สำหรับอุปกรณ์โดยเฉพาะที่สร้างโดยการรวม file_contexts ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงในไฟล์ Boardconfig.mk ของอุปกรณ์
      • ต้องติดตั้งที่ /vendor/etc/selinux/vendor_file_contexts ในพาร์ติชัน vendor และโหลดโดย init ตั้งแต่เริ่มต้นพร้อมกับแพลตฟอร์ม file_context

บริบทของพร็อพเพอร์ตี้

ใน Android 8.0 property_contexts จะแบ่งออกเป็น 2 ไฟล์ ดังนี้

  • plat_property_contexts
    • แพลตฟอร์ม Android property_context ที่ไม่มีป้ายกำกับเฉพาะอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/plat_property_contexts และโหลดโดย init ตั้งแต่เริ่มต้นพร้อมกับผู้ให้บริการ property_contexts
  • vendor_property_contexts
    • property_context สำหรับอุปกรณ์โดยเฉพาะที่สร้างโดยการรวม property_contexts ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงในไฟล์ Boardconfig.mk ของอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/vendor_property_contexts และ init ต้องโหลดไว้ตั้งแต่ต้นพร้อมกับแพลตฟอร์ม property_context

บริบทบริการ

ใน Android 8.0 service_contexts จะแบ่งออกเป็นไฟล์ต่อไปนี้

  • plat_service_contexts
    • service_context สำหรับแพลตฟอร์ม Android โดยเฉพาะสำหรับ servicemanager service_context ไม่มีป้ายกำกับเฉพาะอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/plat_service_contexts และโหลดโดย servicemanager ตั้งแต่เริ่มต้นพร้อมกับผู้ให้บริการ service_contexts
  • vendor_service_contexts
    • service_context สำหรับอุปกรณ์โดยเฉพาะที่สร้างโดยการรวม service_contexts ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงในไฟล์ Boardconfig.mk ของอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/vendor_service_contexts และโหลดโดย servicemanager ตั้งแต่เริ่มต้นพร้อมกับแพลตฟอร์ม service_contexts
    • แม้ว่า servicemanager จะค้นหาไฟล์นี้เมื่อบูต แต่vendor_service_contextsต้องไม่มีอยู่สำหรับอุปกรณ์ TREBLE ที่เป็นไปตามข้อกำหนดอย่างเต็มรูปแบบ เนื่องจากกระบวนการโต้ตอบทั้งหมดระหว่าง vendor กับ system ต้องผ่าน hwservicemanager/hwbinder
  • plat_hwservice_contexts
    • แพลตฟอร์ม Android hwservice_context สำหรับ hwservicemanager ที่ไม่มีป้ายกำกับเฉพาะอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/plat_hwservice_contexts และโหลดโดย hwservicemanager ในช่วงเริ่มต้นพร้อมกับ vendor_hwservice_contexts
  • vendor_hwservice_contexts
    • hwservice_context สำหรับอุปกรณ์โดยเฉพาะที่สร้างโดยการรวม hwservice_contexts ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงในไฟล์ Boardconfig.mk ของอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/vendor_hwservice_contexts และ hwservicemanager ต้องโหลดไฟล์ดังกล่าวตั้งแต่เริ่มต้นพร้อมกับ plat_service_contexts
  • vndservice_contexts
    • service_context สำหรับ vndservicemanager ที่เฉพาะเจาะจงอุปกรณ์ ซึ่งสร้างขึ้นโดยการรวม vndservice_contexts ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงใน Boardconfig.mk ของอุปกรณ์
    • ไฟล์นี้ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/vndservice_contexts และโหลดโดย vndservicemanager ตั้งแต่เริ่มต้น

บริบท Seapp

ใน Android 8.0 seapp_contexts จะแบ่งออกเป็น 2 ไฟล์ ดังนี้

  • plat_seapp_contexts
    • แพลตฟอร์ม Android seapp_context ที่ไม่มีการเปลี่ยนแปลงเฉพาะอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • ส่วนขยายสำหรับอุปกรณ์โดยเฉพาะสำหรับแพลตฟอร์ม seapp_context ที่สร้างขึ้นโดยรวม seapp_contexts ที่พบในไดเรกทอรีซึ่ง BOARD_SEPOLICY_DIRS ชี้ไปยังในไฟล์ Boardconfig.mk ของอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/vendor_seapp_contexts

สิทธิ์ MAC

ใน Android 8.0 mac_permissions.xml จะแบ่งออกเป็น 2 ไฟล์ ดังนี้

  • แพลตฟอร์ม mac_permissions.xml
    • แพลตฟอร์ม Android mac_permissions.xml ที่ไม่มีการเปลี่ยนแปลงเฉพาะอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน system ที่ /system/etc/selinux/.
  • ไม่ใช่แพลตฟอร์ม mac_permissions.xml
    • ส่วนขยายสำหรับอุปกรณ์ที่เฉพาะเจาะจงไปยังแพลตฟอร์ม mac_permissions.xml ที่สร้างจาก mac_permissions.xml ที่พบในไดเรกทอรีที่ BOARD_SEPOLICY_DIRS ชี้ถึงในไฟล์ Boardconfig.mk ของอุปกรณ์
    • ต้องอยู่ในพาร์ติชัน vendor ที่ /vendor/etc/selinux/.