Android 10 bao gồm Android Live-LocK Daemon ( llkd
), được thiết kế để xử lý và giảm thiểu các bế tắc của hạt nhân. Thành phần llkd
cung cấp một triển khai độc lập mặc định, nhưng bạn có thể tích hợp mã llkd
vào một dịch vụ khác, như một phần của vòng lặp chính hoặc như một luồng riêng biệt.
Các tình huống phát hiện
llkd
có hai tình huống phát hiện: Trạng thái D hoặc Z liên tục và chữ ký ngăn xếp liên tục.
Trạng thái D hoặc Z liên tục
Nếu một chuỗi ở trạng thái D (ngủ liên tục) hoặc Z (zombie) không có tiến trình chuyển tiếp lâu hơn ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
, llkd
sẽ giết tiến trình (hoặc quy trình mẹ ). Nếu quá trình quét tiếp theo cho thấy quá trình tương tự vẫn tiếp tục tồn tại, llkd
xác nhận điều kiện khóa trực tiếp và điều khiển hạt nhân theo cách cung cấp báo cáo lỗi chi tiết nhất cho điều kiện đó.
llkd
bao gồm một cơ quan giám sát tự báo động nếu llkd
khóa; cơ quan giám sát tăng gấp đôi thời gian dự kiến để chạy qua mainloop và lấy mẫu là mỗi ro.llk_sample_ms
.
Chữ ký ngăn xếp liên tục
Đối với các bản phát hành userdebug, llkd
có thể phát hiện các khóa trực tiếp của hạt nhân bằng cách sử dụng kiểm tra chữ ký ngăn xếp liên tục. Nếu một luồng ở bất kỳ trạng thái nào ngoại trừ Z có biểu tượng hạt nhân ro.llk.stack
được liệt kê liên tục được báo cáo lâu hơn ro.llk.timeout_ms
hoặc ro.llk.stack.timeout_ms
, llkd
sẽ giết quá trình (ngay cả khi có chuyển tiếp lập kế hoạch tiến độ). Nếu quá trình quét tiếp theo cho thấy quá trình tương tự vẫn tiếp tục tồn tại, llkd
xác nhận điều kiện khóa trực tiếp và điều khiển hạt nhân theo cách cung cấp báo cáo lỗi chi tiết nhất cho điều kiện đó.
Kiểm tra lldk
vẫn tiếp diễn liên tục khi điều kiện khóa trực tiếp tồn tại và tìm kiếm các chuỗi đã soạn " symbol+0x"
hoặc " symbol.cfi+0x"
trong tệp /proc/pid/stack
trên Linux. Danh sách các ký hiệu nằm trong ro.llk.stack
và mặc định là danh sách được phân tách bằng dấu phẩy của " cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
".
Các ký hiệu phải đủ hiếm và tồn tại trong thời gian ngắn để trên một hệ thống điển hình, hàm chỉ được nhìn thấy một lần trong một mẫu trong khoảng thời gian chờ của ro.llk.stack.timeout_ms
(các mẫu xảy ra mỗi ro.llk.check_ms
). Do thiếu bảo vệ ABA, đây là cách duy nhất để ngăn chặn kích hoạt sai. Hàm biểu tượng phải xuất hiện bên dưới hàm gọi khóa có thể cạnh tranh. Nếu ổ khóa nằm bên dưới hoặc trong chức năng biểu tượng, biểu tượng sẽ xuất hiện trong tất cả các quá trình bị ảnh hưởng, không chỉ quá trình gây ra khóa.
Phủ sóng
Việc triển khai mặc định của llkd
không giám sát init
, [kthreadd]
hoặc [kthreadd]
sinh ra. Để llkd
bao gồm các chủ đề được tạo ra [kthreadd]
:
- Người lái xe không được ở trạng thái D liên tục,
HOẶC
- Trình điều khiển phải có cơ chế để khôi phục luồng nếu nó bị giết bên ngoài. Ví dụ: sử dụng
wait_event_interruptible()
thay vìwait_event()
.
Nếu một trong các điều kiện trên được đáp ứng, danh sách đen llkd
có thể được điều chỉnh để bao gồm các thành phần hạt nhân. Kiểm tra ký hiệu ngăn xếp bao gồm một danh sách đen quy trình bổ sung để ngăn chặn các vi phạm riêng lẻ trên các dịch vụ chặn hoạt động ptrace
.
Thuộc tính Android
llkd
phản hồi với một số thuộc tính Android (được liệt kê bên dưới).
- Thuộc tính có tên
prop_ms
tính bằng mili giây. - Các thuộc tính sử dụng dấu phân tách bằng dấu phẩy (,) cho danh sách sử dụng dấu phân tách hàng đầu để bảo toàn mục nhập mặc định, sau đó thêm hoặc trừ các mục nhập có tiền tố cộng (+) và dấu trừ (-) tùy chọn tương ứng. Đối với những danh sách này, chuỗi "false" đồng nghĩa với một danh sách trống và các mục nhập trống hoặc thiếu sử dụng giá trị mặc định được chỉ định.
ro.config.low_ram
Thiết bị được định cấu hình với bộ nhớ hạn chế.
ro.debuggable
Thiết bị được định cấu hình để gỡ lỗi người dùng hoặc bản dựng tương tác.
ro.llk.sysrq_t
Nếu thuộc tính là "eng", thì mặc định không phải là ro.config.low_ram
hoặc ro.debuggable
. Nếu đúng, hãy kết xuất tất cả các chủ đề ( sysrq t
).
ro.llk.enable
Cho phép bật trình nền khóa trực tiếp. Mặc định là sai.
llk.enable
Được đánh giá cho các bản dựng tương tác. Mặc định là ro.llk.enable
.
ro.khungtask.enable
Cho phép bật trình nền [khungtask]
. Mặc định là sai.
khungtask.enable
Được đánh giá cho các bản dựng tương tác. Mặc định là ro.khungtask.enable
.
ro.llk.mlockall
Bật cuộc gọi đến mlockall()
. Mặc định là sai.
ro.khungtask.timeout
[khungtask]
giới hạn thời gian tối đa. Mặc định là 12 phút.
ro.llk.timeout_ms
D hoặc Z giới hạn thời gian tối đa. Mặc định là 10 phút. Nhân đôi giá trị này để đặt cơ quan giám sát cảnh báo cho llkd
.
ro.llk.D.timeout_ms
D giới hạn thời gian tối đa. Mặc định là ro.llk.timeout_ms
.
ro.llk.Z.timeout_ms
Z giới hạn thời gian tối đa. Mặc định là ro.llk.timeout_ms
.
ro.llk.stack.timeout_ms
Kiểm tra giới hạn thời gian tối đa của các ký hiệu ngăn xếp liên tục. Mặc định là ro.llk.timeout_ms
. Chỉ hoạt động trên bản dựng userdebug hoặc eng .
ro.llk.check_ms
Các mẫu chủ đề cho D hoặc Z. Mặc định là hai phút.
ro.llk.stack
Kiểm tra các ký hiệu ngăn xếp hạt nhân mà nếu liên tục xuất hiện có thể chỉ ra một hệ thống con bị khóa. Mặc định là cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
danh sách các ký hiệu hạt nhân được phân tách bằng dấu phẩy. Kiểm tra không thực hiện việc lập lịch chuyển tiếp ABA ngoại trừ bằng cách thăm dò mọi ro.llk_check_ms
trong khoảng thời gian ro.llk.stack.timeout_ms
, do đó, các biểu tượng ngăn xếp phải đặc biệt hiếm và thoáng qua (rất khó có khả năng một biểu tượng hiển thị liên tục trong tất cả mẫu của ngăn xếp). Kiểm tra sự trùng khớp cho " symbol+0x"
hoặc " symbol.cfi+0x"
trong mở rộng ngăn xếp. Chỉ có sẵn trên userdebug hoặc bản dựng eng ; lo ngại về bảo mật trên các bản dựng của người dùng dẫn đến các đặc quyền hạn chế ngăn cản việc kiểm tra này.
ro.llk.blacklist.process
llkd
không xem các quá trình được chỉ định. Mặc định là 0,1,2
( kernel
, init
và [kthreadd]
) cộng với các tên tiến trình init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
. Một quy trình có thể là tham chiếu comm
, cmdline
hoặc pid
. Giá trị mặc định tự động có thể lớn hơn kích thước thuộc tính tối đa hiện tại là 92.
ro.llk.blacklist.parent
llkd
không theo dõi các tiến trình có (các) cha mẹ được chỉ định. Mặc định là 0,2,adbd&[setsid]
( kernel
, [kthreadd]
và adbd
chỉ dành cho setsid
zombie). Dấu phân tách và (&) chỉ định rằng phần tử gốc chỉ bị bỏ qua khi kết hợp với quy trình con đích. Ký hiệu và được chọn vì nó không bao giờ là một phần của tên quy trình; tuy nhiên, một setprop
trong shell yêu cầu ký hiệu và phải được thoát hoặc được trích dẫn, mặc dù tệp init rc
nơi thường được chỉ định không có vấn đề này. Quy trình gốc hoặc quy trình đích có thể là tham chiếu comm
, cmdline
hoặc pid
.
ro.llk.blacklist.uid
llkd
không xem các quá trình khớp với (các) uid được chỉ định. Danh sách số hoặc tên được phân tách bằng dấu phẩy. Mặc định là trống hoặc sai.
ro.llk.blacklist.process.stack
llkd
không giám sát tập hợp con quy trình được chỉ định cho chữ ký ngăn xếp khóa trực tiếp. Mặc định là các tên tiến trình init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. Ngăn chặn vi phạm riêng biệt liên quan đến các quy trình chặn ptrace
(vì không thể kiểm tra các quy trình này). Chỉ hoạt động trên bản dựng userdebug và eng . Để biết chi tiết về các loại bản dựng, hãy tham khảo Xây dựng Android .
Mối quan tâm về kiến trúc
- Thuộc tính được giới hạn trong 92 ký tự (tuy nhiên, điều này bị bỏ qua đối với các giá trị mặc định được xác định trong tệp
include/llkd.h
trong nguồn). - Daemon
[khungtask]
quá chung chung và chạy mã trình điều khiển ở trạng thái D. quá nhiều. Chuyển sang S sẽ làm cho (các) nhiệm vụ có thể giết được (và có thể phục hồi bởi trình điều khiển nếu cần).
Giao diện thư viện (tùy chọn)
Bạn có thể tùy chọn kết hợp llkd
vào một daemon đặc quyền khác bằng cách sử dụng giao diện C sau từ thành phần libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Nếu tên luồng được cung cấp, một luồng sẽ tự động sinh ra, nếu không người gọi phải gọi llkCheckMilliseconds
trong vòng lặp chính của nó. Hàm trả về khoảng thời gian trước cuộc gọi dự kiến tiếp theo tới trình xử lý này.