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:
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
:
- 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.) - Memeriksa file, membuat ekstraktor yang sesuai untuk jenis file
(misalnya, MP3Extractor, atau MPEG4Extractor), dan menampilkan antarmuka Binder untuk
ekstraktor ke proses
mediaserver
. - Melakukan panggilan IPC Binder ke ekstraktor untuk menentukan jenis data dalam file (misalnya, data MP3 atau H.264).
- Memanggil proses
mediacodec
untuk membuat codec dari jenis yang diperlukan; menerima antarmuka Binder untuk codec ini. - 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.