Viết chính sách SELinux

Dự án nguồn mở Android (AOSP) cung cấp chính sách cơ sở vững chắc cho các ứng dụng và dịch vụ phổ biến trên tất cả các thiết bị Android. Những người đóng góp cho AOSP thường xuyên tinh chỉnh chính sách này. Chính sách cốt lõi dự kiến chiếm khoảng 90–95% chính sách cuối cùng trên thiết bị với tuỳ chỉnh chiếm 5-10% còn lại. Bài viết này tập trung vào các cách tuỳ chỉnh dành riêng cho thiết bị này, cách viết chính sách dành riêng cho thiết bị và một số sai lầm cần tránh trong quá trình thực hiện.

Hiển thị thiết bị

Trong khi viết chính sách dành riêng cho thiết bị, hãy làm theo các bước sau.

Chạy ở chế độ cho phép

Khi một thiết bị ở chế độ cho phép, các lượt từ chối được ghi lại nhưng không được thực thi. Chế độ cho phép có ý nghĩa quan trọng đối với hai lý do:

  • Chế độ thoải mái đảm bảo rằng việc thông báo chính sách không trì hoãn các thông tin khác sớm các tác vụ khởi động thiết bị.
  • Việc thực thi từ chối có thể che giấu các lần từ chối khác. Ví dụ: quyền truy cập vào tệp thường yêu cầu tìm kiếm thư mục, mở tệp rồi đọc tệp. Trong thực thi chế độ thực thi, sẽ chỉ xảy ra việc từ chối tìm kiếm thư mục. Cho phép đảm bảo tất cả các lần từ chối đều được nhìn thấy.

Cách đơn giản nhất để đưa một thiết bị vào chế độ cho phép là sử dụng lệnh hạt nhân . Bạn có thể thêm thành phần này vào tệp BoardConfig.mk của thiết bị: platform/device/<vendor>/<target>/BoardConfig.mk Sau khi sửa đổi dòng lệnh, hãy thực hiện make clean, sau đó make bootimage và cài đặt ROM hình ảnh khởi động mới.

Sau đó, xác nhận chế độ cho phép bằng:

adb shell getenforce

2 tuần là khoảng thời gian hợp lý để ở chế độ không bắt buộc trên toàn cầu. Sau khi giải quyết phần lớn ý kiến từ chối, hãy chuyển trở lại chế độ thực thi và xử lý lỗi khi chúng xuất hiện. Các miền vẫn tạo thông báo từ chối hoặc cung cấp dịch vụ giai đoạn phát triển nặng có thể tạm thời được đặt ở chế độ không bắt buộc, quay lại thực thi chế độ càng sớm càng tốt.

Thực thi sớm

Ở chế độ thực thi, việc từ chối được ghi lại và thực thi. Đó là điều tốt nhất để thiết bị của bạn thực thi chế độ càng sớm càng tốt. Đang chờ tạo và thực thi chính sách theo thiết bị cụ thể thường dẫn đến sản phẩm bị lỗi và trải nghiệm người dùng kém. Bắt đầu đủ sớm để tham gia thử nghiệm nội bộ và đảm bảo kiểm thử đầy đủ chức năng trong sử dụng thực tế. Đang khởi động đảm bảo sớm các vấn đề về bảo mật sẽ làm cơ sở cho các quyết định thiết kế. Ngược lại, cấp chỉ dựa trên lượt từ chối quan sát được là một phương pháp không an toàn. Sử dụng bản thảo này thời gian để thực hiện kiểm tra bảo mật của thiết bị và báo cáo lỗi dựa trên hành vi không được phép.

Loại bỏ hoặc xoá chính sách hiện tại

Có một số lý do hợp lý để tạo chính sách dành riêng cho thiết bị cào trên một thiết bị mới, bao gồm:

Giải quyết việc từ chối các dịch vụ chính

Các trường hợp từ chối do các dịch vụ chính tạo ra thường được giải quyết bằng cách gắn nhãn tệp. Ví dụ:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

được giải quyết hoàn toàn bằng cách gắn nhãn /dev/kgsl-3d0 đúng cách. Trong ví dụ này tcontextdevice. Điều này thể hiện ngữ cảnh mặc định, trong đó mọi nội dung trong /dev đều nhận được " thiết bị" trừ phi bạn chỉ định nhãn cụ thể hơn. Chỉ cần chấp nhận dữ liệu đầu ra từ check2allow ở đây sẽ dẫn đến quy tắc không chính xác và quá tuỳ ý.

Để giải quyết loại vấn đề này, hãy cung cấp cho tệp một nhãn cụ thể hơn trong trường hợp này là gpu_device. Không cần thêm quyền nào vì mediaserver đã có các quyền cần thiết trong chính sách chính để truy cập vào gpu_device.

Các tệp khác dành riêng cho thiết bị nên được gắn nhãn bằng các loại được xác định trước trong chính sách cốt lõi:

Nói chung, việc cấp quyền đối với nhãn mặc định là không chính xác. Nhiều phần trong số này không được phép bởi không cho phép quy tắc, nhưng ngay cả khi không được cho phép một cách rõ ràng, phương pháp hay nhất là cung cấp một .

Gắn nhãn địa chỉ và dịch vụ mới từ chối

Các dịch vụ đã khởi chạy phải chạy trong miền SELinux của riêng chúng. Chiến lược phát hành đĩa đơn ví dụ sau đặt dịch vụ “foo” vào miền SELinux riêng và cấp dịch vụ này quyền truy cập.

Dịch vụ này ra mắt trong Tệp init.device.rc dưới dạng:

