#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-3.0-or-later
# Caller must already be in private mount/PID namespaces.
# A plain chroot makes CLONE_NEWUSER fail with EPERM inside sbuild.
set -euo pipefail
(( EUID == 0 )) || exit 1
root_dir=${1:?}
work_dir=${2:?}
account=${3:?}
shift 3
[[ $account == root || $account == builder ]]
[[ -f $root_dir/etc/debian_version && -d $work_dir ]]
[[ ! -L $root_dir && ! -L $root_dir/etc/resolv.conf ]]
[[ $(readlink /proc/self/ns/mnt) != $(readlink /proc/1/ns/mnt) ]] || {
    echo 'enter-root requires the private mount namespace created by its wrapper.' >&2
    exit 1
}
mount --make-rprivate /
mount --bind "$root_dir" "$root_dir"
mkdir -p "$root_dir"/{proc,sys,dev,run,tmp,work}
mount -t proc -o nosuid,nodev,noexec proc "$root_dir/proc"
mount -t sysfs -o ro,nosuid,nodev,noexec sysfs "$root_dir/sys"
mount -t tmpfs -o mode=755,nosuid tmpfs "$root_dir/dev"
for device in null zero full random urandom tty; do
    touch "$root_dir/dev/$device"
    mount --bind "/dev/$device" "$root_dir/dev/$device"
done
mkdir -p "$root_dir/dev/pts" "$root_dir/dev/shm"
mount -t devpts -o newinstance,ptmxmode=0666,mode=0620 devpts "$root_dir/dev/pts"
mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs "$root_dir/dev/shm"
ln -s pts/ptmx "$root_dir/dev/ptmx"
ln -s /proc/self/fd "$root_dir/dev/fd"
ln -s /proc/self/fd/0 "$root_dir/dev/stdin"
ln -s /proc/self/fd/1 "$root_dir/dev/stdout"
ln -s /proc/self/fd/2 "$root_dir/dev/stderr"
mount -t tmpfs -o mode=755,nosuid,nodev tmpfs "$root_dir/run"
mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs "$root_dir/tmp"
mount --bind "$work_dir" "$root_dir/work"
cat /etc/resolv.conf > "$root_dir/etc/resolv.conf"
mkdir "$root_dir/run/.old-root"
cd "$root_dir"
pivot_root . run/.old-root
cd /
umount --lazy /run/.old-root
rmdir /run/.old-root
user_home=/home/builder
[[ $account != root ]] || user_home=/root
command=(/usr/bin/env -i HOME="$user_home" USER="$account" LOGNAME="$account"
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    LANG=C.UTF-8 LC_ALL=C.UTF-8 TERM="${TERM:-dumb}"
    /bin/bash --noprofile --norc -c 'cd /work; exec "$@"' bash "$@")
if [[ $account == root ]]; then
    exec "${command[@]}"
else
    exec setpriv --reuid=builder --regid=builder --init-groups "${command[@]}"
fi
