Ensure that the payload was large enough, reject rather than ignore an incorrect NBD_INFO_EXPORT size, and emit debug messages for the infos that we are ignoring. Using a switch statement will also make it easier for future patches to parse other NBD_INFO that we will eventually care about. --- generator/states-newstyle-opt-go.c | 40 ++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/generator/states-newstyle-opt-go.c b/generator/states-newstyle-opt-go.c index 06bbaca..2ee739f 100644 --- a/generator/states-newstyle-opt-go.c +++ b/generator/states-newstyle-opt-go.c @@ -109,6 +109,7 @@ uint32_t reply; uint32_t len; const size_t maxpayload = sizeof h->sbuf.or.payload; + uint16_t info; uint64_t exportsize; uint16_t eflags; @@ -131,20 +132,37 @@ SET_NEXT_STATE (%.READY); return 0; case NBD_REP_INFO: - if (len <= maxpayload /* see RECV_NEWSTYLE_OPT_GO_REPLY */) { - if (len >= sizeof h->sbuf.or.payload.export) { - if (be16toh (h->sbuf.or.payload.export.info) == NBD_INFO_EXPORT) { - exportsize = be64toh (h->sbuf.or.payload.export.exportsize); - eflags = be16toh (h->sbuf.or.payload.export.eflags); - if (nbd_internal_set_size_and_flags (h, - exportsize, eflags) == -1) { - SET_NEXT_STATE (%.DEAD); - return -1; - } + if (len > maxpayload /* see RECV_NEWSTYLE_OPT_GO_REPLY */) { + debug (h, "skipping large NBD_REP_INFO"); + } + else if (len < sizeof h->sbuf.or.payload.export.info) { + SET_NEXT_STATE (%.DEAD); + set_error (0, "handshake: NBD_REP_INFO reply length too small"); + return -1; + } + else { + info = be16toh (h->sbuf.or.payload.export.info); + switch (info) { + case NBD_INFO_EXPORT: + if (len != sizeof h->sbuf.or.payload.export) { + SET_NEXT_STATE (%.DEAD); + set_error (0, "handshake: incorrect NBD_INFO_EXPORT option reply length"); + return -1; } + exportsize = be64toh (h->sbuf.or.payload.export.exportsize); + eflags = be16toh (h->sbuf.or.payload.export.eflags); + if (nbd_internal_set_size_and_flags (h, exportsize, eflags) == -1) { + SET_NEXT_STATE (%.DEAD); + return -1; + } + break; + default: + /* XXX Handle other info types, like NBD_INFO_BLOCK_SIZE */ + debug (h, "skipping unknown NBD_REP_INFO type %d", + be16toh (h->sbuf.or.payload.export.info)); + break; } } - /* ... else ignore the payload. */ /* Server is allowed to send any number of NBD_REP_INFO, read next one. */ h->rbuf = &h->sbuf; h->rlen = sizeof (h->sbuf.or.option_reply); -- 2.20.1