1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
summary: Test for the mount-control interface
details: |
The mount-control interface allows a snap to request creation or removal of
a mount point with certain constraints. The test checks that requests to
snapd, with "snapctl mount" observe the restrictions set in the plug
attributes. The test also checks that persistent mounts survive reboots.
environment:
MOUNT_SRC: /var/tmp/test-snapd-mount-control
SNAP_COMMON: /var/snap/test-snapd-mount-control/common
SNAP_NAME: test-snapd-mount-control
# what: /var/tmp/** | where: $SNAP_COMMON/target1 | options: [rw, bind] | persistent
MOUNT_DEST1: $SNAP_COMMON/target1
# what: none | where: $SNAP_COMMON/target2/* | type: [tmpfs] | options: [rw]
MOUNT_DEST2: $SNAP_COMMON/target2/path
# what: /usr/** | where: $SNAP_COMMON/target3/** | options: [rw, bind]
MOUNT_DEST3: $SNAP_COMMON/target3/path/subpath
prepare: |
if ! [ -f /etc/audit/auditd.conf ] && os.query is-ubuntu && os.query is-classic; then
#shellcheck source=tests/lib/pkgdb.sh
. "$TESTSLIB/pkgdb.sh"
distro_install_package auditd
fi
mkdir -p "$MOUNT_SRC/dir1"
echo "Something" > "$MOUNT_SRC/file1"
restore: |
rm -f connect_error.log
rm -rf "$MOUNT_SRC"
execute: |
if [ "$SPREAD_REBOOT" = 0 ]; then
# first pass: install the snap and try basic mount operations
echo "First verify that a snap with a malicious manifest cannot be connected"
"$TESTSTOOLS"/snaps-state install-local test-mount-control-invalid
snap connect test-mount-control-invalid:mntctl 2> connect_error.log || true
if os.query is-trusty; then
echo "On Trusty, we should fail anyway due to systemd being too old"
MATCH "systemd version 204 is too old" < connect_error.log
exit 0
fi
MATCH 'mount-control "where" pattern is not clean' < connect_error.log
echo "Installing the test snap"
"$TESTSTOOLS"/snaps-state install-local "${SNAP_NAME}"
echo "Connecting the mount-control interface"
snap connect "${SNAP_NAME}":mntctl
echo "Verify that the snap can perform a mount"
mkdir -p "$MOUNT_DEST1"
"${SNAP_NAME}".cmd mount -o bind,rw "$MOUNT_SRC" "$MOUNT_DEST1"
echo "Verify that the mount has been performed"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo
echo "and that it's only in the snap's namespace"
NOMATCH "$MOUNT_DEST1" < /proc/self/mountinfo
echo "Ensure that the mounted files are visible"
"${SNAP_NAME}".cmd test -e "$MOUNT_DEST1/file1"
echo "Unmount via the system command umount(8)"
"${SNAP_NAME}".cmd umount "$MOUNT_DEST1"
if "${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo; then
echo "Unmount failed"
exit 1
fi
"${SNAP_NAME}".cmd test "!" -e "$MOUNT_DEST1/file1"
echo "Verify that a mount with the 'nofail' option can be created"
"${SNAP_NAME}".cmd mount -o bind,rw,nofail "$MOUNT_SRC" "$MOUNT_DEST1"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo
"${SNAP_NAME}".cmd umount "$MOUNT_DEST1"
echo "Verify that a mount with a specific FS type can be created"
"${SNAP_NAME}".cmd mkdir -p "$MOUNT_DEST2"
"${SNAP_NAME}".cmd mount -o rw -t tmpfs none "$MOUNT_DEST2/"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST2.*tmpfs" /proc/self/mountinfo
"${SNAP_NAME}".cmd umount "$MOUNT_DEST2/"
echo "Verify that a mount with fs-specific options can be created"
"${SNAP_NAME}".cmd mount -o rw,uid=2000,gid=2000 -t tmpfs none "$MOUNT_DEST2/"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST2.*tmpfs" /proc/self/mountinfo
"${SNAP_NAME}".cmd umount "$MOUNT_DEST2/"
if [ "$(snap debug confinement)" = partial ] ; then
echo "Early exit on systems where strict confinement does not work"
exit 0
fi
if os.query is-opensuse && ! os.query is-opensuse tumbleweed; then
echo "Early exit in OpenSUSE as confinement is disabled"
exit 0
fi
echo "Verify that a mount not matching the allowed pattern will fail"
if "${SNAP_NAME}".cmd mount -o bind,rw "$MOUNT_SRC" "/tmp/"; then
echo "Mount succeeded despite not matching the allowed pattern"
exit 1
fi
echo "Verify that a mount not matching the allowed options will fail"
if "${SNAP_NAME}".cmd mount -o sync "$MOUNT_SRC" "$MOUNT_DEST1"; then
echo "Mount succeeded despite not matching the allowed options"
exit 1
fi
echo "Verify that a mount not matching the allowed FS type will fail"
mkdir -p /media/somedir
if "${SNAP_NAME}".cmd mount -t debugfs "/dev/sda" "/media/somedir"; then
echo "Mount succeeded despite not matching the allowed FS type"
exit 1
fi
if os.query is-ubuntu && os.query is-classic; then
grep 'fstype="debugfs"' /var/log/audit/audit.log | MATCH 'info="failed type match"'
fi
rmdir /media/somedir
echo "Verify that a maliciously crafted path cannot bypass the allowed pattern"
if "${SNAP_NAME}".cmd mount -o bind,rw "$MOUNT_SRC" "$SNAP_COMMON/.."; then
echo "Malicious pattern was not blocked"
exit 1
fi
echo "Now create the same mount using snapctl"
"${SNAP_NAME}".cmd snapctl mount -o bind,rw "$MOUNT_SRC" "$MOUNT_DEST1"
echo "Verify the mount"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo
"${SNAP_NAME}".cmd test -e "$MOUNT_DEST1/file1"
echo "Unmount via snapctl"
"${SNAP_NAME}".cmd snapctl umount "$MOUNT_DEST1"
# Now try to create a persistent mount, but for a target which doesn't
# have the `persistent` flag set in the plug rules: it must fail
echo "Attempt persistent mount not allowed by plug specification"
"${SNAP_NAME}".cmd mkdir -p "$MOUNT_DEST3"
"${SNAP_NAME}".cmd snapctl mount --persistent -o bind,rw /usr/share "$MOUNT_DEST3" 2>&1 \
| MATCH 'snap "test-snapd-mount-control" lacks permissions to create the requested mount'
# Do the same, but for an allowed target: this should work
echo "Create a persistent mount"
"${SNAP_NAME}".cmd snapctl mount --persistent -o bind,rw "$MOUNT_SRC" "$MOUNT_DEST1"
echo "Verify that the persistent mount is also immediately available"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo
"${SNAP_NAME}".cmd test -e "$MOUNT_DEST1/file1"
REBOOT
else
# after reboot
echo "Verify that the persistent mount is still active"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo
"${SNAP_NAME}".cmd test -e "$MOUNT_DEST1/file1"
echo "Remove the persistent mount"
"${SNAP_NAME}".cmd snapctl umount "$MOUNT_DEST1"
echo "Verify that the mount is gone"
"${SNAP_NAME}".cmd grep "$MOUNT_DEST1" /proc/self/mountinfo && exit 1
"${SNAP_NAME}".cmd test "!" -e "$MOUNT_DEST1/file1"
fi
|