Skip to content

Commit

Permalink
nbd/server: Prepare to receive extended header requests
Browse files Browse the repository at this point in the history
Although extended mode is not yet enabled, once we do turn it on, we
need to accept extended requests for all messages.  Previous patches
have already taken care of supporting 64-bit lengths, now we just need
to read it off the wire.

Note that this implementation will block indefinitely on a buggy
client that sends a non-extended payload (that is, we try to read a
full packet before we ever check the magic number, but a client that
mistakenly sends a simple request after negotiating extended headers
doesn't send us enough bytes), but it's no different from any other
client that stops talking to us partway through a packet and thus not
worth coding around.

Signed-off-by: Eric Blake <[email protected]>
Reviewed-by: Vladimir Sementsov-Ogievskiy <[email protected]>
Message-ID: <[email protected]>
  • Loading branch information
ebblake committed Oct 5, 2023
1 parent 009cd86 commit c8720ca
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
5 changes: 4 additions & 1 deletion nbd/nbd-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@
* https://github.com/yoe/nbd/blob/master/doc/proto.md
*/

/* Size of all NBD_OPT_*, without payload */
/* Size of all compact NBD_CMD_*, without payload */
#define NBD_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 4)
/* Size of all extended NBD_CMD_*, without payload */
#define NBD_EXTENDED_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 8)

/* Size of all NBD_REP_* sent in answer to most NBD_OPT_*, without payload */
#define NBD_REPLY_SIZE (4 + 4 + 8)
/* Size of reply to NBD_OPT_EXPORT_NAME */
Expand Down
43 changes: 30 additions & 13 deletions nbd/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,39 +1411,56 @@ nbd_read_eof(NBDClient *client, void *buffer, size_t size, Error **errp)
static int coroutine_fn nbd_receive_request(NBDClient *client, NBDRequest *request,
Error **errp)
{
uint8_t buf[NBD_REQUEST_SIZE];
uint32_t magic;
uint8_t buf[NBD_EXTENDED_REQUEST_SIZE];
uint32_t magic, expect;
int ret;
size_t size = client->mode >= NBD_MODE_EXTENDED ?
NBD_EXTENDED_REQUEST_SIZE : NBD_REQUEST_SIZE;

ret = nbd_read_eof(client, buf, sizeof(buf), errp);
ret = nbd_read_eof(client, buf, size, errp);
if (ret < 0) {
return ret;
}
if (ret == 0) {
return -EIO;
}

/* Request
[ 0 .. 3] magic (NBD_REQUEST_MAGIC)
[ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
[ 6 .. 7] type (NBD_CMD_READ, ...)
[ 8 .. 15] cookie
[16 .. 23] from
[24 .. 27] len
/*
* Compact request
* [ 0 .. 3] magic (NBD_REQUEST_MAGIC)
* [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, ...)
* [ 6 .. 7] type (NBD_CMD_READ, ...)
* [ 8 .. 15] cookie
* [16 .. 23] from
* [24 .. 27] len
* Extended request
* [ 0 .. 3] magic (NBD_EXTENDED_REQUEST_MAGIC)
* [ 4 .. 5] flags (NBD_CMD_FLAG_FUA, NBD_CMD_FLAG_PAYLOAD_LEN, ...)
* [ 6 .. 7] type (NBD_CMD_READ, ...)
* [ 8 .. 15] cookie
* [16 .. 23] from
* [24 .. 31] len
*/

magic = ldl_be_p(buf);
request->flags = lduw_be_p(buf + 4);
request->type = lduw_be_p(buf + 6);
request->cookie = ldq_be_p(buf + 8);
request->from = ldq_be_p(buf + 16);
request->len = (uint32_t)ldl_be_p(buf + 24); /* widen 32 to 64 bits */
if (client->mode >= NBD_MODE_EXTENDED) {
request->len = ldq_be_p(buf + 24);
expect = NBD_EXTENDED_REQUEST_MAGIC;
} else {
request->len = (uint32_t)ldl_be_p(buf + 24); /* widen 32 to 64 bits */
expect = NBD_REQUEST_MAGIC;
}

trace_nbd_receive_request(magic, request->flags, request->type,
request->from, request->len);

if (magic != NBD_REQUEST_MAGIC) {
error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
if (magic != expect) {
error_setg(errp, "invalid magic (got 0x%" PRIx32 ", expected 0x%"
PRIx32 ")", magic, expect);
return -EINVAL;
}
return 0;
Expand Down

0 comments on commit c8720ca

Please sign in to comment.