Pengerasan kerangka media

Untuk meningkatkan keamanan perangkat, Android 7.0 memecah proses mediaserver monolitik menjadi beberapa proses dengan izin dan kemampuan terbatas hanya pada proses yang diperlukan oleh setiap proses. Perubahan ini memitigasi kerentanan keamanan kerangka media dengan:

  • Memisahkan komponen pipeline AV ke dalam proses sandbox khusus aplikasi.
  • Mengaktifkan komponen media yang dapat diperbarui (ekstraktor, codec, dll.).

Perubahan ini juga meningkatkan keamanan bagi pengguna akhir dengan secara signifikan mengurangi tingkat keparahan sebagian besar kerentanan keamanan terkait media, menjaga perangkat dan data pengguna akhir tetap aman.

Vendor OEM dan SoC perlu memperbarui HAL dan perubahan kerangka kerja mereka agar kompatibel dengan arsitektur baru. Khususnya, karena kode Android yang disediakan vendor sering kali mengasumsikan segala sesuatunya berjalan dalam proses yang sama, vendor harus memperbarui kode mereka untuk meneruskan handle asli ( native_handle ) yang memiliki arti di seluruh proses. Untuk referensi penerapan perubahan terkait pengerasan media, lihat frameworks/av dan frameworks/native .

Perubahan arsitektur

Versi Android sebelumnya menggunakan satu proses mediaserver monolitik dengan banyak izin (akses kamera, akses audio, akses driver video, akses file, akses jaringan, dll.). Android 7.0 membagi proses mediaserver menjadi beberapa proses baru yang masing-masing memerlukan serangkaian izin yang jauh lebih kecil:

pengerasan server media

Gambar 1. Perubahan arsitektur untuk pengerasan server media

Arsitektur baru ini memastikan bahwa meskipun suatu proses disusupi, kode berbahaya tidak memiliki akses ke seluruh izin yang sebelumnya dimiliki oleh mediaserver . Proses dibatasi oleh kebijakan SElinux dan seccomp.

Catatan: Karena ketergantungan vendor, beberapa codec masih berjalan di mediaserver dan akibatnya memberikan izin mediaserver lebih dari yang diperlukan. Secara khusus, Widevine Classic terus berjalan di mediaserver untuk Android 7.0.

Perubahan Server Media

Di Android 7.0, ada proses mediaserver untuk mendorong pemutaran dan perekaman, misalnya meneruskan dan menyinkronkan buffer antara komponen dan proses. Proses berkomunikasi melalui mekanisme Binder standar.

Dalam sesi pemutaran file lokal standar, aplikasi meneruskan deskriptor file (FD) ke mediaserver (biasanya melalui MediaPlayer Java API), dan mediaserver :

  1. Membungkus FD menjadi objek Binder DataSource yang diteruskan ke proses ekstraktor, yang menggunakannya untuk membaca dari file menggunakan Binder IPC. (Mediaextractor tidak mendapatkan FD melainkan membuat Binder memanggil kembali ke mediaserver untuk mendapatkan data.)
  2. Memeriksa file, membuat ekstraktor yang sesuai untuk jenis file (misalnya MP3Extractor, atau MPEG4Extractor), dan mengembalikan antarmuka Binder untuk ekstraktor ke proses mediaserver .
  3. Melakukan panggilan Binder IPC ke ekstraktor untuk menentukan jenis data dalam file (misalnya data MP3 atau H.264).
  4. Memanggil proses mediacodec untuk membuat codec dari jenis yang diperlukan; menerima antarmuka Binder untuk codec ini.
  5. Melakukan panggilan Binder IPC berulang kali ke ekstraktor untuk membaca sampel yang dikodekan, menggunakan Binder IPC untuk mengirim data yang dikodekan ke proses mediacodec untuk didekode, dan menerima data yang didekodekan.

Dalam beberapa kasus penggunaan, tidak ada codec yang terlibat (seperti pemutaran yang dibongkar di mana data yang dikodekan dikirim langsung ke perangkat keluaran), atau codec dapat merender data yang didekode secara langsung alih-alih mengembalikan buffer data yang didekode (pemutaran video).

Perubahan MediaCodecService

Layanan codec adalah tempat encoder dan decoder berada. Karena ketergantungan vendor, belum semua codec aktif dalam proses codec. Di Android 7.0:

  • Decoder dan encoder perangkat lunak yang tidak aman hidup dalam proses codec.
  • Decoder aman dan encoder perangkat keras berada di mediaserver (tidak berubah).

Sebuah aplikasi (atau mediaserver ) memanggil proses codec untuk membuat codec dari jenis yang diperlukan, kemudian memanggil codec tersebut untuk meneruskan data yang dikodekan dan mengambil data yang didekodekan (untuk decoding) atau untuk meneruskan data yang didekodekan dan mengambil data yang dikodekan (untuk pengkodean) . Transfer data ke dan dari codec sudah menggunakan memori bersama, sehingga prosesnya tidak berubah.

Perubahan MediaDrmServer

Server DRM digunakan saat memutar konten yang dilindungi DRM, seperti film di Google Play Film. Ini menangani dekripsi data terenkripsi dengan cara yang aman, dan dengan demikian memiliki akses ke sertifikat dan penyimpanan kunci serta komponen sensitif lainnya. Karena ketergantungan vendor, proses DRM belum digunakan di semua kasus.

