ns_run_unshared (3172B)
1 #!/command/execlineb 2 3 ## usage: ns_run_unshared <root_directory> { extra_command } <executable> [<arg1> ...] 4 ## 5 ## Prepares isolated namespace/container with given root and runs given 6 ## executable in it. 7 ## 8 ## Environment variables used: 9 ## HOST - hostname to set 10 ## NS_ROOT - where to bind-mount the root directory 11 ## NS_FSTAB - file with extra mounts to perform after running above script 12 ## NS_TMPFS - place to store binaries in the container that are run 13 ## before dropping privs, relative path from new root 14 ## NS_BIN - directory to get said binaries from; currently needs: 15 ## - `if` from execline 16 ## - busybox with `umount` and `chpst` functions 17 ## - anything you wish to call before and for dropping privs, 18 ## eg. s6-applyuidgid 19 ## All statically linked of course. 20 ## NS_NO_PID1 - Allow not running as init process of the namespace. 21 22 # import variables from environment, with defaults 23 multisubstitute { 24 importas -i 1 1 # require first argument 25 importas -D container HOST HOST 26 importas -D /mnt/chroot NS_ROOT NS_ROOT 27 importas -D mnt/ns NS_TMPFS NS_TMPFS 28 importas -D /mnt/volumes/containers/bin NS_BIN NS_BIN 29 } 30 31 # remove first argument so we don't have to deal with it with runblock 32 shift -n 1 33 34 # check we are PID1 (in a new PID namespace) 35 getpid PID 36 ifelse { 37 importas -D "" NS_NO_PID1 NS_NO_PID1 38 importas -i PID PID 39 test -z ${NS_NO_PID1} -a 1 -ne $PID 40 } { 41 fdmove -c 1 2 42 foreground { echo "ns_run: fatal: not PID 1" } 43 exit 111 44 } 45 unexport PID 46 47 48 foreground { importas -i HOST HOST hostname $HOST } 49 50 # We will generate final script we will exec into to enter the container. 51 # We need to generate it before we start mounting anything, 52 # so only the mountpoints that exist at this point will get unmounted and 53 # everything we will mount below will stay. 54 backtick -i NS_FINAL_SCRIPT { 55 # Generate execline script that performs pivot_root 56 # and umounts all the filesystems not used by the container 57 # formerly: /root/ns_execline.zsh $@ 58 59 if { 60 printf "%s\n" 61 "if { pivot_root . \${NS_TMPFS}/oldroot }" 62 } 63 if { 64 ns_umount_script.awk 65 -vROOT=/${NS_TMPFS}/oldroot 66 -vBIN=/${NS_TMPFS}/bin 67 /proc/self/mountinfo 68 } 69 if { printf "%s\n" "./${NS_TMPFS}/bin/busybox chpst -/ ." "\$@" } 70 } 71 72 # mount and enter the chroot directory 73 if { mount -o rbind $1 $NS_ROOT } 74 cd $NS_ROOT 75 76 if { ns_run_mounts . } 77 78 # mountpoint for privileged operations and pivot_root 79 if { s6-mount -nwt tmpfs -o nosuid,nodev,mode=711 mnt_ns $NS_TMPFS } 80 if { mkdir ${NS_TMPFS}/oldroot ${NS_TMPFS}/bin } 81 #if { s6-hiercopy $NS_BIN ${NS_TMPFS}/bin } 82 if { s6-mount -n -o bind,ro $NS_BIN ${NS_TMPFS}/bin } 83 84 # optional fstab file for extra mounts 85 if { 86 if -t { eltest -v NS_FSTAB } 87 importas -i NS_FSTAB NS_FSTAB 88 mount -a -T $NS_FSTAB 89 } 90 unexport NS_FSTAB 91 92 # container-specific setup 93 if { runblock 1 } 94 95 # now we can make /dev immutable 96 if { mount -o remount,ro dev } 97 98 # exec into the script we generated above, it: 99 # * does pivot_root to change rootdir 100 # * umounts all undesired filesystems 101 # * execs into $@ 102 importas -i -u NS_FINAL_SCRIPT NS_FINAL_SCRIPT 103 runblock -r 1 104 emptyenv -c 105 execlineb -S0 -c $NS_FINAL_SCRIPT