Совместимость политики

На этой странице описывается, как Android обрабатывает проблемы совместимости политик при беспроводных обновлениях платформы (OTA), когда новые настройки SELinux платформы могут отличаться от старых настроек SELinux от производителя.

Право собственности на объекты и их маркировка

Для обеспечения разделения политик платформы и поставщика необходимо четко определить права собственности на каждый объект. Например, если политика поставщика присваивает метку /dev/foo , а политика платформы — метку /dev/foo в последующем обновлении OTA, это может привести к неопределенному поведению, например, к неожиданному отказу или, что более важно, к сбою загрузки. Для SELinux это проявляется как конфликт меток. Узел устройства может иметь только одну метку, которая разрешается в ту метку, которая была применена последней. В результате:

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

Конфликты между метками платформы и поставщика могут возникать для любого объекта, имеющего метку SELinux, включая свойства, службы, процессы, файлы и сокеты. Чтобы избежать этих проблем, четко определите права собственности на эти объекты.

Пространства имен типов/атрибутов

Помимо конфликтов меток, могут возникать конфликты и имен типов и атрибутов SELinux. SELinux не допускает множественных объявлений одних и тех же типов и атрибутов. Политика с повторяющимися объявлениями не скомпилируется. Чтобы избежать конфликтов имен типов и атрибутов, настоятельно рекомендуется начинать все объявления поставщиков с префикса vendor_ . Например, поставщикам следует использовать type vendor_foo, domain; вместо type foo, domain; .

Право собственности на файл

Предотвращение конфликтов имен файлов представляет собой сложную задачу, поскольку политика платформы и поставщика обычно предоставляет метки для всех файловых систем. В отличие от именования типов, именование файлов в пространства имен непрактично, поскольку многие из них создаются ядром. Чтобы предотвратить эти конфликты, следуйте рекомендациям по именованию файловых систем, приведенным в этом разделе. Для Android 8.0 это рекомендации без технического контроля. В будущем эти рекомендации будут контролироваться с помощью набора тестов поставщика (VTS).

Система (/система)

Только образ системы должен содержать метки для компонентов /system через file_contexts , service_contexts и т. д. Если метки для компонентов /system добавлены в политику поставщика, обновление по воздуху только для фреймворка может быть невозможно.

Поставщик (/vendor)

Политика AOSP SELinux уже помечает части раздела vendor , с которым взаимодействует платформа, что позволяет писать правила SELinux для процессов платформы, чтобы они могли взаимодействовать или получать доступ к частям раздела vendor . Примеры:

/путь поставщика Предоставленная платформой метка Процессы платформы зависят от метки.
/vendor(/. * )? vendor_file Все клиенты HAL в рамках фреймворка, ueventd и т. д.
/vendor/framework(/. * )? vendor_framework_file dex2oat , appdomain и т. д.
/vendor/app(/. * )? vendor_app_file dex2oat , installd , idmap и т. д.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap и т. д.

В результате, при присвоении меток дополнительным файлам в разделе vendor необходимо соблюдать определенные правила (обеспечиваемые с помощью параметра neverallows ):

  • vendor_file должен быть меткой по умолчанию для всех файлов в разделе vendor . Политика платформы требует этого для доступа к реализациям HAL, обеспечивающим сквозную передачу данных.
  • Все новые exec_types добавленные в раздел vendor через политику поставщика, должны иметь атрибут vendor_file_type . Это обеспечивается параметром neverallows.
  • Во избежание конфликтов с будущими обновлениями платформы/фреймворка, не следует присваивать файлам в разделе vendor метки, отличные от exec_types .
  • Все библиотечные зависимости для HAL, идентифицированных в соответствии с AOSP и работающих в одном процессе, должны быть помечены как same_process_hal_file.

Procfs (/proc)

Файлы в /proc могут быть помечены только с помощью метки genfscon . В Android 7.0 как политика платформы , так и политика поставщика использовали genfscon для маркировки файлов в procfs .

Рекомендация: Только политика платформы должна помечать /proc . Если процессам поставщика требуется доступ к файлам в /proc , которые в настоящее время помечены меткой по умолчанию ( proc ), политика поставщика не должна явно указывать на них метку, а вместо этого должна использовать общий тип proc для добавления правил для доменов поставщика. Это позволит обновлениям платформы учитывать будущие интерфейсы ядра, предоставляемые через procfs , и явно помечать их по мере необходимости.

Debugfs (/sys/kernel/debug)

Debugfs могут быть помечены как в file_contexts , так и genfscon . В Android 7.0–10 метки debugfs используются как платформой, так и производителем.

