Xác thực SELinux

Android đặc biệt khuyến khích các OEM kiểm tra kỹ lưỡng việc triển khai SELinux của họ. Khi các nhà sản xuất triển khai SELinux, trước tiên họ nên áp dụng chính sách mới cho nhóm thiết bị thử nghiệm.

Sau khi áp dụng chính sách mới, hãy đảm bảo SELinux đang chạy ở chế độ chính xác trên thiết bị bằng cách ra lệnh getenforce .

Điều này in ra chế độ SELinux toàn cầu: Thực thi hoặc Cho phép. Để xác định chế độ SELinux cho từng miền, bạn phải kiểm tra các tệp tương ứng hoặc chạy phiên bản sepolicy-analyze mới nhất với cờ ( -p ) thích hợp, có trong /platform/system/sepolicy/tools/ .

Đọc từ chối

Kiểm tra lỗi, được định tuyến dưới dạng nhật ký sự kiện tới dmesglogcat và có thể xem được cục bộ trên thiết bị. Các nhà sản xuất nên kiểm tra đầu ra SELinux cho dmesg trên các thiết bị này và tinh chỉnh cài đặt trước khi phát hành công khai ở chế độ cho phép và cuối cùng là chuyển sang chế độ thực thi. Thông báo nhật ký SELinux chứa avc: và do đó có thể dễ dàng tìm thấy bằng grep . Có thể ghi lại nhật ký từ chối đang diễn ra bằng cách chạy cat /proc/kmsg hoặc ghi nhật ký từ chối từ lần khởi động trước bằng cách chạy cat /sys/fs/pstore/console-ramoops .

Thông báo lỗi SELinux bị giới hạn tốc độ sau khi khởi động xong để tránh làm xáo trộn nhật ký. Để đảm bảo bạn thấy tất cả các thông báo có liên quan, bạn có thể tắt tính năng này bằng cách chạy adb shell auditctl -r 0 .

Với kết quả đầu ra này, nhà sản xuất có thể dễ dàng xác định khi nào người dùng hoặc thành phần hệ thống vi phạm chính sách SELinux. Sau đó, các nhà sản xuất có thể sửa chữa hành vi xấu này bằng cách thay đổi phần mềm, chính sách SELinux hoặc cả hai.

Cụ thể, các thông báo nhật ký này cho biết quy trình nào sẽ không thành công trong chế độ thực thi và tại sao. Đây là một ví dụ:

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

Giải thích đầu ra này như vậy:

  • { connectto } ở trên thể hiện hành động đang được thực hiện. Cùng với tclass ở cuối ( unix_stream_socket ), nó cho bạn biết đại khái những gì đang được thực hiện và cái gì. Trong trường hợp này, có thứ gì đó đang cố gắng kết nối với ổ cắm luồng unix.
  • scontext (u:r:shell:s0) cho bạn biết bối cảnh nào đã bắt đầu hành động. Trong trường hợp này đây là thứ gì đó đang chạy dưới dạng shell.
  • tcontext (u:r:netd:s0) cho bạn biết ngữ cảnh của mục tiêu hành động. Trong trường hợp này, đó là unix_stream_socket thuộc sở hữu của netd .
  • comm="ping" ở trên cùng cung cấp cho bạn gợi ý bổ sung về những gì đang được chạy tại thời điểm từ chối được tạo ra. Trong trường hợp này, đó là một gợi ý khá hay.

Một vi dụ khac:

adb shell su root dmesg | grep 'avc: '

Đầu ra:

<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

Dưới đây là những yếu tố chính từ sự từ chối này:

  • Hành động - hành động đã thử được đánh dấu trong ngoặc, read write hoặc setenforce .
  • Diễn viên - Mục nhập scontext (ngữ cảnh nguồn) đại diện cho tác nhân, trong trường hợp này là daemon rmt_storage .
  • Đối tượng - Mục nhập tcontext (bối cảnh đích) đại diện cho đối tượng đang được xử lý, trong trường hợp này là kmem.
  • Kết quả - Mục nhập tclass (lớp đích) cho biết loại đối tượng đang được xử lý, trong trường hợp này là chr_file (thiết bị ký tự).

Kết xuất ngăn xếp người dùng và hạt nhân

