diff --git a/root-enter/APKBUILD b/root-enter/APKBUILD index 6ba5ea3..11f7cd2 100644 --- a/root-enter/APKBUILD +++ b/root-enter/APKBUILD @@ -1,13 +1,12 @@ # Contributor: Patrycja Rosa # Maintainer: Patrycja Rosa pkgname=root-enter -pkgver=8 +pkgver=9 pkgrel=0 pkgdesc="enter chroot with mounts" url="https://git.ddd.rip/ptrcnull/ptrcports" arch="noarch" license="BSD-2-Clause" -depends="execline" source="enter" builddir="$srcdir" options="!check" @@ -17,5 +16,5 @@ package() { } sha512sums=" -2c46100bb0c1a2a1b683d3e6070a970fcdd0bf688ccdfa3bcf4310b8f4ea0a69946a3a1b3cffec18af70eb09fb53a977a034318a7be4f103a864239880f4a1be enter +4a054f60ded2e17c8eca35ff30b2e23b00dba58b7208f62121ffce849502838022f61ea2a1ddc4b6c80e63cbb33e1a331f1d7aecace5ada5bd6b0ae23cd790ea enter " diff --git a/root-enter/enter b/root-enter/enter index d49fef8..4104422 100755 --- a/root-enter/enter +++ b/root-enter/enter @@ -1,83 +1,104 @@ -#!/bin/execlineb +#!/bin/sh +set -eu -elgetopt "be:u:c:" +# make sure we're root +if [ "$(id -u)" != 0 ]; then + sucmd="su -c" + if command -v doas >/dev/null; then + sucmd="doas" + elif command -v sudo >/dev/null; then + sucmd="sudo" + fi -multisubstitute { - importas -D "0" build ELGETOPT_b - importas -D "" extra_mounts ELGETOPT_e - importas -D "" user_arg ELGETOPT_u - importas -D "" command_arg ELGETOPT_c - importas -D "" dest 1 - importas -i USER USER - importas -i HOME HOME -} + exec $sucmd env HOME="$HOME" USERNAME="$(id -u -n)" "$0" "$@" +fi +# and make sure we're in a separate mount namespace +if [ "$(readlink /proc/$$/ns/mnt | cut -d: -f2)" = "$(readlink /proc/1/ns/mnt | cut -d: -f2)" ]; then + exec unshare -m "$0" "$@" +fi + +bindpoints="/etc/resolv.conf" +command="" +user="$USERNAME" + +while getopts "be:u:c:" opt; do + case $opt in + 'b') bindpoints=" + $bindpoints + $HOME/aports + $HOME/packages + $HOME/.abuild + " ;; + 'e') bindpoints="$bindpoints $OPTARG" ;; + 'u') user="$OPTARG" ;; + 'c') command="$OPTARG" ;; + *) echo "unknown $opt" ;; + esac +done +shift $(( $OPTIND - 1 )) + +dest="$1" shift -elgetpositionals -emptyenv -oP -backtick -D "ash -l" command { - ifelse { test -n $command_arg } { - echo $command_arg - } +if [ ! -d "$dest" ]; then + echo "no such directory: $dest" + exit 1 +fi - ifelse { test $# -gt 0 } { - echo $@ - } +if [ ! -x "$dest"/bin/sh ]; then + echo "$dest does not contain executable /bin/sh" + exit 1 +fi - echo ash -l -} -importas -ui command command -# TODO: add -s to that when not using `su` later +mount -t proc proc "$dest"/proc +mount -t sysfs sysfs "$dest"/sys +mount -t tmpfs tmpfs "$dest"/tmp +# some mini kernels don't have devtmpfs +if grep -q devtmpfs /proc/filesystems; then + mount -t devtmpfs devtmpfs "$dest"/dev +else + mount -t tmpfs tmpfs "$dest"/dev -backtick -D "" -E user { ifelse { test -n $user_arg } { echo $user_arg } echo $USER } + if [ -x "$dest"/sbin/mdev ]; then + echo "devtmpfs not supported - running 'mdev -s' instead" + chroot "$dest" /sbin/mdev -s + else + echo "devtmpfs not supported - devices need to be created manually" + fi +fi +mount -t devpts devpts "$dest"/dev/pts +mount -t tmpfs tmpfs "$dest"/dev/shm -backtick -D "" -E build_mounts { - if { test $build = 1 } - echo " - ${HOME}/aports - ${HOME}/packages - ${HOME}/.abuild - " -} +for bindpoint in $bindpoints; do + if [ -f "$bindpoint" ]; then + touch "$dest"/"$bindpoint" + else + mkdir -p "$dest"/"$bindpoint" + fi -define -s -C bindpoints "/etc/resolv.conf ${build_mounts} ${extra_mounts}" + mount --bind "$bindpoint" "$dest"/"$bindpoint" +done -ifelse -n { test -d $dest } { - foreground { echo "no such file or directory: $dest" } - exit 1 -} +# if running on chromeos, fixup symlink exec +# https://goo.gl/8xICW6 +# https://github.com/dnschneid/crouton/commit/5cb7ad05 +if [ -e "/run/chrome" ]; then + if mount -n -t securityfs -o nodev,noexec,nosuid securityfs /sys/kernel/security; then + policies=/sys/kernel/security/chromiumos/inode_security_policies + if [ -d "$policies" ]; then + for policy in "$policies/allow_"*; do + printf "$(realpath "$dest")" > "$policy" + done + fi + umount /sys/kernel/security + fi +fi -ifelse -n { test -x ${dest}/bin/sh } { - foreground { echo "$dest does not contain executable /bin/sh" } - exit 1 -} - -backtick -E uid { id -u } -backtick -E -D "exec" sucmd { if { test $uid != 0 } echo doas } -$sucmd - -unshare -m - -foreground { mount -t devtmpfs devtmpfs ${dest}/dev } -foreground { mount -t tmpfs shm ${dest}/dev/shm } -foreground { mount -t devpts devpts ${dest}/dev/pts } -foreground { mount -t sysfs sysfs ${dest}/sys } -foreground { mount -t proc proc ${dest}/proc } -foreground { mount -t tmpfs tmpfs ${dest}/tmp } -foreground { - forx -E point { $bindpoints } - - # ensure $point exists in destination - ifthenelse { test -f $point } { - touch ${dest}${point} - } { - mkdir -p ${dest}${point} - } - - mount --bind $point ${dest}${point} -} - -chroot ${dest} - -su $user -c "$command" +if [ "$command" ]; then + exec chroot "$dest" su $user -c "$command" +elif [ "$#" -gt 0 ]; then + exec chroot "$dest" su $user -c "$*" +else + exec chroot "$dest" login -f $user +fi