Replace mountpoint command by checking mounts file

`mountpoint` does not detect some directory. By checking directly
from `/proc/self/mounts` groot can be more reliable and portable.
This commit is contained in:
Filippo Squillace 2017-04-20 19:29:46 +01:00
parent 137788a98a
commit bd0e9fbbcc
3 changed files with 42 additions and 50 deletions

View file

@ -132,7 +132,7 @@ need to be satisfied: 1) Only starting from Linux 3.8, unprivileged processes ca
create the required user and mount namespaces.
2) Moreover, the Linux kernel distro must have the user namespace enabled.
Hopefully, in the future the major GNU/Linux distros will start enabling such feature by default.
For instance, Ubuntu (version 14.04+) already has such feature enabled.
For instance, Ubuntu (version 12.04+) already has such feature enabled.
In order to run JuNest via Linux namespaces:

View file

@ -16,7 +16,6 @@ CHROOTCMD=${CHROOTCMD:-chroot}
SHELL="/bin/sh"
MOUNT=mount
UMOUNT=umount
MOUNTPOINT=mountpoint
MKDIR=mkdir
TOUCH=touch
CUT=cut
@ -35,6 +34,15 @@ source "${JUNEST_BASE}/lib/utils/utils.sh"
################################ MAIN FUNCTIONS ###########################
function is_mountpoint() {
local mountpoint="$1"
for mp in $($CAT $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ)
do
[[ $mp == $mountpoint ]] && return 0
done
return 1
}
function chroot_teardown() {
# Remove all mounts starting from the most nested ones.
# Suffix the CHROOTDIR with / to avoid umounting directories not belonging
@ -43,7 +51,7 @@ function chroot_teardown() {
local final_res=0
for mp in $($CAT $MOUNTS_FILE | $CUT -f2 -d' ' | $SORT -r | $UNIQ)
do
if [[ $mp =~ ^${normalized_chrootdir}.* ]] && $MOUNTPOINT -q "$mp"
if [[ $mp =~ ^${normalized_chrootdir}.* ]] && is_mountpoint "$mp"
then
$UMOUNT $mp || final_res=$?
fi
@ -66,7 +74,7 @@ function chroot_maybe_add_mount() {
function chroot_setup() {
$OPT_NO_UMOUNT || check_and_trap 'chroot_teardown' QUIT EXIT ABRT KILL TERM INT
if ! chroot_maybe_add_mount "! $MOUNTPOINT -q '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR"
if ! chroot_maybe_add_mount "! is_mountpoint '$CHROOTDIR'" --bind "$CHROOTDIR" "$CHROOTDIR"
then
warn "Failed mount of directories. $CHROOTDIR is already a mountpoint. Skipping it..."
return 0

View file

@ -53,6 +53,10 @@ function init_mocks() {
function check_and_trap() {
echo "check_and_trap($@)"
}
# As default suppose the mountpoint "chrootdir" does not exist
echo -e "1 /home/mychroot/dev\n" > ./mounts
MOUNTS_FILE=./mounts
}
function test_help(){
@ -77,41 +81,42 @@ function test_groot_no_directory(){
assertCommandFailOnStatus $NOT_EXISTING_FILE main no-directory
}
function test_groot_mountpoint_exist(){
MOUNTPOINT=mountpoint_mock
echo -e "1 /home/mychroot/dev\n1 chrootdir\n" > ./mounts
MOUNTS_FILE=./mounts
assertCommandSuccess main chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_mountpoint_does_not_exist(){
assertCommandSuccess main chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind(){
assertCommandSuccess main -b /tmp chrootdir
[[ -d chrootdir/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_file(){
touch file_src
assertCommandSuccess main -b ${PWD}/file_src:/file_src chrootdir
[[ -f chrootdir/file_src ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind ${PWD}/file_src chrootdir/file_src)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_not_existing_node(){
assertCommandFailOnStatus $NOT_EXISTING_FILE main -b ${PWD}/file_src:/file_src chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_not_absolute_path_node(){
touch file_src
assertCommandFailOnStatus $NOT_ABSOLUTE_PATH main -b file_src:/file_src chrootdir
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_guest_host(){
assertCommandSuccess main -b /tmp:/home/tmp chrootdir
[[ -d chrootdir/home/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_multiple_bind(){
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir
@ -119,11 +124,11 @@ function test_groot_with_multiple_bind(){
assertEquals 0 $?
[[ -d chrootdir/dev ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_command(){
assertCommandSuccess main chrootdir ls -la -h
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
}
function test_groot_with_bind_and_command(){
assertCommandSuccess main -b /tmp:/home/tmp -b /dev chrootdir ls -la -h
@ -131,30 +136,24 @@ function test_groot_with_bind_and_command(){
assertEquals 0 $?
[[ -d chrootdir/dev ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /dev chrootdir/dev)\nchroot(chrootdir ls -la -h)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--bind /tmp chrootdir/home/tmp)\nmount(--bind /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)"
assertEquals "$(echo -e "mount(--bind chrootdir chrootdir)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown(){
MOUNTPOINT=mountpoint_mock
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 "mountpoint(-q /home/mychroot/proc/fs1)
umount(/home/mychroot/proc/fs1)
mountpoint(-q /home/mychroot/proc)
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
mountpoint(-q /home/mychroot/dev/shm)
umount(/home/mychroot/dev/shm)
mountpoint(-q /home/mychroot/dev)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown_umount_failure(){
MOUNTPOINT=mountpoint_mock
function umount() {
echo "umount($@)"
[[ "$1" == "/home/mychroot/dev/shm" ]] && return 128
@ -164,47 +163,32 @@ function test_groot_with_chroot_teardown_umount_failure(){
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 assertCommandFailOnStatus 128 chroot_teardown
assertEquals "$(echo -e "mountpoint(-q /home/mychroot/proc/fs1)
umount(/home/mychroot/proc/fs1)
mountpoint(-q /home/mychroot/proc)
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
mountpoint(-q /home/mychroot/dev/shm)
umount(/home/mychroot/dev/shm)
mountpoint(-q /home/mychroot/dev)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown_with_trailing_slash(){
MOUNTPOINT=mountpoint_mock
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 "mountpoint(-q /home/mychroot/proc/fs1)
umount(/home/mychroot/proc/fs1)
mountpoint(-q /home/mychroot/proc)
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
mountpoint(-q /home/mychroot/dev/shm)
umount(/home/mychroot/dev/shm)
mountpoint(-q /home/mychroot/dev)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
function test_groot_with_chroot_teardown_mountpoint_failure(){
mountpoint_mock() {
echo "mountpoint($@)"
[[ $2 == "/home/mychroot/dev/shm" ]] && return 128
is_mountpoint() {
[[ $1 == "/home/mychroot/dev/shm" ]] && return 128
return 0
}
MOUNTPOINT=mountpoint_mock
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 "mountpoint(-q /home/mychroot/proc/fs1)
umount(/home/mychroot/proc/fs1)
mountpoint(-q /home/mychroot/proc)
assertEquals "$(echo -e "umount(/home/mychroot/proc/fs1)
umount(/home/mychroot/proc)
mountpoint(-q /home/mychroot/dev/shm)
mountpoint(-q /home/mychroot/dev)
umount(/home/mychroot/dev)
umount(/home/mychroot)")" "$(cat $STDOUTF)"
}
@ -213,42 +197,42 @@ function test_groot_with_rbind(){
assertCommandSuccess main -r -b /tmp chrootdir
[[ -d chrootdir/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(--rbind /tmp chrootdir/tmp)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_proc(){
assertCommandSuccess main -i -b /proc chrootdir
[[ -d chrootdir/proc ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(proc chrootdir/proc -t proc)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(proc chrootdir/proc -t proc)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_dev(){
assertCommandSuccess main -i -b /dev chrootdir
[[ -d chrootdir/dev ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(udev chrootdir/dev -t devtmpfs)\nmount(devpts /dev/pts -t devpts)\nmount(shm /dev/shm -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(udev chrootdir/dev -t devtmpfs)\nmount(devpts /dev/pts -t devpts)\nmount(shm /dev/shm -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_sys(){
assertCommandSuccess main -i -b /sys chrootdir
[[ -d chrootdir/sys ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(sys chrootdir/sys -t sysfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(sys chrootdir/sys -t sysfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_run(){
assertCommandSuccess main -i -b /run chrootdir
[[ -d chrootdir/run ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(run chrootdir/run -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(run chrootdir/run -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_tmp(){
assertCommandSuccess main -i -b /tmp chrootdir
[[ -d chrootdir/tmp ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
function test_groot_with_avoid_bind_combined(){
@ -258,7 +242,7 @@ function test_groot_with_avoid_bind_combined(){
assertEquals 0 $?
[[ -d chrootdir/usr ]]
assertEquals 0 $?
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmountpoint(-q chrootdir)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nmount(--bind /usr chrootdir/usr)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
assertEquals "$(echo -e "check_and_trap(chroot_teardown QUIT EXIT ABRT KILL TERM INT)\nmount(--bind chrootdir chrootdir)\nmount(tmp chrootdir/tmp -t tmpfs)\nmount(--bind /usr chrootdir/usr)\nchroot(chrootdir)")" "$(cat $STDOUTF)"
}
source $(dirname $0)/../utils/shunit2