สร้างนโยบาย SELinux

หน้านี้จะอธิบายวิธีสร้างนโยบาย SELinux นโยบาย SELinux สร้างขึ้นจากนโยบายหลักของ AOSP (แพลตฟอร์ม) และนโยบายเฉพาะอุปกรณ์ (ผู้ให้บริการ) ขั้นตอนการบิลด์นโยบาย SELinux สำหรับ Android 4.4 ถึง Android 7.0 จะผสานกลุ่ม sepolicy ทั้งหมด แล้วสร้างไฟล์แบบโมโนลิธิคในไดเรกทอรีรูท ซึ่งหมายความว่าผู้ให้บริการ SoC และผู้ผลิต ODM ต้องแก้ไข boot.img (สำหรับอุปกรณ์ที่ไม่ใช่ A/B) หรือ system.img (สำหรับอุปกรณ์ A/B) ทุกครั้งที่มีการเปลี่ยนแปลงนโยบาย

ใน Android 8.0 ขึ้นไป ระบบจะสร้างนโยบายแพลตฟอร์มและนโยบายของผู้ให้บริการแยกกัน SOC และ OEM สามารถอัปเดตนโยบายส่วนของตน สร้างรูปภาพ (เช่น vendor.img และ boot.img) จากนั้นอัปเดตรูปภาพเหล่านั้นโดยไม่ขึ้นอยู่กับการอัปเดตแพลตฟอร์ม

อย่างไรก็ตาม เนื่องจากไฟล์นโยบาย SELinux แบบโมดูลจะจัดเก็บไว้ในพาร์ติชัน /vendor กระบวนการ init จึงต้องเมานต์พาร์ติชันระบบและพาร์ติชันของผู้ให้บริการก่อนเพื่อให้อ่านไฟล์ SELinux จากพาร์ติชันเหล่านั้นและผสานกับไฟล์ SELinux หลักในไดเรกทอรีระบบได้ (ก่อนที่จะโหลดลงในเคอร์เนล)

ไฟล์ต้นฉบับ

ตรรกะในการสร้าง SELinux อยู่ในไฟล์ต่อไปนี้

  • external/selinux: โปรเจ็กต์ SELinux ภายนอก ซึ่งใช้สําหรับสร้างยูทิลิตีบรรทัดคําสั่งของ HOST เพื่อคอมไพล์นโยบายและป้ายกํากับ SELinux
    • external/selinux/libselinux: Android ใช้เฉพาะชุดย่อยของโปรเจ็กต์ libselinux ภายนอกพร้อมกับการปรับแต่งบางอย่างสำหรับ Android โดยเฉพาะ โปรดดูรายละเอียดที่หัวข้อ external/selinux/README.android
    • external/selinux/libsepol:
      • chkcon: ระบุว่าบริบทความปลอดภัยถูกต้องสำหรับนโยบายไบนารีที่ระบุ (ไฟล์ปฏิบัติการของโฮสต์) หรือไม่
      • libsepol: ไลบรารี SELinux สำหรับจัดการนโยบายความปลอดภัยแบบไบนารี (ไลบรารีแบบคงที่/ที่ใช้ร่วมกันของโฮสต์ ไลบรารีแบบคงที่ของเป้าหมาย)
    • external/selinux/checkpolicy: คอมไพเลอร์นโยบาย SELinux (ไฟล์ปฏิบัติการของโฮสต์: checkpolicy, checkmodule และ dispol) ขึ้นอยู่กับ libsepol
  • system/sepolicy: การกําหนดค่านโยบาย SELinux หลักของ Android ซึ่งรวมถึงบริบทและไฟล์นโยบาย ตรรกะการสร้างนโยบายความปลอดภัยที่สำคัญก็อยู่ที่นี่ด้วย (system/sepolicy/Android.mk)

ดูรายละเอียดเพิ่มเติมเกี่ยวกับไฟล์ได้ในsystem/sepolicy การใช้ SELinux

Android 7.x และต่ำกว่า

ส่วนนี้จะอธิบายวิธีสร้างนโยบาย SELinux ใน Android 7.x และเวอร์ชันก่อนหน้า

กระบวนการสร้างสำหรับ Android 7.x และต่ำกว่า

