110 lines
5.3 KiB
Bash
110 lines
5.3 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
load helpers
|
|
|
|
@test "chroot mount flags" {
|
|
skip_if_no_unshare
|
|
if ! test -e /etc/subuid ; then
|
|
skip "we can't bind mount over /etc/subuid during the test if there is no /etc/subuid file"
|
|
fi
|
|
if ! test -e /etc/subgid ; then
|
|
skip "we can't bind mount over /etc/subgid during the test if there is no /etc/subgid file"
|
|
fi
|
|
# whom should we map to root in a nested namespace?
|
|
if is_rootless ; then
|
|
subid=128
|
|
rangesize=1024
|
|
else
|
|
subid=1048576
|
|
rangesize=16384
|
|
fi
|
|
# we're going to have to prefetch into storage used by someone else image
|
|
# chosen because its rootfs doesn't have any uid/gid ownership above
|
|
# $rangesize, because the nested namespace needs to be able to represent all
|
|
# of them
|
|
baseimage=registry.access.redhat.com/ubi9-micro:latest
|
|
_prefetch $baseimage
|
|
baseimagef=$(tr -c a-zA-Z0-9.- - <<< "$baseimage")
|
|
# create the directories that we need
|
|
tmpfs=${TEST_SCRATCH_DIR}/tmpfs
|
|
mkdir $tmpfs
|
|
context=${TEST_SCRATCH_DIR}/context
|
|
mkdir $context
|
|
storagedir=${TEST_SCRATCH_DIR}/storage
|
|
mkdir $storagedir
|
|
rootdir=${storagedir}/rootdir
|
|
mkdir $rootdir
|
|
runrootdir=${storagedir}/runrootdir
|
|
mkdir $runrootdir
|
|
xdgruntimedir=${storagedir}/xdgruntime
|
|
mkdir $xdgruntimedir
|
|
xdgconfighome=${storagedir}/xdgconfighome
|
|
mkdir $xdgconfighome
|
|
xdgdatahome=${storagedir}/xdgdatahome
|
|
mkdir $xdgdatahome
|
|
storageopts="--storage-driver vfs --root $rootdir --runroot $runrootdir"
|
|
# our temporary parent directory might not be world-searchable, which will
|
|
# cause someone in the nested user namespace to hit permissions issues even
|
|
# looking for $storagedir, so tweak perms to let them do at least that much
|
|
fixupdir=$storagedir
|
|
while test $(stat -c %d:%i $fixupdir) != $(stat -c %d:%i /) ; do
|
|
# walk up to root, or the first parent that we don't own
|
|
if test $(stat -c %u $fixupdir) -ne $(id -u) ; then
|
|
break
|
|
fi
|
|
chmod +x $fixupdir
|
|
fixupdir=$fixupdir/..
|
|
done
|
|
# start writing the script to run in the nested user namespace
|
|
cp -v ${TEST_SOURCES}/containers.conf ${TEST_SCRATCH_DIR}/containers.conf
|
|
chmod ugo+r ${TEST_SCRATCH_DIR}/containers.conf
|
|
echo set -e > ${TEST_SCRATCH_DIR}/script.sh
|
|
echo export XDG_RUNTIME_DIR=$xdgruntimedir >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo export XDG_CONFIG_HOME=$xdgconfighome >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo export XDG_DATA_HOME=$xdgdatahome >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo export CONTAINERS_CONF=${TEST_SCRATCH_DIR}/containers.conf >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# give our would-be user ownership of that directory
|
|
echo chown --recursive ${subid}:${subid} ${storagedir} >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# make newuidmap/newgidmap, invoked by unshare even for uid=0, happy
|
|
echo root:0:4294967295 > ${TEST_SCRATCH_DIR}/subid
|
|
echo mount --bind -r ${TEST_SCRATCH_DIR}/subid /etc/subuid >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo mount --bind -r ${TEST_SCRATCH_DIR}/subid /etc/subgid >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# don't get tripped up by ${TEST_SCRATCH_DIR} potentially being on a filesystem with non-default mount flags
|
|
echo mount -t tmpfs -o size=256K tmpfs $tmpfs >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# mount a small tmpfs with every mount flag combination that concerns us, and
|
|
# be ready to tell buildah to mount everything conservatively, to mirror the
|
|
# TransientMounts API being used to nodev/noexec/nosuid/ro bind in a source
|
|
# that doesn't necessarily have those flags already set on it
|
|
for d in dev nodev ; do
|
|
for e in exec noexec ; do
|
|
for s in suid nosuid ; do
|
|
for r in ro rw ; do
|
|
subdir=$tmpfs/d-$d-$e-$s-$r
|
|
echo mkdir ${subdir} >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo mount -t tmpfs -o size=256K,$d,$e,$s,$r tmpfs ${subdir} >> ${TEST_SCRATCH_DIR}/script.sh
|
|
mounts="${mounts:+${mounts} }--volume ${subdir}:/mounts/d-$d-$e-$s-$r:nodev,noexec,nosuid,ro"
|
|
done
|
|
done
|
|
done
|
|
done
|
|
# make sure that RUN doesn't just break when we try to use volume mounts with
|
|
# flags set that we're not allowed to modify
|
|
echo FROM $baseimage > $context/Dockerfile
|
|
echo RUN cat /proc/mounts >> $context/Dockerfile
|
|
# copy in the prefetched image
|
|
# unshare from util-linux 2.39 also accepts INNER:OUTER:SIZE for --map-users
|
|
# and --map-groups, but fedora 37's is too old, so the older OUTER,INNER,SIZE
|
|
# (using commas instead of colons as field separators) will have to do
|
|
echo "env | sort" >> ${TEST_SCRATCH_DIR}/script.sh
|
|
echo "env _CONTAINERS_USERNS_CONFIGURED=done unshare -Umpf --mount-proc --setuid 0 --setgid 0 --map-users=${subid},0,${rangesize} --map-groups=${subid},0,${rangesize} ${COPY_BINARY} ${storageopts} dir:$_BUILDAH_IMAGE_CACHEDIR/$baseimagef containers-storage:$baseimage" >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# try to do a build with all of the volume mounts
|
|
echo "env _CONTAINERS_USERNS_CONFIGURED=done unshare -Umpf --mount-proc --setuid 0 --setgid 0 --map-users=${subid},0,${rangesize} --map-groups=${subid},0,${rangesize} ${BUILDAH_BINARY} ${BUILDAH_REGISTRY_OPTS} ${storageopts} build --isolation chroot --pull=never $mounts $context" >> ${TEST_SCRATCH_DIR}/script.sh
|
|
# run that whole script in a nested mount namespace with no $XDG_...
|
|
# variables leaked into it
|
|
if is_rootless ; then
|
|
run_buildah unshare env -i bash -x ${TEST_SCRATCH_DIR}/script.sh
|
|
else
|
|
unshare -mpf --mount-proc env -i bash -x ${TEST_SCRATCH_DIR}/script.sh
|
|
fi
|
|
}
|