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 หรือทั้ง 2 อย่าง
โดยเฉพาะอย่างยิ่ง ข้อความบันทึกเหล่านี้จะระบุกระบวนการที่ล้มเหลวภายใต้โหมดบังคับใช้และเพราะเหตุใด มีตัวอย่างดังต่อไปนี้
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
) จะบอกให้คุณทราบคร่าวๆ ถึงสิ่งที่กำลังทำ ในกรณีนี้ มีบางอย่างพยายามเชื่อมต่อกับซ็อกเก็ตสตรีม Unix -
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
- ออบเจ็กต์ - รายการ
tcontext
(บริบทเป้าหมาย) แสดงถึงออบเจ็กต์ที่มีการดำเนินการ ซึ่งในกรณีนี้เป็น kmem - ผลลัพธ์ - รายการ
tclass
(คลาสเป้าหมาย) ระบุประเภทของออบเจ็กต์ที่มีการดำเนินการ ซึ่งในกรณีนี้คือchr_file
(อุปกรณ์ที่มีอักขระ)
แสดงผลสแต็กผู้ใช้และสแต็กเคอร์เนล
ในบางกรณี ข้อมูลที่อยู่ในบันทึกเหตุการณ์อาจไม่เพียงพอที่จะระบุที่มาของการปฏิเสธได้ คุณควรรวบรวมเชนการโทร รวมถึงเคอร์เนลและ Userspace ไว้ด้วย เพื่อให้เข้าใจสาเหตุของการปฏิเสธได้ดียิ่งขึ้น
เคอร์เนลล่าสุดกำหนดจุดติดตามชื่อ avc:selinux_audited
ใช้ Android simpleperf
เพื่อเปิดใช้ Tracepoint นี้และบันทึก Callchain
การกำหนดค่าที่รองรับ
- เคอร์เนลของ Linux >= 5.10 ใน Android Common Kernel Branch
mainline
และ
android12-5.10
โดยเฉพาะ
นอกจากนี้ ยังรองรับสาขา android12-5.4 ด้วย คุณสามารถใช้
simpleperf
เพื่อดูว่ามีการกําหนดจุดติดตามในอุปกรณ์หรือไม่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
อาจใช้เพื่อตรวจสอบสแต็กเทรซที่บันทึกไว้
เช่น
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 Executable
เปลี่ยนเป็นอนุญาต
คุณสามารถปิดใช้การบังคับใช้ SELinux ได้ด้วย adb ในรุ่น userdebug หรือ eng วิธีการคือต้องเปลี่ยน ADB ไปเป็นรูทโดยเรียกใช้ 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
ที่แสดงก่อนหน้านี้แก่ audit2allow
จะทำให้ได้ข้อความนโยบาย SELinux ที่แนะนำดังต่อไปนี้
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
การดำเนินการนี้จะช่วยให้ rmt
เขียนหน่วยความจำเคอร์เนลได้ ซึ่งเป็นช่องโหว่ด้านความปลอดภัยที่เห็นได้ชัด บ่อยครั้งที่คำสั่ง audit2allow
เป็นเพียงจุดเริ่มต้นเท่านั้น หลังจากใช้คำสั่งเหล่านี้ คุณอาจต้องเปลี่ยนโดเมนต้นทางและป้ายกำกับของเป้าหมาย รวมถึงใช้มาโครที่เหมาะสมเพื่อให้ได้นโยบายที่ดี บางครั้งการปฏิเสธที่อยู่ระหว่างการตรวจสอบไม่ควรส่งผลให้เกิดการเปลี่ยนแปลงนโยบายใดๆ เลย แต่ควรเปลี่ยนแปลงแอปที่ละเมิด