mrrl-containers

MRRL version of container scripts
git clone https://ccx.te2000.cz/git/mrrl-containers
Log | Files | Refs

commit 40db72b1aa35e90b6923e905095f3da6b7cf7b0b
parent a8bba2bd4a388d24d10aff7d97b0a66e8cf6fb54
Author: ccx <ccx@te2000.cz>
Date:   Mon, 18 Mar 2024 14:01:29 +0000

Refactor ns_run into several discrete commands

Diffstat:
Asbin/ns_run_mount_dev | 40++++++++++++++++++++++++++++++++++++++++
Asbin/ns_run_mounts | 11+++++++++++
Asbin/ns_run_unshared | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mservice_scripts/xorg/run | 35+++++++++++++++--------------------
Mzsh-functions/confz_containers_init | 6+++---
5 files changed, 171 insertions(+), 23 deletions(-)

diff --git a/sbin/ns_run_mount_dev b/sbin/ns_run_mount_dev @@ -0,0 +1,40 @@ +#!/command/execlineb -S1 + +# /dev +if { s6-mount -nwt tmpfs -o nosuid,dev,mode=0755 dev $1 } +if { mknod -m 666 ${1}/null c 1 3 } +if { mknod -m 666 ${1}/full c 1 7 } +if { mknod -m 666 ${1}/ptmx c 5 2 } +if { mknod -m 644 ${1}/random c 1 8 } +if { mknod -m 644 ${1}/urandom c 1 9 } +if { mknod -m 666 ${1}/zero c 1 5 } +if { mknod -m 666 ${1}/tty c 5 0 } +if { s6-ln -sf /proc/self/fd ${1}/fd } +if { s6-ln -sf /proc/self/fd/0 ${1}/stdin } +if { s6-ln -sf /proc/self/fd/1 ${1}/stout } +if { s6-ln -sf /proc/self/fd/2 ${1}/stderr } + +# dev/shm is handled via /run synlink +# pts and mqueue are provided below +# also have some convenience dirs in place for optionally bind-mounting them +if { + mkdir + + ${1}/pts + ${1}/mqueue + + ${1}/block + ${1}/bus + ${1}/char + ${1}/dri + ${1}/input + ${1}/loop + ${1}/net + ${1}/snd + ${1}/usb + +} +if { mount -t devpts devpts ${1}/pts } +#if { s6-mount -nwt tmpfs -o nosuid,nodev,mode=1777 shm ${1}/shm } +if { s6-ln -sf ../run/shm ${1}/shm } +if { s6-mount -nwt mqueue -o nosuid,nodev,noexec mqueue ${1}/mqueue } diff --git a/sbin/ns_run_mounts b/sbin/ns_run_mounts @@ -0,0 +1,11 @@ +#!/command/execlineb -S1 + +# /proc +if { mount -t proc proc ${1}/proc } + +# /dev +if { ns_run_mount_dev ${1}/dev } + +# /dev/shm -> /run/shm +if { mkdir ${1}/run/shm } +if { chmod 1777 ${1}/run/shm } diff --git a/sbin/ns_run_unshared b/sbin/ns_run_unshared @@ -0,0 +1,102 @@ +#!/command/execlineb -s1 + +## usage: ns_run <root_directory> <executable> [<arg1> ...] +## +## Creates isolated namespace/container with given root and runs given +## executable in it. +## +## Environment variables used: +## HOST - hostname to set +## NS_ROOT - where to bind-mount the root directory +## NS_EXTRA - extra execline script to run after setting up the namespaces +## and mounting essential filesystems but before entering it +## and unmounting host filesystem +## NS_FSTAB - file with extra mounts to perform after running above script +## NS_TMPFS - place to store binaries in the container that are run +## before dropping privs, relative path from new root +## NS_BIN - directory to get said binaries from; currently needs: +## - `if` from execline +## - busybox with `umount` and `chpst` functions +## - anything you wish to call before and for dropping privs, +## eg. s6-applyuidgid +## All statically linked of course. +## NS_NO_PID1 - Allow not running as init process of the namespace. + +# import variables from environment, with defaults +multisubstitute { + importas -D container HOST HOST + importas -D /mnt/chroot NS_ROOT NS_ROOT + importas -D mnt/ns NS_TMPFS NS_TMPFS + importas -D /mnt/volumes/containers/bin NS_BIN NS_BIN +} + +# check we are PID1 (in a new PID namespace) +getpid PID +ifelse { + importas -D "" NS_NO_PID1 NS_NO_PID1 + importas -i PID PID + test -z ${NS_NO_PID1} -a 1 -ne $PID +} { + fdmove -c 1 2 + foreground { echo "ns_run: fatal: not PID 1" } + exit 111 +} +unexport PID + + +foreground { importas -i HOST HOST hostname $HOST } + +# We will generate final script we will exec into to enter the container. +# We need to generate it before we start mounting anything, +# so only the mountpoints that exist at this point will get unmounted and +# everything we will mount below will stay. +backtick -i NS_FINAL_SCRIPT { + # Generate execline script that performs pivot_root + # and umounts all the filesystems not used by the container + # formerly: /root/ns_execline.zsh $@ + + if { + printf "%s\n" + "if { pivot_root . \${NS_TMPFS}/oldroot }" + } + if { + ns_umount_script.awk + -vROOT=/${NS_TMPFS}/oldroot + -vBIN=/${NS_TMPFS}/bin + /proc/self/mountinfo + } + if { printf "%s\n" "./${NS_TMPFS}/bin/busybox chpst -/ ." "\$@" } +} + +# mount and enter the chroot directory +if { mount -o rbind $1 $NS_ROOT } +cd $NS_ROOT + +ns_run_mounts . + +# mountpoint for privileged operations and pivot_root +if { s6-mount -nwt tmpfs -o nosuid,nodev,mode=700 mnt_ns $NS_TMPFS } +if { mkdir ${NS_TMPFS}/oldroot ${NS_TMPFS}/bin } +#if { s6-hiercopy $NS_BIN ${NS_TMPFS}/bin } +if { s6-mount -n -o bind,ro $NS_BIN ${NS_TMPFS}/bin } + +# container-specific setup +if { runblock -n 1 1 } + +# optional fstab file for extra mounts +if { + if -t { eltest -v NS_FSTAB } + importas -i NS_FSTAB NS_FSTAB + mount -a -T $NS_FSTAB +} +unexport NS_FSTAB + +# now we can make /dev immutable +if { mount -o remount,ro dev } + +# exec into the script we generated above, it: +# * does pivot_root to change rootdir +# * umounts all undesired filesystems +# * execs into $@ +importas -i -u NS_FINAL_SCRIPT NS_FINAL_SCRIPT +runblock -r -n 1 1 emptyenv -c execlineb -S0 -c $NS_FINAL_SCRIPT $@ diff --git a/service_scripts/xorg/run b/service_scripts/xorg/run @@ -42,38 +42,33 @@ if { chown ${CONTAINER_USER}:${CONTAINER_USER} ${CONTAINER_TMPFS}${XDG_RUNTIME_D # if { redirfd -w 1 ${CONTAINER_TMPFS}/run/resolv.conf printf "nameserver 127.0.0.1\n" } # if { chown ${CONTAINER_USER}:${CONTAINER_USER} ${CONTAINER_TMPFS}/run/resolv.conf } -backtick -i FSTAB_FILE { realpath data/fstab } - -# Put UID/GID/GIDLIST into environment for use by s6-applyuidgid below +# Put UID/GID/GIDLIST into environment for use by applyuidgid-caps below s6-envuidgid ${CONTAINER_USER} -env - HOST=${CONTAINER_NAME} - #RUN_CHOWN=${UID}:${GID} - NS_EXTRA=" - if { mount -a -T ${FSTAB_FILE} } +export HOST ${CONTAINER_NAME} + +emptyenv -c +unshare -m -u -i # new mount, UTS and IPC namespaces +ns_run_unshared data/root { + # pre pivot-root commands if { mount -o bind,ro /etc/passwd ./etc/passwd } if { mount -o bind,ro /etc/group ./etc/group } if { mount -o bind /dev/input ./dev/input } if { cp -a /dev/tty${vtN} ./dev/tty${vtN} } if { chmod 660 ./dev/tty${vtN} } if { chown root:xorg ./dev/tty${vtN} } -" - -emptyenv -c -ns_run data/root +} +# This runs with changed / so use absolute paths before dropping privs /mnt/ns/current/command/applyuidgid-caps -U "" env HOME=${CONTAINER_USER_HOME} USER=${CONTAINER_USER} - -s6-setsid -s6-envuidgid xorg applyuidgid-caps -U "" +# s6-setsid if { - pipeline { - if { printf "add :%d . " ${vtN} } - if { redirfd -r 0 /dev/urandom xxd -p -l 16 } - } - xauth -f ${XDG_RUNTIME_DIR}/Xauthority source - + pipeline { + if { printf "add :%d . " ${vtN} } + if { redirfd -r 0 /dev/urandom xxd -p -l 16 } + } + xauth -f ${XDG_RUNTIME_DIR}/Xauthority source - } Xorg diff --git a/zsh-functions/confz_containers_init b/zsh-functions/confz_containers_init @@ -497,7 +497,7 @@ confz_container_service_xorg_check() { require fs_d filename=$container_user_dir/root - fstab=( + fstab_post=( $vars[containers_dir]/systems/$vars[image_name]$'\t'$container_user_dir/root$'\tnone\tbind,ro,nosuid,nodev\t0 0' /run/containers/$container.$vars[user]/run$'\t'$container_user_dir/root/run$'\tnone\tbind,nosuid,nodev\t0 0' /run/containers/$container.$vars[user]/tmp$'\t'$container_user_dir/root/tmp$'\tnone\tbind,nosuid,nodev\t0 0' @@ -509,8 +509,8 @@ confz_container_service_xorg_check() { svc_dir=$svc_dir control_user=0 control_group=0 \ log_dir=/run/container-logs/$container \ log_uid=0 log_gid=0 \ - root_link=$container_user_dir/root \ - fstab=${(F)fstab} \?down \?fstab_post + root_link=$vars[containers_dir]/systems/$vars[image_name] \ + fstab_post=${(F)fstab_post} \?down \?fstab require fs_d filename=$svc_dir/env require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \ content=$vars[user]