[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR |
Date: |
Wed, 6 Dec 2017 13:16:45 -0600 |
From: Eric Blake <address@hidden>
The NBD spec says that clients should not try to write/trim to
an export advertised as read-only by the server. But we failed
to check that, and would allow the block layer to use NBD with
BDRV_O_RDWR even when the server is read-only, which meant we
were depending on the server sending a proper EPERM failure for
various commands, and also exposes a leaky abstraction: using
qemu-io in read-write mode would succeed on 'w -z 0 0' because
of local short-circuiting logic, but 'w 0 0' would send a
request over the wire (where it then depends on the server, and
fails at least for qemu-nbd but might pass for other NBD
implementations).
With this patch, a client MUST request read-only mode to access
a server that is doing a read-only export, or else it will get
a message like:
can't open device nbd://localhost:10809/foo: request for write access conflicts
with read-only export
It is no longer possible to even attempt writes over the wire
(including the corner case of 0-length writes), because the block
layer enforces the explicit read-only request; this matches the
behavior of qcow2 when backed by a read-only POSIX file.
Fix several iotests to comply with the new behavior (since
qemu-nbd of an internal snapshot, as well as nbd-server-add over QMP,
default to a read-only export, we must tell blockdev-add/qemu-io to
set up a read-only client).
CC: address@hidden
Signed-off-by: Eric Blake <address@hidden>
Message-Id: <address@hidden>
Reviewed-by: Vladimir Sementsov-Ogievskiy <address@hidden>
(cherry picked from commit 1104d83c726d2b20f9cec7b99ab3570a2fdbd46d)
Signed-off-by: Michael Roth <address@hidden>
---
block/nbd-client.c | 9 +++++++++
tests/qemu-iotests/058 | 8 ++++----
tests/qemu-iotests/140 | 4 ++--
tests/qemu-iotests/147 | 1 +
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/block/nbd-client.c b/block/nbd-client.c
index ea728fffc8..db9d41eb04 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -256,6 +256,7 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t
offset,
NBDReply reply;
ssize_t ret;
+ assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
if (flags & BDRV_REQ_FUA) {
assert(client->info.flags & NBD_FLAG_SEND_FUA);
request.flags |= NBD_CMD_FLAG_FUA;
@@ -284,6 +285,7 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs,
int64_t offset,
};
NBDReply reply;
+ assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
return -ENOTSUP;
}
@@ -339,6 +341,7 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t
offset, int bytes)
NBDReply reply;
ssize_t ret;
+ assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
return 0;
}
@@ -403,6 +406,12 @@ int nbd_client_init(BlockDriverState *bs,
logout("Failed to negotiate with the NBD server\n");
return ret;
}
+ if (client->info.flags & NBD_FLAG_READ_ONLY &&
+ !bdrv_is_read_only(bs)) {
+ error_setg(errp,
+ "request for write access conflicts with read-only export");
+ return -EACCES;
+ }
if (client->info.flags & NBD_FLAG_SEND_FUA) {
bs->supported_write_flags = BDRV_REQ_FUA;
bs->supported_zero_flags |= BDRV_REQ_FUA;
diff --git a/tests/qemu-iotests/058 b/tests/qemu-iotests/058
index 2253c6a6d1..5eb8784669 100755
--- a/tests/qemu-iotests/058
+++ b/tests/qemu-iotests/058
@@ -117,15 +117,15 @@ _export_nbd_snapshot sn1
echo
echo "== verifying the exported snapshot with patterns, method 1 =="
-$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
-$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
_export_nbd_snapshot1 sn1
echo
echo "== verifying the exported snapshot with patterns, method 2 =="
-$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
-$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
+$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" |
_filter_qemu_io
$QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image"
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
index f89d0d6789..a8fc95145c 100755
--- a/tests/qemu-iotests/140
+++ b/tests/qemu-iotests/140
@@ -78,7 +78,7 @@ _send_qemu_cmd $QEMU_HANDLE \
'arguments': { 'device': 'drv' }}" \
'return'
-$QEMU_IO_PROG -f raw -c 'read -P 42 0 64k' \
+$QEMU_IO_PROG -f raw -r -c 'read -P 42 0 64k' \
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
| _filter_qemu_io | _filter_nbd
@@ -87,7 +87,7 @@ _send_qemu_cmd $QEMU_HANDLE \
'arguments': { 'device': 'drv' }}" \
'return'
-$QEMU_IO_PROG -f raw -c close \
+$QEMU_IO_PROG -f raw -r -c close \
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
| _filter_qemu_io | _filter_nbd
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
index db34838cd0..90f40ed245 100755
--- a/tests/qemu-iotests/147
+++ b/tests/qemu-iotests/147
@@ -43,6 +43,7 @@ class NBDBlockdevAddBase(iotests.QMPTestCase):
'driver': 'raw',
'file': {
'driver': 'nbd',
+ 'read-only': True,
'server': address
} }
if export is not None:
--
2.11.0
- [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped, (continued)
- [Qemu-devel] [PATCH 47/55] virtio-net: don't touch virtqueue if vm is stopped, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 48/55] nbd/server: CVE-2017-15119 Reject options larger than 32M, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 42/55] vhost: restore avail index from vring used index on disconnection, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 44/55] spapr: reset DRCs after devices, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 46/55] block/nfs: fix nfs_client_open for filesize greater than 1TB, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 50/55] vhost: fix error check in vhost_verify_ring_mappings(), Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 43/55] hw/ppc: clear pending_events on machine reset, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 49/55] nbd/server: CVE-2017-15118 Stack smash on large export name, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 45/55] scripts/make-release: ship u-boot source as a tarball, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 04/55] kvmclock: use the updated system_timer_msr, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 52/55] nbd-client: Refuse read-only client with BDRV_O_RDWR,
Michael Roth <=
- [Qemu-devel] [PATCH 53/55] nbd/client: Don't hard-disconnect on ESHUTDOWN from server, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 51/55] nbd/server: fix nbd_negotiate_handle_info, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 54/55] vga: drop line_offset variable, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 55/55] vga: handle cirrus vbe mode wraparounds., Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 06/55] exec: Explicitly export target AS from address_space_translate_internal, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 05/55] block: Perform copy-on-read in loop, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 08/55] memory: Move FlatView allocation to a helper, Michael Roth, 2017/12/06
- [Qemu-devel] [PATCH 07/55] memory: Open code FlatView rendering, Michael Roth, 2017/12/06