Подключение к приложению#
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 обёртка отклоняет.