VirtualBox

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

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

Runtime/RTFuzz: Started to extend the master command to provide a network interface for controlling the fuzzing process. The interface uses JSON requests and responses to control the fuzzing process, like creating a new fuzzing run and suspending, resuming and stopping it. The JSON request contains everything required (except for the binary itself) for easier control of multiple masters on different hosts via a central control mechanism (later integration into the validation kit).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.8 KB
Line 
1/* $Id: fuzzmastercmd.cpp 72571 2018-06-15 20:36:17Z 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.virtualbox.org. 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/base64.h>
37#include <iprt/buildconfig.h>
38#include <iprt/ctype.h>
39#include <iprt/err.h>
40#include <iprt/file.h>
41#include <iprt/getopt.h>
42#include <iprt/json.h>
43#include <iprt/list.h>
44#include <iprt/mem.h>
45#include <iprt/message.h>
46#include <iprt/path.h>
47#include <iprt/process.h>
48#include <iprt/stream.h>
49#include <iprt/string.h>
50#include <iprt/tcp.h>
51#include <iprt/thread.h>
52#include <iprt/vfs.h>
53#include <iprt/zip.h>
54
55
56/**
57 * A running fuzzer state.
58 */
59typedef struct RTFUZZRUN
60{
61 /** List node. */
62 RTLISTNODE NdFuzzed;
63 /** Identifier. */
64 char *pszId;
65 /** Number of processes. */
66 uint32_t cProcs;
67 /** Maximum input size to generate. */
68 size_t cbInputMax;
69 /** The fuzzing observer state handle. */
70 RTFUZZOBS hFuzzObs;
71} RTFUZZRUN;
72/** Pointer to a running fuzzer state. */
73typedef RTFUZZRUN *PRTFUZZRUN;
74
75
76/**
77 * Fuzzing master command state.
78 */
79typedef struct RTFUZZCMDMASTER
80{
81 /** List of running fuzzers. */
82 RTLISTANCHOR LstFuzzed;
83 /** The port to listen on. */
84 uint16_t uPort;
85 /** The TCP server for requests. */
86 PRTTCPSERVER hTcpSrv;
87 /** The root temp directory. */
88 const char *pszTmpDir;
89 /** The root results directory. */
90 const char *pszResultsDir;
91 /** Flag whether to shutdown. */
92 bool fShutdown;
93} RTFUZZCMDMASTER;
94/** Pointer to a fuzzing master command state. */
95typedef RTFUZZCMDMASTER *PRTFUZZCMDMASTER;
96
97
98/**
99 * Wrapper around RTErrInfoSetV / RTMsgErrorV.
100 *
101 * @returns @a rc
102 * @param pErrInfo Extended error info.
103 * @param rc The return code.
104 * @param pszFormat The message format.
105 * @param ... The message format arguments.
106 */
107static int rtFuzzCmdMasterErrorRc(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...)
108{
109 va_list va;
110 va_start(va, pszFormat);
111 if (pErrInfo)
112 RTErrInfoSetV(pErrInfo, rc, pszFormat, va);
113 else
114 RTMsgErrorV(pszFormat, va);
115 va_end(va);
116 return rc;
117}
118
119
120/**
121 * Returns a running fuzzer state by the given ID.
122 *
123 * @returns Pointer to the running fuzzer state or NULL if not found.
124 * @param pThis The fuzzing master command state.
125 * @param pszId The ID to look for.
126 */
127static PRTFUZZRUN rtFuzzCmdMasterGetFuzzerById(PRTFUZZCMDMASTER pThis, const char *pszId)
128{
129 PRTFUZZRUN pIt = NULL;
130 RTListForEach(&pThis->LstFuzzed, pIt, RTFUZZRUN, NdFuzzed)
131 {
132 if (!RTStrCmp(pIt->pszId, pszId))
133 return pIt;
134 }
135
136 return NULL;
137}
138
139
140#if 0 /* unused */
141/**
142 * Processes and returns the value of the given config item in the JSON request.
143 *
144 * @returns IPRT status code.
145 * @param ppszStr Where to store the pointer to the string on success.
146 * @param pszCfgItem The config item to resolve.
147 * @param hJsonCfg The JSON object containing the item.
148 * @param pErrInfo Where to store the error information on failure, optional.
149 */
150static int rtFuzzCmdMasterFuzzRunProcessCfgString(char **ppszStr, const char *pszCfgItem, RTJSONVAL hJsonCfg, PRTERRINFO pErrInfo)
151{
152 int rc = RTJsonValueQueryStringByName(hJsonCfg, pszCfgItem, ppszStr);
153 if (RT_FAILURE(rc))
154 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query string value of \"%s\"", pszCfgItem);
155
156 return rc;
157}
158
159
160/**
161 * Processes and returns the value of the given config item in the JSON request.
162 *
163 * @returns IPRT status code.
164 * @param pfVal Where to store the config value on success.
165 * @param pszCfgItem The config item to resolve.
166 * @param hJsonCfg The JSON object containing the item.
167 * @param pErrInfo Where to store the error information on failure, optional.
168 */
169static int rtFuzzCmdMasterFuzzRunProcessCfgBool(bool *pfVal, const char *pszCfgItem, RTJSONVAL hJsonCfg, PRTERRINFO pErrInfo)
170{
171 int rc = RTJsonValueQueryBooleanByName(hJsonCfg, pszCfgItem, pfVal);
172 if (RT_FAILURE(rc))
173 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query boolean value of \"%s\"", pszCfgItem);
174
175 return rc;
176}
177#endif
178
179
180/**
181 * Processes and returns the value of the given config item in the JSON request.
182 *
183 * @returns IPRT status code.
184 * @param pfVal Where to store the config value on success.
185 * @param pszCfgItem The config item to resolve.
186 * @param hJsonCfg The JSON object containing the item.
187 * @param fDef Default value if the item wasn't found.
188 * @param pErrInfo Where to store the error information on failure, optional.
189 */
190static int rtFuzzCmdMasterFuzzRunProcessCfgBoolDef(bool *pfVal, const char *pszCfgItem, RTJSONVAL hJsonCfg, bool fDef, PRTERRINFO pErrInfo)
191{
192 int rc = RTJsonValueQueryBooleanByName(hJsonCfg, pszCfgItem, pfVal);
193 if (rc == VERR_NOT_FOUND)
194 {
195 *pfVal = fDef;
196 rc = VINF_SUCCESS;
197 }
198 else if (RT_FAILURE(rc))
199 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query boolean value of \"%s\"", pszCfgItem);
200
201 return rc;
202}
203
204
205/**
206 * Processes and returns the value of the given config item in the JSON request.
207 *
208 * @returns IPRT status code.
209 * @param pcbVal Where to store the config value on success.
210 * @param pszCfgItem The config item to resolve.
211 * @param hJsonCfg The JSON object containing the item.
212 * @param cbDef Default value if the item wasn't found.
213 * @param pErrInfo Where to store the error information on failure, optional.
214 */
215static int rtFuzzCmdMasterFuzzRunProcessCfgSizeDef(size_t *pcbVal, const char *pszCfgItem, RTJSONVAL hJsonCfg, size_t cbDef, PRTERRINFO pErrInfo)
216{
217 int64_t i64Val = 0;
218 int rc = RTJsonValueQueryIntegerByName(hJsonCfg, pszCfgItem, &i64Val);
219 if (rc == VERR_NOT_FOUND)
220 {
221 *pcbVal = cbDef;
222 rc = VINF_SUCCESS;
223 }
224 else if (RT_FAILURE(rc))
225 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query size_t value of \"%s\"", pszCfgItem);
226 else if (i64Val < 0 || (size_t)i64Val != (uint64_t)i64Val)
227 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_OUT_OF_RANGE, "JSON request malformed: Integer \"%s\" is out of range", pszCfgItem);
228 else
229 *pcbVal = (size_t)i64Val;
230
231 return rc;
232}
233
234
235/**
236 * Processes and returns the value of the given config item in the JSON request.
237 *
238 * @returns IPRT status code.
239 * @param pcbVal Where to store the config value on success.
240 * @param pszCfgItem The config item to resolve.
241 * @param hJsonCfg The JSON object containing the item.
242 * @param cbDef Default value if the item wasn't found.
243 * @param pErrInfo Where to store the error information on failure, optional.
244 */
245static int rtFuzzCmdMasterFuzzRunProcessCfgU32Def(uint32_t *pu32Val, const char *pszCfgItem, RTJSONVAL hJsonCfg, size_t u32Def, PRTERRINFO pErrInfo)
246{
247 int64_t i64Val = 0;
248 int rc = RTJsonValueQueryIntegerByName(hJsonCfg, pszCfgItem, &i64Val);
249 if (rc == VERR_NOT_FOUND)
250 {
251 *pu32Val = u32Def;
252 rc = VINF_SUCCESS;
253 }
254 else if (RT_FAILURE(rc))
255 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query uint32_t value of \"%s\"", pszCfgItem);
256 else if (i64Val < 0 || (uint32_t)i64Val != (uint64_t)i64Val)
257 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_OUT_OF_RANGE, "JSON request malformed: Integer \"%s\" is out of range", pszCfgItem);
258 else
259 *pu32Val = (uint32_t)i64Val;
260
261 return rc;
262}
263
264
265/**
266 * Processes binary related configs for the given fuzzing run.
267 *
268 * @returns IPRT status code.
269 * @param pFuzzRun The fuzzing run.
270 * @param hJsonRoot The root node of the JSON request.
271 * @param pErrInfo Where to store the error information on failure, optional.
272 */
273static int rtFuzzCmdMasterFuzzRunProcessBinaryCfg(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
274{
275 RTJSONVAL hJsonVal;
276 int rc = RTJsonValueQueryByName(hJsonRoot, "BinaryPath", &hJsonVal);
277 if (RT_SUCCESS(rc))
278 {
279 const char *pszBinary = RTJsonValueGetString(hJsonVal);
280 if (RT_LIKELY(pszBinary))
281 {
282 bool fFileInput = false;
283 rc = rtFuzzCmdMasterFuzzRunProcessCfgBoolDef(&fFileInput, "FileInput", hJsonRoot, false, pErrInfo);
284 if (RT_SUCCESS(rc))
285 {
286 uint32_t fFlags = 0;
287 if (fFileInput)
288 fFlags |= RTFUZZ_OBS_BINARY_F_INPUT_FILE;
289 rc = RTFuzzObsSetTestBinary(pFuzzRun->hFuzzObs, pszBinary, fFlags);
290 if (RT_FAILURE(rc))
291 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Failed to add the binary path for the fuzzing run");
292 }
293 }
294 else
295 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "JSON request malformed: \"BinaryPath\" is not a string");
296 RTJsonValueRelease(hJsonVal);
297 }
298 else
299 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to query value of \"BinaryPath\"");
300
301 return rc;
302}
303
304
305/**
306 * Processes argument related configs for the given fuzzing run.
307 *
308 * @returns IPRT status code.
309 * @param pFuzzRun The fuzzing run.
310 * @param hJsonRoot The root node of the JSON request.
311 * @param pErrInfo Where to store the error information on failure, optional.
312 */
313static int rtFuzzCmdMasterFuzzRunProcessArgCfg(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
314{
315 RTJSONVAL hJsonValArgArray;
316 int rc = RTJsonValueQueryByName(hJsonRoot, "Arguments", &hJsonValArgArray);
317 if (RT_SUCCESS(rc))
318 {
319 unsigned cArgs = 0;
320 rc = RTJsonValueQueryArraySize(hJsonValArgArray, &cArgs);
321 if (RT_SUCCESS(rc))
322 {
323 if (cArgs > 0)
324 {
325 const char **papszArgs = (const char **)RTMemAllocZ(cArgs * sizeof(const char *));
326 RTJSONVAL *pahJsonVal = (RTJSONVAL *)RTMemAllocZ(cArgs * sizeof(RTJSONVAL));
327 if (RT_LIKELY(papszArgs && pahJsonVal))
328 {
329 unsigned idx = 0;
330
331 for (idx = 0; idx < cArgs && RT_SUCCESS(rc); idx++)
332 {
333 rc = RTJsonValueQueryByIndex(hJsonValArgArray, idx, &pahJsonVal[idx]);
334 if (RT_SUCCESS(rc))
335 {
336 papszArgs[idx] = RTJsonValueGetString(pahJsonVal[idx]);
337 if (RT_UNLIKELY(!papszArgs[idx]))
338 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "Argument %u is not a string", idx);
339 }
340 }
341
342 if (RT_SUCCESS(rc))
343 {
344 rc = RTFuzzObsSetTestBinaryArgs(pFuzzRun->hFuzzObs, papszArgs, cArgs);
345 if (RT_FAILURE(rc))
346 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Failed to set arguments for the fuzzing run");
347 }
348
349 /* Release queried values. */
350 while (idx > 0)
351 {
352 RTJsonValueRelease(pahJsonVal[idx - 1]);
353 idx--;
354 }
355 }
356 else
357 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NO_MEMORY, "Out of memory allocating memory for the argument vector");
358
359 if (papszArgs)
360 RTMemFree(papszArgs);
361 if (pahJsonVal)
362 RTMemFree(pahJsonVal);
363 }
364 }
365 else
366 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: \"Arguments\" is not an array");
367 RTJsonValueRelease(hJsonValArgArray);
368 }
369
370 return rc;
371}
372
373
374/**
375 * Processes the given seed and adds it to the input corpus.
376 *
377 * @returns IPRT status code.
378 * @param hFuzzCtx The fuzzing context handle.
379 * @param pszCompression Compression used for the seed.
380 * @param pszSeed The seed as a base64 encoded string.
381 * @param pErrInfo Where to store the error information on failure, optional.
382 */
383static int rtFuzzCmdMasterFuzzRunProcessSeed(RTFUZZCTX hFuzzCtx, const char *pszCompression, const char *pszSeed, PRTERRINFO pErrInfo)
384{
385 int rc = VINF_SUCCESS;
386 ssize_t cbSeedDecoded = RTBase64DecodedSize(pszSeed, NULL);
387 if (cbSeedDecoded > 0)
388 {
389 uint8_t *pbSeedDecoded = (uint8_t *)RTMemAllocZ(cbSeedDecoded);
390 if (RT_LIKELY(pbSeedDecoded))
391 {
392 rc = RTBase64Decode(pszSeed, pbSeedDecoded, cbSeedDecoded, NULL, NULL);
393 if (RT_SUCCESS(rc))
394 {
395 /* Decompress if applicable. */
396 if (!RTStrICmp(pszCompression, "None"))
397 rc = RTFuzzCtxCorpusInputAdd(hFuzzCtx, pbSeedDecoded, cbSeedDecoded);
398 else
399 {
400 RTVFSIOSTREAM hVfsIosSeed;
401 rc = RTVfsIoStrmFromBuffer(RTFILE_O_READ, pbSeedDecoded, cbSeedDecoded, &hVfsIosSeed);
402 if (RT_SUCCESS(rc))
403 {
404 RTVFSIOSTREAM hVfsDecomp;
405
406 if (!RTStrICmp(pszCompression, "Gzip"))
407 rc = RTZipGzipDecompressIoStream(hVfsIosSeed, RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR, &hVfsDecomp);
408 else
409 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "Request error: Compression \"%s\" is not known", pszCompression);
410
411 if (RT_SUCCESS(rc))
412 {
413 RTVFSFILE hVfsFile;
414 rc = RTVfsMemFileCreate(hVfsDecomp, 2 * _1M, &hVfsFile);
415 if (RT_SUCCESS(rc))
416 {
417 rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL);
418 if (RT_SUCCESS(rc))
419 {
420 /* The VFS file contains the buffer for the seed now. */
421 rc = RTFuzzCtxCorpusInputAddFromVfsFile(hFuzzCtx, hVfsFile);
422 if (RT_FAILURE(rc))
423 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to add input seed");
424 RTVfsFileRelease(hVfsFile);
425 }
426 else
427 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "Request error: Failed to seek to the beginning of the seed");
428 }
429 else
430 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "Request error: Failed to decompress input seed");
431
432 RTVfsIoStrmRelease(hVfsDecomp);
433 }
434
435 RTVfsIoStrmRelease(hVfsIosSeed);
436 }
437 else
438 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to create I/O stream from seed buffer");
439 }
440 }
441 else
442 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to decode the seed string");
443
444 RTMemFree(pbSeedDecoded);
445 }
446 else
447 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NO_MEMORY, "Request error: Failed to allocate %zd bytes of memory for the seed", cbSeedDecoded);
448 }
449 else
450 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "JSON request malformed: Couldn't find \"Seed\" doesn't contain a base64 encoded value");
451
452 return rc;
453}
454
455
456/**
457 * Processes a signle input seed for the given fuzzing run.
458 *
459 * @returns IPRT status code.
460 * @param pFuzzRun The fuzzing run.
461 * @param hJsonSeed The seed node of the JSON request.
462 * @param pErrInfo Where to store the error information on failure, optional.
463 */
464static int rtFuzzCmdMasterFuzzRunProcessInputSeedSingle(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonSeed, PRTERRINFO pErrInfo)
465{
466 RTFUZZCTX hFuzzCtx;
467 int rc = RTFuzzObsQueryCtx(pFuzzRun->hFuzzObs, &hFuzzCtx);
468 if (RT_SUCCESS(rc))
469 {
470 RTJSONVAL hJsonValComp;
471 rc = RTJsonValueQueryByName(hJsonSeed, "Compression", &hJsonValComp);
472 if (RT_SUCCESS(rc))
473 {
474 const char *pszCompression = RTJsonValueGetString(hJsonValComp);
475 if (RT_LIKELY(pszCompression))
476 {
477 RTJSONVAL hJsonValSeed;
478 rc = RTJsonValueQueryByName(hJsonSeed, "Seed", &hJsonValSeed);
479 if (RT_SUCCESS(rc))
480 {
481 const char *pszSeed = RTJsonValueGetString(hJsonValSeed);
482 if (RT_LIKELY(pszSeed))
483 rc = rtFuzzCmdMasterFuzzRunProcessSeed(hFuzzCtx, pszCompression, pszSeed, pErrInfo);
484 else
485 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "JSON request malformed: \"Seed\" value is not a string");
486
487 RTJsonValueRelease(hJsonValSeed);
488 }
489 else
490 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Couldn't find \"Seed\" value");
491 }
492 else
493 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_INVALID_STATE, "JSON request malformed: \"Compression\" value is not a string");
494
495 RTJsonValueRelease(hJsonValComp);
496 }
497 else
498 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Couldn't find \"Compression\" value");
499
500 RTFuzzCtxRelease(hFuzzCtx);
501 }
502 else
503 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Failed to query fuzzing context from observer");
504
505 return rc;
506}
507
508
509/**
510 * Processes input seed related configs for the given fuzzing run.
511 *
512 * @returns IPRT status code.
513 * @param pFuzzRun The fuzzing run.
514 * @param hJsonRoot The root node of the JSON request.
515 * @param pErrInfo Where to store the error information on failure, optional.
516 */
517static int rtFuzzCmdMasterFuzzRunProcessInputSeeds(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
518{
519 RTJSONVAL hJsonValSeedArray;
520 int rc = RTJsonValueQueryByName(hJsonRoot, "InputSeeds", &hJsonValSeedArray);
521 if (RT_SUCCESS(rc))
522 {
523 RTJSONIT hIt;
524 rc = RTJsonIteratorBegin(hJsonValSeedArray, &hIt);
525 if (RT_SUCCESS(rc))
526 {
527 RTJSONVAL hJsonInpSeed;
528 while ( RT_SUCCESS(rc)
529 && RTJsonIteratorQueryValue(hIt, &hJsonInpSeed, NULL) != VERR_JSON_ITERATOR_END)
530 {
531 rc = rtFuzzCmdMasterFuzzRunProcessInputSeedSingle(pFuzzRun, hJsonInpSeed, pErrInfo);
532 RTJsonValueRelease(hJsonInpSeed);
533 if (RT_FAILURE(rc))
534 break;
535 rc = RTJsonIteratorNext(hIt);
536 }
537
538 if (rc == VERR_JSON_ITERATOR_END)
539 rc = VINF_SUCCESS;
540 }
541 else
542 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Failed to create array iterator");
543
544 RTJsonValueRelease(hJsonValSeedArray);
545 }
546
547 return rc;
548}
549
550
551/**
552 * Processes miscellaneous config items.
553 *
554 * @returns IPRT status code.
555 * @param pFuzzRun The fuzzing run.
556 * @param hJsonRoot The root node of the JSON request.
557 * @param pErrInfo Where to store the error information on failure, optional.
558 */
559static int rtFuzzCmdMasterFuzzRunProcessMiscCfg(PRTFUZZRUN pFuzzRun, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
560{
561 size_t cbTmp;
562 int rc = rtFuzzCmdMasterFuzzRunProcessCfgSizeDef(&cbTmp, "InputSeedMax", hJsonRoot, 0, pErrInfo);
563 if (RT_SUCCESS(rc))
564 {
565 RTFUZZCTX hFuzzCtx;
566 rc = RTFuzzObsQueryCtx(pFuzzRun->hFuzzObs, &hFuzzCtx);
567 AssertRC(rc);
568
569 rc = RTFuzzCtxCfgSetInputSeedMaximum(hFuzzCtx, cbTmp);
570 if (RT_FAILURE(rc))
571 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to set maximum input seed size to %zu", cbTmp);
572 }
573
574 if (RT_SUCCESS(rc))
575 rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&pFuzzRun->cProcs, "FuzzingProcs", hJsonRoot, 0, pErrInfo);
576
577 return rc;
578}
579
580
581/**
582 * Creates a new fuzzing run with the given ID.
583 *
584 * @returns IPRT status code.
585 * @param pThis The fuzzing master command state.
586 * @param pszId The ID to use.
587 * @param hJsonRoot The root node of the JSON request.
588 * @param pErrInfo Where to store the error information on failure, optional.
589 */
590static int rtFuzzCmdMasterCreateFuzzRunWithId(PRTFUZZCMDMASTER pThis, const char *pszId, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
591{
592 int rc = VINF_SUCCESS;
593 PRTFUZZRUN pFuzzRun = (PRTFUZZRUN)RTMemAllocZ(sizeof(*pFuzzRun));
594 if (RT_LIKELY(pFuzzRun))
595 {
596 pFuzzRun->pszId = RTStrDup(pszId);
597 if (RT_LIKELY(pFuzzRun->pszId))
598 {
599 rc = RTFuzzObsCreate(&pFuzzRun->hFuzzObs);
600 if (RT_SUCCESS(rc))
601 {
602 rc = rtFuzzCmdMasterFuzzRunProcessBinaryCfg(pFuzzRun, hJsonRoot, pErrInfo);
603 if (RT_SUCCESS(rc))
604 rc = rtFuzzCmdMasterFuzzRunProcessArgCfg(pFuzzRun, hJsonRoot, pErrInfo);
605 if (RT_SUCCESS(rc))
606 rc = rtFuzzCmdMasterFuzzRunProcessInputSeeds(pFuzzRun, hJsonRoot, pErrInfo);
607 if (RT_SUCCESS(rc))
608 rc = rtFuzzCmdMasterFuzzRunProcessMiscCfg(pFuzzRun, hJsonRoot, pErrInfo);
609 if (RT_SUCCESS(rc))
610 {
611 /* Create temp directories. */
612 char szTmpDir[RTPATH_MAX];
613 rc = RTPathJoin(&szTmpDir[0], sizeof(szTmpDir), pThis->pszTmpDir, pFuzzRun->pszId);
614 AssertRC(rc);
615 rc = RTDirCreate(szTmpDir, 0700, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_SET
616 | RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
617 if (RT_SUCCESS(rc))
618 {
619 rc = RTFuzzObsSetTmpDirectory(pFuzzRun->hFuzzObs, szTmpDir);
620 if (RT_SUCCESS(rc))
621 {
622 rc = RTPathJoin(&szTmpDir[0], sizeof(szTmpDir), pThis->pszResultsDir, pFuzzRun->pszId);
623 AssertRC(rc);
624 rc = RTDirCreate(szTmpDir, 0700, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_SET
625 | RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
626 if (RT_SUCCESS(rc))
627 {
628 rc = RTFuzzObsSetResultDirectory(pFuzzRun->hFuzzObs, szTmpDir);
629 if (RT_SUCCESS(rc))
630 {
631 /* Start fuzzing. */
632 RTListAppend(&pThis->LstFuzzed, &pFuzzRun->NdFuzzed);
633 rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
634 if (RT_FAILURE(rc))
635 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to start fuzzing with %Rrc", rc);
636 }
637 else
638 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to set results directory to %s", szTmpDir);
639 }
640 else
641 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to create results directory %s", szTmpDir);
642 }
643 else
644 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to set temporary directory to %s", szTmpDir);
645 }
646 else
647 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Failed to create temporary directory %s", szTmpDir);
648 }
649 }
650 }
651 else
652 rc = VERR_NO_STR_MEMORY;
653 }
654 else
655 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NO_MEMORY, "Request error: Out of memory allocating the fuzzer state");
656
657 return rc;
658}
659
660
661/**
662 * Resolves the fuzzing run from the given ID config item and the given JSON request.
663 *
664 * @returns IPRT status code.
665 * @param pThis The fuzzing master command state.
666 * @param hJsonRoot The root node of the JSON request.
667 * @param pszIdItem The JSON item which contains the ID of the fuzzing run.
668 * @param ppFuzzRun Where to store the pointer to the fuzzing run on success.
669 */
670static int rtFuzzCmdMasterQueryFuzzRunFromJson(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, const char *pszIdItem, PRTERRINFO pErrInfo,
671 PRTFUZZRUN *ppFuzzRun)
672{
673 RTJSONVAL hJsonValId;
674 int rc = RTJsonValueQueryByName(hJsonRoot, pszIdItem, &hJsonValId);
675 if (RT_SUCCESS(rc))
676 {
677 const char *pszId = RTJsonValueGetString(hJsonValId);
678 if (pszId)
679 {
680 PRTFUZZRUN pFuzzRun = rtFuzzCmdMasterGetFuzzerById(pThis, pszId);
681 if (pFuzzRun)
682 *ppFuzzRun = pFuzzRun;
683 else
684 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_NOT_FOUND, "Request error: The ID \"%s\" wasn't found", pszId);
685 }
686 else
687 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "JSON request malformed: \"Id\" is not a string value");
688
689 RTJsonValueRelease(hJsonValId);
690 }
691 else
692 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Couldn't find \"Id\" value");
693 return rc;
694}
695
696
697/**
698 * Processes the "StartFuzzing" request.
699 *
700 * @returns IPRT status code.
701 * @param pThis The fuzzing master command state.
702 * @param hJsonRoot The root node of the JSON request.
703 * @param pErrInfo Where to store the error information on failure, optional.
704 */
705static int rtFuzzCmdMasterProcessJsonReqStart(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
706{
707 RTJSONVAL hJsonValId;
708 int rc = RTJsonValueQueryByName(hJsonRoot, "Id", &hJsonValId);
709 if (RT_SUCCESS(rc))
710 {
711 const char *pszId = RTJsonValueGetString(hJsonValId);
712 if (pszId)
713 {
714 PRTFUZZRUN pFuzzRun = rtFuzzCmdMasterGetFuzzerById(pThis, pszId);
715 if (!pFuzzRun)
716 rc = rtFuzzCmdMasterCreateFuzzRunWithId(pThis, pszId, hJsonRoot, pErrInfo);
717 else
718 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_ALREADY_EXISTS, "Request error: The ID \"%s\" is already registered", pszId);
719 }
720 else
721 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "JSON request malformed: \"Id\" is not a string value");
722
723 RTJsonValueRelease(hJsonValId);
724 }
725 else
726 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Couldn't find \"Id\" value");
727 return rc;
728}
729
730
731/**
732 * Processes the "StopFuzzing" request.
733 *
734 * @returns IPRT status code.
735 * @param pThis The fuzzing master command state.
736 * @param hJsonValRoot The root node of the JSON request.
737 * @param pErrInfo Where to store the error information on failure, optional.
738 */
739static int rtFuzzCmdMasterProcessJsonReqStop(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
740{
741 PRTFUZZRUN pFuzzRun;
742 int rc = rtFuzzCmdMasterQueryFuzzRunFromJson(pThis, hJsonRoot, "Id", pErrInfo, &pFuzzRun);
743 if (RT_SUCCESS(rc))
744 {
745 RTListNodeRemove(&pFuzzRun->NdFuzzed);
746 RTFuzzObsExecStop(pFuzzRun->hFuzzObs);
747 RTFuzzObsDestroy(pFuzzRun->hFuzzObs);
748 RTStrFree(pFuzzRun->pszId);
749 RTMemFree(pFuzzRun);
750 }
751
752 return rc;
753}
754
755
756/**
757 * Processes the "SuspendFuzzing" request.
758 *
759 * @returns IPRT status code.
760 * @param pThis The fuzzing master command state.
761 * @param hJsonValRoot The root node of the JSON request.
762 * @param pErrInfo Where to store the error information on failure, optional.
763 */
764static int rtFuzzCmdMasterProcessJsonReqSuspend(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
765{
766 PRTFUZZRUN pFuzzRun;
767 int rc = rtFuzzCmdMasterQueryFuzzRunFromJson(pThis, hJsonRoot, "Id", pErrInfo, &pFuzzRun);
768 if (RT_SUCCESS(rc))
769 {
770 rc = RTFuzzObsExecStop(pFuzzRun->hFuzzObs);
771 if (RT_FAILURE(rc))
772 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Suspending the fuzzing process failed");
773 }
774
775 return rc;
776}
777
778
779/**
780 * Processes the "ResumeFuzzing" request.
781 *
782 * @returns IPRT status code.
783 * @param pThis The fuzzing master command state.
784 * @param hJsonValRoot The root node of the JSON request.
785 * @param pErrInfo Where to store the error information on failure, optional.
786 */
787static int rtFuzzCmdMasterProcessJsonReqResume(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
788{
789 PRTFUZZRUN pFuzzRun;
790 int rc = rtFuzzCmdMasterQueryFuzzRunFromJson(pThis, hJsonRoot, "Id", pErrInfo, &pFuzzRun);
791 if (RT_SUCCESS(rc))
792 {
793 rc = rtFuzzCmdMasterFuzzRunProcessCfgU32Def(&pFuzzRun->cProcs, "FuzzingProcs", hJsonRoot, pFuzzRun->cProcs, pErrInfo);
794 if (RT_SUCCESS(rc))
795 {
796 rc = RTFuzzObsExecStart(pFuzzRun->hFuzzObs, pFuzzRun->cProcs);
797 if (RT_FAILURE(rc))
798 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "Request error: Resuming the fuzzing process failed");
799 }
800 }
801
802 return rc;
803}
804
805
806/**
807 * Processes the "QueryStats" request.
808 *
809 * @returns IPRT status code.
810 * @param pThis The fuzzing master command state.
811 * @param hJsonValRoot The root node of the JSON request.
812 * @param pErrInfo Where to store the error information on failure, optional.
813 */
814static int rtFuzzCmdMasterProcessJsonReqQueryStats(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
815{
816 RT_NOREF(pThis, hJsonRoot, pErrInfo);
817 return VERR_NOT_IMPLEMENTED;
818}
819
820
821/**
822 * Processes a JSON request.
823 *
824 * @returns IPRT status code.
825 * @param pThis The fuzzing master command state.
826 * @param hJsonValRoot The root node of the JSON request.
827 * @param pErrInfo Where to store the error information on failure, optional.
828 */
829static int rtFuzzCmdMasterProcessJsonReq(PRTFUZZCMDMASTER pThis, RTJSONVAL hJsonRoot, PRTERRINFO pErrInfo)
830{
831 RTJSONVAL hJsonValReq;
832 int rc = RTJsonValueQueryByName(hJsonRoot, "Request", &hJsonValReq);
833 if (RT_SUCCESS(rc))
834 {
835 const char *pszReq = RTJsonValueGetString(hJsonValReq);
836 if (pszReq)
837 {
838 if (!RTStrCmp(pszReq, "StartFuzzing"))
839 rc = rtFuzzCmdMasterProcessJsonReqStart(pThis, hJsonRoot, pErrInfo);
840 else if (!RTStrCmp(pszReq, "StopFuzzing"))
841 rc = rtFuzzCmdMasterProcessJsonReqStop(pThis, hJsonRoot, pErrInfo);
842 else if (!RTStrCmp(pszReq, "SuspendFuzzing"))
843 rc = rtFuzzCmdMasterProcessJsonReqSuspend(pThis, hJsonRoot, pErrInfo);
844 else if (!RTStrCmp(pszReq, "ResumeFuzzing"))
845 rc = rtFuzzCmdMasterProcessJsonReqResume(pThis, hJsonRoot, pErrInfo);
846 else if (!RTStrCmp(pszReq, "QueryStats"))
847 rc = rtFuzzCmdMasterProcessJsonReqQueryStats(pThis, hJsonRoot, pErrInfo);
848 else if (!RTStrCmp(pszReq, "Shutdown"))
849 pThis->fShutdown = true;
850 else
851 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "JSON request malformed: \"Request\" contains unknown value \"%s\"", pszReq);
852 }
853 else
854 rc = rtFuzzCmdMasterErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "JSON request malformed: \"Request\" is not a string value");
855
856 RTJsonValueRelease(hJsonValReq);
857 }
858 else
859 rc = rtFuzzCmdMasterErrorRc(pErrInfo, rc, "JSON request malformed: Couldn't find \"Request\" value");
860
861 return rc;
862}
863
864
865/**
866 * Loads a fuzzing configuration for immediate startup from the given file.
867 *
868 * @returns IPRT status code.
869 * @param pThis The fuzzing master command state.
870 * @param pszFuzzCfg The fuzzing config to load.
871 */
872static int rtFuzzCmdMasterFuzzCfgLoadFromFile(PRTFUZZCMDMASTER pThis, const char *pszFuzzCfg)
873{
874 RTJSONVAL hJsonRoot;
875 int rc = RTJsonParseFromFile(&hJsonRoot, pszFuzzCfg, NULL);
876 if (RT_SUCCESS(rc))
877 {
878 rc = rtFuzzCmdMasterProcessJsonReqStart(pThis, hJsonRoot, NULL);
879 RTJsonValueRelease(hJsonRoot);
880 }
881 else
882 rc = rtFuzzCmdMasterErrorRc(NULL, rc, "JSON request malformed: Couldn't load file \"%s\"", pszFuzzCfg);
883
884 return rc;
885}
886
887
888/**
889 * Destroys all running fuzzers for the given master state.
890 *
891 * @returns nothing.
892 * @param pThis The fuzzing master command state.
893 */
894static void rtFuzzCmdMasterDestroy(PRTFUZZCMDMASTER pThis)
895{
896 RT_NOREF(pThis);
897}
898
899
900/**
901 * Sends an ACK response to the client.
902 *
903 * @returns nothing.
904 * @param hSocket The socket handle to send the ACK to.
905 */
906static void rtFuzzCmdMasterTcpSendAck(RTSOCKET hSocket)
907{
908 const char s_szSucc[] = "{ \"Status\": \"ACK\" }\n";
909 RTTcpWrite(hSocket, s_szSucc, sizeof(s_szSucc));
910}
911
912
913/**
914 * Sends an NACK response to the client.
915 *
916 * @returns nothing.
917 * @param hSocket The socket handle to send the ACK to.
918 * @param pErrInfo Optional error information to send along.
919 */
920static void rtFuzzCmdMasterTcpSendNAck(RTSOCKET hSocket, PRTERRINFO pErrInfo)
921{
922 const char s_szFail[] = "{ \"Status\": \"NACK\" }\n";
923 const char s_szFailInfo[] = "{ \"Status\": \"NACK\"\n \"Information\": \"%s\" }\n";
924
925 if (pErrInfo)
926 {
927 char szTmp[1024];
928 ssize_t cchResp = RTStrPrintf2(szTmp, sizeof(szTmp), s_szFailInfo, pErrInfo->pszMsg);
929 if (cchResp > 0)
930 RTTcpWrite(hSocket, szTmp, cchResp);
931 else
932 RTTcpWrite(hSocket, s_szFail, strlen(s_szFail));
933 }
934 else
935 RTTcpWrite(hSocket, s_szFail, strlen(s_szFail));
936}
937
938
939/**
940 * TCP server serving callback for a single connection.
941 *
942 * @returns IPRT status code.
943 * @param hSocket The socket handle of the connection.
944 * @param pvUser Opaque user data.
945 */
946static DECLCALLBACK(int) rtFuzzCmdMasterTcpServe(RTSOCKET hSocket, void *pvUser)
947{
948 PRTFUZZCMDMASTER pThis = (PRTFUZZCMDMASTER)pvUser;
949 size_t cbReqMax = _32K;
950 size_t cbReq = 0;
951 uint8_t *pbReq = (uint8_t *)RTMemAllocZ(cbReqMax);
952
953 if (RT_LIKELY(pbReq))
954 {
955 uint8_t *pbCur = pbReq;
956
957 for (;;)
958 {
959 size_t cbThisRead = cbReqMax - cbReq;
960 int rc = RTTcpRead(hSocket, pbCur, cbThisRead, &cbThisRead);
961 if (RT_SUCCESS(rc))
962 {
963 cbReq += cbThisRead;
964
965 /* Check for a zero terminator marking the end of the request. */
966 uint8_t *pbEnd = (uint8_t *)memchr(pbCur, 0, cbThisRead);
967 if (pbEnd)
968 {
969 /* Adjust request size, data coming after the zero terminiator is ignored right now. */
970 cbReq -= cbThisRead - (pbEnd - pbCur) + 1;
971
972 RTJSONVAL hJsonReq;
973 RTERRINFOSTATIC ErrInfo;
974 RTErrInfoInitStatic(&ErrInfo);
975
976 rc = RTJsonParseFromBuf(&hJsonReq, pbReq, cbReq, &ErrInfo.Core);
977 if (RT_SUCCESS(rc))
978 {
979 rc = rtFuzzCmdMasterProcessJsonReq(pThis, hJsonReq, &ErrInfo.Core);
980 if (RT_SUCCESS(rc))
981 rtFuzzCmdMasterTcpSendAck(hSocket);
982 else
983 rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core);
984 RTJsonValueRelease(hJsonReq);
985 }
986 else
987 rtFuzzCmdMasterTcpSendNAck(hSocket, &ErrInfo.Core);
988 break;
989 }
990 else if (cbReq == cbReqMax)
991 {
992 /* Try to increase the buffer. */
993 uint8_t *pbReqNew = (uint8_t *)RTMemRealloc(pbReq, cbReqMax + _32K);
994 if (RT_LIKELY(pbReqNew))
995 {
996 cbReqMax += _32K;
997 pbReq = pbReqNew;
998 pbCur = pbReq + cbReq;
999 }
1000 else
1001 rtFuzzCmdMasterTcpSendNAck(hSocket, NULL);
1002 }
1003 else
1004 pbCur += cbThisRead;
1005 }
1006 else
1007 break;
1008 }
1009 }
1010 else
1011 rtFuzzCmdMasterTcpSendNAck(hSocket, NULL);
1012
1013 if (pbReq)
1014 RTMemFree(pbReq);
1015
1016 return pThis->fShutdown ? VERR_TCP_SERVER_STOP : VINF_SUCCESS;
1017}
1018
1019
1020/**
1021 * Mainloop for the fuzzing master.
1022 *
1023 * @returns Process exit code.
1024 * @param pThis The fuzzing master command state.
1025 * @param pszLoadCfg Initial config to load.
1026 */
1027static RTEXITCODE rtFuzzCmdMasterRun(PRTFUZZCMDMASTER pThis, const char *pszLoadCfg)
1028{
1029 if (pszLoadCfg)
1030 {
1031 int rc = rtFuzzCmdMasterFuzzCfgLoadFromFile(pThis, pszLoadCfg);
1032 if (RT_FAILURE(rc))
1033 return RTEXITCODE_FAILURE;
1034 }
1035
1036 /* Start up the control server. */
1037 int rc = RTTcpServerCreateEx(NULL, pThis->uPort, &pThis->hTcpSrv);
1038 if (RT_SUCCESS(rc))
1039 {
1040 do
1041 {
1042 rc = RTTcpServerListen(pThis->hTcpSrv, rtFuzzCmdMasterTcpServe, pThis);
1043 } while (rc != VERR_TCP_SERVER_STOP);
1044 }
1045
1046 RTTcpServerDestroy(pThis->hTcpSrv);
1047 rtFuzzCmdMasterDestroy(pThis);
1048 return RTEXITCODE_SUCCESS;
1049}
1050
1051
1052RTR3DECL(RTEXITCODE) RTFuzzCmdMaster(unsigned cArgs, char **papszArgs)
1053{
1054 /*
1055 * Parse the command line.
1056 */
1057 static const RTGETOPTDEF s_aOptions[] =
1058 {
1059 { "--fuzz-config", 'c', RTGETOPT_REQ_STRING },
1060 { "--temp-dir", 't', RTGETOPT_REQ_STRING },
1061 { "--results-dir", 'r', RTGETOPT_REQ_STRING },
1062 { "--listen-port", 'p', RTGETOPT_REQ_UINT16 },
1063 { "--daemonize", 'd', RTGETOPT_REQ_NOTHING },
1064 { "--daemonized", 'Z', RTGETOPT_REQ_NOTHING },
1065 { "--help", 'h', RTGETOPT_REQ_NOTHING },
1066 { "--version", 'V', RTGETOPT_REQ_NOTHING },
1067 };
1068
1069 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
1070 RTGETOPTSTATE GetState;
1071 int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
1072 RTGETOPTINIT_FLAGS_OPTS_FIRST);
1073 if (RT_SUCCESS(rc))
1074 {
1075 /* Option variables: */
1076 bool fDaemonize = false;
1077 bool fDaemonized = false;
1078 const char *pszLoadCfg = NULL;
1079 RTFUZZCMDMASTER This;
1080
1081 RTListInit(&This.LstFuzzed);
1082 This.hTcpSrv = NIL_RTTCPSERVER;
1083 This.uPort = 4242;
1084 This.pszTmpDir = NULL;
1085 This.pszResultsDir = NULL;
1086 This.fShutdown = false;
1087
1088 /* Argument parsing loop. */
1089 bool fContinue = true;
1090 do
1091 {
1092 RTGETOPTUNION ValueUnion;
1093 int chOpt = RTGetOpt(&GetState, &ValueUnion);
1094 switch (chOpt)
1095 {
1096 case 0:
1097 fContinue = false;
1098 break;
1099
1100 case 'c':
1101 pszLoadCfg = ValueUnion.psz;
1102 break;
1103
1104 case 'p':
1105 This.uPort = ValueUnion.u16;
1106 break;
1107
1108 case 't':
1109 This.pszTmpDir = ValueUnion.psz;
1110 break;
1111
1112 case 'r':
1113 This.pszResultsDir = ValueUnion.psz;
1114 break;
1115
1116 case 'd':
1117 fDaemonize = true;
1118 break;
1119
1120 case 'Z':
1121 fDaemonized = true;
1122 fDaemonize = false;
1123 break;
1124
1125 case 'h':
1126 RTPrintf("Usage: to be written\nOption dump:\n");
1127 for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
1128 RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
1129 fContinue = false;
1130 break;
1131
1132 case 'V':
1133 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
1134 fContinue = false;
1135 break;
1136
1137 default:
1138 rcExit = RTGetOptPrintError(chOpt, &ValueUnion);
1139 fContinue = false;
1140 break;
1141 }
1142 } while (fContinue);
1143
1144 if (rcExit == RTEXITCODE_SUCCESS)
1145 {
1146 /*
1147 * Daemonize ourselves if asked to.
1148 */
1149 if (fDaemonize)
1150 {
1151 rc = RTProcDaemonize(papszArgs, "--daemonized");
1152 if (RT_FAILURE(rc))
1153 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTProcDaemonize: %Rrc\n", rc);
1154 }
1155 else
1156 rcExit = rtFuzzCmdMasterRun(&This, pszLoadCfg);
1157 }
1158 }
1159 else
1160 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTGetOptInit: %Rrc", rc);
1161 return rcExit;
1162}
1163
Note: See TracBrowser for help on using the repository browser.

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