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 kernel đều phải được cho phép rõ ràng theo chính sách. Đ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 đủ về 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 ra các thiết bị Android mới. Đã có rất nhiều thông tin về SELinux. Hãy xem phần Tài liệu hỗ trợ để biết các tài nguyên được đề xuất.
Các tệp chính
Để bật SELinux, hãy tích hợp kernel 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 kernel SELinux và bao gồm hệ điều hành Android ngược dòng.
Nhìn 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 riêng bạn trong thư mục
/device/manufacturer/device-name/sepolicy. Trong Android 8.0 trở lên, các 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 của bạn. Để biết thêm thông tin chi tiết 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+. Bất kể phiên bản Android nào, bạn vẫn đang sửa đổi các tệp này:
Tệp chính sách
Các tệp kết thúc bằng *.te là các 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ể cần tạo các 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 ngữ cảnh là nơi bạn chỉ định nhãn cho các đối tượng của mình.
file_contextsgán 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 các chính sách mới, hãy tạo hoặc cập nhật tệp này để gán nhãn mới cho các tệp. Để áp dụngfile_contexts, hãy xây dựng lại hình ảnh hệ thống tệp hoặc chạyrestorecontrên tệp cần được gắn lại nhãn. Khi nâng cấp, các thay đổi đối vớifile_contextssẽ 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ể tự động được á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ọirestorecon_recursivevào tệp init.board.rc sau khi phân vùng được gắn ở chế độ đọc-ghi.genfs_contextsgán nhãn cho các hệ thống tệp, chẳng hạn nhưprochoặcvfatkhô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 kernel 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 và gắn lại hệ thống tệp để áp dụng đầy đủ thay đổi. Các nhãn cụ thể cũng có thể được gán cho các điểm gắn cụ thể, chẳng hạn nhưvfatbằng cách sử dụng tuỳ chọncontext=mount.property_contextsgán 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ìnhinitđọc trong quá trình khởi động.service_contextsgán nhãn cho các dịch vụ trình 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) tham chiếu trình liên kết cho dịch vụ. Cấu hình này được quy trìnhservicemanagerđọc trong quá trình khởi động.seapp_contextsgán nhãn cho các quy trình ứng dụng và/data/datathư mục. Cấu hình này được quy trìnhzygoteđọc trên mỗi lần khởi chạy ứng dụng và bởiinstalldtrong quá trình khởi động.mac_permissions.xmlgán thẻseinfocho các ứng dụng dựa trên chữ ký và tên gói (không bắt buộc). Sau đó, thẻseinfocó thể được dùng làm khoá trong tệpseapp_contextsđể gán nhãn cụ thể cho tất cả các ứng dụng có thẻseinfođó. Cấu hình này đượcsystem_serverđọc trong quá trình khởi động.keystore2_key_contextsgán nhãn cho các không gian tên Keystore 2. Các không gian tên này được trình nềnkeystore2thực thi. 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 theo 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 các tệp chính sách và ngữ cảnh, hãy cập nhật
/device/manufacturer/device-name/BoardConfig.mk
makefile để tham chiếu đến 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
system/sepolicy/README tệp.
BOARD_SEPOLICY_DIRS += \
<root>/device/manufacturer/device-name/sepolicy
BOARD_SEPOLICY_UNION += \
genfs_contexts \
file_contexts \
sepolicy.te
Sau khi xây dựng 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 các 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 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à bản 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 kernel cuối cùng. Để biết thêm thông tin về cách sepolicy được xây dựng trên thiết bị, hãy xem Xây dựng sepolicy.
Triển khai
Cách bắt đầu sử dụng SELinux:
- Bật SELinux trong kernel:
CONFIG_SECURITY_SELINUX=y - Thay đổi tham số kernel_cmdline hoặc bootconfig để:
hoặcBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Điều này chỉ dành cho quá trình 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.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Khởi động hệ thống ở chế độ cho phép và xem những trường hợp bị từ chối gặp phải khi khởi động:
Trên Ubuntu 14.04 trở lên: Trên Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Đánh giá kết quả đầu ra để tìm các cảnh báo tương tự như
init: Warning! Service name needs a SELinux domain defined; please fix!Xem Xác thực để biết hướng dẫn và công cụ. - Xác định các thiết bị và các tệp mới khác cần được gắn nhãn.
- Sử dụng nhãn hiện có hoặc nhãn mới cho các đối tượng của bạn. Hãy xem các tệp
*_contextsđể biết cách các mục được gắn nhãn trước đó và sử dụng kiến thức về ý nghĩa của nhãn để gán nhãn mới. Tốt nhất là, đây là nhãn hiện có phù hợp với chính sách, nhưng đôi khi cần có nhãn mới và các quy tắc để truy cập vào nhãn đó là cần thiết. Thêm nhãn vào các tệp ngữ cảnh thích hợp. - Xác định các miền/quy trình cần có miền bảo mật riêng.
Bạn có thể cần viết một chính sách hoàn toàn mới cho từng miền/quy trình. Ví dụ: tất cả các101 dịch vụ được tạo từ
init, đều phải có miền bảo mật riêng. Các lệnh sau đây giúp tiết lộ những dịch vụ 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: '
- Xem xét
init.device.rcđể xác định mọi miền không có loại miền. Hãy cung cấp cho chúng một miền sớm trong quá trình phát triển của bạn để tránh thêm các quy tắc vàoinithoặc gây nhầm lẫn cho các quyền truy cậpinitvới các quyền truy cập trong chính sách riêng của chúng. - Thiết lập
BOARD_CONFIG.mkđể sử dụng các biếnBOARD_SEPOLICY_*. Hãy xem README trongsystem/sepolicyđể biết thông tin chi tiết về cách thiết lập. - Kiểm tra tệp init.device.rc và fstab.device và đảm bảo rằng mọi lần sử dụng
mountđều tương ứng với hệ thống tệp được gắn nhãn đúng cách hoặc tuỳ chọncontext= mountđược chỉ định. - Xem xét từng trường hợp bị từ chối và tạo chính sách SELinux để xử lý đúng cách từng trường hợp. Hãy xem các ví dụ trong Tuỳ chỉnh.
Bạn nên bắt đầu với các chính sách trong AOSP rồi 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 bài viết Viết chính sách SELinux.
Trường hợp sử dụng
Dưới đây là các ví dụ cụ thể về các lỗ hổng cần xem xét khi tạo phần mềm của riêng bạn và các chính sách SELinux liên quan:
Symlink: Vì symlink 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 lỗ hổng. 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 symlink để mã hoá các tệp 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 rằng ứng dụng của bạn không bao giờ đi qua symlink, bạn có thể cấm ứng dụng đó làm như vậy bằng SELinux.
Tệp hệ thống: Hãy xem xét lớp tệp hệ thống chỉ nên được sửa đổi bởi máy chủ hệ thống. Tuy nhiên, vì netd, init và vold 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 phạm, thì nó có thể xâm phạm các tệp đó và có khả năng xâm phạm chính máy chủ hệ thống.
Với SELinux, bạn có thể xác định các 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 tệp đó là máy chủ hệ thống.
Ngay cả khi netd bị xâm phạm, 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ù nó 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 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 các khẳng định trên phạm vi rộng, 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ư chmod và chown, 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ứ bên ngoài tập hợp đó đều có thể bị cấm thực hiện các thay đổi này, ngay cả ở dạng gốc. Vì vậy, một ứng dụng có thể chạy chmod và chown đối với các tệp được gắn nhãn app_data_files nhưng không phải shell_data_files hoặc system_data_files.