โครงการโอเพ่นซอร์ส Android (AOSP) มีนโยบายพื้นฐานที่มั่นคงสำหรับแอปพลิเคชันและบริการที่เหมือนกันในอุปกรณ์ Android ทั้งหมด ผู้สนับสนุน AOSP ปรับปรุงนโยบายนี้อย่างสม่ำเสมอ นโยบายหลักคาดว่าจะคิดเป็นประมาณ 90–95% ของนโยบายบนอุปกรณ์ขั้นสุดท้ายโดยมีการปรับแต่งเฉพาะอุปกรณ์ซึ่งคิดเป็น 5-10% ที่เหลือ บทความนี้เน้นที่การปรับแต่งเฉพาะอุปกรณ์เหล่านี้ วิธีเขียนนโยบายเฉพาะอุปกรณ์ และข้อผิดพลาดบางประการที่ควรหลีกเลี่ยง
การนำอุปกรณ์
ขณะเขียนนโยบายเฉพาะอุปกรณ์ ให้ทำตามขั้นตอนเหล่านี้
เรียกใช้ในโหมดอนุญาต
เมื่ออุปกรณ์อยู่ใน โหมดอนุญาต การปฏิเสธจะถูกบันทึกไว้แต่ไม่มีการบังคับใช้ โหมดอนุญาตมีความสำคัญด้วยเหตุผลสองประการ:
- โหมดอนุญาตช่วยให้แน่ใจว่าการนำนโยบายมาใช้จะไม่ทำให้งานการนำอุปกรณ์ต้นทางอื่นๆ ล่าช้าออกไป
- การบังคับใช้การปฏิเสธอาจปิดบังการปฏิเสธอื่นๆ ตัวอย่างเช่น การเข้าถึงไฟล์มักเกี่ยวข้องกับการค้นหาไดเร็กทอรี เปิดไฟล์ จากนั้นจึงอ่านไฟล์ ในโหมดบังคับใช้ เฉพาะการปฏิเสธการค้นหาไดเร็กทอรีเท่านั้นที่จะเกิดขึ้น โหมดอนุญาตช่วยให้มั่นใจได้ว่าจะเห็นการปฏิเสธทั้งหมด
วิธีที่ง่ายที่สุดในการทำให้อุปกรณ์เข้าสู่โหมดอนุญาตคือการใช้ บรรทัดคำสั่งเคอร์เนล สามารถเพิ่มลงในไฟล์ BoardConfig.mk
ของอุปกรณ์: platform/device/<vendor>/<target>/BoardConfig.mk
หลังจากแก้ไขบรรทัดคำสั่ง ให้ทำการ make clean
จากนั้น make bootimage
และแฟลชอิมเมจสำหรับบูตใหม่
หลังจากนั้น ยืนยันโหมดอนุญาตด้วย:
adb shell getenforce
สองสัปดาห์เป็นเวลาที่เหมาะสมที่จะอยู่ในโหมดอนุญาตทั่วโลก หลังจากจัดการกับการปฏิเสธส่วนใหญ่แล้ว ให้ย้ายกลับเข้าสู่โหมดบังคับใช้และจัดการจุดบกพร่องเมื่อเข้ามา โดเมนที่ยังคงสร้างการปฏิเสธหรือบริการที่ยังอยู่ภายใต้การพัฒนาอย่างหนักสามารถใส่ลงในโหมดอนุญาตชั่วคราวได้ แต่ให้ย้ายกลับไปใช้โหมดบังคับใช้โดยเร็วที่สุด
บังคับใช้ก่อน
ในโหมดบังคับใช้ การปฏิเสธจะถูกบันทึกและบังคับใช้ แนวทางปฏิบัติที่ดีที่สุดในการทำให้อุปกรณ์ของคุณเข้าสู่โหมดบังคับใช้โดยเร็วที่สุด การรอสร้างและบังคับใช้นโยบายเฉพาะอุปกรณ์มักส่งผลให้เกิดผลิตภัณฑ์ที่มีข้อบกพร่องและประสบการณ์ของผู้ใช้ที่ไม่ดี เริ่มต้นเร็วพอที่จะเข้าร่วมในการ ลองใช้ และรับรองการทดสอบการใช้งานอย่างเต็มรูปแบบในการใช้งานจริง การเริ่มตั้งแต่เนิ่นๆ ช่วยให้มั่นใจถึงปัญหาด้านความปลอดภัยจะแจ้งการตัดสินใจออกแบบ ในทางกลับกัน การให้สิทธิ์ตามการปฏิเสธที่สังเกตได้เพียงอย่างเดียวนั้นเป็นแนวทางที่ไม่ปลอดภัย ใช้เวลานี้เพื่อทำการตรวจสอบความปลอดภัยของอุปกรณ์และไฟล์บั๊กกับพฤติกรรมที่ไม่ควรอนุญาต
ลบหรือลบนโยบายที่มีอยู่
มีเหตุผลที่ดีหลายประการในการสร้างนโยบายเฉพาะอุปกรณ์ตั้งแต่เริ่มต้นบนอุปกรณ์ใหม่ ซึ่งรวมถึง:
- การตรวจสอบความปลอดภัย
- นโยบายที่อนุญาตมากเกินไป
- การลดขนาดนโยบาย
- นโยบายที่ตายแล้ว
ที่อยู่การปฏิเสธบริการหลัก
การปฏิเสธที่เกิดจากบริการหลักมักจะได้รับการแก้ไขโดยการติดป้ายกำกับไฟล์ ตัวอย่างเช่น:
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 ไม่จำเป็นต้องมีสิทธิ์เพิ่มเติมเนื่องจากเซิร์ฟเวอร์มีเดีย มีสิทธิ์ที่จำเป็น ในนโยบายหลักเพื่อเข้าถึง gpu_device แล้ว
ไฟล์เฉพาะอุปกรณ์อื่นๆ ที่ควรติดป้ายกำกับด้วยประเภทที่กำหนดไว้ล่วงหน้าในนโยบายหลัก:
- บล็อกอุปกรณ์
- อุปกรณ์เครื่องเสียง
- อุปกรณ์วิดีโอ
- เซ็นเซอร์
- nfc
- gps_device
- ไฟล์ใน /sys
- ไฟล์ใน /proc
โดยทั่วไป การให้สิทธิ์กับป้ายกำกับเริ่มต้นไม่ถูกต้อง สิทธิ์เหล่านี้จำนวนมากไม่อนุญาตโดยกฎ neverallow แต่ถึงแม้จะไม่ได้รับอนุญาตอย่างชัดแจ้ง แนวทางปฏิบัติที่ดีที่สุดคือการจัดเตรียมป้ายกำกับเฉพาะ
ติดป้ายกำกับบริการใหม่และการปฏิเสธที่อยู่
บริการที่เปิดตัวครั้งแรกจำเป็นต้องทำงานในโดเมน 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
เจตนาชัดเจน: ทุกคนยกเว้นแอปของบุคคลที่สามอาจเข้าถึงอุปกรณ์แก้ไขข้อบกพร่องได้
กฎมีข้อบกพร่องในสองสามวิธี การยกเว้นของ untrusted_app
เป็นเรื่องเล็กน้อยในการแก้ไข เนื่องจากแอปทั้งหมดอาจเรียกใช้บริการในโดเมน isolated_app
ได้ ในทำนองเดียวกัน หากมีการเพิ่มโดเมนใหม่สำหรับแอปของบุคคลที่สามใน AOSP พวกเขาจะมีสิทธิ์เข้าถึง scary_debug_device
ด้วย กฎนี้อนุญาตมากเกินไป โดเมนส่วนใหญ่จะไม่ได้รับประโยชน์จากการเข้าถึงเครื่องมือแก้ไขข้อบกพร่องนี้ กฎควรเขียนขึ้นเพื่ออนุญาตเฉพาะโดเมนที่ต้องการการเข้าถึงเท่านั้น
คุณสมบัติการดีบักในการผลิต
ฟีเจอร์การดีบักไม่ควรแสดงบนบิลด์ที่ใช้งานจริงและไม่ควรมีนโยบาย
ทางเลือกที่ง่ายที่สุดคือการอนุญาตเฉพาะคุณลักษณะการดีบักเมื่อ SELinux ถูกปิดใช้งานบน eng/userdebug builds เช่น adb root
และ adb shell setenforce 0
ทางเลือกที่ปลอดภัยอีกทางหนึ่งคือการใส่สิทธิ์การดีบักไว้ในคำสั่ง userdebug_or_eng
การขยายขนาดนโยบาย
การกำหนดลักษณะนโยบาย SEAndroid ในป่า จะอธิบายแนวโน้มที่เกี่ยวข้องในการเติบโตของการปรับแต่งนโยบายอุปกรณ์ นโยบายเฉพาะอุปกรณ์ควรคิดเป็น 5-10% ของนโยบายโดยรวมที่ทำงานบนอุปกรณ์ การปรับแต่งในช่วง 20%+ เกือบจะมีมากกว่าโดเมนที่มีสิทธิพิเศษและนโยบายที่ไม่ทำงาน
นโยบายขนาดใหญ่ที่ไม่จำเป็น:
- ใช้หน่วยความจำสองครั้งเนื่องจากนโยบายอยู่ใน ramdisk และโหลดลงในหน่วยความจำเคอร์เนลด้วย
- เปลืองเนื้อที่ดิสก์โดยต้องใช้ bootimage ที่ใหญ่ขึ้น
- ส่งผลต่อเวลาการค้นหานโยบายรันไทม์
ตัวอย่างต่อไปนี้แสดงอุปกรณ์สองเครื่องที่นโยบายเฉพาะของผู้ผลิตประกอบด้วย 50% และ 40% ของนโยบายบนอุปกรณ์ การเขียนนโยบายใหม่ทำให้ได้รับการปรับปรุงการรักษาความปลอดภัยอย่างมากโดยไม่มีการสูญเสียฟังก์ชันการทำงาน ดังที่แสดงด้านล่าง (มีอุปกรณ์ AOSP Shamu และ Flounder เพื่อเปรียบเทียบ)
รูปที่ 1 . การเปรียบเทียบขนาดนโยบายเฉพาะอุปกรณ์หลังการตรวจสอบความปลอดภัย
ในทั้งสองกรณี นโยบายถูกลดขนาดลงอย่างมากทั้งในด้านขนาดและจำนวนการอนุญาต ขนาดนโยบายที่ลดลงเกือบทั้งหมดเกิดจากการเอาสิทธิ์ที่ไม่จำเป็นออก ซึ่งส่วนใหญ่มักเป็นกฎที่สร้างโดย audit2allow
ซึ่งถูกเพิ่มเข้าไปในนโยบายตามอำเภอใจ โดเมนที่ไม่ทำงานก็เป็นปัญหาสำหรับอุปกรณ์ทั้งสองเครื่อง
ให้ความสามารถ dac_override
การปฏิเสธ dac_override
หมายความว่ากระบวนการที่ละเมิดกำลังพยายามเข้าถึงไฟล์ที่มีสิทธิ์ผู้ใช้/กลุ่ม/โลก unix ที่ไม่ถูกต้อง วิธีแก้ปัญหาที่เหมาะสมแทบจะไม่เคยให้สิทธิ์ dac_override
ให้ เปลี่ยนการอนุญาตยูนิกซ์ในไฟล์หรือกระบวนการ แทน บางโดเมนเช่น init
, vold
และ installd
ต้องการความสามารถในการแทนที่การอนุญาตไฟล์ unix เพื่อเข้าถึงไฟล์ของกระบวนการอื่น ๆ ดู บล็อกของ Dan Walsh สำหรับคำอธิบายเชิงลึกเพิ่มเติม