โครงการโอเพนซอร์ส Android (AOSP) มอบนโยบายพื้นฐานที่แข็งแกร่งสำหรับแอปและบริการที่ใช้ร่วมกันได้ในอุปกรณ์ Android ทั้งหมด ผู้ร่วมให้ข้อมูลกับ AOSP จะปรับแต่งนโยบายนี้อย่างสม่ำเสมอ นโยบายหลักคาดว่าจะคิดเป็นสัดส่วนประมาณ 90-95% ของนโยบายในอุปกรณ์ขั้นสุดท้าย โดยมีการปรับแต่งเฉพาะอุปกรณ์คิดเป็นสัดส่วน 5-10% ที่เหลือ บทความนี้จะเน้นที่การปรับแต่งเฉพาะอุปกรณ์ วิธีเขียนนโยบายเฉพาะอุปกรณ์ และข้อผิดพลาดบางอย่างที่ควรหลีกเลี่ยง
การเปิดใช้งานอุปกรณ์
ขณะเขียนนโยบายเฉพาะอุปกรณ์ ให้ทำตามขั้นตอนต่อไปนี้
ทำงานในโหมดไม่เข้มงวด
เมื่ออุปกรณ์อยู่ในโหมดที่อนุญาต ระบบจะบันทึกการปฏิเสธแต่ไม่ได้บังคับใช้ โหมดอนุญาตมีความสำคัญเนื่องจากเหตุผล 2 ประการ ดังนี้
- โหมดอนุญาตช่วยให้มั่นใจได้ว่าการเปิดใช้งานนโยบายจะไม่ทำให้งานอื่นๆ ในการเริ่มต้นใช้งานอุปกรณ์ในช่วงต้นล่าช้า
- การปฏิเสธที่บังคับใช้อาจมาสก์การปฏิเสธอื่นๆ เช่น การเข้าถึงไฟล์มักจะเกี่ยวข้องกับการค้นหาไดเรกทอรี การเปิดไฟล์ และการอ่านไฟล์ ในโหมดบังคับใช้ ระบบจะปฏิเสธการค้นหาไดเรกทอรีเท่านั้น โหมดอนุญาตจะช่วยให้เห็นการปฏิเสธทั้งหมด
วิธีที่ง่ายที่สุดในการเปลี่ยนอุปกรณ์เป็นโหมดอนุญาตคือการใช้บรรทัดคำสั่งเคอร์เนล คุณสามารถเพิ่มข้อมูลนี้ลงในไฟล์ BoardConfig.mk
ของอุปกรณ์ได้
platform/device/<vendor>/<target>/BoardConfig.mk
หลังจากแก้ไขบรรทัดคำสั่งแล้ว ให้กด make clean
แล้วกด make bootimage
แล้วแฟลชอิมเมจการบูตใหม่
หลังจากนั้น ให้ยืนยันโหมดอนุญาตด้วย
adb shell getenforce
2 สัปดาห์เป็นระยะเวลาที่เหมาะสมในการอยู่ในโหมดอนุญาตทั่วโลก หลังจากจัดการกับการปฏิเสธส่วนใหญ่แล้ว ให้กลับไปเข้าสู่โหมดบังคับใช้และแก้ไขข้อบกพร่องที่ได้รับ โดเมนที่ยังคงแสดงการปฏิเสธหรือบริการที่ยังคงอยู่ระหว่างการพัฒนาอย่างหนักสามารถย้ายไปไว้ในโหมดอนุญาตชั่วคราวได้ แต่ให้ย้ายกลับไปยังโหมดบังคับใช้โดยเร็วที่สุด
บังคับใช้ตั้งแต่เนิ่นๆ
ในโหมดบังคับใช้ ระบบจะบันทึกและบังคับใช้การปฏิเสธ แนวทางปฏิบัติแนะนำคือให้นำอุปกรณ์เข้าสู่โหมดบังคับใช้โดยเร็วที่สุด การรอสร้างและบังคับใช้นโยบายเฉพาะอุปกรณ์มักจะทำให้เกิดข้อบกพร่องและประสบการณ์ของผู้ใช้ที่ไม่ดี เริ่มตั้งแต่เนิ่นๆ เพื่อเข้าร่วมการทดสอบกับผู้ใช้จริงและตรวจสอบว่าฟังก์ชันการทํางานได้รับการทดสอบอย่างครอบคลุมสําหรับการใช้งานจริง การเริ่มต้นตั้งแต่เนิ่นๆ จะช่วยให้ข้อกังวลด้านความปลอดภัยเป็นข้อมูลในการตัดสินใจออกแบบ ในทางกลับกัน การให้สิทธิ์โดยพิจารณาจากการปฏิเสธที่สังเกตได้เพียงอย่างเดียวเป็นแนวทางที่ไม่ปลอดภัย ใช้เวลานี้เพื่อทำการตรวจสอบความปลอดภัยของอุปกรณ์และรายงานข้อบกพร่องเกี่ยวกับลักษณะการทำงานที่ไม่ควรอนุญาต
นำนโยบายที่มีอยู่ออกหรือลบนโยบาย
มีเหตุผลหลายประการที่ควรสร้างนโยบายเฉพาะอุปกรณ์ตั้งแต่ต้นในอุปกรณ์เครื่องใหม่ ซึ่งรวมถึง
- การตรวจสอบความปลอดภัย
- นโยบายที่อนุญาตมากเกินไป
- การลดขนาดนโยบาย
- นโยบายที่ใช้งานไม่ได้
จัดการการปฏิเสธบริการหลัก
โดยปกติแล้ว การปฏิเสธที่เกิดจากบริการหลักจะได้รับการแก้ไขด้วยการติดป้ายกำกับไฟล์ เช่น
avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0” dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1 avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
ได้รับการแก้ไขอย่างสมบูรณ์แล้วด้วยการติดป้ายกํากับ /dev/kgsl-3d0
อย่างถูกต้อง ในตัวอย่างนี้ tcontext
คือ device
รายการนี้แสดงบริบทเริ่มต้นที่ทุกอย่างใน /dev
จะได้รับป้ายกำกับ "
อุปกรณ์" เว้นแต่จะมีการกำหนดป้ายกำกับที่เฉพาะเจาะจงมากขึ้น การยอมรับเอาต์พุตจาก audit2allow ที่นี่เพียงอย่างเดียวจะทำให้ได้กฎที่ไม่ถูกต้องและอนุญาตมากเกินไป
หากต้องการแก้ปัญหาประเภทนี้ ให้ติดป้ายกำกับไฟล์ให้เฉพาะเจาะจงมากขึ้น ซึ่งในกรณีนี้คือ gpu_device ไม่จำเป็นต้องมีสิทธิ์เพิ่มเติมเนื่องจาก MediaServer มีสิทธิ์ที่จำเป็นอยู่แล้วในนโยบายหลักในการเข้าถึง GPU_device
ไฟล์อื่นๆ สำหรับอุปกรณ์ที่เฉพาะเจาะจงซึ่งควรติดป้ายกำกับด้วยประเภทที่กำหนดไว้ล่วงหน้าในนโยบายหลัก
- บล็อกอุปกรณ์
- อุปกรณ์เสียง
- อุปกรณ์วิดีโอ
- เซ็นเซอร์
- nfc
- gps_device
- ไฟล์ใน /sys
- ไฟล์ใน /proc
โดยทั่วไปแล้ว การให้สิทธิ์ป้ายกำกับเริ่มต้นเป็นสิ่งที่ไม่ถูกต้อง กฎ neverallow ไม่อนุญาตให้ใช้สิทธิ์เหล่านี้จำนวนมาก แต่แม้ว่าจะไม่ได้ห้ามอย่างชัดเจน แนวทางปฏิบัติแนะนำคือให้ระบุป้ายกำกับที่เฉพาะเจาะจง
ติดป้ายกำกับบริการใหม่และแก้ไขการปฏิเสธ
บริการที่เริ่มต้นด้วย Init ต้องทำงานในโดเมน SELinux ของตนเอง ตัวอย่างต่อไปนี้จะใส่บริการ "foo" ไว้ในโดเมน SELinux ของตัวเองและมอบสิทธิ์ให้
บริการนี้มีการเปิดตัวในไฟล์ init.device.rc
ของอุปกรณ์ดังนี้
service foo /system/bin/foo class core
- สร้างโดเมนใหม่ "foo"
สร้างไฟล์
device/manufacturer/device-name/sepolicy/foo.te
ที่มีเนื้อหาต่อไปนี้# foo service type foo, domain; type foo_exec, exec_type, file_type; init_daemon_domain(foo)
นี่คือเทมเพลตเริ่มต้นสำหรับโดเมน foo SELinux ที่คุณสามารถ เพิ่มกฎตามการดำเนินการเฉพาะที่ดำเนินการโดยไฟล์ปฏิบัติการนั้น
- ป้ายกำกับ
/system/bin/foo
เพิ่มข้อมูลต่อไปนี้ลงใน
device/manufacturer/device-name/sepolicy/file_contexts
/system/bin/foo u:object_r:foo_exec:s0
การดำเนินการนี้จะทำให้ไฟล์ปฏิบัติการมีการติดป้ายกำกับอย่างถูกต้องเพื่อให้ SELinux เรียกใช้บริการในโดเมนที่ถูกต้อง
- สร้างและแฟลชอิมเมจการเปิดเครื่องและอิมเมจของระบบ
- ปรับแต่งกฎ SELinux สำหรับโดเมน
ใช้การปฏิเสธเพื่อระบุสิทธิ์ที่จําเป็น เครื่องมือ audit2allow มีหลักเกณฑ์ที่ดี แต่ให้ใช้เพื่อใช้เป็นข้อมูลในการเขียนนโยบายเท่านั้น อย่าคัดลอกเอาต์พุตเพียงอย่างเดียว
เปลี่ยนกลับไปใช้โหมดบังคับใช้
การแก้ปัญหาในโหมดที่อนุญาตนั้นทำได้ แต่ให้เปลี่ยนไปใช้โหมดบังคับใช้โดยเร็วที่สุดและพยายามใช้โหมดนี้ต่อไป
ความผิดพลาดที่พบบ่อย
ต่อไปนี้เป็นวิธีแก้ปัญหาข้อผิดพลาดที่พบบ่อยเมื่อเขียนนโยบายเฉพาะอุปกรณ์
การใช้การปฏิเสธมากเกินไป
กฎตัวอย่างต่อไปนี้จะเหมือนกับการล็อกประตูหน้าแต่เปิดหน้าต่างทิ้งไว้
allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms
เจตนานั้นชัดเจนว่าทุกคนยกเว้นแอปของบุคคลที่สามจะมีสิทธิ์เข้าถึงอุปกรณ์แก้ไขข้อบกพร่อง
กฎนี้มีข้อบกพร่องอยู่ 2-3 อย่าง การยกเว้น untrusted_app
นั้นแก้ไขได้ง่าย เนื่องจากแอปทั้งหมดอาจเลือกที่จะเรียกใช้บริการในโดเมน isolated_app
ได้ ในทำนองเดียวกัน หากเพิ่มโดเมนใหม่สำหรับแอปของบุคคลที่สามลงใน AOSP แอปเหล่านั้นจะมีสิทธิ์เข้าถึง scary_debug_device
ด้วย
กฎอนุญาตมากเกินไป โดเมนส่วนใหญ่จะไม่ได้รับประโยชน์จากการมีสิทธิ์เข้าถึงเครื่องมือแก้ไขข้อบกพร่องนี้ กฎควรเขียนขึ้นเพื่ออนุญาตเฉพาะโดเมนที่ต้องเข้าถึง
แก้ไขข้อบกพร่องของฟีเจอร์ในเวอร์ชันที่ใช้งานจริง
ฟีเจอร์แก้ไขข้อบกพร่องไม่ควรมีอยู่ในบิลด์เวอร์ชันที่ใช้งานจริงและไม่ควรมีนโยบาย
วิธีที่ง่ายที่สุดคือการอนุญาตฟีเจอร์แก้ไขข้อบกพร่องเมื่อปิดใช้ SELinux ในบิลด์ eng/userdebug เช่น adb root
และ adb shell setenforce 0
เท่านั้น
อีกทางเลือกที่ปลอดภัยคือการใส่สิทธิ์การแก้ไขข้อบกพร่องในคำสั่ง userdebug_or_eng
นโยบายที่เพิ่มขึ้นอย่างรวดเร็ว
การจำแนกลักษณะของนโยบาย SEAndroid ในสภาพป่าเถื่อน อธิบายแนวโน้มที่น่ากังวลในการเติบโตของการปรับแต่งนโยบายด้านอุปกรณ์ นโยบายเฉพาะอุปกรณ์ควรคิดเป็นสัดส่วน 5-10% ของนโยบายโดยรวมที่ทำงานในอุปกรณ์ การปรับแต่งในช่วง 20%ขึ้นไปมีโดเมนที่มีสิทธิ์มากเกินไปและนโยบายที่ใช้งานไม่ได้เกือบแน่นอน
นโยบายที่มีขนาดใหญ่เกินความจำเป็น
- เกิดหน่วยความจำแบบ 2 ครั้งเมื่อนโยบายอยู่ใน RAM และโหลดลงในหน่วยความจำของเคอร์เนลด้วย
- สิ้นเปลืองพื้นที่ในดิสก์เนื่องจากต้องใช้บูตอิมเมจขนาดใหญ่ขึ้น
- ส่งผลต่อเวลาในการค้นหานโยบายรันไทม์
ตัวอย่างต่อไปนี้แสดงอุปกรณ์ 2 เครื่องที่นโยบายเฉพาะผู้ผลิตคิดเป็นสัดส่วน 50% และ 40% ของนโยบายในอุปกรณ์ การเขียนนโยบายขึ้นใหม่ทำให้มีการปรับปรุงด้านความปลอดภัยอย่างมากโดยไม่สูญเสียฟังก์ชันการทำงาน ดังที่แสดงด้านล่าง (รวมอุปกรณ์ AOSP Shamu และ Flounder ไว้เพื่อการเปรียบเทียบ)
ในทั้ง 2 กรณี นโยบายนี้ลดขนาดลงอย่างมากทั้งด้านขนาดและจำนวนสิทธิ์ การลดขนาดนโยบายลงเกือบทั้งหมดเกิดจากการนำสิทธิ์ที่ไม่จำเป็นออก ซึ่งส่วนใหญ่มักเป็นกฎที่สร้างโดย audit2allow
และได้เพิ่มลงในนโยบายอย่างไม่ตั้งใจ โดเมนที่ใช้งานไม่ได้ก็เป็นปัญหาสำหรับทั้ง 2 อุปกรณ์ด้วย
ให้สิทธิ์ dac_override
การปฏิเสธ dac_override
หมายความว่ากระบวนการที่ละเมิดกำลังพยายามเข้าถึงไฟล์ที่มีสิทธิ์ผู้ใช้/กลุ่ม/โลก Unix ไม่ถูกต้อง
โซลูชันที่เหมาะสมคือแทบจะไม่ให้สิทธิ์ dac_override
แต่ให้
измените права Unix на файл или процесс โดเมนบางรายการ เช่น init
, vold
และ installd
จำเป็นต้องมีความสามารถในการลบล้างสิทธิ์เข้าถึงไฟล์ Unix เพื่อเข้าถึงไฟล์ของกระบวนการอื่นๆ
ดูคำอธิบายโดยละเอียดเพิ่มเติมได้ที่บล็อกของ Dan Walsh