aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/nbd-client.c21
-rw-r--r--block/trace-events1
2 files changed, 17 insertions, 5 deletions
diff --git a/block/nbd-client.c b/block/nbd-client.c
index bfbaf7ebe9..8fe660b609 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -240,8 +240,8 @@ static int nbd_parse_offset_hole_payload(NBDStructuredReplyChunk *chunk,
}
/* nbd_parse_blockstatus_payload
- * support only one extent in reply and only for
- * base:allocation context
+ * Based on our request, we expect only one extent in reply, for the
+ * base:allocation context.
*/
static int nbd_parse_blockstatus_payload(NBDClientSession *client,
NBDStructuredReplyChunk *chunk,
@@ -250,7 +250,8 @@ static int nbd_parse_blockstatus_payload(NBDClientSession *client,
{
uint32_t context_id;
- if (chunk->length != sizeof(context_id) + sizeof(*extent)) {
+ /* The server succeeded, so it must have sent [at least] one extent */
+ if (chunk->length < sizeof(context_id) + sizeof(*extent)) {
error_setg(errp, "Protocol error: invalid payload for "
"NBD_REPLY_TYPE_BLOCK_STATUS");
return -EINVAL;
@@ -276,10 +277,20 @@ static int nbd_parse_blockstatus_payload(NBDClientSession *client,
return -EINVAL;
}
- /* The server is allowed to send us extra information on the final
- * extent; just clamp it to the length we requested. */
+ /*
+ * We used NBD_CMD_FLAG_REQ_ONE, so the server should not have
+ * sent us any more than one extent, nor should it have included
+ * status beyond our request in that extent. However, it's easy
+ * enough to ignore the server's noncompliance without killing the
+ * connection; just ignore trailing extents, and clamp things to
+ * the length of our request.
+ */
+ if (chunk->length > sizeof(context_id) + sizeof(*extent)) {
+ trace_nbd_parse_blockstatus_compliance("more than one extent");
+ }
if (extent->length > orig_length) {
extent->length = orig_length;
+ trace_nbd_parse_blockstatus_compliance("extent length too large");
}
return 0;
diff --git a/block/trace-events b/block/trace-events
index e6bb5a8f05..debb25c0ac 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -157,6 +157,7 @@ nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pa
iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, uint64_t bytes, int ret) "src_lun %p offset %"PRIu64" dst_lun %p offset %"PRIu64" bytes %"PRIu64" ret %d"
# nbd-client.c
+nbd_parse_blockstatus_compliance(const char *err) "ignoring extra data from non-compliant server: %s"
nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s"
nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s"