Để cải thiện tính bảo mật của thiết bị, Android 7.0 chia quy trình mediaserver
nguyên khối thành nhiều quy trình với các quyền và chức năng chỉ bị hạn chế ở những quyền và chức năng mà mỗi quy trình yêu cầu. Những thay đổi này giảm thiểu các lỗ hổng bảo mật của khung nội dung nghe nhìn bằng cách:
- Phân tách các thành phần của quy trình AV thành các quy trình hộp cát dành riêng cho ứng dụng.
- Bật các thành phần nội dung nghe nhìn có thể cập nhật (trình trích xuất, bộ mã hoá và giải mã, v.v.).
Những thay đổi này cũng cải thiện tính bảo mật cho người dùng cuối bằng cách giảm đáng kể mức độ nghiêm trọng của hầu hết các lỗ hổng bảo mật liên quan đến nội dung nghe nhìn, giúp bảo vệ an toàn cho thiết bị và dữ liệu của người dùng cuối.
Nhà sản xuất thiết bị gốc (OEM) và nhà cung cấp SoC cần cập nhật các thay đổi về HAL và khung để tương thích với cấu trúc mới. Cụ thể, vì mã Android do nhà cung cấp cung cấp thường giả định mọi thứ chạy trong cùng một quy trình, nên nhà cung cấp phải cập nhật mã của họ để truyền các tay điều khiển gốc (native_handle
) có ý nghĩa trên các quy trình. Để tham khảo cách triển khai các thay đổi liên quan đến việc tăng cường bảo mật nội dung đa phương tiện, hãy tham khảo frameworks/av
và frameworks/native
.
Thay đổi về cấu trúc
Các phiên bản Android trước đây sử dụng một quy trình mediaserver
đơn lẻ, nguyên khối với nhiều quyền (quyền truy cập vào máy ảnh, quyền truy cập vào âm thanh, quyền truy cập vào trình điều khiển video, quyền truy cập vào tệp, quyền truy cập vào mạng, v.v.). Android 7.0 chia quy trình mediaserver
thành một số quy trình mới, mỗi quy trình yêu cầu một nhóm quyền nhỏ hơn nhiều:
Hình 1. Thay đổi về cấu trúc để tăng cường bảo mật mediaserver
Cấu trúc mới này đảm bảo rằng ngay cả khi một quy trình bị xâm phạm, mã độc cũng không có quyền truy cập vào toàn bộ các quyền mà mediaserver
từng nắm giữ. Các quy trình bị hạn chế theo chính sách SElinux và seccomp.
Lưu ý: Do các phần phụ thuộc của nhà cung cấp, một số bộ mã hoá và giải mã vẫn chạy trong mediaserver
và do đó cấp cho mediaserver
nhiều quyền hơn mức cần thiết. Cụ thể, Widevine Classic tiếp tục chạy trong mediaserver
cho Android 7.0.
Thay đổi về MediaServer
Trong Android 7.0, quy trình mediaserver
tồn tại để điều khiển quá trình phát và ghi, ví dụ: truyền và đồng bộ hoá vùng đệm giữa các thành phần và quy trình. Các quy trình giao tiếp thông qua cơ chế Binder tiêu chuẩn.
Trong một phiên phát tệp cục bộ tiêu chuẩn, ứng dụng sẽ truyền một chỉ số mô tả tệp (FD) đến mediaserver
(thường là thông qua API MediaPlayer Java) và mediaserver
:
- Gói FD vào đối tượng Binder DataSource được truyền đến quy trình trích xuất. Quy trình này sử dụng đối tượng đó để đọc từ tệp bằng Binder IPC. (Trình trích xuất nội dung đa phương tiện không nhận được FD mà thay vào đó, trình này sẽ gọi lại Binder đến
mediaserver
để lấy dữ liệu.) - Kiểm tra tệp, tạo trình trích xuất thích hợp cho loại tệp (ví dụ: MP3Extractor hoặc MPEG4Extractor) và trả về giao diện Binder cho trình trích xuất vào quy trình
mediaserver
. - Thực hiện lệnh gọi Binder IPC đến trình trích xuất để xác định loại dữ liệu trong tệp (ví dụ: dữ liệu MP3 hoặc H.264).
- Gọi vào quy trình
mediacodec
để tạo bộ mã hoá và giải mã thuộc loại bắt buộc; nhận giao diện Binder cho các bộ mã hoá và giải mã này. - Thực hiện các lệnh gọi Binder IPC lặp lại cho trình trích xuất để đọc các mẫu đã mã hoá, sử dụng Binder IPC để gửi dữ liệu đã mã hoá đến quy trình
mediacodec
để giải mã và nhận dữ liệu đã giải mã.
Trong một số trường hợp sử dụng, không có bộ mã hoá và giải mã nào tham gia (chẳng hạn như phát tải xuống, trong đó dữ liệu đã mã hoá được gửi trực tiếp đến thiết bị đầu ra) hoặc bộ mã hoá và giải mã có thể hiển thị trực tiếp dữ liệu đã giải mã thay vì trả về vùng đệm của dữ liệu đã giải mã (phát video).
Thay đổi đối với MediaCodecService
Dịch vụ bộ mã hoá và giải mã là nơi lưu trữ bộ mã hoá và bộ giải mã. Do các phần phụ thuộc của nhà cung cấp, chưa phải tất cả bộ mã hoá và giải mã đều có trong quy trình bộ mã hoá và giải mã. Trong Android 7.0:
- Bộ giải mã không an toàn và bộ mã hoá phần mềm nằm trong quy trình bộ mã hoá và giải mã.
- Bộ giải mã bảo mật và bộ mã hoá phần cứng nằm trong
mediaserver
(không thay đổi).
Một ứng dụng (hoặc mediaserver
) gọi quy trình bộ mã hoá và giải mã để tạo bộ mã hoá và giải mã thuộc loại bắt buộc, sau đó gọi bộ mã hoá và giải mã đó để truyền dữ liệu đã mã hoá và truy xuất dữ liệu đã giải mã (để giải mã) hoặc để truyền dữ liệu đã giải mã và truy xuất dữ liệu đã mã hoá (để mã hoá). Quá trình chuyển dữ liệu đến và đi từ bộ mã hoá và giải mã đã sử dụng bộ nhớ dùng chung, vì vậy, quá trình đó không thay đổi.
Thay đổi về MediaDrmServer
Máy chủ DRM được dùng khi phát nội dung được bảo vệ bằng DRM, chẳng hạn như phim trong Google Play Phim. Lớp này xử lý việc giải mã dữ liệu đã mã hoá một cách an toàn, đồng thời có quyền truy cập vào chứng chỉ và bộ nhớ khoá cũng như các thành phần nhạy cảm khác. Do các phần phụ thuộc của nhà cung cấp, quy trình DRM chưa được sử dụng trong mọi trường hợp.
Các thay đổi đối với AudioServer
Quy trình AudioServer lưu trữ các thành phần liên quan đến âm thanh, chẳng hạn như đầu vào và đầu ra âm thanh, dịch vụ policymanager xác định định tuyến âm thanh và dịch vụ đài FM. Để biết thông tin chi tiết về các thay đổi đối với tính năng Âm thanh và hướng dẫn triển khai, hãy xem phần Triển khai âm thanh.
Thay đổi đối với CameraServer
CameraServer điều khiển máy ảnh và được dùng khi quay video để lấy khung hình video từ máy ảnh, sau đó chuyển các khung hình đó đến mediaserver
để xử lý thêm. Để biết thông tin chi tiết về các thay đổi và hướng dẫn triển khai cho các thay đổi đối với CameraServer, hãy tham khảo phần Cải thiện độ bảo mật của Khung máy ảnh.
Thay đổi đối với ExtractorService
Dịch vụ trình trích xuất lưu trữ trình trích xuất, các thành phần phân tích cú pháp nhiều định dạng tệp mà khung nội dung nghe nhìn hỗ trợ. Dịch vụ trình trích xuất có ít đặc quyền nhất trong tất cả các dịch vụ – dịch vụ này không thể đọc FD, do đó, dịch vụ này thực hiện các lệnh gọi đến giao diện Binder (do mediaserver for
cung cấp cho mỗi phiên phát) để truy cập vào các tệp.
Một ứng dụng (hoặc mediaserver
) thực hiện lệnh gọi đến quy trình trích xuất để lấy IMediaExtractor
, gọi IMediaExtractor
đó để lấy IMediaSources
cho bản nhạc chứa trong tệp, sau đó gọi IMediaSources
để đọc dữ liệu từ các tệp đó.
Để chuyển dữ liệu giữa các quy trình, ứng dụng (hoặc mediaserver
) sẽ đưa dữ liệu vào gói trả lời trong giao dịch Liên kết hoặc sử dụng bộ nhớ dùng chung:
- Việc sử dụng bộ nhớ dùng chung đòi hỏi một lệnh gọi Binder bổ sung để giải phóng bộ nhớ dùng chung, nhưng nhanh hơn và tiêu tốn ít năng lượng hơn cho các vùng đệm lớn.
- Việc sử dụng trong gói đòi hỏi phải sao chép thêm nhưng nhanh hơn và sử dụng ít năng lượng hơn cho các vùng đệm nhỏ hơn 64 KB.
Triển khai
Để hỗ trợ việc di chuyển các thành phần MediaDrm
và MediaCrypto
vào quy trình mediadrmserver
mới, nhà cung cấp phải thay đổi phương thức phân bổ cho vùng đệm bảo mật để cho phép chia sẻ vùng đệm giữa các quy trình.
Trong các bản phát hành Android trước, vùng đệm bảo mật được phân bổ trong mediaserver
bởi OMX::allocateBuffer
và được sử dụng trong quá trình giải mã trong cùng một quy trình, như minh hoạ dưới đây:
Hình 2. Phân bổ vùng đệm Android 6.0 trở xuống trong mediaserver.
Trong Android 7.0, quy trình phân bổ vùng đệm đã thay đổi thành một cơ chế mới giúp mang lại sự linh hoạt trong khi giảm thiểu tác động đến các phương thức triển khai hiện có. Với ngăn xếp MediaDrm
và MediaCrypto
trong quy trình mediadrmserver
mới, các vùng đệm được phân bổ khác nhau và nhà cung cấp phải cập nhật tay điều khiển vùng đệm bảo mật để có thể truyền qua trình liên kết khi MediaCodec
gọi một thao tác giải mã trên MediaCrypto
.
Hình 3. Phân bổ vùng đệm Android 7.0 trở lên trong mediaserver.
Sử dụng tên người dùng gốc
OMX::allocateBuffer
phải trả về con trỏ đến cấu trúc native_handle
, chứa chỉ số mô tả tệp (FD) và dữ liệu số nguyên bổ sung. native_handle
có tất cả các lợi thế khi sử dụng FD, bao gồm cả tính năng hỗ trợ liên kết hiện có cho việc chuyển đổi tuần tự/huỷ chuyển đổi tuần tự, đồng thời cho phép các nhà cung cấp hiện không sử dụng FD linh hoạt hơn.
Sử dụng native_handle_create()
để phân bổ tay điều khiển gốc.
Mã khung có quyền sở hữu cấu trúc native_handle
được phân bổ và chịu trách nhiệm giải phóng tài nguyên trong cả quá trình phân bổ ban đầu của native_handle
và trong quá trình chuyển đổi tuần tự. Khung này phát hành các tay điều khiển gốc bằng native_handle_close()
, theo sau là native_handle_delete()
và chuyển đổi tuần tự/huỷ chuyển đổi tuần tự native_handle
bằng Parcel::writeNativeHandle()/readNativeHandle()
.
Các nhà cung cấp SoC sử dụng FD để biểu thị vùng đệm bảo mật có thể điền FD vào native_handle
bằng FD của họ. Những nhà cung cấp không sử dụng FD có thể đại diện cho vùng đệm bảo mật bằng cách sử dụng các trường bổ sung trong native_buffer
.
Đặt vị trí giải mã
Nhà cung cấp phải cập nhật phương thức giải mã OEMCrypto hoạt động trên native_handle
để thực hiện mọi thao tác cần thiết dành riêng cho nhà cung cấp nhằm giúp native_handle
có thể sử dụng được trong không gian quy trình mới (các thay đổi thường bao gồm cả nội dung cập nhật cho thư viện OEMCrypto).
Vì allocateBuffer
là một thao tác OMX chuẩn, nên Android 7.0 bao gồm một tiện ích OMX mới (OMX.google.android.index.allocateNativeHandle
) để truy vấn tính năng hỗ trợ này và lệnh gọi OMX_SetParameter
sẽ thông báo cho quá trình triển khai OMX rằng ứng dụng này sẽ sử dụng các tay điều khiển gốc.