Triển khai SELinux

SELinux được thiết lập để từ chối theo mặc định, nghĩa là mọi quyền truy cập mà SELinux có một hook trong nhân đều phải được chính sách cho phép một cách rõ ràng. Điều này có nghĩa là tệp chính sách bao gồm một lượng lớn thông tin về các quy tắc, loại, lớp, quyền và nhiều thông tin khác. Việc xem xét đầy đủ SELinux nằm ngoài phạm vi của tài liệu này, nhưng việc hiểu cách viết các quy tắc chính sách hiện là điều cần thiết khi đưa các thiết bị Android mới vào hoạt động. Đã có rất nhiều thông tin về SELinux. Hãy xem Tài liệu hỗ trợ để biết các tài nguyên được đề xuất.

Tệp khoá

Để bật SELinux, hãy tích hợp nhân Android mới nhất rồi kết hợp các tệp có trong thư mục system/sepolicy. Khi được biên dịch, các tệp đó sẽ bao gồm chính sách bảo mật của kernel SELinux và bao gồm hệ điều hành Android nguồn mở.

Nói chung, bạn không nên sửa đổi trực tiếp các tệp system/sepolicy. Thay vào đó, hãy thêm hoặc chỉnh sửa các tệp chính sách dành riêng cho thiết bị của bạn trong thư mục /device/manufacturer/device-name/sepolicy. Trong Android 8.0 trở lên, những thay đổi mà bạn thực hiện đối với các tệp này chỉ ảnh hưởng đến chính sách trong thư mục nhà cung cấp. Để biết thêm thông tin về việc tách sepolicy công khai trong Android 8.0 trở lên, hãy xem bài viết Tuỳ chỉnh SEPolicy trong Android 8.0 trở lên. Bất kể phiên bản Android nào, bạn vẫn đang sửa đổi các tệp sau:

Tệp chính sách

Những tệp có đuôi *.te là tệp nguồn chính sách SELinux, xác định các miền và nhãn của chúng. Bạn có thể phải tạo tệp chính sách mới trong /device/manufacturer/device-name/sepolicy, nhưng bạn nên cố gắng cập nhật các tệp hiện có nếu có thể.

Tệp ngữ cảnh

Tệp bối cảnh là nơi bạn chỉ định nhãn cho các đối tượng.

  • file_contexts chỉ định nhãn cho các tệp và được nhiều thành phần không gian người dùng sử dụng. Khi bạn tạo chính sách mới, hãy tạo hoặc cập nhật tệp này để chỉ định nhãn mới cho các tệp. Để áp dụng file_contexts mới, hãy tạo lại hình ảnh hệ thống tệp hoặc chạy restorecon trên tệp cần được gắn nhãn lại. Khi nâng cấp, các thay đổi đối với file_contexts sẽ tự động được áp dụng cho các phân vùng hệ thống và dữ liệu người dùng trong quá trình nâng cấp. Các thay đổi cũng có thể được tự động áp dụng khi nâng cấp lên các phân vùng khác bằng cách thêm các lệnh gọi restorecon_recursive vào tệp init.board.rc sau khi phân vùng được gắn ở chế độ đọc-ghi.
  • genfs_contexts chỉ định nhãn cho các hệ thống tệp, chẳng hạn như proc hoặc vfat không hỗ trợ các thuộc tính mở rộng. Cấu hình này được tải như một phần của chính sách hạt nhân nhưng các thay đổi có thể không có hiệu lực đối với các inode trong lõi, yêu cầu khởi động lại hoặc huỷ gắn kết và gắn kết lại hệ thống tệp để áp dụng hoàn toàn thay đổi. Bạn cũng có thể chỉ định nhãn cụ thể cho các điểm gắn kết cụ thể, chẳng hạn như vfat bằng cách sử dụng tuỳ chọn context=mount.
  • property_contexts chỉ định nhãn cho các thuộc tính hệ thống Android để kiểm soát những quy trình có thể đặt các thuộc tính đó. Cấu hình này được quy trình init đọc trong quá trình khởi động.
  • service_contexts chỉ định nhãn cho các dịch vụ liên kết Android để kiểm soát những quy trình có thể thêm (đăng ký) và tìm (tra cứu) một tham chiếu liên kết cho dịch vụ. Cấu hình này được quy trình servicemanager đọc trong quá trình khởi động.
  • seapp_contexts chỉ định nhãn cho các quy trình ứng dụng và thư mục /data/data. Cấu hình này được quy trình zygote đọc mỗi khi ứng dụng khởi chạy và được installd đọc trong quá trình khởi động.
  • mac_permissions.xml chỉ định thẻ seinfo cho các ứng dụng dựa trên chữ ký và tên gói (không bắt buộc). Sau đó, bạn có thể dùng thẻ seinfo làm khoá trong tệp seapp_contexts để chỉ định một nhãn cụ thể cho tất cả các ứng dụng có thẻ seinfo đó. system_server sẽ đọc cấu hình này trong quá trình khởi động.
  • keystore2_key_contexts chỉ định nhãn cho các không gian tên Keystore 2. Các không gian tên này được thực thi bởi trình nền keystore2. Keystore luôn cung cấp các không gian tên dựa trên UID/AID. Keystore 2 cũng thực thi các không gian tên được xác định sepolicy. Bạn có thể xem nội dung mô tả chi tiết về định dạng và quy ước của tệp này tại đây.