นโยบาย SELinux สร้างขึ้นโดยการรวมนโยบายหลักของ AOSP เข้ากับการปรับแต่งเฉพาะอุปกรณ์ จากนั้นระบบจะส่งนโยบายที่รวมเข้าด้วยกันไปยังคอมไพเลอร์นโยบายและโปรแกรมตรวจสอบต่างๆ การปรับแต่งเฉพาะอุปกรณ์ทำได้ผ่านตัวแปร BOARD_SEPOLICY_DIRS ที่กําหนดไว้ในไฟล์ Boardconfig.mk เฉพาะอุปกรณ์ ตัวแปรบิลด์ส่วนกลางนี้มีรายการไดเรกทอรีที่ระบุลําดับการค้นหาไฟล์นโยบายเพิ่มเติม

ตัวอย่างเช่น ผู้ให้บริการ SoC และ ODM อาจเพิ่มไดเรกทอรีแต่ละรายการ โดยไดเรกทอรีหนึ่งสำหรับการตั้งค่าเฉพาะ SoC และอีกไดเรกทอรีหนึ่งสำหรับการตั้งค่าเฉพาะอุปกรณ์ เพื่อสร้างการกำหนดค่า SELinux สุดท้ายสำหรับอุปกรณ์หนึ่งๆ ดังนี้

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

ระบบจะต่อเนื้อหาของไฟล์ file_contexts ใน system/sepolicy และ BOARD_SEPOLICY_DIRS เข้าด้วยกันเพื่อสร้างไฟล์ file_contexts.bin ในอุปกรณ์

รูปภาพนี้แสดงตรรกะการสร้าง SELinux สำหรับ Android 7.x

รูปที่ 1 ตรรกะการสร้าง SELinux

ไฟล์ sepolicy ประกอบด้วยไฟล์ต้นฉบับหลายไฟล์ ดังนี้

  • ระบบจะสร้างข้อความธรรมดา policy.conf โดยการต่อไฟล์ security_classes, initial_sids, *.te, genfs_contexts และ port_contexts ตามลำดับ
  • สำหรับแต่ละไฟล์ (เช่น security_classes) เนื้อหาของไฟล์จะเกิดจากการต่อไฟล์ที่มีชื่อเดียวกันในส่วน system/sepolicy/ และ BOARDS_SEPOLICY_DIRS
  • ระบบจะส่ง policy.conf ไปยังคอมไพเลอร์ SELinux เพื่อตรวจสอบไวยากรณ์และคอมไพล์เป็นรูปแบบไบนารีเป็น sepolicy ในอุปกรณ์
    รูปภาพนี้แสดงไฟล์ที่สร้างไฟล์นโยบาย SELinux สำหรับ Android 7.x

    รูปที่ 2 ไฟล์นโยบาย SELinux

ไฟล์ SELinux