Trong một số trường hợp, thông tin có trong nhật ký sự kiện không đủ để xác định nguồn gốc của việc từ chối. Việc thu thập chuỗi cuộc gọi, bao gồm kernel và không gian người dùng, thường rất hữu ích để hiểu rõ hơn lý do xảy ra tình trạng từ chối.

Các hạt nhân gần đây xác định một điểm theo dõi có tên avc:selinux_audited . Sử dụng Android simpleperf để kích hoạt điểm theo dõi này và nắm bắt chuỗi cuộc gọi.

Cấu hình được hỗ trợ

  • Nhân Linux >= 5.10, đặc biệt là dòng chính của nhánh Android Common Kernel và android12-5.10 được hỗ trợ. Nhánh android12-5.4 cũng được hỗ trợ. Bạn có thể sử dụng simpleperf để xác định xem tracepoint có được xác định trên thiết bị của bạn hay không: adb root && adb shell simpleperf list | grep avc:selinux_audited . Đối với các phiên bản kernel khác, bạn có thể chọn cam kết dd8166230969bc .
  • Có thể tái tạo sự kiện bạn đang gỡ lỗi. Các sự kiện thời gian khởi động không được hỗ trợ khi sử dụng Simpleperf; tuy nhiên bạn vẫn có thể khởi động lại dịch vụ để kích hoạt sự kiện.

Ghi lại chuỗi cuộc gọi

Bước đầu tiên là ghi lại sự kiện bằng cách sử dụng simpleperf record :

adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"

Sau đó, sự kiện gây ra sự từ chối sẽ được kích hoạt. Sau đó, việc ghi âm sẽ được dừng lại. Trong ví dụ này, bằng cách sử dụng Ctrl-c , mẫu sẽ được chụp:

^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.

Cuối cùng, simpleperf report có thể được sử dụng để kiểm tra dấu vết ngăn xếp đã ghi lại. Ví dụ:

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

Chuỗi cuộc gọi ở trên là chuỗi cuộc gọi hạt nhân và không gian người dùng hợp nhất. Nó cung cấp cho bạn cái nhìn rõ hơn về luồng mã bằng cách bắt đầu theo dõi từ không gian người dùng cho đến tận kernel nơi xảy ra việc từ chối. Để biết thêm thông tin về simpleperf , hãy xem tài liệu tham khảo về các lệnh có thể thực thi của Simpleperf

Chuyển sang cho phép

Việc thực thi SELinux có thể bị vô hiệu hóa thông qua ADB trên các bản dựng userdebug hoặc eng. Để làm như vậy, trước tiên hãy chuyển ADB sang root bằng cách chạy adb root . Sau đó, để vô hiệu hóa việc thực thi SELinux, hãy chạy:

adb shell setenforce 0

Hoặc tại dòng lệnh kernel (trong quá trình khởi động thiết bị sớm):

androidboot.selinux=permissive
androidboot.selinux=enforcing

Hoặc thông qua bootconfig trong Android 12:

androidboot.selinux=permissive
androidboot.selinux=enforcing

Sử dụng Audit2allow

Công cụ audit2allow xử lý các từ chối dmesg và chuyển đổi chúng thành các tuyên bố chính sách SELinux tương ứng. Như vậy, nó có thể tăng tốc độ phát triển SELinux rất nhiều.

Để sử dụng nó, hãy chạy:

adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy

Tuy nhiên, cần phải cẩn thận để kiểm tra từng phần bổ sung tiềm năng để phát hiện các quyền vượt mức. Ví dụ: cung cấp audit2allow từ chối rmt_storage được hiển thị trước đó trong tuyên bố chính sách SELinux được đề xuất sau:

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

Điều này sẽ cấp cho rmt khả năng ghi bộ nhớ kernel, một lỗ hổng bảo mật rõ ràng. Thông thường các câu lệnh audit2allow chỉ là điểm khởi đầu. Sau khi sử dụng các câu lệnh này, bạn có thể cần phải thay đổi miền nguồn và nhãn của đích cũng như kết hợp các macro thích hợp để đạt được chính sách tốt. Đôi khi việc từ chối được xem xét sẽ không dẫn đến bất kỳ thay đổi chính sách nào cả; thay vào đó ứng dụng vi phạm nên được thay đổi.