tests: add regression tests for snapd mount-control

The test adds a very small and simple smoke test that shows that a mount rule
with both fstype and options allows mounts to be performed on a real running
kernel.

The test is structured in a way that should make it easy to extend with new
variants (flags, fstype) in the future.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
This commit is contained in:
Zygmunt Krynicki 2024-11-28 14:15:44 +01:00 committed by Zygmunt Krynicki
parent d9304c7653
commit 1f60021979
3 changed files with 110 additions and 0 deletions

View file

@ -136,3 +136,5 @@ suites:
make -C "$SPREAD_PATH"/tests/regression/apparmor -j"$(nproc)" make -C "$SPREAD_PATH"/tests/regression/apparmor -j"$(nproc)"
restore: | restore: |
rm -f apparmor-regression-tests.txt rm -f apparmor-regression-tests.txt
tests/snapd/:
summary: Tests exercising a subset of behavior of snapd

View file

@ -0,0 +1,39 @@
abi <abi/4.0>,
profile "test-mount-tmpfs-rw" flags=(attach_disconnected,mediate_deleted) {
# See parser/mount.cc for implementation details.
mount fstype=tmpfs options=(rw) none -> /tmp/**,
capability sys_admin,
# Remaining permissions required to run mount. We are _not_ using any
# abstractions to avoid getting confused by what is really needed. This
# approach helps both in understanding the test and in helping shape mount
# profiles generated by snapd.
/etc/ld.so.cache r,
/etc/locale.alias r,
/proc/*/mountinfo r,
/proc/*/mounts r,
/proc/filesystems r,
/run/mount/utab r,
/usr/lib/*-linux-gnu/gconv/gconv-modules.cache r,
/usr/lib/*-linux-gnu/libblkid.so.* rm,
/usr/lib/*-linux-gnu/libc.so.* rm,
/usr/lib/*-linux-gnu/libmount.so.* rm,
/usr/lib/*-linux-gnu/libpcre2-*.so.* rm,
/usr/lib/*-linux-gnu/libselinux.so.* rm,
/usr/lib/locale/C.utf8/LC_ADDRESS r,
/usr/lib/locale/C.utf8/LC_COLLATE r,
/usr/lib/locale/C.utf8/LC_CTYPE r,
/usr/lib/locale/C.utf8/LC_IDENTIFICATION r,
/usr/lib/locale/C.utf8/LC_MEASUREMENT r,
/usr/lib/locale/C.utf8/LC_MESSAGES/ r,
/usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES r,
/usr/lib/locale/C.utf8/LC_MONETARY r,
/usr/lib/locale/C.utf8/LC_NAME r,
/usr/lib/locale/C.utf8/LC_NUMERIC r,
/usr/lib/locale/C.utf8/LC_PAPER r,
/usr/lib/locale/C.utf8/LC_TELEPHONE r,
/usr/lib/locale/C.utf8/LC_TIME r,
/usr/lib/locale/locale-archive r,
}

View file

@ -0,0 +1,69 @@
summary: Tests mimicking what snapd mount-control interface is doing
details: |
The mount-control interface allows snap applications to issue limited calls
to the mount system call. The set of file systems, flags, source and target
paths is carefully controlled. Snapd generates apparmor profiles with rules
that look like this:
mount fstype=(
aufs,autofs,btrfs,ext2,ext3,ext4,hfs,iso9660,jfs,msdos,ntfs,ramfs,
reiserfs,squashfs,tmpfs,ubifs,udf,ufs,vfat,xfs,zfs
) options=(ro) "/dev/sda{0,1}" -> "/var/snap/consumer/common/**{,/}",
Verify that such profiles can be compiled and loaded into the kernel, and
that they allow mounts to actually happen.
environment:
PROFILE: mount-tmpfs-rw.profile
PROFILE_NAME: test-mount-tmpfs-rw
MOUNT_FS: tmpfs
MOUNT_WHAT: none
MOUNT_OPTS: rw
artifacts:
- parser.txt
- denials.txt
prepare: |
rm -f parser.txt denials.txt
"$SPREAD_PATH"/parser/apparmor_parser --base="$SPREAD_PATH"/profiles/apparmor.d --warn=all --replace "$PROFILE" 2>parser.txt
if [ test -s parser.txt ]; then
echo "Parser produced warnings:"
cat parser.txt
fi
mkdir -p /tmp/dir
dmesg --clear # Clear ring buffer
sysctl --values kernel.printk_ratelimit >old-ratelimit.txt
sysctl --write kernel.printk_ratelimit=0
# TODO: if we actually add test systems with auditd pre-installed and
# running then either alter the test or stop the service in prepare and
# start again in restore.
if [ "$(systemctl is-active auditd.service)" != inactive ]; then
echo "This test does not work if auditd is active"
exit 1
fi
execute: |
if ! "$SPREAD_PATH"/binutils/aa-exec -p "$PROFILE_NAME" mount -t "$MOUNT_FS" "$MOUNT_WHAT" /tmp/dir -o "$MOUNT_OPTS"; then
echo "Mount failed, looking for denials"
if dmesg | grep DENIED > denials.txt; then
echo "Profile caused fatal denials"
cat denials.txt
fi
exit 1
elif dmesg | grep DENIED > denials.txt; then
echo "Profile caused non-fatal denials"
cat denials.txt
exit 1
fi
restore: |
if [ -f old-ratelimit.txt ]; then
sysctl -w kernel.printk_ratelimit="$(cat old-ratelimit.txt)"
rm -f old-ratelimit.txt
fi
"$SPREAD_PATH"/parser/apparmor_parser --base="$SPREAD_PATH"/profiles/apparmor.d --remove "$PROFILE"
if [ -d /tmp/dir ]; then
if mountpoint /tmp/dir; then
umount /tmp/dir
fi
rmdir /tmp/dir
fi