Renforcement du cadre multimédia

Pour améliorer la sécurité de l'appareil, Android 7.0 divise le processus de mediaserver monolithique en plusieurs processus avec des autorisations et des capacités limitées uniquement à celles requises par chaque processus. Ces modifications atténuent les vulnérabilités de sécurité de l'infrastructure multimédia en :

  • Fractionnement des composants du pipeline AV en processus en bac à sable spécifiques à l'application.
  • Activation des composants multimédias pouvant être mis à jour (extracteurs, codecs, etc.).

Ces modifications améliorent également la sécurité des utilisateurs finaux en réduisant considérablement la gravité de la plupart des vulnérabilités de sécurité liées aux médias, en protégeant les appareils et les données des utilisateurs finaux.

Les OEM et les fournisseurs de SoC doivent mettre à jour leurs modifications de HAL et de framework pour les rendre compatibles avec la nouvelle architecture. Plus précisément, étant donné que le code Android fourni par le fournisseur suppose souvent que tout s'exécute dans le même processus, les fournisseurs doivent mettre à jour leur code pour transmettre les poignées natives ( native_handle ) qui ont une signification entre les processus. Pour une implémentation de référence des modifications liées au durcissement des médias, reportez-vous à frameworks/av et frameworks/native .

Changements architecturaux

Les versions précédentes d'Android utilisaient un seul processus de mediaserver monolithique avec de nombreuses autorisations (accès à la caméra, accès audio, accès au pilote vidéo, accès aux fichiers, accès au réseau, etc.). Android 7.0 divise le processus du mediaserver en plusieurs nouveaux processus qui nécessitent chacun un ensemble beaucoup plus restreint d'autorisations :

durcissement du serveur multimédia

Figure 1. Modifications de l'architecture pour le renforcement du serveur multimédia

Cette nouvelle architecture garantit que même si un processus est compromis, le code malveillant n'a pas accès à l'ensemble complet des autorisations précédemment détenues par le serveur multimédia. Les processus sont limités par les politiques SElinux et seccomp.

Remarque : en raison des dépendances des fournisseurs, certains codecs s'exécutent toujours dans le mediaserver et accordent par conséquent au mediaserver plus d'autorisations que nécessaire. Plus précisément, Widevine Classic continue de fonctionner dans le mediaserver pour Android 7.0.

Modifications du serveur multimédia

Dans Android 7.0, le processus de mediaserver existe pour piloter la lecture et l'enregistrement, par exemple en passant et en synchronisant les tampons entre les composants et les processus. Les processus communiquent via le mécanisme Binder standard.

Dans une session de lecture de fichier local standard, l'application transmet un descripteur de fichier (FD) au mediaserver (généralement via l'API Java mediaserver ), et le serveur multimédia :

  1. Enveloppe le FD dans un objet Binder DataSource qui est transmis au processus d'extraction, qui l'utilise pour lire le fichier à l'aide de Binder IPC. (Le mediaextractor n'obtient pas le FD mais effectue à la place des appels Binder vers le mediaserver pour obtenir les données.)
  2. Examine le fichier, crée l'extracteur approprié pour le type de fichier (par exemple, MP3Extractor ou MPEG4Extractor) et renvoie une interface Binder pour l'extracteur au processus du mediaserver .
  3. Effectue des appels Binder IPC à l'extracteur pour déterminer le type de données dans le fichier (par exemple, des données MP3 ou H.264).
  4. Appels dans le processus mediacodec pour créer des codecs du type requis ; reçoit les interfaces Binder pour ces codecs.
  5. Effectue des appels répétés Binder IPC à l'extracteur pour lire des échantillons codés, utilise le Binder IPC pour envoyer des données codées au processus mediacodec pour décodage et reçoit des données décodées.

Dans certains cas d'utilisation, aucun codec n'est impliqué (comme une lecture déchargée où les données codées sont envoyées directement au périphérique de sortie), ou le codec peut restituer les données décodées directement au lieu de renvoyer un tampon de données décodées (lecture vidéo).

Modifications de MediaCodecService

Le service de codec est l'endroit où vivent les encodeurs et les décodeurs. En raison des dépendances des fournisseurs, tous les codecs ne sont pas encore intégrés au processus de codec. Sous Android 7.0 :

  • Les décodeurs non sécurisés et les encodeurs logiciels vivent dans le processus de codec.
  • Les décodeurs sécurisés et les encodeurs matériels résident dans le mediaserver (inchangé).

Une application (ou un serveur multimédia) appelle le processus de codec pour créer un codec du type requis, puis appelle ce codec pour transmettre les données codées et récupérer les données décodées (pour le décodage) ou pour transmettre les données décodées et récupérer les données codées (pour le codage) . Le transfert de données vers et depuis les codecs utilise déjà la mémoire partagée, de sorte que le processus reste inchangé.

Modifications de MediaDrmServer

Le serveur DRM est utilisé lors de la lecture de contenu protégé par DRM, tel que des films dans Google Play Films. Il gère le décryptage des données cryptées de manière sécurisée et, en tant que tel, a accès au stockage des certificats et des clés et à d'autres composants sensibles. En raison des dépendances des fournisseurs, le processus DRM n'est pas encore utilisé dans tous les cas.

