การใช้งาน SELinux

SELinux ได้รับการตั้งค่าเป็น default-deny ซึ่งหมายความว่าทุกๆ การเข้าถึงที่มี hook ในเคอร์เนลจะต้องได้รับอนุญาตอย่างชัดเจนจากนโยบาย ซึ่งหมายความว่าไฟล์นโยบายประกอบด้วยข้อมูลจำนวนมากเกี่ยวกับกฎ ประเภท คลาส สิทธิ์ และอื่นๆ การพิจารณา SELinux อย่างเต็มรูปแบบอยู่นอกขอบเขตของเอกสารนี้ แต่ความเข้าใจเกี่ยวกับวิธีการเขียนกฎนโยบายถือเป็นสิ่งสำคัญเมื่อนำอุปกรณ์ Android ใหม่มาใช้ มีข้อมูลมากมายเกี่ยวกับ SELinux อยู่แล้ว ดู เอกสารประกอบ สำหรับทรัพยากรที่แนะนำ

ไฟล์สำคัญ

หากต้องการเปิดใช้งาน SELinux ให้รวม เคอร์เนล Android ล่าสุด จากนั้นรวมไฟล์ที่พบในไดเร็กทอรี system/sepolicy เมื่อคอมไพล์ ไฟล์เหล่านั้นจะประกอบด้วยนโยบายความปลอดภัยเคอร์เนล SELinux และครอบคลุมระบบปฏิบัติการ Android ขั้นต้น

โดยทั่วไป คุณไม่ควรแก้ไขไฟล์ system/sepolicy โดยตรง ให้เพิ่มหรือแก้ไขไฟล์นโยบายเฉพาะอุปกรณ์ของคุณเองใน /device/ manufacturer / device-name /sepolicy ใน Android 8.0 และสูงกว่า การเปลี่ยนแปลงที่คุณทำกับไฟล์เหล่านี้ควรส่งผลต่อนโยบายในไดเรกทอรีผู้จำหน่ายของคุณเท่านั้น สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการแยกนโยบายสาธารณะใน Android 8.0 ขึ้นไป โปรดดูที่ การปรับแต่ง SEPolicy ใน Android 8.0 ขึ้น ไป ไม่ว่าเวอร์ชัน Android จะเป็นเช่นไร คุณยังคงแก้ไขไฟล์เหล่านี้:

ไฟล์นโยบาย

ไฟล์ที่ลงท้ายด้วย *.te คือไฟล์ต้นฉบับนโยบาย SELinux ซึ่งกำหนดโดเมนและป้ายกำกับ คุณอาจต้องสร้างไฟล์นโยบายใหม่ใน /device/ manufacturer / device-name /sepolicy แต่คุณควรพยายามอัปเดตไฟล์ที่มีอยู่หากเป็นไปได้

ไฟล์บริบท

