О bubblewrap
Аналогично firejail для создания изолированных окружений bubblewrap использует такие механизмы ядра Linux, как namespaces и seccomp, рассмотренные в статье «Обзор механизмов организации изолированных окружений в Linux». Firejail дополнительно использует cgroups, в bubblewrap ограничение ресурсов средствами cgroups не предусмотрено.
Также аналогично firejail инструмент bubblewrap представляет собой SUID-процесс, что позволяет создавать изолированные окружения обычным пользователям.
Ключевым отличием от firejail является минималистичность bubblewrap: он, по сути, является не решением «из коробки», а своего рода прослойкой для создания песочниц. Эту прослойку удобно использовать сторонним приложениям, для которых организация изолированного окружения — это лишь одна из задач. Отличительные особенности bubblewrap, таким образом, — это минимализация и максимальная гибкость настройки.
Благодаря своей минималистичности bubblewrap используется как прослойка изоляции в таком инструменте распространения приложений, как flatpack. Flatpack-пакеты подразумевают запуск содержащихся в них приложений в режиме изоляции от внешней среды, что и обеспечивается средствами bubblewrap.
Механизм профилей отсутствует, параметры изоляции полностью задаются параметрами командной строки. Естественно, нет и возможности настроить запуск приложений в песочнице автоматически, как это можно сделать в firejail.
Установка bubblewrap
Bubblewrap, как правило, содержится в одноименном пакете. Соответственно, его установка в зависимости от используемого вами дистрибутива Linux выглядит так:
# apt-get install bubblewrap
Или так:
# dnf install buublewrap
Основная утилита bubblewrap, через параметры которой создаются изолированные окружения, — bwrap. Справка по ее использованию доступна по команде:
$ man bwrap
Chroot-изация средствами bwrap
Принципы chroot-изации рассмотрены в статьях «Изоляция процессов средствами chroot» и «Chroot: Запуск существующего приложения в песочнице». Утилита bwrap для chroot-изации использует пространство имен MOUNT механизма namespaces.
По умолчанию bwrap создает для запускаемого процесса новый, абсолютно пустой каталог chroot-изации на временной файловой системе (tmpfs). Этот каталог не доступен для процессов вне песочницы и автоматически очищается при завершении работы.
За счет дополнительных параметров можно наполнить содержимым файловую систему песочницы — например, подключить туда целиком или частично основную файловую систему хоста.
Опция –ro-bind SRC DEST позволяет подключить хостовый путь SRC к точке монтирования DEST в песочнице. Например, команда
# bwrap --ro-bind / / bash
подключает в каталог chroot-изации всю иерархию каталогов хоста в режиме только для чтения и запускает в созданной таким образом песочнице командный интерпретатор.
# bwrap --ro-bind / / --bind /tmp /tmp --proc /proc --dev /dev bash
В данном случае мы разрешаем изолированному командному интерпретатору писать в каталог /tmp хостовой системы и формируем для него собственные devfs и procfs в соответствующих каталогах.
Естественно, вы можете и сформировать полностью свое собственное окружение аналогично тому, как мы это делали при рассмотрении системного вызова chroot().
# bwrap --bind ~/sanbox/ /
--ro-bind /etc/resolv.conf /etc/resolv.conf
--proc /proc --dev /dev bash
Предполагается, что по пути ~/sanbox/ создан chroot-каталог с необходимым содержимым — например, туда добавлены необходимые для работы командного интерпретатора динамические библиотеки. К сформированному каталогу мы добавили /etc/resolv.conf из хостовой системы и сформировали отдельные procfs и devfs для песочницы.
Изоляция других пространств имен
Кроме пространства MOUNT (каталог chroot-изации), которое позволяет сформировать изолированную иерархию каталогов для создаваемой песочницы, bwrap позволяет также изолировать и другие пространства имен.
Используя механизм namespaces (ссылка на статью «Обзор механизмов организации изолированных окружений в Linux»), bwrap позволяет выполнить изоляцию других пространств имен.
Пример: изолируем пространство имен пользователей, идентификаторов процессов и UTS, задавая при этом в песочнице идентификатор пользователя (для песочницы он таким образом является суперпользователем) и имя узла.
[egor@y520 ~]$ bwrap --ro-bind / / --dev /dev
--unshare-uts --unshare-pid --unshare-user
--uid 0 --hostname sss
bash
[root@sss ~]# id
uid=0(root) gid=500(egor) группы=500(egor),65534(nobody)
[root@sss ~]# hostname
sss
Обратите внимание, что в запущенном командном интерпретаторе мы действительно стали суперпользователем (UID=0), а также видим, что имя узла у нас поменялось.
При этом дерево процессов вне chroot выглядит примерно следующим образом
# ps af -o pid,uid,cmd
PID UID CMD
96311 500 /bin/bash
102755 0 _ su -
102761 0 _ -bash
103424 0 _ ps af -o pid,uid,cmd
91093 500 /bin/bash
103215 0 _ bwrap --ro-bind / / --dev /dev
103216 500 _ bwrap --ro-bind / / --dev /dev
103218 500 _ bash
8731 500 /bin/bash
3273 0 X -nolisten tcp :0 -seat seat0
То есть командный интерпретатор, который мы запустили в песочнице, в данном случае имеет идентификатор процесса 103218, как мы видели выше. В рамках песочницы он работает под учетной записью суперпользователя, а с точки зрения хостовой системы работает под учетной записью непривилегированного пользователя (UID=500).
То есть даже если код злоумышленника в песочнице может получить привилегии суперпользователя и найти способы выйти за пределы песочницы (а такая возможность существует, например, через специальные файлы устройств), то всё равно в основной системе он будет обычным пользователем и не сможет причинить существенный урон.
Также в bwrap есть возможность не создавать пространство имен с нуля, а использовать существующее (параметры –userns, –pidns и так далее) — например, созданное ранее для другой песочницы.
Завершение
Таким образом, мы рассмотрели инструмент bubblewrap, позволяющий достаточно гибко и эффективно описывать параметры создаваемых изолированных окружений.