Внедрить SELinux

SELinux настроен на запрет по умолчанию, что означает, что любой доступ, для которого есть хук в ядре, должен быть явно разрешён политикой. Это означает, что файл политики содержит большой объём информации о правилах, типах, классах, разрешениях и т.д. Полное рассмотрение SELinux выходит за рамки данного документа, но понимание того, как писать правила политики, теперь крайне важно при запуске новых устройств Android. Уже доступно много информации о SELinux. См. вспомогательную документацию для получения рекомендуемых ресурсов.

Ключевые файлы

Чтобы включить SELinux, интегрируйте последнюю версию ядра Android , а затем добавьте файлы из каталога system/sepolicy . После компиляции эти файлы образуют политику безопасности ядра SELinux и охватывают основную операционную систему Android.

Как правило, не следует изменять файлы system/sepolicy напрямую. Вместо этого добавьте или отредактируйте собственные файлы политики для конкретного устройства в каталоге /device/ manufacturer / device-name /sepolicy . В Android 8.0 и более поздних версиях изменения, вносимые в эти файлы, должны влиять только на политику в каталоге поставщика. Подробнее о разделении публичной политики sepolicy в Android 8.0 и более поздних версиях см. в разделе «Настройка SEPolicy в Android 8.0+» . Независимо от версии Android, вам всё равно придётся изменять эти файлы:

Файлы политики

Файлы с расширением *.te — это исходные файлы политики SELinux, которые определяют домены и их метки. Возможно, вам потребуется создать новые файлы политики в каталоге /device/ manufacturer / device-name /sepolicy , но по возможности постарайтесь обновить существующие файлы.

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

Контекстные файлы — это место, где вы указываете метки для своих объектов.

  • file_contexts назначает метки файлам и используется различными компонентами пользовательского пространства. При создании новых политик создайте или обновите этот файл, чтобы назначить новые метки файлам. Чтобы применить новый file_contexts , пересоберите образ файловой системы или запустите restorecon для файла, который необходимо перемаркировать. При обновлении изменения file_contexts автоматически применяются к системным разделам и разделам пользовательских данных. Изменения также можно автоматически применять к другим разделам при обновлении, добавив вызовы restorecon_recursive в файл board после монтирования раздела в режиме чтения и записи.
  • genfs_contexts назначает метки файловым системам, таким как proc или vfat , которые не поддерживают расширенные атрибуты. Эта конфигурация загружается как часть политики ядра, но изменения могут не вступить в силу для in-core inodes, что потребует перезагрузки или размонтирования и повторного монтирования файловой системы для полного применения изменений. Конкретные метки также можно назначать конкретным точкам монтирования, например vfat с помощью параметра context=mount .
  • property_contexts присваивает метки системным свойствам Android, чтобы контролировать, какие процессы могут их устанавливать. Эта конфигурация считывается процессом init во время запуска.
  • service_contexts назначает метки службам-биндерам Android, чтобы контролировать, какие процессы могут добавлять (регистрировать) и находить (искать) ссылки на связыватели для данной службы. Эта конфигурация считывается процессом servicemanager во время запуска.
  • seapp_contexts назначает метки процессам приложения и каталогам /data/data . Эта конфигурация считывается процессом zygote при каждом запуске приложения и installd во время его запуска.
  • Файл mac_permissions.xml назначает приложениям тег seinfo на основе их подписи и, при необходимости, имени пакета. Тег seinfo затем можно использовать в качестве ключа в файле seapp_contexts для назначения определённой метки всем приложениям с этим тегом seinfo . Эта конфигурация считывается system_server во время запуска.
  • keystore2_key_contexts назначает метки пространствам имён Keystore 2. Эти пространства имён поддерживаются демоном keystore2 . Keystore всегда предоставлял пространства имён на основе UID/AID. Keystore 2 также поддерживает пространства имён, определённые в sepolicy. Подробное описание формата и соглашений этого файла можно найти здесь .

BoardConfig.mk makefile

После редактирования или добавления файлов политики и контекста обновите make-файл /device/ manufacturer / device-name /BoardConfig.mk указав подкаталог sepolicy и каждый новый файл политики. Подробнее о переменных BOARD_SEPOLICY см. в файле system/sepolicy/README .

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

