aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/export/fuse.c28
-rw-r--r--qapi/block-export.json33
-rwxr-xr-xtests/qemu-iotests/3086
-rw-r--r--tests/qemu-iotests/common.rc6
4 files changed, 65 insertions, 8 deletions
diff --git a/block/export/fuse.c b/block/export/fuse.c
index d0b88e8..4068250 100644
--- a/block/export/fuse.c
+++ b/block/export/fuse.c
@@ -46,6 +46,8 @@ typedef struct FuseExport {
char *mountpoint;
bool writable;
bool growable;
+ /* Whether allow_other was used as a mount option or not */
+ bool allow_other;
} FuseExport;
static GHashTable *exports;
@@ -57,7 +59,7 @@ static void fuse_export_delete(BlockExport *exp);
static void init_exports_table(void);
static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
- Error **errp);
+ bool allow_other, Error **errp);
static void read_from_fuse_export(void *opaque);
static bool is_regular_file(const char *path, Error **errp);
@@ -118,7 +120,22 @@ static int fuse_export_create(BlockExport *blk_exp,
exp->writable = blk_exp_args->writable;
exp->growable = args->growable;
- ret = setup_fuse_export(exp, args->mountpoint, errp);
+ /* set default */
+ if (!args->has_allow_other) {
+ args->allow_other = FUSE_EXPORT_ALLOW_OTHER_AUTO;
+ }
+
+ if (args->allow_other == FUSE_EXPORT_ALLOW_OTHER_AUTO) {
+ /* Ignore errors on our first attempt */
+ ret = setup_fuse_export(exp, args->mountpoint, true, NULL);
+ exp->allow_other = ret == 0;
+ if (ret < 0) {
+ ret = setup_fuse_export(exp, args->mountpoint, false, errp);
+ }
+ } else {
+ exp->allow_other = args->allow_other == FUSE_EXPORT_ALLOW_OTHER_ON;
+ ret = setup_fuse_export(exp, args->mountpoint, exp->allow_other, errp);
+ }
if (ret < 0) {
goto fail;
}
@@ -146,7 +163,7 @@ static void init_exports_table(void)
* Create exp->fuse_session and mount it.
*/
static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
- Error **errp)
+ bool allow_other, Error **errp)
{
const char *fuse_argv[4];
char *mount_opts;
@@ -157,8 +174,9 @@ static int setup_fuse_export(FuseExport *exp, const char *mountpoint,
* max_read needs to match what fuse_init() sets.
* max_write need not be supplied.
*/
- mount_opts = g_strdup_printf("max_read=%zu,default_permissions",
- FUSE_MAX_BOUNCE_BYTES);
+ mount_opts = g_strdup_printf("max_read=%zu,default_permissions%s",
+ FUSE_MAX_BOUNCE_BYTES,
+ allow_other ? ",allow_other" : "");
fuse_argv[0] = ""; /* Dummy program name */
fuse_argv[1] = "-o";
diff --git a/qapi/block-export.json b/qapi/block-export.json
index e819e70..0ed6344 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -121,6 +121,23 @@
'*num-queues': 'uint16'} }
##
+# @FuseExportAllowOther:
+#
+# Possible allow_other modes for FUSE exports.
+#
+# @off: Do not pass allow_other as a mount option.
+#
+# @on: Pass allow_other as a mount option.
+#
+# @auto: Try mounting with allow_other first, and if that fails, retry
+# without allow_other.
+#
+# Since: 6.1
+##
+{ 'enum': 'FuseExportAllowOther',
+ 'data': ['off', 'on', 'auto'] }
+
+##
# @BlockExportOptionsFuse:
#
# Options for exporting a block graph node on some (file) mountpoint
@@ -132,11 +149,25 @@
# @growable: Whether writes beyond the EOF should grow the block node
# accordingly. (default: false)
#
+# @allow-other: If this is off, only qemu's user is allowed access to
+# this export. That cannot be changed even with chmod or
+# chown.
+# Enabling this option will allow other users access to
+# the export with the FUSE mount option "allow_other".
+# Note that using allow_other as a non-root user requires
+# user_allow_other to be enabled in the global fuse.conf
+# configuration file.
+# In auto mode (the default), the FUSE export driver will
+# first attempt to mount the export with allow_other, and
+# if that fails, try again without.
+# (since 6.1; default: auto)
+#
# Since: 6.0
##
{ 'struct': 'BlockExportOptionsFuse',
'data': { 'mountpoint': 'str',
- '*growable': 'bool' },
+ '*growable': 'bool',
+ '*allow-other': 'FuseExportAllowOther' },
'if': 'defined(CONFIG_FUSE)' }
##
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
index 11c28a7..d13a9a9 100755
--- a/tests/qemu-iotests/308
+++ b/tests/qemu-iotests/308
@@ -58,6 +58,9 @@ _supported_os Linux # We need /dev/urandom
# $4: Node to export (defaults to 'node-format')
fuse_export_add()
{
+ # The grep -v is a filter for errors when /etc/fuse.conf does not contain
+ # user_allow_other. (The error is benign, but it is printed by fusermount
+ # on the first mount attempt, so our export code cannot hide it.)
_send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'block-export-add',
'arguments': {
@@ -67,7 +70,8 @@ fuse_export_add()
$2
} }" \
"${3:-return}" \
- | _filter_imgfmt
+ | _filter_imgfmt \
+ | grep -v 'option allow_other only allowed if'
}
# $1: Export ID
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index cbbf6d7..609d82d 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -512,9 +512,13 @@ _make_test_img()
# Usually, users would export formatted nodes. But we present fuse as a
# protocol-level driver here, so we have to leave the format to the
# client.
+ # Switch off allow-other, because in general we do not need it for
+ # iotests. The default allow-other=auto has the downside of printing a
+ # fusermount error on its first attempt if allow_other is not
+ # permissible, which we would need to filter.
QSD_NEED_PID=y $QSD \
--blockdev file,node-name=export-node,filename=$img_name,discard=unmap \
- --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=on \
+ --export fuse,id=fuse-export,node-name=export-node,mountpoint="$export_mp",writable=on,growable=on,allow-other=off \
&
pidfile="$QEMU_TEST_DIR/qemu-storage-daemon.pid"