The NBD spec says that if a client requests a 1-query SET_META_CONTEXT
for context "base:allocation", then changes its mind and requests a
1-query SET_META_CONTEXT for "other:context", only the final query
matters; in such a case, since we did not reply with a context the
second time, the client must not call NBD_CMD_BLOCK_STATUS, and the
server should fail it with EINVAL. If the client actually wants two
contexts, it must request them in a 2-query SET_META_CONTEXT.
However, our code didn't reset the boolean between two uses of the
option, so we were not catching an invalid clients that requests block
status in spite of their second SET_META_CONTEXT.
Note that there are no known clients in the wild that can actually
perform this secondary SET_META_CONTEXT request; this was found by
inspection. As nbdkit does not crash in this situation, I don't see
the point in hacking libnbd to make it possible to become such a
client.
Fixes: 26455d45
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
server/protocol-handshake-newstyle.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/protocol-handshake-newstyle.c b/server/protocol-handshake-newstyle.c
index 06fc53ad..38978c67 100644
--- a/server/protocol-handshake-newstyle.c
+++ b/server/protocol-handshake-newstyle.c
@@ -566,10 +566,10 @@ negotiate_handshake_newstyle_options (struct connection *conn)
debug ("newstyle negotiation: %s: %s count: %d", optname,
option == NBD_OPT_LIST_META_CONTEXT ? "query" :
"set",
nr_queries);
+ if (option == NBD_OPT_SET_META_CONTEXT)
+ conn->meta_context_base_allocation = false;
if (nr_queries == 0) {
- if (option == NBD_OPT_SET_META_CONTEXT)
- conn->meta_context_base_allocation = false;
- else /* LIST */ {
+ if (option == NBD_OPT_LIST_META_CONTEXT) {
if (send_newstyle_option_reply_meta_context
(conn, option, NBD_REP_META_CONTEXT,
0, "base:allocation") == -1)
--
2.21.0