Укрепление медиа-структуры

Чтобы повысить безопасность устройства, Android 7.0 разбивает монолитный процесс mediaserver на несколько процессов, при этом разрешения и возможности ограничены только теми, которые необходимы каждому процессу. Эти изменения устраняют уязвимости безопасности медиа-инфраструктуры за счет:

  • Разделение компонентов AV-конвейера на изолированные процессы для конкретных приложений.
  • Включение обновляемых медиа-компонентов (экстракторов, кодеков и т.п.).

Эти изменения также повышают безопасность конечных пользователей за счет значительного снижения серьезности большинства уязвимостей безопасности, связанных с мультимедиа, обеспечивая безопасность устройств и данных конечных пользователей.

OEM-производителям и поставщикам SoC необходимо обновить свои HAL и изменения в структуре, чтобы сделать их совместимыми с новой архитектурой. В частности, поскольку код Android, предоставленный поставщиком, часто предполагает, что все выполняется в одном и том же процессе, поставщики должны обновлять свой код, чтобы передавать собственные дескрипторы ( native_handle ), которые имеют значение между процессами. Справочную реализацию изменений, связанных с усилением защиты мультимедиа, см. в frameworks/av и frameworks/native .

Архитектурные изменения

Предыдущие версии Android использовали единый монолитный процесс mediaserver с большим количеством разрешений (доступ к камере, доступ к аудио, доступ к видеодрайверу, доступ к файлам, доступ к сети и т. д.). В Android 7.0 процесс mediaserver разделен на несколько новых процессов, каждый из которых требует гораздо меньшего набора разрешений:

усиление защиты медиасервера

Рисунок 1. Изменения архитектуры для усиления защиты медиасервера

Эта новая архитектура гарантирует, что даже в случае взлома процесса вредоносный код не получит доступа ко всему набору разрешений, ранее принадлежавших mediaserver . Процессы ограничены политиками SElinux и seccomp.

Примечание. Из-за зависимости от поставщика некоторые кодеки по-прежнему работают на mediaserver и, следовательно, предоставляют mediaserver больше разрешений, чем необходимо. В частности, Widevine Classic продолжает работать на mediaserver для Android 7.0.

Изменения медиасервера

В Android 7.0 существует процесс mediaserver для управления воспроизведением и записью, например, для передачи и синхронизации буферов между компонентами и процессами. Процессы взаимодействуют через стандартный механизм Binder.

В стандартном сеансе воспроизведения локального файла приложение передает дескриптор файла (FD) mediaserver (обычно через Java API MediaPlayer), а mediaserver :

  1. Обертывает FD в объект Binder DataSource, который передается процессу извлечения, который использует его для чтения из файла с помощью Binder IPC. (Медиаэкстрактор не получает FD, а вместо этого отправляет Binder обратный вызов mediaserver для получения данных.)
  2. Проверяет файл, создает соответствующий экстрактор для данного типа файла (например, MP3Extractor или MPEG4Extractor) и возвращает интерфейс Binder для экстрактора процессу mediaserver .
  3. Выполняет вызовы Binder IPC к экстрактору для определения типа данных в файле (например, данные MP3 или H.264).
  4. Вызывает процесс mediacodec для создания кодеков требуемого типа; получает интерфейсы Binder для этих кодеков.
  5. Выполняет повторные вызовы Binder IPC к экстрактору для чтения закодированных выборок, использует Binder IPC для отправки закодированных данных в процесс mediacodec для декодирования и получает декодированные данные.

В некоторых случаях использования кодек не используется (например, при воспроизведении с разгрузкой, при котором закодированные данные отправляются непосредственно на устройство вывода), или кодек может визуализировать декодированные данные напрямую вместо возврата буфера декодированных данных (воспроизведение видео).

Изменения в Медиакодексервице

Служба кодеков — это место, где живут кодеры и декодеры. Из-за зависимостей от поставщиков не все кодеки пока включены в процесс кодирования. В Android 7.0:

  • Незащищенные декодеры и программные кодеры встроены в процесс кодирования.
  • Безопасные декодеры и аппаратные кодировщики находятся на mediaserver (без изменений).

Приложение (или mediaserver ) вызывает процесс кодека для создания кодека требуемого типа, затем вызывает этот кодек для передачи закодированных данных и получения декодированных данных (для декодирования) или для передачи декодированных данных и получения закодированных данных (для кодирования). . Передача данных к кодекам и обратно уже использует общую память, поэтому процесс не меняется.

Изменения МедиаДрмсервера

