#!/usr/bin/env bash # group: rw # # Test FUSE exports' allow-other option # # Copyright (C) 2021 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # seq=$(basename "$0") echo "QA output created by $seq" status=1 # failure is the default! _cleanup() { _cleanup_qemu _cleanup_test_img rm -f "$EXT_MP" } trap "_cleanup; exit \$status" 0 1 2 3 15 # get standard environment, filters and checks . ../common.rc . ../common.filter . ../common.qemu _supported_fmt generic _supported_proto file # We create the FUSE export manually sudo -n -u nobody true || \ _notrun 'Password-less sudo as nobody required to test allow_other' # $1: Export ID # $2: Options (beyond the node-name and ID) # $3: Expected return value (defaults to 'return') # $4: Node to export (defaults to 'node-format') fuse_export_add() { allow_other_not_supported='option allow_other only allowed if' output=$( success_or_failure=yes _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'block-export-add', 'arguments': { 'type': 'fuse', 'id': '$1', 'node-name': '${4:-node-format}', $2 } }" \ "${3:-return}" \ "$allow_other_not_supported" \ | _filter_imgfmt ) if echo "$output" | grep -q "$allow_other_not_supported"; then # Shut down qemu gracefully so it can unmount the export _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'quit'}" \ 'return' wait=yes _cleanup_qemu _notrun "allow_other not supported" fi echo "$output" } EXT_MP="$TEST_DIR/fuse-export" _make_test_img 64k touch "$EXT_MP" echo echo '=== Test permissions ===' # $1: allow-other value ('on'/'off'/'auto') run_permission_test() { _launch_qemu \ -blockdev \ "$IMGFMT,node-name=node-format,file.driver=file,file.filename=$TEST_IMG" _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'qmp_capabilities'}" \ 'return' fuse_export_add 'export' \ "'mountpoint': '$EXT_MP', 'allow-other': '$1'" # Should always work echo '(Removing all permissions)' chmod 000 "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt stat -c 'Permissions post-chmod: %a' "$EXT_MP" # Should always work echo '(Granting u+r)' chmod u+r "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt stat -c 'Permissions post-chmod: %a' "$EXT_MP" # Should only work with allow-other: Otherwise, no permissions can be # granted to the group or others echo '(Granting read permissions for everyone)' chmod 444 "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt stat -c 'Permissions post-chmod: %a' "$EXT_MP" echo 'Doing operations as nobody:' # Change to TEST_DIR, so nobody will not have to attempt a lookup pushd "$TEST_DIR" >/dev/null # This is already prevented by the permissions (without allow-other, FUSE # exports always have o-r), but test it anyway sudo -n -u nobody cat fuse-export >/dev/null # If the only problem were the lack of permissions, we should still be able # to stat the export as nobody; it should not work without allow-other, # though sudo -n -u nobody \ stat -c 'Permissions seen by nobody: %a' fuse-export 2>&1 \ | _filter_imgfmt # To prove the point, revoke read permissions for others and try again chmod o-r fuse-export 2>&1 | _filter_testdir | _filter_imgfmt # Should fail sudo -n -u nobody cat fuse-export >/dev/null # Should work with allow_other sudo -n -u nobody \ stat -c 'Permissions seen by nobody: %a' fuse-export 2>&1 \ | _filter_imgfmt popd >/dev/null _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'quit'}" \ 'return' wait=yes _cleanup_qemu } # 'auto' should behave exactly like 'on', because 'on' tests that # allow_other works (otherwise, this test is skipped) for ao in off on auto; do echo echo "--- allow-other=$ao ---" run_permission_test "$ao" done # success, all done echo "*** done" rm -f $seq.full status=0