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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
summary: Ensure that the personal-files interface works.
details: |
The personal-files interface allows access specific personal files or
directories. Missing parent directories of write paths are created when a
snap application is run by a non-root user.
environment:
TEST_USER_HOME: /home/test
TEST_USER2: test2
TEST_USER2_HOME: /home/test2
TEST_USER3: test3
ROOT_OWNED_DIR: /etc
prepare: |
"$TESTSTOOLS"/snaps-state install-local test-snapd-sh
# First layer of dirs and files
"$TESTSTOOLS"/fs-state mock-file /root/.testfile1
"$TESTSTOOLS"/fs-state mock-file /root/testfile1
"$TESTSTOOLS"/fs-state mock-dir /root/.testdir1
"$TESTSTOOLS"/fs-state mock-dir /root/testdir1
# Second layer of dirs and files
"$TESTSTOOLS"/fs-state mock-file /root/.testdir1/.testfile2
"$TESTSTOOLS"/fs-state mock-file "/root/.testdir1/test file2"
"$TESTSTOOLS"/fs-state mock-dir /root/.testdir1/.testdir2
# Not accessible dirs and files
"$TESTSTOOLS"/fs-state mock-dir /var/tmp/.testdir1
"$TESTSTOOLS"/fs-state mock-file /var/tmp/.testfile1
"$TESTSTOOLS"/fs-state mock-dir /var/tmp/root
"$TESTSTOOLS"/fs-state mock-file /var/tmp/root/testfile2
"$TESTSTOOLS"/fs-state mock-file /var/tmp/root/.testfile2
# Ubuntu 14.04 does not have busctl required by tests.session
if ! os.query is-ubuntu 14.04; then
# Create additional users.
tests.session -u test prepare
if ! useradd -m -d "$TEST_USER2_HOME" "$TEST_USER2"; then
# Ubuntu Core requires using extrausers db
useradd --extrausers -m -d "$TEST_USER2_HOME" "$TEST_USER2"
fi
tests.session -u "$TEST_USER2" prepare
if ! useradd -M "$TEST_USER3"; then
useradd --extrausers -M "$TEST_USER3"
fi
tests.session -u "$TEST_USER3" prepare
fi
restore: |
if ! os.query is-ubuntu 14.04; then
tests.session -u test restore
tests.session -u "$TEST_USER2" restore
tests.session -u "$TEST_USER3" restore
if ! userdel -rf "$TEST_USER2"; then
userdel --extrausers -rf "$TEST_USER2"
fi
if ! userdel -rf "$TEST_USER3"; then
userdel --extrausers -rf "$TEST_USER3"
fi
fi
"$TESTSTOOLS"/fs-state restore-file /root/.testfile1
"$TESTSTOOLS"/fs-state restore-file /root/testfile1
"$TESTSTOOLS"/fs-state restore-dir /root/.testdir1
"$TESTSTOOLS"/fs-state restore-dir /root/testdir1
"$TESTSTOOLS"/fs-state restore-dir /var/tmp/.testdir1
"$TESTSTOOLS"/fs-state restore-file /var/tmp/.testfile1
"$TESTSTOOLS"/fs-state restore-dir /var/tmp/root
rm -rf "$TEST_USER_HOME/.testdir1"
rm -rf "$TEST_USER_HOME/.missing/testdir1"
execute: |
echo "The interface is not connected by default"
snap interfaces -i personal-files | MATCH "\\- +test-snapd-sh:personal-files"
echo "When the interface is connected"
snap connect test-snapd-sh:personal-files
echo "There is a single \"ensure-dir\" kind of user mount entry for \$HOME/.local/share"
test -e /var/lib/snapd/mount/snap.test-snapd-sh.user-fstab
test "$(wc -l </var/lib/snapd/mount/snap.test-snapd-sh.user-fstab)" -eq 1
# shellcheck disable=SC2016
MATCH 'none \$HOME/.missing none x-snapd.kind=ensure-dir,x-snapd.must-exist-dir=\$HOME 0 0' < /var/lib/snapd/mount/snap.test-snapd-sh.user-fstab
echo "Find snap-confine"
SNAP_CONFINE=$(os.paths libexec-dir)/snapd/snap-confine
if tests.info is-snapd-from-archive; then
MOUNT_DIR="$(os.paths snap-mount-dir)"
SNAP_CONFINE="$MOUNT_DIR/snapd/current$SNAP_CONFINE"
fi
# on Ubuntu Core we need to use the correct path to ensure it is
# appropriately confined by apparmor as it may be from the snapd
# snap
if os.query is-core16; then
# on uc16, we should just use /usr/lib/snapd/snap-confine from the host
# which by definition will come from the currently installed core snap
SNAP_CONFINE=/usr/lib/snapd/snap-confine
elif os.query is-core; then
# on UC18+, snap-confine will come from the snapd snap, so use the
# active installed revision as the snap-confine to execute
SNAPD_SNAP_REV=$(snap list snapd | tail -n +2 | awk '{print $3}')
SNAP_CONFINE="/snap/snapd/$SNAPD_SNAP_REV/usr/lib/snapd/snap-confine"
fi
# Ubuntu 14.04 does not have busctl required by tests.session
if ! os.query is-ubuntu 14.04; then
echo "Cannot abuse snap-confine to create $TEST_USER_HOME/.missing owned by user $TEST_USER2"
# This command is based on what snap run contructs for running a non-classic app with non-root user without the final snap-exec stage
cmd="SNAP_INSTANCE_NAME=test-snapd-sh SNAP_REVISION=x1 SNAP_REAL_HOME=$TEST_USER_HOME $SNAP_CONFINE snap.test-snapd-sh.with-personal-files-plug /bin/sh -c exit"
if tests.session -u $TEST_USER2 exec sh -c "$cmd" > call.error 2>&1; then
echo 'Expected error: "snap-update-ns failed with code 1"'
exit 1
fi
# shellcheck disable=SC2016
MATCH 'cannot update snap namespace: cannot expand mount entry \(none \$HOME/.missing none x-snapd.kind=ensure-dir,x-snapd.must-exist-dir=\$HOME 0 0\): cannot use invalid home directory '"\"$TEST_USER_HOME\": permission denied" < call.error
MATCH "snap-update-ns failed with code 1" < call.error
echo "Cannot abuse snap-confine to create $ROOT_OWNED_DIR/.missing owned by user $TEST_USER2"
# This command is based on what snap run contructs for running a non-classic app with non-root user without the final snap-exec stage
cmd="SNAP_INSTANCE_NAME=test-snapd-sh SNAP_REVISION=x1 SNAP_REAL_HOME=$ROOT_OWNED_DIR $SNAP_CONFINE snap.test-snapd-sh.with-personal-files-plug /bin/sh -c exit"
tests.session -u $TEST_USER2 exec sh -c "$cmd" 2> call.error
prefix="cannot change mount namespace according to change mount \(none $ROOT_OWNED_DIR/.missing none x-snapd.kind=ensure-dir,x-snapd.must-exist-dir=$ROOT_OWNED_DIR 0 0\)"
MATCH "$prefix: cannot create directory \"$ROOT_OWNED_DIR/.missing\": permission denied" < call.error || \
MATCH "$prefix: cannot operate on read-only filesystem at $ROOT_OWNED_DIR" < call.error
echo "The snap run as user $TEST_USER3 without a home directory will error"
if tests.session -u "$TEST_USER3" exec test-snapd-sh.with-personal-files-plug -c "exit" > call.error 2>&1; then
echo 'Expected error: "snap-update-ns failed with code 1"'
exit 1
fi
# shellcheck disable=SC2016
MATCH 'cannot update snap namespace: cannot expand mount entry \(none \$HOME/.missing none x-snapd.kind=ensure-dir,x-snapd.must-exist-dir=\$HOME 0 0\): cannot use invalid home directory '"\"/home/$TEST_USER3\": no such file or directory" < call.error
MATCH "snap-update-ns failed with code 1" < call.error
echo "The snap run as user test can create /home/test/testdir and /home/test/.missing/testdir1"
tests.session -u test exec test-snapd-sh.with-personal-files-plug -c "mkdir -p $TEST_USER_HOME/.testdir1"
tests.session -u test exec test-snapd-sh.with-personal-files-plug -c "mkdir -p $TEST_USER_HOME/.missing/testdir1"
fi
echo "The snap is able to access all the files and dirs in $HOME"
test-snapd-sh.with-personal-files-plug -c "cat /root/.testfile1" | MATCH "mock file"
test-snapd-sh.with-personal-files-plug -c "cat /root/testfile1" | MATCH "mock file"
test-snapd-sh.with-personal-files-plug -c "ls /root/.testdir1"
test-snapd-sh.with-personal-files-plug -c "ls /root/testdir1"
test-snapd-sh.with-personal-files-plug -c "cat /root/.testdir1/.testfile2" | MATCH "mock file"
test-snapd-sh.with-personal-files-plug -c "cat '/root/.testdir1/test file2'" | MATCH "mock file"
test-snapd-sh.with-personal-files-plug -c "ls /root/.testdir1/.testdir2/"
echo "The snap is able to write on /root/.testdir1 and /root/.testfile1"
test-snapd-sh.with-personal-files-plug -c "echo test >> /root/.testfile1"
test-snapd-sh.with-personal-files-plug -c "touch /root/.testdir1/testfile2"
if [ "$(snap debug confinement)" = partial ] ; then
exit 0
fi
echo "The snap is not able to write outside /root/.testdir1 and /root/.testfile1"
if test-snapd-sh.with-personal-files-plug -c "echo test >> /root/testfile1" 2> call.error; then
echo "Expected permission error writing the personal file"
exit 1
fi
MATCH "Permission denied" < call.error
echo "The snap is not able to to access files and dirs outside $HOME"
test-snapd-sh.with-personal-files-plug -c "ls /var/tmp/.testdir1" 2>&1| MATCH "Permission denied"
test-snapd-sh.with-personal-files-plug -c "cat /var/tmp/.testfile1" 2>&1| MATCH "Permission denied"
test-snapd-sh.with-personal-files-plug -c "ls /var/tmp/root/" 2>&1| MATCH "Permission denied"
test-snapd-sh.with-personal-files-plug -c "cat /var/tmp/root/testfile2" 2>&1| MATCH "Permission denied"
test-snapd-sh.with-personal-files-plug -c "cat /var/tmp/root/.testfile2" 2>&1| MATCH "Permission denied"
echo "When the plug is disconnected"
snap disconnect test-snapd-sh:personal-files
echo "There are no user mount entries"
test ! -e /var/lib/snapd/mount/snap.test-snapd-sh.user-fstab
echo "The snap is not able to read files and dirs in $HOME"
if test-snapd-sh.with-personal-files-plug -c "ls /root/.testdir1" 2> call.error; then
echo "Expected permission error accessing the personal dir"
exit 1
fi
MATCH "Permission denied" < call.error
if test-snapd-sh.with-personal-files-plug -c "cat /root/.testfile1" 2> call.error; then
echo "Expected permission error accessing the personal file"
exit 1
fi
MATCH "Permission denied" < call.error
|