diff mbox

[04/14] fuzz/x86_emulate: Add a better input size check

Message ID 20170825164343.29015-4-george.dunlap@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

George Dunlap Aug. 25, 2017, 4:43 p.m. UTC
For some reason the 'feof()' check for the file size isn't working in
llvm-clang-fast mode; the result is several kilobyte files rather than
the 4k limit files as we've requested.  This is bad in part because
AFL will spend time trying to "fuzz" bits of the input that are never
touched.

Add a new check: Offer to read INPUT_SIZE + 1; if we actually get that
many bytes, return an error.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
---
CC: Ian Jackson <ian.jackson@citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Jan Beulich <jbeulich@suse.com>
---
 tools/fuzz/x86_instruction_emulator/afl-harness.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Andrew Cooper Aug. 25, 2017, 5:42 p.m. UTC | #1
On 25/08/17 17:43, George Dunlap wrote:
> For some reason the 'feof()' check for the file size isn't working in
> llvm-clang-fast mode; the result is several kilobyte files rather than
> the 4k limit files as we've requested.  This is bad in part because
> AFL will spend time trying to "fuzz" bits of the input that are never
> touched.
>
> Add a new check: Offer to read INPUT_SIZE + 1; if we actually get that
> many bytes, return an error.
>
> Signed-off-by: George Dunlap <george.dunlap@citrix.com>

Doesn't fast mode pass the corpus by shared memory?  I wonder if it is
doing something slightly wonky with hooking the library functions.

Has this issue been reported upstream?  A workaround like this shouldn't
be necessary.

~Andrew
George Dunlap Sept. 25, 2017, 9:36 a.m. UTC | #2
On Fri, Sep 15, 2017 at 12:39 PM, Wei Liu <wei.liu2@citrix.com> wrote:
> On Fri, Aug 25, 2017 at 05:43:33PM +0100, George Dunlap wrote:
>> For some reason the 'feof()' check for the file size isn't working in
>> llvm-clang-fast mode; the result is several kilobyte files rather than
>> the 4k limit files as we've requested.  This is bad in part because
>> AFL will spend time trying to "fuzz" bits of the input that are never
>> touched.
>>
>
> You mean feof returns non-zero (true) when it shouldn't?

It looks like it does.  I modified the code thus:

        if ( !feof(fp) )
        {
            printf("Input too large\n");
            if ( optind + 1 ==  argc )
                exit(-1);
            continue;
        }

        if ( fread(input, 1, 1, fp) > 0 )
        {
            fprintf(stderr, "feof check failed to detect oversized input!");
            abort();
        }

And ran AFL for a bit in afl-clang-fast mode.  It ran fine for about
two cycles, before the massive repetition started happening; but once
the file size got larger than 4096 it found "crashes", even though
running it manually with the same input file results in a simple
"Input too large".

>> Add a new check: Offer to read INPUT_SIZE + 1; if we actually get that
>> many bytes, return an error.
>>
>> Signed-off-by: George Dunlap <george.dunlap@citrix.com>
>> ---
>> CC: Ian Jackson <ian.jackson@citrix.com>
>> CC: Wei Liu <wei.liu2@citrix.com>
>> CC: Andrew Cooper <andrew.cooper3@citrix.com>
>> CC: Jan Beulich <jbeulich@suse.com>
>> ---
>>  tools/fuzz/x86_instruction_emulator/afl-harness.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/fuzz/x86_instruction_emulator/afl-harness.c b/tools/fuzz/x86_instruction_emulator/afl-harness.c
>> index 1a79ff228e..51e0183356 100644
>> --- a/tools/fuzz/x86_instruction_emulator/afl-harness.c
>> +++ b/tools/fuzz/x86_instruction_emulator/afl-harness.c
>> @@ -76,7 +76,7 @@ int main(int argc, char **argv)
>>              }
>>          }
>>
>> -        size = fread(input, 1, INPUT_SIZE, fp);
>> +        size = fread(input, 1, INPUT_SIZE + 1, fp);
>
> You probably want to actual define input to be of INPUT_SIZE+1 byte as well.
>
> I doubt address sanitiser will be happy with overrunning the buffer.

Yeah, the check is a little suboptimal; I'll see what I can come up with.

 -George
George Dunlap Sept. 25, 2017, 11:08 a.m. UTC | #3
On Mon, Sep 25, 2017 at 10:36 AM, George Dunlap
<george.dunlap@citrix.com> wrote:
> On Fri, Sep 15, 2017 at 12:39 PM, Wei Liu <wei.liu2@citrix.com> wrote:
>> On Fri, Aug 25, 2017 at 05:43:33PM +0100, George Dunlap wrote:
>>> For some reason the 'feof()' check for the file size isn't working in
>>> llvm-clang-fast mode; the result is several kilobyte files rather than
>>> the 4k limit files as we've requested.  This is bad in part because
>>> AFL will spend time trying to "fuzz" bits of the input that are never
>>> touched.
>>>
>>
>> You mean feof returns non-zero (true) when it shouldn't?
>
> It looks like it does.  I modified the code thus:
>
>         if ( !feof(fp) )
>         {
>             printf("Input too large\n");
>             if ( optind + 1 ==  argc )
>                 exit(-1);
>             continue;
>         }
>
>         if ( fread(input, 1, 1, fp) > 0 )
>         {
>             fprintf(stderr, "feof check failed to detect oversized input!");
>             abort();
>         }
>
> And ran AFL for a bit in afl-clang-fast mode.  It ran fine for about
> two cycles, before the massive repetition started happening; but once
> the file size got larger than 4096 it found "crashes", even though
> running it manually with the same input file results in a simple
> "Input too large".

Actually -- I had forgotten that over the weekend I came up with
another hypothesis: The reason feof() is returning true even when
we're not at an EOF is that we haven't called clearerr() on the
previous iteration.

Testing now with clearerr() -- if that works I'll send a patch that
fixes the root problem.

 -George
diff mbox

Patch

diff --git a/tools/fuzz/x86_instruction_emulator/afl-harness.c b/tools/fuzz/x86_instruction_emulator/afl-harness.c
index 1a79ff228e..51e0183356 100644
--- a/tools/fuzz/x86_instruction_emulator/afl-harness.c
+++ b/tools/fuzz/x86_instruction_emulator/afl-harness.c
@@ -76,7 +76,7 @@  int main(int argc, char **argv)
             }
         }
 
-        size = fread(input, 1, INPUT_SIZE, fp);
+        size = fread(input, 1, INPUT_SIZE + 1, fp);
 
         if ( ferror(fp) )
         {
@@ -84,7 +84,7 @@  int main(int argc, char **argv)
             exit(-1);
         }
 
-        if ( !feof(fp) )
+        if ( !feof(fp) || size > INPUT_SIZE )
         {
             printf("Input too large\n");
             exit(-1);