Процесс инициализации имеет практически неограниченные разрешения и использует входные сценарии как из системного раздела, так и из раздела поставщика для инициализации системы во время процесса загрузки. Этот доступ создает огромную дыру в разделении системы и поставщика Treble, поскольку сценарии поставщика могут дать команду init получить доступ к файлам, свойствам и т. д., которые не являются частью стабильного двоичного интерфейса приложения система-поставщик (ABI).
Vendor init предназначен для закрытия этой дыры за счет использования отдельного домена vendor_init
с повышенной безопасностью Linux (SELinux) для запуска команд, найденных в /vendor
с разрешениями, специфичными для поставщика.
Механизм
Vendor init разветвляет подпроцесс init в начале процесса загрузки с контекстом SELinux u:r:vendor_init:s0
. Этот контекст SELinux имеет значительно меньше разрешений, чем контекст инициализации по умолчанию, и его доступ ограничен файлами, свойствами и т. д., которые либо зависят от поставщика, либо являются частью стабильного ABI поставщика системы.
Init проверяет каждый загружаемый сценарий, чтобы определить, начинается ли его путь с /vendor
и если да, то помечает его, указывая, что его команды должны выполняться в контексте инициализации поставщика. Каждая встроенная функция init помечена логическим значением, которое указывает, должна ли команда запускаться в подпроцессе инициализации поставщика:
- Большинство команд, которые обращаются к файловой системе, помечены для запуска в подпроцессе инициализации поставщика и, следовательно, подчиняются SEPolicy инициализации поставщика.
- Большинство команд, влияющих на внутреннее состояние инициализации (например, запуск и остановка служб), выполняются в рамках обычного процесса инициализации. Эти команды уведомляются о том, что сценарий поставщика вызывает их для выполнения собственной обработки разрешений, отличных от SELinux.
Основной цикл обработки init содержит проверку того, что, если команда помечена для запуска в подпроцессе поставщика и исходит из сценария поставщика, эта команда отправляется через межпроцессное взаимодействие (IPC) в подпроцесс init поставщика, который запускает команду и отправляет результат обратно в init.
Использовать инициализацию поставщика
Инициализация поставщика включена по умолчанию, и ее ограничения применяются ко всем сценариям инициализации, присутствующим в разделе /vendor
. Инициализация поставщика должна быть прозрачной для поставщиков, чьи сценарии уже не обращаются только к системным файлам, свойствам и т. д.
Однако если команды в данном сценарии поставщика нарушают ограничения инициализации поставщика, команды завершаются неудачно. Неудачные команды имеют строку в журнале ядра (видимую с помощью dmesg) из init, указывающую на сбой. Аудит SELinux сопровождает любую неудачную команду, которая не удалась из-за политики SELinux. Пример сбоя, включая аудит SELinux:
type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0 init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied
Если команда не выполнена, есть два варианта:
- Если команда завершается сбоем из-за предполагаемого ограничения (например, если команда обращается к системному файлу или свойству), команду необходимо повторно реализовать с использованием Treble-дружественного способа, используя только стабильные интерфейсы. Правила Neverallow запрещают добавление разрешений на доступ к системным файлам, которые не являются частью стабильного ABI поставщика системы.
- Если метка SELinux является новой и ей еще не предоставлены разрешения в
vendor_init.te
и не исключены разрешения с помощью правил Neverallow, новой метке могут быть предоставлены разрешения вvendor_init.te
для конкретного устройства.
Для устройств, выпущенных до Android 9, правила Neverallows можно обойти, добавив атрибут типа data_between_core_and_vendor_violators
в файл vendor_init.te
для конкретного устройства.
Расположение кода
Основная часть логики IPC поставщика init находится в system/core/init/subcontext.cpp .
Таблица команд находится в классе BuiltinFunctionMap
в файле system/core/init/builtins.cpp и включает аннотации, указывающие, должна ли команда выполняться в подпроцессе инициализации поставщика.
SEPolicy для поставщика init разделена на частные ( system/sepolicy/private/vendor_init.te ) и общедоступные ( system/sepolicy/public/vendor_init.te ) каталоги в system/sepolicy.
,Процесс инициализации имеет практически неограниченные разрешения и использует входные сценарии как из системного раздела, так и из раздела поставщика для инициализации системы во время процесса загрузки. Этот доступ создает огромную дыру в разделении системы и поставщика Treble, поскольку сценарии поставщика могут указывать init на доступ к файлам, свойствам и т. д., которые не являются частью стабильного двоичного интерфейса приложения система-поставщик (ABI).
Vendor init предназначен для закрытия этой дыры за счет использования отдельного домена vendor_init
с повышенной безопасностью Linux (SELinux) для запуска команд, найденных в /vendor
с разрешениями, специфичными для поставщика.
Механизм
Vendor init разветвляет подпроцесс init в начале процесса загрузки с контекстом SELinux u:r:vendor_init:s0
. Этот контекст SELinux имеет значительно меньше разрешений, чем контекст инициализации по умолчанию, и его доступ ограничен файлами, свойствами и т. д., которые либо зависят от поставщика, либо являются частью стабильного ABI поставщика системы.
Init проверяет каждый загружаемый сценарий, чтобы определить, начинается ли его путь с /vendor
и если да, то помечает его, указывая, что его команды должны выполняться в контексте инициализации поставщика. Каждая встроенная функция init помечена логическим значением, которое указывает, должна ли команда запускаться в подпроцессе инициализации поставщика:
- Большинство команд, которые обращаются к файловой системе, помечены для запуска в подпроцессе инициализации поставщика и, следовательно, подчиняются SEPolicy инициализации поставщика.
- Большинство команд, влияющих на внутреннее состояние инициализации (например, запуск и остановка служб), выполняются в рамках обычного процесса инициализации. Эти команды уведомляются о том, что сценарий поставщика вызывает их для выполнения собственной обработки разрешений, отличных от SELinux.
Основной цикл обработки init содержит проверку того, что, если команда помечена для запуска в подпроцессе поставщика и исходит из сценария поставщика, эта команда отправляется через межпроцессное взаимодействие (IPC) в подпроцесс init поставщика, который запускает команду и отправляет результат обратно в init.
Использовать инициализацию поставщика
Инициализация поставщика включена по умолчанию, и ее ограничения применяются ко всем сценариям инициализации, присутствующим в разделе /vendor
. Инициализация поставщика должна быть прозрачной для поставщиков, чьи сценарии уже не обращаются только к системным файлам, свойствам и т. д.
Однако если команды в данном сценарии поставщика нарушают ограничения инициализации поставщика, команды завершаются неудачно. Неудачные команды имеют строку в журнале ядра (видимую с помощью dmesg) из init, указывающую на сбой. Аудит SELinux сопровождает любую неудачную команду, которая не выполнена из-за политики SELinux. Пример сбоя, включая аудит SELinux:
type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0 init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied
Если команда не выполнена, есть два варианта:
- Если команда завершается сбоем из-за предполагаемого ограничения (например, если команда обращается к системному файлу или свойству), команду необходимо повторно реализовать с использованием Treble-дружественного способа, используя только стабильные интерфейсы. Правила Neverallow запрещают добавление разрешений на доступ к системным файлам, которые не являются частью стабильного ABI поставщика системы.
- Если метка SELinux является новой и ей еще не предоставлены разрешения в
vendor_init.te
и не исключены разрешения с помощью правил Neverallow, новой метке могут быть предоставлены разрешения вvendor_init.te
для конкретного устройства.
Для устройств, выпущенных до Android 9, правила Neverallows можно обойти, добавив атрибут типа data_between_core_and_vendor_violators
в файл vendor_init.te
для конкретного устройства.
Расположение кода
Основная часть логики IPC поставщика init находится в system/core/init/subcontext.cpp .
Таблица команд находится в классе BuiltinFunctionMap
в файле system/core/init/builtins.cpp и включает аннотации, указывающие, должна ли команда выполняться в подпроцессе инициализации поставщика.
SEPolicy для поставщика init разделена на частные ( system/sepolicy/private/vendor_init.te ) и общедоступные ( system/sepolicy/public/vendor_init.te ) каталоги в system/sepolicy.