Init nhà cung cấp

Quy trình khởi tạo có các quyền gần như không bị hạn chế và sử dụng các tập lệnh đầu vào từ cả phân vùng hệ thống và phân vùng nhà cung cấp để khởi động hệ thống trong quá trình khởi động của chúng tôi. Quyền truy cập này gây ra một lỗ hổng lớn trong việc phân chia hệ thống/nhà cung cấp Treble, vì tập lệnh của nhà cung cấp có thể hướng dẫn Init truy cập vào các tệp, thuộc tính, v.v. không được tạo thành một phần của giao diện nhị phân của ứng dụng nhà cung cấp hệ thống (ABI) ổn định.

Cung cấp init được thiết kế để đóng lỗ này bằng cách sử dụng một miền Linux (SELinux) tăng cường bảo mật vendor_init để chạy có các lệnh được tìm thấy trong /vendor kèm theo quyền truy cập dành riêng cho nhà cung cấp.

Cơ chế

Nhà cung cấp khởi tạo phát triển nhánh một quy trình phụ của khởi tạo trong quá trình khởi động bằng Ngữ cảnh SELinux u:r:vendor_init:s0. Ngữ cảnh SELinux này có có ít quyền hơn đáng kể so với ngữ cảnh khởi tạo mặc định và quyền truy cập của ngữ cảnh chỉ dành cho các tệp, thuộc tính, v.v. dành riêng cho nhà cung cấp hoặc một phần của ABI của nhà cung cấp hệ thống ổn định.

Init kiểm tra từng tập lệnh được tải để xem đường dẫn của tập lệnh đó có bắt đầu bằng hay không /vendor và nếu có, hãy gắn thẻ cho tài sản đó với chỉ báo rằng các lệnh của thiết bị phải được chạy trong ngữ cảnh khởi tạo nhà cung cấp. Mỗi tích hợp khởi tạo được chú thích bằng giá trị boolean chỉ định liệu lệnh có phải được chạy trong init nhà cung cấp hay không quy trình phụ:

  • Hầu hết các lệnh truy cập vào hệ thống tệp đều được chú thích để chạy trong nhà cung cấp quy trình phụ init và do đó phải tuân theo init SEPolicy của nhà cung cấp.
  • Hầu hết các lệnh ảnh hưởng đến trạng thái khởi tạo nội bộ (ví dụ: bắt đầu và dừng) mới) được chạy trong quy trình khởi tạo thông thường. Các lệnh này được tạo biết rằng tập lệnh của nhà cung cấp đang yêu cầu họ thực hiện mã không phải SELinux của riêng họ quản lý quyền.

Vòng lặp xử lý chính của init chứa bước kiểm tra để đảm bảo rằng liệu một lệnh có được chú giải hay không để chạy trong quy trình phụ của nhà cung cấp và bắt nguồn từ tập lệnh của nhà cung cấp, được gửi qua giao tiếp liên quy trình (IPC) đến khởi tạo của nhà cung cấp quy trình phụ, chạy lệnh và gửi lại kết quả cho init.

Sử dụng Init nhà cung cấp

Nhà cung cấp init được bật theo mặc định và các hạn chế của nhà cung cấp này áp dụng cho tất cả tập lệnh init có trong phân vùng /vendor. Thông tin của nhà cung cấp phải minh bạch cho các nhà cung cấp có tập lệnh chưa truy cập vào các tệp chỉ dành cho hệ thống, thuộc tính, v.v.

Tuy nhiên, nếu các lệnh trong một tập lệnh của nhà cung cấp nhất định vi phạm thông tin khởi tạo của nhà cung cấp thì các lệnh đó sẽ không thực hiện được. Các lệnh không đạt sẽ có một dòng trong nhân log (hiển thị với dmesg) từ init cho biết không thành công. Kiểm tra SELinux đi kèm với mọi lệnh không thực hiện được do chính sách SELinux. Ví dụ: lỗi bao gồm kiểm tra SELinux:

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

Nếu một lệnh không thành công, có hai tuỳ chọn:

  • Nếu lệnh không thành công do hạn chế dự kiến (chẳng hạn như là truy cập vào tệp hoặc thuộc tính hệ thống), thì lệnh phải được triển khai lại theo cách thân thiện với Treble, chỉ chuyển qua các giao diện ổn định. Quy tắc không bao giờ cho phép ngăn việc thêm quyền truy cập vào các tệp hệ thống không được một phần của ABI nhà cung cấp hệ thống ổn định.
  • Nếu nhãn SELinux là nhãn mới và chưa được cấp quyền trong hệ thống vendor_init.te cũng như các quyền bị loại trừ thông qua luồng không bao giờ cho phép quy tắc này, nhãn mới có thể được cấp quyền trong vendor_init.te.

Đối với các thiết bị chạy trước Android 9, quy tắc không bao giờ có thể được bỏ qua bằng cách thêm thuộc tính loại data_between_core_and_vendor_violators vào tệp vendor_init.te dành riêng cho thiết bị.

Vị trí mã

Phần lớn logic cho IPC khởi tạo của nhà cung cấp nằm trong system/core/init/subcontext.cpp.

Bảng lệnh nằm trong lớp BuiltinFunctionMap trong system/core/init/vòng lặp.cpp và bao gồm các chú giải cho biết liệu lệnh có phải chạy trong nhà cung cấp hay không quy trình phụ init.

SEPolicy cho init nhà cung cấp được chia thành riêng tư (system/sepolicy/private/vendor_init.te) và công khai (system/sepolicy/public/vendor_init.te) các thư mục trong system/sepolicy.