媒體框架強化

為了提高設備安全性,Android 7.0 將單一的mediaserver進程分解為多個進程,其權限和功能僅限於每個進程所需的權限和功能。這些更改通過以下方式緩解媒體框架安全漏洞:

  • 將 AV 管道組件拆分為特定於應用程序的沙盒進程。
  • 啟用可更新的媒體組件(提取器、編解碼器等)。

這些更改還通過顯著降低大多數與媒體相關的安全漏洞的嚴重性、保持最終用戶設備和數據的安全來提高最終用戶的安全性。

OEM 和 SoC 供應商需要更新其 HAL 和框架更改,以使其與新架構兼容。具體來說,由於供應商提供的 Android 代碼通常假定所有內容都在同一進程中運行,因此供應商必須更新其代碼以傳遞跨進程有意義的本機句柄 ( native_handle )。有關與媒體強化相關的更改的參考實現,請參閱frameworks/avframeworks/native

架構變化

以前的 Android 版本使用具有大量權限(攝像頭訪問、音頻訪問、視頻驅動程序訪問、文件訪問、網絡訪問等)的單一、單一的mediaserver進程。 Android 7.0 將mediaserver進程拆分為幾個新進程,每個進程需要的權限要少得多:

媒體服務器加固

圖 1.媒體服務器強化的架構更改

這種新架構確保即使進程受到破壞,惡意代碼也無法訪問以前由 mediaserver 持有的完整權限集。進程受 SElinux 和 seccomp 策略的限制。

注意:由於供應商依賴性,一些編解碼器仍然在mediaserver中運行,因此授予mediaserver比必要更多的權限。具體來說, mediaserver Classic 繼續在適用於 Android 7.0 的媒體服務器中運行。

媒體服務器更改

在 Android 7.0 中, mediaserver進程用於驅動播放和錄製,例如在組件和進程之間傳遞和同步緩衝區。進程通過標準的 Binder 機制進行通信。

在標準的本地文件播放會話中,應用程序將文件描述符 (FD) 傳遞給mediaserver (通常通過 MediaPlayer Java API),然後mediaserver

  1. 將 FD 包裝到一個 Binder DataSource 對像中,該對像傳遞給提取器進程,該進程使用它使用 Binder IPC 從文件中讀取。 (mediaextractor 沒有獲取 FD,而是讓 Binder 回調到mediaserver以獲取數據。)
  2. 檢查文件,為文件類型(例如 MP3Extractor 或 MPEG4Extractor)創建適當的提取器,並將提取器的 Binder 接口返回給mediaserver進程。
  3. 使 Binder IPC 調用提取器以確定文件中數據的類型(例如 MP3 或 H.264 數據)。
  4. 調用mediacodec進程以創建所需類型的編解碼器;接收這些編解碼器的 Binder 接口。
  5. 重複 Binder IPC 調用提取器讀取編碼樣本,使用 Binder IPC 將編碼數據發送到mediacodec進程進行解碼,並接收解碼數據。

在某些用例中,不涉及編解碼器(例如卸載播放,其中編碼數據直接發送到輸出設備),或者編解碼器可以直接渲染解碼數據而不是返回解碼數據的緩衝區(視頻播放)。

MediaCodecService 更改

編解碼器服務是編碼器和解碼器所在的位置。由於供應商依賴性,並非所有編解碼器都存在於編解碼器進程中。在 Android 7.0 中:

  • 非安全解碼器和軟件編碼器存在於編解碼器過程中。
  • 安全解碼器和硬件編碼器位於mediaserver中(未更改)。

應用程序(或媒體服務器)調用編解碼器進程以創建所需類型的編解碼器,然後調用該編解碼器以傳入編碼數據並檢索解碼數據(用於解碼)或傳入解碼數據並檢索編碼數據(用於編碼) .與編解碼器之間的數據傳輸已經使用共享內存,因此該過程保持不變。

MediaDrmServer 更改