service foo /system/bin/foo
    class core
  1. Tạo miền mới "foo"

    Tạo tệp device/manufacturer/device-name/sepolicy/foo.te có nội dung sau:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    Đây là mẫu ban đầu cho miền foo SELinux mà bạn có thể thêm quy tắc dựa trên thao tác cụ thể được thực hiện bởi tệp thực thi đó.

  2. Nhãn /system/bin/foo

    Thêm đoạn mã sau vào device/manufacturer/device-name/sepolicy/file_contexts:

    /system/bin/foo   u:object_r:foo_exec:s0
    

    Việc này đảm bảo tệp thực thi được gắn nhãn đúng cách để SELinux chạy trong miền phù hợp.

  3. Tạo và cài đặt ROM hình ảnh hệ thống và hình ảnh khởi động.
  4. Tinh chỉnh quy tắc SELinux cho miền.

    Sử dụng cơ chế từ chối để xác định các quyền cần thiết. Chiến lược phát hành đĩa đơn check2allow công cụ cung cấp các nguyên tắc hữu ích, nhưng chỉ nên dùng công cụ này để làm cơ sở xây dựng chính sách đang viết. Đừng chỉ sao chép kết quả đầu ra.

Chuyển về chế độ thực thi

Bạn có thể khắc phục sự cố ở chế độ không bắt buộc, nhưng chuyển về thực thi càng sớm càng tốt và cố gắng duy trì trạng thái đó.

Lỗi thường gặp

Sau đây là một số giải pháp cho những lỗi thường gặp khi viết lách các chính sách dành riêng cho từng thiết bị.

Lạm dụng câu phủ định

Quy tắc ví dụ sau đây giống như khoá cửa trước nhưng để cửa sổ đang mở:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

Mục đích rất rõ ràng: tất cả mọi người trừ các ứng dụng bên thứ ba có thể có quyền truy cập vào gỡ lỗi thiết bị.

Quy tắc này có một số sai sót. Loại trừ untrusted_app không dễ xử lý vì tất cả ứng dụng có thể tuỳ ý chạy các dịch vụ trong isolated_app. Tương tự, nếu miền mới cho các ứng dụng bên thứ ba được thêm vào AOSP, thì chúng cũng sẽ có quyền truy cập vào scary_debug_device. Quy tắc này quá thoải mái. Hầu hết các miền sẽ không được hưởng lợi khi có truy cập vào công cụ gỡ lỗi này. Bạn phải viết quy tắc để chỉ cho phép các miền yêu cầu quyền truy cập.

Các tính năng gỡ lỗi trong giai đoạn phát hành chính thức

Các tính năng gỡ lỗi không nên xuất hiện trên bản dựng chính thức cũng như .

Giải pháp thay thế đơn giản nhất là chỉ cho phép tính năng gỡ lỗi khi SELinux bị tắt trên bản dựng eng/userdebug, chẳng hạn như adb rootadb shell setenforce 0

Một cách thay thế an toàn khác là chứa quyền gỡ lỗi trong một userdebug_or_eng.

Sự bùng nổ về quy mô chính sách

Giới thiệu đặc điểm của chính sách SEAndroid mô tả một xu hướng đáng lo ngại về mức tăng số lượng tuỳ chỉnh chính sách thiết bị. Chính sách theo thiết bị cụ thể cần chiếm 5-10% tổng thể chính sách chạy trên một thiết bị. Các tuỳ chỉnh trong phạm vi 20%trở lên gần như chắc chắn chứa hơn miền đặc quyền và chính sách không còn được hỗ trợ.

Chính sách lớn không cần thiết:

  • Thực hiện một lần nhấn đúp vào bộ nhớ vì chính sách nằm trong ổ đĩa cứng và cũng được tải vào bộ nhớ nhân.
  • Lãnh phí dung lượng ổ đĩa do cần có hình ảnh khởi động lớn hơn.
  • Ảnh hưởng đến thời gian tra cứu chính sách trong thời gian chạy.

Ví dụ sau đây cho thấy hai thiết bị mà chính sách bao gồm 50% và 40% chính sách trên thiết bị. Bản viết lại chính sách mang lại những cải tiến đáng kể về khả năng bảo mật mà không làm giảm chức năng, vì như bên dưới. (Bao gồm các thiết bị AOSP (Dự án nguồn mở Android) Shamu và Flounder để so sánh.)

Hình 1: So sánh quy mô chính sách theo thiết bị cụ thể sau khi kiểm tra bảo mật.

Hình 1 So sánh các thiết bị cụ thể chính sách của bạn sau khi kiểm tra bảo mật.

Trong cả hai trường hợp, chính sách đã bị giảm đáng kể cả về quy mô và số lượng quyền. Việc giảm quy mô chính sách gần như hoàn toàn là do việc xóa những quyền không cần thiết, nhiều quyền trong số đó có thể là các quy tắc được tạo bởi audit2allow đã được thêm một cách bừa bãi vào chính sách. Ngừng cũng là một vấn đề đối với cả hai thiết bị.

Cấp chức năng dac_override

Từ chối dac_override có nghĩa là quá trình vi phạm đang cố truy cập vào một tệp có quyền không chính xác của người dùng/nhóm/thế giới trong hệ thống Unix. Giải pháp thích hợp hầu như không bao giờ là cấp quyền dac_override. Thay vào đó thay đổi quyền Unix trên tệp hoặc quy trình. Một số miền như init, voldinstalld thực sự cần khả năng ghi đè quyền đối với tệp Unix để truy cập vào tệp của các quy trình khác. Xem blog của DanWsh để được giải thích chi tiết hơn.