В Android 11 на серийных устройствах доступ к debugfs и его монтирование невозможны. Производителям устройств следует удалить debugfs .

Tracefs (/sys/kernel/debug/tracing)

Tracefs могут быть указаны как в file_contexts , так и genfscon . В Android 7.0 метки tracefs указывает только платформа.

Рекомендация: Только платформа может помечать tracefs .

Sysfs (/sys)

Файлы в каталоге /sys могут быть помечены с помощью file_contexts и genfscon . В Android 7.0 и платформа, и производитель используют genfscon для маркировки файлов в sysfs .

Рекомендация: Платформа может присваивать метки узлам sysfs , не привязанным к конкретному устройству. В противном случае, метки файлам может присваивать только производитель.

tmpfs (/dev)

Файлы в каталоге /dev могут быть помечены в переменной file_contexts . В Android 7.0 как платформа, так и производитель помечают файлы здесь.

Рекомендация: Производитель может присваивать метки только файлам в каталоге /dev/vendor (например, /dev/vendor/foo , /dev/vendor/socket/bar ).

Корневая файловая система (/)

Файлы в корневом каталоге / могут быть помечены в переменной file_contexts . В Android 7.0 здесь указываются метки файлов как платформой, так и производителем.

Рекомендация: Только система может присваивать метки файлам в корневом каталоге / .

Данные (/data)

Данные маркируются с помощью комбинации file_contexts и seapp_contexts .

Рекомендация: Запретить добавление меток поставщиков за пределами /data/vendor . Только платформа может добавлять метки в другие части /data .

Версия этикеток Genfs

Начиная с API поставщика уровня 202504, новые метки SELinux, назначенные с помощью genfscon в system/sepolicy/compat/plat_sepolicy_genfs_ ver .cil являются необязательными для разделов старых vendor . Это позволяет разделам старых vendor сохранять существующую реализацию SEPolicy. Это контролируется переменной Makefile BOARD_GENFS_LABELS_VERSION , которая хранится в /vendor/etc/selinux/genfs_labels_version.txt .

Пример:

  • В API поставщика уровня 202404 узел /sys/class/udc по умолчанию помечается как sysfs .
  • Начиная с уровня API поставщика 202504, /sys/class/udc помечен как sysfs_udc .

Однако /sys/class/udc может использоваться разделами vendor , работающими с уровнем API 202404, либо с меткой sysfs по умолчанию, либо с меткой, специфичной для производителя. Безусловное присвоение /sys/class/udc метки sysfs_udc может нарушить совместимость с этими разделами vendor . Проверка параметра BOARD_GENFS_LABELS_VERSION позволяет платформе продолжать использовать предыдущие метки и разрешения для более старых разделов vendor .

BOARD_GENFS_LABELS_VERSION может быть больше или равно уровню API поставщика. Например, для разделов vendor , использующих уровень API 202404, можно установить BOARD_GENFS_LABELS_VERSION равным 202504, чтобы использовать новые метки, введенные в версии 202504. См. список меток genfs, специфичных для версии 202504 .

При присвоении меток узлам genfscon платформа должна учитывать разделы более старых vendor и реализовывать механизмы резервного копирования для обеспечения совместимости при необходимости. Платформа может использовать библиотеки, доступные только на платформе, для запроса версии меток genfs.

Политика публичной платформы

Политика SELinux для платформы делится на частную и публичную. Политика platform-public состоит из типов и атрибутов, которые всегда доступны на уровне API поставщика , выступая в качестве API между платформой и поставщиком. Эта политика предоставляется разработчикам политик поставщиков, чтобы позволить поставщикам создавать файлы политик, которые в сочетании с политикой platform-private приводят к созданию полностью функциональной политики для устройства. Политика platform-public определяется в system/sepolicy/public .

Например, тип vendor_init , представляющий процесс инициализации в контексте поставщика, определен в файле system/sepolicy/public/vendor_init.te :

type vendor_init, domain;

Поставщики могут использовать тип vendor_init для написания пользовательских правил политики:

# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)

Атрибуты совместимости

Политика SELinux — это взаимодействие между типами источника и цели для определенных классов объектов и разрешений. Каждый объект (например, процессы, файлы), на который распространяется политика SELinux, может иметь только один тип, но этот тип может иметь несколько атрибутов.

Политика написана преимущественно на основе существующих типов. В данном случае vendor_init и debugfs являются типами:

allow vendor_init debugfs:dir { mounton };

