[Libguestfs] [libnbd PATCH 4/7] states: Rewrite NBD_REP_INFO parsing

Eric Blake eblake at redhat.com
Fri Jun 14 21:54:00 UTC 2019


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




More information about the Libguestfs mailing list