On Thu, Sep 21, 2023 at 10:22:08PM +0100, Richard W.M. Jones wrote:
> On Thu, Sep 21, 2023 at 03:58:01PM -0500, Eric Blake wrote:
> > When fuzzing, it is more desirable to always provoke the server into
> > sending a response, rather than sometimes accidentally skipping a wire
> > call because a client-side strictness test failed.
> > 
> > [Our fuzzer could probably be made even more powerful by changing the
> > fuzzer input file to be a series of records, where each record is the
> > API to call and then the server's response; right now, the sequence of
> > APIs called is hard-coded, which is not as powerful at testing
> > potential cross-command coupling. But that's a project for another
> > day.]
> 
> Intrigued by how this would work exactly.  The current file is just a
> stream of bytes from the "server" (the output from libnbd is
> discarded).  Would the input file be of the form:
> 
>   ( [ request + args ] [ stream of bytes from server ] )*
> 
> where [ request + args ] would be a simple serialized representation
> of a synchronous nbd_* API call?  I think that would work ...

Actually I don't think this would work.  The stream of bytes is
variable length so it would need a sentinel to indicate the end of one
stream (hard to do in-stream) or a length field up front.  However
fuzzing doesn't work well with length + data since the fuzzer doesn't
understand the relationship.

This could work (I've abbreviated "request + args" to just "request"
and "stream ..." to "stream"):

  ( [ request ] )* [ sentinel ] [ stream ]        (* case B *)

where [ sentinel ] is some sentinel that can be distinguished from a
request.

The idea here is the fuzzing wrapper would read the set of requests
into an internal structure, then process the stream as it does now
while issuing the requests.

However I still don't think the fuzzer would work well with this.  The
problem is that the stream of bytes is still related to the set of
requests.  For example if a new request was inserted then some later
point in the stream would need to change, but the fuzzer wouldn't
understand this relationship.  [Now I'm thinking if only we could use
an AI transformer it would solve this problem too!  Transformers can
find these kind of long-range moving dependencies.]

This seems better still:

  [ request ] [ stream ]                         (* case C *)

There's a single request (which can represent exactly one nbd_*
request), and a single associated stream.  The fuzzer would generate
alternate nbd_* APIs as it mutated the request field.

However the problem here is we no longer have any way to describe
multiple dependent requests.

So ...

I think my answer is to go back to case B:

  ( [ request ] )* [ sentinel ] [ stream ]

but make the starting test cases all look (nearly) like case C:

  [ request ] [ sentinel ] [ stream ]

The fuzzer would start by finding the simple test cases looking like
C, and then might create longer test cases looking like B later in the
run (or might not, we'd need to examine the output after a long run).

Anyway, something for a rainy day.

Rich.

> Rich.
> 
> > Signed-off-by: Eric Blake <ebl...@redhat.com>
> > Reviewed-by: Richard W.M. Jones <rjo...@redhat.com>
> > Reviewed-by: Laszlo Ersek <ler...@redhat.com>
> > ---
> >  fuzzing/libnbd-fuzz-wrapper.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fuzzing/libnbd-fuzz-wrapper.c b/fuzzing/libnbd-fuzz-wrapper.c
> > index cbd55380..fcd1d04c 100644
> > --- a/fuzzing/libnbd-fuzz-wrapper.c
> > +++ b/fuzzing/libnbd-fuzz-wrapper.c
> > @@ -193,8 +193,11 @@ client (int sock)
> >    }
> > 
> >    /* Note we ignore errors in these calls because we are only
> > -   * interested in whether the process crashes.
> > +   * interested in whether the process crashes.  Likewise, we don't
> > +   * want to accidentally avoid sending traffic to the server merely
> > +   * because client side strictness sees a problem.
> >     */
> > +  nbd_set_strict_mode (nbd, 0);
> > 
> >    /* Enable a metadata context, for block status below. */
> >    nbd_add_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
> > -- 
> > 2.41.0
> 
> -- 
> Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
> Read my programming and virtualization blog: http://rwmj.wordpress.com
> virt-top is 'top' for virtual machines.  Tiny program with many
> powerful monitoring features, net stats, disk stats, logging, etc.
> http://people.redhat.com/~rjones/virt-top

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to