Это работает, потому что политика была написана с учетом всех типов. Однако, если политика поставщика и политика платформы используют определенные типы, и метка конкретного объекта изменяется только в одной из этих политик, другая может содержать политику, которая получила или потеряла доступ, на который ранее полагались. Например, предположим, что политика платформы помечает узлы sysfs как sysfs :

/sys(/.*)? u:object_r:sysfs:s0

Политика поставщика предоставляет доступ к /sys/usb , помеченному как sysfs :

allow vendor_init sysfs:chr_file rw_file_perms;

Если политика платформы будет изменена таким образом, чтобы /sys/usb помечался как sysfs_usb , политика поставщика останется прежней, но vendor_init потеряет доступ к /sys/usb из-за отсутствия политики для нового типа sysfs_usb :

/sys/usb u:object_r:sysfs_usb:s0

Для решения этой проблемы Android вводит концепцию версионированных атрибутов. Во время компиляции система сборки автоматически преобразует общедоступные типы платформы, используемые в политике поставщика, в эти версионированные атрибуты. Это преобразование обеспечивается путем сопоставления файлов, которые связывают версионированный атрибут с одним или несколькими общедоступными типами платформы.

Например, предположим, что /sys/usb помечен как sysfs в политике платформы 202504, а политика поставщика 202504 предоставляет vendor_init доступ к /sys/usb . В этом случае:

  • Политика поставщика создает правило allow vendor_init sysfs:chr_file rw_file_perms; , поскольку /sys/usb помечен как sysfs в политике платформы 202504. Когда система сборки компилирует политику поставщика, она автоматически преобразует правило в allow vendor_init _202504 sysfs _202504 :chr_file rw_file_perms; . Атрибуты vendor_init_202504 и sysfs_202504 соответствуют типам vendor_init и sysfs , которые определены платформой.
  • Система сборки генерирует файл сопоставления идентификаторов /system/etc/selinux/mapping/202504.cil . Поскольку system и vendor разделы используют одну и ту же версию 202504 , файл сопоставления содержит сопоставления идентификаторов от type_202504 к type . Например, vendor_init_202504 сопоставляется с vendor_init , а sysfs_202504 — с sysfs :
    (typeattributeset sysfs_202504 (sysfs))
    (typeattributeset vendor_init_202504 (vendor_init))
    ...

При повышении версии с 202504 до 202604 создается новый файл сопоставления для разделов vendor версии 202504 в каталоге system/sepolicy/private/compat/202504/202504.cil , который устанавливается в /system/etc/selinux/mapping/202504.cil для system разделов версии 202604 или более новых. Первоначально этот файл сопоставления содержит сопоставления идентификаторов, как описано ранее. Если в политику платформы 202604 добавляется новая метка sysfs_usb для /sys/usb , файл сопоставления обновляется, чтобы сопоставить sysfs_202504 с sysfs_usb :

(typeattributeset sysfs_202504 (sysfs sysfs_usb))
(typeattributeset vendor_init_202504 (vendor_init))
...

Это обновление позволяет преобразованному правилу политики поставщика allow vendor_init_202504 sysfs_202504:chr_file rw_file_perms; автоматически предоставлять vendor_init доступ к новому типу sysfs_usb .

Для обеспечения совместимости со старыми разделами vendor , при добавлении нового общедоступного типа этот тип должен быть сопоставлен как минимум с одним из версионированных атрибутов в файле сопоставления system/sepolicy/private/compat/ ver / ver .cil или указан в system/sepolicy/private/compat/ ver / ver .ignore.cil , чтобы указать, что в предыдущих версиях поставщика нет соответствующего типа.

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

политика общедоступных ресурсов системы_ext и политика общедоступных продуктов

Начиная с Android 11, разделы system_ext и product могут экспортировать свои назначенные общедоступные типы в раздел vendor . Подобно политике общедоступных типов платформы, политика vendor использует типы и правила, автоматически преобразуемые в версионированные атрибуты, например, из type в type_ ver , где ver — это уровень API раздела vendor .

Когда разделы system_ext и product основаны на одной и той же версии платформы ver , система сборки генерирует файлы сопоставления базовых значений для system_ext/etc/selinux/mapping/ ver .cil и product/etc/selinux/mapping/ ver .cil , которые содержат сопоставления идентификаторов от type к type_ ver . Политика поставщика может получить доступ type с помощью атрибута версии type_ ver .

