Skip to content

Руководство по разработке модулей

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

Модульный механизм KernelSU практически аналогичен механизму Magisk. Если вы знакомы с разработкой модулей Magisk, то разработка модулей KernelSU очень похожа. Представление модулей ниже можно пропустить, достаточно прочитать [различия-с-magisk] (difference-with-magisk.md).

Busybox

В комплект поставки KernelSU входит полнофункциональный бинарный файл BusyBox (включая полную поддержку SELinux). Исполняемый файл находится по адресу /data/adb/ksu/bin/busybox. BusyBox от KernelSU поддерживает переключаемый во время работы "ASH Standalone Shell Mode". Этот автономный режим означает, что при запуске в оболочке ash BusyBox каждая команда будет напрямую использовать апплет внутри BusyBox, независимо от того, что задано в качестве PATH. Например, такие команды, как ls, rm, chmod будут НЕ использовать то, что находится в PATH (в случае Android по умолчанию это будут /system/bin/ls, /system/bin/rm и /system/bin/chmod соответственно), а вместо этого будут напрямую вызывать внутренние апплеты BusyBox. Это гарантирует, что скрипты всегда будут выполняться в предсказуемом окружении и всегда будут иметь полный набор команд, независимо от того, на какой версии Android они выполняются. Чтобы заставить команду не использовать BusyBox, необходимо вызвать исполняемый файл с полными путями.

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

Для тех, кто хочет использовать эту возможность "Автономного режима" вне KernelSU, есть два способа включить ее:

  1. Установите переменной окружения ASH_STANDALONE значение 1
    Пример: ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script>
  2. Переключитесь с помощью параметров командной строки:
    /data/adb/ksu/bin/busybox sh -o standalone <script>

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

отличие от Magisk

BusyBox в KernelSU теперь использует бинарный файл, скомпилированный непосредственно из проекта Magisk. **Поэтому вам не нужно беспокоиться о проблемах совместимости между скриптами BusyBox в Magisk и KernelSU, поскольку они абсолютно одинаковы!

Модули KernelSU

Модуль KernelSU - это папка, размещенная в каталоге /data/adb/modules и имеющая следующую структуру:

txt
/data/adb/modules
├── .
├── .
|
├── $MODID                  <--- Папка имеет имя с идентификатором модуля
│   │
│   │      *** Идентификация модуля ***
│   │
│   ├── module.prop         <--- В этом файле хранятся метаданные модуля
│   │
│   │      *** Основное содержимое ***
│   │
│   ├── system              <--- Эта папка будет смонтирована, если skip_mount не существует
│   │   ├── ...
│   │   ├── ...
│   │   └── ...
│   │
│   │      *** Флаги состояния ***
│   │
│   ├── skip_mount          <--- Если он существует, то KernelSU НЕ будет монтировать вашу системную папку
│   ├── disable             <--- Если модуль существует, то он будет отключен
│   ├── remove              <--- Если модуль существует, то при следующей перезагрузке он будет удален
│   │
│   │      *** Необязательные файлы ***
│   │
│   ├── post-fs-data.sh     <--- Этот скрипт будет выполняться в post-fs-data
│   ├── service.sh          <--- Этот скрипт будет выполняться в сервисе late_start
|   ├── uninstall.sh        <--- Этот скрипт будет выполнен, когда KernelSU удалит ваш модуль
│   ├── system.prop         <--- Свойства из этого файла будут загружены в качестве системных свойств программой resetprop
│   ├── sepolicy.rule       <--- Дополнительные пользовательские правила sepolicy
│   │
│   │      *** Автоматически генерируется, НЕЛЬЗЯ создавать или изменять вручную ***
│   │
│   ├── vendor              <--- Символьная ссылка на $MODID/system/vendor
│   ├── product             <--- Символьная ссылка на $MODID/system/product
│   ├── system_ext          <--- Симлинк на $MODID/system/system_ext
│   │
│   │      *** Допускается использование любых дополнительных файлов/папок ***
│   │
│   ├── ...
│   └── ...
|
├── another_module
│   ├── .
│   └── .
├── .
├── .

различия с Magisk

KernelSU не имеет встроенной поддержки Zygisk, поэтому в модуле нет содержимого, связанного с Zygisk. Однако для поддержки модулей Zygisk можно использовать ZygiskNext. В этом случае содержимое модуля Zygisk идентично содержимому, поддерживаемому Magisk.

module.prop

module.prop - это конфигурационный файл модуля. В KernelSU, если модуль не содержит этого файла, он не будет распознан как модуль. Формат этого файла следующий:

