VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzzmastercmd.cpp@ 72465

Last change on this file since 72465 was 72465, checked in by vboxsync, 7 years ago

Runtime/RTFuzz: Save fuzzed inputs which cause crashes or client hangs, rewrite client execution code to support looking for timeouts and capturing stdout/stderr of the fuzzed process for inspection. Also make it possible to specify precisely where the input filename is given on the command line using a ${INPUT} placeholder

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/* $Id: fuzzmastercmd.cpp 72465 2018-06-06 21:12:23Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, master command.
4 */
5
6/*
7 * Copyright (C) 2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/fuzz.h>
32#include "internal/iprt.h"
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/buildconfig.h>
37#include <iprt/ctype.h>
38#include <iprt/err.h>
39#include <iprt/getopt.h>
40#include <iprt/mem.h>
41#include <iprt/message.h>
42#include <iprt/stream.h>
43#include <iprt/thread.h>
44
45
46
47/**
48 * Wrapper around RTErrInfoSetV / RTMsgErrorV.
49 *
50 * @returns @a rc
51 * @param pErrInfo Extended error info.
52 * @param rc The return code.
53 * @param pszFormat The message format.
54 * @param ... The message format arguments.
55 */
56static int rtFuzzCmdMasterErrorRc(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...)
57{
58 va_list va;
59 va_start(va, pszFormat);
60 if (pErrInfo)
61 RTErrInfoSetV(pErrInfo, rc, pszFormat, va);
62 else
63 RTMsgErrorV(pszFormat, va);
64 va_end(va);
65 return rc;
66}
67
68
69/**
70 * Executes the
71 */
72static RTEXITCODE rtFuzzCmdMasterDoIt(const char *pszBinary, uint32_t cProcs, const char *pszInpSeedDir,
73 const char *pszResultsDir, size_t cbInputMax, const char * const *papszClientArgs,
74 unsigned cClientArgs, bool fInputFile, const char *pszTmpDir)
75{
76 RTFUZZOBS hFuzzObs;
77
78 int rc = RTFuzzObsCreate(&hFuzzObs);
79 if (RT_SUCCESS(rc))
80 {
81 RTFUZZCTX hFuzzCtx;
82
83 rc = RTFuzzObsQueryCtx(hFuzzObs, &hFuzzCtx);
84 if (RT_SUCCESS(rc))
85 {
86 uint32_t fFlags = 0;
87
88 if (fInputFile)
89 {
90 fFlags |= RTFUZZ_OBS_BINARY_F_INPUT_FILE;
91 rc = RTFuzzObsSetTmpDirectory(hFuzzObs, pszTmpDir);
92 }
93
94 if (RT_SUCCESS(rc))
95 rc = RTFuzzObsSetResultDirectory(hFuzzObs, pszResultsDir);
96 if (RT_SUCCESS(rc))
97 {
98 rc = RTFuzzObsSetTestBinary(hFuzzObs, pszBinary, fFlags);
99 if (RT_SUCCESS(rc))
100 {
101 rc = RTFuzzObsSetTestBinaryArgs(hFuzzObs, papszClientArgs, cClientArgs);
102 if (RT_SUCCESS(rc))
103 {
104 rc = RTFuzzCtxCfgSetInputSeedMaximum(hFuzzCtx, cbInputMax);
105 if (RT_SUCCESS(rc))
106 {
107 rc = RTFuzzCtxCorpusInputAddFromDirPath(hFuzzCtx, pszInpSeedDir);
108 if (RT_SUCCESS(rc))
109 {
110 rc = RTFuzzObsExecStart(hFuzzObs, cProcs);
111 if (RT_SUCCESS(rc))
112 {
113 RTThreadSleep(3600 * RT_MS_1SEC);
114 RTFuzzObsExecStop(hFuzzObs);
115 }
116 else
117 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Failed to start fuzzing observer: %Rrc\n", rc);
118 }
119 else
120 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Failed to load corpus seeds from \"%s\": %Rrc\n", pszInpSeedDir, rc);
121 }
122 else
123 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Failed to set maximum input size to %zu: %Rrc\n", cbInputMax, rc);
124 }
125 else
126 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Failed to set test program arguments: %Rrc\n", rc);
127 }
128 else
129 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Failed to set the specified binary as test program: %Rrc\n", rc);
130 }
131
132 RTFuzzCtxRelease(hFuzzCtx);
133 }
134 else
135 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Error obtaining the fuzzing context from the observer: %Rrc\n", rc);
136
137 RTFuzzObsDestroy(hFuzzObs);
138 }
139 else
140 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "Error creating observer instance: %Rrc\n", rc);
141
142 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
143}
144
145
146RTR3DECL(RTEXITCODE) RTFuzzCmdMaster(unsigned cArgs, char **papszArgs)
147{
148 /*
149 * Parse the command line.
150 */
151 static const RTGETOPTDEF s_aOptions[] =
152 {
153 { "--binary", 'b', RTGETOPT_REQ_STRING },
154 { "--processes", 'p', RTGETOPT_REQ_UINT32 },
155 { "--input-as-file", 'f', RTGETOPT_REQ_STRING },
156 { "--input-seed-file", 'i', RTGETOPT_REQ_STRING },
157 { "--input-seed-dir", 's', RTGETOPT_REQ_STRING },
158 { "--input-seed-size-max", 'm', RTGETOPT_REQ_UINT32 },
159 { "--results-dir", 'r', RTGETOPT_REQ_STRING },
160 { "--args", 'a', RTGETOPT_REQ_STRING },
161 { "--help", 'h', RTGETOPT_REQ_NOTHING },
162 { "--version", 'V', RTGETOPT_REQ_NOTHING },
163 };
164
165 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
166 RTGETOPTSTATE GetState;
167 int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
168 RTGETOPTINIT_FLAGS_OPTS_FIRST);
169 if (RT_SUCCESS(rc))
170 {
171 /* Option variables: */
172 const char *pszBinary = NULL;
173 uint32_t cProcs = 0;
174 const char *pszInpSeedDir = NULL;
175 int cClientArgs = 0;
176 size_t cbInputMax = 0;
177 char **papszClientArgs = NULL;
178 bool fInputFile = false;
179 const char *pszTmpDir = NULL;
180 const char *pszResultsDir = NULL;
181
182 /* Argument parsing loop. */
183 bool fContinue = true;
184 do
185 {
186 RTGETOPTUNION ValueUnion;
187 int chOpt = RTGetOpt(&GetState, &ValueUnion);
188 switch (chOpt)
189 {
190 case 0:
191 rcExit = rtFuzzCmdMasterDoIt(pszBinary, cProcs, pszInpSeedDir, pszResultsDir, cbInputMax,
192 papszClientArgs, cClientArgs, fInputFile, pszTmpDir);
193 fContinue = false;
194 break;
195
196 case 'b':
197 pszBinary = ValueUnion.psz;
198 break;
199
200 case 'p':
201 cProcs = ValueUnion.u32;
202 break;
203
204 case 'f':
205 pszTmpDir = ValueUnion.psz;
206 fInputFile = true;
207 break;
208
209 case 'r':
210 pszResultsDir = ValueUnion.psz;
211 break;
212
213 case 'a':
214 rc = RTGetOptArgvFromString(&papszClientArgs, &cClientArgs, ValueUnion.psz, 0, NULL);
215 break;
216
217 case 's':
218 pszInpSeedDir = ValueUnion.psz;
219 break;
220
221 case 'm':
222 cbInputMax = ValueUnion.u32;
223 break;
224
225 case 'h':
226 RTPrintf("Usage: to be written\nOption dump:\n");
227 for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
228 RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
229 fContinue = false;
230 break;
231
232 case 'V':
233 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
234 fContinue = false;
235 break;
236
237 default:
238 rcExit = RTGetOptPrintError(chOpt, &ValueUnion);
239 fContinue = false;
240 break;
241 }
242 } while (fContinue);
243 }
244 else
245 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTGetOptInit: %Rrc", rc);
246 return rcExit;
247}
248
Note: See TracBrowser for help on using the repository browser.

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