diff --git a/README.md b/README.md index 73989b857f5e0d9ff2200208dd506011845038fa..2c8af6eabe6b7d09beac91da93e71ee054de1474 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ -# apparmor-tumbler +apparmor-tumbler test +Debug output variables: + +* DEBUG=1 will enable all output, stdout and stderr (disabled by default) diff --git a/apparmor-tumbler.yaml b/apparmor-tumbler.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2e62b2032390c13dc8c15714c977615ba9677a03 --- /dev/null +++ b/apparmor-tumbler.yaml @@ -0,0 +1,26 @@ +metadata: + name: apparmor-tumbler + format: "Lava-Test-Shell Test Definition 1.0" + description: "Tests that the tumbler AppArmor profile doesn't cause false negatives + and that it does not allow arbitrary reading of files in the home directory." + maintainer: "luis.araujo@collabora.co.uk" + scope: + - functional + devices: + - i386 + environment: + - lava-test-shell + +run: + steps: + - common/run-test-in-systemd --name run-test-sh --timeout 900 ./run-test.sh + +parse: + fixupdict: + FAILED: fail + PASSED: pass + FAIL: fail + PASS: pass + SKIP: skip + UNKNOWN: unknown + pattern: ^(?P<test_case_id>[\w\-\.]+):\s(?P<result>PASS|pass|FAIL|fail|SKIP|skip|UNKNOWN|unknown)$ diff --git a/config.sh b/config.sh new file mode 100644 index 0000000000000000000000000000000000000000..2f61bbd497c2b276672e04e8d39326257c1474c6 --- /dev/null +++ b/config.sh @@ -0,0 +1 @@ +. "${TESTDIR}/common/inherit-config.sh" diff --git a/resources/media/documents/lorem_ipsum.pdf b/resources/media/documents/lorem_ipsum.pdf new file mode 100644 index 0000000000000000000000000000000000000000..619776ef3f8f043cba6c6bbae2672e8309823c58 Binary files /dev/null and b/resources/media/documents/lorem_ipsum.pdf differ diff --git a/resources/media/documents/lorem_presentation.odp b/resources/media/documents/lorem_presentation.odp new file mode 100644 index 0000000000000000000000000000000000000000..b4df0bc3b10ba542b4a7912c8e1d7036eddd35fc Binary files /dev/null and b/resources/media/documents/lorem_presentation.odp differ diff --git a/resources/media/documents/lorem_spreadsheet.ods b/resources/media/documents/lorem_spreadsheet.ods new file mode 100644 index 0000000000000000000000000000000000000000..9a5833a8db3e2a92d04d3e4220cad5053f7d43cf Binary files /dev/null and b/resources/media/documents/lorem_spreadsheet.ods differ diff --git a/resources/media/documents/lorem_text.txt b/resources/media/documents/lorem_text.txt new file mode 100644 index 0000000000000000000000000000000000000000..a8245a605d4972ef13111e20109c15e6560e7911 --- /dev/null +++ b/resources/media/documents/lorem_text.txt @@ -0,0 +1,11 @@ +Sed quis felis ac enim condimentum tempus. Suspendisse imperdiet consequat urna +a ultrices. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices +posuere cubilia Curae; Vestibulum faucibus sem et sem placerat dapibus. In +dictum elit in dolor porta ullamcorper. Nulla facilisi. Etiam ac neque nunc. +Donec scelerisque pulvinar feugiat. Nulla congue varius diam rhoncus dapibus. +Ut metus libero, porttitor vitae vestibulum sed, interdum quis dui. Suspendisse +sagittis dui at ante semper at semper erat tincidunt. Nullam sed dolor semper +turpis suscipit congue. Nulla diam ipsum, elementum id fringilla eu, tincidunt +fringilla lorem. Ut nec est id arcu facilisis bibendum sed vel nisl. Nullam +venenatis, nisi et ornare scelerisque, enim ligula blandit nunc, a porttitor +elit tellus eleifend sapien. diff --git a/resources/media/documents/more_lorem_ipsum.odt b/resources/media/documents/more_lorem_ipsum.odt new file mode 100644 index 0000000000000000000000000000000000000000..fa38dd13d149656873667d5666f9166d646d05dd Binary files /dev/null and b/resources/media/documents/more_lorem_ipsum.odt differ diff --git a/resources/media/images/320px-European_Common_Frog_Rana_temporaria.jpg b/resources/media/images/320px-European_Common_Frog_Rana_temporaria.jpg new file mode 100644 index 0000000000000000000000000000000000000000..105bb39903ba68b2a047bc93fb5c78a49eca14ad Binary files /dev/null and b/resources/media/images/320px-European_Common_Frog_Rana_temporaria.jpg differ diff --git a/resources/media/images/collabora-logo-big.png b/resources/media/images/collabora-logo-big.png new file mode 100644 index 0000000000000000000000000000000000000000..8de06b5e720431f0217910eedc2c049360372bcd Binary files /dev/null and b/resources/media/images/collabora-logo-big.png differ diff --git a/resources/media/videos/big_buck_bunny_smaller.ogv b/resources/media/videos/big_buck_bunny_smaller.ogv new file mode 100644 index 0000000000000000000000000000000000000000..010216c906fb2363e600b2c7293e979431c52314 Binary files /dev/null and b/resources/media/videos/big_buck_bunny_smaller.ogv differ diff --git a/run-test.sh b/run-test.sh new file mode 100755 index 0000000000000000000000000000000000000000..605ff1b99837ad354cdef6c80b1d65a1f4a5433d --- /dev/null +++ b/run-test.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# vim: tw=0 + +TESTDIR=$(cd $(dirname $0); pwd; cd - >/dev/null 2>&1) +. "${TESTDIR}/config.sh" + +# We want to use the pre-existing session bus. +export LAUNCH_DBUS="no" + +error=0 +"${TESTDIR}"/common/run-aa-test "${TESTDIR}"/tumbler.normal.expected "${TESTDIR}"/tumbler normal || error=$? +"${TESTDIR}"/common/run-aa-test "${TESTDIR}"/tumbler.malicious.expected "${TESTDIR}"/tumbler malicious || error=$? + +if [ $error = 0 ]; then + echo "# apparmor-tumbler: all tests passed" +else + echo "# apparmor-tumbler: at least one test failed" +fi + +exit $error diff --git a/test-tumbler b/test-tumbler new file mode 100755 index 0000000000000000000000000000000000000000..c393b28dab907f0866a471e80274b9b5bb45cace --- /dev/null +++ b/test-tumbler @@ -0,0 +1,164 @@ +#!/bin/bash +# vim: set sts=4 sw=4 et tw=0 : + +set -e + +TESTDIR=$(cd $(dirname $0); pwd; cd - >/dev/null 2>&1) +. "${TESTDIR}/config.sh" + +. "${TESTDIR}/common/update-test-path" + +MEDIA_RESOURCE_DIR="$(cd "${TESTDIR}/resources/media" && pwd)" + +######### +# Setup # +######### +trap "setup_failure" EXIT + +set -x +# Need a DBus session for this test +ensure_dbus_session +set +x + +setup_success + +########### +# Execute # +########### +_launch_monitor() { + # Launch tumblerd manually to allow LD_PRELOAD to work for + # chaiwala-apparmor-tumbler-tests + pkill tumblerd || true + /usr/lib/*-linux-gnu*/tumbler-1/tumblerd & + TUMBLERD_PID=$! + sleep 5 + # Launch and monitor the thumbnailer + ${GDBUS} monitor --session --dest "${addr}" --object-path "${obj_path}" >"${logfile}" & + GDBUS_MONITOR_PID=$! +} + +_kill_monitor_return() { + kill -s TERM $GDBUS_MONITOR_PID || true + kill -s TERM $TUMBLERD_PID || true + return $1 +} + +bash_arrays_to_gvariant_as() { + local i converted="['$1'" + shift + for i in "$@"; do + converted+=", '$i'" + done + converted+="]" + echo "${converted}" +} + +_check_uris_have_thumbnail() { + local size=$1 + local uris=$2 + for i in "${uris[@]}"; do + local thumb="${HOME}/.cache/thumbnails/${size}/$(echo -n "${i}" | md5sum | cut -f1 -d\ ).png" + say $thumb + if [[ ! -f "${thumb}" ]]; then + whine "Couldn't find thumbnail $thumb, file $i didn't get thumbnailed!?" + ret=1 + fi + done +} + +_generate_thumbnails() { + set -x + local i ret files logfile addr obj_path method uris filetypes + local copy + ret=0 + local size="$1" + local special_dir="$2" + shift 2 + files=("$@") + logfile="${WORKDIR}/monitor-tumblerd.log" + addr="org.freedesktop.thumbnails.Thumbnailer1" + obj_path="/org/freedesktop/thumbnails/Thumbnailer1" + method="org.freedesktop.thumbnails.Thumbnailer1.Queue" + uris=() + filetypes=() + + for i in "${files[@]}"; do + # Tumbler's AppArmor profile doesn't necessarily let it read the + # apertis-tests directory if we're running uninstalled. Copy the + # file to a more realistic location, which exercises the AppArmor + # profile better anyway. + if [ $(( $RANDOM % 2 )) = 0 ] && [ -e "/home/shared/$special_dir" ]; then + copy="/home/shared/$special_dir/apertis-tests__$(basename "$i")" + else + copy="$HOME/$special_dir/apertis-tests__$(basename "$i")" + fi + + cp -v "$i" "$copy" + + # Need path relative to / + # FIXME: This doesn't do whitespace/special character escaping, etc + uris+=("file://$copy") + filetypes+=($(file --mime-type "$copy" | cut -d ":" -f 2 | tr -d ' ')) + done + + # Clear out old thumbnails. + rm -rf ${HOME}/.cache/thumbnails/ + + _launch_monitor + + # Files to thumbnail + ${GDBUS} call --session --dest "${addr}" --object-path "${obj_path}" \ + --method "${method}" \ + "$(bash_arrays_to_gvariant_as "${uris[@]}")" \ + "$(bash_arrays_to_gvariant_as "${filetypes[@]}")" \ + "${size}" foreground 0 + + # Wait for thumbnailing to finish + # FIXME: Race condition! Fix me to loop on the monitor log file. + _sleep 2 + _check_uris_have_thumbnail $size $uris || ret=1 + + rm -f "/home/shared/$special_dir"/apertis-tests__* + rm -f "${HOME}/$special_dir"/apertis-tests__* + + _kill_monitor_return $ret + set +x +} + +test_image_normal_thumbnail_generation() { + _generate_thumbnails normal Pictures "${MEDIA_RESOURCE_DIR}/images"/* +} + +test_image_large_thumbnail_generation() { + _generate_thumbnails large Pictures "${MEDIA_RESOURCE_DIR}/images"/* +} + +test_video_normal_thumbnail_generation() { + _generate_thumbnails normal Videos "${MEDIA_RESOURCE_DIR}/videos"/* +} + +test_video_large_thumbnail_generation() { + _generate_thumbnails large Videos "${MEDIA_RESOURCE_DIR}/videos"/* +} + +test_document_normal_thumbnail_generation() { + _generate_thumbnails normal Documents "${MEDIA_RESOURCE_DIR}/documents"/*.{pdf,odt} +} + +test_document_large_thumbnail_generation() { + _generate_thumbnails large Documents "${MEDIA_RESOURCE_DIR}/documents"/*.{pdf,odt} +} + +trap "test_failure" EXIT + +# NOTE: Tumbler cannot thumbnail audio files +src_test_pass <<-EOF +test_image_normal_thumbnail_generation +test_image_large_thumbnail_generation +test_document_normal_thumbnail_generation +test_document_large_thumbnail_generation +test_video_normal_thumbnail_generation +test_video_large_thumbnail_generation +EOF + +test_success diff --git a/tumbler b/tumbler new file mode 100755 index 0000000000000000000000000000000000000000..134aea19af0ec142d94cfcfd8e8a9a7375c24987 --- /dev/null +++ b/tumbler @@ -0,0 +1,36 @@ +#!/bin/sh +# vim: set sts=4 sw=4 et tw=0 : + +TESTDIR=$(cd $(dirname $0); pwd; cd - >/dev/null 2>&1) +. "${TESTDIR}/config.sh" + +. "${TESTDIR}/common/update-test-path" + +if [ $# -ne 1 ] || { [ "$1" != normal ] && [ "$1" != malicious ] ; } +then + echo "Usage: $0 <normal|malicious>" + exit 1 +fi + +export APERTIS_TESTS_NAME_PREFIX="${1}_" + +if [ "$1" = malicious ]; then + # Lets copy the system tumbler apparmor profile and modify it to allow + # loading the preloaded library + TMP_DIR=$(mktemp -d) + cp /etc/apparmor.d/usr.lib.tumbler-1.tumblerd ${TMP_DIR} + rule=" ${TESTDIR}/${ARCHDIR}/lib/libtumbler-malicious-override.so rm," + rule=$(echo "$rule" | sed 's/\//\\\//g') + sed -i ${TMP_DIR}/usr.lib.tumbler-1.tumblerd -e "s/\(\/usr\/lib\/\*\/tumbler-1\/tumblerd {\)/\1\n${rule}/g" + echo ">> Loading apparmor profile ${TMP_DIR}/usr.lib.tumbler-1.tumblerd" + sudo apparmor_parser -r ${TMP_DIR}/usr.lib.tumbler-1.tumblerd + + LD_PRELOAD="${TESTDIR}/${ARCHDIR}/lib/libtumbler-malicious-override.so" \ + $TESTDIR/test-tumbler + + echo ">> Reloading apparmor profile /etc/apparmor.d/usr.lib.tumbler-1.tumblerd" + sudo apparmor_parser -r /etc/apparmor.d/usr.lib.tumbler-1.tumblerd +else + $TESTDIR/test-tumbler +fi + diff --git a/tumbler.malicious.expected b/tumbler.malicious.expected new file mode 100644 index 0000000000000000000000000000000000000000..6072727cda9804dbd3b8f97c09904d2a6b64bbde --- /dev/null +++ b/tumbler.malicious.expected @@ -0,0 +1,42 @@ +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r +==== +profile:/usr/lib/*/tumbler-1/tumblerd +sdmode:REJECTING +denied_mask:r +operation:open +name:/home/user/.bash_history +request_mask:r diff --git a/tumbler.normal.expected b/tumbler.normal.expected new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391