ใช้งาน SELinux

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

ไฟล์สำคัญ

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

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

ไฟล์นโยบาย

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

ไฟล์บริบท

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

  • file_contexts จะกำหนดป้ายกำกับให้กับไฟล์และใช้โดยคอมโพเนนต์ต่างๆ ใน พื้นที่ผู้ใช้ เมื่อสร้างนโยบายใหม่ ให้สร้างหรืออัปเดตไฟล์นี้ เพื่อกำหนดป้ายกำกับใหม่ให้กับไฟล์ หากต้องการใช้ file_contexts ใหม่ ให้สร้างอิมเมจระบบไฟล์ใหม่หรือเรียกใช้ restorecon ในไฟล์ที่จะ ติดป้ายกำกับใหม่ เมื่ออัปเกรด ระบบจะนำการเปลี่ยนแปลงใน file_contexts ไปใช้กับพาร์ติชันระบบและพาร์ติชัน userdata โดยอัตโนมัติ ซึ่งเป็นส่วนหนึ่งของการอัปเกรด นอกจากนี้ คุณยังใช้การเปลี่ยนแปลงโดยอัตโนมัติเมื่ออัปเกรดเป็นพาร์ติชันอื่นๆ ได้ด้วย โดยเพิ่มrestorecon_recursiveการเรียกใช้boardไฟล์ init.rc หลังจากที่เมานต์พาร์ติชันเป็นแบบอ่าน/เขียนแล้ว
  • genfs_contexts กำหนดป้ายกำกับให้กับระบบไฟล์ เช่น proc หรือ vfat ที่ไม่รองรับแอตทริบิวต์ แบบขยาย การกำหนดค่านี้จะโหลดเป็นส่วนหนึ่งของนโยบายเคอร์เนล แต่การเปลี่ยนแปลงอาจไม่มีผลกับ Inode ในแกนกลาง ซึ่งต้องรีบูตหรือ ยกเลิกการเชื่อมต่อและเชื่อมต่อระบบไฟล์ใหม่เพื่อให้การเปลี่ยนแปลงมีผลอย่างเต็มที่ นอกจากนี้ คุณยังกำหนดป้ายกำกับที่เฉพาะเจาะจงให้กับเมานต์ที่เฉพาะเจาะจงได้ด้วย เช่น 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 keystore2 Daemon จะบังคับใช้เนมสเปซเหล่านี้ Keystore มีเนมสเปซที่อิงตาม UID/AID มาโดยตลอด นอกจากนี้ Keystore 2 ยังบังคับใช้ 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 ที่เกี่ยวข้องมีดังนี้

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

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

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

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

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

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