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