В случае, если обновляются только разделы system_ext и product , например, ver до ver+1 (или более поздней версии), а раздел vendor остается в версии ver , политика поставщика может потерять доступ к типам разделов system_ext и product . Для предотвращения сбоев разделы system_ext и product должны предоставлять файлы сопоставления конкретных типов с атрибутами type_ ver . Каждый партнер несет ответственность за поддержание файлов сопоставления, если он поддерживает раздел vendor ver с разделами system_ext и product версии ver+1 (или более поздней).

Для установки файлов сопоставления в разделы system_ext и разделы product от разработчиков устройств или поставщиков ожидается следующее:

  1. Скопируйте сгенерированные файлы сопоставления базовых файлов из разделов ver system_ext и product в их исходное дерево .
  2. При необходимости внесите изменения в файлы сопоставления.
  3. Установите файлы сопоставления в разделы system_ext и product ver+1 (или более поздней).

Например, предположим, что в разделе system_ext 202504 есть один публичный тип с именем foo_type . Тогда system_ext/etc/selinux/mapping/202504.cil в разделе system_ext 202504 выглядит следующим образом:

(typeattributeset foo_type_202504 (foo_type))
(expandtypeattribute foo_type_202504 true)
(typeattribute foo_type_202504)

Если параметр bar_type добавлен к system_ext 202604, и если bar_type должен быть сопоставлен с foo_type для раздела vendor 202504, то 202504.cil можно обновить с (typeattributeset foo_type_202504 (foo_type)) на (typeattributeset foo_type_202504 (foo_type bar_type)) , а затем установить в раздел system_ext 202604. Раздел vendor 202504 сможет продолжать обращаться к foo_type и bar_type из system_ext 202604.

Изменения атрибутов для Android 9

Устройства, обновляющиеся до Android 9, могут использовать следующие атрибуты, но устройства, изначально работающие под управлением Android 9, этого использовать не должны.

Атрибуты нарушителя

В Android 9 включены следующие атрибуты, относящиеся к предметной области:

  • data_between_core_and_vendor_violators . Атрибут для всех доменов, нарушающих требование не обмениваться файлами по пути между доменами vendor и coredomains . Процессы платформы и поставщика не должны использовать файлы на диске для связи (нестабильный ABI). Рекомендация:
    • В коде поставщика следует использовать /data/vendor .
    • Система не должна использовать /data/vendor .
  • system_executes_vendor_violators . Атрибут для всех системных доменов (кроме shell domains init и оболочки), которые нарушают требование не выполнять бинарные файлы сторонних поставщиков. Выполнение бинарных файлов сторонних поставщиков имеет нестабильный API. Платформа не должна выполнять бинарные файлы сторонних поставщиков напрямую. Рекомендация:
    • Подобные зависимости платформы от исполняемых файлов поставщиков должны быть скрыты за HAL-интерфейсами HIDL.

      ИЛИ

    • coredomains , которым необходим доступ к исполняемым файлам сторонних поставщиков, следует переместить в раздел, vendor , и таким образом перестать быть coredomain .

Ненадежные атрибуты

Ненадежные приложения, содержащие произвольный код, не должны иметь доступа к службам HwBinder, за исключением тех, которые считаются достаточно безопасными для доступа из таких приложений (см. безопасные службы ниже). Две основные причины этого:

  1. Серверы HwBinder не выполняют аутентификацию клиентов, поскольку HIDL в настоящее время не раскрывает информацию об UID вызывающего абонента. Даже если бы HIDL раскрывал такие данные, многие службы HwBinder либо работают на уровне ниже приложений (например, HAL), либо не должны полагаться на идентификацию приложения для авторизации. Таким образом, для обеспечения безопасности по умолчанию предполагается, что каждая служба HwBinder рассматривает всех своих клиентов как одинаково авторизованных для выполнения операций, предлагаемых службой.
  2. Серверы HAL (подмножество сервисов HwBinder) содержат код с более высокой частотой возникновения проблем безопасности, чем system/core компоненты, и имеют доступ к нижним уровням стека (вплоть до оборудования), что увеличивает возможности для обхода модели безопасности Android.

Безопасные услуги

К услугам обеспечения безопасности относятся:

  • same_process_hwservice . Эти службы (по определению) выполняются в процессе клиента и, следовательно, имеют тот же доступ, что и домен клиента, в котором выполняется процесс.
  • coredomain_hwservice . Эти сервисы не представляют рисков, связанных с причиной №2.
  • hal_configstore_ISurfaceFlingerConfigs . Этот сервис специально разработан для использования любым доменом.
  • hal_graphics_allocator_hwservice . Эти операции также предоставляются службой surfaceflinger Binder, к которой приложениям разрешен доступ.
  • hal_omx_hwservice . Это версия службы mediacodec Binder, использующая протокол HwBinder, к которой приложениям разрешен доступ.
  • hal_codec2_hwservice . Это более новая версия hal_omx_hwservice .