ไฟล์บริบทคือที่ที่คุณระบุป้ายกำกับสำหรับออบเจ็กต์ของคุณ

  • file_contexts กำหนดป้ายกำกับให้กับไฟล์และถูกใช้โดยส่วนประกอบพื้นที่ผู้ใช้ต่างๆ เมื่อคุณสร้างนโยบายใหม่ ให้สร้างหรืออัปเดตไฟล์นี้เพื่อกำหนดป้ายกำกับใหม่ให้กับไฟล์ หากต้องการใช้ new file_contexts ให้สร้างอิมเมจระบบไฟล์ใหม่หรือรัน restorecon บนไฟล์ที่จะติดป้ายกำกับใหม่ ในการอัพเกรด การเปลี่ยนแปลง file_contexts จะถูกนำไปใช้กับระบบและพาร์ติชันข้อมูลผู้ใช้โดยอัตโนมัติโดยเป็นส่วนหนึ่งของการอัพเกรด การเปลี่ยนแปลงยังสามารถนำมาใช้โดยอัตโนมัติในการอัพเกรดเป็นพาร์ติชั่นอื่น ๆ โดยเพิ่มการเรียก restorecon_recursive ให้กับ init ของคุณ board .rc หลังจากที่พาร์ติชันถูกเมานต์อ่าน-เขียนแล้ว
  • genfs_contexts กำหนดป้ายกำกับให้กับระบบไฟล์ เช่น proc หรือ vfat ที่ไม่รองรับแอตทริบิวต์เพิ่มเติม การกำหนดค่านี้โหลดเป็นส่วนหนึ่งของนโยบายเคอร์เนล แต่การเปลี่ยนแปลงอาจไม่มีผลกับ in-core inodes ซึ่งจำเป็นต้องรีบูตหรือยกเลิกการต่อเชื่อมและติดตั้งระบบไฟล์ใหม่เพื่อใช้การเปลี่ยนแปลงโดยสมบูรณ์ ป้ายกำกับเฉพาะอาจถูกกำหนดให้กับการเมาท์เฉพาะ เช่น vfat โดยใช้ตัวเลือก context=mount
  • property_contexts กำหนดป้ายกำกับให้กับคุณสมบัติระบบ Android เพื่อควบคุมว่ากระบวนการใดบ้างที่สามารถตั้งค่าได้ การกำหนดค่านี้ถูกอ่านโดยกระบวนการ init ในระหว่างการเริ่มต้นระบบ
  • service_contexts กำหนดป้ายกำกับให้กับบริการ Binder ของ Android เพื่อควบคุมกระบวนการที่สามารถเพิ่ม (ลงทะเบียน) และค้นหา (ค้นหา) การอ้างอิง Binder สำหรับบริการ การกำหนดค่านี้ถูกอ่านโดยกระบวนการ servicemanager ระหว่างการเริ่มต้นระบบ
  • seapp_contexts กำหนดป้ายกำกับให้กับกระบวนการของแอปและไดเร็กทอรี /data/data การกำหนดค่านี้ถูกอ่านโดยกระบวนการ zygote ในการเปิดตัวแอปแต่ละครั้งและโดย installd ระหว่างการเริ่มต้นระบบ
  • mac_permissions.xml กำหนดแท็ก seinfo ให้กับแอปตามลายเซ็นและชื่อแพ็คเกจ (ไม่บังคับ) แท็ก seinfo สามารถใช้เป็นคีย์ในไฟล์ seapp_contexts เพื่อกำหนดป้ายกำกับเฉพาะให้กับแอปทั้งหมดที่มีแท็ก seinfo นั้น การกำหนดค่านี้ถูกอ่านโดย system_server ระหว่างการเริ่มต้นระบบ
  • keystore2_key_contexts กำหนดเลเบลให้กับเนมสเปซ Keystore 2.0 เนมสเปซเหล่านี้บังคับใช้โดย keystore2 daemon Keystore ให้เนมสเปซที่ใช้ UID/AID เสมอ Keystore 2.0 บังคับใช้เนมสเปซที่กำหนดโดย sepolicy เพิ่มเติม คำอธิบายโดยละเอียดเกี่ยวกับรูปแบบและแบบแผนของไฟล์นี้สามารถพบได้ ที่นี่

Makefile ของ BoardConfig.mk

หลังจากแก้ไขหรือเพิ่มไฟล์นโยบายและบริบท ให้อัปเดต /device/ manufacturer / device-name /BoardConfig.mk makefile ของคุณเพื่ออ้างอิงไดเร็กทอรีย่อย sepolicy และไฟล์นโยบายใหม่แต่ละไฟล์ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวแปร BOARD_SEPOLICY โปรดดูที่ ไฟล์ system/sepolicy/README

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

หลังจากสร้างใหม่ อุปกรณ์ของคุณเปิดใช้งานด้วย SELinux ตอนนี้คุณสามารถปรับแต่งนโยบาย SELinux ของคุณเพื่อรองรับการเพิ่มระบบปฏิบัติการ Android ของคุณเองตามที่อธิบายไว้ใน การปรับแต่ง หรือตรวจสอบการตั้งค่าที่มีอยู่ของคุณตามที่ครอบคลุมใน การตรวจสอบความถูกต้อง

เมื่อมีไฟล์นโยบายใหม่และการอัพเดต BoardConfig.mk การตั้งค่านโยบายใหม่จะถูกสร้างขึ้นในไฟล์นโยบายเคอร์เนลขั้นสุดท้ายโดยอัตโนมัติ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีสร้าง sepolicy บนอุปกรณ์ โปรดดูที่ การสร้าง sepolicy

