VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/fuzz/fuzzclientcmd.cpp@ 74158

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

Runtime/RTFuzz: Some updates, add a mode where the client is aware of being fuzzed for improved efficiency. The input data is fuzzed in the client and fed to the consumer until the program crashes upon the master can reconstruct the input causing the crash because we work with deterministic random number generators. This eliminates the overhead of constantly spawning new client processes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: fuzzclientcmd.cpp 72940 2018-07-07 13:37:19Z vboxsync $ */
2/** @file
3 * IPRT - Fuzzing framework API, fuzzed client 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/assert.h>
35#include <iprt/buildconfig.h>
36#include <iprt/getopt.h>
37#include <iprt/mem.h>
38#include <iprt/message.h>
39#include <iprt/stream.h>
40#include <iprt/string.h>
41#include <iprt/types.h>
42#include <iprt/vfs.h>
43
44
45/**
46 * Fuzzing client command state.
47 */
48typedef struct RTFUZZCMDCLIENT
49{
50 /** Our own fuzzing context containing all the data. */
51 RTFUZZCTX hFuzzCtx;
52 /** Consumption callback. */
53 PFNFUZZCLIENTCONSUME pfnConsume;
54 /** Opaque user data to pass to the consumption callback. */
55 void *pvUser;
56 /** Standard input VFS handle. */
57 RTVFSIOSTREAM hVfsStdIn;
58 /** Standard output VFS handle. */
59 RTVFSIOSTREAM hVfsStdOut;
60} RTFUZZCMDCLIENT;
61/** Pointer to a fuzzing client command state. */
62typedef RTFUZZCMDCLIENT *PRTFUZZCMDCLIENT;
63
64
65/**
66 * The fuzzing client mainloop.
67 *
68 * @returns IPRT status code.
69 * @param pThis The fuzzing client command state.
70 */
71static int rtFuzzCmdClientMainloop(PRTFUZZCMDCLIENT pThis)
72{
73 int rc = VINF_SUCCESS;
74 bool fShutdown = false;
75
76 while ( !fShutdown
77 && RT_SUCCESS(rc))
78 {
79 RTFUZZINPUT hFuzzInput;
80
81 rc = RTFuzzCtxInputGenerate(pThis->hFuzzCtx, &hFuzzInput);
82 if (RT_SUCCESS(rc))
83 {
84 void *pv = NULL;
85 size_t cb = 0;
86 rc = RTFuzzInputQueryData(hFuzzInput, &pv, &cb);
87 if (RT_SUCCESS(rc))
88 {
89 char bResp = '.';
90 int rc2 = pThis->pfnConsume(pv, cb, pThis->pvUser);
91 if (RT_SUCCESS(rc2))
92 {
93 rc = RTFuzzInputAddToCtxCorpus(hFuzzInput);
94 bResp = 'A';
95 }
96
97 if (RT_SUCCESS(rc))
98 rc = RTVfsIoStrmWrite(pThis->hVfsStdOut, &bResp, 1, true /*fBlocking*/, NULL);
99 }
100
101 RTFuzzInputRelease(hFuzzInput);
102 }
103 }
104
105 return rc;
106}
107
108
109/**
110 * Run the fuzzing client.
111 *
112 * @returns Process exit status.
113 * @param pThis The fuzzing client command state.
114 */
115static RTEXITCODE rtFuzzCmdClientRun(PRTFUZZCMDCLIENT pThis)
116{
117 int rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_INPUT, 0, true /*fLeaveOpen*/, &pThis->hVfsStdIn);
118 if (RT_SUCCESS(rc))
119 {
120 rc = RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, 0, true /*fLeaveOpen*/, &pThis->hVfsStdOut);
121 if (RT_SUCCESS(rc))
122 {
123 /* Read the initial input fuzzer state from the standard input. */
124 uint32_t cbFuzzCtxState;
125 rc = RTVfsIoStrmRead(pThis->hVfsStdIn, &cbFuzzCtxState, sizeof(cbFuzzCtxState), true /*fBlocking*/, NULL);
126 if (RT_SUCCESS(rc))
127 {
128 void *pvFuzzCtxState = RTMemAllocZ(cbFuzzCtxState);
129 if (RT_LIKELY(pvFuzzCtxState))
130 {
131 rc = RTVfsIoStrmRead(pThis->hVfsStdIn, pvFuzzCtxState, cbFuzzCtxState, true /*fBlocking*/, NULL);
132 if (RT_SUCCESS(rc))
133 {
134 rc = RTFuzzCtxCreateFromState(&pThis->hFuzzCtx, pvFuzzCtxState, cbFuzzCtxState);
135 if (RT_SUCCESS(rc))
136 rc = rtFuzzCmdClientMainloop(pThis);
137 }
138
139 RTMemFree(pvFuzzCtxState);
140 }
141 else
142 rc = VERR_NO_MEMORY;
143 }
144 }
145 }
146
147 if (RT_SUCCESS(rc))
148 return RTEXITCODE_SUCCESS;
149
150 return RTEXITCODE_FAILURE;
151}
152
153
154RTR3DECL(RTEXITCODE) RTFuzzCmdFuzzingClient(unsigned cArgs, char **papszArgs, PFNFUZZCLIENTCONSUME pfnConsume, void *pvUser)
155{
156 /*
157 * Parse the command line.
158 */
159 static const RTGETOPTDEF s_aOptions[] =
160 {
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 RTFUZZCMDCLIENT This;
173
174 This.pfnConsume = pfnConsume;
175 This.pvUser = pvUser;
176
177 /* Argument parsing loop. */
178 bool fContinue = true;
179 do
180 {
181 RTGETOPTUNION ValueUnion;
182 int chOpt = RTGetOpt(&GetState, &ValueUnion);
183 switch (chOpt)
184 {
185 case 0:
186 fContinue = false;
187 break;
188
189 case 'h':
190 RTPrintf("Usage: to be written\nOption dump:\n");
191 for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
192 RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
193 fContinue = false;
194 break;
195
196 case 'V':
197 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
198 fContinue = false;
199 break;
200
201 default:
202 rcExit = RTGetOptPrintError(chOpt, &ValueUnion);
203 fContinue = false;
204 break;
205 }
206 } while (fContinue);
207
208 if (rcExit == RTEXITCODE_SUCCESS)
209 rcExit = rtFuzzCmdClientRun(&This);
210 }
211 else
212 rcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "RTGetOptInit: %Rrc", rc);
213 return rcExit;
214}
215
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