โครงการ Android Open Source (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 แล้ว
ไฟล์เฉพาะอุปกรณ์อื่นๆ ที่ควรติดป้ายกำกับประเภทที่กำหนดไว้ล่วงหน้าในนโยบายหลัก:
- บล็อกอุปกรณ์
- อุปกรณ์เครื่องเสียง
- อุปกรณ์วิดีโอ
- เซ็นเซอร์
- เอ็นเอฟซี
- gps_device
- ไฟล์ใน /sys
- ไฟล์ใน /proc
โดยทั่วไป การให้สิทธิ์แก่ป้ายกำกับเริ่มต้นเป็นสิ่งที่ผิด สิทธิ์เหล่านี้จำนวนมากไม่ได้รับอนุญาตตามกฎ Neverallow แต่ถึงแม้จะไม่ได้ไม่ได้รับอนุญาตอย่างชัดเจน แนวทางปฏิบัติที่ดีที่สุดก็คือการระบุป้ายกำกับเฉพาะ
ติดป้ายกำกับบริการใหม่และการปฏิเสธที่อยู่
บริการที่เปิดตัวครั้งแรกจำเป็นต้องทำงานในโดเมน SELinux ของตนเอง ตัวอย่างต่อไปนี้ใส่บริการ “foo” ลงในโดเมน SELinux ของตัวเองและให้สิทธิ์
บริการเปิดตัวใน init. device .rc
ของอุปกรณ์ของเรา ไฟล์ 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 เช่น adb root
และ adb shell setenforce 0
อีกทางเลือกหนึ่งที่ปลอดภัยคือการใส่สิทธิ์ในการแก้ไขข้อบกพร่องในคำสั่ง userdebug_or_eng
นโยบายระเบิดขนาด
การระบุลักษณะนโยบาย SEAndroid ทั่วไป อธิบายถึงแนวโน้มที่เกี่ยวข้องในการเติบโตของการปรับแต่งนโยบายอุปกรณ์ นโยบายเฉพาะอุปกรณ์ควรคิดเป็น 5-10% ของนโยบายโดยรวมที่ทำงานบนอุปกรณ์ การปรับแต่งในช่วง 20%+ เกือบจะประกอบด้วยโดเมนที่ได้รับสิทธิพิเศษและนโยบายที่ไม่ทำงาน
นโยบายขนาดใหญ่โดยไม่จำเป็น:
- โจมตีหน่วยความจำสองครั้งเนื่องจากนโยบายอยู่ใน ramdisk และโหลดลงในหน่วยความจำเคอร์เนลด้วย
- เปลืองพื้นที่ดิสก์โดยต้องใช้บูตอิมเมจที่ใหญ่ขึ้น
- ส่งผลต่อเวลาในการค้นหานโยบายรันไทม์
ตัวอย่างต่อไปนี้แสดงอุปกรณ์ 2 เครื่องที่นโยบายเฉพาะของผู้ผลิตประกอบด้วย 50% และ 40% ของนโยบายด้านอุปกรณ์ การเขียนนโยบายใหม่ทำให้ได้รับการปรับปรุงด้านความปลอดภัยอย่างมาก โดยไม่สูญเสียฟังก์ชันการทำงาน ดังที่แสดงด้านล่าง (รวมอุปกรณ์ AOSP Shamu และ Flounder ไว้เพื่อการเปรียบเทียบ)
ในทั้งสองกรณี นโยบายจะลดลงอย่างมากทั้งขนาดและจำนวนสิทธิ์ ขนาดของนโยบายที่ลดลงเกือบทั้งหมดเกิดจากการลบสิทธิ์ที่ไม่จำเป็นออกไป ซึ่งหลายรายการน่าจะเป็นกฎที่สร้างโดย audit2allow
ที่ถูกเพิ่มเข้าไปในนโยบายโดยไม่เลือกปฏิบัติ โดเมนที่เสียก็เป็นปัญหาสำหรับอุปกรณ์ทั้งสองเช่นกัน
การกำหนดความสามารถ dac_override
การปฏิเสธ dac_override
หมายความว่ากระบวนการที่ละเมิดกำลังพยายามเข้าถึงไฟล์ที่มีสิทธิ์ผู้ใช้/กลุ่ม/โลก Unix ที่ไม่ถูกต้อง วิธีแก้ปัญหาที่เหมาะสมคือแทบไม่เคยให้สิทธิ์ dac_override
เลย เปลี่ยนสิทธิ์ยูนิกซ์ในไฟล์หรือกระบวนการ แทน โดเมนบางส่วน เช่น init
, vold
และ installd
จำเป็นต้องมีความสามารถในการแทนที่การอนุญาตไฟล์ยูนิกซ์เพื่อเข้าถึงไฟล์ของกระบวนการอื่นๆ ดู บล็อกของ Dan Walsh สำหรับคำอธิบายเชิงลึกเพิ่มเติม