untitled paste

unlisted ⁨1⁩ ⁨file⁩ 2023-03-26 14:46:30 UTC

my-chroot

Raw
#!/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" "$@"