Makefile BoardConfig.mk

Sau khi chỉnh sửa hoặc thêm tệp chính sách và tệp bối cảnh, hãy cập nhật tệp /device/manufacturer/device-name/BoardConfig.mk makefile để tham chiếu thư mục con sepolicy và từng tệp chính sách mới. Để biết thêm thông tin về các biến BOARD_SEPOLICY, hãy xem tệp system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Sau khi tạo lại, thiết bị của bạn sẽ được bật SELinux. Giờ đây, bạn có thể tuỳ chỉnh các chính sách SELinux để phù hợp với những nội dung bổ sung của riêng bạn cho hệ điều hành Android như mô tả trong phần Tuỳ chỉnh hoặc xác minh chế độ thiết lập hiện có như trình bày trong phần Xác thực.

Khi các tệp chính sách mới và nội dung cập nhật BoardConfig.mk được áp dụng, các chế độ cài đặt chính sách mới sẽ tự động được tích hợp vào tệp chính sách cuối cùng của nhân. Để biết thêm thông tin về cách sepolicy được tạo trên thiết bị, hãy xem phần Tạo sepolicy.

Triển khai

Cách bắt đầu sử dụng SELinux:

  1. Bật SELinux trong nhân: CONFIG_SECURITY_SELINUX=y
  2. Thay đổi tham số kernel_cmdline hoặc bootconfig để:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    hoặc
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Đây chỉ là bước phát triển ban đầu của chính sách cho thiết bị. Sau khi bạn có chính sách khởi động ban đầu, hãy xoá tham số này để thiết bị của bạn thực thi hoặc không vượt qua CTS.
  3. Khởi động hệ thống ở chế độ cho phép và xem những trường hợp từ chối gặp phải khi khởi động:
    Trên Ubuntu 14.04 trở lên:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    Trên Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Đánh giá đầu ra để tìm những cảnh báo tương tự như init: Warning! Service name needs a SELinux domain defined; please fix! Xem phần Xác thực để biết hướng dẫn và công cụ.
  5. Xác định các thiết bị và tệp mới khác cần được gắn nhãn.
  6. Sử dụng nhãn hiện có hoặc nhãn mới cho các đối tượng của bạn. Xem các tệp *_contexts để biết cách các đối tượng được gắn nhãn trước đây và sử dụng kiến thức về ý nghĩa của nhãn để chỉ định một nhãn mới. Lý tưởng nhất là đây là một nhãn hiện có phù hợp với chính sách, nhưng đôi khi cần có một nhãn mới và cần có các quy tắc để truy cập vào nhãn đó. Thêm nhãn vào các tệp ngữ cảnh thích hợp.
  7. Xác định những miền/quy trình cần có miền bảo mật riêng. Bạn có thể cần phải viết một chính sách hoàn toàn mới cho từng trường hợp. Tất cả các dịch vụ được tạo từ init, chẳng hạn như, phải có dịch vụ riêng. Các lệnh sau đây giúp hiển thị những lệnh vẫn đang chạy (nhưng TẤT CẢ các dịch vụ đều cần được xử lý như vậy):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Xem xét init.device.rc để xác định mọi miền không có loại miền. Cung cấp cho họ một miền sớm trong quá trình phát triển để tránh thêm các quy tắc vào init hoặc gây nhầm lẫn cho các quyền truy cập init với những quyền truy cập nằm trong chính sách của họ.
  9. Thiết lập BOARD_CONFIG.mk để sử dụng các biến BOARD_SEPOLICY_*. Hãy xem phần README trong system/sepolicy để biết thông tin chi tiết về cách thiết lập.
  10. Kiểm tra tệp init.device.rc và fstab.device, đồng thời đảm bảo rằng mọi lần sử dụng mount đều tương ứng với một hệ thống tệp được gắn nhãn đúng cách hoặc bạn đã chỉ định một lựa chọn context= mount.
  11. Xem xét từng trường hợp từ chối và tạo chính sách SELinux để xử lý từng trường hợp một cách thích hợp. Xem các ví dụ trong phần Tuỳ chỉnh.