Полезные атрибуты

Все hwservices не считающиеся безопасными, имеют атрибут untrusted_app_visible_hwservice . Соответствующие HAL-серверы имеют атрибут untrusted_app_visible_halserver . Устройства, запускаемые с Android 9, НЕ ДОЛЖНЫ использовать ни один из атрибутов untrusted .

Рекомендация:

  • Вместо этого ненадежные приложения должны взаимодействовать с системной службой, которая, в свою очередь, взаимодействует с HAL HIDL от поставщика. Например, приложения могут взаимодействовать с binderservicedomain , а затем mediaserver (который является binderservicedomain ) взаимодействует с hal_graphics_allocator .

    ИЛИ

  • Приложениям, которым необходим прямой доступ к HAL-интерфейсам vendor , следует иметь собственный домен политики безопасности, определяемый поставщиком.

Тесты атрибутов файлов

В Android 9 включены тесты, выполняемые на этапе сборки , которые гарантируют, что все файлы в определенных местах имеют соответствующие атрибуты (например, все файлы в sysfs имеют необходимый атрибут sysfs_type ).

маркировка контекстов SELinux

Для обеспечения разграничения между политикой безопасности платформы и политикой безопасности поставщика система формирует контекстные файлы SELinux по-разному, чтобы обеспечить их разделение.

Контексты файлов

В Android 8.0 были внесены следующие изменения в функцию file_contexts :

  • Чтобы избежать дополнительных затрат на компиляцию на устройстве во время загрузки, file_contexts перестают существовать в двоичном виде. Вместо этого они представляют собой читаемые текстовые файлы с регулярными выражениями, например {property, service}_contexts (как это было до версии 7.0).
  • Содержимое file_contexts разделено между двумя файлами:
    • plat_file_contexts
      • В file_context платформы Android отсутствуют метки, специфичные для устройства, за исключением меток частей раздела /vendor , которые должны быть точно помечены для обеспечения корректной работы файлов sepolicy.
      • Должен находиться в system разделе по адресу /system/etc/selinux/plat_file_contexts на устройстве и загружаться init при запуске вместе с file_context поставщика.
    • vendor_file_contexts
      • file_context специфичный для устройства, формируется путем объединения file_contexts найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
      • Необходимо установить в /vendor/etc/selinux/vendor_file_contexts в разделе vendor и загрузить init вместе с платформенным file_context .

Контексты недвижимости

В Android 8.0 свойство property_contexts разделено на два файла:

  • plat_property_contexts
    • property_context платформы Android, не имеющий меток, специфичных для устройства.
    • Должен находиться в system разделе по адресу /system/etc/selinux/plat_property_contexts и загружаться init при запуске вместе с файлом property_contexts .
  • vendor_property_contexts
    • property_context , специфичные для устройства, формируются путем объединения property_contexts найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
    • Должен находиться в разделе vendor по адресу /vendor/etc/selinux/vendor_property_contexts и загружаться процессом init при запуске вместе с платформенным property_context

Контексты обслуживания

В Android 8.0 файл service_contexts разделен между следующими файлами:

  • plat_service_contexts
    • Специфичный для платформы Android service_context для servicemanager . service_context не содержит меток, специфичных для устройства.
    • Должен находиться в system разделе по адресу /system/etc/selinux/plat_service_contexts и загружаться servicemanager при запуске вместе с service_contexts от поставщика.
  • vendor_service_contexts
    • service_context специфичный для устройства, формируется путем объединения service_contexts найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
    • Должен находиться в разделе vendor по адресу /vendor/etc/selinux/vendor_service_contexts и загружаться servicemanager при запуске вместе с платформенными service_contexts .
    • Хотя servicemanager ищет этот файл при загрузке, для полностью совместимого устройства TREBLE файл vendor_service_contexts НЕ ДОЛЖЕН существовать. Это связано с тем, что все взаимодействие между процессами vendor и system ДОЛЖНО проходить через hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • В hwservice_context платформы Android для hwservicemanager отсутствуют метки, специфичные для устройства.
    • Должен находиться в system разделе по адресу /system/etc/selinux/plat_hwservice_contexts и загружаться hwservicemanager при запуске вместе с vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • Контекст аппаратного hwservice_context специфичный для устройства, формируется путем объединения hwservice_contexts найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
    • Должен находиться в разделе vendor по адресу /vendor/etc/selinux/vendor_hwservice_contexts и загружаться hwservicemanager при запуске вместе с plat_service_contexts .
  • vndservice_contexts
    • service_context специфичный для устройства, для vndservicemanager создается путем объединения vndservice_contexts , найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в Boardconfig.mk устройства.
    • Этот файл должен находиться в разделе vendor по адресу /vendor/etc/selinux/vndservice_contexts и загружаться vndservicemanager при запуске.

