ptrcports/root-enter/enter

135 lines
3.2 KiB
Bash
Executable file

#!/bin/sh
set -eu
USERNAME="${USERNAME:-$(id -u -n)}"
UNSHARE_CMD="${UNSHARE_CMD:-unshare}"
# make sure we're root
if [ "$(id -u)" != 0 ]; then
sucmd="su -c"
if command -v doas >/dev/null; then
sucmd="doas"
elif command -v sudo >/dev/null; then
sucmd="sudo"
fi
exec $sucmd \
env \
HOME="$HOME" \
USERNAME="$USERNAME" \
UNSHARE_CMD="$UNSHARE_CMD" \
WAYLAND_DISPLAY="$WAYLAND_DISPLAY" \
DISPLAY="$DISPLAY" \
XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \
DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
"$0" "$@"
fi
# and make sure we're in a separate mount namespace
if [ "$(readlink /proc/$$/ns/mnt | cut -d: -f2)" = "$(readlink /proc/1/ns/mnt | cut -d: -f2)" ]; then
exec $UNSHARE_CMD --keep-caps -m "$0" "$@"
fi
bindpoints="/etc/resolv.conf"
command=""
user="$USERNAME"
while getopts "bde:u:c:" opt; do
case $opt in
'b') bindpoints="
$bindpoints
/var/cache/distfiles
$HOME/aports
$HOME/packages
$HOME/.abuild
" ;;
'd') bindpoints="
$bindpoints
$XDG_RUNTIME_DIR
/tmp
" ;;
'e') bindpoints="$bindpoints $OPTARG" ;;
'u') user="$OPTARG" ;;
'c') command="$OPTARG" ;;
*) echo "unknown $opt" ;;
esac
done
shift $(( $OPTIND - 1 ))
dest="$1"
shift
if [ ! -d "$dest" ]; then
echo "no such directory: $dest"
exit 1
fi
if ! [ -x "$dest"/bin/sh -o -L "$dest"/bin/sh ]; then
echo "$dest does not contain executable /bin/sh"
exit 1
fi
# do stupid path fixup
export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"
mount -t proc proc "$dest"/proc
mount -t sysfs sysfs "$dest"/sys
mount -t tmpfs tmpfs "$dest"/tmp
# some mini kernels don't have devtmpfs
if grep -q devtmpfs /proc/filesystems; then
mount -t devtmpfs devtmpfs "$dest"/dev
else
mount -t tmpfs tmpfs "$dest"/dev
if [ -x "$dest"/sbin/mdev -o -L "$dest"/sbin/mdev ]; then
echo "devtmpfs not supported - running 'mdev -s' instead"
chroot "$dest" /sbin/mdev -sv
else
echo "devtmpfs not supported - devices need to be created manually"
fi
fi
mkdir -p "$dest"/dev/pts "$dest"/dev/shm
mount -t devpts devpts "$dest"/dev/pts
mount -t tmpfs tmpfs "$dest"/dev/shm
# workaround for shitty android-based stuff
if ! [ -f /etc/resolv.conf ]; then
# remove /etc/resolv.conf from bindpoints
bindpoints="${bindpoints#/etc/resolv.conf}"
fi
for bindpoint in $bindpoints; do
if [ -f "$bindpoint" ]; then
touch "$dest"/"$bindpoint"
else
mkdir -p "$dest"/"$bindpoint"
fi
mount -o bind "$bindpoint" "$dest"/"$bindpoint"
done
# if running on chromeos, fixup symlink exec
# https://goo.gl/8xICW6
# https://github.com/dnschneid/crouton/commit/5cb7ad05
if [ -e "/run/chrome" ]; then
if mount -n -t securityfs -o nodev,noexec,nosuid securityfs /sys/kernel/security; then
policies=/sys/kernel/security/chromiumos/inode_security_policies
if [ -d "$policies" ]; then
for policy in "$policies/allow_"*; do
printf "$(realpath "$dest")" > "$policy"
done
fi
umount /sys/kernel/security
fi
fi
mount -o bind "$dest" /mnt
pivot_root /mnt /mnt/mnt
if [ "$command" ]; then
exec su $user -c "$command"
elif [ "$#" -gt 0 ]; then
exec su $user -c "$*"
else
exec login -p -f $user
fi