SELinux ได้รับการตั้งค่าให้ปฏิเสธโดยค่าเริ่มต้น ซึ่งหมายความว่าการเข้าถึงแต่ละรายการที่มีฮุกในเคอร์เนลต้องได้รับอนุญาตโดยนโยบายอย่างชัดเจน ซึ่งหมายความว่าไฟล์นโยบายประกอบด้วยข้อมูลจำนวนมากเกี่ยวกับกฎ ประเภท คลาส สิทธิ์ และอื่นๆ การพิจารณา SELinux อย่างเต็มรูปแบบอยู่นอกขอบเขตของเอกสารนี้ แต่การทำความเข้าใจวิธีเขียนกฎนโยบายเป็นสิ่งจําเป็นเมื่อเปิดใช้อุปกรณ์ Android เครื่องใหม่ มีข้อมูลเกี่ยวกับ SELinux อยู่มากมายแล้ว ดูแหล่งข้อมูลที่แนะนำในเอกสารประกอบสนับสนุน
ไฟล์คีย์
หากต้องการเปิดใช้ SELinux ให้ผสานรวมเคอร์เนล Android เวอร์ชันล่าสุด แล้วรวมไฟล์ที่พบในไดเรกทอรี system/sepolicy เมื่อคอมไพล์แล้ว ไฟล์เหล่านั้นจะประกอบไปด้วยนโยบายความปลอดภัยเคอร์เนล SELinux และครอบคลุมระบบปฏิบัติการ Android เวอร์ชัน upstream
โดยทั่วไปแล้ว คุณไม่ควรแก้ไขไฟล์ 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
กำหนดป้ายกำกับให้กับไฟล์และคอมโพเนนต์ต่างๆ ของพื้นที่ผู้ใช้ใช้ เมื่อสร้างนโยบายใหม่ ให้สร้างหรืออัปเดตไฟล์นี้เพื่อกำหนดป้ายกำกับใหม่ให้กับไฟล์ หากต้องการใช้file_contexts
ใหม่ ให้สร้างอิมเมจระบบไฟล์ใหม่หรือเรียกใช้restorecon
ในไฟล์ที่จะติดป้ายกำกับใหม่ ในการอัปเกรด การเปลี่ยนแปลงในfile_contexts
จะมีผลกับพาร์ติชันระบบและพาร์ติชันข้อมูลผู้ใช้โดยอัตโนมัติโดยเป็นส่วนหนึ่งของการอัปเกรด นอกจากนี้ คุณยังใช้การเปลี่ยนแปลงโดยอัตโนมัติในการอัปเกรดไปยังพาร์ติชันอื่นๆ ได้ด้วยการเพิ่มการเรียกใช้restorecon_recursive
ลงในไฟล์ init.board.rc หลังจากที่ระบบได้ต่อเชื่อมพาร์ติชันแบบอ่าน/เขียนแล้วgenfs_contexts
กำหนดป้ายกำกับให้กับระบบไฟล์ เช่นproc
หรือvfat
ที่ไม่รองรับแอตทริบิวต์แบบขยาย ระบบจะโหลดการกําหนดค่านี้เป็นส่วนหนึ่งของนโยบายเคอร์เนล แต่การเปลี่ยนแปลงอาจไม่มีผลกับอินโนดในเคอร์เนล ซึ่งจะต้องรีบูตหรือยกเลิกการต่อเชื่อมและต่อเชื่อมระบบไฟล์อีกครั้งเพื่อให้การเปลี่ยนแปลงมีผลอย่างสมบูรณ์ นอกจากนี้ คุณยังกำหนดป้ายกำกับที่เจาะจงให้กับการต่อเชื่อมที่เจาะจงได้ด้วย เช่น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 เสมอมา คีย์สโตร์มีเนมสเปซที่อิงตาม UID/AID นอกจากนี้ Keystore 2.0 ยังบังคับใช้เนมสเปซที่กําหนดโดย sepolicy ด้วย ดูคำอธิบายโดยละเอียดเกี่ยวกับรูปแบบและรูปแบบของไฟล์นี้ได้ที่นี่
ไฟล์ Make ของ 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
- เปิดใช้ SELinux ในเคอร์เนล โดยทำดังนี้
CONFIG_SECURITY_SELINUX=y
- เปลี่ยนพารามิเตอร์ kernel_cmdline หรือ bootconfig เพื่อให้มีลักษณะดังนี้
หรือBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
การดำเนินการนี้มีไว้สําหรับการพัฒนานโยบายสําหรับอุปกรณ์ในระยะแรกเท่านั้น หลังจากมีนโยบายการบูตเริ่มต้นแล้ว ให้นำพารามิเตอร์นี้ออกเพื่อให้อุปกรณ์บังคับใช้หรือจะทดสอบไม่ผ่าน CTS ก็ได้BOARD_BOOTCONFIG := androidboot.selinux=permissive
- บูตระบบในโหมดอนุญาตและดูการปฏิเสธที่พบในการบูต
ใน Ubuntu 14.04 ขึ้นไป ให้ทำดังนี้ ใน Ubuntu 12.04adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- ประเมินผลลัพธ์เพื่อหาคำเตือนที่คล้ายกับ
init: Warning! Service name needs a SELinux domain defined; please fix!
ดูการตรวจสอบเพื่อดูวิธีการและเครื่องมือ - ระบุอุปกรณ์และไฟล์ใหม่อื่นๆ ที่ต้องติดป้ายกำกับ
- ใช้ป้ายกำกับที่มีอยู่หรือป้ายกำกับใหม่สำหรับวัตถุ ดูไฟล์
*_contexts
เพื่อดูว่าก่อนหน้านี้มีการติดป้ายกำกับรายการต่างๆ อย่างไร และใช้ความรู้เกี่ยวกับความหมายของป้ายกำกับเพื่อกำหนดป้ายกำกับใหม่ โดยปกติแล้ว ป้ายกำกับนี้ควรเป็นป้ายกำกับที่มีอยู่ซึ่งสอดคล้องกับนโยบาย แต่บางครั้งก็จำเป็นต้องมีป้ายกำกับใหม่และกฎสำหรับการเข้าถึงป้ายกำกับนั้น เพิ่มป้ายกำกับลงในไฟล์บริบทที่เหมาะสม - ระบุโดเมน/กระบวนการที่ควรมีโดเมนความปลอดภัยของตนเอง
คุณอาจต้องเขียนนโยบายใหม่ทั้งหมดสำหรับแต่ละรายการ ตัวอย่างเช่น บริการทั้งหมดที่เกิดจาก
init
ควรมี คำสั่งต่อไปนี้จะช่วยแสดงบริการที่ยังคงทำงานอยู่ (แต่บริการทั้งหมดต้องได้รับการดำเนินการดังกล่าว)
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- ตรวจสอบ
init.device.rc
เพื่อระบุโดเมนที่ไม่มีประเภทโดเมน กำหนดโดเมนให้แอปตั้งแต่เนิ่นๆ ในกระบวนการพัฒนาเพื่อหลีกเลี่ยงการเพิ่มกฎลงในinit
หรือทำให้การเข้าถึงinit
เกิดความสับสนกับสิทธิ์เข้าถึงที่อยู่ในนโยบายของแอป - ตั้งค่า
BOARD_CONFIG.mk
ให้ใช้ตัวแปรBOARD_SEPOLICY_*
ดูรายละเอียดเกี่ยวกับการตั้งค่านี้ได้ใน README ในsystem/sepolicy
- ตรวจสอบไฟล์ init.device.rc และ fstab.device และตรวจสอบว่าการใช้
mount
ทั้งหมดสอดคล้องกับระบบไฟล์ที่ติดป้ายกำกับอย่างถูกต้อง หรือมีการระบุตัวเลือกcontext= mount
- ตรวจสอบการปฏิเสธแต่ละรายการและสร้างนโยบาย SELinux เพื่อจัดการแต่ละรายการอย่างเหมาะสม ดูตัวอย่างในการปรับแต่ง
คุณควรเริ่มต้นด้วยนโยบายใน AOSP แล้วปรับแต่งตามต้องการ ดูข้อมูลเพิ่มเติมเกี่ยวกับกลยุทธ์ด้านนโยบายและดูรายละเอียดเพิ่มเติมเกี่ยวกับขั้นตอนเหล่านี้ได้ที่การเขียนนโยบาย SELinux
กรณีการใช้งาน
ตัวอย่างที่เฉพาะเจาะจงของการโจมตีที่ควรพิจารณาเมื่อสร้างซอฟต์แวร์ของคุณเองและนโยบาย SELinux ที่เกี่ยวข้องมีดังนี้
Symlink: เนื่องจาก 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