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:
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]