O Google está comprometido em promover a equidade racial para as comunidades negras. Veja como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Endurecimento da estrutura de mídia

Para melhorar a segurança do dispositivo, o Android 7.0 divide o processo monolítico do mediaserver em vários processos com permissões e recursos restritos apenas aos exigidos por cada processo. Essas alterações atenuam as vulnerabilidades de segurança da estrutura de mídia:

  • Divisão dos componentes do pipeline AV em processos em área restrita específicos do aplicativo.
  • Ativando componentes de mídia atualizáveis ​​(extratores, codecs etc.).

Essas alterações também melhoram a segurança dos usuários finais, reduzindo significativamente a gravidade da maioria das vulnerabilidades de segurança relacionadas à mídia, mantendo os dispositivos e os dados do usuário final seguros.

Os OEMs e fornecedores de SoC precisam atualizar suas alterações de HAL e estrutura para torná-las compatíveis com a nova arquitetura. Especificamente, como o código Android fornecido pelo fornecedor geralmente pressupõe que tudo é executado no mesmo processo, os fornecedores devem atualizar seu código para passar por identificadores nativos ( native_handle ) que tenham significado entre os processos. Para uma implementação de referência das mudanças relacionadas ao fortalecimento da mídia, consulte frameworks/av e frameworks/native .

Mudanças arquitetônicas

As versões anteriores do Android usavam um único processo de mediaserver monolítico com muitas permissões (acesso à câmera, acesso a áudio, acesso ao driver de vídeo, acesso a arquivos, acesso à rede etc.). O Android 7.0 divide o processo do mediaserver em vários novos processos, cada um exigindo um conjunto de permissões muito menor:

endurecimento do mediaserver

Figura 1. Alterações na arquitetura para o fortalecimento do mediaserver

Essa nova arquitetura garante que, mesmo que um processo seja comprometido, o código malicioso não tenha acesso ao conjunto completo de permissões anteriormente mantidas pelo mediaserver. Os processos são restritos pelas políticas SElinux e seccomp.

Nota: Devido às dependências do fornecedor, alguns codecs ainda são executados no mediaserver e consequentemente concedem ao mediaserver mais permissões do que o necessário. Especificamente, o Widevine Classic continua sendo executado no mediaserver para Android 7.0.

Alterações no MediaServer

No Android 7.0, o processo mediaserver existe para direcionar a reprodução e a gravação, por exemplo, passando e sincronizando buffers entre componentes e processos. Os processos se comunicam através do mecanismo padrão do fichário.

Em uma sessão de reprodução de arquivo local padrão, o aplicativo passa um descritor de arquivo (FD) para o mediaserver de mediaserver (geralmente por meio da API Java do MediaPlayer) e o mediaserver :

  1. Agrupa o FD em um objeto Binder DataSource que é passado para o processo extrator, que o utiliza para ler o arquivo usando o Binder IPC. (O mediaextractor não recebe o FD, mas faz as chamadas do Binder de volta ao mediaserver de mediaserver para obter os dados.)
  2. Examina o arquivo, cria o extrator apropriado para o tipo de arquivo (por exemplo, MP3Extractor ou MPEG4Extractor) e retorna uma interface do Binder para o extrator ao processo do mediaserver .
  3. Faz chamadas IPC do Binder ao extrator para determinar o tipo de dados no arquivo (por exemplo, dados MP3 ou H.264).
  4. Chama o processo mediacodec para criar codecs do tipo necessário; recebe interfaces do Binder para esses codecs.
  5. Faz chamadas repetidas do Binder IPC ao extrator para ler amostras codificadas, usa o Binder IPC para enviar dados codificados para o processo mediacodec para decodificação e recebe dados decodificados.

Em alguns casos de uso, nenhum codec está envolvido (como uma reprodução descarregada em que os dados codificados são enviados diretamente para o dispositivo de saída) ou o codec pode renderizar os dados decodificados diretamente em vez de retornar um buffer de dados decodificados (reprodução de vídeo).

Alterações do MediaCodecService

O serviço de codec é onde vivem os codificadores e decodificadores. Devido às dependências do fornecedor, nem todos os codecs ainda vivem no processo. No Android 7.0:

  • Decodificadores não seguros e codificadores de software vivem no processo de codec.
  • Decodificadores seguros e codificadores de hardware vivem no mediaserver (inalterado).

Um aplicativo (ou servidor de mídia) chama o processo de codec para criar um codec do tipo necessário, depois chama esse codec para passar dados codificados e recuperar dados decodificados (para decodificação) ou para passar dados decodificados e recuperar dados codificados (para codificação) . A transferência de dados para e de codecs já usa memória compartilhada, para que o processo não seja alterado.

Alterações do MediaDrmServer

