DarthShader is a fuzzer for fuzzing the WebGPU shader compilation pipeline in web browsers. To this end, the fuzzer uses a combination of code generation and mutation to produce WebGPU shaders (wgsl). These wgsl shaders are then processed by a shader translator (the front-end). In particular, we support the shader translators of Chrome (tint), Firefox (naga), and Safari (wgslc). These components translate the input shader into a representation native to the respective GPU stack of the host operating system. For example, on Windows the WebGPU shaders are translated to HLSL. Once this native representation has been generated, shaders are then further processed by the respective graphics stack (the back-end). On Windows, HLSL shaders are consumed by dxcompiler, the shader compiler of DirectX12. DarthShader also supports testing of this component: First, WebGPU shaders are translated with tint to HLSL. Next, the HLSL output is fed into dxcompiler. This two-stage approach replicates the shader translation pipeline and hence ensures that crashes in dxcompiler are reachable from the web.
The usage of DarthShader is best explained by its --help
switch:
Usage: darthshader [OPTIONS] --output <out> <exec> [-- [arguments]...]
Arguments:
<exec> The instrumented binary we want to fuzz
[arguments]...
Options:
-o, --output <out> The directory to place finds in ('corpus')
-i, --input <in> The directory to read initial inputs from ('seeds')
-l, --logfile <logfile> Duplicates all output to this file [default: libafl.log]
-t, --timeout <timeout> Timeout for each individual execution, in milliseconds [default: 1200]
-d, --debug-child If not set, the child's stdout and stderror will be redirected to /dev/null
--iterations <iterations> Number of iterations to fuzz
--config <generatorconfig> The .yaml generator config file
--seed <generatorseed> Seed for the generation process
--discard-crashes Do not store crashes but explore for coverage only
-h, --help Print help
-V, --version Print version
The most important arguments are:
exec
argument specifies the fuzzing harness executable.--output
folder contains two sub-directories. There is the queue
file which contains all samples contributing new coverage. In addition, there is a crashes
directory containing, as the name implies, all crashes found during the fuzzing campaign. Note that the samples are serialized in .ron
files. Converting them to .wgsl
files is possible using the lifter. This utility program is build alongside the fuzzer.--input
folder will be traversed recursively for all shader files for importing them.The fuzzer supports importing seeds from in the following formats: wgsl, spv, and glsl. In our evaluation (and as a good starting point), we use the dawn
repository as source, as it contains thousands of shaders.
The fuzzing targets are instrumented with a variant of the well-known AFL++ instrumentation. More precisely, the only difference is that instead of collecting hit-counts, we only collect information about whether an edge was hit (or not). Please note that the AFL++ forkserver was recently updated. The libAFL version used by DarthShader is incompatible with these changes. Hence building with an older version of AFL++ (e.g., 4.10c) is required.
DarthShader currently provided fuzzing harnesses for 4 different shader compilers. These are 3 front-end translators used directly in browsers (tint, naga, wgslc) and the back-end compiler of DirectX, dxcompiler. For each of the fuzzing targets, the repository contains patches that add an AFL forkserver to the target.
This is the shader compiler of Chrome, supporting compilation from WGSL to the HLSL (Windows), SPIR-V (Linux & Android), and Metal (OSX). Our fuzzing harness for tint translates a single WGSL shader to each of the three target languages.
This is the DirectX shader compiler taking HLSL as input and producing an output format based on LLVM IR. Our fuzzing harness first translates WGSL shaders to HLSL via tint and subsequently passes the HLSL code to dxc, our setup hence replicates browser usage.
This is the shader compiler of Firefox supporting compilation from WGSL to HLSL, SPIR-V, and Metal. Analogue to the tint harness, our naga harness translates a single WGSL shader to HLSL, SPIR-V, and Metal.
The shader compiler of Safari translating WGSL to Metal. No other output languages are supported.