หลังจากคอมไพล์แล้ว อุปกรณ์ Android ที่ใช้ 7.x และเวอร์ชันก่อนหน้ามักจะมีไฟล์ต่อไปนี้ที่เกี่ยวข้องกับ SELinux

  • selinux_version
  • sepolicy: เอาต์พุตไบนารีหลังจากรวมไฟล์นโยบาย (เช่น security_classes, initial_sids และ *.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

โปรดดูรายละเอียดเพิ่มเติมที่หัวข้อการใช้ SELinux

การเริ่มต้น SELinux

เมื่อระบบบูตขึ้น SELinux จะอยู่ในโหมดอนุญาต (ไม่ใช่โหมดบังคับใช้) กระบวนการ init จะทํางานต่อไปนี้

  • โหลดไฟล์ sepolicy จากแรมดิสก์ลงในเคอร์เนลผ่าน /sys/fs/selinux/load
  • เปลี่ยน SELinux เป็นโหมดบังคับใช้
  • เรียกใช้ re-exec() เพื่อใช้กฎโดเมน SELinux กับตนเอง

หากต้องการลดเวลาในการบูต ให้ดำเนินการre-exec()ในinitโดยเร็วที่สุด

Android 8.0 ขึ้นไป

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

sepolicy ของแพลตฟอร์มจะแยกออกเป็นส่วนแพลตฟอร์มแบบส่วนตัวและแบบสาธารณะเพื่อส่งออกประเภทและแอตทริบิวต์ที่เฉพาะเจาะจงไปยังผู้เขียนนโยบายของผู้ให้บริการ เรารับประกันว่าประเภท/แอตทริบิวต์สาธารณะของแพลตฟอร์มจะได้รับการบำรุงรักษาให้เป็น API ที่เสถียรสำหรับเวอร์ชันแพลตฟอร์มหนึ่งๆ คุณสามารถรับประกันความเข้ากันได้กับประเภท/แอตทริบิวต์สาธารณะของแพลตฟอร์มเวอร์ชันก่อนหน้าได้หลายเวอร์ชันโดยใช้ไฟล์การแมปแพลตฟอร์ม

กระบวนการบิลด์สำหรับ Android 8.0

นโยบาย SELinux ใน Android 8.0 สร้างขึ้นโดยการรวมชิ้นส่วนจาก /system และ /vendor ตรรกะในการตั้งค่านี้อย่างเหมาะสมอยู่ใน /platform/system/sepolicy/Android.mk

นโยบายมีอยู่ในตำแหน่งต่อไปนี้

ตำแหน่ง ประกอบด้วย
system/sepolicy/public sepolicy API ของแพลตฟอร์ม
system/sepolicy/private รายละเอียดการติดตั้งใช้งานแพลตฟอร์ม (ผู้ให้บริการสามารถละเว้นได้)
system/sepolicy/vendor ไฟล์นโยบายและบริบทที่ผู้ให้บริการใช้ได้ (ผู้ให้บริการสามารถละเว้นได้หากต้องการ)
BOARD_SEPOLICY_DIRS นโยบายความปลอดภัยของผู้ให้บริการ
BOARD_ODM_SEPOLICY_DIRS (Android 9 ขึ้นไป) Odm sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 ขึ้นไป) sepolicy API ของ System_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 ขึ้นไป) รายละเอียดการใช้งาน System_ext (ผู้ให้บริการสามารถละเว้นได้)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 ขึ้นไป) sepolicy API ของผลิตภัณฑ์
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 ขึ้นไป) รายละเอียดการติดตั้งใช้งานผลิตภัณฑ์ (ผู้ให้บริการสามารถละเว้นได้)

ระบบบิลด์จะใช้นโยบายนี้เพื่อสร้างคอมโพเนนต์นโยบาย system, system_ext, product, vendor และ odm ในพาร์ติชันที่เกี่ยวข้อง ขั้นตอนต่างๆ มีดังนี้

  1. การเปลี่ยนนโยบายเป็นรูปแบบ Common Intermediate Language (CIL) ของ SELinux โดยเฉพาะอย่างยิ่งในกรณีต่อไปนี้
    1. นโยบายแพลตฟอร์มสาธารณะ (system + system_ext + product)
    2. นโยบายสาธารณะและนโยบายส่วนตัวรวมกัน
    3. นโยบายสาธารณะ + ผู้ให้บริการและ BOARD_SEPOLICY_DIRS
  2. การกำหนดเวอร์ชันนโยบายที่เผยแพร่ต่อสาธารณะซึ่งเป็นส่วนหนึ่งของนโยบายของผู้ให้บริการ ดำเนินการโดยใช้นโยบาย CIL สาธารณะที่ผลิตเพื่อแจ้งนโยบายแบบรวมสาธารณะ + ผู้ให้บริการ + BOARD_SEPOLICY_DIRS ว่าต้องเปลี่ยนส่วนใดให้กลายเป็นแอตทริบิวต์ที่จะลิงก์กับนโยบายแพลตฟอร์ม
  3. การสร้างไฟล์การแมปที่ลิงก์ส่วนแพลตฟอร์มและส่วนผู้ให้บริการ ในช่วงแรก การดำเนินการนี้จะลิงก์ประเภทจากนโยบายสาธารณะกับแอตทริบิวต์ที่เกี่ยวข้องในนโยบายของผู้ให้บริการ หลังจากนั้นจะใช้เป็นพื้นฐานสำหรับไฟล์ที่ดูแลรักษาในแพลตฟอร์มเวอร์ชันในอนาคตด้วย ซึ่งจะช่วยให้ใช้งานร่วมกับนโยบายของผู้ให้บริการที่กำหนดเป้าหมายเป็นแพลตฟอร์มเวอร์ชันนี้ได้
  4. การรวมไฟล์นโยบาย (อธิบายทั้งโซลูชันในอุปกรณ์และโซลูชันที่คอมไพล์ไว้ล่วงหน้า)
    1. รวมการแมป นโยบายแพลตฟอร์ม และนโยบายของผู้ให้บริการ
    2. คอมไพล์ไฟล์นโยบายไบนารีเอาต์พุต

