qio: Fix Qmsg panic in read_all_blocks()
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jul 2018 17:25:10 +0000 (13:25 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jul 2018 17:54:08 +0000 (13:54 -0400)
Qmsg queues will return a full block, regardless of the number of bytes.
Short reads on Qmsg queues will have BLEN > amt, which is fine.  Those
bytes are discarded, which is what you get with Qmsg.  We simply shouldn't
panic in those cases.

Reported-by: syzbot+2c8228df3c647d4f581e@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/ns/qio.c

index 2c8e141..3debe27 100644 (file)
@@ -1284,8 +1284,8 @@ static size_t read_from_block(struct block *b, uint8_t *to, size_t amt)
 
        copy_amt = MIN(BHLEN(b), amt);
        memcpy(to, b->rp, copy_amt);
-       /* advance the rp, since this block not be completely consumed and future
-        * reads need to know where to pick up from */
+       /* advance the rp, since this block might not be completely consumed and
+        * future reads need to know where to pick up from */
        b->rp += copy_amt;
        to += copy_amt;
        amt -= copy_amt;
@@ -1352,12 +1352,11 @@ static size_t read_all_blocks(struct block *b, void *va, size_t len)
        struct block *next;
 
        do {
-               /* We should be draining every block completely. */
-               assert(BLEN(b) <= len - sofar);
                assert(va);
-               assert(va + sofar);
                assert(b->rp);
                sofar += read_from_block(b, va + sofar, len - sofar);
+               if (BLEN(b) && b->next)
+                       panic("Failed to drain entire block (Qmsg?) but had a next!");
                next = b->next;
                freeb(b);
                b = next;