Last active
August 7, 2023 06:35
-
-
Save agrif/bc20474136a99ddaf627166f6178feca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
# this is mostly copied from arch-chroot | |
BASE="$(realpath $(dirname "$0"))" | |
LFS="$BASE/root" | |
die() { | |
printf "ERROR: " | |
echo "$@" | |
exit 1 | |
} | |
add_mount() { | |
mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}") | |
} | |
add_mount_lazy() { | |
mount "$@" && CHROOT_ACTIVE_LAZY=("$2" "${CHROOT_ACTIVE_LAZY[@]}") | |
} | |
bind_device() { | |
touch "$2" && CHROOT_ACTIVE_FILES=("$2" "${CHROOT_ACTIVE_FILES[@]}") | |
add_mount "$1" "$2" --bind | |
} | |
add_link() { | |
ln -sf "$1" "$2" && CHROOT_ACTIVE_FILES=("$2" "${CHROOT_ACTIVE_FILES[@]}") | |
} | |
pid_unshare="unshare --fork --pid" | |
mount_unshare="$pid_unshare --mount --map-auto --map-root-user --setuid 0 --setgid 0" | |
setup() { | |
CHROOT_ACTIVE_MOUNTS=() | |
CHROOT_ACTIVE_LAZY=() | |
CHROOT_ACTIVE_FILES=() | |
[[ $(trap -p EXIT) ]] && die cannot set EXIT trap | |
trap 'cleanup' EXIT | |
add_mount_lazy "$1" "$1" --bind | |
add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev | |
add_mount_lazy /sys "$1/sys" --rbind | |
add_link "/proc/self/fd" "$1/dev/fd" | |
add_link "/proc/self/fd/0" "$1/dev/stdin" | |
add_link "/proc/self/fd/1" "$1/dev/stdout" | |
add_link "/proc/self/fd/2" "$1/dev/stderr" | |
bind_device /dev/full "$1/dev/full" | |
bind_device /dev/null "$1/dev/null" | |
bind_device /dev/random "$1/dev/random" | |
bind_device /dev/tty "$1/dev/tty" | |
bind_device /dev/urandom "$1/dev/urandom" | |
bind_device /dev/zero "$1/dev/zero" | |
add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 | |
add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid | |
add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev | |
add_mount "$BASE/sources" "$1/sources" --bind | |
add_mount "$BASE/packages" "$1/packages" --bind | |
add_mount "$BASE/pkgspecs" "$1/pkgspecs" --bind | |
} | |
cleanup() { | |
if (( ${#CHROOT_ACTIVE_MOUNTS[@]} )); then | |
umount "${CHROOT_ACTIVE_MOUNTS[@]}" | |
fi | |
unset CHROOT_ACTIVE_MOUNTS | |
if (( ${#CHROOT_ACTIVE_LAZY[@]} )); then | |
umount --lazy "${CHROOT_ACTIVE_LAZY[@]}" | |
fi | |
unset CHROOT_ACTIVE_LAZY | |
if (( ${#CHROOT_ACTIVE_FILES[@]} )); then | |
rm "${CHROOT_ACTIVE_FILES[@]}" | |
fi | |
unset CHROOT_ACTIVE_FILES | |
} | |
declare_all() { | |
declare -p | grep -Fvf <(declare -rp) | |
declare -pf | |
} | |
do_chroot() { | |
(( EUID == 0 )) || die do_chroot must be run as root | |
[[ -d $chrootdir ]] || die path $chrootdir is not a directory | |
setup "$chrootdir" | |
chroot_args=() | |
[[ $userspec ]] && chroot_args+=(--userspec "$userspec") | |
user=$(echo "$userspec" | cut -d: -f1) | |
[[ "$user" ]] || user="root" | |
# FIXME uids don't work here | |
if [[ "$user" == "root" ]]; then | |
homedir="/root" | |
else | |
homedir="/home/$user" | |
fi | |
$pid_unshare /sbin/chroot "${chroot_args[@]}" -- "$chrootdir" /usr/bin/env -i HOME="$homedir" TERM="$TERM" PS1='(lfs chroot) \u:\w\$ ' PATH=/usr/bin:/usr/sbin "${args[@]}" | |
} | |
while getopts ':hu:' flag; do | |
case $flag in | |
h) | |
cat <<EOF | |
usage: $(basename "$0") [newroot] [command ...] | |
-h Print this help message | |
-u <user>[:group] Specify non-root user and optional group to use | |
If 'command' is unspecified, $(basename "$0") will launch /bin/bash. | |
If 'newroot' is unspecified, chroot.sh will use: | |
$LFS | |
EOF | |
exit 0 | |
;; | |
u) | |
userspec=$OPTARG | |
;; | |
:) | |
die option requires an argument -- $OPTARG | |
;; | |
?) | |
die invalid option -- $OPTARG | |
;; | |
esac | |
done | |
shift $(( OPTIND - 1 )) | |
chrootdir="$LFS" | |
(( $# )) && chrootdir=$1 && shift | |
args=("/bin/bash" "--login" "+h") | |
[[ "$@" ]] && args=("$@") | |
$mount_unshare bash -c "$(declare_all); do_chroot" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment