commit 00055f0322d33a0c18902daf71202ded2cf82c1f
parent 2250aae515a3b4b1f777e637853435b5e9f09ab7
Author: Jan Pobříslo <ccx@te2000.cz>
Date: Thu, 16 Dec 2021 13:27:55 +0000
scripts to run in the sysroot container directly without going through s6 services
Diffstat:
5 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/sbin/container_sysroot_run b/sbin/container_sysroot_run
@@ -0,0 +1,43 @@
+#!/command/execlineb -s0
+s6-envdir env
+multisubstitute {
+ importas -i -u CONTAINER_NAME CONTAINER_NAME
+ importas -i -u CONTAINER_USER CONTAINER_USER
+}
+backtick -in CONTAINER_USER_HOME { homeof $CONTAINER_USER }
+multisubstitute {
+ importas -i -u CONTAINER_USER_HOME CONTAINER_USER_HOME
+ define CONTAINER_TMPFS /run/containers/${CONTAINER_NAME}.sysroot
+ define -s tmpfs_dirs "home run tmp inbox run/inbox tmp/.X11-unix"
+}
+
+getpid NS_PID
+foreground {
+ importas -i NS_PID NS_PID
+ if { test -d /run/cgroup2 }
+ if { mkdir -p /run/cgroup2/containers/${CONTAINER_USER}/${CONTAINER_NAME} }
+ redirfd -w 1 /run/cgroup2/containers/${CONTAINER_USER}/${CONTAINER_NAME}/cgroup.procs
+ printf "%s" ${NS_PID}
+}
+
+if { touch ${CONTAINER_TMPFS}.lockfile }
+s6-setlock -n ${CONTAINER_TMPFS}.lockfile
+if { rm -rf ${CONTAINER_TMPFS} }
+if { mkdir -p ${CONTAINER_TMPFS}/${tmpfs_dirs} }
+if { chmod 1770 ${CONTAINER_TMPFS}/${tmpfs_dirs} }
+if { chown root:${CONTAINER_USER} ${CONTAINER_TMPFS}/${tmpfs_dirs} }
+if { mount -a --fstab data/fstab }
+
+# Put UID/GID/GIDLIST into environment for use by s6-applyuidgid below
+s6-envuidgid ${CONTAINER_USER}
+
+#env
+# NS_EXTRA="if { mount -o bind,ro /etc/passwd etc/passwd } if { mount -o bind,ro /etc/group etc/group }"
+
+emptyenv -c
+pidns_run
+ns_run data/root
+/mnt/ns/bin/s6-applyuidgid -U
+env HOME=/root
+$@
+
diff --git a/sbin/pidns_run b/sbin/pidns_run
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+import sys
+import os
+import os.path
+import ctypes
+import fcntl
+
+libc = ctypes.CDLL(None, use_errno=True)
+CLONE_NEWPID = 0x20000000
+
+
+def nonblock_cloexec(fd):
+ fcntl.fcntl(
+ fd,
+ fcntl.F_SETFD,
+ fcntl.fcntl(fd, fcntl.F_GETFD) | os.O_NONBLOCK | fcntl.FD_CLOEXEC,
+ )
+
+
+def exit_status(status):
+ sig = status & 0xff
+ ret = status >> 8
+ if sig:
+ raise SystemExit(128 + sig)
+ if ret >= 128
+ raise SystemExit(128)
+ raise SystemExit(ret)
+
+
+def main(argv):
+ (parent_rfd, parent_wfd) = os.pipe()
+ nonblock_cloexec(read_fd)
+ nonblock_cloexec(write_fd)
+ if libc.unshare(CLONE_NEWPID) != 0:
+ raise OSError(ctypes.get_errno())
+ fork_pid = os.fork()
+ if fork_pid:
+ # child
+ os.close(parent_wfd)
+ fork2_pid = os.fork()
+ if fork2_pid:
+ # child
+ if argv[1][0] == '/':
+ os.execve(argv[1], argv[1:])
+ for d in os.environ['PATH'].split(':'):
+ try:
+ os.execv(os.path.join(d, argv[1]), argv[1:])
+ except FileNotFoundError:
+ continue
+ raise SystemExit(127)
+ else:
+ # parent
+ rlist, wlist, elist = (parent_rfd), (), ()
+ while True:
+ (pid, status) = os.waitpid(0, os.WNOHANG)
+ if pid:
+ exit_status(status)
+ try:
+ r, w, x = select.select(rlist, wlist, elist, timeout=1.0)
+ except select.error as e:
+ code, msg = e.args
+ # We might get interrupted by SIGCHLD here
+ if code != errno.EINTR:
+ raise
+ else:
+ # parent
+ os.close(parent_rfd)
+ (pid, status) = os.waitpid(fork_pid)
+ exit_status(status)
+
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/service_scripts/sysroot/run b/service_scripts/sysroot/run
@@ -1,4 +1,4 @@
-#!/command/execlineb
+#!/command/execlineb -P
s6-envdir env
multisubstitute {
importas -i -u CONTAINER_NAME CONTAINER_NAME
@@ -20,6 +20,8 @@ foreground {
printf "%s" ${NS_PID}
}
+if { touch ${CONTAINER_TMPFS}.lockfile }
+s6-setlock -n ${CONTAINER_TMPFS}.lockfile
if { rm -rf ${CONTAINER_TMPFS} }
if { mkdir -p ${CONTAINER_TMPFS}/${tmpfs_dirs} }
if { chmod 1770 ${CONTAINER_TMPFS}/${tmpfs_dirs} }
diff --git a/zsh-functions/confz_containers_init b/zsh-functions/confz_containers_init
@@ -756,6 +756,29 @@ confz_container_alpine_image_check() {
root=$root user=container-$vars[image_name]
}
+confz_container_alpine_packages_installed_check() {
+ checkvars containers_dir image_name packages svscan_dir
+
+ local root=$vars[containers_dir]/systems/$vars[image_name]
+ local -a world=( "${(@f)$(<$root/etc/apk/world)}" )
+ local -a missing
+ local pkg
+
+ for pkg in $=vars[packages]; do
+ (( $world[(I)${pkg}] )) || missing+=( $pkg )
+ done
+
+ unify to_install "${(F)missing}"
+
+ do_command=(
+ cd $vars[svscan_dir]/container.$vars[image_name].sysroot
+ container_sysroot_run
+ apk add $missing
+ )
+
+ (( $#missing ))
+}
+
# --- Void ---
confz_container_void_base_files_check() {
diff --git a/zsh-functions/confz_site_containers_init b/zsh-functions/confz_site_containers_init
@@ -43,8 +43,20 @@ confz_site_container_services_check() {
confz_site_container_images_check() {
defvar containers_dir /mnt/volumes/containers
+ defvar svscan_dir /run/service
+ local -a alpine_core=(
+ abduco
+ s6
+ s6-{rc,linux-utils,portable-utils}
+ execline
+ ncurses-terminfo
+ rxvt-unicode-terminfo
+ zsh
+ )
require container_alpine_image :containers_dir arch=x86_64 \
image_name=alpine-sndio
+ require container_alpine_packages_installed :containers_dir :svscan_dir \
+ image_name=alpine-sndio packages="$alpine_core"
require container_void_image :containers_dir arch=x86_64-musl \
repository=current/musl image_name=void-browsers
}