Android สนับสนุนอย่างยิ่งให้ OEM ทดสอบการใช้งาน SELinux อย่างละเอียด เนื่องจากผู้ผลิตใช้ SELinux พวกเขาควรใช้นโยบายใหม่กับกลุ่มทดสอบของอุปกรณ์ก่อน
หลังจากใช้นโยบายใหม่ ตรวจสอบให้แน่ใจว่า SELinux กำลังทำงานในโหมดที่ถูกต้องบนอุปกรณ์โดยออกคำสั่ง getenforce
สิ่งนี้พิมพ์โหมด SELinux ส่วนกลาง: การบังคับใช้หรืออนุญาต หากต้องการกำหนดโหมด SELinux สำหรับแต่ละโดเมน คุณต้องตรวจสอบไฟล์ที่เกี่ยวข้องหรือรัน sepolicy-analyze
เวอร์ชันล่าสุดด้วยแฟล็ก ( -p
) ที่เหมาะสม ซึ่งมีอยู่ใน /platform/system/sepolicy/tools/
การอ่านคำปฏิเสธ
ตรวจสอบข้อผิดพลาด ซึ่งถูกกำหนดเส้นทางเป็นบันทึกเหตุการณ์ไปยัง dmesg
และ logcat
และสามารถดูได้ในเครื่อง ผู้ผลิตควรตรวจสอบเอาต์พุต SELinux เป็น dmesg
บนอุปกรณ์เหล่านี้และปรับแต่งการตั้งค่าก่อนที่จะเผยแพร่สู่สาธารณะในโหมดอนุญาตและเปลี่ยนเป็นโหมดบังคับใช้ในที่สุด ข้อความบันทึกของ SELinux ประกอบด้วย avc:
และอาจพบ grep
ได้อย่างง่ายดาย เป็นไปได้ที่จะบันทึกบันทึกการปฏิเสธที่กำลังดำเนินอยู่โดยการเรียกใช้ cat /proc/kmsg
หรือบันทึกบันทึกการปฏิเสธจากการบูตครั้งก่อนโดยเรียกใช้ cat /sys/fs/pstore/console-ramoops
ข้อความแสดงข้อผิดพลาด SELinux จะถูกจำกัดอัตราหลังจากการบู๊ตเสร็จสิ้น เพื่อหลีกเลี่ยงการล้นบันทึก เพื่อให้แน่ใจว่าคุณเห็นข้อความที่เกี่ยวข้องทั้งหมด คุณสามารถปิดใช้งานได้โดยการเรียกใช้ adb shell auditctl -r 0
ด้วยเอาต์พุตนี้ ผู้ผลิตสามารถระบุได้ทันทีเมื่อผู้ใช้ระบบหรือส่วนประกอบละเมิดนโยบาย SELinux ผู้ผลิตสามารถแก้ไขลักษณะการทำงานที่ไม่ดีนี้ได้ โดยการเปลี่ยนแปลงซอฟต์แวร์ นโยบาย SELinux หรือทั้งสองอย่าง
โดยเฉพาะอย่างยิ่ง ข้อความบันทึกเหล่านี้ระบุว่ากระบวนการใดจะล้มเหลวภายใต้โหมดบังคับใช้และเพราะเหตุใด นี่คือตัวอย่าง:
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
ตีความผลลัพธ์เช่นนี้:
-
{ connectto }
ด้านบนแสดงถึงการดำเนินการที่กำลังดำเนินการ เมื่อรวมกับtclass
ในตอนท้าย (unix_stream_socket
) จะบอกคุณอย่างคร่าว ๆ ว่ากำลังทำอะไรกับอะไร ในกรณีนี้ มีบางอย่างพยายามเชื่อมต่อกับซ็อกเก็ตยูนิกซ์สตรีม -
scontext (u:r:shell:s0)
บอกคุณว่าบริบทใดที่เริ่มต้นการดำเนินการ ในกรณีนี้ นี่คือสิ่งที่ทำงานเป็นเชลล์ -
tcontext (u:r:netd:s0)
บอกคุณถึงบริบทของเป้าหมายของการกระทำ ในกรณีนี้ นั่นคือ unix_stream_socket ที่netd
เป็นเจ้าของ -
comm="ping"
ที่ด้านบนจะให้คำแนะนำเพิ่มเติมเกี่ยวกับสิ่งที่กำลังดำเนินการในขณะที่สร้างการปฏิเสธ ในกรณีนี้ มันเป็นคำแนะนำที่ดีทีเดียว
ตัวอย่างอื่น:
adb shell su root dmesg | grep 'avc: '
เอาท์พุต:
<5> type=1400 audit: avc: denied { read write } for pid=177 comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 tcontext=u:object_r:kmem_device:s0 tclass=chr_file
นี่คือองค์ประกอบสำคัญจากการปฏิเสธนี้:
- การกระทำ - การกระทำที่พยายามถูกเน้นในวงเล็บ
read write
หรือsetenforce
- นักแสดง - รายการ
scontext
(บริบทแหล่งที่มา) แสดงถึงนักแสดง ในกรณีนี้คือrmt_storage
daemon - วัตถุ - รายการ
tcontext
(บริบทเป้าหมาย) แสดงถึงวัตถุที่กำลังดำเนินการ ในกรณีนี้คือ kmem - ผลลัพธ์ - รายการ
tclass
(คลาสเป้าหมาย) ระบุประเภทของวัตถุที่ถูกดำเนินการ ในกรณีนี้คือchr_file
(อุปกรณ์อักขระ)
การทุ่มตลาดผู้ใช้และเคอร์เนลสแต็ค
ในบางกรณี ข้อมูลที่อยู่ในบันทึกเหตุการณ์ไม่เพียงพอที่จะระบุที่มาของการปฏิเสธ การรวบรวมสายเรียกเข้า รวมถึงเคอร์เนลและพื้นที่ผู้ใช้มักจะมีประโยชน์ เพื่อทำความเข้าใจว่าทำไมการปฏิเสธจึงเกิดขึ้น
เคอร์เนลล่าสุดกำหนด tracepoint ชื่อ avc:selinux_audited
ใช้ Android simpleperf
เพื่อเปิดใช้งาน tracepoint นี้และจับภาพ callchain
การกำหนดค่าที่รองรับ
- เคอร์เนล Linux >= 5.10 โดยเฉพาะอย่างยิ่ง Android Common Kernel สาขา mainline และ android12-5.10 ได้รับการสนับสนุน รองรับสาขา android12-5.4 คุณสามารถใช้
simpleperf
เพื่อระบุว่ามีการกำหนด tracepoint บนอุปกรณ์ของคุณหรือไม่:adb root && adb shell simpleperf list | grep avc:selinux_audited
สำหรับเคอร์เนลเวอร์ชันอื่น ๆ คุณสามารถเลือกยืนยันการกระทำและ dd81662 30969bc - ควรเป็นไปได้ที่จะจำลองเหตุการณ์ที่คุณกำลังแก้ไขจุดบกพร่อง เหตุการณ์เวลาบูตไม่ได้รับการสนับสนุนโดยใช้ simpleperf; อย่างไรก็ตาม คุณอาจยังคงสามารถเริ่มบริการใหม่เพื่อทริกเกอร์เหตุการณ์ได้
จับภาพห่วงโซ่การโทร
ขั้นตอนแรกคือการบันทึกเหตุการณ์โดยใช้ simpleperf record
:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
จากนั้นเหตุการณ์ที่ทำให้เกิดการปฏิเสธควรจะถูกกระตุ้น หลังจากนั้นควรหยุดการบันทึก ในตัวอย่างนี้ เมื่อใช้ Ctrl-c
ตัวอย่างควรจะถูกจับ:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
สุดท้าย อาจใช้ simpleperf report
เพื่อตรวจสอบ stacktrace ที่จับได้ ตัวอย่างเช่น:
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph" [...] Children Self Command Pid Tid Shared Object Symbol 100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init | -- __libc_init | -- main toybox_main toy_exec_which dmesg_main klogctl entry_SYSCALL_64_after_hwframe do_syscall_64 __x64_sys_syslog do_syslog selinux_syslog slow_avc_audit common_lsm_audit avc_audit_post_callback avc_audit_post_callback
ห่วงโซ่การโทรด้านบนเป็นเคอร์เนลแบบรวมและห่วงโซ่การโทรของยูสเซอร์สเปซ มันช่วยให้คุณมีมุมมองที่ดีขึ้นของการไหลของโค้ดโดยเริ่มการติดตามจาก userspace ไปจนถึงเคอร์เนลที่มีการปฏิเสธเกิดขึ้น สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ simpleperf
โปรดดูการ อ้างอิงคำสั่งปฏิบัติการ Simpleperf
เปลี่ยนเป็นอนุญาต
การบังคับใช้ SELinux สามารถปิดใช้งานได้ผ่าน ADB บน userdebug หรือ eng builds ในการทำเช่นนั้น ก่อนอื่นให้เปลี่ยน ADB เป็น root โดยเรียกใช้ adb root
จากนั้น หากต้องการปิดใช้งานการบังคับใช้ SELinux ให้เรียกใช้:
adb shell setenforce 0
หรือที่บรรทัดรับคำสั่งของเคอร์เนล (ระหว่างการเปิดใช้อุปกรณ์ในช่วงแรก):
androidboot.selinux=permissive
androidboot.selinux=enforcing
หรือผ่าน bootconfig ใน Android 12:
androidboot.selinux=permissive
androidboot.selinux=enforcing
การใช้audit2allow
เครื่องมือ audit2allow
รับการปฏิเสธ dmesg
และแปลงเป็นคำสั่งนโยบาย SELinux ที่สอดคล้องกัน ด้วยเหตุนี้ จึงสามารถเร่งการพัฒนา SELinux ได้อย่างมาก
หากต้องการใช้งาน ให้เรียกใช้:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
อย่างไรก็ตาม ต้องใช้ความระมัดระวังในการตรวจสอบการเพิ่มที่เป็นไปได้สำหรับการอนุญาตที่มากเกินไป ตัวอย่างเช่น การป้อน audit2allow
อนุญาตการปฏิเสธ rmt_storage
แสดงผลลัพธ์ก่อนหน้านี้ในคำสั่งนโยบาย SELinux ที่แนะนำต่อไปนี้:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
สิ่งนี้จะทำให้ rmt
สามารถเขียนหน่วยความจำเคอร์เนล ซึ่งเป็นช่องโหว่ด้านความปลอดภัยที่เห็นได้ชัด บ่อยครั้งที่คำสั่ง audit2allow
เป็นเพียงจุดเริ่มต้นเท่านั้น หลังจากใช้ข้อความเหล่านี้แล้ว คุณอาจต้องเปลี่ยนโดเมนต้นทางและป้ายกำกับของเป้าหมาย รวมทั้งรวมมาโครที่เหมาะสมเพื่อให้ได้นโยบายที่ดี บางครั้งการถูกปฏิเสธการตรวจสอบไม่ควรส่งผลให้เกิดการเปลี่ยนแปลงนโยบายใดๆ เลย ควรเปลี่ยนแอปพลิเคชันที่ละเมิด