Xem lại trang này để làm quen với các khái niệm về SELinux.
Kiểm soát quyền truy cập bắt buộc
Security Enhanced Linux (SELinux) là một hệ thống kiểm soát quyền truy cập bắt buộc (MAC) cho hệ điều hành Linux. Là một hệ thống MAC, hệ thống này khác với hệ thống kiểm soát quyền truy cập tuỳ ý (DAC) quen thuộc của Linux. Trong hệ thống DAC, tồn tại khái niệm về quyền sở hữu, theo đó, chủ sở hữu của một tài nguyên cụ thể sẽ kiểm soát các quyền truy cập liên kết với tài nguyên đó. Quyền truy cập này thường là quyền truy cập thô và có thể bị leo thang quyền không mong muốn. Tuy nhiên, hệ thống MAC sẽ tham khảo ý kiến của một cơ quan trung ương để đưa ra quyết định về mọi nỗ lực truy cập.
SELinux đã được triển khai như một phần của khung Mô-đun bảo mật Linux (LSM), khung này nhận dạng nhiều đối tượng nhân và các hành động nhạy cảm được thực hiện trên các đối tượng đó. Tại thời điểm mỗi hành động này sẽ được thực hiện, một hàm móc LSM sẽ được gọi để xác định xem có nên cho phép hành động đó hay không dựa trên thông tin được lưu trữ trong một đối tượng bảo mật không rõ ràng. SELinux cung cấp một cách triển khai cho các móc này và quản lý các đối tượng bảo mật này, kết hợp với chính sách riêng của SELinux để xác định các quyết định truy cập.
Cùng với các biện pháp bảo mật khác của Android, chính sách kiểm soát quyền truy cập của Android giúp hạn chế đáng kể thiệt hại tiềm ẩn của các máy và tài khoản bị xâm phạm. Việc sử dụng các công cụ như quyền kiểm soát quyền truy cập tuỳ ý và bắt buộc của Android sẽ giúp bạn có một cấu trúc để đảm bảo phần mềm của bạn chỉ chạy ở cấp quyền tối thiểu. Điều này giúp giảm thiểu tác động của các cuộc tấn công và giảm khả năng các quy trình bị lỗi ghi đè hoặc thậm chí truyền dữ liệu.
Trên Android 4.3 trở lên, SELinux cung cấp một hệ thống kiểm soát quyền truy cập bắt buộc (MAC) bao trùm các môi trường kiểm soát quyền truy cập tuỳ ý (DAC) truyền thống. Ví dụ: phần mềm thường phải chạy dưới dạng tài khoản người dùng gốc để ghi vào các thiết bị khối thô. Trong môi trường Linux truyền thống dựa trên DAC, nếu người dùng gốc bị xâm phạm, thì người dùng đó có thể ghi vào mọi thiết bị khối thô. Tuy nhiên, bạn có thể sử dụng SELinux để gắn nhãn cho các thiết bị này, nhờ đó, quy trình được gán quyền gốc chỉ có thể ghi vào những thiết bị được chỉ định trong chính sách liên kết. Bằng cách này, quy trình không thể ghi đè dữ liệu và chế độ cài đặt hệ thống bên ngoài thiết bị khối thô cụ thể.
Hãy xem phần Trường hợp sử dụng để biết thêm ví dụ về các mối đe doạ và cách giải quyết các mối đe doạ đó bằng SELinux.
Các cấp thực thi
Bạn có thể triển khai SELinux ở nhiều chế độ:
- Cho phép – Chính sách bảo mật SELinux không được thực thi mà chỉ được ghi vào nhật ký.
- Thực thi – Chính sách bảo mật được thực thi và ghi vào nhật ký. Lỗi xuất hiện dưới dạng lỗi EPERM.
Lựa chọn này là lựa chọn nhị phân và xác định xem chính sách của bạn có thực hiện hành động hay chỉ cho phép bạn thu thập các lỗi tiềm ẩn. Chế độ cho phép đặc biệt hữu ích trong quá trình triển khai.
Các loại, thuộc tính và quy tắc
Android dựa vào thành phần Thực thi loại (TE) của SELinux cho chính sách của mình. Điều này có nghĩa là tất cả các đối tượng (chẳng hạn như tệp, quy trình hoặc ổ cắm) đều có một loại liên kết với chúng. Ví dụ: theo mặc định, một ứng dụng có loại untrusted_app. Đối với một quy trình, loại của quy trình đó còn được gọi là miền. Bạn có thể chú thích một loại bằng một hoặc nhiều thuộc tính. Thuộc tính hữu ích để tham chiếu đến nhiều loại cùng một lúc.
Các đối tượng được ánh xạ đến các lớp
(ví dụ: tệp, thư mục, liên kết tượng trưng, ổ cắm) và các loại quyền truy cập khác nhau
cho mỗi lớp được biểu thị bằng quyền.
Ví dụ: quyền open tồn tại cho lớp file. Mặc dù các loại và thuộc tính được cập nhật thường xuyên như một phần của chính sách SELinux trên Android, nhưng các quyền và lớp được xác định tĩnh và hiếm khi được cập nhật như một phần của bản phát hành Linux mới.
Một quy tắc chính sách có dạng:
allow source target:class permissions;
trong đó:
- Nguồn – Loại (hoặc thuộc tính) của đối tượng của quy tắc. Ai đang yêu cầu quyền truy cập?
- Mục tiêu – Loại (hoặc thuộc tính) của đối tượng. Quyền truy cập được yêu cầu đối với mục tiêu nào?
- Lớp – Loại đối tượng (ví dụ: tệp, ổ cắm) đang được truy cập.
- Quyền – Thao tác (hoặc tập hợp các thao tác) (ví dụ: đọc, ghi) đang được thực hiện.
Ví dụ về một quy tắc:
allow untrusted_app app_data_file:file { read write };
Quy tắc này cho biết rằng các ứng dụng được phép đọc và ghi các tệp được gắn nhãn app_data_file. Có các loại khác cho ứng dụng. Ví dụ: isolated_app được dùng cho các dịch vụ ứng dụng có isolatedProcess=true trong tệp kê khai. Thay vì lặp lại quy tắc cho cả hai loại, Android sử dụng một thuộc tính có tên là appdomain cho tất cả các loại bao gồm ứng dụng:
# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app appdomain;
# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app appdomain;
allow appdomain app_data_file:file { read write };
Khi một quy tắc được viết để chỉ định tên thuộc tính, tên đó sẽ tự động mở rộng thành danh sách các miền hoặc loại liên kết với thuộc tính. Một số thuộc tính đáng chú ý là:
domain– thuộc tính liên kết với tất cả các loại quy trình,file_type– thuộc tính liên kết với tất cả các loại tệp.
Macro
Đối với quyền truy cập tệp nói riêng, có nhiều loại quyền cần cân nhắc. Ví dụ: quyền read không đủ để mở tệp hoặc gọi stat trên tệp đó. Để đơn giản hoá định nghĩa quy tắc, Android cung cấp một tập hợp các macro để xử lý các trường hợp phổ biến nhất. Ví dụ: để đưa các quyền bị thiếu vào (chẳng hạn như open), bạn có thể viết lại quy tắc ở trên như sau:
allow appdomain app_data_file:file rw_file_perms;
Hãy xem các tệp global_macros
và te_macros
để biết thêm ví dụ về các macro hữu ích. Bạn nên sử dụng macro bất cứ khi nào có thể để giúp giảm khả năng xảy ra lỗi do bị từ chối quyền liên quan.
Sau khi xác định một loại, bạn cần liên kết loại đó với tệp hoặc quy trình mà loại đó đại diện. Hãy xem phần Triển khai SELinux để biết thêm thông tin chi tiết về cách thực hiện mối liên kết này. Để biết thêm thông tin về các quy tắc, hãy xem Sổ tay SELinux.
Bối cảnh bảo mật và danh mục
Khi gỡ lỗi chính sách SELinux hoặc gắn nhãn tệp (bằng file_contexts hoặc ls -Z), bạn có thể gặp phải bối cảnh bảo mật (còn gọi là nhãn). Ví dụ: u:r:untrusted_app:s0:c15,c256,c513,c768. Bối cảnh bảo mật có định dạng: user:role:type:sensitivity[:categories]. Bạn thường có thể bỏ qua các trường
user, role và sensitivity của một
bối cảnh (xem phần Mức độ cụ thể). Trường type được giải thích trong phần trước. categories là một phần của
tính năng hỗ trợ Bảo mật nhiều cấp (MLS)
trong SELinux. Trên Android 12 trở lên, danh mục được dùng để:
- Cách ly dữ liệu ứng dụng khỏi quyền truy cập của một ứng dụng khác,
- Cách ly dữ liệu ứng dụng từ người dùng vật lý này sang người dùng vật lý khác.
Mức độ cụ thể
Android không sử dụng tất cả các tính năng do SELinux cung cấp. Khi đọc tài liệu bên ngoài, hãy lưu ý những điểm sau:
- Phần lớn các chính sách trong AOSP được xác định bằng Ngôn ngữ chính sách nhân. Có một số trường hợp ngoại lệ khi sử dụng Ngôn ngữ trung gian chung (CIL).
- Không sử dụng người dùng SELinux. Người dùng duy nhất được xác định là
u. Khi cần, người dùng vật lý được biểu thị bằng trường danh mục của bối cảnh bảo mật. - Không sử dụng vai trò SELinux và Kiểm soát quyền truy cập dựa trên vai trò (RBAC). Hai vai trò mặc định được xác định và sử dụng:
rcho đối tượng vàobject_rcho đối tượng. - Không sử dụng độ nhạy SELinux. Độ nhạy
s0mặc định luôn được đặt. - Không sử dụng boolean SELinux. Khi chính sách được xây dựng cho một thiết bị, chính sách đó không phụ thuộc vào trạng thái của thiết bị. Điều này giúp đơn giản hoá việc kiểm tra và gỡ lỗi chính sách.