การนำไปปฏิบัติ

ในการเริ่มต้นใช้งาน SELinux:

  1. เปิดใช้งาน SELinux ในเคอร์เนล: CONFIG_SECURITY_SELINUX=y
  2. เปลี่ยนพารามิเตอร์ kernel_cmdline หรือ bootconfig เพื่อให้:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    หรือ
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    นี่เป็นเพียงสำหรับการพัฒนานโยบายเบื้องต้นสำหรับอุปกรณ์เท่านั้น หลังจากที่คุณมีนโยบายบูตสแตรปเริ่มต้นแล้ว ให้ลบพารามิเตอร์นี้เพื่อให้อุปกรณ์ของคุณบังคับใช้ ไม่เช่นนั้น CTS จะล้มเหลว
  3. บู๊ตระบบโดยได้รับอนุญาตและดูว่ามีการปฏิเสธอะไรบ้างเมื่อบู๊ต:
    บน Ubuntu 14.04 หรือใหม่กว่า:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    บน Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. ประเมินผลลัพธ์สำหรับคำเตือนที่คล้ายกับ init: Warning! Service name needs a SELinux domain defined; please fix! ดู การตรวจสอบ สำหรับคำแนะนำและเครื่องมือ
  5. ระบุอุปกรณ์และไฟล์ใหม่อื่นๆ ที่จำเป็นต้องมีการติดป้ายกำกับ
  6. ใช้ป้ายกำกับที่มีอยู่หรือใหม่สำหรับออบเจ็กต์ของคุณ ดูไฟล์ *_contexts เพื่อดูว่าสิ่งต่าง ๆ ได้รับการติดป้ายกำกับก่อนหน้านี้อย่างไร และใช้ความรู้เกี่ยวกับความหมายของป้ายกำกับเพื่อกำหนดป้ายกำกับใหม่ ตามหลักการแล้ว นี่จะเป็นป้ายกำกับที่มีอยู่ซึ่งจะสอดคล้องกับนโยบาย แต่บางครั้งก็จำเป็นต้องมีป้ายกำกับใหม่และจำเป็นต้องมีกฎสำหรับการเข้าถึงป้ายกำกับนั้น เพิ่มป้ายกำกับของคุณลงในไฟล์บริบทที่เหมาะสม
  7. ระบุโดเมน/กระบวนการที่ควรมีโดเมนความปลอดภัยของตนเอง คุณอาจต้องเขียนนโยบายใหม่สำหรับแต่ละนโยบาย บริการทั้งหมดที่เกิดจาก init ควรมีเป็นของตัวเอง คำสั่งต่อไปนี้ช่วยเปิดเผยคำสั่งที่ยังคงทำงานอยู่ (แต่บริการทั้งหมดจำเป็นต้องได้รับการดูแลเช่นนี้):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. รีวิว init. device .rc เพื่อระบุโดเมนที่ไม่มีประเภทโดเมน มอบโดเมนแก่พวกเขา ตั้งแต่เนิ่นๆ ในกระบวนการพัฒนาของคุณ เพื่อหลีกเลี่ยงการเพิ่มกฎเพื่อ init หรือมิฉะนั้น ทำให้การเข้าถึง init สับสนกับกฎที่อยู่ในนโยบายของตนเอง
  9. ตั้งค่า BOARD_CONFIG.mk เพื่อใช้ตัวแปร BOARD_SEPOLICY_* ดู README ใน system/sepolicy สำหรับรายละเอียดเกี่ยวกับการตั้งค่านี้
  10. ตรวจสอบ init. device .rc และ fstab device และตรวจสอบให้แน่ใจว่าการใช้ mount ทุกครั้งสอดคล้องกับระบบไฟล์ที่มีป้ายกำกับอย่างถูกต้อง หรือระบุตัวเลือก context= mount
  11. ผ่านการปฏิเสธแต่ละครั้งและสร้างนโยบาย SELinux เพื่อจัดการแต่ละรายการอย่างเหมาะสม ดูตัวอย่างใน การปรับแต่ง

