commit 268faa95dd5b1470643e69dd575b8b121a5bd5df
parent 7fbfb934cdaa187a063a4df41498c06c46d4a6a9
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Mon, 8 Dec 2025 04:14:21 +0000
Provide alternatives for creating chroot (tmpfs, bind-mount)
Diffstat:
5 files changed, 133 insertions(+), 73 deletions(-)
diff --git a/README b/README
@@ -138,24 +138,52 @@ Options:
left in the root directory.
* Finally it executes into <prog>.
-lns-mount-chroot
-~~~~~~~~~~~~~~~~
-Execline script to prepare new root, usually to be run in freshly created mount
-namespace.
+lns-prepare-chroot
+~~~~~~~~~~~~~~~~~~
+Populate necessary directories and device nodes in new root.
-Usage:
-> lns-mount-chroot chroot_dir { prog1... } prog2...
+> lns-prepare-chroot chroot_dir
-`lns-mount-chroot` performs these steps in sequence:
-* runs `lns-mount-to-env` to record existing mountpoints to be unmounted by `lns-lockdown`
-* bind-mounts <image_root> onto $LNS_ROOT (defaults to /mnt/chroot)
* mounts proc filesystem
* mounts tmpfs at $LNS_ROOT/dev, devpts on dev/pts and mqueue on dev/mqueue
* creates device nodes for null, full, random, urandom, zero, tty and ptmx
* creates `/proc/self/fd` symlinks for stdin, stdout and stderr
+
+
+lns-bind-chroot
+~~~~~~~~~~~~~~~
+
+Execline script to prepare new root by mounting existing directory as a base.
+Usually to be run in freshly created mount namespace.
+
+Usage:
+> lns-bind-chroot image_root { prog1... } prog2...
+
+`lns-bind-chroot` performs these steps in sequence:
+* runs `lns-mount-to-env` to record existing mountpoints to be unmounted by `lns-lockdown`
+* bind-mounts <image_root> onto $LNS_ROOT (defaults to /mnt/chroot)
+* runs `lns-prepare-chroot` on $LNS_ROOT
* runs <prog1> which can do further modifications to $LNS_ROOT/dev
* remounts $LNS_ROOT/dev read-only
* executes into <prog2>
+lns-tmpfs-chroot
+~~~~~~~~~~~~~~~~
+
+Execline script to prepare new root by mounting empty tmpfs.
+Usually to be run in freshly created mount namespace.
+
+Usage:
+> lns-tmpfs-chroot chroot_dir { prog1... } prog2...
+
+`lns-tmpfs-chroot` performs these steps in sequence:
+* runs `lns-mount-to-env` to record existing mountpoints to be unmounted by `lns-lockdown`
+* mounts empty tmpfs on top of <chroot_dir>
+* runs `lns-prepare-chroot` on <chroot_dir>
+* runs <prog1> which can do further modifications to <chroot_dir>/dev
+* remounts <chroot_dir>/dev read-only
+* executes into <prog2>
+
+
diff --git a/src/lns-bind-chroot.in b/src/lns-bind-chroot.in
@@ -0,0 +1,27 @@
+#!shebang:execlineb -S1
+
+elquote:multisubstitute {
+ elquote:importas -i 1 1 # require first argument
+ elquote:importas -D /mnt/chroot LNS_ROOT LNS_ROOT
+}
+elquote:shift -n 1 # remove first argument so we don't have to deal with it with runblock
+
+# snapshot current mountpoints for later umount (anything past this point stays)
+elquote:lns-mounts-to-env
+
+elquote:if { elquote:mount -o rbind $1 $LNS_ROOT }
+
+# mount /dev and /proc
+elquote:if { elquote:lns-prepare-chroot $LNS_ROOT }
+
+# run
+elquote:if {
+ elquote:cd $LNS_ROOT
+ elquote:runblock 1
+}
+
+# now we can make /dev immutable
+elquote:if { elquote:mount -o remount,ro ${LNS_ROOT}/dev }
+
+# chainload into the rest of the argv
+elquote:runblock -r 1
diff --git a/src/lns-mount-chroot.in b/src/lns-mount-chroot.in
@@ -1,64 +0,0 @@
-#!shebang:execlineb -S1
-
-elquote:multisubstitute {
- elquote:importas -i 1 1 # require first argument
- elquote:importas -D /mnt/chroot LNS_ROOT LNS_ROOT
-}
-elquote:shift -n 1 # remove first argument so we don't have to deal with it with runblock
-
-elquote:lns-mounts-to-env
-
-elquote:if { elquote:mount -o rbind $1 $LNS_ROOT }
-
-# /proc
-elquote:if { elquote:mount -t proc proc ${LNS_ROOT}/proc }
-
-# /dev
-elquote:if { elquote:mount -wt tmpfs -o nosuid,dev,mode=0755 dev ${LNS_ROOT}/dev }
-# Create top-level /dev directories. Many may be bind-mounted from host if needed.
-elquote:if {
- elquote:mkdir
-
- ${LNS_ROOT}/dev/pts
- ${LNS_ROOT}/dev/mqueue
- # dev/shm is intentionally ommited to allow custom mount or symlink
-
- ${LNS_ROOT}/dev/block
- ${LNS_ROOT}/dev/bus
- ${LNS_ROOT}/dev/bus/usb
- ${LNS_ROOT}/dev/char
- ${LNS_ROOT}/dev/dri
- ${LNS_ROOT}/dev/input
- ${LNS_ROOT}/dev/loop
- ${LNS_ROOT}/dev/net
- ${LNS_ROOT}/dev/snd
- ${LNS_ROOT}/dev/usb
-
-}
-elquote:if { elquote:mount -wt devpts devpts ${LNS_ROOT}/dev/pts }
-elquote:if { elquote:mount -wt mqueue -o nosuid,nodev,noexec mqueue ${LNS_ROOT}/dev/mqueue }
-
-elquote:if { elquote:mknod -m 666 ${LNS_ROOT}/dev/null c 1 3 }
-elquote:if { elquote:mknod -m 666 ${LNS_ROOT}/dev/full c 1 7 }
-elquote:if { elquote:mknod -m 666 ${LNS_ROOT}/dev/ptmx c 5 2 }
-elquote:if { elquote:mknod -m 644 ${LNS_ROOT}/dev/random c 1 8 }
-elquote:if { elquote:mknod -m 644 ${LNS_ROOT}/dev/urandom c 1 9 }
-elquote:if { elquote:mknod -m 666 ${LNS_ROOT}/dev/zero c 1 5 }
-elquote:if { elquote:mknod -m 666 ${LNS_ROOT}/dev/tty c 5 0 }
-elquote:if { elquote:ln -sf /proc/self/fd ${LNS_ROOT}/dev/fd }
-elquote:if { elquote:ln -sf /proc/self/fd/0 ${LNS_ROOT}/dev/stdin }
-elquote:if { elquote:ln -sf /proc/self/fd/1 ${LNS_ROOT}/dev/stout }
-elquote:if { elquote:ln -sf /proc/self/fd/2 ${LNS_ROOT}/dev/stderr }
-
-
-# run
-elquote:if {
- elquote:cd $LNS_ROOT
- elquote:runblock 1
-}
-
-# now we can make /dev immutable
-elquote:if { elquote:mount -o remount,ro ${LNS_ROOT}/dev }
-
-# chainload into the rest of the argv
-elquote:runblock -r 1
diff --git a/src/lns-prepare-chroot.in b/src/lns-prepare-chroot.in
@@ -0,0 +1,43 @@
+#!shebang:execlineb -s1
+
+elquote:if { elquote:mkdir -p ${1}/proc ${1}/dev }
+
+# /proc
+elquote:if { elquote:mount -t proc proc ${1}/proc }
+
+# /dev
+elquote:if { elquote:mount -wt tmpfs -o nosuid,dev,mode=0755 dev ${1}/dev }
+# Create top-level /dev directories. Many may be bind-mounted from host if needed.
+elquote:if {
+ elquote:mkdir
+
+ ${1}/dev/pts
+ ${1}/dev/mqueue
+ # dev/shm is intentionally ommited to allow custom mount or symlink
+
+ ${1}/dev/block
+ ${1}/dev/bus
+ ${1}/dev/bus/usb
+ ${1}/dev/char
+ ${1}/dev/dri
+ ${1}/dev/input
+ ${1}/dev/loop
+ ${1}/dev/net
+ ${1}/dev/snd
+ ${1}/dev/usb
+
+}
+elquote:if { elquote:mount -wt devpts devpts ${1}/dev/pts }
+elquote:if { elquote:mount -wt mqueue -o nosuid,nodev,noexec mqueue ${1}/dev/mqueue }
+
+elquote:if { elquote:mknod -m 666 ${1}/dev/null c 1 3 }
+elquote:if { elquote:mknod -m 666 ${1}/dev/full c 1 7 }
+elquote:if { elquote:mknod -m 666 ${1}/dev/ptmx c 5 2 }
+elquote:if { elquote:mknod -m 644 ${1}/dev/random c 1 8 }
+elquote:if { elquote:mknod -m 644 ${1}/dev/urandom c 1 9 }
+elquote:if { elquote:mknod -m 666 ${1}/dev/zero c 1 5 }
+elquote:if { elquote:mknod -m 666 ${1}/dev/tty c 5 0 }
+elquote:if { elquote:ln -sf /proc/self/fd ${1}/dev/fd }
+elquote:if { elquote:ln -sf /proc/self/fd/0 ${1}/dev/stdin }
+elquote:if { elquote:ln -sf /proc/self/fd/1 ${1}/dev/stout }
+elquote:if { elquote:ln -sf /proc/self/fd/2 ${1}/dev/stderr }
diff --git a/src/lns-tmpfs-chroot.in b/src/lns-tmpfs-chroot.in
@@ -0,0 +1,26 @@
+#!shebang:execlineb -S1
+
+elquote:multisubstitute {
+ elquote:importas -i 1 1 # require first argument
+}
+elquote:shift -n 1 # remove first argument so we don't have to deal with it with runblock
+
+# snapshot current mountpoints for later umount (anything past this point stays)
+elquote:lns-mounts-to-env
+
+elquote:if { elquote:mount -wt tmpfs -o nosuid,dev lns_root $1 }
+
+# mount /dev and /proc
+elquote:if { elquote:lns-prepare-chroot $1 }
+
+# run
+elquote:if {
+ elquote:cd $1
+ elquote:runblock 1
+}
+
+# now we can make /dev immutable
+elquote:if { elquote:mount -o remount,ro ${1}/dev }
+
+# chainload into the rest of the argv
+elquote:runblock -r 1