-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
539 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import Fuzzilli | ||
|
||
let njsProfile = Profile( | ||
processArgs: { randomize in | ||
["fuzz"] | ||
}, | ||
|
||
processEnv: ["UBSAN_OPTIONS": "handle_segv=0"], | ||
|
||
maxExecsBeforeRespawn: 1000, | ||
|
||
timeout: 250, | ||
|
||
codePrefix: """ | ||
""", | ||
|
||
codeSuffix: """ | ||
""", | ||
|
||
ecmaVersion: ECMAScriptVersion.es6, | ||
|
||
startupTests: [ | ||
// Check that the fuzzilli integration is available. | ||
("fuzzilli('FUZZILLI_PRINT', 'test')", .shouldSucceed), | ||
|
||
// Check that common crash types are detected. | ||
("fuzzilli('FUZZILLI_CRASH', 0)", .shouldCrash), | ||
("fuzzilli('FUZZILLI_CRASH', 1)", .shouldCrash), | ||
("fuzzilli('FUZZILLI_CRASH', 2)", .shouldCrash), | ||
], | ||
|
||
additionalCodeGenerators: [], | ||
|
||
additionalProgramTemplates: WeightedList<ProgramTemplate>([]), | ||
|
||
disabledCodeGenerators: [], | ||
|
||
disabledMutators: [], | ||
|
||
additionalBuiltins: [:], | ||
|
||
additionalObjectGroups: [], | ||
|
||
optionalPostProcessor: nil | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Target: NJS | ||
|
||
To build njs for fuzzing: | ||
* Step 1 - prepare env | ||
* Run `setup.sh`, this will: | ||
* Clone the NJS repo from https://github.com/nginx/njs/ | ||
* Apply the relevant patches & add a _fuzzilli_ JS module | ||
* Step 2 - Build fuzzer | ||
* Run `fuzzbuild.sh`, this will: | ||
* Configure with `./configure --cc=clang --cc-opt="-g -fsanitize-coverage=trace-pc-guard"` | ||
* Run `make njs_fuzzilli` | ||
|
||
The REPRL shell/fuzzable build will be saved at `<njs-dir>/build/njs_fuzzilli` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
d8fbff1b0b1099fac5f75112580d671007584b00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
cd njs/ | ||
./configure --cc=clang --cc-opt="-g -fsanitize-coverage=trace-pc-guard" | ||
make njs_fuzzilli |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/bash | ||
|
||
NEEDLE='main(int argc, char \*\*argv)' | ||
MODIF='not_main(int argc, char \*\*argv)' | ||
sed -i "s/$NEEDLE/$MODIF/" ./external/njs_fuzzilli_shell.c | ||
|
||
sed -i '1s/^/int not_main(int argc, char **argv);\n/' ./external/njs_fuzzilli_shell.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
void __sanitizer_cov_reset_edgeguards(void); | ||
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop); | ||
void __sanitizer_cov_trace_pc_guard(uint32_t *guard); | ||
|
||
struct shmem_data { | ||
uint32_t num_edges; | ||
unsigned char edges[]; | ||
}; | ||
|
||
#define SHM_SIZE 0x100000 | ||
#define MAX_EDGES ((SHM_SIZE - 4) * 8) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
#include <njs.h> | ||
#include <njs_unix.h> | ||
#include <njs_arr.h> | ||
#include <njs_queue.h> | ||
#include <njs_rbtree.h> | ||
#include <stdio.h> | ||
#include <sys/types.h> | ||
#include <sys/mman.h> | ||
#include <sys/stat.h> | ||
#include <fcntl.h> | ||
#include "njs_coverage.h" | ||
#include <njs_fuzzilli_shell.c> | ||
|
||
|
||
// defs | ||
#define REPRL_CRFD 100 | ||
#define REPRL_CWFD 101 | ||
#define REPRL_DRFD 102 | ||
#define REPRL_DWFD 103 | ||
|
||
#define SHM_SIZE 0x100000 | ||
#define MAX_EDGES ((SHM_SIZE - 4) * 8) | ||
|
||
#define CHECK(cond) if (!(cond)) { fprintf(stderr, "\"" #cond "\" failed\n"); _exit(-1); } | ||
|
||
// Will be imported from `njs_fuzzilli_module.o` during linking phase | ||
extern struct shmem_data* __shmem; | ||
extern uint32_t *__edges_start, *__edges_stop; | ||
|
||
|
||
njs_str_t* njs_fetch_fuzz_input(void); | ||
|
||
njs_str_t* njs_fetch_fuzz_input(void) { | ||
njs_str_t *script = NULL; | ||
char *script_src, *ptr; | ||
size_t script_size = 0, remaining = 0; | ||
unsigned action; | ||
|
||
script_size = 0; | ||
CHECK(read(REPRL_CRFD, &action, 4) == 4); | ||
if (action == 'cexe') { | ||
CHECK(read(REPRL_CRFD, &script_size, 8) == 8); | ||
} else { | ||
fprintf(stderr, "Unknown action: %u\n", action); | ||
_exit(-1); | ||
} | ||
|
||
script_src = malloc(script_size+1); | ||
ptr = script_src; | ||
remaining = script_size; | ||
|
||
while (remaining > 0) { | ||
ssize_t rv = read(REPRL_DRFD, ptr, remaining); | ||
if (rv <= 0) { | ||
fprintf(stderr, "Failed to load script\n"); | ||
_exit(-1); | ||
} | ||
remaining -= rv; | ||
ptr += rv; | ||
} | ||
|
||
script = malloc(sizeof(njs_str_t)); | ||
script_src[script_size] = '\0'; | ||
script->start = (u_char*)script_src; | ||
script->length = script_size; | ||
|
||
return script; | ||
} | ||
|
||
|
||
static njs_int_t | ||
njs_main_fuzzable(njs_opts_t *opts) | ||
{ | ||
njs_int_t ret; | ||
njs_engine_t *engine; | ||
|
||
engine = njs_create_engine(opts); | ||
if (engine == NULL) { | ||
return NJS_ERROR; | ||
} | ||
|
||
ret = njs_console_init(opts, &njs_console); | ||
if (njs_slow_path(ret != NJS_OK)) { | ||
njs_stderror("njs_console_init() failed\n"); | ||
return NJS_ERROR; | ||
} | ||
|
||
ret = njs_process_script(engine, &njs_console, &opts->command); | ||
engine->destroy(engine); | ||
return ret; | ||
} | ||
|
||
|
||
int | ||
main(int argc, char **argv) | ||
{ | ||
njs_opts_t opts; | ||
njs_memzero(&opts, sizeof(njs_opts_t)); | ||
int result=0, status=0; | ||
|
||
if(argc < 2) { | ||
printf("usage: ./%s <opt>\navailable opts: \n\t'filename.js' - path of js file to be executed\n\tfuzz - entering REPRL mode(fuzzilli)\n", argv[0]); | ||
return NJS_ERROR; | ||
} | ||
|
||
if(!strcmp(argv[1], "fuzz")) { | ||
char helo[] = "HELO"; | ||
if (write(REPRL_CWFD, helo, 4) != 4 || read(REPRL_CRFD, helo, 4) != 4) { | ||
printf("Invalid HELO response from parent\n"); | ||
_exit(-1); | ||
} | ||
|
||
if (memcmp(helo, "HELO", 4) != 0) { | ||
printf("Invalid response from parent\n"); | ||
_exit(-1); | ||
} | ||
|
||
while(1) { | ||
njs_str_t* fuzzer_input = njs_fetch_fuzz_input(); | ||
|
||
opts.file = (char *) "fuzzer"; | ||
opts.command.start = fuzzer_input->start; | ||
opts.command.length = fuzzer_input->length; | ||
opts.suppress_stdout = 0; | ||
result = njs_main_fuzzable(&opts); | ||
|
||
free(fuzzer_input->start); | ||
free(fuzzer_input); | ||
|
||
status = (result & 0xff) << 8; | ||
CHECK(write(REPRL_CWFD, &status, 4) == 4); | ||
__sanitizer_cov_reset_edgeguards(); | ||
} | ||
} else { | ||
njs_int_t ret; | ||
njs_engine_t *engine; | ||
|
||
opts.file = argv[1]; | ||
engine = njs_create_engine(&opts); | ||
if (engine == NULL) { | ||
return NJS_ERROR; | ||
} | ||
|
||
ret = njs_console_init(&opts, &njs_console); | ||
if (njs_slow_path(ret != NJS_OK)) { | ||
njs_stderror("njs_console_init() failed\n"); | ||
return NJS_ERROR; | ||
} | ||
result = njs_process_file(&opts); | ||
engine->destroy(engine); | ||
|
||
} | ||
|
||
return result; | ||
} | ||
|
Oops, something went wrong.