Android khuyến khích nhà sản xuất thiết bị gốc (OEM) kiểm thử kỹ lưỡng việc triển khai SELinux. Khi triển khai SELinux, nhà sản xuất nên áp dụng chính sách mới cho một nhóm thiết bị thử nghiệm trước tiên.
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
hãy xác định chế độ SELinux cho từng miền, bạn phải kiểm tra chế độ
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/
.
Đọc thông báo từ chối
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 dmesg
và logcat
và có thể xem được trên thiết bị. 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 chế độ 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 đ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ể ghi lại các nhật ký từ chối đang diễn ra bằng cách chạy cat /proc/kmsg
hoặc ghi lại các 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 hoặc thành phần hệ thống vi phạm chính sách SELinux. Sau đó, nhà sản xuất có thể khắc phục 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 điệp nhật ký này cho biết những quy trình sẽ không thành công ở 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ớitclass
ở cuối (unix_stream_socket
), hàm này cho bạn biết sơ lược về những gì đang được thực hiện với đối tượng nào. 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 ngữ cảnh nào đã khởi tạo hành động. Ngang bằng 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 ngữ cảnh của mục tiêu của hành động. Ngang bằng trong trường hợp này, đó là một unix_stream_socket thuộc sở hữu củanetd
. -
comm="ping"
ở trên cùng cung cấp cho bạn thêm gợi ý về nội dung đang chạy tại thời điểm tạo lệnh từ chối. Trong trường hợp này, đây là một gợi ý khá tốt.
Mộ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
Sau đây là những 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ặcsetenforce
. - 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ềnrmt_storage
. - Đối tượng – Mục
tcontext
(ngữ cảnh mục tiêu) đạ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
tclass
(lớp mục tiêu) 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à ngăn xếp 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 quyết định từ chối. Thông thường, bạn nên thu thập chuỗi lệnh gọi, bao gồm cả hạt nhân và không gian người dùng, để hiểu rõ hơn lý do xảy ra trường hợp 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
để 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 hệ điều hành Linux >= 5.10, đặc biệt là các nhánh Nhân hệ điều hành Android phổ biến mainline và android12-5.10 được hỗ trợ.
Nhánh android12-5.4 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 nhân khác, bạn có thể chọn các thay đổi dd81662 và 30969bc. - Bạn có thể tái tạo sự kiện mà bạn đang gỡ lỗi. Các 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.
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 gây ra trường hợp từ chối sẽ được kích hoạt. Sau đó, quá trình ghi sẽ dừng. Trong ví dụ này, bằng cách sử dụng Ctrl-c
, bạn đã thu thập được mẫu:
^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à 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
Chuyển sang chế độ cho phép
Bạn có thể tắt tính năng thực thi SELinux bằng 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
sẽ lấy các quyết định từ chối dmesg
và chuyển đổi các quyết định đó thành các câu lệnh chính sách SELinux tương ứng. Do đó, công cụ này có thể giúp đẩy nhanh đáng kể quá trình 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á mức. Ví dụ: việc cung cấp cho audit2allow
lệnh từ chối rmt_storage
đã hiển thị trước đó sẽ dẫn đến câu lệnh chính sách SELinux được đề xuất sau đây:
#============= 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ớ nhân, một lỗ hổng bảo mật rõ ràng. Thông thường, câu lệnh audit2allow
chỉ là một điểm xuất phát. Sau khi sử dụng các câu lệnh 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 thích hợp để có được một 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.