После пересборки на вашем устройстве будет активирован SELinux. Теперь вы можете либо настроить политики SELinux для поддержки собственных дополнений к операционной системе Android, как описано в разделе «Настройка» , либо проверить существующую настройку, как описано в разделе «Проверка» .

После установки новых файлов политики и обновлений BoardConfig.mk новые параметры политики автоматически встраиваются в финальный файл политики ядра. Подробнее о построении sepolicy на устройстве см. в разделе «Создание sepolicy» .

Выполнение

Чтобы начать работу с SELinux:

  1. Включить SELinux в ядре: CONFIG_SECURITY_SELINUX=y
  2. Измените параметр kernel_cmdline или bootconfig таким образом:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    или
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Это необходимо только для первоначальной разработки политики для устройства. После создания начальной политики самозагрузки удалите этот параметр, чтобы устройство выполняло принудительное применение политики, иначе оно не сможет пройти CTS.
  3. Загрузите систему в разрешительном режиме и посмотрите, какие запреты возникнут при загрузке:
    В Ubuntu 14.04 или новее:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    В Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Проверьте вывод на наличие предупреждений, похожих init: Warning! Service name needs a SELinux domain defined; please fix! Инструкции и инструменты см. в разделе «Проверка» .
  5. Определите устройства и другие новые файлы, требующие маркировки.
  6. Используйте существующие или новые метки для своих объектов. Просмотрите файлы *_contexts , чтобы узнать, как объекты были помечены ранее, и используйте информацию о значениях меток для назначения новой. В идеале это должна быть существующая метка, соответствующая политике, но иногда требуется новая метка и правила доступа к ней. Добавьте свои метки в соответствующие файлы контекста.
  7. Определите домены/процессы, которым следует задать собственные домены безопасности. Вероятно, вам потребуется написать совершенно новую политику для каждого из них. Например, все службы, запущенные из init , должны иметь свою собственную. Следующие команды помогают определить, какие из них остаются запущенными (но такая обработка требуется для ВСЕХ служб):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Проверьте init. device .rc чтобы определить все домены, у которых нет типа домена. Задайте им домен на ранних этапах разработки, чтобы избежать добавления правил в init и не путать доступы init с доступами, указанными в их собственной политике.
  9. Настройте BOARD_CONFIG.mk для использования переменных BOARD_SEPOLICY_* . Подробную информацию о настройке см. в файле README в system/sepolicy
  10. Проверьте файлы device и device и убедитесь, что каждое использование mount соответствует правильно помеченной файловой системе или что указана опция context= mount .
  11. Проанализируйте каждое отклонение и создайте политику SELinux для его корректной обработки. См. примеры в разделе «Настройка» .

Начните с политик в AOSP, а затем дополняйте их собственными настройками. Подробнее о стратегии политики и более подробном рассмотрении некоторых из этих шагов см. в разделе «Написание политики SELinux» .

Варианты использования

Вот конкретные примеры эксплойтов, которые следует учитывать при создании собственного программного обеспечения и связанных с ним политик SELinux:

Символические ссылки: Поскольку символические ссылки выглядят как файлы, они часто читаются как файлы, что может привести к эксплойтам. Например, некоторые привилегированные компоненты, такие как init , изменяют права доступа к определённым файлам, иногда делая их чрезмерно открытыми.

Затем злоумышленники могут заменить эти файлы символическими ссылками на контролируемый ими код, что позволит им перезаписывать произвольные файлы. Но если вы знаете, что ваше приложение никогда не использует символические ссылки, вы можете запретить ему это делать с помощью SELinux.

Системные файлы: Рассмотрим класс системных файлов, которые должен изменять только системный сервер. Однако, поскольку netd , init и vold работают от имени root, они могут получить доступ к этим системным файлам. Таким образом, если netd будет скомпрометирован, это может привести к компрометации этих файлов и, возможно, самого системного сервера.

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

Данные приложения: Другой пример — класс функций, которые должны запускаться от имени пользователя root, но не должны иметь доступа к данным приложения. Это невероятно полезно, поскольку позволяет делать широкие утверждения, например, запрещать доступ к интернету определённым доменам, не связанным с данными приложения.

setattr: Для таких команд, как chmod и chown , можно определить набор файлов, к которым соответствующий домен может применить setattr . Изменения, вносимые за пределами этого списка, могут быть запрещены, даже для root-пользователя. Таким образом, приложение может выполнять chmod и chown для файлов с меткой app_data_files , но не shell_data_files или system_data_files .