คุณควรเริ่มต้นด้วยนโยบายใน AOSP จากนั้นจึงต่อยอดจากนโยบายเหล่านั้นเพื่อการปรับแต่งของคุณเอง สำหรับข้อมูลเพิ่มเติมเกี่ยวกับกลยุทธ์นโยบายและการพิจารณาขั้นตอนเหล่านี้อย่างละเอียด โปรดดูที่ การเขียนนโยบาย SELinux

กรณีการใช้งาน

ต่อไปนี้คือตัวอย่างเฉพาะของการหาประโยชน์ที่ควรพิจารณาเมื่อสร้างซอฟต์แวร์ของคุณเองและนโยบาย SELinux ที่เกี่ยวข้อง:

Symlinks - เนื่องจาก Symlink ปรากฏเป็นไฟล์ จึงมักถูกอ่านเป็นไฟล์ ซึ่งอาจนำไปสู่การหาประโยชน์ได้ ตัวอย่างเช่น ส่วนประกอบที่ได้รับสิทธิพิเศษบางอย่าง เช่น init เปลี่ยนแปลงการอนุญาตของไฟล์บางไฟล์ ซึ่งบางครั้งก็เปิดมากเกินไป

ผู้โจมตีอาจแทนที่ไฟล์เหล่านั้นด้วยลิงก์สัญลักษณ์ไปยังโค้ดที่พวกเขาควบคุม ทำให้ผู้โจมตีสามารถเขียนทับไฟล์ที่กำหนดเองได้ แต่ถ้าคุณรู้ว่าแอปพลิเคชันของคุณจะไม่ข้ามผ่าน Symlink คุณสามารถห้ามไม่ให้ดำเนินการดังกล่าวด้วย SELinux

ไฟล์ระบบ - พิจารณาคลาสของไฟล์ระบบที่ควรแก้ไขโดยเซิร์ฟเวอร์ระบบเท่านั้น ถึงกระนั้น เนื่องจาก netd , init และ vold ทำงานในฐานะ root พวกเขาจึงสามารถเข้าถึงไฟล์ระบบเหล่านั้นได้ ดังนั้นหาก netd ถูกบุกรุก ก็อาจทำให้ไฟล์เหล่านั้นเสียหายและอาจรวมถึงเซิร์ฟเวอร์ระบบด้วย

ด้วย SELinux คุณสามารถระบุไฟล์เหล่านั้นเป็นไฟล์ข้อมูลเซิร์ฟเวอร์ระบบได้ ดังนั้น โดเมนเดียวที่มีสิทธิ์การเข้าถึงแบบอ่าน/เขียนคือเซิร์ฟเวอร์ระบบ แม้ว่า netd จะถูกโจมตี แต่ก็ไม่สามารถสลับโดเมนไปยังโดเมนเซิร์ฟเวอร์ระบบและเข้าถึงไฟล์ระบบเหล่านั้นได้แม้ว่าจะทำงานในฐานะรูทก็ตาม

ข้อมูลแอพ - อีกตัวอย่างหนึ่งคือคลาสของฟังก์ชันที่ต้องรันในฐานะรูท แต่ไม่ควรเข้าถึงข้อมูลแอพ สิ่งนี้มีประโยชน์อย่างเหลือเชื่อเนื่องจากสามารถยืนยันได้หลากหลาย เช่น โดเมนบางโดเมนที่ไม่เกี่ยวข้องกับข้อมูลแอปพลิเคชันถูกห้ามไม่ให้เข้าถึงอินเทอร์เน็ต

setattr - สำหรับคำสั่ง เช่น chmod และ chown คุณสามารถระบุชุดของไฟล์ที่โดเมนที่เกี่ยวข้องสามารถดำเนิน setattr ได้ สิ่งใดก็ตามนอกเหนือจากนั้นอาจถูกห้ามจากการเปลี่ยนแปลงเหล่านี้ แม้จะทำการรูตก็ตาม ดังนั้นแอปพลิเคชันอาจรัน chmod และ chown กับ app_data_files ที่มีป้ายกำกับ แต่ไม่ใช่ shell_data_files หรือ system_data_files