Написание политики SELinux

Проект Android с открытым исходным кодом (AOSP) обеспечивает надежную базовую политику для приложений и служб, которые являются общими для всех устройств Android. Участники AOSP регулярно дорабатывают эту политику. Ожидается, что основная политика составит около 90–95 % окончательной политики для устройств, а настройки для конкретных устройств составят оставшиеся 5–10 %. В этой статье основное внимание уделяется настройкам для конкретных устройств, написанию политики для конкретных устройств и некоторым ловушкам, которых следует избегать на этом пути.

Вызов устройства

При написании политики для конкретного устройства выполните следующие действия.

Запуск в разрешительном режиме

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

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

Самый простой способ перевести устройство в разрешительный режим — использовать командную строку ядра . Его можно добавить в файл BoardConfig.mk устройства: platform/device/<vendor>/<target>/BoardConfig.mk . После изменения командной строки выполните make clean , затем make bootimage и запишите новый загрузочный образ.

После этого подтвердите разрешительный режим с помощью:

adb shell getenforce

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

Применять на ранней стадии

В принудительном режиме отказы одновременно протоколируются и применяются. Рекомендуется как можно раньше перевести ваше устройство в обязательный режим. Ожидание создания и применения политики для конкретного устройства часто приводит к появлению ошибок в продукте и ухудшению пользовательского опыта. Начните достаточно рано, чтобы принять участие в тестировании и обеспечить полное тестирование функциональности в реальных условиях. Ранний старт гарантирует, что соображения безопасности будут учитываться при принятии проектных решений. И наоборот, предоставление разрешений исключительно на основании наблюдаемых отказов является небезопасным подходом. Используйте это время для проверки безопасности устройства и выявления ошибок в поведении, которое не должно быть разрешено.

Удалить или удалить существующую политику

Существует ряд веских причин создать политику для конкретного устройства с нуля на новом устройстве, в том числе:

Устранение отказов в основных услугах

Отказы, генерируемые основными службами, обычно устраняются путем маркировки файлов. Например:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

полностью решается путем правильной маркировки /dev/kgsl-3d0 . В этом примере tcontext — это device . Это представляет собой контекст по умолчанию, в котором все в /dev получает метку « устройство », если не назначена более конкретная метка. Простое принятие вывода Audit2allow приведет к созданию неправильного и чрезмерно разрешающего правила.

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

Другие файлы, специфичные для устройства, которые должны быть помечены типами, предопределенными в основной политике:

В целом предоставление разрешений меткам по умолчанию неверно. Многие из этих разрешений запрещены правилами Neverallow , но даже если они не запрещены явно, рекомендуется указать специальную метку.

Маркируйте новые услуги и устраняйте отказы

Службы, запускаемые с помощью Init, должны работать в собственных доменах SELinux. В следующем примере служба «foo» помещается в собственный домен SELinux и предоставляет ей разрешения.

Сервис запускается в init. device .rc файл init. device .rc как:

service foo /system/bin/foo
    class core
  1. Создайте новый домен «foo»

    Создайте файл device/ manufacturer / device-name /sepolicy/foo.te со следующим содержимым:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    Это исходный шаблон для домена foo SELinux, к которому вы можете добавлять правила, основанные на конкретных операциях, выполняемых этим исполняемым файлом.

  2. Метка /system/bin/foo

    Добавьте следующее в device/ manufacturer / device-name /sepolicy/file_contexts :

    /system/bin/foo   u:object_r:foo_exec:s0
    

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

  3. Создайте и прошейте загрузочные и системные образы.
  4. Уточните правила SELinux для домена.

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

Вернитесь в режим принудительного применения

Устранять неполадки в разрешительном режиме можно, но как можно раньше вернитесь в принудительный режим и постарайтесь оставаться в нем.

Распространенные ошибки

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

Чрезмерное использование отрицания

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

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

Цель ясна: все, кроме сторонних приложений, могут иметь доступ к устройству отладки.

Это правило ошибочно по нескольким причинам. Исключение untrusted_app легко обойти, поскольку все приложения могут при желании запускать службы в домене isolated_app . Аналогично, если в AOSP будут добавлены новые домены для сторонних приложений, они также получат доступ к scary_debug_device . Это правило слишком либерально. Большинству доменов не будет полезно иметь доступ к этому инструменту отладки. Правило должно было быть написано так, чтобы разрешать только те домены, которым требуется доступ.

Отладка функций в продакшене

Функции отладки не должны присутствовать в производственных сборках, равно как и их политика.

Самая простая альтернатива — разрешить функцию отладки только тогда, когда SELinux отключен в сборках eng/userdebug, таких как adb root и adb shell setenforce 0 .

Другая безопасная альтернатива — включить разрешения на отладку в оператор userdebug_or_eng .

Взрыв размера политики

Характеристика SEAndroid Policies in the Wild описывает тревожную тенденцию роста количества настроек политик устройств. Политика, специфичная для устройства, должна составлять 5–10 % от общей политики, действующей на устройстве. Настройки в диапазоне 20%+ почти наверняка содержат слишком привилегированные домены и мертвую политику.

Неоправданно большая политика:

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

В следующем примере показаны два устройства, где политика, специфичная для производителя, составляла 50 % и 40 % политики на устройстве. Переписывание политики привело к существенному улучшению безопасности без потери функциональности, как показано ниже. (Устройства AOSP Shamu и Flounder включены для сравнения.)

Рисунок 1. Сравнение размера политики для конкретного устройства после аудита безопасности.

Рисунок 1 . Сравнение размера политики для конкретного устройства после аудита безопасности.

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

Предоставление возможности dac_override

Отказ dac_override означает, что процесс-нарушитель пытается получить доступ к файлу с неправильными разрешениями пользователя/группы/мира unix. Правильное решение — почти никогда не предоставлять разрешение dac_override . Вместо этого измените разрешения Unix для файла или процесса . Некоторым доменам, таким как init , vold и installd действительно нужна возможность переопределять разрешения файлов unix для доступа к файлам других процессов. См. блог Дэна Уолша для более подробного объяснения.