mirror of
https://github.com/fsquillace/junest.git
synced 2026-07-25 20:03:58 +00:00
commit
dc8018a4b9
6 changed files with 152 additions and 26 deletions
10
README.md
10
README.md
|
|
@ -87,7 +87,7 @@ You can build a new JuNest image from scratch by running the following command:
|
|||
junest -b [-n]
|
||||
|
||||
The script will create a directory containing all the essentials
|
||||
files in order to make JuNest working properly (such as pacman, yaourt, arch-chroot and proot).
|
||||
files in order to make JuNest working properly (such as pacman, yaourt and proot).
|
||||
The option **-n** will skip the final validation tests if they are not needed.
|
||||
Remember that the script to build the image must run in an Arch Linux OS with
|
||||
arch-install-scripts, package-query, git and the base-devel packages installed.
|
||||
|
|
@ -132,18 +132,20 @@ Internals
|
|||
There are two main chroot jail used in JuNest.
|
||||
The main one is [proot](https://wiki.archlinux.org/index.php/Proot) which
|
||||
allows unprivileged users to execute programs inside a sandbox and
|
||||
jchroot, a small and portable version of
|
||||
[arch-chroot](https://wiki.archlinux.org/index.php/Chroot) which is an
|
||||
enhanced chroot for privileged users that mounts the primary directories
|
||||
(i.e. /proc, /sys, /dev and /run) before executing any programs inside
|
||||
the sandbox.
|
||||
|
||||
##Automatic fallback to classic chroot##
|
||||
Since the [arch-chroot](https://wiki.archlinux.org/index.php/Chroot) may not work
|
||||
on some distros, JuNest automatically tries to fallback to the classic chroot.
|
||||
If jchroot fails for some reasons in the host system (i.e. it is not able to
|
||||
mount one of the directories),
|
||||
JuNest automatically tries to fallback to the classic chroot.
|
||||
|
||||
##Automatic fallback for all the dependent host OS executables##
|
||||
JuNest attempt first to run the executables in the host OS located in different
|
||||
positions (/usr/bin, /bin and /sbin).
|
||||
positions (/usr/bin, /bin, /usr/sbin and /sbin).
|
||||
As a fallback it tries to run the same executable if it is available in the JuNest
|
||||
image.
|
||||
|
||||
|
|
|
|||
112
bin/jchroot
Executable file
112
bin/jchroot
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012-2015
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Library General Public License as published
|
||||
# by the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# This script is the simplified and portable version of arch-chroot
|
||||
# (https://wiki.archlinux.org/index.php/Change_root#Using_arch-chroot)
|
||||
|
||||
set -e
|
||||
|
||||
################################ IMPORTS ##################################
|
||||
source "$(dirname $0)/../lib/util.sh"
|
||||
|
||||
################################ MAIN FUNCTIONS ###########################
|
||||
|
||||
chroot_add_mount() {
|
||||
mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}")
|
||||
}
|
||||
|
||||
chroot_maybe_add_mount() {
|
||||
local cond=$1; shift
|
||||
if eval "$cond"; then
|
||||
chroot_add_mount "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
chroot_setup() {
|
||||
CHROOT_ACTIVE_MOUNTS=()
|
||||
[[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap'
|
||||
trap 'chroot_teardown' EXIT
|
||||
|
||||
chroot_maybe_add_mount "! mountpoint -q '$1'" "$1" "$1" --bind &&
|
||||
chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev &&
|
||||
chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro &&
|
||||
chroot_add_mount udev "$1/dev" -t devtmpfs -o mode=0755,nosuid &&
|
||||
chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec &&
|
||||
chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev &&
|
||||
chroot_add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 &&
|
||||
chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,atime,nodev,nosuid &&
|
||||
mkdir -p "$1/$HOME" &&
|
||||
chroot_add_mount $HOME "$1/$HOME" --bind
|
||||
|
||||
mkdir -p "$1/run/lock"
|
||||
}
|
||||
|
||||
chroot_teardown() {
|
||||
umount "${CHROOT_ACTIVE_MOUNTS[@]}"
|
||||
unset CHROOT_ACTIVE_MOUNTS
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: ${0##*/} chroot-dir [command]
|
||||
|
||||
-h Print this help message
|
||||
|
||||
If 'command' is unspecified, ${0##*/} will launch /bin/sh.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
chroot_add_resolv_conf() {
|
||||
local chrootdir=$1 resolv_conf=$1/etc/resolv.conf
|
||||
|
||||
# Handle resolv.conf as a symlink to somewhere else.
|
||||
if [[ -L $chrootdir/etc/resolv.conf ]]; then
|
||||
# readlink(1) should always give us *something* since we know at this point
|
||||
# it's a symlink. For simplicity, ignore the case of nested symlinks.
|
||||
resolv_conf=$(readlink "$chrootdir/etc/resolv.conf")
|
||||
if [[ $resolv_conf = /* ]]; then
|
||||
resolv_conf=$chrootdir$resolv_conf
|
||||
else
|
||||
resolv_conf=$chrootdir/etc/$resolv_conf
|
||||
fi
|
||||
|
||||
# ensure file exists to bind mount over
|
||||
if [[ ! -f $resolv_conf ]]; then
|
||||
install -Dm644 /dev/null "$resolv_conf" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
chroot_add_mount /etc/resolv.conf "$resolv_conf" --bind
|
||||
}
|
||||
|
||||
if [[ -z $1 || $1 == -h || $1 == --help ]]; then
|
||||
usage
|
||||
exit $(( $# ? 0 : 1 ))
|
||||
fi
|
||||
|
||||
(( EUID == 0 )) || die 'This script must be run with root privileges'
|
||||
chrootdir=$1
|
||||
shift
|
||||
|
||||
[[ -d $chrootdir ]] || die "Can't create chroot on non-directory $chrootdir"
|
||||
|
||||
chroot_setup "$chrootdir" || die "failed to setup chroot $chrootdir"
|
||||
chroot_add_resolv_conf "$chrootdir" || die "failed to setup resolv.conf"
|
||||
|
||||
SHELL="/bin/sh" chroot "$chrootdir" "$@"
|
||||
|
|
@ -18,7 +18,9 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
source "$(dirname $0)/../lib/core.sh"
|
||||
JUNEST_BASE="$(dirname $0)/.."
|
||||
|
||||
source "${JUNEST_BASE}/lib/core.sh"
|
||||
|
||||
###################################
|
||||
### General functions ###
|
||||
|
|
|
|||
30
lib/core.sh
30
lib/core.sh
|
|
@ -46,6 +46,7 @@ then
|
|||
fi
|
||||
|
||||
[ -z ${JUNEST_HOME} ] && JUNEST_HOME=~/.${CMD}
|
||||
[ -z ${JUNEST_BASE} ] && JUNEST_BASE=${JUNEST_HOME}/opt/junest
|
||||
if [ -z ${JUNEST_TEMPDIR} ] || [ ! -d ${JUNEST_TEMPDIR} ]
|
||||
then
|
||||
JUNEST_TEMPDIR=/tmp
|
||||
|
|
@ -86,14 +87,14 @@ ID="id -u"
|
|||
|
||||
# List of executables that are run in the host OS:
|
||||
PROOT_COMPAT="${JUNEST_HOME}/opt/proot/proot-${ARCH}"
|
||||
CHROOT=${JUNEST_HOME}/usr/bin/arch-chroot
|
||||
CLASSIC_CHROOT=${JUNEST_HOME}/usr/bin/chroot
|
||||
CHROOT=${JUNEST_BASE}/bin/jchroot
|
||||
CLASSIC_CHROOT="chroot"
|
||||
WGET="wget --no-check-certificate"
|
||||
CURL="curl -L -J -O -k"
|
||||
TAR=tar
|
||||
CHOWN="chown"
|
||||
|
||||
PATH=/usr/bin:/bin:/sbin:$PATH
|
||||
PATH=/usr/bin:/bin:/usr/sbin:/sbin:$PATH
|
||||
LD_EXEC="$LD_LIB --library-path ${JUNEST_HOME}/usr/lib:${JUNEST_HOME}/lib"
|
||||
|
||||
# The following functions attempt first to run the executable in the host OS.
|
||||
|
|
@ -120,6 +121,10 @@ function download_cmd(){
|
|||
$WGET $@ || $CURL $@
|
||||
}
|
||||
|
||||
function chroot_cmd(){
|
||||
$CHROOT "$@" || $CLASSIC_CHROOT "$@" || $LD_EXEC ${JUNEST_HOME}/usr/bin/chroot "$@"
|
||||
}
|
||||
|
||||
################################# MAIN FUNCTIONS ##############################
|
||||
|
||||
function is_env_installed(){
|
||||
|
|
@ -182,32 +187,20 @@ function setup_env_from_file(){
|
|||
builtin cd $ORIGIN_WD
|
||||
}
|
||||
|
||||
|
||||
function run_env_as_root(){
|
||||
local uid=$UID
|
||||
[ -z $SUDO_UID ] || uid=$SUDO_UID:$SUDO_GID
|
||||
|
||||
local main_cmd="${SH[@]}"
|
||||
[ "$1" != "" ] && main_cmd="$(insert_quotes_on_spaces "$@")"
|
||||
local cmd="mkdir -p ${JUNEST_HOME}/${HOME} && mkdir -p /run/lock && ${main_cmd}"
|
||||
|
||||
trap - QUIT EXIT ABRT KILL TERM INT
|
||||
trap "[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME}; rm_cmd -r ${JUNEST_HOME}/etc/mtab" EXIT QUIT ABRT KILL TERM INT
|
||||
|
||||
[ ! -e ${JUNEST_HOME}/etc/mtab ] && ln_cmd -s /proc/self/mounts ${JUNEST_HOME}/etc/mtab
|
||||
|
||||
if ${CHROOT} $JUNEST_HOME ${TRUE} 1> /dev/null
|
||||
then
|
||||
JUNEST_ENV=1 ${CHROOT} $JUNEST_HOME "${SH[@]}" "-c" "${cmd}"
|
||||
local ret=$?
|
||||
elif ${CLASSIC_CHROOT} $JUNEST_HOME ${TRUE} 1> /dev/null
|
||||
then
|
||||
warn "Warning: The executable arch-chroot does not work, falling back to classic chroot"
|
||||
JUNEST_ENV=1 ${CLASSIC_CHROOT} $JUNEST_HOME "${SH[@]}" "-c" "${cmd}"
|
||||
local ret=$?
|
||||
else
|
||||
die "Error: Chroot does not work"
|
||||
fi
|
||||
JUNEST_ENV=1 chroot_cmd "$JUNEST_HOME" "${SH[@]}" "-c" "${main_cmd}"
|
||||
local ret=$?
|
||||
|
||||
# The ownership of the files is assigned to the real user
|
||||
[ -z $uid ] || chown_cmd -R ${uid} ${JUNEST_HOME}
|
||||
|
|
@ -319,7 +312,7 @@ function build_image_env(){
|
|||
# The archlinux-keyring and libunistring are due to missing dependencies declaration in ARM archlinux
|
||||
# All the essential executables (ln, mkdir, chown, etc) are in coreutils
|
||||
# yaourt requires sed
|
||||
sudo pacstrap -G -M -d ${maindir}/root pacman arch-install-scripts coreutils binutils libunistring archlinux-keyring sed
|
||||
sudo pacstrap -G -M -d ${maindir}/root pacman coreutils binutils libunistring archlinux-keyring sed
|
||||
sudo bash -c "echo 'Server = $DEFAULT_MIRROR' >> ${maindir}/root/etc/pacman.d/mirrorlist"
|
||||
|
||||
info "Generating the locales..."
|
||||
|
|
@ -394,7 +387,6 @@ function validate_image(){
|
|||
JUNEST_HOME=${testdir} sudo -E ${testdir}/opt/${CMD}/bin/${CMD} -r pacman -Qi pacman 1> /dev/null
|
||||
JUNEST_HOME=${testdir} sudo -E ${testdir}/opt/${CMD}/bin/${CMD} -r yaourt -V 1> /dev/null
|
||||
JUNEST_HOME=${testdir} sudo -E ${testdir}/opt/${CMD}/bin/${CMD} -r /opt/proot/proot-$ARCH --help 1> /dev/null
|
||||
JUNEST_HOME=${testdir} sudo -E ${testdir}/opt/${CMD}/bin/${CMD} -r arch-chroot --help 1> /dev/null
|
||||
|
||||
local repo_package=sysstat
|
||||
info "Installing ${repo_package} package from official repo using proot..."
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/bash
|
||||
source $(dirname $0)/../bin/* -h &> /dev/null
|
||||
source $(dirname $0)/../bin/junest -h &> /dev/null
|
||||
|
||||
# Disable the exiterr
|
||||
set +e
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ function install_mini_env(){
|
|||
function setUp(){
|
||||
cd $CURRPWD
|
||||
JUNEST_HOME=$(TMPDIR=/tmp mktemp -d -t envhome.XXXXXXXXXX)
|
||||
source "$(dirname $0)/../lib/core.sh"
|
||||
JUNEST_BASE="$CURRPWD/$(dirname $0)/.."
|
||||
source "${JUNEST_BASE}/lib/core.sh"
|
||||
ORIGIN_WD=$(TMPDIR=/tmp mktemp -d -t envowd.XXXXXXXXXX)
|
||||
cd $ORIGIN_WD
|
||||
JUNEST_TEMPDIR=$(TMPDIR=/tmp mktemp -d -t envtemp.XXXXXXXXXX)
|
||||
|
|
@ -217,6 +218,23 @@ function test_run_env_as_classic_root(){
|
|||
assertEquals 0 $?
|
||||
}
|
||||
|
||||
function test_run_env_as_junest_root(){
|
||||
[ $SKIP_ROOT_TESTS -eq 1 ] && return
|
||||
|
||||
install_mini_env
|
||||
CHROOT="sudo unknowncommand"
|
||||
CLASSIC_CHROOT="sudo unknowncommand"
|
||||
LD_EXEC="sudo $LD_EXEC"
|
||||
CHOWN="sudo $CHOWN"
|
||||
|
||||
local output=$(run_env_as_root pwd 2> /dev/null)
|
||||
assertEquals "/" "$output"
|
||||
run_env_as_root [ -e /run/lock ] 2> /dev/null
|
||||
assertEquals 0 $?
|
||||
run_env_as_root [ -e $HOME ] 2> /dev/null
|
||||
assertEquals 0 $?
|
||||
}
|
||||
|
||||
function test_run_env_as_user(){
|
||||
install_mini_env
|
||||
local output=$(run_env_as_user "-k 3.10" "/usr/bin/mkdir" "-v" "/newdir2" | awk -F: '{print $1}')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue