Trình nền khoá trực tiếp của Android (llkd)

Android 10 có trình nền Android-lock (llkd), được thiết kế để phát hiện và giảm thiểu tình trạng tắc nghẽn hạt nhân. llkd thành phần này sẽ cung cấp cách triển khai độc lập mặc định, nhưng bạn có thể ngoài ra, tích hợp mã llkd vào một dịch vụ khác, dưới dạng một phần của vòng lặp chính hoặc dưới dạng một luồng riêng biệt.

Các trường hợp phát hiện

llkd có 2 tình huống phát hiện: Trạng thái D hoặc Z liên tục và liên tục chữ ký của ngăn xếp.

Trạng thái D hoặc Z ổn định

Nếu một luồng ở trạng thái D (ngủ không gián đoạn) hoặc Z (thây ma) không chuyển tiếp tiến trình dài hơn ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms, thì llkd tắt quy trình (hoặc tiến trình mẹ). Nếu lần quét tiếp theo hiển thị quy trình tương tự vẫn tiếp tục, llkd sẽ xác nhận điều kiện khoá trực tiếp và làm hoảng loạn nhân hệ điều hành theo cách cung cấp báo cáo lỗi chi tiết nhất cho .

llkd có một bộ đếm giờ tự giám sát sẽ báo động nếu llkd khoá; bộ đếm giờ phòng vệ là gấp đôi thời gian dự kiến để luồng chính qua vòng lặp chính và việc lấy mẫu là mỗi ro.llk_sample_ms.

Chữ ký ngăn xếp cố định

Đối với bản phát hành userdebug, llkd có thể phát hiện khoá trực tiếp của hạt nhân bằng cách sử dụng liên tục kiểm tra chữ ký ngăn xếp. Nếu một luồng ở bất kỳ trạng thái nào ngoại trừ Z có được liệt kê biểu tượng hạt nhân ro.llk.stack được báo cáo dài hơn ro.llk.timeout_ms hoặc ro.llk.stack.timeout_ms, llkd sẽ tắt quy trình (ngay cả khi có tiến trình lên lịch chuyển tiếp). Nếu lần quét tiếp theo hiển thị quy trình tương tự vẫn tiếp tục, llkd sẽ xác nhận điều kiện khoá trực tiếp và làm hoảng loạn nhân hệ điều hành theo cách cung cấp báo cáo lỗi chi tiết nhất cho .

Quá trình kiểm tra lldk sẽ liên tục khi có điều kiện khoá trực tiếp và hãy tìm các chuỗi đã soạn symbol+0x hoặc symbol.cfi+0x trong /proc/pid/stack trên Linux. Danh sách các biểu tượng có trong ro.llk.stack và mặc định thành danh sách được phân tách bằng dấu phẩy cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable.

Các biểu tượng phải hiếm và tồn tại trong thời gian ngắn để trên một hệ thống thông thường, chỉ được nhìn thấy một lần trong mẫu trong khoảng thời gian chờ ro.llk.stack.timeout_ms (lấy mẫu xảy ra mỗi ro.llk.check_ms). Do thiếu của tính năng bảo vệ ABA, đây là cách duy nhất để ngăn chặn trình kích hoạt giả mạo. Biểu tượng phải xuất hiện bên dưới hàm gọi khoá có thể cạnh tranh. Nếu khoá ở bên dưới hoặc trong hàm biểu tượng, biểu tượng sẽ xuất hiện trong tất cả các chứ không chỉ là quá trình gây ra khoá.

Độ bao phủ

Phương thức triển khai mặc định của llkd không giám sát init, [kthreadd] hoặc [kthreadd] sẽ xuất hiện. Để llkd bao gồm các luồng đã được [kthreadd] tạo:

  • Trình điều khiển không được duy trì 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 luồng đó bị vô hiệu hoá bên ngoài. Ví dụ: sử dụng wait_event_interruptible() thay vì wait_event().

Nếu đáp ứng một trong các điều kiện trên, bạn có thể điều chỉnh danh sách từ chối llkd thành bao gồm các thành phần nhân hệ điều hành. Kiểm tra biểu tượng ngăn xếp bao gồm một quy trình bổ sung danh sách từ chối để ngăn chặn các lỗi vi phạm sepolicy trên các dịch vụ chặn ptrace các toán tử.

Thuộc tính Android

llkd phản hồi một số thuộc tính Android (liệt kê dưới đây).

  • Các thuộc tính có tên prop_ms có kích thước tính bằng mili giây.
  • Những tài sản sử dụng dấu phân cách (,) cho danh sách sử dụng dấu phân cách phía trước để giữ nguyên mục nhập mặc định, sau đó cộng hoặc trừ các mục nhập bằng dấu cộng tuỳ ý Các tiền tố (+) và trừ (-) tương ứng. Đối với các danh sách này, chuỗi false đồng nghĩa với danh sách trống và mục nhập trống hoặc bị thiếu cần phải giá trị mặc định được chỉ định.

ro.config.low_ram

Thiết bị được định cấu hình có bộ nhớ giới hạn.

ro.có thể gỡ lỗi

Thiết bị được định cấu hình cho bản dựng userdebug hoặc eng.

ro.llk.sysrq_t

