บทความนี้อธิบายวิธีที่ 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
-
ในเนทีฟ ให้ใช้
libgenfslabelsversion
ดูไฟล์ส่วนหัวของlibgenfslabelsversion
ได้ที่genfslabelsversion.h
-
ใน Java ให้ใช้
android.os.SELinux.getGenfsLabelsVersion()
แอตทริบิวต์ความเข้ากันได้
นโยบาย 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
เมื่ออัปเกรดจาก v1
→ v2
นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้
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
และต้องรวมกฎนั้นไว้เป็นแอตทริบิวต์ของประเภทใหม่
เมื่ออัปเกรดจาก v1
→ v2
นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้
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 ออก)
เมื่ออัปเกรดจาก v1
→ v2
นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้
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)
เมื่ออัปเกรดจาก v1
→ v2
นโยบายแพลตฟอร์มต้องมีข้อมูลต่อไปนี้
# 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
- แพลตฟอร์มที่ต้องใช้ไบนารีของผู้ให้บริการต้องอยู่หลัง HAL ของ HIDL
แอตทริบิวต์ที่ไม่น่าเชื่อถือ
แอปที่ไม่น่าเชื่อถือซึ่งโฮสต์โค้ดที่ไม่รู้จักไม่ควรมีสิทธิ์เข้าถึงบริการ HwBinder ยกเว้นบริการที่ถือว่าปลอดภัยเพียงพอสำหรับการเข้าถึงจากแอปดังกล่าว (ดูบริการที่ปลอดภัยด้านล่าง) สาเหตุหลัก 2 ประการมีดังนี้
- เซิร์ฟเวอร์ HwBinder จะไม่ตรวจสอบสิทธิ์ไคลเอ็นต์เนื่องจากปัจจุบัน HIDL ไม่ได้เปิดเผยข้อมูล UID ของผู้เรียก แม้ว่า HIDL จะแสดงข้อมูลดังกล่าว แต่บริการ HwBinder จำนวนมากจะทำงานในระดับที่ต่ำกว่าแอป (เช่น HAL) หรือต้องไม่อาศัยข้อมูลประจำตัวของแอปเพื่อขอสิทธิ์ ดังนั้น เพื่อเป็นการป้องกันไว้ก่อน ระบบจะถือว่าบริการ HwBinder ทั้งหมดถือว่าลูกค้าทุกรายได้รับสิทธิ์อย่างเท่าเทียมกันในการดําเนินการต่างๆ ที่บริการเสนอ
- เซิร์ฟเวอร์ HAL (ชุดย่อยของบริการ HwBinder) มีโค้ดที่มีอัตราการเกิดปัญหาด้านความปลอดภัยสูงกว่าคอมโพเนนต์
system/core
และมีสิทธิ์เข้าถึงเลเยอร์ล่างของสแต็ก (ไปจนถึงระดับฮาร์ดแวร์) จึงเพิ่มโอกาสในการหลบเลี่ยงรูปแบบการรักษาความปลอดภัยของ Android
บริการตู้เซฟ
บริการที่ปลอดภัย ได้แก่
same_process_hwservice
. บริการเหล่านี้ (ตามคำจำกัดความ) จะทำงานในกระบวนการของไคลเอ็นต์ จึงมีสิทธิ์เข้าถึงเช่นเดียวกับโดเมนไคลเอ็นต์ที่กระบวนการทำงานcoredomain_hwservice
บริการเหล่านี้ไม่มีความเสี่ยงที่เชื่อมโยงกับเหตุผลที่ 2hal_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
สำหรับการเปลี่ยนแปลงป้ายกำกับของวัตถุ เช่น sysfs
→ sysfs_A
หรือ mediaserver
→ audioserver
การสร้างการแมปนี้ไม่ใช่เรื่องง่าย (และอธิบายไว้ในตัวอย่างด้านบน) ผู้ดูแลนโยบายแพลตฟอร์มต้องกำหนดวิธีสร้างการแมปที่จุดเปลี่ยนสำหรับออบเจ็กต์ ซึ่งต้องใช้ความเข้าใจความสัมพันธ์ระหว่างออบเจ็กต์กับป้ายกำกับที่กำหนด และกำหนดว่าเหตุการณ์นี้จะเกิดขึ้นเมื่อใด เพื่อความเข้ากันได้แบบย้อนหลัง ความซับซ้อนนี้ต้องจัดการจากฝั่งแพลตฟอร์ม ซึ่งเป็นพาร์ติชันเดียวที่อัปเกรดได้
การอัปเกรดเวอร์ชัน
แพลตฟอร์ม 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
พาร์ทเนอร์ต้องดำเนินการต่อไปนี้
- คัดลอกไฟล์การแมปฐานที่สร้างขึ้นจากพาร์ติชัน
N
system_ext
และproduct
ไปยังต้นไม้แหล่งที่มา - แก้ไขไฟล์การแมปตามต้องการ
-
ติดตั้งไฟล์การแมปลงในพาร์ติชัน
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
- แพลตฟอร์ม Android
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
- แพลตฟอร์ม Android
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
- แพลตฟอร์ม Android
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.
- แพลตฟอร์ม Android
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/.
- แพลตฟอร์ม Android
- ไม่ใช่แพลตฟอร์ม
mac_permissions.xml
- ส่วนขยายสำหรับอุปกรณ์ที่เฉพาะเจาะจงไปยังแพลตฟอร์ม
mac_permissions.xml
ที่สร้างจากmac_permissions.xml
ที่พบในไดเรกทอรีที่BOARD_SEPOLICY_DIRS
ชี้ถึงในไฟล์Boardconfig.mk
ของอุปกรณ์ - ต้องอยู่ในพาร์ติชัน
vendor
ที่/vendor/etc/selinux/.
- ส่วนขยายสำหรับอุปกรณ์ที่เฉพาะเจาะจงไปยังแพลตฟอร์ม