Modifications du serveur audio

Le processus AudioServer héberge des composants audio tels que l'entrée et la sortie audio, le service policymanager qui détermine le routage audio et le service de radio FM. Pour plus d'informations sur les modifications audio et les conseils d'implémentation, voir Implémentation de l'audio .

Modifications de CameraServer

Le CameraServer contrôle la caméra et est utilisé lors de l'enregistrement vidéo pour obtenir des images vidéo de la caméra, puis les transmettre au mediaserver pour une manipulation ultérieure. Pour plus de détails sur les modifications et les conseils de mise en œuvre des modifications de CameraServer, reportez-vous à Camera Framework Hardening .

Modifications d'ExtractorService

Le service d'extraction héberge les extracteurs , des composants qui analysent les différents formats de fichiers pris en charge par le framework multimédia. Le service d'extraction est le moins privilégié de tous les services - il ne peut pas lire les FD, il fait donc à la place des appels sur une interface Binder (fournie par le mediaserver for chaque session de lecture) pour accéder aux fichiers.

Une application (ou mediaserver ) appelle le processus d'extraction pour obtenir un IMediaExtractor , appelle ce IMediaExtractor pour obtenir IMediaSources pour la piste contenue dans le fichier, puis appelle IMediaSources pour en lire les données.

Pour transférer les données entre les processus, l'application (ou mediaserver ) inclut les données dans le colis de réponse dans le cadre de la transaction Binder ou utilise la mémoire partagée :

  • L'utilisation de la mémoire partagée nécessite un appel Binder supplémentaire pour libérer la mémoire partagée, mais elle est plus rapide et consomme moins d'énergie pour les tampons volumineux.
  • L'utilisation de in-Parcel nécessite une copie supplémentaire mais est plus rapide et utilise moins d'énergie pour les tampons inférieurs à 64 Ko.

Mise en œuvre

Pour prendre en charge le déplacement des composants MediaDrm et MediaCrypto dans le nouveau processus mediadrmserver , les fournisseurs doivent modifier la méthode d'allocation des tampons sécurisés pour permettre le partage des tampons entre les processus.

Dans les versions précédentes d'Android, les tampons sécurisés sont alloués dans mediaserver par OMX::allocateBuffer allocateBuffer et utilisés lors du déchiffrement dans le même processus, comme indiqué ci-dessous :

Figure 2. Android 6.0 et allocation de tampon inférieure dans le serveur multimédia.

Dans Android 7.0, le processus d'allocation de mémoire tampon a été remplacé par un nouveau mécanisme qui offre de la flexibilité tout en minimisant l'impact sur les implémentations existantes. Avec les piles MediaDrm et MediaCrypto dans le nouveau processus mediadrmserver , les tampons sont alloués différemment et les fournisseurs doivent mettre à jour les descripteurs de tampon sécurisés afin qu'ils puissent être transportés à travers le classeur lorsque MediaCodec appelle une opération de décryptage sur MediaCrypto .

Figure 3. Allocation de tampon Android 7.0 et versions ultérieures dans le serveur multimédia.

Utilisation de poignées natives

Le OMX::allocateBuffer allocateBuffer doit renvoyer un pointeur vers une structure native_handle , qui contient des descripteurs de fichiers (FD) et des données entières supplémentaires. Un native_handle présente tous les avantages de l'utilisation des FD, y compris la prise en charge des classeurs existants pour la sérialisation/désérialisation, tout en offrant plus de flexibilité aux fournisseurs qui n'utilisent pas actuellement les FD.

Utilisez native_handle_create() pour allouer le handle natif. Le code du framework s'approprie la structure native_handle allouée et est responsable de la libération des ressources à la fois dans le processus où le native_handle est initialement alloué et dans le processus où il est désérialisé. Le framework libère les handles natifs avec native_handle_close() suivi de native_handle_delete() et sérialise/désérialise le native_handle en utilisant Parcel::writeNativeHandle()/readNativeHandle() .

Les fournisseurs de SoC qui utilisent des FD pour représenter des tampons sécurisés peuvent remplir le FD dans native_handle avec leur FD. Les fournisseurs qui n'utilisent pas de FD peuvent représenter des tampons sécurisés en utilisant des champs supplémentaires dans native_buffer .

Définition de l'emplacement de décryptage

Les fournisseurs doivent mettre à jour la méthode de décryptage OEMCrypto qui fonctionne sur le native_handle pour effectuer toutes les opérations spécifiques au fournisseur nécessaires pour rendre le native_handle utilisable dans le nouvel espace de processus (les modifications incluent généralement des mises à jour des bibliothèques OEMCrypto).

Comme allocateBuffer est une opération OMX standard, Android 7.0 inclut une nouvelle extension OMX ( OMX.google.android.index.allocateNativeHandle ) pour demander cette prise en charge et un appel OMX_SetParameter qui notifie à l'implémentation OMX qu'elle doit utiliser des poignées natives.