Сервер DRM используется при воспроизведении контента, защищенного DRM, например фильмов в Google Play Movies. Он безопасно расшифровывает зашифрованные данные и поэтому имеет доступ к хранилищу сертификатов и ключей, а также к другим конфиденциальным компонентам. Из-за зависимости от поставщиков процесс DRM пока используется не во всех случаях.

Изменения Аудиосервера

В процессе AudioServer размещаются компоненты, связанные со звуком, такие как аудиовход и выход, служба диспетчера политик, определяющая маршрутизацию звука, и служба FM-радио. Подробные сведения об изменениях звука и руководствах по реализации см. в разделе «Реализация звука» .

Изменения в CameraServer

CameraServer управляет камерой и используется при записи видео для получения видеокадров с камеры и последующей передачи их на mediaserver для дальнейшей обработки. Подробные сведения об изменениях и рекомендации по реализации изменений CameraServer см. в разделе Усиление защиты платформы камеры .

Изменения в ExtractorService

В службе экстрактора размещаются экстракторы — компоненты, которые анализируют различные форматы файлов, поддерживаемые медиа-инфраструктурой. Служба извлечения является наименее привилегированной из всех служб: она не может читать FD, поэтому вместо этого она обращается к интерфейсу Binder (предоставляемому ей mediaserver for каждого сеанса воспроизведения) для доступа к файлам.

Приложение (или mediaserver ) вызывает процесс извлечения для получения IMediaExtractor , вызывает этот IMediaExtractor для получения IMediaSources для дорожки, содержащейся в файле, а затем вызывает IMediaSources для чтения данных из них.

Для передачи данных между процессами приложение (или mediaserver ) включает данные в ответную посылку как часть транзакции Binder или использует общую память:

  • Использование общей памяти требует дополнительного вызова Binder для освобождения общей памяти, но это быстрее и требует меньше энергии для больших буферов.
  • Использование In-Parcel требует дополнительного копирования, но выполняется быстрее и потребляет меньше энергии для буферов размером менее 64 КБ.

Выполнение

Чтобы поддержать перемещение компонентов MediaDrm и MediaCrypto в новый процесс mediadrmserver , поставщики должны изменить метод выделения безопасных буферов, чтобы разрешить совместное использование буферов между процессами.

В предыдущих выпусках Android безопасные буферы выделялись на mediaserver с помощью OMX::allocateBuffer и использовались во время расшифровки в том же процессе, как показано ниже:

Рисунок 2. Android 6.0 и более ранние версии выделения буфера на медиасервере.

В Android 7.0 процесс выделения буфера изменился на новый механизм, обеспечивающий гибкость и минимизирующий влияние на существующие реализации. Благодаря стекам MediaDrm и MediaCrypto в новом процессе mediadrmserver буферы распределяются по-разному, и поставщики должны обновлять дескрипторы безопасных буферов, чтобы их можно было транспортировать через связующее, когда MediaCodec вызывает операцию дешифрования в MediaCrypto .

Рисунок 3. Распределение буфера в Android 7.0 и более поздних версиях на медиасервере.

Используйте собственные дескрипторы

OMX::allocateBuffer должен возвращать указатель на структуру native_handle , которая содержит файловые дескрипторы (FD) и дополнительные целочисленные данные. native_handle обладает всеми преимуществами использования FD, включая существующую поддержку привязки для сериализации/десериализации, а также обеспечивает большую гибкость для поставщиков, которые в настоящее время не используют FD.

Используйте native_handle_create() , чтобы выделить собственный дескриптор. Код платформы берет на себя ответственность за выделенную структуру native_handle и отвечает за освобождение ресурсов как в процессе, в котором изначально выделяется native_handle , так и в процессе его десериализации. Платформа выпускает собственные дескрипторы с помощью native_handle_close() , за которым следует метод native_handle_delete() , и сериализует/десериализует native_handle с помощью Parcel::writeNativeHandle()/readNativeHandle() .

Поставщики SoC, которые используют FD для представления безопасных буферов, могут заполнить FD в native_handle своим FD. Поставщики, которые не используют FD, могут представлять безопасные буферы, используя дополнительные поля в native_buffer .

Установить местоположение расшифровки

Поставщики должны обновить метод дешифрования OEMCrypto, который работает с native_handle , чтобы выполнять любые специфичные для поставщика операции, необходимые для того, чтобы native_handle можно было использовать в новом пространстве процессов (изменения обычно включают обновления библиотек OEMCrypto).

Поскольку allocateBuffer является стандартной операцией OMX, Android 7.0 включает новое расширение OMX ( OMX.google.android.index.allocateNativeHandle ) для запроса этой поддержки и вызов OMX_SetParameter , который уведомляет реализацию OMX о необходимости использования собственных дескрипторов.