[Libguestfs] [libnbd PATCH 1/2] api: Tighter checking of structured read replies

Eric Blake eblake at redhat.com
Tue May 31 16:13:33 UTC 2022


On Tue, May 31, 2022 at 06:59:25PM +0300, Nir Soffer wrote:
> On Tue, May 31, 2022 at 5:15 PM Eric Blake <eblake at redhat.com> wrote:
> >
> > Now that we allow clients to bypass buffer pre-initialization, it
> > becomes more important to detect when a buggy server using structured
> > replies does not send us enough bytes to cover the requested read
> > size.  Our check is not perfect (a server that duplicates reply chunks
> > for byte 0 and omits byte 1 gets past our check), but this is a
> > tighter sanity check so that we are less likely to report a successful
> > read containing uninitialized memory on a buggy server.
> 
> Nice!
> 
> > Because we have a maximum read buffer size of 64M, and first check
> > that the server's chunk fits bounds, we don't have to worry about
> > overflowing a uint32_t, even if a server sends enough duplicate
> > responses that an actual sum would overflow.
> > ---

> > +++ b/generator/states-reply-structured.c
> > @@ -354,7 +354,6 @@ STATE_MACHINE {
> >      assert (cmd); /* guaranteed by CHECK */
> >
> >      assert (cmd->data && cmd->type == NBD_CMD_READ);
> > -    cmd->data_seen = true;
> >
> >      /* Length of the data following. */
> >      length -= 8;
> > @@ -364,6 +363,8 @@ STATE_MACHINE {
> >        SET_NEXT_STATE (%.DEAD);
> >        return 0;
> >      }
> > +    if (cmd->data_seen <= cmd->count)
> > +      cmd->data_seen += length;
> 
> This does not feel right. if you received more data, it should be counted,
> and if this causes data_seen to be bigger than cmd->count, isn't this a fatal
> error?

cmd->count is at most 64M; it represents how much we asked the server
to provide.  length was just validated (in the elided statement
between these two hunks) to be <= cmd->count (otherwise, the server is
known-buggy for replying with more than we asked, and we've already
moved to %.DEAD state).  cmd->data_seen is a cumulative count of all
bytes seen in prior chunks, plus the current chunk.  If we have not
yet passed cmd->count, then this chunk counts towards the cumulative
limit (and there is no overflow, since 64M*2 < UINT32_MAX).  If we
have already passed cmd->count (in a previous chunk), then we don't
further increase cmd->count, but we already know that we will fail the
overall read later.  In other words, we can stop incrementing
cmd->data_seen as soon as we know it exceeds cmd->count, and by
stopping early, we still detect server bugs without overflowing
uint32_t.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


More information about the Libguestfs mailing list