VirtualBox

Changeset 77564 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Mar 5, 2019 10:30:33 AM (6 years ago)
Author:
vboxsync
Message:

Runtime/fuzz: Add libFuzzer compatible wrapper to be able to evaluate our fuzzer against others

Location:
trunk/src/VBox/Runtime/common/fuzz
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fuzz/fuzz.cpp

    r77544 r77564  
    368368static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplacePrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
    369369                                                         PPRTFUZZMUTATION ppMutation);
     370static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     371                                                        PPRTFUZZMUTATION ppMutation);
    370372static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
    371373                                                                      PPRTFUZZMUTATION ppMutation);
     
    381383static DECLCALLBACK(int) rtFuzzCtxMutatorByteReplaceExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    382384                                                         uint8_t *pbBuf, size_t cbBuf);
     385static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
     386                                                        uint8_t *pbBuf, size_t cbBuf);
    383387static DECLCALLBACK(int) rtFuzzCtxMutatorByteSequenceInsertAppendExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
    384388                                                                      uint8_t *pbBuf, size_t cbBuf);
     
    425429static RTFUZZMUTATOR const g_aMutators[] =
    426430{
    427     /* pszId         pszDesc                                          uMutator     fFlags                      pfnPrep                                       pfnExec                                       pfnExport                                       pfnImport */
     431    /* pszId         pszDesc                                          uMutator     fFlags                      pfnPrep                                       pfnExec                                       pfnExport                      pfnImport */
    428432    { "BitFlip",     "Flips a single bit in the input",               0,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorBitFlipPrep,                  rtFuzzCtxMutatorBitFlipExec,                  rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
    429433    { "ByteReplace", "Replaces a single byte in the input",           1,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteReplacePrep,              rtFuzzCtxMutatorByteReplaceExec,              rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
    430     { "ByteSeqIns",  "Inserts a byte sequence in the input",          2,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
    431     { "ByteSeqApp",  "Appends a byte sequence to the input",          3,           RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
    432     { "ByteDelete",  "Deletes a single byte sequence from the input", 4,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteDeletePrep,               rtFuzzCtxMutatorByteDeleteExec,               NULL,                          NULL                          },
    433     { "ByteSeqDel",  "Deletes a byte sequence from the input",        5,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceDeletePrep,       rtFuzzCtxMutatorByteSequenceDeleteExec,       NULL,                          NULL                          }
     434    { "ByteInsert",  "Inserts a single byte sequence into the input", 2,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteInsertPrep,               rtFuzzCtxMutatorByteInsertExec,               rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     435    { "ByteSeqIns",  "Inserts a byte sequence in the input",          3,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     436    { "ByteSeqApp",  "Appends a byte sequence to the input",          4,           RTFUZZMUTATOR_F_END_OF_BUF, rtFuzzCtxMutatorByteSequenceInsertAppendPrep, rtFuzzCtxMutatorByteSequenceInsertAppendExec, rtFuzzCtxMutatorExportDefault, rtFuzzCtxMutatorImportDefault },
     437    { "ByteDelete",  "Deletes a single byte sequence from the input", 5,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteDeletePrep,               rtFuzzCtxMutatorByteDeleteExec,               NULL,                          NULL                          },
     438    { "ByteSeqDel",  "Deletes a byte sequence from the input",        6,           RTFUZZMUTATOR_F_DEFAULT,    rtFuzzCtxMutatorByteSequenceDeletePrep,       rtFuzzCtxMutatorByteSequenceDeleteExec,       NULL,                          NULL                          }
    434439};
    435440
     
    705710    uint8_t bReplace = *(uint8_t *)pvMutation;
    706711    *pbBuf = bReplace;
     712    return VINF_SUCCESS;
     713}
     714
     715
     716/**
     717 * Mutator callback - inserts a single byte into the input.
     718 */
     719static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertPrep(PRTFUZZCTXINT pThis, uint64_t offStart, PRTFUZZMUTATION pMutationParent,
     720                                                        PPRTFUZZMUTATION ppMutation)
     721{
     722    int rc = VINF_SUCCESS;
     723    uint8_t *pbInsert = 0;
     724    if (pMutationParent->cbInput < pThis->cbInputMax)
     725    {
     726        PRTFUZZMUTATION pMutation = rtFuzzMutationCreate(pThis, offStart, pMutationParent, 1 /*cbAdditional*/, (void **)&pbInsert);
     727        if (RT_LIKELY(pMutation))
     728        {
     729            pMutation->cbInput = pMutationParent->cbInput + 1;
     730            RTRandAdvBytes(pThis->hRand, pbInsert, 1);
     731            *ppMutation = pMutation;
     732        }
     733        else
     734            rc = VERR_NO_MEMORY;
     735    }
     736
     737    return rc;
     738}
     739
     740
     741static DECLCALLBACK(int) rtFuzzCtxMutatorByteInsertExec(PRTFUZZCTXINT pThis, PCRTFUZZMUTATION pMutation, const void *pvMutation,
     742                                                        uint8_t *pbBuf, size_t cbBuf)
     743{
     744    RT_NOREF(pThis, pMutation, pvMutation);
     745
     746    /* Just move the residual data one byte to the back. */
     747    memmove(pbBuf + 1, pbBuf, cbBuf);
     748    *pbBuf = *(uint8_t *)pvMutation;
    707749    return VINF_SUCCESS;
    708750}
     
    794836{
    795837    int rc = VINF_SUCCESS;
    796     if (pMutationParent->cbInput > 1)
     838    if (pMutationParent->cbInput > offStart)
    797839    {
    798840        size_t cbInputMutated = (size_t)RTRandAdvU64Ex(pThis->hRand, offStart, pMutationParent->cbInput - 1);
  • trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp

    r77509 r77564  
    3535#include <iprt/buildconfig.h>
    3636#include <iprt/errcore.h>
     37#include <iprt/file.h>
    3738#include <iprt/getopt.h>
     39#include <iprt/ldr.h>
    3840#include <iprt/mem.h>
    3941#include <iprt/message.h>
     
    4446
    4547
     48
     49typedef DECLCALLBACK(int) FNLLVMFUZZERTESTONEINPUT(const uint8_t *pbData, size_t cbData);
     50typedef FNLLVMFUZZERTESTONEINPUT *PFNLLVMFUZZERTESTONEINPUT;
     51
     52
    4653/**
    4754 * Fuzzing client command state.
     
    5057{
    5158    /** Our own fuzzing context containing all the data. */
    52     RTFUZZCTX               hFuzzCtx;
     59    RTFUZZCTX                 hFuzzCtx;
    5360    /** Consumption callback. */
    54     PFNFUZZCLIENTCONSUME    pfnConsume;
     61    PFNFUZZCLIENTCONSUME      pfnConsume;
    5562    /** Opaque user data to pass to the consumption callback. */
    56     void                    *pvUser;
     63    void                      *pvUser;
     64    /** The LLVM libFuzzer compatible entry point if configured */
     65    PFNLLVMFUZZERTESTONEINPUT pfnLlvmFuzzerTestOneInput;
     66    /** The selected input channel. */
     67    RTFUZZOBSINPUTCHAN        enmInputChan;
    5768    /** Standard input VFS handle. */
    58     RTVFSIOSTREAM           hVfsStdIn;
     69    RTVFSIOSTREAM             hVfsStdIn;
    5970    /** Standard output VFS handle. */
    60     RTVFSIOSTREAM           hVfsStdOut;
     71    RTVFSIOSTREAM             hVfsStdOut;
    6172} RTFUZZCMDCLIENT;
    6273/** Pointer to a fuzzing client command state. */
    6374typedef RTFUZZCMDCLIENT *PRTFUZZCMDCLIENT;
     75
     76
     77
     78/**
     79 * Runs the appropriate consumption callback with the provided data.
     80 *
     81 * @returns Status code, 0 for success.
     82 * @param   pThis               The fuzzing client command state.
     83 * @param   pvData              The data to consume.
     84 * @param   cbData              Size of the data in bytes.
     85 */
     86static int rtFuzzCmdClientConsume(PRTFUZZCMDCLIENT pThis, const void *pvData, size_t cbData)
     87{
     88    if (pThis->pfnLlvmFuzzerTestOneInput)
     89        return pThis->pfnLlvmFuzzerTestOneInput((const uint8_t *)pvData, cbData);
     90    else
     91        return pThis->pfnConsume(pvData, cbData, pThis->pvUser);
     92}
    6493
    6594
     
    89118            {
    90119                char bResp = '.';
    91                 int rc2 = pThis->pfnConsume(pv, cb, pThis->pvUser);
     120                int rc2 = rtFuzzCmdClientConsume(pThis, pv, cb);
    92121                if (RT_SUCCESS(rc2))
    93122                {
     
    153182
    154183
     184/**
     185 * Run a single iteration of the fuzzing client and return.
     186 *
     187 * @returns Process exit status.
     188 * @param   pThis               The fuzzing client command state.
     189 */
     190static RTEXITCODE rtFuzzCmdClientRunFile(PRTFUZZCMDCLIENT pThis, const char *pszFilename)
     191{
     192    void *pv = NULL;
     193    size_t cbFile = 0;
     194    int rc = RTFileReadAll(pszFilename, &pv, &cbFile);
     195    if (RT_SUCCESS(rc))
     196    {
     197        rtFuzzCmdClientConsume(pThis, pv, cbFile);
     198        RTFileReadAllFree(pv, cbFile);
     199        return RTEXITCODE_SUCCESS;
     200    }
     201
     202    return RTEXITCODE_FAILURE;
     203}
     204
     205
    155206RTR3DECL(RTEXITCODE) RTFuzzCmdFuzzingClient(unsigned cArgs, char **papszArgs, PFNFUZZCLIENTCONSUME pfnConsume, void *pvUser)
    156207{
     
    162213        { "--help",                            'h', RTGETOPT_REQ_NOTHING },
    163214        { "--version",                         'V', RTGETOPT_REQ_NOTHING },
     215        { "--llvm-input",                      'l', RTGETOPT_REQ_STRING  },
     216        { "--file",                            'f', RTGETOPT_REQ_STRING  },
    164217    };
    165218
     
    172225        /* Option variables:  */
    173226        RTFUZZCMDCLIENT This;
    174 
    175         This.pfnConsume = pfnConsume;
    176         This.pvUser     = pvUser;
     227        RTLDRMOD hLlvmMod = NIL_RTLDRMOD;
     228        const char *pszFilename = NULL;
     229
     230        This.pfnConsume   = pfnConsume;
     231        This.pvUser       = pvUser;
     232        This.enmInputChan = RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT;
    177233
    178234        /* Argument parsing loop. */
    179235        bool fContinue = true;
     236        bool fExit = false;
    180237        do
    181238        {
     
    188245                    break;
    189246
     247                case 'f':
     248                {
     249                    pszFilename = ValueUnion.psz;
     250                    This.enmInputChan = RTFUZZOBSINPUTCHAN_FILE;
     251                    break;
     252                }
     253
     254                case 'l':
     255                {
     256                    /*
     257                     * Load the indicated library and try to resolve LLVMFuzzerTestOneInput,
     258                     * which will act as the input callback.
     259                     */
     260                    rc = RTLdrLoad(ValueUnion.psz, &hLlvmMod);
     261                    if (RT_SUCCESS(rc))
     262                    {
     263                        rc = RTLdrGetSymbol(hLlvmMod, "LLVMFuzzerTestOneInput", (void **)&This.pfnLlvmFuzzerTestOneInput);
     264                        if (RT_FAILURE(rc))
     265                            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to query '%s' from '%s': %Rrc",
     266                                                    "LLVMFuzzerTestOneInput",
     267                                                    ValueUnion.psz,
     268                                                    rc);
     269                    }
     270                    break;
     271                }
     272
    190273                case 'h':
    191274                    RTPrintf("Usage: to be written\nOption dump:\n");
     
    193276                        RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
    194277                    fContinue = false;
     278                    fExit = true;
    195279                    break;
    196280
     
    198282                    RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
    199283                    fContinue = false;
     284                    fExit = true;
    200285                    break;
    201286
     
    207292        } while (fContinue);
    208293
    209         if (rcExit == RTEXITCODE_SUCCESS)
    210             rcExit = rtFuzzCmdClientRun(&This);
     294        if (   rcExit == RTEXITCODE_SUCCESS
     295            && !fExit)
     296        {
     297            switch (This.enmInputChan)
     298            {
     299                case RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT:
     300                    rcExit = rtFuzzCmdClientRun(&This);
     301                    break;
     302                case RTFUZZOBSINPUTCHAN_FILE:
     303                    rcExit = rtFuzzCmdClientRunFile(&This, pszFilename);
     304                    break;
     305                default:
     306                    rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "Input channel unknown/not implemented yet");
     307            }
     308        }
     309
     310        if (hLlvmMod != NIL_RTLDRMOD)
     311            RTLdrClose(hLlvmMod);
    211312    }
    212313    else
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette