summaryrefslogtreecommitdiff
path: root/nbd/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'nbd/client.c')
-rw-r--r--nbd/client.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/nbd/client.c b/nbd/client.c
index 9b9b7f0ea2..dd0174b036 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -599,8 +599,8 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc,
* Set one meta context. Simple means that reply must contain zero (not
* negotiated) or one (negotiated) contexts. More contexts would be considered
* as a protocol error. It's also implied that meta-data query equals queried
- * context name, so, if server replies with something different then @context,
- * it considered as error too.
+ * context name, so, if server replies with something different than @context,
+ * it is considered an error too.
* return 1 for successful negotiation, context_id is set
* 0 if operation is unsupported,
* -1 with errp set for any other error
@@ -649,25 +649,33 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc,
if (reply.type == NBD_REP_META_CONTEXT) {
char *name;
- size_t len;
+
+ if (reply.length != sizeof(received_id) + context_len) {
+ error_setg(errp, "Failed to negotiate meta context '%s', server "
+ "answered with unexpected length %" PRIu32, context,
+ reply.length);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
if (nbd_read(ioc, &received_id, sizeof(received_id), errp) < 0) {
return -1;
}
be32_to_cpus(&received_id);
- len = reply.length - sizeof(received_id);
- name = g_malloc(len + 1);
- if (nbd_read(ioc, name, len, errp) < 0) {
+ reply.length -= sizeof(received_id);
+ name = g_malloc(reply.length + 1);
+ if (nbd_read(ioc, name, reply.length, errp) < 0) {
g_free(name);
return -1;
}
- name[len] = '\0';
+ name[reply.length] = '\0';
if (strcmp(context, name)) {
error_setg(errp, "Failed to negotiate meta context '%s', server "
"answered with different context '%s'", context,
name);
g_free(name);
+ nbd_send_opt_abort(ioc);
return -1;
}
g_free(name);
@@ -690,6 +698,12 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc,
if (reply.type != NBD_REP_ACK) {
error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x",
reply.type, NBD_REP_ACK);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
+ if (reply.length) {
+ error_setg(errp, "Unexpected length to ACK response");
+ nbd_send_opt_abort(ioc);
return -1;
}