Android 7.0, cihaz güvenliğini iyileştirmek için tekil mediaserver
sürecini, izinleri ve özellikleri yalnızca her bir sürecin gerektirdiğiyle sınırlı olacak şekilde birden fazla sürece ayırır. Bu değişiklikler, medya çerçevesi güvenlik açıklarını aşağıdaki şekilde azaltır:
- AV ardışık düzeni bileşenlerini uygulamaya özel korumalı alan süreçlerine bölme.
- Güncellenebilir medya bileşenlerini (ayırıcı, codec vb.) etkinleştirme
Bu değişiklikler, medyayla ilgili güvenlik açıklarının çoğunun önemini önemli ölçüde azaltarak son kullanıcıların güvenliğini de artırır ve son kullanıcı cihazlarını ve verilerini güvende tutar.
OEM'lerin ve SoC tedarikçi firmalarının, HAL ve çerçeve değişikliklerini yeni mimariyle uyumlu hale getirmek için güncellemeleri gerekir. Daha açık belirtmek gerekirse, tedarikçi firma tarafından sağlanan Android kodu genellikle her şeyin aynı işlemde çalıştığını varsaydığında, tedarikçiler kodlarını, işlemler arasında anlamlı olan yerel tutamaçların (native_handle
) aktarılması için güncellemelidir. Medya güçlendirmeyle ilgili değişikliklerin referans uygulaması için frameworks/av
ve frameworks/native
başlıklı makaleleri inceleyin.
Mimari değişiklikler
Android'in önceki sürümlerinde, çok sayıda izine (kamera erişimi, ses erişimi, video sürücüsü erişimi, dosya erişimi, ağ erişimi vb.) sahip tek bir monolitik mediaserver
işlemi kullanılıyordu. Android 7.0, mediaserver
sürecini her biri çok daha küçük bir izin grubu gerektiren birkaç yeni sürece ayırır:
Şekil 1. Medya sunucusunun güvenliğini artırmak için mimari değişiklikleri
Bu yeni mimari, bir işlemin güvenliği ihlal edilse bile kötü amaçlı kodun daha önce mediaserver
tarafından sahip olunan izinlerin tamamına erişememesi için gerekli önlemleri alır. İşlemler SELinux ve seccomp politikalarıyla kısıtlanır.
Not: Tedarikçi bağımlılıkları nedeniyle bazı codec'ler hâlâ mediaserver
içinde çalışır ve sonuç olarak mediaserver
'ye gerekenden daha fazla izin verir. Daha açık belirtmek gerekirse Widevine Classic, Android 7.0 için mediaserver
sürümünde çalışmaya devam eder.
MediaServer değişiklikleri
Android 7.0'da mediaserver
işlemi, oynatma ve kaydı (ör. bileşenler ve işlemler arasında arabellekleri aktarma ve senkronize etme) yönetmek için kullanılır. İşlemler, standart Binder mekanizması aracılığıyla iletişim kurar.
Standart bir yerel dosya oynatma oturumunda uygulama, mediaserver
'e (genellikle MediaPlayer Java API aracılığıyla) bir dosya tanımlayıcısı (FD) iletir ve mediaserver
:
- FD'yi, ayıklayıcı işlemine iletilen ve Binder IPC'yi kullanarak dosyadan okumak için kullanan bir Binder DataSource nesnesine sarar. (mediaextractor, FD'yi almaz, bunun yerine verileri almak için
mediaserver
'ye geri Binder çağrıları yapar.) - Dosyayı inceler, dosya türü için uygun ayıklayıcıyı (ör. MP3Extractor veya MPEG4Extractor) oluşturur ve
mediaserver
işlemine ayıklayıcı için bir Binder arayüzü döndürür. - Dosyadaki veri türünü (ör. MP3 veya H.264 verileri) belirlemek için ayrıştırıcıya Binder IPC çağrıları yapar.
- Gerekli türde codec'ler oluşturmak için
mediacodec
sürecini çağırır; bu codec'ler için Binder arayüzlerini alır. - Kodlanmış örnekleri okumak için ayıklayıcıya tekrar tekrar Binder IPC çağrıları yapar, kodlanmış verileri kod çözme işlemi için
mediacodec
işlemine göndermek üzere Binder IPC'yi kullanır ve kod çözülmüş verileri alır.
Bazı kullanım alanlarında kodlayıcı kullanılmaz (ör. kodlanmış verilerin doğrudan çıkış cihazına gönderildiği aktarılan oynatma) veya kodlayıcı, kodlanmış verilerin arabelleğini döndürmek yerine kodlanmış verileri doğrudan oluşturabilir (video oynatma).
MediaCodecService değişiklikleri
Kodek hizmeti, kodlayıcıların ve kod çözücülerin bulunduğu yerdir. Tedarikçi bağımlılıkları nedeniyle, tüm codec'ler henüz codec sürecinde kullanılamıyor. Android 7.0'da:
- Güvenli olmayan kod çözücüler ve yazılım kodlayıcılar codec işleminde bulunur.
- Güvenli kod çözücüler ve donanım kodlayıcılar
mediaserver
(değişmedi) sürümündedir.
Bir uygulama (veya mediaserver
), gerekli türde bir codec oluşturmak için codec işlemini çağırır, ardından kodlanmış verileri iletmek ve kodlanmış verileri almak (kod çözme için) ya da kodlanmış verileri iletmek ve kodlanmış verileri almak (kodlama için) için bu codec'i çağırır. Kodeklere ve kodeklerden veri aktarımı zaten paylaşılan bellek kullandığından bu işlemde değişiklik yapılmamıştır.
MediaDrmServer değişiklikleri
DRM sunucusu, Google Play Filmler'deki filmler gibi DRM korumalı içerikler oynatırken kullanılır. Şifrelenmiş verilerin şifresini güvenli bir şekilde çözer ve bu nedenle sertifika, anahtar depolama ve diğer hassas bileşenlere erişebilir. Tedarikçi bağımlılıkları nedeniyle DRM süreci henüz her durumda kullanılmıyor.
AudioServer değişiklikleri
AudioServer işlemi, ses girişi ve çıkışı, ses yönlendirmesini belirleyen policymanager hizmeti ve FM radyo hizmeti gibi sesle ilgili bileşenleri barındırır. Ses değişiklikleri ve uygulamayla ilgili ayrıntılar için Sesi uygulama başlıklı makaleyi inceleyin.
CameraServer değişiklikleri
CameraServer, kamerayı kontrol eder ve video kaydederken kameradan video kareleri almak ve daha sonra bunları daha fazla işleme almak için mediaserver
'e iletmek üzere kullanılır. Değişiklikler ve CameraServer değişiklikleri için uygulama kılavuzu hakkında ayrıntılı bilgi edinmek üzere Kamera Çerçevesi Güçlendirme başlıklı makaleyi inceleyin.
ExtractorService değişiklikleri
Ayıklama hizmeti, medya çerçevesi tarafından desteklenen çeşitli dosya biçimlerini ayrıştıran bileşenler olan ayıklama araçlarını barındırır. Ayıklama hizmeti, tüm hizmetler arasında en az ayrıcalıklı olanıdır. FD'leri okuyamadığı için dosyalara erişmek amacıyla bir Binder arayüzüne (mediaserver for
her oynatma oturumu tarafından sağlanır) çağrı yapar.
Bir uygulama (veya mediaserver
), IMediaExtractor
elde etmek için ayrıştırıcı işlemine çağrı gönderir, dosyadaki parça için IMediaExtractor
'ı çağırır ve ardından bu parçalardan veri okumak için IMediaSources
'ı çağırır. IMediaSources
Uygulama (veya mediaserver
), verileri Binder işleminin bir parçası olarak yanıt paketine dahil eder veya paylaşılan belleği kullanır:
- Paylaşılan bellek kullanmak, paylaşılan belleği serbest bırakmak için ek bir Binder çağrısı gerektirir ancak büyük arabellekler için daha hızlıdır ve daha az güç kullanır.
- Paket içi kullanmanın ekstra kopyalama işlemi gerektirmesi dezavantaj olsa da bu yöntem, 64 KB'tan küçük tamponlar için daha hızlıdır ve daha az güç tüketir.
Uygulama
MediaDrm
ve MediaCrypto
bileşenlerinin yeni mediadrmserver
sürecine taşınmasını desteklemek için tedarikçilerin, güvenli tamponların süreçler arasında paylaşılmasına izin vermek üzere tamponların ayırma yöntemini değiştirmesi gerekir.
Önceki Android sürümlerinde güvenli tamponlar mediaserver
tarafından OMX::allocateBuffer
içinde ayrılır ve aşağıdaki gibi aynı işlemde şifre çözme sırasında kullanılır:
Şekil 2. Android 6.0 ve önceki sürümlerde medya sunucusunda arabellek ayırma.
Android 7.0'da, arabellek ayırma süreci, mevcut uygulamalar üzerindeki etkiyi en aza indirirken esneklik sağlayan yeni bir mekanizmayla değiştirildi. Yeni mediadrmserver
sürecinde MediaDrm
ve MediaCrypto
yığınları kullanıldığında tamponlar farklı şekilde ayrılır ve MediaCodec
, MediaCrypto
üzerinde bir şifre çözme işlemi başlattığında tedarikçi firmaların güvenli tampon tutamaçlarını, binder üzerinden taşınabilmeleri için güncellemesi gerekir.
Şekil 3. Android 7.0 ve sonraki sürümlerde medya sunucusunda arabellek ayırma.
Yerel herkese açık kullanıcı adlarını kullanma
OMX::allocateBuffer
, dosya tanımlayıcıları (FD'ler) ve ek tam sayı verileri içeren bir native_handle
yapısının işaretçisini döndürmelidir. native_handle
, serileştirme/seri bozma için mevcut bağlayıcı desteği de dahil olmak üzere FD'leri kullanmanın tüm avantajlarına sahiptir. Ayrıca, şu anda FD'leri kullanmayan tedarikçilere daha fazla esneklik sağlar.
Yerel herkese açık kullanıcı adını atamak için native_handle_create()
öğesini kullanın.
Çerçeve kodu, ayrılan native_handle
struct'unun sahipliğini alır ve hem native_handle
'ün ilk olarak ayrıldığı işlemde hem de seri dışına çıkarıldığı işlemde kaynakları serbest bırakmaktan sorumludur. Çerçeve, native_handle_close()
ve ardından native_handle_delete()
ile yerel alıcılar yayınlar ve Parcel::writeNativeHandle()/readNativeHandle()
kullanarak native_handle
öğesini serileştirir/seri dışına çıkarır.
Güvenli tamponları temsil etmek için FD'leri kullanan SoC tedarikçileri, native_handle
içindeki FD'yi kendi FD'leriyle doldurabilir. FD kullanmayan tedarikçiler, native_buffer
içinde ek alanlar kullanarak güvenli arabellekleri temsil edebilir.
Şifre çözme konumunu ayarlama
Tedarikçi firmalar, native_handle
'yi yeni işlem alanında kullanılabilir hale getirmek için gerekli olan tedarikçiye özgü işlemleri gerçekleştirmek üzere native_handle
üzerinde çalışan OEMCrypto şifre çözme yöntemini güncellemelidir (değişiklikler genellikle OEMCrypto kitaplıklarında yapılan güncellemeleri içerir).
allocateBuffer
standart bir OMX işlemi olduğundan Android 7.0, bu desteği sorgulamak için yeni bir OMX uzantısı (OMX.google.android.index.allocateNativeHandle
) ve OMX uygulamasına yerel imleçleri kullanması gerektiğini bildiren bir OMX_SetParameter
çağrısı içerir.