Pengerasan Kerangka Media

Untuk meningkatkan keamanan perangkat, Android 7.0 memecah proses mediaserver media monolitik menjadi beberapa proses dengan izin dan kemampuan yang dibatasi hanya yang diperlukan oleh setiap proses. Perubahan ini mengurangi kerentanan keamanan kerangka kerja 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 pengguna akhir dan data 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 mengasumsikan semuanya berjalan dalam proses yang sama, vendor harus memperbarui kode mereka untuk menyebarkan pegangan asli ( native_handle ) yang memiliki arti di seluruh proses. Untuk implementasi referensi perubahan yang terkait dengan pengerasan media, lihat frameworks/av dan frameworks/native .

Perubahan arsitektur

Versi Android sebelumnya menggunakan proses mediaserver monolitik tunggal dengan banyak izin (akses kamera, akses audio, akses driver video, akses file, akses jaringan, dll.). Android 7.0 membagi proses mediaserver media 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 set lengkap izin yang sebelumnya dipegang oleh server media. Proses dibatasi oleh SElinux dan kebijakan seccomp.

Catatan: Karena ketergantungan vendor, beberapa codec masih berjalan di mediaserver media dan akibatnya memberikan mediaserver lebih banyak kepada server media daripada yang diperlukan. Secara khusus, Widevine Classic terus berjalan di mediaserver media untuk Android 7.0.

Perubahan MediaServer

Di Android 7.0, ada proses mediaserver media 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 media (biasanya melalui MediaPlayer Java API), dan mediaserver media :

  1. Membungkus FD menjadi objek Binder DataSource yang diteruskan ke proses ekstraktor, yang menggunakannya untuk membaca dari file menggunakan Binder IPC. ( mediaserver tidak mendapatkan FD tetapi membuat panggilan Binder kembali ke server media untuk mendapatkan data.)
  2. Memeriksa file, membuat ekstraktor yang sesuai untuk jenis file (misalnya MP3Extractor, atau mediaserver ), dan mengembalikan antarmuka Binder untuk ekstraktor ke proses server media.
  3. Membuat panggilan IPC Binder ke extractor untuk menentukan jenis data dalam file (misalnya data MP3 atau H.264).
  4. Panggilan ke dalam proses mediacodec untuk membuat codec dari jenis yang diperlukan; menerima antarmuka Binder untuk codec ini.
  5. Membuat panggilan IPC Binder berulang ke ekstraktor untuk membaca sampel yang disandikan, menggunakan IPC Binder untuk mengirim data yang disandikan ke proses mediacodec untuk decoding, dan menerima data yang didekodekan.

Dalam beberapa kasus penggunaan, tidak ada codec yang terlibat (seperti pemutaran offloaded di mana data yang dikodekan dikirim langsung ke perangkat output), atau codec dapat membuat data yang didekodekan secara langsung alih-alih mengembalikan buffer data yang didekodekan (pemutaran video).

Perubahan Layanan MediaCodec

Layanan codec adalah tempat encoder dan decoder tinggal. Karena ketergantungan vendor, belum semua codec hidup 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 hidup di mediaserver media (tidak berubah).

Sebuah aplikasi (atau server media) memanggil proses codec untuk membuat codec dari jenis yang diperlukan, kemudian memanggil codec itu untuk meneruskan data yang disandikan dan mengambil data yang didekodekan (untuk decoding) atau untuk meneruskan data yang didekodekan dan mengambil data yang disandikan (untuk encoding) . 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 dan komponen sensitif lainnya. Karena ketergantungan vendor, proses DRM belum digunakan dalam semua kasus.

Perubahan AudioServer

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

KameraServer berubah

mediaserver mengontrol kamera dan digunakan saat merekam video untuk mendapatkan bingkai video dari kamera dan kemudian meneruskannya ke server media untuk penanganan lebih lanjut. Untuk detail tentang perubahan dan panduan implementasi untuk perubahan CameraServer, lihat Camera Framework Hardening .

Perubahan ExtractorService

Layanan ekstraktor menghosting ekstraktor , komponen yang mengurai berbagai format file yang didukung oleh kerangka kerja media. Layanan ekstraktor adalah yang paling tidak memiliki hak istimewa dari semua layanan—tidak dapat membaca FD jadi alih-alih membuat panggilan ke antarmuka Binder (disediakan oleh server media mediaserver for setiap sesi pemutaran) untuk mengakses file.

Aplikasi (atau IMediaExtractor mediaserver memanggil IMediaExtractor untuk mendapatkan IMediaSources untuk trek yang terdapat dalam file, dan kemudian memanggil IMediaSources untuk membaca data dari mereka.

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 tambahan 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 pemindahan komponen MediaDrm dan MediaCrypto ke dalam proses mediadrmserver baru, vendor harus mengubah metode alokasi buffer aman untuk memungkinkan buffer dibagikan di antara proses.

Dalam 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 mediaserver.

Di Android 7.0, proses alokasi buffer telah berubah menjadi mekanisme baru yang memberikan fleksibilitas sekaligus meminimalkan dampak pada implementasi yang ada. Dengan tumpukan MediaDrm dan MediaCrypto dalam proses mediadrmserver yang baru, buffer dialokasikan secara berbeda dan vendor harus memperbarui pegangan buffer yang aman sehingga dapat diangkut melintasi pengikat saat MediaCodec menjalankan operasi dekripsi pada MediaCrypto .

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

Menggunakan 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, sementara memungkinkan lebih banyak fleksibilitas untuk 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 deserialized. Kerangka kerja melepaskan 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 bidang tambahan di native_buffer .

Mengatur lokasi dekripsi

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

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