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 sẽ 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 mới nhất của sepolicy-analyze
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 đến dmesg
và logcat
và có thể xem cục bộ trên thiết bị. Các nhà sản xuất nên kiểm tra đầu ra SELinux thành 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 chuyển sang chế độ thực thi. Thông báo nhật ký SELinux chứa avc:
và vì vậy có thể dễ dàng tìm thấy với 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 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
.
Với kết quả đầu ra này, các 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
Diễn giải đầu ra này như sau:
-
{ connectto }
ở trên đại diện cho hành động đang được thực hiện. Cùng vớitclass
ở cuối (unix_stream_socket
), nó cho bạn biết đại khái những gì đang được thực hiện với những 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 ngữ cảnh nào đã khởi tạo hành động. Trong trường hợp này, đây là một cái gì đó đang 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 trường hợp này, đó là unix_stream_socket thuộc sở hữu củanetd
. - Dấu
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. 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à các yếu tố chính từ sự từ chối này:
- Hành động - hành động đã cố gắng được đánh dấu trong dấu ngoặc vuông,
read write
hoặcsetenforce
. - Actor - Mục
scontext
(ngữ cảnh nguồn) đại diện cho tác nhân, trong trường hợp này là daemonrmt_storage
. - Đối tượng - Mục
tcontext
(ngữ cảnh đích) đại diện cho đối tượng đang được tác động, trong trường hợp này là kmem. - Kết quả - Mục
tclass
(lớp đích) cho biết loại đối tượng đang được tác động, trong trường hợp này làchr_file
(thiết bị ký tự).
Bán phá giá Người dùng và Kernel Stacks
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 sự từ chối. Thường hữu ích khi thu thập chuỗi cuộc gọi, bao gồm hạt nhân và không gian người dùng, để hiểu rõ hơn lý do tại sao xảy ra từ chối.
Các hạt nhân gần đây xác định điểm theo dõi có tên là 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ợ
- Hạt nhân Linux> = 5.10, đặc biệt là các nhánh Hạt nhân chung Android cụ thể là mainline 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 điểm theo dõi có được xác định trên thiết bị của mình hay không:adb root && adb shell simpleperf list | grep avc:selinux_audited
. Đối với các phiên bản hạt nhân khác, bạn có thể chọn cam kết dd81662 và 30969bc . - Có thể tạo lại sự kiện mà bạn đang gỡ lỗi. Sự kiện thời gian khởi động không được hỗ trợ bằ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.
Nắm bắt chuỗi cuộc 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 gây ra từ chối sẽ được kích hoạt. Sau đó, quá trình ghi sẽ được dừng lại. Trong ví dụ này, bằng cách sử dụng Ctrl-c
, mẫu phải đượ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 stacktrace đã thu được. 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à một 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 một cái nhìn tốt hơn về dòng mã bằng cách bắt đầu theo dõi từ không gian người dùng cho đến tận hạt nhân nơi xảy ra từ chối. Để biết thêm thông tin về simpleperf
, hãy xem tham chiếu lệnh Simpleperf Executable
Chuyển sang dễ dãi
Việc thực thi SELinux có thể bị vô hiệu hóa thông qua ADB trên userdebug hoặc bản dựng 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 đó, để tắt thực thi SELinux, hãy chạy:
adb shell setenforce 0
Hoặc tại dòng lệnh hạt nhân (trong quá trình khởi động thiết bị ban đầu):
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 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.
Để 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 xem có vượt quá quyền hay không. Ví dụ: việc cấp dữ liệu audit2allow
cho phép từ chối rmt_storage
được hiển thị trước đó dẫn đến kết quả 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ớ hạt nhân, một lỗ hổng bảo mật rõ ràng. Thường thì các câu lệnh audit2allow
chỉ là một đ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 mục tiêu, cũng như kết hợp các macro thích hợp, để đưa ra một chính sách tốt. Đôi khi việc từ chối được kiểm tra sẽ không dẫn đến bất kỳ thay đổi chính sách nào; thay vào đó, ứng dụng vi phạm phải được thay đổi.