DRM 服務器用於播放受 DRM 保護的內容,例如 Google Play 電影中的電影。它以安全的方式處理加密數據的解密,因此可以訪問證書和密鑰存儲以及其他敏感組件。由於供應商依賴性,DRM 流程尚未在所有情況下都使用。

音頻服務器更改

AudioServer 進程託管音頻相關組件,例如音頻輸入和輸出、確定音頻路由的策略管理器服務和 FM 廣播服務。有關音頻更改和實施指南的詳細信息,請參閱實施音頻

相機服務器更改

CameraServer 控制攝像頭,用於在錄製視頻時從攝像頭獲取視頻幀,然後將它們傳遞給mediaserver進行進一步處理。有關 CameraServer 更改的更改和實施指南的詳細信息,請參閱Camera Framework Hardening

ExtractorService 更改

提取器服務託管提取器、解析媒體框架支持的各種文件格式的組件。提取器服務是所有服務中權限最低的——它無法讀取 FD,因此它調用 Binder 接口(由mediaserver for每個播放會話提供)來訪問文件。

應用程序(或mediaserver )調用提取器進程以獲取IMediaExtractor ,調用該IMediaExtractor以獲取文件中包含的軌道的IMediaSources ,然後調用IMediaSources以從中讀取數據。

為了在進程之間傳輸數據,應用程序(或mediaserver )將 reply-Parcel 中的數據包含在 Binder 事務中或使用共享內存:

  • 使用共享內存需要額外的 Binder 調用來釋放共享內存,但對於大緩衝區來說速度更快且功耗更低。
  • 使用in-Parcel需要額外的複制,但對於小於 64KB 的緩衝區,速度更快且功耗更低。

執行

為了支持將MediaDrmMediaCrypto組件移動到新的mediadrmserver進程中,供應商必須更改安全緩衝區的分配方法,以允許在進程之間共享緩衝區。

在之前的 Android 版本中,安全緩衝區由OMX::allocateBuffermediaserver中分配,並在同一進程中解密時使用,如下所示:

圖 2. Android 6.0 及更低版本媒體服務器中的緩衝區分配。

在 Android 7.0 中,緩衝區分配過程已更改為一種新機制,該機制提供了靈活性,同時將對現有實現的影響降至最低。在新的mediadrmserver進程中使用MediaDrmMediaCrypto堆棧,緩衝區的分配方式不同,供應商必須更新安全緩衝區句柄,以便在MediaCodec調用MediaCrypto上的解密操作時可以跨綁定器傳輸它們。

圖 3. Android 7.0 及更高版本在 mediaserver 中的緩衝區分配。

使用本機句柄

OMX::allocateBuffer必須返回一個指向native_handle結構的指針,該結構包含文件描述符 (FD) 和其他整數數據。 native_handle具有使用 FD 的所有優點,包括現有的對序列化/反序列化的 binder 支持,同時為當前不使用 FD 的供應商提供更大的靈活性。

使用native_handle_create()分配本機句柄。框架代碼擁有分配的native_handle結構的所有權,並負責在native_handle最初分配的進程和反序列化的進程中釋放資源。該框架使用native_handle_close()和 native_handle_delete() 釋放本機句柄,並使用Parcel::writeNativeHandle()/readNativeHandle() native_handle_delete()化/反序列化native_handle

使用 FD 表示安全緩衝區的 SoC 供應商可以使用他們的 FD 填充native_handle中的 FD。不使用 FD 的供應商可以使用native_buffer中的附加字段來表示安全緩衝區。

設置解密位置

供應商必須更新在 native_handle 上運行的native_handle解密方法,以執行使native_handle在新進程空間中可用所需的任何供應商特定操作(更改通常包括對 OEMCrypto 庫的更新)。

由於allocateBuffer是標準的 OMX 操作,Android 7.0 包含一個新的 OMX 擴展 ( OMX.google.android.index.allocateNativeHandle ) 來查詢此支持和一個OMX_SetParameter調用,通知 OMX 實現它應該使用本機句柄。