นโยบายความปลอดภัยสาธารณะของแพลตฟอร์ม

นโยบายความปลอดภัยสาธารณะของแพลตฟอร์มจะรวมทุกอย่างที่กําหนดไว้ในส่วน system/sepolicy/public แพลตฟอร์มจะถือว่าประเภทและแอตทริบิวต์ที่กําหนดไว้ในนโยบายสาธารณะเป็น API ที่เสถียรสําหรับแพลตฟอร์มเวอร์ชันหนึ่งๆ ข้อมูลนี้เป็นส่วนหนึ่งของ sepolicy ที่แพลตฟอร์มส่งออก ซึ่งนักพัฒนานโยบายของเวนเดอร์ (นั่นคือ อุปกรณ์) อาจเขียนนโยบายเฉพาะอุปกรณ์เพิ่มเติมได้

ประเภทจะมีเวอร์ชันตามเวอร์ชันของนโยบายที่ใช้เขียนไฟล์ของผู้ให้บริการ ซึ่งกำหนดโดยPLATFORM_SEPOLICY_VERSIONตัวแปรบิลด์ จากนั้นนโยบายสาธารณะเวอร์ชันดังกล่าวจะรวมอยู่ในนโยบายของผู้ให้บริการและ (ในรูปแบบต้นฉบับ) ในนโยบายแพลตฟอร์ม ดังนั้น นโยบายสุดท้ายจึงประกอบด้วยนโยบายแพลตฟอร์มส่วนตัว นโยบายความปลอดภัยสาธารณะของแพลตฟอร์มปัจจุบัน นโยบายเฉพาะอุปกรณ์ และนโยบายสาธารณะเวอร์ชันที่สอดคล้องกับเวอร์ชันแพลตฟอร์มที่เขียนนโยบายอุปกรณ์

นโยบายความปลอดภัยส่วนตัวของแพลตฟอร์ม

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

การแมปแบบส่วนตัวของแพลตฟอร์ม

การแมปแบบส่วนตัวของแพลตฟอร์มประกอบด้วยข้อความนโยบายที่แมปแอตทริบิวต์ที่แสดงในนโยบายสาธารณะของแพลตฟอร์มในเวอร์ชันก่อนหน้าของแพลตฟอร์มกับประเภทที่เฉพาะเจาะจงซึ่งใช้ในนโยบายความปลอดภัยสาธารณะของแพลตฟอร์มปัจจุบัน วิธีนี้ช่วยให้มั่นใจว่านโยบายของผู้ให้บริการที่เขียนขึ้นตามแอตทริบิวต์สาธารณะของแพลตฟอร์มจากเวอร์ชันนโยบายการรักษาความปลอดภัยสาธารณะของแพลตฟอร์มก่อนหน้าจะยังคงใช้งานได้ต่อไป การกำหนดเวอร์ชันจะอิงตามPLATFORM_SEPOLICY_VERSIONตัวแปรบิลด์ ที่ตั้งค่าไว้ใน AOSP สำหรับเวอร์ชันแพลตฟอร์มหนึ่งๆ มีไฟล์การแมปแยกต่างหากสำหรับแพลตฟอร์มเวอร์ชันก่อนหน้าแต่ละเวอร์ชันที่คาดว่าแพลตฟอร์มนี้จะยอมรับนโยบายของผู้ให้บริการ โปรดดูรายละเอียดเพิ่มเติมที่หัวข้อความเข้ากันได้

Android 11 ขึ้นไป

system_ext และ product sepolicy

