Подключение к приложению#

astra-shim подключается к приложению вручную. Нужны три вещи: файл с таблицей правил внутри приложения, скрипт-лаунчер, который вызывает обёртку расширения, и команда запуска приложения, указывающая на этот лаунчер.

Обёртка в приложение не входит: она приезжает расширением среды выполнения. Приложение приносит только правила и лаунчер.

Откуда берётся обёртка#

Среды выполнения Astra объявляют точку расширения org.astra.Shim:

[Extension org.astra.Shim]
directory=lib/astra-shim
autodelete=true
version=1.8.6
add-ld-path=lib

Точка объявлена без no-autodownload, поэтому расширение ставится вместе со средой и отдельной установки не требует. Проверить, что среда объявляет точку:

flatpak info -m org.astra.Gtk//1.8.6 | grep -A5 'Extension org.astra.Shim'

Содержимое монтируется в /usr/lib/astra-shim:

/usr/lib/astra-shim/bin/astra-shim-wrapper
/usr/lib/astra-shim/bin/astra-seccomp-launch
/usr/lib/astra-shim/lib/libastra-shim.so

Обёртка вызывается как astra-shim-wrapper КОМАНДА [АРГУМЕНТЫ...]. Она подставляет библиотеку перехвата в LD_PRELOAD и запускает команду. Свои библиотеки приложения в LD_PRELOAD сохраняются.

Файл правил и лаунчер#

Оба файла кладутся в приложение командами секции commands.pre-export. Они выполняются в каталоге сборки, где лежит дерево files, поэтому пути записываются относительно него: files/etc станет /app/etc, а files/bin станет /app/bin.

commands:
  pre-export:
    - mkdir -p files/etc files/bin
    - |
      cat > files/etc/astra-shim.conf <<'EOF'
      /usr/lib/myapp   = /app/lib/myapp
      /usr/share/myapp = /app/share/myapp
      /etc/myapp       = /app/etc/myapp
      systemctl        = flatpak-spawn --host systemctl
      EOF
    - |
      cat > files/bin/myapp-launch <<'EOF'
      #!/bin/sh
      exec /usr/lib/astra-shim/bin/astra-shim-wrapper /app/bin/myapp "$@"
      EOF
    - chmod 0755 files/bin/myapp-launch

Обёртка ищет правила в /app/etc/astra-shim.conf, поэтому при таком расположении ничего указывать дополнительно не нужно. Другой путь задаётся переменной ASTRA_SHIM_CONFIG.

Команда запуска#

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

files:
  command: myapp-launch

Существование команды при сборке не проверяется, а pre-export выполняется уже после того, как команда записана в метаданные. Порядок при этом верный: лаунчер появляется в дереве до экспорта.

Слой seccomp#

Слой seccomp поднимается переменной ASTRA_SHIM_SECCOMP. Проще всего выставить её прямо в лаунчере:

#!/bin/sh
ASTRA_SHIM_SECCOMP=1 exec /usr/lib/astra-shim/bin/astra-shim-wrapper /app/bin/myapp "$@"

То же самое даёт запись в разрешениях приложения:

permissions:
  env:
    - ASTRA_SHIM_SECCOMP=1

Включать слой имеет смысл только тогда, когда без него конкретная программа не работает. Что он добавляет и чего требует от ядра, разобрано в блоках Как устроен перехват и Ограничения и уход от astra-shim.

Полный пример#

version: "1.0"

metadata:
  id: ru.example.MyApp
  name: "Программа поставщика"
  branch: stable

runtime:
  id: org.astra.Gtk
  version: "1.8.6"

source:
  type: local
  local:
    path: ./myapp_1.0_amd64.deb

files:
  command: myapp-launch

permissions:
  sockets: [wayland, fallback-x11]
  devices: [dri]
  talk-name:
    - org.freedesktop.Flatpak

commands:
  pre-export:
    - mkdir -p files/etc files/bin
    - |
      cat > files/etc/astra-shim.conf <<'EOF'
      /usr/lib/myapp = /app/lib/myapp
      systemctl      = flatpak-spawn --host systemctl
      EOF
    - |
      cat > files/bin/myapp-launch <<'EOF'
      #!/bin/sh
      exec /usr/lib/astra-shim/bin/astra-shim-wrapper /app/bin/myapp "$@"
      EOF
    - chmod 0755 files/bin/myapp-launch

export:
  repository: ./repo

Разрешение talk-name: org.freedesktop.Flatpak нужно только при подмене команд на flatpak-spawn --host: без него подменённая команда завершится ошибкой обращения к шине. Разрешение позволяет приложению запускать на хосте произвольные команды, поэтому подменяются только те вызовы, без которых программа не работает.

Подбор правил через analyze#

Правила не обязательно искать вручную. Команда aft-app analyze разбирает содержимое источника и показывает отдельным разделом то, что можно закрыть через astra-shim:

aft-app analyze --package myapp --runtime org.astra.Gtk --runtime-version 1.8.6

В разделе про astra-shim выводятся найденные зашитые пути с предлагаемым ремапом и примером файла, где путь встретился, а также найденные вызовы хостовых команд с предлагаемой заменой. Строки переносятся в файл правил как есть: формат вывода совпадает с форматом конфига.

Анализ намеренно сужает правило до первого каталога, специфичного для приложения. Вместо /usr/lib предлагается /usr/lib/myapp: ремап целого /usr/lib перекрыл бы общие библиотеки среды выполнения, которых в /app/lib нет, и приложение перестало бы запускаться. По той же причине из предложений исключаются разделяемые библиотеки, общие пространства имён вроде /usr/share/icons или /etc/pam.d и системные файлы /etc вроде passwd и resolv.conf.

Из хостовых команд распознаются apt, apt-get, aptitude, dpkg, dpkg-query, systemctl, update-desktop-database, update-mime-database, gtk-update-icon-cache, ldconfig и gsettings.

Проверка#

После установки приложения стоит убедиться, что обёртка на месте, правила лежат там, где их ищут, и запуск через лаунчер проходит. Проще всего сделать это изнутри песочницы:

flatpak run --command=sh ru.example.MyApp

Внутри:

ls /usr/lib/astra-shim/bin
cat /app/etc/astra-shim.conf
/usr/lib/astra-shim/bin/astra-shim-wrapper /app/bin/myapp --version

Пустой каталог /usr/lib/astra-shim означает, что расширение не смонтировалось: среда не объявляет точку или расширение не установлено.

Чтобы увидеть, какие пути перехватываются и во что переписываются, в файл правил добавляется строка debug = 1 и приложение пересобирается. Журнал перехвата идёт в поток ошибок. В готовой сборке эту строку не оставляют.

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