Xác thực SELinux

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

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

Thao tác này sẽ in chế độ SELinux toàn cục: Thực thi hoặc Cho phép. Người nhận cho mỗi miền, bạn phải kiểm tra chế độ SELinux tương ứng. hoặc chạy phiên bản mới nhất của sepolicy-analyze bằng cờ thích hợp (-p), hiển thị trong /platform/system/sepolicy/tools/.

Thông báo từ chối đọc

Kiểm tra lỗi. Các lỗi này được định tuyến dưới dạng nhật ký sự kiện đến dmesglogcat và có thể xem được trên thiết bị. Nhà sản xuất phải kiểm tra đầu ra SELinux sang dmesg trên các thiết bị này và tinh chỉnh chế độ cài đặt trước khi phát hành công khai ở chế độ không bắt buộc và chuyển đổi cuối cùng sang chế độ thực thi. Thông điệp nhật ký SELinux chứa avc: nên có thể dễ dàng được tìm thấy nhờ grep. Bạn có thể nắm bắt các nhật ký từ chối bằng cách chạy cat /proc/kmsg hoặc ghi lại 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ỷ lệ sau khi khởi động xong để tránh tình trạng tràn ngập 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ả này, nhà sản xuất có thể dễ dàng xác định thời điểm người dùng hệ thống hoặc thành phần nào vi phạm chính sách SELinux. Sau đó, nhà sản xuất có thể sửa chữa hành vi xấu này, do thay đổi đối với phần mềm, chính sách SELinux hoặc cả hai.

Cụ thể, những thông điệp nhật ký này cho biết những quy trình sẽ không thành công trong chế độ thực thi và lý do. Dưới đây là 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

Diễn giải kết quả này như sau:

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

Ví dụ khác:

adb shell su root dmesg | grep 'avc: '

Kết quả:

<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à các yếu tố chính trong quyết định từ chối này:

  • Hành động – hành động đã thử được đánh dấu trong dấu ngoặc đơn, read write hoặc setenforce.
  • Actor (Tác nhân) – Mục scontext (ngữ cảnh nguồn) biểu thị tác nhân, trong trường hợp này là trình nền rmt_storage.
  • Object (Đối tượng) – Mục nhập tcontext (ngữ cảnh mục tiêu) biểu thị đối tượng đang được tác dụng, trong trường hợp này là kmem.
  • Kết quả – Mục tclass (lớp mục tiêu) cho biết loại của đối tượng đang được thực hiện, 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à ngăn xếp hạt nhân

Trong một số trường hợp, thông tin trong nhật ký sự kiện không đủ để xác định nguồn gốc của thông báo từ chối. Thường thì bạn nên thu thập chuỗi lệnh gọi, bao gồm cả kernel và người dùng, để hiểu rõ hơn lý do 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. Dùng Android simpleperf để bật điểm theo dõi này và ghi lại chuỗi lệnh gọi.

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

  • Nhân Linux >= 5.10, cụ thể là các nhánh Hạt nhân phổ biến của Android đường chínhandroid12 – 5.10 được hỗ trợ. android12-5.4 nhánh cũng được hỗ trợ. Bạn có thể dùng simpleperf để xác định xem điểm theo dõi có đang được xác định trên thiết bị của bạn: 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 mà bạn đang gỡ lỗi. Sự kiện thời gian khởi động không được hỗ trợ 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 lệnh gọi

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

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

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

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

Cuối cùng, bạn có thể dùng simpleperf report để kiểm tra dấu vết ngăn xếp đã thu thập. 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 lệnh gọi ở trên là một chuỗi lệnh gọi hạt nhân và chuỗi lệnh gọi không gian người dùng hợp nhất. Tính năng này cung cấp cho bạn chế độ xem luồng mã bằng cách bắt đầu dấu vết từ không gian người dùng cho đến nhân hệ điều hành mà việc từ chối xảy ra. Để 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

Đang chuyển sang quyền tự do

Bạn có thể tắt quá trình thực thi SELinux 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 thư mục gốc bằng cách chạy adb root. Sau đó, để vô hiệu hoá SELinux thực thi, chạy:

adb shell setenforce 0

Hoặc tại dòng lệnh kernel (trong thời gian thiết bị xuất hiện 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 nhận dmesg từ chối và chuyển đổi chúng thành các câu lệnh chính sách SELinux tương ứng. Như vậy, tính năng này có thể giúp tăng tốc độ phát triển SELinux.

Để sử dụng trình tạo này, hãy chạy:

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

Tuy nhiên, phải thận trọng để xem xét từng lần bổ sung tiềm năng cho quyền truy cập quá cao. Ví dụ: cấp dữ liệu cho audit2allow rmt_storage từ chối được hiển thị trước đó dẫn đến kết quả sau tuyên bố chính sách SELinux được đề xuất:

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

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