ใน Android 11 ระบบจะเพิ่มนโยบาย system_ext และนโยบายผลิตภัณฑ์ เช่นเดียวกับ platform sepolicy นโยบาย system_ext และนโยบายผลิตภัณฑ์จะแบ่งออกเป็นนโยบายสาธารณะและนโยบายส่วนตัว

ระบบจะส่งออกนโยบายสาธารณะไปยังผู้ให้บริการ ประเภทและแอตทริบิวต์จะกลายเป็น API ที่เสถียร และนโยบายของผู้ให้บริการจะอ้างอิงประเภทและแอตทริบิวต์ในนโยบายสาธารณะได้ ประเภทต่างๆ จะมีการระบุเวอร์ชันตาม PLATFORM_SEPOLICY_VERSION และนโยบายเวอร์ชันดังกล่าวจะรวมอยู่ในนโยบายของผู้ให้บริการ นโยบายเดิมจะรวมอยู่ในพาร์ติชัน system_ext และ product แต่ละพาร์ติชัน

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

การแมป system_ext และผลิตภัณฑ์

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

  • หากต้องการติดตั้งไฟล์การแมปสําหรับ system_ext ให้วางไฟล์ cil ที่มีข้อมูลการแมปที่ต้องการลงใน {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil แล้วเพิ่ม system_ext_{ver}.cil ลงใน PRODUCT_PACKAGES
  • หากต้องการติดตั้งไฟล์การแมปสำหรับผลิตภัณฑ์ ให้วางไฟล์ cil ที่มีข้อมูลการแมปที่ต้องการลงใน {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil แล้วเพิ่ม product_{ver}.cil ลงใน PRODUCT_PACKAGES

โปรดดูตัวอย่างซึ่งเพิ่มไฟล์การแมปของพาร์ติชันผลิตภัณฑ์ของอุปกรณ์ Redbull

นโยบาย SELinux ที่คอมไพล์ไว้ล่วงหน้า

ก่อนที่ init จะเปิด SELinux init จะรวบรวมไฟล์ CIL ทั้งหมดจากพาร์ติชัน (system, system_ext, product, vendor และ odm) และคอมไพล์เป็นนโยบายแบบไบนารี ซึ่งเป็นรูปแบบที่โหลดลงในเคอร์เนลได้ เนื่องจากการคอมไพล์ต้องใช้เวลา (โดยปกติ 1-2 วินาที) ระบบจะคอมไพล์ไฟล์ CIL ล่วงหน้า ณ เวลาที่สร้าง และวางไฟล์ที่ /vendor/etc/selinux/precompiled_sepolicy หรือ /odm/etc/selinux/precompiled_sepolicy พร้อมกับแฮช sha256 ของไฟล์ CIL อินพุต ขณะรันไทม์ init จะตรวจสอบว่าไฟล์นโยบายมีการอัปเดตหรือไม่โดยเปรียบเทียบแฮช หากไม่มีการเปลี่ยนแปลงใดๆ init จะโหลดนโยบายที่คอมไพล์ไว้ล่วงหน้า หากไม่มี init จะคอมไพล์ขณะทำงานและใช้ไฟล์นั้นแทนไฟล์ที่คอมไพล์ไว้ล่วงหน้า

กล่าวโดยละเอียดคือ ระบบจะใช้นโยบายที่คอมไพล์ไว้ล่วงหน้าหากเป็นไปตามเงื่อนไขต่อไปนี้ทั้งหมด ในที่นี้ {partition} แสดงถึงพาร์ติชันที่มีนโยบายที่คอมไพล์ไว้ล่วงหน้า ซึ่งก็คือ vendor หรือ odm

  • ทั้ง /system/etc/selinux/plat_sepolicy_and_mapping.sha256 และ /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 มีอยู่และเหมือนกัน
  • ทั้ง /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 และ /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 ไม่มีอยู่ หรือมีทั้งสองรายการและเหมือนกัน
  • ทั้ง /product/etc/selinux/product_sepolicy_and_mapping.sha256 และ /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 ไม่มีอยู่ หรือมีทั้งสองรายการและเหมือนกัน

หากค่าใดค่าหนึ่งไม่ตรงกัน init จะกลับไปใช้เส้นทางการคอมไพล์ในอุปกรณ์ ดูรายละเอียดเพิ่มเติมได้ที่ system/core/init/selinux.cpp