โครงการโอเพนซอร์ส 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
จะได้รับป้ายกํากับ "
device" เว้นแต่จะมีการกําหนดป้ายกํากับที่เฉพาะเจาะจงมากขึ้น การยอมรับเอาต์พุตจาก 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)
นี่คือเทมเพลตเริ่มต้นสำหรับโดเมน SELinux ของ foo ซึ่งคุณสามารถเพิ่มกฎตามการดำเนินการที่เฉพาะเจาะจงซึ่งไฟล์ปฏิบัติการนั้นดำเนินการได้
- ป้ายกำกับ
/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
เจตนานั้นชัดเจนว่าทุกคนยกเว้นแอปของบุคคลที่สามจะมีสิทธิ์เข้าถึงอุปกรณ์แก้ไขข้อบกพร่อง
กฎมีข้อบกพร่องในหลายประการ การยกเว้น 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 เท่าเนื่องจากนโยบายอยู่ใน RAMdisk และโหลดลงในหน่วยความจําเคอร์เนลด้วย
- สิ้นเปลืองพื้นที่ในดิสก์เนื่องจากต้องใช้บูตอิมเมจขนาดใหญ่ขึ้น
- ส่งผลต่อเวลาในการค้นหานโยบายรันไทม์
ตัวอย่างต่อไปนี้แสดงอุปกรณ์ 2 เครื่องที่นโยบายเฉพาะผู้ผลิตคิดเป็นสัดส่วน 50% และ 40% ของนโยบายในอุปกรณ์ การเขียนนโยบายขึ้นใหม่ทำให้มีการปรับปรุงด้านความปลอดภัยอย่างมากโดยไม่สูญเสียฟังก์ชันการทำงาน ดังที่แสดงด้านล่าง (รวมอุปกรณ์ AOSP Shamu และ Flounder ไว้เพื่อการเปรียบเทียบ)
รูปที่ 1 การเปรียบเทียบขนาดนโยบายเฉพาะอุปกรณ์หลังจากการตรวจสอบความปลอดภัย
นโยบายทั้ง 2 ฉบับนี้มีขนาดและจำนวนสิทธิ์ลดลงอย่างมาก ขนาดนโยบายที่ลดลงเกือบทั้งหมดเกิดจากการนําสิทธิ์ที่ไม่จําเป็นออก ซึ่งส่วนใหญ่เป็นกฎที่ audit2allow
สร้างขึ้นและเพิ่มลงในนโยบายโดยไม่คํานึงถึง โดเมนที่ใช้งานไม่ได้ก็เป็นปัญหาสำหรับทั้ง 2 อุปกรณ์ด้วย
ให้สิทธิ์ dac_override
การปฏิเสธ dac_override
หมายความว่ากระบวนการที่ละเมิดกำลังพยายามเข้าถึงไฟล์ที่มีสิทธิ์ผู้ใช้/กลุ่ม/โลก Unix ไม่ถูกต้อง
แทบจะไม่เคยมีโซลูชันที่เหมาะสมในการให้สิทธิ์ dac_override
แต่ให้
измените права Unix на файл или процесс โดเมนบางรายการ เช่น init
, vold
และ installd
จำเป็นต้องมีความสามารถในการลบล้างสิทธิ์เข้าถึงไฟล์ Unix เพื่อเข้าถึงไฟล์ของกระบวนการอื่นๆ
ดูคำอธิบายโดยละเอียดเพิ่มเติมได้ที่บล็อกของ Dan Walsh