txt
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
  • id должно соответствовать данному регулярному выражению: ^[a-zA-Z][a-zA-Z0-9._-]+$
    экс: ✓ a_module, ✓ a.module, ✓ module-101, ✗ a module, ✗ 1_module, ✗ -a-module
    Это уникальный идентификатор вашего модуля. Не следует изменять его после публикации.
  • versionCode должен быть целым. Это используется для сравнения версий
  • Другими, не упомянутыми выше, могут быть любые однострочные строки.
  • Обязательно используйте тип перевода строки UNIX (LF), а не Windows (CR+LF) или Macintosh (CR).

Сценарии командной оболочки

Чтобы понять разницу между post-fs-data.sh и Service.sh, прочитайте раздел Boot Scripts. Для большинства разработчиков модулей service.sh должно быть достаточно, если вам нужно просто запустить загрузочный скрипт.

Во всех скриптах вашего модуля используйте MODDIR=${0%/*} для получения пути к базовому каталогу вашего модуля; НЕ кодируйте жестко путь к вашему модулю в скриптах.

различия с Magisk

С помощью переменной окружения KSU можно определить, выполняется ли сценарий в KernelSU или в Magisk. Если скрипт выполняется в KernelSU, то это значение будет равно true.

каталог system

После загрузки системы содержимое этого каталога будет наложено поверх раздела /system с помощью overlayfs. Это означает, что:

  1. Файлы с теми же именами, что и в соответствующем каталоге в системе, будут перезаписаны файлами в этом каталоге.
  2. Папки с теми же именами, что и в соответствующем каталоге в системе, будут объединены с папками в этом каталоге.

Если вы хотите удалить файл или папку в исходном каталоге системы, необходимо создать файл с тем же именем, что и файл/папка, в каталоге модуля с помощью команды mknod filename c 0 0. Таким образом, система overlayfs автоматически "забелит" этот файл, как если бы он был удален (раздел /system при этом фактически не изменится).

Вы также можете объявить в customize.sh переменную с именем REMOVE, содержащую список каталогов для выполнения операций удаления, и KernelSU автоматически выполнит команду mknod <TARGET> c 0 0 в соответствующих каталогах модуля. Например:

sh
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"

В приведенном выше списке будут выполнены команды mknod $MODPATH/system/app/YouTuBe c 0 0 и mknod $MODPATH/system/app/Bloatware c 0 0; при этом /system/app/YouTube и /system/app/Bloatware будут удалены после вступления модуля в силу.

Если вы хотите заменить каталог в системе, то необходимо создать каталог с тем же путем в каталоге модуля, а затем установить для этого каталога атрибут setfattr -n trusted.overlay.opaque -v y <TARGET>. Таким образом, система overlayfs автоматически заменит соответствующий каталог в системе (без изменения раздела /system).

Вы можете объявить в файле customize.sh переменную с именем REPLACE, содержащую список заменяемых каталогов, и KernelSU автоматически выполнит соответствующие операции в каталоге вашего модуля. Например:

REPLACE=" /system/app/YouTube /system/app/Bloatware "

В этом списке будут автоматически созданы каталоги $MODPATH/system/app/YouTube и $MODPATH/system/app/Bloatware, а затем выполнены команды setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/YouTube и setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/Bloatware. После вступления модуля в силу каталоги /system/app/YouTube и /system/app/Bloatware будут заменены на пустые.

различия с Magisk

В KernelSU бессистемный механизм реализован через overlayfs ядра, а в Magisk в настоящее время используется магическое монтирование (bind mount). Эти два метода реализации имеют существенные различия, но конечная цель у них одна: модификация файлов /system без физического изменения раздела /system.

Если вы заинтересованы в использовании overlayfs, рекомендуется прочитать документацию по overlayfs ядра Linux.

system.prop

Этот файл имеет тот же формат, что и build.prop. Каждая строка состоит из [key]=[value].

sepolicy.rule

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

Установщик модулей

Инсталлятор модуля KernelSU - это модуль KernelSU, упакованный в zip-файл, который может быть прошит в APP-менеджере KernelSU. Простейший установщик модуля KernelSU - это просто модуль KernelSU, упакованный в zip-файл.

txt
module.zip

├── customize.sh                       <--- (Необязательно, более подробно позже)
│                                           Этот скрипт будет использоваться в update-binary
├── ...
├── ...  /* Остальные файлы модуля */

WARNING

Модуль KernelSU НЕ поддерживается для установки в пользовательское Recovery!!!

Персонализация

Если вам необходимо настроить процесс установки модуля, то в качестве опции вы можете создать в программе установки скрипт с именем customize.sh. Этот скрипт будет источником (не исполняться!) сценария установщика модуля после извлечения всех файлов и применения стандартных разрешений и secontext. Это очень удобно, если ваш модуль требует дополнительной настройки в зависимости от ABI устройства, или вам необходимо установить специальные разрешения/секонтекст для некоторых файлов модуля.

Если вы хотите полностью контролировать и настраивать процесс установки, объявите SKIPUNZIP=1 в файле customize.sh, чтобы пропустить все шаги установки по умолчанию. При этом ваш customize.sh будет сам отвечать за установку.

Сценарий customize.sh запускается в оболочке BusyBox ash KernelSU с включенным "Автономным режимом". Доступны следующие переменные и функции:

Переменные

  • KSU (bool): переменная, отмечающая, что скрипт выполняется в окружении KernelSU, причем значение этой переменной всегда будет true. Ее можно использовать для различения KernelSU и Magisk.
  • KSU_VER (string): строка версии текущего установленного KernelSU (например, v0.4.0)
  • KSU_VER_CODE (int): код версии текущего установленного KernelSU в пользовательском пространстве (например, 10672)
  • KSU_KERNEL_VER_CODE (int): код версии текущей установленной KernelSU в пространстве ядра (например, 10672)
  • BOOTMODE (bool): в KernelSU всегда должно быть true.
  • MODPATH (path): путь, по которому должны быть установлены файлы ваших модулей
  • TMPDIR (path): место, где вы можете временно хранить файлы
  • ZIPFILE (path): установочный zip-архив вашего модуля
  • ARCH (string): архитектура процессора устройства. Значение: arm, arm64, x86 или x64.
  • IS64BIT (bool): true, если $ARCH имеет значение arm64 или x64.
  • API (int): уровень API (версия Android) устройства (например, 23 для Android 6.0)

WARNING

В KernelSU MAGISK_VER_CODE всегда равен 25200, а MAGISK_VER всегда равен v25.2. Пожалуйста, не используйте эти две переменные для определения того, запущен ли он на KernelSU или нет.

Функции

txt
ui_print <msg>
    вывести <msg> на консоль
    Избегайте использования 'echo', так как он не будет отображаться в консоли пользовательского recovery

abort <msg>
    вывести сообщение об ошибке <msg> на консоль и завершить установку
    Избегайте использования команды 'exit', так как в этом случае будут пропущены шаги очистки завершения установки

set_perm <target> <owner> <group> <permission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    Эта функция является сокращением для следующих команд:
       chown owner.group target
       chmod permission target
       chcon context target

set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    для всех файлов в <directory> будет вызвана команда:
       set_perm file owner group filepermission context
    для всех каталогов в <directory> (включая себя самого), он вызовет:
       set_perm dir owner group dirpermission context

Загрузочные сценарии

В KernelSU скрипты делятся на два типа в зависимости от режима их работы: режим post-fs-data и режим late_start service:

  • режим post-fs-data
    • Эта стадия является БЛОКИРУЮЩЕЙ. Процесс загрузки приостанавливается до завершения выполнения или по истечении 10 секунд.
    • Сценарии запускаются до того, как будут смонтированы какие-либо модули. Это позволяет разработчику модулей динамически настраивать свои модули до того, как они будут смонтированы.
    • Этот этап происходит до запуска Zygote, что практически означает, что все в Android
    • ПРЕДУПРЕЖДЕНИЕ: использование setprop приведет к блокировке процесса загрузки! Вместо этого используйте resetprop -n <prop_name> <prop_value>.
    • Запускайте скрипты в этом режиме только в случае необходимости.
  • режим обслуживания late_start
    • Эта стадия является НЕБЛОКИРУЮЩЕЙ. Ваш скрипт выполняется параллельно с остальным процессом загрузки.
    • Это рекомендуемый этап для запуска большинства скриптов.

В KernelSU скрипты запуска делятся на два типа по месту их хранения: общие скрипты и скрипты модулей:

  • Общие скрипты
    • Размещаются в файлах /data/adb/post-fs-data.d или /data/adb/service.d.
    • Выполняется только в том случае, если скрипт установлен как исполняемый (chmod +x script.sh)
    • Скрипты в post-fs-data.d выполняются в режиме post-fs-data, а скрипты в service.d - в режиме late_start service.
    • Модули не должны НЕ добавлять общие скрипты при установке
  • Скрипты модуля
    • Размещаются в отдельной папке модуля
    • Выполняются только в том случае, если модуль включен
    • post-fs-data.sh запускается в режиме post-fs-data, а service.sh - в режиме late_start service.

Все загрузочные скрипты будут выполняться в оболочке BusyBox ash от KernelSU с включенным "Автономным режимом".

Выпускается под лицензией GPL3.