Nếu thuộc tính là eng, giá trị mặc định không phải là ro.config.low_ram hoặc ro.debuggable. Nếu là true, hãy kết xuất tất cả các luồng (sysrq t).

ro.llk.enable

Cho phép bật trình nền khoá trực tiếp. Mặc định là false.

llk.enable

Được đánh giá theo bản dựng eng. Mặc định là ro.llk.enable.

ro.khungtask.enable

Cho phép bật trình nền [khungtask]. Mặc định là false.

khungtask.enable

Được đánh giá theo bản dựng eng. Mặc định là ro.khungtask.enable.

ro.llk.mlockall

Bật lệnh gọi đến mlockall(). Mặc định là false.

ro.khungtask.timeout

Giới hạn thời gian tối đa là [khungtask]. Mặc định là 12 phút.

ro.llk.timeout_ms

Giới hạn thời gian tối đa D hoặc Z. Mặc định là 10 phút. Nhân đôi giá trị này để đặt bộ đếm giờ phòng vệ của chuông báo cho llkd.

ro.llk.D.timeout_ms

Giới hạn thời gian tối đa của D. Mặc định là ro.llk.timeout_ms.

ro.llk.Z.timeout_ms

Giới hạn thời gian tối đa Z. 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 biểu tượng ngăn xếp cố định. 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

Mẫu luồng cho D hoặc Z. Mặc định là 2 phút.

ro.llk.stack

Kiểm tra các biểu tượng ngăn xếp hạt nhân mà nếu sự tồn tại liên tục có thể cho biết hệ thống con đã bị khoá. Mặc định là cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable danh sách ký hiệu hạt nhân được phân tách bằng dấu phẩy. Bước kiểm tra này không thực hiện việc lên lịch chuyển tiếp ABA, ngoại trừ bằng cách thăm dò ý kiến ro.llk_check_ms một lần trong khoảng thời gian ro.llk.stack.timeout_ms nên biểu tượng ngăn xếp phải cực kỳ hiếm và thoáng qua (rất khó có khả năng một biểu tượng xuất hiện liên tục trong tất cả mẫu của ngăn xếp). Kiểm tra kết quả trùng khớp cho symbol+0x hoặc symbol.cfi+0x trong ngăn xếp mở rộng. Chỉ có khi dùng userdebug hoặc eng bản dựng; các vấn đề về bảo mật trên bản dựng của người dùng sẽ khiến đặc quyền bị hạn chế ngăn chặn việc kiểm tra này.

ro.llk.black.process

llkd không theo dõi các quy trình được chỉ định. Mặc định là 0,1,2 (kernel, init[kthreadd]) cùng với tên quy trình init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]. Quy trình có thể là tham chiếu comm, cmdline hoặc pid. Chế độ mặc định tự động có thể lớn hơn kích thước tài sản tối đa hiện tại là 92.

ro.llk.black.parent

llkd không theo dõi các quy trình có phần tử mẹ được chỉ định. Mặc định là 0,2,adbd&[setsid] (kernel, [kthreadd]adbd chỉ đối với thây ma setsid). Dấu phân cách (&) chỉ định rằng thành phần mẹ chỉ bị bỏ qua kết hợp với quy trình con mục tiêu. Dấ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, setprop trong shell yêu cầu ký hiệu "&" để thoát hoặc được đóng dấu ngoặc kép, mặc dù tệp init rc có chứa ký tự này thường được chỉ định không có vấn đề này. Quá trình mẹ hoặc quá trình nhắm mục tiêu có thể là một Tham chiếu comm, cmdline hoặc pid.

ro.llk.black.uid

llkd không theo dõi các quy trình khớp với UID được chỉ định. Danh sách được phân tách bằng dấu phẩy gồm số hoặc tên UIS. Mặc định là trống hoặc false.

ro.llk.black.process.stack

llkd không giám sát tập hợp con quy trình được chỉ định đối với ngăn xếp khoá trực tiếp chữ ký. Mặc định là tên quy trình init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd. Ngăn chặn sepolicy lỗi vi phạm liên quan đến các quy trình chặn ptrace (vì những quy trình này không được đã chọn). Chỉ hoạt động trên các bản dựng userdebug và eng. Thông tin chi tiết về bản dựng hãy tham khảo nội dung Xây dựng Android.

Vấn đề về kiến trúc

  • Thuộc tính được giới hạn trong 92 ký tự (tuy nhiên, thuộc tính này sẽ bị bỏ qua đối với giá trị mặc định đã xác định trong tệp include/llkd.h trong các nguồn).
  • Daemon [khungtask] tích hợp sẵn quá chung chung và các chuyến đi trên mã trình điều khiển ngồi quá nhiều ở trạng thái D. Nếu bạn chuyển sang S sẽ khiến các nhiệm vụ có thể tắt (và tài xế có thể gọi lại nếu cần).

Giao diện thư viện (không bắt buộc)

Bạn có thể tuỳ ý kết hợp llkd vào một trình nền đặc quyền khác bằng cách sử dụng giao diện C sau đây 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, thì một luồng sẽ tự động tạo, nếu không thì phương thức gọi phải gọi llkCheckMilliseconds trong vòng lặp chính. Hàm trả về giá trị khoảng thời gian trước khi thực hiện lệnh gọi dự kiến tiếp theo đến trình xử lý này.