Hardening framework media

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

  • Memisahkan komponen pipeline AV menjadi proses dengan sandbox khusus aplikasi.
  • Mengaktifkan komponen media yang dapat diupdate (ekstraktor, codec, dll.).

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

OEM dan vendor SoC perlu memperbarui perubahan HAL dan framework agar kompatibel dengan arsitektur baru. Secara khusus, karena kode Android yang disediakan vendor sering kali mengasumsikan bahwa semuanya berjalan dalam proses yang sama, vendor harus memperbarui kode mereka untuk meneruskan handle native (native_handle) yang memiliki arti di seluruh proses. Untuk implementasi referensi perubahan terkait hardening 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 kumpulan izin yang jauh lebih kecil:

hardening mediaserver

Gambar 1. Perubahan arsitektur untuk hardening mediaserver

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

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

Perubahan MediaServer

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

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

  1. Menggabungkan FD ke dalam objek DataSource Binder yang diteruskan ke proses ekstraktor, yang menggunakannya untuk membaca dari file menggunakan Binder IPC. (Mediaextractor tidak mendapatkan FD, tetapi membuat Binder memanggil kembali mediaserver untuk mendapatkan data.)
  2. Memeriksa file, membuat ekstraktor yang sesuai untuk jenis file (misalnya, MP3Extractor, atau MPEG4Extractor), dan menampilkan antarmuka Binder untuk ekstraktor ke proses mediaserver.
  3. Melakukan panggilan IPC Binder 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 ke ekstraktor untuk membaca sampel yang dienkode, menggunakan Binder IPC untuk mengirim data yang dienkode ke proses mediacodec untuk dekode, dan menerima data yang didekode.

Dalam beberapa kasus penggunaan, tidak ada codec yang terlibat (seperti pemutaran yang di-offload saat data yang dienkode dikirim langsung ke perangkat output), atau codec dapat merender data yang didekode secara langsung, bukan menampilkan buffer data yang didekode (pemutaran video).

Perubahan MediaCodecService

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

  • Dekoder dan encoder software yang tidak aman berada dalam proses codec.
  • Decoder aman dan encoder hardware berada di mediaserver (tidak berubah).

Aplikasi (atau mediaserver) memanggil proses codec untuk membuat codec dari jenis yang diperlukan, lalu memanggil codec tersebut untuk meneruskan data yang dienkode dan mengambil data yang didekode (untuk dekode) atau meneruskan data yang didekode dan mengambil data yang dienkode (untuk encoding). Transfer data ke dan dari codec sudah menggunakan memori bersama, sehingga proses tersebut tidak berubah.

Perubahan MediaDrmServer

Server DRM digunakan saat memutar konten yang dilindungi DRM, seperti film di Google Play Film. Komponen ini menangani dekripsi data terenkripsi dengan cara yang aman, sehingga memiliki akses ke penyimpanan sertifikat dan kunci serta komponen sensitif lainnya. Karena dependensi 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 pemilihan rute audio, dan layanan radio FM. Untuk mengetahui detail tentang Perubahan audio dan panduan penerapan, lihat Menerapkan audio.

Perubahan CameraServer

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

Perubahan ExtractorService

Layanan ekstraktor menghosting ekstraktor, komponen yang mengurai berbagai format file yang didukung oleh framework media. Layanan ekstraktor adalah layanan dengan hak istimewa terendah dari semua layanan—layanan ini tidak dapat membaca FD sehingga melakukan panggilan ke antarmuka Binder (disediakan oleh mediaserver for setiap sesi pemutaran) untuk mengakses file.

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

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

  • Penggunaan memori bersama memerlukan panggilan Binder tambahan untuk melepaskan memori bersama, tetapi lebih cepat dan menggunakan lebih sedikit daya untuk buffer besar.
  • Menggunakan dalam Paket memerlukan penyalinan tambahan, tetapi lebih cepat dan menggunakan lebih sedikit daya untuk buffering yang lebih kecil dari 64 KB.

Implementasi

Untuk mendukung pemindahan komponen MediaDrm dan MediaCrypto ke dalam proses mediadrmserver baru, vendor harus mengubah metode alokasi untuk buffering aman agar buffering dapat dibagikan di antara proses.

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

Gambar 2. Alokasi buffering Android 6.0 dan yang lebih rendah di mediaserver.

Di Android 7.0, proses alokasi buffering telah berubah menjadi mekanisme baru yang memberikan fleksibilitas sekaligus meminimalkan dampak pada implementasi yang ada. Dengan stack MediaDrm dan MediaCrypto dalam proses mediadrmserver baru, buffering dialokasikan secara berbeda dan vendor harus memperbarui handle buffering yang aman sehingga dapat ditranspor di seluruh binder saat MediaCodec memanggil operasi dekripsi di MediaCrypto.

Gambar 3. Alokasi buffering Android 7.0 dan yang lebih tinggi di mediaserver.

Menggunakan nama sebutan channel native

OMX::allocateBuffer harus menampilkan pointer ke struct native_handle, yang berisi deskripsi file (FD) dan data bilangan bulat tambahan. native_handle memiliki semua keuntungan penggunaan FD, termasuk dukungan binder yang ada untuk serialisasi/deserialisasi, sekaligus memungkinkan lebih banyak fleksibilitas bagi vendor yang saat ini tidak menggunakan FD.

Gunakan native_handle_create() untuk mengalokasikan handle native. Kode framework mengambil kepemilikan struct native_handle yang dialokasikan dan bertanggung jawab untuk merilis resource dalam proses tempat native_handle awalnya dialokasikan dan dalam proses tempat native_handle dideserialisasi. Framework merilis handle native dengan native_handle_close() diikuti dengan native_handle_delete() dan melakukan serialisasi/deserialisasi native_handle menggunakan Parcel::writeNativeHandle()/readNativeHandle().

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

Menetapkan lokasi dekripsi

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

Karena allocateBuffer adalah operasi OMX standar, Android 7.0 menyertakan ekstensi OMX baru (OMX.google.android.index.allocateNativeHandle) untuk membuat kueri dukungan ini dan panggilan OMX_SetParameter yang memberi tahu implementasi OMX yang harus menggunakan handle native.