กำลังตรวจสอบ SELinux

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) จะบอกให้คุณทราบคร่าวๆ ถึงสิ่งที่มีการดำเนินการ เพื่ออะไร ในกรณีนี้ มีบางอย่างพยายามเชื่อมต่อกับซ็อกเก็ตสตรีม 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 (อุปกรณ์อักขระ)

การดัมพ์ผู้ใช้และกลุ่มเคอร์เนล

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

เคอร์เนลล่าสุดกำหนดจุดติดตามชื่อ avc:selinux_audited ใช้ Android simpleperf เพื่อเปิดใช้ Tracepoint นี้และบันทึก Callchain

การกำหนดค่าที่รองรับ

  • เคอร์เนลของ Linux >= 5.10 สำหรับ Android Common Kernel Branch เมนไลน์ และ Android12-5.10 ได้ Android12-5.4 Branch ก็รับการสนับสนุนได้เช่นกัน คุณอาจใช้ 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 แบบรวม ช่วยให้คุณได้รับประสบการณ์การใช้งาน ดูโฟลว์ของโค้ดได้โดยเริ่มต้นการติดตามจาก userspace ลงไปจนถึงเคอร์เนล การปฏิเสธก็เกิดขึ้น ดูข้อมูลเพิ่มเติมเกี่ยวกับ simpleperf ได้ที่ การอ้างอิงคำสั่ง Simpleperf Executable

กำลังเปลี่ยนเป็นแบบไม่เข้มงวด

การบังคับใช้ SELinux สามารถปิดใช้ผ่าน ADB ในบิลด์การแก้ไขข้อบกพร่องของผู้ใช้หรือสร้างวิศวกร (ภาษาอังกฤษ) โดยดำเนินการดังนี้ ก่อนอื่นให้เปลี่ยน 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 แสดงขึ้นก่อนหน้านี้ในผลลัพธ์ต่อไปนี้ คำชี้แจงนโยบาย SELinux ที่แนะนำ

#============= shell ==============
allow shell kernel:security setenforce;
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };

การดำเนินการนี้จะทำให้ rmt เขียนหน่วยความจำเคอร์เนลได้ ช่องโหว่ด้านความปลอดภัยที่เห็นได้ชัด บ่อยครั้งที่คำสั่ง audit2allow เป็นเพียง จุดเริ่มต้น หลังจากใช้ข้อความเหล่านี้แล้ว คุณอาจต้องเปลี่ยน โดเมนต้นทางและป้ายกำกับของเป้าหมาย รวมทั้งรวม เพื่อให้ได้นโยบายที่ดี บางครั้งการปฏิเสธที่กำลังตรวจสอบควร ไม่ส่งผลให้เกิดการเปลี่ยนแปลงนโยบายใดๆ แอปพลิเคชันที่ไม่เหมาะสม ควรเปลี่ยน