Контексты Seapp

В Android 8.0 файл seapp_contexts разделен на два файла:

  • plat_seapp_contexts
    • seapp_context для платформы Android, не содержащий изменений, специфичных для конкретного устройства.
    • Должен находиться в system разделе по адресу /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Расширение для платформы seapp_context , специфичное для данного устройства, создается путем объединения seapp_contexts , найденных в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
    • Должен находиться в разделе vendor по адресу /vendor/etc/selinux/vendor_seapp_contexts .

Разрешения MAC

В Android 8.0 файл mac_permissions.xml разделен на два файла:

  • Platform mac_permissions.xml
    • Файл mac_permissions.xml платформы Android, не содержащий изменений, специфичных для конкретного устройства.
    • Должен находиться в system разделе по адресу /system/etc/selinux/.
  • Non-Platform mac_permissions.xml
    • Расширение, специфичное для устройства, для файла mac_permissions.xml платформы, созданное на основе файла mac_permissions.xml , расположенного в каталогах, на которые указывает параметр BOARD_SEPOLICY_DIRS в файлах Boardconfig.mk устройства.
    • Должен находиться в разделе vendor по адресу /vendor/etc/selinux/.

Изменения в общей памяти для Android 17

Начиная с Android 17, устройства, запускаемые со следующими свойствами, должны включить возможность политики memfd_class и обновить свою политику, связанную с разделяемой памятью, для поддержки объектов класса memfd_file :

  • Уровень API поставщика 202604 или выше предоставляет поставщикам и OEM-производителям возможность обновить свою политику поставщика для поддержки memfd . Это также позволяет существующим устройствам обновляться до более высоких версий Android без необходимости обновления раздела поставщика.
  • Ядро android16-6.12 или более поздней версии, поскольку эти ядра поддерживают функцию memfd_class , необходимую для реализации детальной политики для memfd .

Включите возможность политики memfd_class.

До недавнего времени SELinux помечал memfd как файл того же типа, что и базовая файловая система — tmpfs. Это делало невозможным различение memfd от другого файла на монтированной файловой системе tmpfs с точки зрения политик. Теперь SELinux помечает memfd контекстом безопасности выделяющего процесса, и memfds рассматриваются как объекты класса memfd_file . Эта функциональность защищена возможностью политики memfd_class , что обеспечивает обратную совместимость со старыми средами пользовательского пространства.

Для включения возможности политики memfd_class создайте файл policy_capabilities в каталоге BOARD_VENDOR_SEPOLICY_DIRS . Файл должен содержать следующую запись:

# $BOARD_VENDOR_SEPOLICY_DIRS/*/policy_capabilities
policycap memfd_class;

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

Убедитесь, что функция политики memfd_class включена.

Для проверки состояния параметра политики memfd_class используйте следующую команду:

adb shell 'cat /sys/fs/selinux/policy_capabilities/memfd_class'

Если результат равен 1 , то возможность политики memfd_class включена. В противном случае она не включена.

Перевести существующую политику на memfd

Некоторые процессы использовали макрос tmpfs_domain() в своей политике для доступа к своим memfds и создания пространств имен, например:

# foo.te
tmpfs_domain(foo)

Это переводится как:

# foo.te
type_transition foo tmpfs:file foo_tmpfs;
allow foo foo_tmpfs:file { read write getattr map };

и давайте обработаем процесс bar и получим доступ к memfds процесса foo следующим образом:

# bar.te
allow bar foo_tmpfs:file { read write getattr map };

При включении возможности политики memfd_class макрос tmpfs_domain() больше не требуется, поскольку политика платформы была обновлена ​​и позволяет любому процессу создавать и использовать собственные memfds , как показано здесь:

# system/sepolicy/private/domain.te
allow domain self:memfd_file { create read write getattr map };

А memfds созданные процессом foo могут быть доступны из bar процессов следующим образом:

# bar.te
allow bar foo:memfd_file { read write getattr map };

