#!/bin/sh
# 2018DECTMP
# Максимально близкий chroot. Т. е. chroot'имся так, чтобы расшарить с хостом максимальное число ресурсов, в отличие от systemd-nspawn, который, наоборот, стремится к максимальной изоляции. Цель в том, чтобы как можно больше вещей в chroot'е работало, например, X-клиенты. Вместе с тем любое добавление нужно вносить в скрипт только если оно требуется для какого-то из приложений, например, для запуска X-клиентов. Т. е. максимально близкий настолько, насколько это нужно, чтобы всё работало, но не ближе
# Любое действие делаем так, чтобы охватить как можно больше применений. Например, работоспособность X-клиентов, вероятно, можно было обеспечить копированием x authority в chroot. Но мы вместо этого делаем bind mount /tmp, т. к., возможно, это приведёт к тому, что заработает что-то ещё
# Делаем unshare, чтобы удаление каталога снаружи не привело к удалению чего либо, кроме самого каталога
# Информация: "sudo aplay" в X работает, т. к. sudo пробрасывает DISPLAY и XAUTHORITY
# Мы по максимуму избегаем bind-монтирования /dev, чтобы chroot не получил доступ к блочным устройствам
set -e
[ $# -lt 2 ] && echo "Usage: ${0##*/} [--no-chroot] DIR EXEC-CMD..." >&2 && exit 1
# Для отладки
if [ "$1" = "--no-chroot" ]; then
SHOULD_CHROOT=false
shift
else
SHOULD_CHROOT=true
fi
DIR="$1"
shift
exec unshare --mount sh -c '
set -e
SHOULD_CHROOT="$1"
shift
DIR="$1"
shift
mount --bind "$DIR" "$DIR" # Чтобы работал opam, он использует bwrap
mkdir -p "$DIR/proc"
umount -R "$DIR/proc" 2> /dev/null || :
mount --bind /proc "$DIR/proc" # Чтобы можно было получить доступ к файлам хоста с помощью /proc/1/root
mkdir -p "$DIR/tmp"
umount -R "$DIR/tmp" 2> /dev/null || :
mount --bind /tmp "$DIR/tmp" # Т. к. /tmp содержит XAUTHORITY
mkdir -p "$DIR/run"
umount -R "$DIR/run" 2> /dev/null || :
mount --rbind /run "$DIR/run" # Нужен для pulseaudio. Нужен именно rbind. Этот фрагмент добавлен при тестировании на X-сервере
mkdir -p "$DIR/etc"
: >> "$DIR/etc/machine-id"
umount "$DIR/etc/machine-id" 2> /dev/null || :
mount --bind /etc/machine-id "$DIR/etc/machine-id" # Нужен для pulseaudio. Этот фрагмент добавлен при тестировании на X-сервере
mkdir -p "$DIR/dev/pts"
umount -R "$DIR/dev/pts" 2> /dev/null || :
mount --bind /dev/pts "$DIR/dev/pts" # Нужен для xterm
mkdir -p "$DIR/dev/dri"
umount -R "$DIR/dev/dri" 2> /dev/null || :
mount --bind /dev/dri "$DIR/dev/dri" # Нужен для "ffmpeg -f kmsgrab". Этот фрагмент добавлен при тестировании на X-сервере
mkdir -p "$DIR/dev/shm"
umount -R "$DIR/dev/shm" 2> /dev/null || :
mount -t tmpfs tmpfs "$DIR/dev/shm" # Нужен, чтобы запустить Chromium от юзера. Этот фрагмент добавлен при тестировании на X-сервере
mkdir -p "$DIR/etc"
if [ -f /etc/resolv.conf ]; then # Если нет интернета, то файл может не резолвиться
rm -f "$DIR/etc/resolv.conf"
cp --dereference /etc/resolv.conf "$DIR/etc"
fi
if $SHOULD_CHROOT; then
exec chroot "$DIR" "$@"
else
exec "$@"
fi
' dummy-argv0 "$SHOULD_CHROOT" "$DIR" "$@"