lnstools

Linux namespace tools
git clone https://ccx.te2000.cz/git/lnstools
Log | Files | Refs | README

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:
MREADME | 46+++++++++++++++++++++++++++++++++++++---------
Asrc/lns-bind-chroot.in | 27+++++++++++++++++++++++++++
Dsrc/lns-mount-chroot.in | 64----------------------------------------------------------------
Asrc/lns-prepare-chroot.in | 43+++++++++++++++++++++++++++++++++++++++++++
Asrc/lns-tmpfs-chroot.in | 26++++++++++++++++++++++++++
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