Bạn nên bắt đầu với các chính sách trong AOSP, sau đó xây dựng dựa trên các chính sách đó để tuỳ chỉnh theo ý mình. Để biết thêm thông tin về chiến lược chính sách và xem xét kỹ hơn một số bước này, hãy xem phần Viết chính sách SELinux.

Trường hợp sử dụng

Sau đây là những ví dụ cụ thể về các lỗ hổng cần cân nhắc khi tạo phần mềm của riêng bạn và các chính sách SELinux liên quan:

Đường liên kết tượng trưng: Vì đường liên kết tượng trưng xuất hiện dưới dạng tệp, nên chúng thường được đọc dưới dạng tệp, điều này có thể dẫn đến các hành vi khai thác. Ví dụ: một số thành phần có đặc quyền, chẳng hạn như init, thay đổi quyền của một số tệp, đôi khi là quá mở.

Sau đó, kẻ tấn công có thể thay thế các tệp đó bằng các đường liên kết tượng trưng đến mã mà chúng kiểm soát, cho phép kẻ tấn công ghi đè các tệp tuỳ ý. Nhưng nếu biết ứng dụng của mình không bao giờ đi qua một đường liên kết tượng trưng, bạn có thể ngăn ứng dụng làm việc đó bằng SELinux.

Tệp hệ thống: Cân nhắc lớp tệp hệ thống mà chỉ máy chủ hệ thống mới được phép sửa đổi. Tuy nhiên, vì netd, initvold chạy dưới dạng gốc, nên chúng có thể truy cập vào các tệp hệ thống đó. Vì vậy, nếu netd bị xâm nhập, thì các tệp đó có thể bị xâm nhập và có khả năng là chính máy chủ hệ thống cũng bị xâm nhập.

Với SELinux, bạn có thể xác định những tệp đó là tệp dữ liệu máy chủ hệ thống. Do đó, miền duy nhất có quyền đọc/ghi đối với các miền này là máy chủ hệ thống. Ngay cả khi netd bị xâm nhập, nó cũng không thể chuyển đổi miền sang miền máy chủ hệ thống và truy cập vào các tệp hệ thống đó mặc dù chạy dưới dạng gốc.

Dữ liệu ứng dụng: Một ví dụ khác là lớp các hàm phải chạy dưới dạng gốc nhưng không được phép truy cập vào dữ liệu ứng dụng. Điều này cực kỳ hữu ích vì bạn có thể đưa ra nhiều khẳng định, chẳng hạn như một số miền không liên quan đến dữ liệu ứng dụng bị cấm truy cập vào Internet.

setattr: Đối với các lệnh như chmodchown, bạn có thể xác định tập hợp các tệp mà miền được liên kết có thể thực hiện setattr. Mọi thứ nằm ngoài phạm vi đó đều có thể bị cấm thực hiện những thay đổi này, ngay cả khi có quyền truy cập vào gốc. Vì vậy, một ứng dụng có thể chạy chmodchown đối với những ứng dụng được gắn nhãn app_data_files nhưng không phải shell_data_files hoặc system_data_files.