Perubahan AudioServer

Proses AudioServer menghosting komponen terkait audio seperti input dan output audio, layanan manajer kebijakan yang menentukan perutean audio, dan layanan radio FM. Untuk detail tentang perubahan Audio dan panduan penerapan, lihat Menerapkan audio .

Perubahan Server Kamera

CameraServer mengontrol kamera dan digunakan saat merekam video untuk mendapatkan frame video dari kamera dan kemudian meneruskannya ke mediaserver untuk penanganan lebih lanjut. Untuk detail tentang perubahan dan panduan penerapan perubahan CameraServer, lihat Pengerasan Kerangka Kamera .

Perubahan ExtractorService

Layanan ekstraktor menampung ekstraktor , komponen yang mengurai berbagai format file yang didukung oleh kerangka media. Layanan ekstraktor adalah layanan yang paling tidak memiliki hak istimewa—layanan ini tidak dapat membaca FD sehingga layanan ini melakukan panggilan ke antarmuka Binder (yang disediakan oleh mediaserver for setiap sesi pemutaran) untuk mengakses file.

Sebuah aplikasi (atau mediaserver ) melakukan panggilan ke proses ekstraktor untuk mendapatkan IMediaExtractor , memanggil IMediaExtractor tersebut untuk mendapatkan IMediaSources untuk trek yang terdapat dalam file, dan kemudian memanggil IMediaSources untuk membaca data darinya.

Untuk mentransfer data antar proses, aplikasi (atau mediaserver ) menyertakan data dalam paket balasan sebagai bagian dari transaksi Binder atau menggunakan memori bersama:

  • Menggunakan memori bersama memerlukan panggilan Binder ekstra untuk melepaskan memori bersama tetapi lebih cepat dan menggunakan lebih sedikit daya untuk buffer besar.
  • Menggunakan in-Parcel memerlukan penyalinan ekstra tetapi lebih cepat dan menggunakan lebih sedikit daya untuk buffer yang lebih kecil dari 64KB.

Penerapan

Untuk mendukung perpindahan komponen MediaDrm dan MediaCrypto ke dalam proses mediadrmserver baru, vendor harus mengubah metode alokasi buffer aman agar buffer dapat dibagikan antar proses.

Pada rilis Android sebelumnya, buffer aman dialokasikan di mediaserver oleh OMX::allocateBuffer dan digunakan selama dekripsi dalam proses yang sama, seperti yang ditunjukkan di bawah ini:

Gambar 2. Android 6.0 dan alokasi buffer yang lebih rendah di server media.

Di Android 7.0, proses alokasi buffer telah diubah menjadi mekanisme baru yang memberikan fleksibilitas sekaligus meminimalkan dampak pada implementasi yang sudah ada. Dengan tumpukan MediaDrm dan MediaCrypto dalam proses mediadrmserver yang baru, buffer dialokasikan secara berbeda dan vendor harus memperbarui pegangan buffer aman sehingga buffer tersebut dapat dipindahkan melintasi binder ketika MediaCodec menjalankan operasi dekripsi di MediaCrypto .

Gambar 3. Android 7.0 dan alokasi buffer yang lebih tinggi di server media.

Gunakan pegangan asli

OMX::allocateBuffer harus mengembalikan pointer ke struct native_handle , yang berisi deskriptor file (FD) dan data integer tambahan. native_handle memiliki semua keuntungan menggunakan FD, termasuk dukungan pengikat yang ada untuk serialisasi/deserialisasi, sekaligus memberikan lebih banyak fleksibilitas bagi vendor yang saat ini tidak menggunakan FD.

Gunakan native_handle_create() untuk mengalokasikan pegangan asli. Kode kerangka mengambil kepemilikan struct native_handle yang dialokasikan dan bertanggung jawab untuk melepaskan sumber daya baik dalam proses di mana native_handle awalnya dialokasikan dan dalam proses di mana ia dideserialisasi. Kerangka kerja ini merilis pegangan asli dengan native_handle_close() diikuti oleh native_handle_delete() dan membuat serial/deserialisasi native_handle menggunakan Parcel::writeNativeHandle()/readNativeHandle() .

Vendor SoC yang menggunakan FD untuk mewakili buffer aman dapat mengisi FD di native_handle dengan FD mereka. Vendor yang tidak menggunakan FD dapat mewakili buffer aman menggunakan kolom tambahan di native_buffer .

Tetapkan lokasi dekripsi

Vendor harus memperbarui metode dekripsi OEMCrypto yang beroperasi pada native_handle untuk melakukan operasi spesifik vendor apa pun yang diperlukan agar native_handle dapat digunakan di ruang proses baru (perubahan biasanya mencakup pembaruan pada perpustakaan OEMCrypto).

Karena allocateBuffer adalah operasi OMX standar, Android 7.0 menyertakan ekstensi OMX baru ( OMX.google.android.index.allocateNativeHandle ) untuk menanyakan dukungan ini dan panggilan OMX_SetParameter yang memberi tahu implementasi OMX bahwa ia harus menggunakan pengendali asli.