diff --git a/spread.yaml b/spread.yaml index d00cffba4..10217791c 100644 --- a/spread.yaml +++ b/spread.yaml @@ -136,3 +136,5 @@ suites: make -C "$SPREAD_PATH"/tests/regression/apparmor -j"$(nproc)" restore: | rm -f apparmor-regression-tests.txt + tests/snapd/: + summary: Tests exercising a subset of behavior of snapd diff --git a/tests/snapd/mount-control/mount-tmpfs-rw.profile b/tests/snapd/mount-control/mount-tmpfs-rw.profile new file mode 100644 index 000000000..27309687f --- /dev/null +++ b/tests/snapd/mount-control/mount-tmpfs-rw.profile @@ -0,0 +1,39 @@ +abi , + +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, +} diff --git a/tests/snapd/mount-control/task.yaml b/tests/snapd/mount-control/task.yaml new file mode 100644 index 000000000..ffef3bbc5 --- /dev/null +++ b/tests/snapd/mount-control/task.yaml @@ -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