Issue #174: Add option -n in groot and umount directories in order

This commit is contained in:
Filippo Squillace 2017-04-07 22:38:47 +01:00
parent 8e5531a27a
commit fcb4a36f30
4 changed files with 57 additions and 20 deletions

View file

@ -19,6 +19,11 @@ UMOUNT=umount
MOUNTPOINT=mountpoint
MKDIR=mkdir
TOUCH=touch
CUT=cut
SORT=sort
UNIQ=uniq
GREP=grep
MOUNTS_FILE=/proc/self/mounts
NOT_EXISTING_FILE=103
NOT_ABSOLUTE_PATH=111
@ -29,28 +34,29 @@ source "${JUNEST_BASE}/lib/utils/utils.sh"
################################ MAIN FUNCTIONS ###########################
function chroot_add_mount() {
$MOUNT "$@" && CHROOT_ACTIVE_MOUNTS=("${@: -1}" "${CHROOT_ACTIVE_MOUNTS[@]}")
}
function chroot_teardown() {
$UMOUNT "${CHROOT_ACTIVE_MOUNTS[@]}"
unset CHROOT_ACTIVE_MOUNTS
# Remove all mounts starting from the most nested ones.
# Suffix the CHROOTDIR with / to avoid umounting directories not belonging
# to CHROOTDIR.
for mp in $($GREP "${CHROOTDIR%/}/" $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ)
do
$UMOUNT $mp
done
$UMOUNT ${CHROOTDIR%/}
}
function chroot_maybe_add_mount() {
local cond=$1
shift
if eval "$cond"; then
chroot_add_mount "$@"
$MOUNT "$@"
return
fi
return 1
}
function chroot_setup() {
CHROOT_ACTIVE_MOUNTS=()
check_and_trap 'chroot_teardown' EXIT
$OPT_NO_UMOUNT || check_and_trap 'chroot_teardown' EXIT
if ! chroot_maybe_add_mount "! $MOUNTPOINT -q '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR"
then
@ -73,7 +79,7 @@ function chroot_setup() {
fi
create_node "${host_path}" "${CHROOTDIR}${guest_path}"
chroot_add_mount --rbind "${host_path}" "${CHROOTDIR}${guest_path}"
$MOUNT --rbind "${host_path}" "${CHROOTDIR}${guest_path}"
done
}
@ -112,6 +118,8 @@ Options:
path in the guest rootfs but users can specify any other location
with the syntax: -b <host_path>:<guest_location>. This option can
be invoked multiple times and the paths specified must be absolutes.
-n, --no-umount
Do not umount after chroot session finished.
-h, --help Print this help message
@ -129,12 +137,14 @@ version() {
function parse_arguments() {
OPT_BIND=false
BINDINGS=()
OPT_NO_UMOUNT=false
OPT_HELP=false
OPT_VERSION=false
for opt in "$@"
do
case "$1" in
-b|--bind) OPT_BIND=true ; shift ; BINDINGS+=("$1") ; shift ;;
-n|--no-umount) OPT_NO_UMOUNT=true ; shift ;;
-h|--help) OPT_HELP=true ; shift ;;
-V|--version) OPT_VERSION=true ; shift ;;
-*) die "Invalid option $1" ;;

View file

@ -46,11 +46,14 @@ function _run_env_with_namespace(){
local backend_args="$1"
shift
# Use option -n in groot because umount do not work sometimes.
# As soon as the process terminates, the namespace
# will terminate too with its own mounted directories.
if [[ "$1" != "" ]]
then
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT -n $bindings $backend_args "$JUNEST_HOME" "${SH[@]}" "-c" "$(insert_quotes_on_spaces "${@}")"
else
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT $bindings $backend_args "$JUNEST_HOME" "${SH[@]}"
JUNEST_ENV=1 unshare_cmd --mount --user --map-root-user $GROOT -n $bindings $backend_args "$JUNEST_HOME" "${SH[@]}"
fi
}

View file

@ -133,5 +133,29 @@ function test_groot_with_bind_and_command(){
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown EXIT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/home/tmp)\nmount(--rbind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_no_umount(){
assertCommandSuccess main -n chrootdir
assertEquals "$(echo -e "mountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown(){
echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts
MOUNTS_FILE=./mounts
CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
umount(/home/mychroot/dev/shm)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown_with_trailing_slash(){
echo -e "1 /home/mychroot/dev\n1 /home/mychroot/proc/fs1\n1 /home/mychroot\n1 /home/mychroot-no/dev\n1 /home/mychroot/dev/shm\n1 /home/mychroot/proc\n" > ./mounts
MOUNTS_FILE=./mounts
CHROOTDIR=/home/mychroot assertCommandSuccess chroot_teardown
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
umount(/home/mychroot/dev/shm)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
source $(dirname $0)/../utils/shunit2

View file

@ -80,7 +80,7 @@ function test_is_user_namespace_enabled_with_config(){
function test_run_env_as_user_with_namespace() {
assertCommandSuccess run_env_as_user_with_namespace "" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
@ -88,7 +88,7 @@ function test_run_env_as_user_with_namespace() {
function test_run_env_as_user_with_namespace_with_bindings() {
assertCommandSuccess run_env_as_user_with_namespace "-b /usr -b /lib:/tmp/lib" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
@ -96,7 +96,7 @@ function test_run_env_as_user_with_namespace_with_bindings() {
function test_run_env_as_user_with_namespace_with_command() {
assertCommandSuccess run_env_as_user_with_namespace "" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
@ -104,7 +104,7 @@ function test_run_env_as_user_with_namespace_with_command() {
function test_run_env_as_user_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_as_user_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
_test_copy_remaining_files
@ -112,28 +112,28 @@ function test_run_env_as_user_with_namespace_with_bindings_and_command() {
function test_run_env_as_fakeroot_with_namespace() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_bindings() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "-b /usr -b /lib:/tmp/lib" ""
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_command() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}
function test_run_env_as_fakeroot_with_namespace_with_bindings_and_command() {
assertCommandSuccess run_env_as_fakeroot_with_namespace "-b /usr -b /lib:/tmp/lib" "ls -la"
assertEquals "unshare --mount --user --map-root-user $GROOT -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
assertEquals "unshare --mount --user --map-root-user $GROOT -n -b $HOME -b /tmp -b /proc -b /sys -b /dev -b /usr -b /lib:/tmp/lib $JUNEST_HOME /bin/sh --login -c \"ls -la\"" "$(cat $STDOUTF)"
_test_copy_common_files
}