Политика платформы была обновлена ​​с учетом существующего использования memfd . Однако политика, специфичная для производителя и устройства и использующая метки tmpfs , должна быть обновлена ​​для использования memfd_file . Если политика используется совместно SoC или устройствами, не имеющими API уровня 202604 или выше, рекомендуется сохранить устаревшую политику tmpfs вместе с новой политикой memfd_file для обеспечения совместимости.

Выявление отказов AVC, связанных с memfd.

Сообщения об отказах, связанных с Memfd можно получить с помощью следующей команды:

adb shell logcat -d -b events | grep memfd

AVC-отказы с использованием tmpfs в качестве цели

Следующий пример демонстрирует отказ avc , с которым столкнулся процесс, пытавшийся записать данные в memfd , на запись в который у него не было разрешения:

audit(0.0:539): avc:  denied  { write } for  comm="binder:665_1" name="memfd:MessageQueue"
dev="tmpfs" ino=8324 scontext=u:r:mediacodec:s0 tcontext=u:object_r:tmpfs:s0 tclass=file
permissive=0

Когда включена возможность применения политики memfd_class , целевым контекстом memfd является контекст безопасности выделяющего процесса, а не tmpfs , и целевым классом является memfd_file , а не file . Поэтому, если вы наблюдаете отказы avc связанные с memfd , где рассматриваемый memfd помечен как файл tmpfs , возможность применения политики memfd_class не включена.

Отказы AVC с целевым классом memfd_file

В следующем примере показан отказ avc , с которым столкнулся процесс, пытавшийся записать данные в memfd , на который у него не было разрешения на запись, при включенной возможности политики memfd_class , а также дополнительная строка, которую logd выводит после отказа с той же меткой времени:

audit(0.0:86): avc: denied { read } for
path=2F6D656D66643A4D6564696142756666657247726F7570202864656C6574656429 ino=512 dev=""
scontext=u:r:mediaserver:s0 tcontext=u:object_r:mediaextractor:s0 tclass=memfd_file

auditd  : Decoded path for audit(0.0:86): /memfd:MediaBufferGroup (deleted)

Соответствующая метка времени указывает на то, что Decoded path for … log связан с отказом avc с меткой времени 0.0.86 . Этот лог декодирует шестнадцатеричную строку из значения пути в отказе avc и предоставляет имя области памяти memfd , что может быть полезно для понимания того, какой буфер используется совместно. Исходный контекст и целевой контекст полезны для понимания того, каким процессам необходимо совместно использовать память. Из приведенного выше примера ясно, что процессу mediaserver необходимо иметь доступ к memfds mediaextractor . Следовательно, соответствующая политика следующая:

# mediaserver.te
allow mediaserver mediaextractor:memfd_file { getattr read write map };

Обновления доменов безопасности в Android 17

API ASharedMemory_create() в Android 17 реализует условную логику для выбора между устаревшим драйвером ashmem и фреймворком memfd при выделении общей памяти.

Для устройств, соответствующих требованиям memfd (уровень API поставщика 202604 или выше и ядро android16-6.12 или новее), API оценивает targetSdkVersion вызывающего приложения. Если целевая версия SDK равна 37 или выше, выделяется memfd . Это позволяет разработчикам исправлять проблемы, возникающие при обновлении целевой версии SDK.

Если устройство не соответствует требованиям memfd's , ASharedMemory переключается на ashmem. Это обеспечивает совместимость обновленных устройств со старыми разделами или ядрами от разных производителей.

Для обеспечения этого перехода политика SELinux платформы блокирует приложениям, ориентированным на версию SDK 37 или выше, в доменах безопасности platform_app , priv_app и untrusted_app , запрещая им открывать /dev/ashmem и вызывать команды ioctl ashmem на memfd . Это достигается путем разделения этих доменов приложений в зависимости от целевой версии SDK. В результате появляются домены безопасности platform_app_36 , priv_app_36 и untrusted_app_34 , которые, наряду с другими доменами приложений, сохраняют разрешения на открытие ashmem и возможность вызывать команды ioctl ashmem на memfds .

В будущей версии Android набор приложений, сохраняющих разрешения на открытие устройства ashmem и выполнение команд ioctl ashmem на memfds будет сокращен до platform_app_36 , priv_app_36 и untrusted_app_34 , а также до доменов ненадежных приложений для более старых версий SDK.

Пользовательские политики SELinux от поставщика или OEM-производителя для приложений, которые фиксируют целевую версию SDK, должны быть обновлены в соответствии с этими изменениями домена, как подробно описано в следующих разделах.

обновления домена SELinux для платформы_приложения