O servidor DRM é usado ao reproduzir conteúdo protegido por DRM, como filmes no Google Play Filmes. Ele lida com a descriptografia dos dados criptografados de maneira segura e, como tal, tem acesso ao armazenamento de certificados e chaves e outros componentes confidenciais. Devido às dependências do fornecedor, o processo DRM ainda não é usado em todos os casos.

Alterações no AudioServer

O processo AudioServer hospeda componentes relacionados a áudio, como entrada e saída de áudio, o serviço de gerenciador de políticas que determina o roteamento de áudio e o serviço de rádio FM. Para detalhes sobre alterações de áudio e orientações de implementação, consulte Implementando áudio .

Alterações no CameraServer

O CameraServer controla a câmera e é usado na gravação de vídeo para obter quadros de vídeo da câmera e depois passá-los ao mediaserver para posterior manuseio. Para obter detalhes sobre mudanças e orientações de implementação para mudanças no CameraServer, consulte Proteção da estrutura da câmera .

Alterações no ExtractorService

O serviço extrator hospeda os extratores , componentes que analisam os vários formatos de arquivo suportados pela estrutura de mídia. O serviço extrator é o menos privilegiado de todos os serviços - ele não consegue ler os FDs; em vez disso, faz chamadas para uma interface do Binder (fornecida pelo mediaserver for cada sessão de reprodução) para acessar arquivos.

Um aplicativo (ou mediaserver ) faz uma chamada para o processo extrator para obter um IMediaExtractor , chama esse IMediaExtractor para obter IMediaSources para a faixa contida no arquivo e chama o IMediaSources para ler dados deles.

Para transferir os dados entre processos, o aplicativo (ou mediaserver ) inclui os dados na resposta-Parcel como parte da transação do Binder ou usa memória compartilhada:

  • O uso de memória compartilhada requer uma chamada adicional do Binder para liberar a memória compartilhada, mas é mais rápido e usa menos energia para buffers grandes.
  • O uso do In-Parcel requer cópia extra, mas é mais rápido e consome menos energia de buffers menores que 64 KB.

Implementação

Para apoiar o movimento de MediaDrm e MediaCrypto componentes para o novo mediadrmserver processo, os fornecedores devem mudar o método de alocação de buffers seguras para permitir buffers para ser compartilhado entre processos.

Nas versões anteriores do Android, os buffers seguros são alocados no mediaserver pelo OMX::allocateBuffer mediaserver e usados ​​durante a descriptografia no mesmo processo, como mostrado abaixo:

Figura 2. Android 6.0 e alocação de buffer mais baixa no mediaserver.

No Android 7.0, o processo de alocação de buffer mudou para um novo mecanismo que fornece flexibilidade e minimiza o impacto nas implementações existentes. Com MediaDrm e MediaCrypto pilhas no novo mediadrmserver processo, buffers são alocados de forma diferente e os fornecedores devem atualizar as alças tampão seguras para que possam ser transportados através aglutinante quando MediaCodec invoca uma operação de descriptografar em MediaCrypto .

Figura 3. Android 7.0 e alocação de buffer superior no mediaserver.

Usando identificadores nativos

O OMX::allocateBuffer native_handle deve retornar um ponteiro para uma estrutura native_handle , que contém FDs (descritores de arquivo) e dados inteiros adicionais. Um native_handle tem todas as vantagens de usar FDs, incluindo suporte de fichário existente para serialização / desserialização, além de permitir mais flexibilidade para fornecedores que atualmente não usam FDs.

Use native_handle_create() para alocar o identificador nativo. O código da estrutura assume a propriedade da estrutura native_handle alocada e é responsável por liberar recursos no processo em que o native_handle é originalmente alocado e no processo em que é desserializado. A estrutura libera identificadores nativos com native_handle_close() seguido por native_handle_delete() e serializa / desserializa o native_handle usando Parcel::writeNativeHandle()/readNativeHandle() .

Os fornecedores de SoC que usam FDs para representar buffers seguros podem preencher o FD no native_handle com seu FD. Os fornecedores que não usam FDs podem representar buffers seguros usando campos adicionais no native_buffer .

Definindo o local de descriptografia

Os fornecedores devem atualizar o método de descriptografia OEMCrypto que opera no native_handle para executar quaisquer operações específicas do fornecedor necessárias para tornar o native_handle utilizável no novo espaço do processo (as alterações geralmente incluem atualizações nas bibliotecas OEMCrypto).

Como allocateBuffer é uma operação OMX padrão, o Android 7.0 inclui uma nova extensão OMX ( OMX.google.android.index.allocateNativeHandle ) para consultar esse suporte e uma chamada OMX_SetParameter que notifica a implementação OMX que deve usar identificadores nativos.