Домен platform_app разделяется в зависимости от targetSdkVersion приложения. Приложениям, ориентированным на SDK версии 37 или выше, назначается домен platform_app , а приложениям, ориентированным на SDK версии 36 или ниже, — домен platform_app_36 . Домен platform_app_36 сохраняет возможность открытия /dev/ashmem для обратной совместимости. Для упрощения управления политиками в обоих доменах используйте атрибут platform_app_all .

Рассмотрим случай, когда приложению-платформе sample-plat-app необходимо читать и записывать данные в /dev/foo_device . Существующая политика SELinux от поставщика может выглядеть следующим образом:

# This will only allow sample-plat-app to access the device if it
# is placed in the platform_app domain (i.e. target SDK version is 37 or higher).
allow platform_app foo_device:chr_file rw_file_perms;

Однако, если sample-plat-app привязан к целевой версии SDK 36, он помещается в домен platform_app_36 , и политика SELinux, примененная ранее, не будет действовать, в результате чего будет наблюдаться следующее сообщение об отказе AVC:

auditd  : type=1400 audit(0.0:11): avc:  denied  { read write } for  comm="sample-plat-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:platform_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0

Для решения этой проблемы политику можно обновить следующим образом, поскольку приложение всегда должно иметь доступ к узлу устройства:

# This allows sample-plat-app to access the device independent of
# target SDK version.
allow platform_app_all foo_device:chr_file rw_file_perms;

В некоторых ситуациях platform_app_all может не работать. Например, если макрос hal_client_domain() используется с platform_app_all , политика не компилируется. Это происходит потому, что platform_app_all является атрибутом, и hal_client_domain() попытается прикрепить к нему другой атрибут, что невозможно:

# platform_app.te
hal_client_domain(platform_app, hal_foo)

В таких сценариях необходимо использовать тип platform_app_36 напрямую, поэтому ваша политика будет содержать следующее:

# platform_app.te
hal_client_domain(platform_app, hal_foo)

# platform_app_36.te
hal_client_domain(platform_app_36, hal_foo)

Обновления домена SELinux для priv_app

Домен priv_app разделяется в зависимости от targetSdkVersion приложения. Привилегированным приложениям, ориентированным на SDK версии 37 или выше, назначается домен priv_app , а приложениям, ориентированным на SDK версии 36 или ниже, — домен priv_app_36 . Домен priv_app_36 сохраняет возможность открытия /dev/ashmem для обратной совместимости. Для упрощения управления политиками в обоих доменах используйте атрибут priv_app_all .

Рассмотрим случай, когда приложению-платформе sample-priv-app необходимо читать и записывать данные в /dev/foo_device . Существующая политика SELinux от поставщика может выглядеть следующим образом:

# This will only allow sample-priv-app to access the device if it
# is placed in the priv_app domain (i.e. target SDK version is 37 or higher).
allow priv_app foo_device:chr_file rw_file_perms;

Однако, если sample-priv-app привязан к целевой версии SDK 36, он помещается в домен priv_app_36 , и политика SELinux, примененная ранее, не будет действовать, в результате чего будет наблюдаться следующее сообщение об отказе AVC:

auditd  : type=1400 audit(0.0:11): avc:  denied  { read write } for  comm="sample-priv-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:priv_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0

Для решения этой проблемы политику можно обновить следующим образом, поскольку приложение всегда должно иметь доступ к узлу устройства:

# This allows sample-priv-app to access the device independent of
# target SDK version.
allow priv_app_all foo_device:chr_file rw_file_perms;

В некоторых ситуациях priv_app_all может не работать. Например, если макрос hal_client_domain() используется с priv_app_all , политика не будет скомпилирована. Это связано с тем, что priv_app_all является атрибутом, и hal_client_domain() попытается прикрепить к нему другой атрибут, что невозможно:

# priv_app.te
hal_client_domain(priv_app, hal_foo)

In those scenarios, it is required to use the priv_app_36 type directly, so your policy files will look something like this:

# priv_app.te
hal_client_domain(priv_app, hal_foo)

# priv_app_36.te
hal_client_domain(priv_app_36, hal_foo)

untrusted_app SELinux domain updates

The untrusted_app domain is split based on the app's targetSdkVersion . Untrusted apps targeting SDK 37 version or higher are assigned the untrusted_app domain, while those targeting SDK versions 34-36 inclusive are assigned the new untrusted_app_34 domain. The untrusted_app_34 domain, as well as the untrusted_app_X domains, where `X` is an older target SDK version, retain the ability to open `/dev/ashmem` for backward compatibility.