├── scripts ├── dict ├── fuzz.sh ├── run.sh └── create-image.sh ├── libfuzzer-ng ├── README.txt ├── build.sh ├── FuzzerExtraCountersDarwin.cpp ├── FuzzerMain.cpp ├── FuzzerFork.h ├── FuzzerSHA1.h ├── dataflow │ ├── DataFlow.h │ ├── DataFlowCallbacks.cpp │ └── DataFlow.cpp ├── FuzzerExtFunctions.h ├── FuzzerUtilLinux.cpp ├── FuzzerBuiltins.h ├── FuzzerExtraCounters.cpp ├── FuzzerDefs.h ├── FuzzerExtFunctionsDlsym.cpp ├── standalone │ └── StandaloneFuzzTargetMain.c ├── FuzzerCrossOver.cpp ├── FuzzerRandom.h ├── FuzzerExtFunctionsWeak.cpp ├── FuzzerBuiltinsMsvc.h ├── FuzzerValueBitMap.h ├── FuzzerExtFunctions.def ├── scripts │ └── unbalanced_allocs.py ├── FuzzerOptions.h ├── FuzzerExtFunctionsWindows.cpp ├── FuzzerInterface.h ├── FuzzerExtraCountersWindows.cpp ├── tests │ └── CMakeLists.txt ├── FuzzerMerge.h ├── FuzzerUtil.h ├── FuzzerDictionary.h ├── FuzzerIO.h ├── FuzzerDataFlowTrace.h ├── FuzzerPlatform.h ├── FuzzerIOPosix.cpp ├── FuzzerUtilPosix.cpp ├── CMakeLists.txt ├── FuzzerUtilDarwin.cpp ├── FuzzerIO.cpp ├── FuzzerSHA1.cpp ├── FuzzerCommand.h ├── FuzzerInternal.h ├── FuzzerUtilWindows.cpp ├── FuzzerUtil.cpp └── FuzzerMutate.h ├── media └── bitmap.png ├── configs ├── bpf.h ├── nvme.h ├── kvm.h ├── v4l2.h └── binder.h ├── agent ├── Makefile ├── driver.h ├── device.h ├── fuzz_configs.h ├── startup.sh ├── fuzz_config.h ├── conveyor.h ├── virt2phys.c ├── fuzz.h ├── driver.c ├── kcov.h ├── user_access.c ├── kcov.c ├── bloat.c └── conveyor.c ├── LICENSE ├── Makefile └── README.md /scripts/dict: -------------------------------------------------------------------------------- 1 | KW1="FUZZ" 2 | KW2="syzkaller\x00" 3 | -------------------------------------------------------------------------------- /libfuzzer-ng/README.txt: -------------------------------------------------------------------------------- 1 | See http://llvm.org/docs/LibFuzzer.html 2 | -------------------------------------------------------------------------------- /media/bitmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BUseclab/FuzzNG/HEAD/media/bitmap.png -------------------------------------------------------------------------------- /libfuzzer-ng/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | LIBFUZZER_SRC_DIR=$(dirname $0) 3 | CXX="${CXX:-clang}" 4 | for f in $LIBFUZZER_SRC_DIR/*.cpp; do 5 | $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 -fPIE $f -c & 6 | done 7 | wait 8 | rm -f libFuzzer.a 9 | ar ru libFuzzer.a Fuzzer*.o 10 | rm -f Fuzzer*.o 11 | 12 | -------------------------------------------------------------------------------- /configs/bpf.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "bpf"; 2 | fdconf conf_fds[] = {}; 3 | uint64_t conf_initscs[][6] = {}; 4 | scconf conf_scs[] = { 5 | { 6 | .nr = __NR_bpf, 7 | .args = 3, 8 | .mask_enabled = 1, 9 | .mask = {-1, -1, -1, -1, -1, -1}, 10 | .identity_arg = 1, 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /agent/Makefile: -------------------------------------------------------------------------------- 1 | EXTRA_CFLAGS=-std=c99 -Werror -O3 2 | LDFLAGS=-lpthread 3 | OBJ = main.o kcov.o virt2phys.o driver.o bloat.o user_access.o conveyor.o 4 | 5 | %.o: %.c 6 | $(CC) -c -o $@ $< $(CFLAGS) $(EXTRA_CFLAGS) 7 | 8 | fuzz: $(OBJ) 9 | $(CC) -o $@ $^ $(CFLAGS) $(EXTRA_CFLAGS) $(LDFLAGS) 10 | 11 | clean: 12 | rm -f *.o fuzz 13 | 14 | ctags: 15 | ctags -R . 16 | -------------------------------------------------------------------------------- /agent/driver.h: -------------------------------------------------------------------------------- 1 | #ifndef DRIVER_H 2 | #define DRIVER_H 3 | 4 | #include "fuzz.h" 5 | 6 | struct cfu_details {void* addr; size_t len; int string;}; 7 | 8 | int get_driver_fd(void); 9 | void driver_watch(void); 10 | void driver_stopwatch(void); 11 | int driver_open(void); 12 | void driver_cleanup(void); 13 | 14 | void driver_start_fuzzing(void); 15 | void driver_clear_patterns(void); 16 | 17 | int driver_set_reverse_fd_offset(int i); 18 | 19 | struct cfu_details driver_get_cfu_details(void); 20 | 21 | void driver_complete_cfu(void); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /agent/device.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICE_H 2 | #define DEVICE_H 3 | 4 | enum { 5 | FUZZ_DEVICE_MAKE_SNAPSHOT = 0, 6 | FUZZ_DEVICE_ADD_CMP_ARRAY=12, 7 | FUZZ_DEVICE_RESET=16, 8 | FUZZ_DEVICE_ADD_INPUT_REGION=20, 9 | FUZZ_DEVICE_GET_INPUT=24, 10 | FUZZ_DEVICE_ADD_OUTPUT_REGION=28, 11 | FUZZ_DEVICE_ADD_REMOTE_COV_ARRAY=32, 12 | FUZZ_DEVICE_ADD_PFN_BASE=36, 13 | FUZZ_DEVICE_ADD_PFN_SIZE=40, 14 | FUZZ_DEVICE_SHOW_TRACE=44, 15 | FUZZ_DEVICE_SET_KCOV_TIMER=48, 16 | FUZZ_DEVICE_ADD_SYSCALL_LOG=52, 17 | FUZZ_DEVICE_ADD_STR0=56, 18 | FUZZ_DEVICE_ADD_STR1=60, 19 | FUZZ_DEVICE_STRCMP=64, 20 | FUZZ_DEVICE_ABORT_INPUT=68, 21 | FUZZ_DEVICE_OPS_END 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /agent/fuzz_configs.h: -------------------------------------------------------------------------------- 1 | #ifndef FUZZ_CONFIGS_H 2 | #define FUZZ_CONFIGS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | typedef struct fdconf { 18 | const char *path; 19 | int flags; 20 | } fdconf; 21 | 22 | typedef struct scconf { 23 | int nr; 24 | int args; 25 | int mask_enabled; 26 | uint64_t mask[6]; 27 | int min_enabled; 28 | uint64_t min[6]; 29 | int identity_arg; 30 | } scconf; 31 | 32 | #include "fuzz_config.h" 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /configs/nvme.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "nvme"; 2 | fdconf conf_fds[] = {{"/dev/nvme0n1", O_RDWR},{"/dev/nvme-fabrics", O_RDWR},{"/dev/nvme0", O_RDWR},{"/dev/ng0n1", O_RDWR}}; 3 | uint64_t conf_initscs[][6] = {{}}; 4 | scconf conf_scs[] = { 5 | {.nr = __NR_ioctl, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 6 | {.nr = __NR_mmap, .args = 6, .mask_enabled = 1, .mask = {0, 0xF000, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_POPULATE, 0xFFFF, -1}}, 7 | {.nr = __NR_close, .args = 1, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 8 | {.nr = __NR_fstat, .args = 2, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 9 | {.nr = __NR_read, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 10 | {.nr = __NR_write, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 11 | }; 12 | -------------------------------------------------------------------------------- /agent/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | ulimit -n 1048576 4 | mknod /dev/fuzzer c $(cat /proc/devices | grep fuzz | cut -f 1 -d " ") 0 5 | mknod /dev/megaraid_sas_ioctl c $(cat /proc/devices | grep megaraid_sas_ioctl | cut -f 1 -d " ") 0 6 | mknod /dev/megadev_legacy c $(cat /proc/devices | grep megadev_legacy | cut -f 1 -d " ") 0 &> /dev/ttyS0 7 | mknod /dev/infiniband_verbs c $(cat /proc/devices | grep infiniband_verbs | tail -n1 | cut -f 1 -d " ") 0 &> /dev/ttyS0 8 | echo 0 | tee /proc/sys/kernel/randomize_va_space &> /dev/ttyS0 9 | sleep 10 10 | /etc/init.d/crond stop 11 | mkdir /dev/binderfs &> /dev/ttyS0 12 | mount -t binder binder /dev/binderfs &> /dev/ttyS0 13 | find /dev/ > /dev/ttyS0 14 | cp -r /hostshare/ /tmp/agent 15 | cd /tmp/agent 16 | make clean; make &> /dev/ttyS0 17 | LD_BIND_NOW=1 nice -20 ./fuzz &> /dev/ttyS0 18 | echo Returned $? 19 | shutdown now 20 | -------------------------------------------------------------------------------- /configs/kvm.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "kvm"; 2 | fdconf conf_fds[] = {{"/dev/kvm", O_RDWR}}; 3 | uint64_t conf_initscs[][6] = {{}}; 4 | scconf conf_scs[] = { 5 | {.nr = __NR_ioctl, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 6 | {.nr = __NR_mmap, .args = 6, .mask_enabled = 1, .mask = {0, 0xF000, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_POPULATE, 0xFFFF, -1}}, 7 | {.nr = __NR_close, .args = 1, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 8 | {.nr = __NR_fstat, .args = 2, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 9 | {.nr = __NR_read, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 10 | {.nr = __NR_write, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 11 | {.nr = __NR_eventfd, .args = 2, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}} 12 | }; 13 | -------------------------------------------------------------------------------- /agent/fuzz_config.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "kvm"; 2 | fdconf conf_fds[] = {{"/dev/kvm", O_RDWR}}; 3 | uint64_t conf_initscs[][6] = {{}}; 4 | scconf conf_scs[] = { 5 | {.nr = __NR_ioctl, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 6 | {.nr = __NR_mmap, .args = 6, .mask_enabled = 1, .mask = {0, 0xF000, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_POPULATE, 0xFFFF, -1}}, 7 | {.nr = __NR_close, .args = 1, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 8 | {.nr = __NR_fstat, .args = 2, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 9 | {.nr = __NR_read, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 10 | {.nr = __NR_write, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 11 | {.nr = __NR_eventfd, .args = 2, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}} 12 | }; 13 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtraCountersDarwin.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtraCountersDarwin.cpp - Extra coverage counters for Darwin -===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Extra coverage counters defined by user code for Darwin. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerPlatform.h" 12 | #include 13 | 14 | #if LIBFUZZER_APPLE 15 | 16 | namespace fuzzer { 17 | uint8_t *ExtraCountersBegin() { return nullptr; } 18 | uint8_t *ExtraCountersEnd() { return nullptr; } 19 | void ClearExtraCounters() {} 20 | } // namespace fuzzer 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerMain.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerMain.cpp - main() function and flags -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // main() and flags. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | #include "FuzzerPlatform.h" 13 | 14 | extern "C" { 15 | // This function should be defined by the user. 16 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 17 | } // extern "C" 18 | 19 | ATTRIBUTE_INTERFACE int main(int argc, char **argv) { 20 | return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); 21 | } 22 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerFork.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerFork.h - run fuzzing in sub-processes --------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef LLVM_FUZZER_FORK_H 10 | #define LLVM_FUZZER_FORK_H 11 | 12 | #include "FuzzerDefs.h" 13 | #include "FuzzerOptions.h" 14 | #include "FuzzerRandom.h" 15 | 16 | #include 17 | 18 | namespace fuzzer { 19 | void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, 20 | const std::vector &Args, 21 | const std::vector &CorpusDirs, int NumJobs); 22 | } // namespace fuzzer 23 | 24 | #endif // LLVM_FUZZER_FORK_H 25 | -------------------------------------------------------------------------------- /configs/v4l2.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "v4l2"; 2 | fdconf conf_fds[] = {{"/dev/video0", O_RDWR},{"/dev/video1", O_RDWR},{"/dev/video2", O_RDWR},{"/dev/video10", O_RDWR},{"/dev/swradio0", O_RDWR},{"/dev/radio0", O_RDWR},{"/dev/vbi0", O_RDWR},{"/dev/cec0", O_RDWR},{"/dev/v4l-subdev0", O_RDWR}}; 3 | uint64_t conf_initscs[][6] = {{}}; 4 | scconf conf_scs[] = { 5 | {.nr = __NR_ioctl, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 6 | {.nr = __NR_mmap, .args = 6, .mask_enabled = 1, .mask = {0, 0xF000, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_POPULATE, 0xFFFF, -1}}, 7 | {.nr = __NR_close, .args = 1, .mask_enabled = 1, .mask = {0xFFF, -1, -1, -1, -1, -1}}, 8 | {.nr = __NR_read, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1}}, 9 | {.nr = __NR_write, .args = 3, .mask_enabled = 1, .mask = {0xFFF, -1, 0xFFFF, -1, -1, -1} 10 | },{.nr = __NR_ppoll, .args = 4, .mask_enabled = 1, .mask = {-1, 0xFFF, -1, -1, -1, -1}} 11 | }; 12 | -------------------------------------------------------------------------------- /agent/conveyor.h: -------------------------------------------------------------------------------- 1 | #ifndef CONVEYOR_H 2 | #define CONVEYOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void ic_setup(size_t max_input); 9 | void ic_new_input(uint8_t* in, size_t len); 10 | void ic_output(uint8_t *out, size_t *len, size_t max_len); 11 | int ic_ingest8(uint8_t *result, uint8_t min, uint8_t max); 12 | int ic_ingest16(uint16_t *result, uint16_t min, uint16_t max); 13 | int ic_ingest32(uint32_t *result, uint32_t min, uint32_t max, uint32_t mask); 14 | int ic_ingest64(uint64_t *result, uint64_t min, uint64_t max); 15 | uint8_t* ic_ingest_buf(size_t *len, uint8_t* token, size_t token_len, int minlen, int string); 16 | void *ic_advance_until_token(uint8_t* token, size_t len); 17 | size_t ic_get_last_token(void); 18 | void* ic_insert(void* src, size_t len, size_t pos); 19 | size_t ic_length_until_token(uint8_t* token, size_t len); 20 | void ic_erase_backwards_until_token(void); 21 | size_t ic_get_cursor(void); 22 | 23 | // Returns the size of the next buffer 24 | size_t ic_lookahead(uint8_t* token, size_t token_len) ; 25 | #endif 26 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerSHA1.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // SHA1 utils. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_SHA1_H 12 | #define LLVM_FUZZER_SHA1_H 13 | 14 | #include "FuzzerDefs.h" 15 | #include 16 | #include 17 | 18 | namespace fuzzer { 19 | 20 | // Private copy of SHA1 implementation. 21 | static const int kSHA1NumBytes = 20; 22 | 23 | // Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. 24 | void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); 25 | 26 | std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); 27 | 28 | std::string Hash(const Unit &U); 29 | 30 | } // namespace fuzzer 31 | 32 | #endif // LLVM_FUZZER_SHA1_H 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 BUseclab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libfuzzer-ng/dataflow/DataFlow.h: -------------------------------------------------------------------------------- 1 | /*===- DataFlow.h - a standalone DataFlow trace -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Internal header file to connect DataFlow.cpp and DataFlowCallbacks.cpp. 9 | //===----------------------------------------------------------------------===*/ 10 | 11 | #ifndef __LIBFUZZER_DATAFLOW_H 12 | #define __LIBFUZZER_DATAFLOW_H 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | // This data is shared between DataFlowCallbacks.cpp and DataFlow.cpp. 19 | struct CallbackData { 20 | size_t NumFuncs, NumGuards; 21 | const uintptr_t *PCsBeg, *PCsEnd; 22 | dfsan_label *FuncLabels; // Array of NumFuncs elements. 23 | bool *BBExecuted; // Array of NumGuards elements. 24 | }; 25 | 26 | extern CallbackData __dft; 27 | 28 | enum { 29 | PCFLAG_FUNC_ENTRY = 1, 30 | }; 31 | 32 | #endif // __LIBFUZZER_DATAFLOW_H 33 | -------------------------------------------------------------------------------- /configs/binder.h: -------------------------------------------------------------------------------- 1 | char *conf_name = "binder"; 2 | fdconf conf_fds[] = {{"/dev/binderfs/vndbinder", O_RDWR|O_NONBLOCK}, {"/dev/binderfs/hwbinder", O_RDWR|O_NONBLOCK},{"/dev/binderfs/binder-control", O_RDWR|O_NONBLOCK},{"/dev/binderfs/binder", O_RDWR|O_NONBLOCK},{"/sys/kernel/debug/binder/state", O_RDWR|O_NONBLOCK},{"/sys/kernel/debug/binder/failed_transaction_log", O_RDWR|O_NONBLOCK},{"/sys/kernel/debug/binder/stats", O_RDWR|O_NONBLOCK},{"/sys/kernel/debug/binder/transaction_log", O_RDWR|O_NONBLOCK},{"/sys/kernel/debug/binder/transactions", O_RDWR|O_NONBLOCK}}; 3 | uint64_t conf_initscs[][6] = {{}}; 4 | scconf conf_scs[] = { 5 | {.nr = __NR_ioctl,.args = 3,.mask_enabled = 1,.mask = {0xFFF, -1, -1, -1, -1, -1},}, 6 | {.nr = __NR_mmap,.args = 6,.mask_enabled = 1,.mask = {0, 0xF000, PROT_READ | PROT_WRITE, MAP_SHARED, 0xFFFF, -1},}, 7 | {.nr = __NR_close,.args = 1,.mask_enabled = 1,.mask = {0xFFF, -1, -1, -1, -1, -1},}, 8 | {.nr = __NR_fstat,.args = 2,.mask_enabled = 1,.mask = {0xFFF, -1, -1, -1, -1, -1},}, 9 | {.nr = __NR_read,.args = 3,.mask_enabled = 1,.mask = {0xFFF, -1, 0xFFFF, -1, -1, -1},}, 10 | {.nr = __NR_write,.args = 3,.mask_enabled = 1,.mask = {0xFFF, -1, 0xFFFF, -1, -1, -1},} 11 | }; 12 | -------------------------------------------------------------------------------- /agent/virt2phys.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define PAGEMAP_LENGTH 8 9 | 10 | size_t virt_to_phys(void* vaddr){ 11 | unsigned long paddr = 0; 12 | int page_size, page_shift = -1; 13 | FILE *pagemap = fopen("/proc/self/pagemap", "rb"); 14 | page_size = sysconf(_SC_PAGESIZE); 15 | size_t offset = ((size_t)vaddr / page_size) * PAGEMAP_LENGTH; 16 | fseek(pagemap, (unsigned long)offset, SEEK_SET); 17 | if (fread(&paddr, 1, (PAGEMAP_LENGTH-1), pagemap) < (PAGEMAP_LENGTH-1)) { 18 | perror("fread fails. "); 19 | exit(0); 20 | } 21 | paddr = paddr & 0x7fffffffffffff; 22 | /* printf("physical frame address is 0x%lx\n", paddr); */ 23 | 24 | offset = (size_t)vaddr % page_size; 25 | 26 | /* PAGE_SIZE = 1U << PAGE_SHIFT */ 27 | while (!((1UL << ++page_shift) & page_size)); 28 | 29 | paddr = (unsigned long)((unsigned long)paddr << page_shift) + offset; 30 | //printf("physical address is 0x%lx\n", paddr); 31 | fclose(pagemap); 32 | return paddr; 33 | } 34 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtFunctions.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Defines an interface to (possibly optional) functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_EXT_FUNCTIONS_H 12 | #define LLVM_FUZZER_EXT_FUNCTIONS_H 13 | 14 | #include 15 | #include 16 | 17 | namespace fuzzer { 18 | 19 | struct ExternalFunctions { 20 | // Initialize function pointers. Functions that are not available will be set 21 | // to nullptr. Do not call this constructor before ``main()`` has been 22 | // entered. 23 | ExternalFunctions(); 24 | 25 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 26 | RETURN_TYPE(*NAME) FUNC_SIG = nullptr 27 | 28 | #include "FuzzerExtFunctions.def" 29 | 30 | #undef EXT_FUNC 31 | }; 32 | } // namespace fuzzer 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtilLinux.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils for Linux. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerPlatform.h" 11 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ 12 | LIBFUZZER_EMSCRIPTEN 13 | #include "FuzzerCommand.h" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | namespace fuzzer { 22 | 23 | int ExecuteCommand(const Command &Cmd) { 24 | std::string CmdLine = Cmd.toString(); 25 | int exit_code = system(CmdLine.c_str()); 26 | if (WIFEXITED(exit_code)) 27 | return WEXITSTATUS(exit_code); 28 | return exit_code; 29 | } 30 | 31 | void DiscardOutput(int Fd) { 32 | FILE* Temp = fopen("/dev/null", "w"); 33 | if (!Temp) 34 | return; 35 | dup2(fileno(Temp), Fd); 36 | fclose(Temp); 37 | } 38 | 39 | } // namespace fuzzer 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /agent/fuzz.h: -------------------------------------------------------------------------------- 1 | #ifndef FUZZ_H 2 | #define FUZZ_H 3 | 4 | #include 5 | #include 6 | 7 | /* 8 | * SEPARATOR is used to separate "operations" in the fuzz input 9 | */ 10 | 11 | #define SEPARATOR (uint8_t*)"FUZZ" 12 | #ifndef DEBUG 13 | #define DEBUG 0 14 | #endif 15 | #define debug_printf(fmt, ...) \ 16 | do { \ 17 | if (DEBUG){ \ 18 | printf(fmt, __VA_ARGS__); \ 19 | fflush(stdout); \ 20 | } \ 21 | } while (0) 22 | 23 | typedef struct { 24 | uint8_t index; /* Index of a byte to increment by stride */ 25 | uint8_t stride; /* Increment each index'th byte by this amount */ 26 | size_t len; 27 | const uint8_t *data; 28 | } pattern; 29 | 30 | extern unsigned char libfuzzer_coverage[32 << 10]; 31 | 32 | size_t virt_to_phys(void* vaddr); 33 | 34 | void pattern_alloc(void* ptr, size_t len, pattern p); 35 | 36 | extern pattern last_pattern; 37 | 38 | void bloatme(void); 39 | 40 | void early_exit(void); 41 | void cfu_worker_start(int fd); 42 | void kcov_print_data(void); 43 | void abort_input(void); 44 | uint64_t kcov_get_current(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerBuiltins.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Wrapper functions and marcos around builtin functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_BUILTINS_H 12 | #define LLVM_FUZZER_BUILTINS_H 13 | 14 | #include "FuzzerPlatform.h" 15 | 16 | #if !LIBFUZZER_MSVC 17 | #include 18 | 19 | #define GET_CALLER_PC() __builtin_return_address(0) 20 | 21 | namespace fuzzer { 22 | 23 | inline uint8_t Bswap(uint8_t x) { return x; } 24 | inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } 25 | inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } 26 | inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } 27 | 28 | inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); } 29 | inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); } 30 | 31 | } // namespace fuzzer 32 | 33 | #endif // !LIBFUZZER_MSVC 34 | #endif // LLVM_FUZZER_BUILTINS_H 35 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtraCounters.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Extra coverage counters defined by user code. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerPlatform.h" 12 | #include 13 | 14 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ 15 | LIBFUZZER_FUCHSIA || LIBFUZZER_EMSCRIPTEN 16 | __attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters; 17 | __attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters; 18 | 19 | namespace fuzzer { 20 | uint8_t *ExtraCountersBegin() { return &__start___libfuzzer_extra_counters; } 21 | uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } 22 | ATTRIBUTE_NO_SANITIZE_ALL 23 | void ClearExtraCounters() { // hand-written memset, don't asan-ify. 24 | uintptr_t *Beg = reinterpret_cast(ExtraCountersBegin()); 25 | uintptr_t *End = reinterpret_cast(ExtraCountersEnd()); 26 | for (; Beg < End; Beg++) { 27 | *Beg = 0; 28 | __asm__ __volatile__("" : : : "memory"); 29 | } 30 | } 31 | 32 | } // namespace fuzzer 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /agent/driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "driver.h" 8 | 9 | #define MAGIC 'k' 10 | #define WATCH _IO(MAGIC, 1) 11 | #define STOPWATCH _IO(MAGIC, 2) 12 | #define FUZZINGSTAGE _IO(MAGIC, 3) 13 | #define CLEAR_PATTERNS _IO(MAGIC, 4) 14 | #define SET_REVERSE_FD_OFFSET _IO(MAGIC, 5) 15 | #define CLEANUP _IO(MAGIC, 6) 16 | #define GET_CFU_DETAILS _IOW(MAGIC, 7, struct cfu_details) 17 | #define COMPLETE_CFU _IO(MAGIC, 8) 18 | 19 | 20 | static int fd; 21 | 22 | int get_driver_fd(void){ 23 | return fd; 24 | } 25 | void driver_start_fuzzing(void){ 26 | assert(fd); 27 | assert(ioctl(fd, FUZZINGSTAGE) == 0); 28 | } 29 | 30 | void driver_clear_patterns(void){ 31 | assert(fd); 32 | assert(ioctl(fd, CLEAR_PATTERNS) == 0); 33 | } 34 | 35 | void driver_watch(void){ 36 | assert(fd); 37 | assert(ioctl(fd, WATCH) == 0); 38 | } 39 | 40 | void driver_stopwatch(void){ 41 | assert(fd); 42 | assert(ioctl(fd, STOPWATCH) == 0); 43 | } 44 | 45 | void driver_cleanup(void){ 46 | assert(fd); 47 | int d=ioctl(fd, CLEANUP); 48 | } 49 | 50 | struct cfu_details driver_get_cfu_details(void){ 51 | struct cfu_details ret; 52 | assert(fd); 53 | ioctl(fd, GET_CFU_DETAILS, &ret); 54 | return ret; 55 | } 56 | 57 | void driver_complete_cfu(void){ 58 | assert(fd); 59 | int d=ioctl(fd, COMPLETE_CFU); 60 | } 61 | 62 | int driver_set_reverse_fd_offset(int i){ 63 | return ioctl(fd, SET_REVERSE_FD_OFFSET, i); 64 | } 65 | 66 | int driver_open(void){ 67 | fd = open("/dev/fuzzer", O_RDWR); 68 | cfu_worker_start(fd); 69 | return fd == -1; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerDefs.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Basic definitions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_DEFS_H 12 | #define LLVM_FUZZER_DEFS_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | namespace fuzzer { 25 | 26 | template T Min(T a, T b) { return a < b ? a : b; } 27 | template T Max(T a, T b) { return a > b ? a : b; } 28 | 29 | class Random; 30 | class Dictionary; 31 | class DictionaryEntry; 32 | class MutationDispatcher; 33 | struct FuzzingOptions; 34 | class InputCorpus; 35 | struct InputInfo; 36 | struct ExternalFunctions; 37 | 38 | // Global interface to functions that may or may not be available. 39 | extern ExternalFunctions *EF; 40 | 41 | typedef std::vector Unit; 42 | typedef std::vector UnitVector; 43 | typedef int (*UserCallback)(const uint8_t *Data, size_t Size); 44 | 45 | int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); 46 | 47 | uint8_t *ExtraCountersBegin(); 48 | uint8_t *ExtraCountersEnd(); 49 | void ClearExtraCounters(); 50 | 51 | extern bool RunningUserCallback; 52 | 53 | } // namespace fuzzer 54 | 55 | #endif // LLVM_FUZZER_DEFS_H 56 | -------------------------------------------------------------------------------- /agent/kcov.h: -------------------------------------------------------------------------------- 1 | #ifndef KCOV_H 2 | #define KCOV_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "fuzz.h" 8 | 9 | #define KCOV_COVER_SIZE (256 << 11) 10 | #define KCOV_TRACE_PC 0 11 | #define KCOV_INIT_TRACE64 _IOR('c', 1, uint64_t) 12 | #define KCOV_REMOTE_ENABLE _IOW('c', 102, struct kcov_remote_arg) 13 | #define KCOV_ENABLE _IO('c', 100) 14 | #define KCOV_DISABLE _IO('c', 101) 15 | 16 | #define KCOV_WORDS_PER_CMP 4 17 | 18 | #define KCOV_TRACE_PC 0 19 | #define KCOV_TRACE_CMP 1 20 | 21 | 22 | #define KCOV_SUBSYSTEM_COMMON (0x00ull << 56) 23 | #define KCOV_SUBSYSTEM_USB (0x01ull << 56) 24 | 25 | #define KCOV_SUBSYSTEM_MASK (0xffull << 56) 26 | #define KCOV_INSTANCE_MASK (0xffffffffull) 27 | 28 | #define KCOV_COMMON_ID 42 29 | #define KCOV_USB_BUS_NUM 1 30 | 31 | struct kcov_remote_arg { 32 | __u32 trace_mode; 33 | __u32 area_size; 34 | __u32 num_handles; 35 | __aligned_u64 common_handle; 36 | __aligned_u64 handles[0]; 37 | }; 38 | 39 | static inline __u64 kcov_remote_handle(__u64 subsys, __u64 inst) 40 | { 41 | if (subsys & ~KCOV_SUBSYSTEM_MASK || inst & ~KCOV_INSTANCE_MASK) 42 | return 0; 43 | return subsys | inst; 44 | } 45 | 46 | #define KCOV_CMP_CONST (1 << 0) 47 | #define KCOV_CMP_SIZE(n) ((n) << 1) 48 | #define KCOV_CMP_MASK KCOV_CMP_SIZE(3) 49 | 50 | void kcov_init(void); 51 | void kcov_trace_pc(void); 52 | void kcov_trace_cmp(void); 53 | 54 | void kcov_sync_coverage(void); 55 | void kcov_reset_coverage(void); 56 | void kcov_check_coverage(void); 57 | void set_mode(int trace_pc); 58 | 59 | uint64_t kcov_get_current(void); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /scripts/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ] || [ -z "$2" ]; then 4 | echo "Usage: fuzz.h num_jobs path/to/config" 5 | exit 6 | fi 7 | 8 | if [ -z "$LOGS_DIR" ]; then 9 | LOGS_DIR=./logs 10 | mkdir -p $LOGS_DIR 11 | fi 12 | 13 | if [ -z "$PROJECT_ROOT" ]; then 14 | export PROJECT_ROOT="./" 15 | fi 16 | 17 | cp "$2" "$PROJECT_ROOT/agent/fuzz_config.h" 18 | 19 | for i in $(seq "$1"); do 20 | if (( i % 3 == 0 )); then 21 | export FUZZ_TRACE_PC="TRACEPC-"; 22 | else 23 | unset FUZZ_TRACE_PC 24 | fi 25 | 26 | if (( i % 2 == 0 )); then 27 | export MUTATE_SYSCALLS="1"; 28 | else 29 | unset MUTATE_SYSCALLS 30 | fi 31 | 32 | if (( i % 6 == 0)); then 33 | export FUZZ_ABORT_ERRORS="ABORTERRORS-" 34 | else 35 | unset FUZZ_ABORT_ERRORS 36 | fi 37 | 38 | tmpd=$(mktemp -d "$LOGS_DIR/kernel-fuzzer-$i-$FUZZ_TRACE_PC$FUZZ_ABORT_ERRORS$KASAN-XXXXX") 39 | export PORT=$(( i + 10100 )) 40 | "${BASH_SOURCE%/*}/run.sh" &> "$tmpd/output" & 41 | sleep 1; 42 | done 43 | 44 | cat << 'EOF' 45 | oooooooooooo ooooo ooo .oooooo. 46 | `888' `8 `888b. `8' d8P' `Y8b 47 | 888 oooo oooo oooooooo oooooooo 8 `88b. 8 888 48 | 888oooo8 `888 `888 d'""7d8P d'""7d8P 8 `88b. 8 888 49 | 888 " 888 888 .d8P' .d8P' 8 `88b.8 888 ooooo 50 | 888 888 888 .d8P' .P .d8P' .P 8 `888 `88. .88' 51 | o888o `V88V"V8P' d8888888P d8888888P o8o `8 `Y8bood8P' 52 | EOF 53 | echo "Initialized $1 Workers with Config: $2" 54 | sleep 1 55 | ls -tr "$LOGS_DIR"/*/output | tail -n"$1" | xargs tail -fq 56 | wait 57 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtFunctionsDlsym.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation for operating systems that support dlsym(). We only use it on 9 | // Apple platforms for now. We don't use this approach on Linux because it 10 | // requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker. 11 | // That is a complication we don't wish to expose to clients right now. 12 | //===----------------------------------------------------------------------===// 13 | #include "FuzzerPlatform.h" 14 | #if LIBFUZZER_APPLE 15 | 16 | #include "FuzzerExtFunctions.h" 17 | #include "FuzzerIO.h" 18 | #include 19 | 20 | using namespace fuzzer; 21 | 22 | template 23 | static T GetFnPtr(const char *FnName, bool WarnIfMissing) { 24 | dlerror(); // Clear any previous errors. 25 | void *Fn = dlsym(RTLD_DEFAULT, FnName); 26 | if (Fn == nullptr) { 27 | if (WarnIfMissing) { 28 | const char *ErrorMsg = dlerror(); 29 | Printf("WARNING: Failed to find function \"%s\".", FnName); 30 | if (ErrorMsg) 31 | Printf(" Reason %s.", ErrorMsg); 32 | Printf("\n"); 33 | } 34 | } 35 | return reinterpret_cast(Fn); 36 | } 37 | 38 | namespace fuzzer { 39 | 40 | ExternalFunctions::ExternalFunctions() { 41 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 42 | this->NAME = GetFnPtr(#NAME, WARN) 43 | 44 | #include "FuzzerExtFunctions.def" 45 | 46 | #undef EXT_FUNC 47 | } 48 | 49 | } // namespace fuzzer 50 | 51 | #endif // LIBFUZZER_APPLE 52 | -------------------------------------------------------------------------------- /libfuzzer-ng/standalone/StandaloneFuzzTargetMain.c: -------------------------------------------------------------------------------- 1 | /*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This main() function can be linked to a fuzz target (i.e. a library 9 | // that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) 10 | // instead of libFuzzer. This main() function will not perform any fuzzing 11 | // but will simply feed all input files one by one to the fuzz target. 12 | // 13 | // Use this file to provide reproducers for bugs when linking against libFuzzer 14 | // or other fuzzing engine is undesirable. 15 | //===----------------------------------------------------------------------===*/ 16 | #include 17 | #include 18 | #include 19 | 20 | extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); 21 | __attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); 22 | int main(int argc, char **argv) { 23 | fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); 24 | if (LLVMFuzzerInitialize) 25 | LLVMFuzzerInitialize(&argc, &argv); 26 | for (int i = 1; i < argc; i++) { 27 | fprintf(stderr, "Running: %s\n", argv[i]); 28 | FILE *f = fopen(argv[i], "r"); 29 | assert(f); 30 | fseek(f, 0, SEEK_END); 31 | size_t len = ftell(f); 32 | fseek(f, 0, SEEK_SET); 33 | unsigned char *buf = (unsigned char*)malloc(len); 34 | size_t n_read = fread(buf, 1, len, f); 35 | fclose(f); 36 | assert(n_read == len); 37 | LLVMFuzzerTestOneInput(buf, len); 38 | free(buf); 39 | fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | KVERSION=linux-6.1 3 | 4 | NPROC ?=2 5 | 6 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 7 | PROJECT_ROOT := $(dir $(MKFILE_PATH)) 8 | 9 | all: image kernelbuild qemubuild libfuzzerng 10 | 11 | # .:: kernel + mod-ng ::. 12 | 13 | kernelbuild: kernel-build/.config mod-ng 14 | cd $(PROJECT_ROOT)/kernel; KBUILD_OUTPUT=$(PROJECT_ROOT)/kernel-build/ \ 15 | make -j$(NPROC) CC=$(CC) \ 16 | KCFLAGS="-fsanitize-coverage-allowlist=$(PROJECT_ROOT)/kernel/whitelist" 17 | 18 | mod-ng: kernel kernel/include/linux/fuzzer_dev.h 19 | 20 | kernel/include/linux/fuzzer_dev.h: 21 | ifeq (,$(wildcard kernel/include/linux/fuzzer_dev.h)) 22 | git apply -v --directory=kernel/ kernel-patches/*.patch 23 | endif 24 | 25 | kernel-build/.config: 26 | mkdir -p kernel-build 27 | cp kernel-configs/general kernel-build/.config 28 | 29 | kernel: 30 | curl -s -L https://cdn.kernel.org/pub/linux/kernel/v6.x/$(KVERSION).tar.gz | tar -xz 31 | cp -r $(KVERSION) kernel 32 | 33 | # .:: qemu-ng ::. 34 | qemubuild: qemu/build/qemu-fuzz-x86_64 35 | 36 | qemu/build/qemu-fuzz-x86_64: qemu/hw/i386/fuzz.c libfuzzerng qemu-build 37 | cd qemu-build; ninja -j$(NPROC) qemu-fuzz-x86_64 38 | 39 | qemu-build: 40 | mkdir -p qemu-build; cd qemu-build; \ 41 | LIB_FUZZING_ENGINE="$(PROJECT_ROOT)/libfuzzer-ng/libFuzzer.a" \ 42 | $(PROJECT_ROOT)/qemu/configure --enable-fuzzing --enable-virtfs; 43 | 44 | qemu/hw/i386/fuzz.c: qemu/ 45 | ifeq (,$(wildcard qemu/hw/i386/fuzz.c)) 46 | cd $(PROJECT_ROOT)/qemu; git am $(PROJECT_ROOT)/qemu-patches/*.patch 47 | endif 48 | 49 | qemu/: 50 | git clone https://gitlab.com/qemu-project/qemu 51 | cd qemu; git checkout v8.0.0; 52 | 53 | # .:: agent ::. 54 | # agentbuild: 55 | # cd $(PROJECT_ROOT)/agent; make 56 | 57 | # .:: libfuzzer-ng ::. 58 | libfuzzerng: libfuzzer-ng/libFuzzer.a 59 | 60 | libfuzzer-ng/libFuzzer.a: 61 | cd libfuzzer-ng; ./build.sh 62 | 63 | # .:: image ::. 64 | 65 | image: images/bullseye.img 66 | 67 | images/bullseye.img: 68 | mkdir -p images 69 | cd images; $(PROJECT_ROOT)/scripts/create-image.sh 70 | 71 | run: 72 | 73 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerCrossOver.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Cross over test inputs. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | #include "FuzzerMutate.h" 13 | #include "FuzzerRandom.h" 14 | #include 15 | 16 | namespace fuzzer { 17 | 18 | // Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. 19 | size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, 20 | const uint8_t *Data2, size_t Size2, 21 | uint8_t *Out, size_t MaxOutSize) { 22 | assert(Size1 || Size2); 23 | MaxOutSize = Rand(MaxOutSize) + 1; 24 | size_t OutPos = 0; 25 | size_t Pos1 = 0; 26 | size_t Pos2 = 0; 27 | size_t *InPos = &Pos1; 28 | size_t InSize = Size1; 29 | const uint8_t *Data = Data1; 30 | bool CurrentlyUsingFirstData = true; 31 | while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { 32 | // Merge a part of Data into Out. 33 | size_t OutSizeLeft = MaxOutSize - OutPos; 34 | if (*InPos < InSize) { 35 | size_t InSizeLeft = InSize - *InPos; 36 | size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); 37 | size_t ExtraSize = Rand(MaxExtraSize) + 1; 38 | memcpy(Out + OutPos, Data + *InPos, ExtraSize); 39 | OutPos += ExtraSize; 40 | (*InPos) += ExtraSize; 41 | } 42 | // Use the other input data on the next iteration. 43 | InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; 44 | InSize = CurrentlyUsingFirstData ? Size2 : Size1; 45 | Data = CurrentlyUsingFirstData ? Data2 : Data1; 46 | CurrentlyUsingFirstData = !CurrentlyUsingFirstData; 47 | } 48 | return OutPos; 49 | } 50 | 51 | } // namespace fuzzer 52 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerRandom.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::Random 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_RANDOM_H 12 | #define LLVM_FUZZER_RANDOM_H 13 | 14 | #include 15 | 16 | namespace fuzzer { 17 | class Random : public std::minstd_rand { 18 | public: 19 | Random(unsigned int seed) : std::minstd_rand(seed) {} 20 | result_type operator()() { return this->std::minstd_rand::operator()(); } 21 | template 22 | typename std::enable_if::value, T>::type Rand() { 23 | return static_cast(this->operator()()); 24 | } 25 | size_t RandBool() { return this->operator()() % 2; } 26 | size_t SkewTowardsLast(size_t n) { 27 | size_t T = this->operator()(n * n); 28 | size_t Res = static_cast(sqrt(T)); 29 | return Res; 30 | } 31 | template 32 | typename std::enable_if::value, T>::type operator()(T n) { 33 | return n ? Rand() % n : 0; 34 | } 35 | template 36 | typename std::enable_if::value, T>::type 37 | operator()(T From, T To) { 38 | assert(From < To); 39 | auto RangeSize = static_cast(To) - 40 | static_cast(From) + 1; 41 | return static_cast(this->operator()(RangeSize) + From); 42 | } 43 | }; 44 | 45 | // N-1 is k times more likely than 0 46 | inline int biased_rand(int n, int k, Random &Rand) { 47 | double nf = n; 48 | double kf = k; 49 | double rf = nf * (kf/2 + 1) * (double)(Rand(100000))/(double)100000; 50 | double bf = (-1 + sqrt(1+2*kf*rf/nf)) * nf / kf; 51 | return (int)bf; 52 | }; 53 | 54 | } // namespace fuzzer 55 | 56 | #endif // LLVM_FUZZER_RANDOM_H 57 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtFunctionsWeak.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation for Linux. This relies on the linker's support for weak 9 | // symbols. We don't use this approach on Apple platforms because it requires 10 | // clients of LibFuzzer to pass ``-U _`` to the linker to allow 11 | // weak symbols to be undefined. That is a complication we don't want to expose 12 | // to clients right now. 13 | //===----------------------------------------------------------------------===// 14 | #include "FuzzerPlatform.h" 15 | #if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \ 16 | LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN 17 | 18 | #include "FuzzerExtFunctions.h" 19 | #include "FuzzerIO.h" 20 | 21 | extern "C" { 22 | // Declare these symbols as weak to allow them to be optionally defined. 23 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 24 | __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG 25 | 26 | #include "FuzzerExtFunctions.def" 27 | 28 | #undef EXT_FUNC 29 | } 30 | 31 | using namespace fuzzer; 32 | 33 | static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) { 34 | if (FnPtr == nullptr && WarnIfMissing) { 35 | Printf("WARNING: Failed to find function \"%s\".\n", FnName); 36 | } 37 | } 38 | 39 | namespace fuzzer { 40 | 41 | ExternalFunctions::ExternalFunctions() { 42 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 43 | this->NAME = ::NAME; \ 44 | CheckFnPtr(reinterpret_cast(reinterpret_cast(::NAME)), \ 45 | #NAME, WARN); 46 | 47 | #include "FuzzerExtFunctions.def" 48 | 49 | #undef EXT_FUNC 50 | } 51 | 52 | } // namespace fuzzer 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | 4 | if [ -z "$PORT" ]; then 5 | PORT=10021 6 | fi 7 | 8 | if [ -z "$SHARE_DIR" ]; then 9 | SHARE_DIR=$PROJECT_ROOT/agent/ 10 | fi 11 | 12 | 13 | if [ -z "$CORPUS_DIR" ]; then 14 | CORPUS_DIR=CORPUS/ 15 | mkdir -p $CORPUS_DIR 16 | fi 17 | 18 | if [ -z "$kernel" ]; then 19 | kernel=$PROJECT_ROOT/kernel-build/arch/x86/boot/bzImage 20 | fi 21 | 22 | if [ -z "$qemu" ]; then 23 | qemu=$PROJECT_ROOT/qemu-build/qemu-fuzz-x86_64 24 | fi 25 | 26 | image=$PROJECT_ROOT/images/bullseye.img 27 | 28 | export QEMU_SNAP_ARGS="-cpu host,kvm=on,svm=on \ 29 | -machine q35,vmport=off,smbus=off,acpi=off,usb=off,graphics=off -m 1G \ 30 | -kernel $kernel \ 31 | -append 'root=/dev/vda earlyprintk=ttyS0 console=ttyS0 nokaslr silent notsc acpi=off \ 32 | kvm-intel.nested=1 kvm-intel.unrestricted_guest=1 kvm-intel.vmm_exclusive=1 kvm-intel.fasteoi=1 \ 33 | kvm-intel.ept=1 kvm-intel.flexpriority=1 kvm-intel.vpid=1 kvm-intel.emulate_invalid_guest_state=1 \ 34 | kvm-intel.eptad=1 kvm-intel.enable_shadow_vmcs=1 kvm-intel.pml=1 kvm-intel.enable_apicv=1' \ 35 | -drive file=$image,id=dr0,format=raw,if=none \ 36 | -virtfs local,path=$SHARE_DIR,mount_tag=host0,security_model=none,id=host0,readonly=on \ 37 | -device virtio-blk-pci,drive=dr0 \ 38 | -nographic -accel kvm -nodefaults -nographic \ 39 | -drive file=null-co://,if=none,id=nvm -vga virtio \ 40 | -device megasas,id=scsi0 \ 41 | -device scsi-hd,drive=drive0,bus=scsi0.0,channel=0,scsi-id=0,lun=0 \ 42 | -drive file=null-co://,if=none,id=drive0 \ 43 | -device nvme,serial=deadbeef,drive=nvm \ 44 | -serial none -snapshot -cdrom /dev/null $EXTRA_ARGS" 45 | 46 | if [[ -n "$NET_ENABLE" ]]; then 47 | export QEMU_SNAP_ARGS="$QEMU_SNAP_ARGS \ 48 | -device virtio-net-pci,netdev=net0 \ 49 | -netdev user,id=net0,host=10.0.2.11,hostfwd=tcp:127.0.0.1:$PORT-:22" 50 | fi 51 | 52 | echo $QEMU_SNAP_ARGS 53 | $qemu \ 54 | -rss_limit_mb=8096 \ 55 | -use_value_profile=1 \ 56 | -detect_leaks=0 \ 57 | -dict=$PROJECT_ROOT/scripts/dict \ 58 | -len_control=200 \ 59 | -reload=60 \ 60 | $EXTRA_FUZZARGS \ 61 | $CORPUS_DIR 62 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerBuiltinsMsvc.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Wrapper functions and marcos that use intrinsics instead of builtin functions 9 | // which cannot be compiled by MSVC. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef LLVM_FUZZER_BUILTINS_MSVC_H 13 | #define LLVM_FUZZER_BUILTINS_MSVC_H 14 | 15 | #include "FuzzerPlatform.h" 16 | 17 | #if LIBFUZZER_MSVC 18 | #include 19 | #include 20 | #include 21 | 22 | // __builtin_return_address() cannot be compiled with MSVC. Use the equivalent 23 | // from 24 | #define GET_CALLER_PC() _ReturnAddress() 25 | 26 | namespace fuzzer { 27 | 28 | inline uint8_t Bswap(uint8_t x) { return x; } 29 | // Use alternatives to __builtin functions from and on 30 | // Windows since the builtins are not supported by MSVC. 31 | inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } 32 | inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } 33 | inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } 34 | 35 | // The functions below were mostly copied from 36 | // compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used 37 | // outside of Windows. 38 | inline uint32_t Clzll(uint64_t X) { 39 | unsigned long LeadZeroIdx = 0; 40 | 41 | #if !defined(_M_ARM) && !defined(_M_X64) 42 | // Scan the high 32 bits. 43 | if (_BitScanReverse(&LeadZeroIdx, static_cast(X >> 32))) 44 | return static_cast( 45 | 63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. 46 | // Scan the low 32 bits. 47 | if (_BitScanReverse(&LeadZeroIdx, static_cast(X))) 48 | return static_cast(63 - LeadZeroIdx); 49 | 50 | #else 51 | if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; 52 | #endif 53 | return 64; 54 | } 55 | 56 | inline int Popcountll(unsigned long long X) { 57 | #if !defined(_M_ARM) && !defined(_M_X64) 58 | return __popcnt(X) + __popcnt(X >> 32); 59 | #else 60 | return __popcnt64(X); 61 | #endif 62 | } 63 | 64 | } // namespace fuzzer 65 | 66 | #endif // LIBFUZER_MSVC 67 | #endif // LLVM_FUZZER_BUILTINS_MSVC_H 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | FuzzNG is a system-call fuzzer for the Linux Kernel, designed to minimize the 6 | need for system-call descriptions. For details, see our 7 | [NDSS 2023 paper](https://www.ndss-symposium.org/ndss-paper/no-grammar-no-problem-towards-fuzzing-the-linux-kernel-without-system-call-descriptions/). 8 | 9 | FuzzNG is composed of 4 main components. 10 | 11 | * **agent-ng** is the user-space process that executes fuzzing system-calls. Located in `agent/` 12 | * **mod-ng** is the set of kernel modifications that "reshape" the pointer and 13 | file-descriptor input spaces. Located in `kernel-patches/` 14 | * **qemu-ng** is the full-vm snapshot fuzzer which places new inputs into ng-agent 15 | and resets the entire VM after each input. Located in `qemu-patches/` 16 | * **libfuzzer-ng** is a modified version of libfuzzer used for input generation. Located in `libfuzzer-ng` 17 | 18 | # Instructions 19 | These instructions were tested on Debian 12. A CPU with VT-x support is 20 | preferable. 21 | The user needs rw permissions for /dev/kvm 22 | 23 | Install Requirements: 24 | ```bash 25 | # QEMU: 26 | sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build 27 | 28 | # Kernel: 29 | sudo apt-get install build-essential linux-source bc kmod cpio flex libncurses5-dev libelf-dev libssl-dev dwarves bison 30 | 31 | # Misc: 32 | sudo apt install llvm deboostrap qemu-img 33 | ``` 34 | 35 | Build Kernel + FuzzNG (mod-ng/qemu-ng/libfuzzer-ng/agent-ng) 36 | 37 | Note that clang is required. 38 | ```bash 39 | NPROC=4 CC=clang-15 CXX=clang++15 make 40 | # This may ask for your password to set up the disk-image for the fuzzing VM. 41 | ``` 42 | 43 | Now pick a fuzzing-config from `configs/` and start the fuzzer: 44 | 45 | ```bash 46 | # Fuzz KVM with 4 workers 47 | ./scripts/fuzz.sh 4 configs/kvm.h 48 | ``` 49 | 50 | Or, to run a single worker with serial-output from the VM enabled: 51 | ```bash 52 | # Manually copy the KVM config: 53 | cp configs/kvm.h agent/fuzz_config.h 54 | 55 | # Run a fuzzer 56 | EXTRA_ARGS="-serial stdio" PROJECT_ROOT="./" ./scripts/run.sh 57 | ``` 58 | 59 | If you use FuzzNG for your publication, please consider citing the paper: 60 | ```bibtex 61 | @inproceedings{fuzzng, 62 | title={{No Grammar, No Problem: Towards Fuzzing the Linux Kernel without System-Call Descriptions}}, 63 | author={Bulekov, Alexander and Das, Bandan and Hajnoczi, Stefan, and Egele, Manuel}, 64 | booktitle={Symposium on Network and Distributed System Security (NDSS)}, 65 | year={2023} 66 | } 67 | ``` 68 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerValueBitMap.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // ValueBitMap. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_VALUE_BIT_MAP_H 12 | #define LLVM_FUZZER_VALUE_BIT_MAP_H 13 | 14 | #include "FuzzerPlatform.h" 15 | #include 16 | 17 | namespace fuzzer { 18 | 19 | // A bit map containing kMapSizeInWords bits. 20 | struct ValueBitMap { 21 | static const size_t kMapSizeInBits = 1 << 16; 22 | static const size_t kMapPrimeMod = 65371; // Largest Prime < kMapSizeInBits; 23 | static const size_t kBitsInWord = (sizeof(uintptr_t) * 8); 24 | static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord; 25 | public: 26 | 27 | // Clears all bits. 28 | void Reset() { memset(Map, 0, sizeof(Map)); } 29 | 30 | // Computes a hash function of Value and sets the corresponding bit. 31 | // Returns true if the bit was changed from 0 to 1. 32 | ATTRIBUTE_NO_SANITIZE_ALL 33 | inline bool AddValue(uintptr_t Value) { 34 | uintptr_t Idx = Value % kMapSizeInBits; 35 | uintptr_t WordIdx = Idx / kBitsInWord; 36 | uintptr_t BitIdx = Idx % kBitsInWord; 37 | uintptr_t Old = Map[WordIdx]; 38 | uintptr_t New = Old | (1ULL << BitIdx); 39 | Map[WordIdx] = New; 40 | return New != Old; 41 | } 42 | 43 | ATTRIBUTE_NO_SANITIZE_ALL 44 | inline bool AddValueModPrime(uintptr_t Value) { 45 | return AddValue(Value % kMapPrimeMod); 46 | } 47 | 48 | inline bool Get(uintptr_t Idx) { 49 | assert(Idx < kMapSizeInBits); 50 | uintptr_t WordIdx = Idx / kBitsInWord; 51 | uintptr_t BitIdx = Idx % kBitsInWord; 52 | return Map[WordIdx] & (1ULL << BitIdx); 53 | } 54 | 55 | size_t SizeInBits() const { return kMapSizeInBits; } 56 | 57 | template 58 | ATTRIBUTE_NO_SANITIZE_ALL 59 | void ForEach(Callback CB) const { 60 | for (size_t i = 0; i < kMapSizeInWords; i++) 61 | if (uintptr_t M = Map[i]) 62 | for (size_t j = 0; j < sizeof(M) * 8; j++) 63 | if (M & ((uintptr_t)1 << j)) 64 | CB(i * sizeof(M) * 8 + j); 65 | } 66 | 67 | private: 68 | ATTRIBUTE_ALIGNED(512) uintptr_t Map[kMapSizeInWords]; 69 | }; 70 | 71 | } // namespace fuzzer 72 | 73 | #endif // LLVM_FUZZER_VALUE_BIT_MAP_H 74 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtFunctions.def: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This defines the external function pointers that 9 | // ``fuzzer::ExternalFunctions`` should contain and try to initialize. The 10 | // EXT_FUNC macro must be defined at the point of inclusion. The signature of 11 | // the macro is: 12 | // 13 | // EXT_FUNC(, , , ) 14 | //===----------------------------------------------------------------------===// 15 | 16 | // Optional user functions 17 | EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); 18 | EXT_FUNC(LLVMFuzzerCustomMutator, size_t, 19 | (uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed), 20 | false); 21 | EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, 22 | (const uint8_t *Data1, size_t Size1, 23 | const uint8_t *Data2, size_t Size2, 24 | uint8_t *Out, size_t MaxOutSize, unsigned int Seed), 25 | false); 26 | 27 | // Sanitizer functions 28 | EXT_FUNC(__lsan_enable, void, (), false); 29 | EXT_FUNC(__lsan_disable, void, (), false); 30 | EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false); 31 | EXT_FUNC(__sanitizer_acquire_crash_state, int, (), true); 32 | EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int, 33 | (void (*malloc_hook)(const volatile void *, size_t), 34 | void (*free_hook)(const volatile void *)), 35 | false); 36 | EXT_FUNC(__sanitizer_log_write, void, (const char *buf, size_t len), false); 37 | EXT_FUNC(__sanitizer_purge_allocator, void, (), false); 38 | EXT_FUNC(__sanitizer_print_memory_profile, void, (size_t, size_t), false); 39 | EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); 40 | EXT_FUNC(__sanitizer_symbolize_pc, void, 41 | (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); 42 | EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, 43 | (void *pc, char *module_path, 44 | size_t module_path_len,void **pc_offset), false); 45 | EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); 46 | EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); 47 | EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false); 48 | EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false); 49 | EXT_FUNC(__msan_unpoison, void, (const volatile void *, size_t size), false); 50 | EXT_FUNC(__msan_unpoison_param, void, (size_t n), false); 51 | -------------------------------------------------------------------------------- /libfuzzer-ng/scripts/unbalanced_allocs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# 3 | # 4 | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 | # See https://llvm.org/LICENSE.txt for license information. 6 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 | # 8 | #===------------------------------------------------------------------------===# 9 | # 10 | # Post-process -trace_malloc=2 output and printout only allocations and frees 11 | # unbalanced inside of fuzzer runs. 12 | # Usage: 13 | # my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5 14 | # 15 | #===------------------------------------------------------------------------===# 16 | 17 | import argparse 18 | import sys 19 | 20 | _skip = 0 21 | 22 | def PrintStack(line, stack): 23 | global _skip 24 | if _skip > 0: 25 | return 26 | print('Unbalanced ' + line.rstrip()); 27 | for l in stack: 28 | print(l.rstrip()) 29 | 30 | def ProcessStack(line, f): 31 | stack = [] 32 | while line and line.startswith(' #'): 33 | stack += [line] 34 | line = f.readline() 35 | return line, stack 36 | 37 | def ProcessFree(line, f, allocs): 38 | if not line.startswith('FREE['): 39 | return f.readline() 40 | 41 | addr = int(line.split()[1], 16) 42 | next_line, stack = ProcessStack(f.readline(), f) 43 | if addr in allocs: 44 | del allocs[addr] 45 | else: 46 | PrintStack(line, stack) 47 | return next_line 48 | 49 | def ProcessMalloc(line, f, allocs): 50 | if not line.startswith('MALLOC['): 51 | return ProcessFree(line, f, allocs) 52 | 53 | addr = int(line.split()[1], 16) 54 | assert not addr in allocs 55 | 56 | next_line, stack = ProcessStack(f.readline(), f) 57 | allocs[addr] = (line, stack) 58 | return next_line 59 | 60 | def ProcessRun(line, f): 61 | if not line.startswith('MallocFreeTracer: START'): 62 | return ProcessMalloc(line, f, {}) 63 | 64 | allocs = {} 65 | print(line.rstrip()) 66 | line = f.readline() 67 | while line: 68 | if line.startswith('MallocFreeTracer: STOP'): 69 | global _skip 70 | _skip = _skip - 1 71 | for _, (l, s) in allocs.items(): 72 | PrintStack(l, s) 73 | print(line.rstrip()) 74 | return f.readline() 75 | line = ProcessMalloc(line, f, allocs) 76 | return line 77 | 78 | def ProcessFile(f): 79 | line = f.readline() 80 | while line: 81 | line = ProcessRun(line, f); 82 | 83 | def main(argv): 84 | parser = argparse.ArgumentParser() 85 | parser.add_argument('--skip', default=0, help='number of runs to ignore') 86 | args = parser.parse_args() 87 | global _skip 88 | _skip = int(args.skip) + 1 89 | ProcessFile(sys.stdin) 90 | 91 | if __name__ == '__main__': 92 | main(sys.argv) 93 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3 | // See https://llvm.org/LICENSE.txt for license information. 4 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 | // 6 | //===----------------------------------------------------------------------===// 7 | // fuzzer::FuzzingOptions 8 | //===----------------------------------------------------------------------===// 9 | 10 | #ifndef LLVM_FUZZER_OPTIONS_H 11 | #define LLVM_FUZZER_OPTIONS_H 12 | 13 | #include "FuzzerDefs.h" 14 | 15 | namespace fuzzer { 16 | 17 | struct FuzzingOptions { 18 | int Verbosity = 1; 19 | size_t MaxLen = 0; 20 | size_t LenControl = 1000; 21 | bool KeepSeed = false; 22 | int UnitTimeoutSec = 300; 23 | int TimeoutExitCode = 70; 24 | int OOMExitCode = 71; 25 | int InterruptExitCode = 72; 26 | int ErrorExitCode = 77; 27 | bool IgnoreTimeouts = true; 28 | bool IgnoreOOMs = true; 29 | bool IgnoreCrashes = false; 30 | int MaxTotalTimeSec = 0; 31 | int RssLimitMb = 0; 32 | int MallocLimitMb = 0; 33 | bool DoCrossOver = true; 34 | bool CrossOverUniformDist = false; 35 | int MutateDepth = 5; 36 | bool ReduceDepth = false; 37 | bool UseCounters = false; 38 | bool UseMemmem = true; 39 | bool UseCmp = false; 40 | int UseValueProfile = false; 41 | bool Shrink = false; 42 | bool ReduceInputs = false; 43 | int ReloadIntervalSec = 1; 44 | bool ShuffleAtStartUp = true; 45 | bool PreferSmall = true; 46 | size_t MaxNumberOfRuns = -1L; 47 | int ReportSlowUnits = 10; 48 | bool OnlyASCII = false; 49 | bool Entropic = true; 50 | bool ForkCorpusGroups = false; 51 | size_t EntropicFeatureFrequencyThreshold = 0xFF; 52 | size_t EntropicNumberOfRarestFeatures = 100; 53 | bool EntropicScalePerExecTime = true; 54 | std::string OutputCorpus; 55 | std::string ArtifactPrefix = "./"; 56 | std::string ExactArtifactPath; 57 | std::string ExitOnSrcPos; 58 | std::string ExitOnItem; 59 | std::string FocusFunction; 60 | std::string DataFlowTrace; 61 | std::string CollectDataFlow; 62 | std::string FeaturesDir; 63 | std::string MutationGraphFile; 64 | std::string StopFile; 65 | bool SaveArtifacts = true; 66 | bool PrintNEW = true; // Print a status line when new units are found; 67 | bool PrintNewCovPcs = false; 68 | int PrintNewCovFuncs = 0; 69 | bool PrintFinalStats = false; 70 | bool PrintCorpusStats = false; 71 | bool PrintCoverage = false; 72 | bool PrintFullCoverage = false; 73 | bool DumpCoverage = false; 74 | bool DetectLeaks = true; 75 | int PurgeAllocatorIntervalSec = 1; 76 | int TraceMalloc = 0; 77 | bool HandleAbrt = false; 78 | bool HandleAlrm = false; 79 | bool HandleBus = false; 80 | bool HandleFpe = false; 81 | bool HandleIll = false; 82 | bool HandleInt = false; 83 | bool HandleSegv = false; 84 | bool HandleTerm = false; 85 | bool HandleXfsz = false; 86 | bool HandleUsr1 = false; 87 | bool HandleUsr2 = false; 88 | bool HandleWinExcept = false; 89 | }; 90 | 91 | } // namespace fuzzer 92 | 93 | #endif // LLVM_FUZZER_OPTIONS_H 94 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtFunctionsWindows.cpp: -------------------------------------------------------------------------------- 1 | //=== FuzzerExtWindows.cpp - Interface to external functions --------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Implementation of FuzzerExtFunctions for Windows. Uses alternatename when 9 | // compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately 10 | // the method each compiler supports is not supported by the other. 11 | //===----------------------------------------------------------------------===// 12 | #include "FuzzerPlatform.h" 13 | #if LIBFUZZER_WINDOWS 14 | 15 | #include "FuzzerExtFunctions.h" 16 | #include "FuzzerIO.h" 17 | 18 | using namespace fuzzer; 19 | 20 | // Intermediate macro to ensure the parameter is expanded before stringified. 21 | #define STRINGIFY_(A) #A 22 | #define STRINGIFY(A) STRINGIFY_(A) 23 | 24 | #if LIBFUZZER_MSVC 25 | // Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h 26 | #if defined(_M_IX86) || defined(__i386__) 27 | #define WIN_SYM_PREFIX "_" 28 | #else 29 | #define WIN_SYM_PREFIX 30 | #endif 31 | 32 | // Declare external functions as having alternativenames, so that we can 33 | // determine if they are not defined. 34 | #define EXTERNAL_FUNC(Name, Default) \ 35 | __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ 36 | Name) "=" WIN_SYM_PREFIX STRINGIFY(Default))) 37 | #else 38 | // Declare external functions as weak to allow them to default to a specified 39 | // function if not defined explicitly. We must use weak symbols because clang's 40 | // support for alternatename is not 100%, see 41 | // https://bugs.llvm.org/show_bug.cgi?id=40218 for more details. 42 | #define EXTERNAL_FUNC(Name, Default) \ 43 | __attribute__((weak, alias(STRINGIFY(Default)))) 44 | #endif // LIBFUZZER_MSVC 45 | 46 | extern "C" { 47 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 48 | RETURN_TYPE NAME##Def FUNC_SIG { \ 49 | Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ 50 | exit(1); \ 51 | } \ 52 | EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG 53 | 54 | #include "FuzzerExtFunctions.def" 55 | 56 | #undef EXT_FUNC 57 | } 58 | 59 | template 60 | static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { 61 | if (Fun == FunDef) { 62 | if (WarnIfMissing) 63 | Printf("WARNING: Failed to find function \"%s\".\n", FnName); 64 | return nullptr; 65 | } 66 | return Fun; 67 | } 68 | 69 | namespace fuzzer { 70 | 71 | ExternalFunctions::ExternalFunctions() { 72 | #define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ 73 | this->NAME = GetFnPtr(::NAME, ::NAME##Def, #NAME, WARN); 74 | 75 | #include "FuzzerExtFunctions.def" 76 | 77 | #undef EXT_FUNC 78 | } 79 | 80 | } // namespace fuzzer 81 | 82 | #endif // LIBFUZZER_WINDOWS 83 | -------------------------------------------------------------------------------- /agent/user_access.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "driver.h" 14 | #include "conveyor.h" 15 | 16 | extern size_t ignore_addr; 17 | extern size_t ignore_addr_end; 18 | extern size_t min_addr; 19 | extern size_t max_addr; 20 | extern int bloated; 21 | 22 | extern uint64_t *kcov_data; 23 | extern size_t kcov_size; 24 | 25 | static void *user_access_worker(void* opaque){ 26 | int fd = *(int*)opaque; 27 | while(!bloated); 28 | printf(".bloated\n"); 29 | for (;;) { 30 | debug_printf("polling over %d\n", fd); 31 | struct pollfd pollfd; 32 | int nready; 33 | pollfd.fd = fd; 34 | pollfd.events = POLLIN; 35 | nready = poll(&pollfd, 1, -1); 36 | if (nready == -1){ 37 | printf("%s\n","poll\n"); 38 | _Exit(1); 39 | } 40 | 41 | struct cfu_details details = driver_get_cfu_details(); 42 | debug_printf("CFU: %p +%lx\n", details.addr, details.len); 43 | if((size_t)details.addr >= min_addr && (size_t)details.addr + details.len <= max_addr && 44 | !( (size_t)details.addr <= (size_t)kcov_data + kcov_size && (size_t)kcov_data <= (size_t)details.addr + details.len)){ 45 | ignore_addr = (size_t)details.addr; 46 | ignore_addr_end = (size_t)details.addr + details.len; 47 | 48 | 49 | pattern p; 50 | int min; 51 | if(details.len>4096) { 52 | abort_input(); 53 | } 54 | if(details.string) { 55 | p.len = details.len; 56 | min = 4; 57 | } else if(details.len > 200) { 58 | abort_input(); 59 | p.len = 200; 60 | min = 4; 61 | } else { 62 | p.len = details.len; 63 | min = -1; 64 | } 65 | if(!ic_advance_until_token(SEPARATOR, 4)) 66 | ic_insert(SEPARATOR, 4, ic_get_cursor()); 67 | 68 | p.data = ic_ingest_buf(&p.len, SEPARATOR, 4, min, details.string); 69 | p.index = 0; 70 | p.stride = 0; 71 | 72 | if(DEBUG){ 73 | printf(">>> WRITE (%lx) %p %lx \n", kcov_get_current(), details.addr, details.len); 74 | for(int i=0; i 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | // Define FUZZER_INTERFACE_VISIBILITY to set default visibility in a way that 29 | // doesn't break MSVC. 30 | #if defined(_WIN32) 31 | #define FUZZER_INTERFACE_VISIBILITY __declspec(dllexport) 32 | #else 33 | #define FUZZER_INTERFACE_VISIBILITY __attribute__((visibility("default"))) 34 | #endif 35 | 36 | // Mandatory user-provided target function. 37 | // Executes the code under test with [Data, Data+Size) as the input. 38 | // libFuzzer will invoke this function *many* times with different inputs. 39 | // Must return 0. 40 | FUZZER_INTERFACE_VISIBILITY int 41 | LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 42 | 43 | // Optional user-provided initialization function. 44 | // If provided, this function will be called by libFuzzer once at startup. 45 | // It may read and modify argc/argv. 46 | // Must return 0. 47 | FUZZER_INTERFACE_VISIBILITY int LLVMFuzzerInitialize(int *argc, char ***argv); 48 | 49 | // Optional user-provided custom mutator. 50 | // Mutates raw data in [Data, Data+Size) inplace. 51 | // Returns the new size, which is not greater than MaxSize. 52 | // Given the same Seed produces the same mutation. 53 | FUZZER_INTERFACE_VISIBILITY size_t 54 | LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, 55 | unsigned int Seed); 56 | 57 | // Optional user-provided custom cross-over function. 58 | // Combines pieces of Data1 & Data2 together into Out. 59 | // Returns the new size, which is not greater than MaxOutSize. 60 | // Should produce the same mutation given the same Seed. 61 | FUZZER_INTERFACE_VISIBILITY size_t 62 | LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, 63 | const uint8_t *Data2, size_t Size2, uint8_t *Out, 64 | size_t MaxOutSize, unsigned int Seed); 65 | 66 | // Experimental, may go away in future. 67 | // libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator. 68 | // Mutates raw data in [Data, Data+Size) inplace. 69 | // Returns the new size, which is not greater than MaxSize. 70 | FUZZER_INTERFACE_VISIBILITY size_t 71 | LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); 72 | 73 | #undef FUZZER_INTERFACE_VISIBILITY 74 | 75 | #ifdef __cplusplus 76 | } // extern "C" 77 | #endif // __cplusplus 78 | 79 | #endif // LLVM_FUZZER_INTERFACE_H 80 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerExtraCountersWindows.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerExtraCountersWindows.cpp - Extra coverage counters for Win32 -===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Extra coverage counters defined by user code for Windows. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerPlatform.h" 12 | #include 13 | 14 | #if LIBFUZZER_WINDOWS 15 | #include 16 | 17 | namespace fuzzer { 18 | 19 | // 20 | // The __start___libfuzzer_extra_counters variable is align 16, size 16 to 21 | // ensure the padding between it and the next variable in this section (either 22 | // __libfuzzer_extra_counters or __stop___libfuzzer_extra_counters) will be 23 | // located at (__start___libfuzzer_extra_counters + 24 | // sizeof(__start___libfuzzer_extra_counters)). Otherwise, the calculation of 25 | // (stop - (start + sizeof(start))) might be skewed. 26 | // 27 | // The section name, __libfuzzer_extra_countaaa ends with "aaa", so it sorts 28 | // before __libfuzzer_extra_counters alphabetically. We want the start symbol to 29 | // be placed in the section just before the user supplied counters (if present). 30 | // 31 | #pragma section(".data$__libfuzzer_extra_countaaa") 32 | ATTRIBUTE_ALIGNED(16) 33 | __declspec(allocate(".data$__libfuzzer_extra_countaaa")) uint8_t 34 | __start___libfuzzer_extra_counters[16] = {0}; 35 | 36 | // 37 | // Example of what the user-supplied counters should look like. First, the 38 | // pragma to create the section name. It will fall alphabetically between 39 | // ".data$__libfuzzer_extra_countaaa" and ".data$__libfuzzer_extra_countzzz". 40 | // Next, the declspec to allocate the variable inside the specified section. 41 | // Finally, some array, struct, whatever that is used to track the counter data. 42 | // The size of this variable is computed at runtime by finding the difference of 43 | // __stop___libfuzzer_extra_counters and __start___libfuzzer_extra_counters + 44 | // sizeof(__start___libfuzzer_extra_counters). 45 | // 46 | 47 | // 48 | // #pragma section(".data$__libfuzzer_extra_counters") 49 | // __declspec(allocate(".data$__libfuzzer_extra_counters")) 50 | // uint8_t any_name_variable[64 * 1024]; 51 | // 52 | 53 | // 54 | // Here, the section name, __libfuzzer_extra_countzzz ends with "zzz", so it 55 | // sorts after __libfuzzer_extra_counters alphabetically. We want the stop 56 | // symbol to be placed in the section just after the user supplied counters (if 57 | // present). Align to 1 so there isn't any padding placed between this and the 58 | // previous variable. 59 | // 60 | #pragma section(".data$__libfuzzer_extra_countzzz") 61 | ATTRIBUTE_ALIGNED(1) 62 | __declspec(allocate(".data$__libfuzzer_extra_countzzz")) uint8_t 63 | __stop___libfuzzer_extra_counters = 0; 64 | 65 | uint8_t *ExtraCountersBegin() { 66 | return __start___libfuzzer_extra_counters + 67 | sizeof(__start___libfuzzer_extra_counters); 68 | } 69 | 70 | uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } 71 | 72 | ATTRIBUTE_NO_SANITIZE_ALL 73 | void ClearExtraCounters() { 74 | uint8_t *Beg = ExtraCountersBegin(); 75 | SecureZeroMemory(Beg, ExtraCountersEnd() - Beg); 76 | } 77 | 78 | } // namespace fuzzer 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /libfuzzer-ng/dataflow/DataFlowCallbacks.cpp: -------------------------------------------------------------------------------- 1 | /*===- DataFlowCallbacks.cpp - a standalone DataFlow trace -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Instrumentation callbacks for DataFlow.cpp. 9 | // These functions should not be instrumented by DFSan, so we 10 | // keep them in a separate file and compile it w/o DFSan. 11 | //===----------------------------------------------------------------------===*/ 12 | #include "DataFlow.h" 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | static __thread size_t CurrentFunc; 19 | static uint32_t *GuardsBeg, *GuardsEnd; 20 | static inline bool BlockIsEntry(size_t BlockIdx) { 21 | return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY; 22 | } 23 | 24 | extern "C" { 25 | 26 | void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, 27 | uint32_t *stop) { 28 | assert(__dft.NumFuncs == 0 && "This tool does not support DSOs"); 29 | assert(start < stop && "The code is not instrumented for coverage"); 30 | if (start == stop || *start) return; // Initialize only once. 31 | GuardsBeg = start; 32 | GuardsEnd = stop; 33 | } 34 | 35 | void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, 36 | const uintptr_t *pcs_end) { 37 | if (__dft.NumGuards) return; // Initialize only once. 38 | __dft.NumGuards = GuardsEnd - GuardsBeg; 39 | __dft.PCsBeg = pcs_beg; 40 | __dft.PCsEnd = pcs_end; 41 | assert(__dft.NumGuards == (__dft.PCsEnd - __dft.PCsBeg) / 2); 42 | for (size_t i = 0; i < __dft.NumGuards; i++) { 43 | if (BlockIsEntry(i)) { 44 | __dft.NumFuncs++; 45 | GuardsBeg[i] = __dft.NumFuncs; 46 | } 47 | } 48 | __dft.BBExecuted = (bool*)calloc(__dft.NumGuards, sizeof(bool)); 49 | fprintf(stderr, "INFO: %zd instrumented function(s) observed " 50 | "and %zd basic blocks\n", __dft.NumFuncs, __dft.NumGuards); 51 | } 52 | 53 | void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused. 54 | 55 | void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { 56 | size_t GuardIdx = guard - GuardsBeg; 57 | // assert(GuardIdx < __dft.NumGuards); 58 | __dft.BBExecuted[GuardIdx] = true; 59 | if (!*guard) return; // not a function entry. 60 | uint32_t FuncNum = *guard - 1; // Guards start from 1. 61 | // assert(FuncNum < __dft.NumFuncs); 62 | CurrentFunc = FuncNum; 63 | } 64 | 65 | void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, 66 | dfsan_label L1, dfsan_label UnusedL) { 67 | assert(CurrentFunc < __dft.NumFuncs); 68 | __dft.FuncLabels[CurrentFunc] |= L1; 69 | } 70 | 71 | #define HOOK(Name, Type) \ 72 | void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \ 73 | __dft.FuncLabels[CurrentFunc] |= L1 | L2; \ 74 | } 75 | //assert(CurrentFunc < __dft.NumFuncs); 76 | 77 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t) 78 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t) 79 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t) 80 | HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t) 81 | HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t) 82 | HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t) 83 | HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t) 84 | HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t) 85 | 86 | } // extern "C" 87 | -------------------------------------------------------------------------------- /libfuzzer-ng/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(CompilerRTCompile) 2 | 3 | set(LIBFUZZER_UNITTEST_CFLAGS 4 | ${COMPILER_RT_UNITTEST_CFLAGS} 5 | ${COMPILER_RT_GTEST_CFLAGS} 6 | -I${COMPILER_RT_SOURCE_DIR}/lib/fuzzer 7 | -fno-rtti 8 | -O2) 9 | 10 | if (APPLE) 11 | set(FUZZER_SUPPORTED_OS osx) 12 | endif() 13 | 14 | add_custom_target(FuzzerUnitTests) 15 | set_target_properties(FuzzerUnitTests PROPERTIES FOLDER "Compiler-RT Tests") 16 | 17 | add_custom_target(FuzzedDataProviderUnitTests) 18 | set_target_properties(FuzzedDataProviderUnitTests PROPERTIES FOLDER "Compiler-RT Tests") 19 | 20 | set(LIBFUZZER_UNITTEST_LINK_FLAGS ${COMPILER_RT_UNITTEST_LINK_FLAGS}) 21 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS --driver-mode=g++) 22 | 23 | if(WIN32) 24 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -Wl,-defaultlib:libcmt,-defaultlib:oldnames) 25 | else() 26 | if (APPLE) 27 | list(APPEND LIBFUZZER_UNITTEST_CFLAGS -isysroot ${DARWIN_osx_SYSROOT}) 28 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -isysroot ${DARWIN_osx_SYSROOT}) 29 | endif() 30 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lpthread) 31 | endif() 32 | 33 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND 34 | COMPILER_RT_LIBCXX_PATH AND 35 | COMPILER_RT_LIBCXXABI_PATH) 36 | list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++ -fno-exceptions) 37 | list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -nostdlib++ -fno-exceptions) 38 | endif() 39 | 40 | if ("-fvisibility=hidden" IN_LIST LIBFUZZER_CFLAGS) 41 | # Match visibility settings. 42 | list(APPEND LIBFUZZER_UNITTEST_CFLAGS "-fvisibility=hidden") 43 | endif() 44 | 45 | if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) 46 | # libFuzzer unit tests are only run on the host machine. 47 | set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH}) 48 | 49 | set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch}) 50 | if(APPLE) 51 | set(LIBFUZZER_TEST_RUNTIME_OBJECTS 52 | $) 53 | else() 54 | set(LIBFUZZER_TEST_RUNTIME_OBJECTS 55 | $) 56 | endif() 57 | add_library(${LIBFUZZER_TEST_RUNTIME} STATIC 58 | ${LIBFUZZER_TEST_RUNTIME_OBJECTS}) 59 | set_target_properties(${LIBFUZZER_TEST_RUNTIME} PROPERTIES 60 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 61 | FOLDER "Compiler-RT Runtime tests") 62 | 63 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND 64 | COMPILER_RT_LIBCXX_PATH AND 65 | COMPILER_RT_LIBCXXABI_PATH) 66 | file(GLOB libfuzzer_headers ../*.h) 67 | set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}-build ${libfuzzer_headers}) 68 | set(LIBFUZZER_TEST_RUNTIME_CFLAGS -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 69 | set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS ${LIBCXX_${arch}_PREFIX}/lib/libc++.a) 70 | endif() 71 | 72 | set(FuzzerTestObjects) 73 | generate_compiler_rt_tests(FuzzerTestObjects 74 | FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} 75 | SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} 76 | RUNTIME ${LIBFUZZER_TEST_RUNTIME} 77 | DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} 78 | CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} 79 | LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) 80 | set_target_properties(FuzzerUnitTests PROPERTIES 81 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 82 | 83 | set(FuzzedDataProviderTestObjects) 84 | generate_compiler_rt_tests(FuzzedDataProviderTestObjects 85 | FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} 86 | SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} 87 | DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h 88 | CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} 89 | LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) 90 | set_target_properties(FuzzedDataProviderUnitTests PROPERTIES 91 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 92 | endif() 93 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerMerge.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Merging Corpora. 9 | // 10 | // The task: 11 | // Take the existing corpus (possibly empty) and merge new inputs into 12 | // it so that only inputs with new coverage ('features') are added. 13 | // The process should tolerate the crashes, OOMs, leaks, etc. 14 | // 15 | // Algorithm: 16 | // The outer process collects the set of files and writes their names 17 | // into a temporary "control" file, then repeatedly launches the inner 18 | // process until all inputs are processed. 19 | // The outer process does not actually execute the target code. 20 | // 21 | // The inner process reads the control file and sees a) list of all the inputs 22 | // and b) the last processed input. Then it starts processing the inputs one 23 | // by one. Before processing every input it writes one line to control file: 24 | // STARTED INPUT_ID INPUT_SIZE 25 | // After processing an input it writes the following lines: 26 | // FT INPUT_ID Feature1 Feature2 Feature3 ... 27 | // COV INPUT_ID Coverage1 Coverage2 Coverage3 ... 28 | // If a crash happens while processing an input the last line in the control 29 | // file will be "STARTED INPUT_ID" and so the next process will know 30 | // where to resume. 31 | // 32 | // Once all inputs are processed by the inner process(es) the outer process 33 | // reads the control files and does the merge based entirely on the contents 34 | // of control file. 35 | // It uses a single pass greedy algorithm choosing first the smallest inputs 36 | // within the same size the inputs that have more new features. 37 | // 38 | //===----------------------------------------------------------------------===// 39 | 40 | #ifndef LLVM_FUZZER_MERGE_H 41 | #define LLVM_FUZZER_MERGE_H 42 | 43 | #include "FuzzerDefs.h" 44 | #include "FuzzerIO.h" 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | namespace fuzzer { 52 | 53 | struct MergeFileInfo { 54 | std::string Name; 55 | size_t Size = 0; 56 | std::vector Features, Cov; 57 | }; 58 | 59 | struct Merger { 60 | std::vector Files; 61 | size_t NumFilesInFirstCorpus = 0; 62 | size_t FirstNotProcessedFile = 0; 63 | std::string LastFailure; 64 | 65 | bool Parse(std::istream &IS, bool ParseCoverage); 66 | bool Parse(const std::string &Str, bool ParseCoverage); 67 | void ParseOrExit(std::istream &IS, bool ParseCoverage); 68 | size_t Merge(const std::set &InitialFeatures, 69 | std::set *NewFeatures, 70 | const std::set &InitialCov, std::set *NewCov, 71 | std::vector *NewFiles); 72 | size_t SetCoverMerge(const std::set &InitialFeatures, 73 | std::set *NewFeatures, 74 | const std::set &InitialCov, 75 | std::set *NewCov, 76 | std::vector *NewFiles); 77 | size_t ApproximateMemoryConsumption() const; 78 | std::set AllFeatures() const; 79 | }; 80 | 81 | void CrashResistantMerge(const std::vector &Args, 82 | const std::vector &OldCorpus, 83 | const std::vector &NewCorpus, 84 | std::vector *NewFiles, 85 | const std::set &InitialFeatures, 86 | std::set *NewFeatures, 87 | const std::set &InitialCov, 88 | std::set *NewCov, const std::string &CFPath, 89 | bool Verbose, bool IsSetCoverMerge); 90 | 91 | } // namespace fuzzer 92 | 93 | #endif // LLVM_FUZZER_MERGE_H 94 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtil.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Util functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_UTIL_H 12 | #define LLVM_FUZZER_UTIL_H 13 | 14 | #include "FuzzerBuiltins.h" 15 | #include "FuzzerBuiltinsMsvc.h" 16 | #include "FuzzerCommand.h" 17 | #include "FuzzerDefs.h" 18 | 19 | namespace fuzzer { 20 | 21 | void PrintHexArray(const Unit &U, const char *PrintAfter = ""); 22 | 23 | void PrintHexArray(const uint8_t *Data, size_t Size, 24 | const char *PrintAfter = ""); 25 | 26 | void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); 27 | 28 | void PrintASCII(const Unit &U, const char *PrintAfter = ""); 29 | 30 | // Changes U to contain only ASCII (isprint+isspace) characters. 31 | // Returns true iff U has been changed. 32 | bool ToASCII(uint8_t *Data, size_t Size); 33 | 34 | bool IsASCII(const Unit &U); 35 | 36 | bool IsASCII(const uint8_t *Data, size_t Size); 37 | 38 | std::string Base64(const Unit &U); 39 | 40 | void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); 41 | 42 | std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); 43 | 44 | void PrintStackTrace(); 45 | 46 | void PrintMemoryProfile(); 47 | 48 | unsigned NumberOfCpuCores(); 49 | 50 | // Platform specific functions. 51 | void SetSignalHandler(const FuzzingOptions& Options); 52 | 53 | void SleepSeconds(int Seconds); 54 | 55 | unsigned long GetPid(); 56 | 57 | size_t GetPeakRSSMb(); 58 | 59 | int ExecuteCommand(const Command &Cmd); 60 | bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput); 61 | 62 | // Fuchsia does not have popen/pclose. 63 | FILE *OpenProcessPipe(const char *Command, const char *Mode); 64 | int CloseProcessPipe(FILE *F); 65 | 66 | const void *SearchMemory(const void *haystack, size_t haystacklen, 67 | const void *needle, size_t needlelen); 68 | 69 | std::string CloneArgsWithoutX(const std::vector &Args, 70 | const char *X1, const char *X2); 71 | 72 | inline std::string CloneArgsWithoutX(const std::vector &Args, 73 | const char *X) { 74 | return CloneArgsWithoutX(Args, X, X); 75 | } 76 | 77 | inline std::pair SplitBefore(std::string X, 78 | std::string S) { 79 | auto Pos = S.find(X); 80 | if (Pos == std::string::npos) 81 | return std::make_pair(S, ""); 82 | return std::make_pair(S.substr(0, Pos), S.substr(Pos)); 83 | } 84 | 85 | void DiscardOutput(int Fd); 86 | 87 | std::string DisassembleCmd(const std::string &FileName); 88 | 89 | std::string SearchRegexCmd(const std::string &Regex); 90 | 91 | uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial = 0); 92 | 93 | inline size_t Log(size_t X) { 94 | return static_cast((sizeof(unsigned long long) * 8) - Clzll(X) - 1); 95 | } 96 | 97 | inline size_t PageSize() { return 4096; } 98 | inline uint8_t *RoundUpByPage(uint8_t *P) { 99 | uintptr_t X = reinterpret_cast(P); 100 | size_t Mask = PageSize() - 1; 101 | X = (X + Mask) & ~Mask; 102 | return reinterpret_cast(X); 103 | } 104 | inline uint8_t *RoundDownByPage(uint8_t *P) { 105 | uintptr_t X = reinterpret_cast(P); 106 | size_t Mask = PageSize() - 1; 107 | X = X & ~Mask; 108 | return reinterpret_cast(X); 109 | } 110 | 111 | #if __BYTE_ORDER == __LITTLE_ENDIAN 112 | template T HostToLE(T X) { return X; } 113 | #else 114 | template T HostToLE(T X) { return Bswap(X); } 115 | #endif 116 | 117 | } // namespace fuzzer 118 | 119 | #endif // LLVM_FUZZER_UTIL_H 120 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerDictionary.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::Dictionary 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_DICTIONARY_H 12 | #define LLVM_FUZZER_DICTIONARY_H 13 | 14 | #include "FuzzerDefs.h" 15 | #include "FuzzerIO.h" 16 | #include "FuzzerUtil.h" 17 | #include 18 | #include 19 | 20 | namespace fuzzer { 21 | // A simple POD sized array of bytes. 22 | template class FixedWord { 23 | public: 24 | static const size_t kMaxSize = kMaxSizeT; 25 | FixedWord() {} 26 | FixedWord(const uint8_t *B, size_t S) { Set(B, S); } 27 | 28 | void Set(const uint8_t *B, size_t S) { 29 | static_assert(kMaxSizeT <= std::numeric_limits::max(), 30 | "FixedWord::kMaxSizeT cannot fit in a uint8_t."); 31 | assert(S <= kMaxSize); 32 | memcpy(Data, B, S); 33 | Size = static_cast(S); 34 | } 35 | 36 | bool operator==(const FixedWord &w) const { 37 | return Size == w.Size && 0 == memcmp(Data, w.Data, Size); 38 | } 39 | 40 | static size_t GetMaxSize() { return kMaxSize; } 41 | const uint8_t *data() const { return Data; } 42 | uint8_t size() const { return Size; } 43 | 44 | private: 45 | uint8_t Size = 0; 46 | uint8_t Data[kMaxSize]; 47 | }; 48 | 49 | typedef FixedWord<64> Word; 50 | 51 | class DictionaryEntry { 52 | public: 53 | DictionaryEntry() {} 54 | DictionaryEntry(Word W) : W(W) {} 55 | DictionaryEntry(Word W, size_t PositionHint) 56 | : W(W), PositionHint(PositionHint) {} 57 | const Word &GetW() const { return W; } 58 | 59 | bool HasPositionHint() const { 60 | return PositionHint != std::numeric_limits::max(); 61 | } 62 | size_t GetPositionHint() const { 63 | assert(HasPositionHint()); 64 | return PositionHint; 65 | } 66 | void IncUseCount() { UseCount++; } 67 | void IncSuccessCount() { SuccessCount++; } 68 | size_t GetUseCount() const { return UseCount; } 69 | size_t GetSuccessCount() const {return SuccessCount; } 70 | 71 | void Print(const char *PrintAfter = "\n") { 72 | PrintASCII(W.data(), W.size()); 73 | if (HasPositionHint()) 74 | Printf("@%zd", GetPositionHint()); 75 | Printf("%s", PrintAfter); 76 | } 77 | 78 | private: 79 | Word W; 80 | size_t PositionHint = std::numeric_limits::max(); 81 | size_t UseCount = 0; 82 | size_t SuccessCount = 0; 83 | }; 84 | 85 | class Dictionary { 86 | public: 87 | static const size_t kMaxDictSize = 1 << 14; 88 | 89 | bool ContainsWord(const Word &W) const { 90 | return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { 91 | return DE.GetW() == W; 92 | }); 93 | } 94 | const DictionaryEntry *begin() const { return &DE[0]; } 95 | const DictionaryEntry *end() const { return begin() + Size; } 96 | DictionaryEntry & operator[] (size_t Idx) { 97 | assert(Idx < Size); 98 | return DE[Idx]; 99 | } 100 | void push_back(DictionaryEntry DE) { 101 | if (Size < kMaxDictSize) 102 | this->DE[Size++] = DE; 103 | } 104 | void clear() { Size = 0; } 105 | bool empty() const { return Size == 0; } 106 | size_t size() const { return Size; } 107 | 108 | private: 109 | DictionaryEntry DE[kMaxDictSize]; 110 | size_t Size = 0; 111 | }; 112 | 113 | // Parses one dictionary entry. 114 | // If successful, writes the entry to Unit and returns true, 115 | // otherwise returns false. 116 | bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); 117 | // Parses the dictionary file, fills Units, returns true iff all lines 118 | // were parsed successfully. 119 | bool ParseDictionaryFile(const std::string &Text, std::vector *Units); 120 | 121 | } // namespace fuzzer 122 | 123 | #endif // LLVM_FUZZER_DICTIONARY_H 124 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerIO.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO interface. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_IO_H 12 | #define LLVM_FUZZER_IO_H 13 | 14 | #include "FuzzerDefs.h" 15 | 16 | namespace fuzzer { 17 | 18 | long GetEpoch(const std::string &Path); 19 | 20 | Unit FileToVector(const std::string &Path, size_t MaxSize = 0, 21 | bool ExitOnError = true); 22 | 23 | std::string FileToString(const std::string &Path); 24 | 25 | void CopyFileToErr(const std::string &Path); 26 | 27 | void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path); 28 | // Write Data.c_str() to the file without terminating null character. 29 | void WriteToFile(const std::string &Data, const std::string &Path); 30 | void WriteToFile(const Unit &U, const std::string &Path); 31 | 32 | void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path); 33 | void AppendToFile(const std::string &Data, const std::string &Path); 34 | 35 | void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, 36 | size_t MaxSize, bool ExitOnError, 37 | std::vector *VPaths = 0); 38 | 39 | // Returns "Dir/FileName" or equivalent for the current OS. 40 | std::string DirPlusFile(const std::string &DirPath, 41 | const std::string &FileName); 42 | 43 | // Returns the name of the dir, similar to the 'dirname' utility. 44 | std::string DirName(const std::string &FileName); 45 | 46 | // Returns path to a TmpDir. 47 | std::string TmpDir(); 48 | 49 | std::string TempPath(const char *Prefix, const char *Extension); 50 | 51 | bool IsInterestingCoverageFile(const std::string &FileName); 52 | 53 | void DupAndCloseStderr(); 54 | 55 | void CloseStdout(); 56 | 57 | // For testing. 58 | FILE *GetOutputFile(); 59 | void SetOutputFile(FILE *NewOutputFile); 60 | 61 | void Printf(const char *Fmt, ...); 62 | void VPrintf(bool Verbose, const char *Fmt, ...); 63 | 64 | // Print using raw syscalls, useful when printing at early init stages. 65 | void RawPrint(const char *Str); 66 | 67 | // Platform specific functions: 68 | bool IsFile(const std::string &Path); 69 | bool IsDirectory(const std::string &Path); 70 | size_t FileSize(const std::string &Path); 71 | 72 | void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 73 | std::vector *V, bool TopDir); 74 | 75 | bool MkDirRecursive(const std::string &Dir); 76 | void RmDirRecursive(const std::string &Dir); 77 | 78 | // Iterate files and dirs inside Dir, recursively. 79 | // Call DirPreCallback/DirPostCallback on dirs before/after 80 | // calling FileCallback on files. 81 | void IterateDirRecursive(const std::string &Dir, 82 | void (*DirPreCallback)(const std::string &Dir), 83 | void (*DirPostCallback)(const std::string &Dir), 84 | void (*FileCallback)(const std::string &Dir)); 85 | 86 | struct SizedFile { 87 | std::string File; 88 | size_t Size; 89 | bool operator<(const SizedFile &B) const { return Size < B.Size; } 90 | }; 91 | 92 | void GetSizedFilesFromDir(const std::string &Dir, std::vector *V); 93 | 94 | char GetSeparator(); 95 | bool IsSeparator(char C); 96 | // Similar to the basename utility: returns the file name w/o the dir prefix. 97 | std::string Basename(const std::string &Path); 98 | 99 | FILE* OpenFile(int Fd, const char *Mode); 100 | 101 | int CloseFile(int Fd); 102 | 103 | int DuplicateFile(int Fd); 104 | 105 | void RemoveFile(const std::string &Path); 106 | void RenameFile(const std::string &OldPath, const std::string &NewPath); 107 | 108 | intptr_t GetHandleFromFd(int fd); 109 | 110 | void MkDir(const std::string &Path); 111 | void RmDir(const std::string &Path); 112 | 113 | const std::string &getDevNull(); 114 | 115 | } // namespace fuzzer 116 | 117 | #endif // LLVM_FUZZER_IO_H 118 | -------------------------------------------------------------------------------- /agent/kcov.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "kcov.h" 16 | #include "fuzz.h" 17 | #include "device.h" 18 | 19 | 20 | uint64_t *kcov_data; 21 | size_t kcov_size = KCOV_COVER_SIZE * sizeof(kcov_data[0]); 22 | uint64_t *remote_kcov_data; 23 | static int fd; 24 | int remote_fd; 25 | int mode = KCOV_TRACE_CMP; 26 | 27 | void set_mode(int trace_pc){ 28 | if(trace_pc){ 29 | mode = KCOV_TRACE_PC; 30 | } else { 31 | mode = KCOV_TRACE_CMP; 32 | } 33 | 34 | } 35 | 36 | void fail(const char* msg, ...) 37 | { 38 | int e = errno; 39 | va_list args; 40 | va_start(args, msg); 41 | vfprintf(stderr, msg, args); 42 | va_end(args); 43 | fprintf(stderr, " (errno %d)\n", e); 44 | exit(1); 45 | } 46 | 47 | void kcov_trace_pc(void){ 48 | if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_PC)) 49 | fail("cover enable write trace failed"); 50 | mode = KCOV_TRACE_PC; 51 | } 52 | 53 | void kcov_trace_cmp(void){ 54 | if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_CMP)){ 55 | fail("cover enable write trace failed"); 56 | } 57 | mode = KCOV_TRACE_CMP; 58 | } 59 | 60 | 61 | int open_kcov_fd(void** data){ 62 | int kcov_fd = open("/sys/kernel/debug/kcov", O_RDWR); 63 | if (kcov_fd== -1) 64 | fail("open of /sys/kernel/debug/kcov failed"); 65 | if (ioctl(kcov_fd, KCOV_INIT_TRACE64, KCOV_COVER_SIZE)) 66 | fail("cover init trace write failed"); 67 | *data = (uint64_t*)mmap(NULL, kcov_size, 68 | PROT_READ | PROT_WRITE, MAP_SHARED, kcov_fd, 0); 69 | 70 | if (*data == MAP_FAILED) 71 | fail("cover mmap failed"); 72 | return kcov_fd; 73 | } 74 | 75 | static uint64_t remote_handle; 76 | void* kcov_remote(void* a){ 77 | int i; 78 | struct kcov_remote_arg arg = {}; 79 | remote_fd = open_kcov_fd((void**)&remote_kcov_data); 80 | 81 | memset(remote_kcov_data, 0, KCOV_COVER_SIZE * sizeof(kcov_data[0])); 82 | for(i=0; i < KCOV_COVER_SIZE; i+=0x1000/sizeof(remote_kcov_data[0])) 83 | outl(virt_to_phys(&remote_kcov_data[i]) ,0x922 + FUZZ_DEVICE_ADD_REMOTE_COV_ARRAY); 84 | 85 | arg.trace_mode = mode; 86 | arg.area_size = KCOV_COVER_SIZE; 87 | arg.num_handles = 0; 88 | arg.common_handle = kcov_remote_handle(KCOV_SUBSYSTEM_COMMON, 89 | KCOV_COMMON_ID); 90 | if (ioctl(remote_fd, KCOV_REMOTE_ENABLE, &arg)){ 91 | perror("ioctl"); 92 | fail("ioctl"); 93 | } 94 | printf("Pausing Remote Thread...\n"); 95 | while(1) 96 | pause(); 97 | return NULL; 98 | } 99 | 100 | uint64_t kcov_get_current(void) { 101 | int n = __atomic_load_n(&kcov_data[0], __ATOMIC_RELAXED) -1; 102 | uint64_t pc; 103 | if (n<0) 104 | return -1; 105 | if(mode == KCOV_TRACE_PC) { 106 | pc = __atomic_load_n(&kcov_data[1+n], __ATOMIC_RELAXED); 107 | } else { 108 | pc = __atomic_load_n(&kcov_data[1+(n*4)+3], __ATOMIC_RELAXED); 109 | } 110 | return pc; 111 | } 112 | 113 | void kcov_print_data(void){ 114 | printf("KCOV Data:\n"); 115 | for(int i=0; i<4096; i++){ 116 | printf("%02x", ((uint8_t*)kcov_data)[i]); 117 | if(i%20 ==19) 118 | printf("\n"); 119 | } 120 | } 121 | 122 | void kcov_init(void){ 123 | int i; 124 | pthread_t kcov_remote_thread; 125 | 126 | pthread_create(&kcov_remote_thread, NULL, kcov_remote, NULL); 127 | fd = open_kcov_fd((void**)&kcov_data); 128 | memset(kcov_data, 0, KCOV_COVER_SIZE * sizeof(kcov_data[0])); 129 | for(i=0; i < KCOV_COVER_SIZE; i+=0x1000/sizeof(kcov_data[0])) 130 | outl(virt_to_phys(&kcov_data[i]) ,0x922 + FUZZ_DEVICE_ADD_CMP_ARRAY); 131 | } 132 | 133 | int kcov_dead(void) 134 | { 135 | return !(fcntl(fd, F_GETFD) != -1 || errno != EBADF); 136 | } 137 | 138 | static void kcov_reset_bitmap(uint64_t* data){ 139 | __atomic_store_n(&data[0], 0 , __ATOMIC_RELAXED); 140 | } 141 | 142 | void kcov_reset_coverage(void){ 143 | if(kcov_data) 144 | kcov_reset_bitmap(kcov_data); 145 | if(remote_kcov_data) 146 | kcov_reset_bitmap(remote_kcov_data); 147 | } 148 | 149 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerDataFlowTrace.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // fuzzer::DataFlowTrace; reads and handles a data-flow trace. 9 | // 10 | // A data flow trace is generated by e.g. dataflow/DataFlow.cpp 11 | // and is stored on disk in a separate directory. 12 | // 13 | // The trace dir contains a file 'functions.txt' which lists function names, 14 | // oner per line, e.g. 15 | // ==> functions.txt <== 16 | // Func2 17 | // LLVMFuzzerTestOneInput 18 | // Func1 19 | // 20 | // All other files in the dir are the traces, see dataflow/DataFlow.cpp. 21 | // The name of the file is sha1 of the input used to generate the trace. 22 | // 23 | // Current status: 24 | // the data is parsed and the summary is printed, but the data is not yet 25 | // used in any other way. 26 | //===----------------------------------------------------------------------===// 27 | 28 | #ifndef LLVM_FUZZER_DATA_FLOW_TRACE 29 | #define LLVM_FUZZER_DATA_FLOW_TRACE 30 | 31 | #include "FuzzerDefs.h" 32 | #include "FuzzerIO.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | namespace fuzzer { 40 | 41 | int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, 42 | const std::vector &CorporaFiles); 43 | 44 | class BlockCoverage { 45 | public: 46 | // These functions guarantee no CoverageVector is longer than UINT32_MAX. 47 | bool AppendCoverage(std::istream &IN); 48 | bool AppendCoverage(const std::string &S); 49 | 50 | size_t NumCoveredFunctions() const { return Functions.size(); } 51 | 52 | uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) { 53 | auto It = Functions.find(FunctionId); 54 | if (It == Functions.end()) 55 | return 0; 56 | const auto &Counters = It->second; 57 | if (BasicBlockId < Counters.size()) 58 | return Counters[BasicBlockId]; 59 | return 0; 60 | } 61 | 62 | uint32_t GetNumberOfBlocks(size_t FunctionId) { 63 | auto It = Functions.find(FunctionId); 64 | if (It == Functions.end()) return 0; 65 | const auto &Counters = It->second; 66 | return static_cast(Counters.size()); 67 | } 68 | 69 | uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) { 70 | auto It = Functions.find(FunctionId); 71 | if (It == Functions.end()) return 0; 72 | const auto &Counters = It->second; 73 | uint32_t Result = 0; 74 | for (auto Cnt: Counters) 75 | if (Cnt) 76 | Result++; 77 | return Result; 78 | } 79 | 80 | std::vector FunctionWeights(size_t NumFunctions) const; 81 | void clear() { Functions.clear(); } 82 | 83 | private: 84 | typedef std::vector CoverageVector; 85 | 86 | uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { 87 | uint32_t Res = 0; 88 | for (auto Cnt : Counters) 89 | if (Cnt) 90 | Res++; 91 | return Res; 92 | } 93 | 94 | uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const { 95 | return static_cast(Counters.size()) - 96 | NumberOfCoveredBlocks(Counters); 97 | } 98 | 99 | uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const { 100 | assert(!Counters.empty()); 101 | uint32_t Res = Counters[0]; 102 | for (auto Cnt : Counters) 103 | if (Cnt) 104 | Res = Min(Res, Cnt); 105 | assert(Res); 106 | return Res; 107 | } 108 | 109 | // Function ID => vector of counters. 110 | // Each counter represents how many input files trigger the given basic block. 111 | std::unordered_map Functions; 112 | // Functions that have DFT entry. 113 | std::unordered_set FunctionsWithDFT; 114 | }; 115 | 116 | class DataFlowTrace { 117 | public: 118 | void ReadCoverage(const std::string &DirPath); 119 | bool Init(const std::string &DirPath, std::string *FocusFunction, 120 | std::vector &CorporaFiles, Random &Rand); 121 | void Clear() { Traces.clear(); } 122 | const std::vector *Get(const std::string &InputSha1) const { 123 | auto It = Traces.find(InputSha1); 124 | if (It != Traces.end()) 125 | return &It->second; 126 | return nullptr; 127 | } 128 | 129 | private: 130 | // Input's sha1 => DFT for the FocusFunction. 131 | std::unordered_map> Traces; 132 | BlockCoverage Coverage; 133 | std::unordered_set CorporaHashes; 134 | }; 135 | } // namespace fuzzer 136 | 137 | #endif // LLVM_FUZZER_DATA_FLOW_TRACE 138 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerPlatform.h: -------------------------------------------------------------------------------- 1 | //===-- FuzzerPlatform.h --------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Common platform macros. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_PLATFORM_H 12 | #define LLVM_FUZZER_PLATFORM_H 13 | 14 | // Platform detection. 15 | #ifdef __linux__ 16 | #define LIBFUZZER_APPLE 0 17 | #define LIBFUZZER_FUCHSIA 0 18 | #define LIBFUZZER_LINUX 1 19 | #define LIBFUZZER_NETBSD 0 20 | #define LIBFUZZER_FREEBSD 0 21 | #define LIBFUZZER_WINDOWS 0 22 | #define LIBFUZZER_EMSCRIPTEN 0 23 | #elif __APPLE__ 24 | #define LIBFUZZER_APPLE 1 25 | #define LIBFUZZER_FUCHSIA 0 26 | #define LIBFUZZER_LINUX 0 27 | #define LIBFUZZER_NETBSD 0 28 | #define LIBFUZZER_FREEBSD 0 29 | #define LIBFUZZER_WINDOWS 0 30 | #define LIBFUZZER_EMSCRIPTEN 0 31 | #elif __NetBSD__ 32 | #define LIBFUZZER_APPLE 0 33 | #define LIBFUZZER_FUCHSIA 0 34 | #define LIBFUZZER_LINUX 0 35 | #define LIBFUZZER_NETBSD 1 36 | #define LIBFUZZER_FREEBSD 0 37 | #define LIBFUZZER_WINDOWS 0 38 | #define LIBFUZZER_EMSCRIPTEN 0 39 | #elif __FreeBSD__ 40 | #define LIBFUZZER_APPLE 0 41 | #define LIBFUZZER_FUCHSIA 0 42 | #define LIBFUZZER_LINUX 0 43 | #define LIBFUZZER_NETBSD 0 44 | #define LIBFUZZER_FREEBSD 1 45 | #define LIBFUZZER_WINDOWS 0 46 | #define LIBFUZZER_EMSCRIPTEN 0 47 | #elif _WIN32 48 | #define LIBFUZZER_APPLE 0 49 | #define LIBFUZZER_FUCHSIA 0 50 | #define LIBFUZZER_LINUX 0 51 | #define LIBFUZZER_NETBSD 0 52 | #define LIBFUZZER_FREEBSD 0 53 | #define LIBFUZZER_WINDOWS 1 54 | #define LIBFUZZER_EMSCRIPTEN 0 55 | #elif __Fuchsia__ 56 | #define LIBFUZZER_APPLE 0 57 | #define LIBFUZZER_FUCHSIA 1 58 | #define LIBFUZZER_LINUX 0 59 | #define LIBFUZZER_NETBSD 0 60 | #define LIBFUZZER_FREEBSD 0 61 | #define LIBFUZZER_WINDOWS 0 62 | #define LIBFUZZER_EMSCRIPTEN 0 63 | #elif __EMSCRIPTEN__ 64 | #define LIBFUZZER_APPLE 0 65 | #define LIBFUZZER_FUCHSIA 0 66 | #define LIBFUZZER_LINUX 0 67 | #define LIBFUZZER_NETBSD 0 68 | #define LIBFUZZER_FREEBSD 0 69 | #define LIBFUZZER_WINDOWS 0 70 | #define LIBFUZZER_EMSCRIPTEN 1 71 | #else 72 | #error "Support for your platform has not been implemented" 73 | #endif 74 | 75 | #if defined(_MSC_VER) && !defined(__clang__) 76 | // MSVC compiler is being used. 77 | #define LIBFUZZER_MSVC 1 78 | #else 79 | #define LIBFUZZER_MSVC 0 80 | #endif 81 | 82 | #ifndef __has_attribute 83 | #define __has_attribute(x) 0 84 | #endif 85 | 86 | #define LIBFUZZER_POSIX \ 87 | (LIBFUZZER_APPLE || LIBFUZZER_LINUX || LIBFUZZER_NETBSD || \ 88 | LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN) 89 | 90 | #ifdef __x86_64 91 | #if __has_attribute(target) 92 | #define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) 93 | #else 94 | #define ATTRIBUTE_TARGET_POPCNT 95 | #endif 96 | #else 97 | #define ATTRIBUTE_TARGET_POPCNT 98 | #endif 99 | 100 | #ifdef __clang__ // avoid gcc warning. 101 | #if __has_attribute(no_sanitize) 102 | #define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) 103 | #else 104 | #define ATTRIBUTE_NO_SANITIZE_MEMORY 105 | #endif 106 | #define ALWAYS_INLINE __attribute__((always_inline)) 107 | #else 108 | #define ATTRIBUTE_NO_SANITIZE_MEMORY 109 | #define ALWAYS_INLINE 110 | #endif // __clang__ 111 | 112 | #if LIBFUZZER_WINDOWS 113 | #define ATTRIBUTE_NO_SANITIZE_ADDRESS 114 | #else 115 | #define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) 116 | #endif 117 | 118 | #if LIBFUZZER_WINDOWS 119 | #define ATTRIBUTE_ALIGNED(X) __declspec(align(X)) 120 | #define ATTRIBUTE_INTERFACE __declspec(dllexport) 121 | // This is used for __sancov_lowest_stack which is needed for 122 | // -fsanitize-coverage=stack-depth. That feature is not yet available on 123 | // Windows, so make the symbol static to avoid linking errors. 124 | #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC static 125 | #define ATTRIBUTE_NOINLINE __declspec(noinline) 126 | #else 127 | #define ATTRIBUTE_ALIGNED(X) __attribute__((aligned(X))) 128 | #define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) 129 | #define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ 130 | ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local 131 | 132 | #define ATTRIBUTE_NOINLINE __attribute__((noinline)) 133 | #endif 134 | 135 | #if defined(__has_feature) 136 | #if __has_feature(address_sanitizer) 137 | #define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_ADDRESS 138 | #elif __has_feature(memory_sanitizer) 139 | #define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_MEMORY 140 | #else 141 | #define ATTRIBUTE_NO_SANITIZE_ALL 142 | #endif 143 | #else 144 | #define ATTRIBUTE_NO_SANITIZE_ALL 145 | #endif 146 | 147 | #endif // LLVM_FUZZER_PLATFORM_H 148 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerIOPosix.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO functions implementation using Posix API. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerPlatform.h" 11 | #if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA 12 | 13 | #include "FuzzerExtFunctions.h" 14 | #include "FuzzerIO.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fuzzer { 26 | 27 | bool IsFile(const std::string &Path) { 28 | struct stat St; 29 | if (stat(Path.c_str(), &St)) 30 | return false; 31 | return S_ISREG(St.st_mode); 32 | } 33 | 34 | bool IsDirectory(const std::string &Path) { 35 | struct stat St; 36 | if (stat(Path.c_str(), &St)) 37 | return false; 38 | return S_ISDIR(St.st_mode); 39 | } 40 | 41 | size_t FileSize(const std::string &Path) { 42 | struct stat St; 43 | if (stat(Path.c_str(), &St)) 44 | return 0; 45 | return St.st_size; 46 | } 47 | 48 | std::string Basename(const std::string &Path) { 49 | size_t Pos = Path.rfind(GetSeparator()); 50 | if (Pos == std::string::npos) return Path; 51 | assert(Pos < Path.size()); 52 | return Path.substr(Pos + 1); 53 | } 54 | 55 | void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, 56 | std::vector *V, bool TopDir) { 57 | auto E = GetEpoch(Dir); 58 | if (Epoch) 59 | if (E && *Epoch >= E) return; 60 | 61 | DIR *D = opendir(Dir.c_str()); 62 | if (!D) { 63 | Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); 64 | exit(1); 65 | } 66 | while (auto E = readdir(D)) { 67 | std::string Path = DirPlusFile(Dir, E->d_name); 68 | if (E->d_type == DT_REG || E->d_type == DT_LNK || 69 | (E->d_type == DT_UNKNOWN && IsFile(Path))) 70 | V->push_back(Path); 71 | else if ((E->d_type == DT_DIR || 72 | (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 73 | *E->d_name != '.') 74 | ListFilesInDirRecursive(Path, Epoch, V, false); 75 | } 76 | closedir(D); 77 | if (Epoch && TopDir) 78 | *Epoch = E; 79 | } 80 | 81 | void IterateDirRecursive(const std::string &Dir, 82 | void (*DirPreCallback)(const std::string &Dir), 83 | void (*DirPostCallback)(const std::string &Dir), 84 | void (*FileCallback)(const std::string &Dir)) { 85 | DirPreCallback(Dir); 86 | DIR *D = opendir(Dir.c_str()); 87 | if (!D) return; 88 | while (auto E = readdir(D)) { 89 | std::string Path = DirPlusFile(Dir, E->d_name); 90 | if (E->d_type == DT_REG || E->d_type == DT_LNK || 91 | (E->d_type == DT_UNKNOWN && IsFile(Path))) 92 | FileCallback(Path); 93 | else if ((E->d_type == DT_DIR || 94 | (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && 95 | *E->d_name != '.') 96 | IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); 97 | } 98 | closedir(D); 99 | DirPostCallback(Dir); 100 | } 101 | 102 | char GetSeparator() { 103 | return '/'; 104 | } 105 | 106 | bool IsSeparator(char C) { 107 | return C == '/'; 108 | } 109 | 110 | FILE* OpenFile(int Fd, const char* Mode) { 111 | return fdopen(Fd, Mode); 112 | } 113 | 114 | int CloseFile(int fd) { 115 | return close(fd); 116 | } 117 | 118 | int DuplicateFile(int Fd) { 119 | return dup(Fd); 120 | } 121 | 122 | void RemoveFile(const std::string &Path) { 123 | unlink(Path.c_str()); 124 | } 125 | 126 | void RenameFile(const std::string &OldPath, const std::string &NewPath) { 127 | rename(OldPath.c_str(), NewPath.c_str()); 128 | } 129 | 130 | intptr_t GetHandleFromFd(int fd) { 131 | return static_cast(fd); 132 | } 133 | 134 | std::string DirName(const std::string &FileName) { 135 | char *Tmp = new char[FileName.size() + 1]; 136 | memcpy(Tmp, FileName.c_str(), FileName.size() + 1); 137 | std::string Res = dirname(Tmp); 138 | delete [] Tmp; 139 | return Res; 140 | } 141 | 142 | std::string TmpDir() { 143 | if (auto Env = getenv("TMPDIR")) 144 | return Env; 145 | return "/tmp"; 146 | } 147 | 148 | bool IsInterestingCoverageFile(const std::string &FileName) { 149 | if (FileName.find("compiler-rt/lib/") != std::string::npos) 150 | return false; // sanitizer internal. 151 | if (FileName.find("/usr/lib/") != std::string::npos) 152 | return false; 153 | if (FileName.find("/usr/include/") != std::string::npos) 154 | return false; 155 | if (FileName == "") 156 | return false; 157 | return true; 158 | } 159 | 160 | void RawPrint(const char *Str) { 161 | (void)write(2, Str, strlen(Str)); 162 | } 163 | 164 | void MkDir(const std::string &Path) { 165 | mkdir(Path.c_str(), 0700); 166 | } 167 | 168 | void RmDir(const std::string &Path) { 169 | rmdir(Path.c_str()); 170 | } 171 | 172 | const std::string &getDevNull() { 173 | static const std::string devNull = "/dev/null"; 174 | return devNull; 175 | } 176 | 177 | } // namespace fuzzer 178 | 179 | #endif // LIBFUZZER_POSIX 180 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtilPosix.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils implementation using Posix API. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerPlatform.h" 11 | #if LIBFUZZER_POSIX 12 | #include "FuzzerIO.h" 13 | #include "FuzzerInternal.h" 14 | #include "FuzzerTracePC.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace fuzzer { 31 | 32 | static void AlarmHandler(int, siginfo_t *, void *) { 33 | Fuzzer::StaticAlarmCallback(); 34 | } 35 | 36 | static void (*upstream_segv_handler)(int, siginfo_t *, void *); 37 | 38 | static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { 39 | assert(si->si_signo == SIGSEGV); 40 | if (upstream_segv_handler) 41 | return upstream_segv_handler(sig, si, ucontext); 42 | Fuzzer::StaticCrashSignalCallback(); 43 | } 44 | 45 | static void CrashHandler(int, siginfo_t *, void *) { 46 | Fuzzer::StaticCrashSignalCallback(); 47 | } 48 | 49 | static void InterruptHandler(int, siginfo_t *, void *) { 50 | Fuzzer::StaticInterruptCallback(); 51 | } 52 | 53 | static void GracefulExitHandler(int, siginfo_t *, void *) { 54 | Fuzzer::StaticGracefulExitCallback(); 55 | } 56 | 57 | static void FileSizeExceedHandler(int, siginfo_t *, void *) { 58 | Fuzzer::StaticFileSizeExceedCallback(); 59 | } 60 | 61 | static void SetSigaction(int signum, 62 | void (*callback)(int, siginfo_t *, void *)) { 63 | struct sigaction sigact = {}; 64 | if (sigaction(signum, nullptr, &sigact)) { 65 | Printf("libFuzzer: sigaction failed with %d\n", errno); 66 | exit(1); 67 | } 68 | if (sigact.sa_flags & SA_SIGINFO) { 69 | if (sigact.sa_sigaction) { 70 | if (signum != SIGSEGV) 71 | return; 72 | upstream_segv_handler = sigact.sa_sigaction; 73 | } 74 | } else { 75 | if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && 76 | sigact.sa_handler != SIG_ERR) 77 | return; 78 | } 79 | 80 | struct sigaction new_sigact = {}; 81 | // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a 82 | // dedicated stack) in order to be able to detect stack overflows; keep the 83 | // flag if it's set. 84 | new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK); 85 | new_sigact.sa_sigaction = callback; 86 | if (sigaction(signum, &new_sigact, nullptr)) { 87 | Printf("libFuzzer: sigaction failed with %d\n", errno); 88 | exit(1); 89 | } 90 | } 91 | 92 | // Return true on success, false otherwise. 93 | bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { 94 | FILE *Pipe = popen(Cmd.toString().c_str(), "r"); 95 | if (!Pipe) 96 | return false; 97 | 98 | if (CmdOutput) { 99 | char TmpBuffer[128]; 100 | while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) 101 | CmdOutput->append(TmpBuffer); 102 | } 103 | return pclose(Pipe) == 0; 104 | } 105 | 106 | void SetTimer(int Seconds) { 107 | struct itimerval T { 108 | {Seconds, 0}, { Seconds, 0 } 109 | }; 110 | if (setitimer(ITIMER_REAL, &T, nullptr)) { 111 | Printf("libFuzzer: setitimer failed with %d\n", errno); 112 | exit(1); 113 | } 114 | SetSigaction(SIGALRM, AlarmHandler); 115 | } 116 | 117 | void SetSignalHandler(const FuzzingOptions& Options) { 118 | // setitimer is not implemented in emscripten. 119 | if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) 120 | SetTimer(Options.UnitTimeoutSec / 2 + 1); 121 | if (Options.HandleInt) 122 | SetSigaction(SIGINT, InterruptHandler); 123 | if (Options.HandleTerm) 124 | SetSigaction(SIGTERM, InterruptHandler); 125 | if (Options.HandleSegv) 126 | SetSigaction(SIGSEGV, SegvHandler); 127 | if (Options.HandleBus) 128 | SetSigaction(SIGBUS, CrashHandler); 129 | if (Options.HandleAbrt) 130 | SetSigaction(SIGABRT, CrashHandler); 131 | if (Options.HandleIll) 132 | SetSigaction(SIGILL, CrashHandler); 133 | if (Options.HandleFpe) 134 | SetSigaction(SIGFPE, CrashHandler); 135 | if (Options.HandleXfsz) 136 | SetSigaction(SIGXFSZ, FileSizeExceedHandler); 137 | if (Options.HandleUsr1) 138 | SetSigaction(SIGUSR1, GracefulExitHandler); 139 | if (Options.HandleUsr2) 140 | SetSigaction(SIGUSR2, GracefulExitHandler); 141 | } 142 | 143 | void SleepSeconds(int Seconds) { 144 | sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. 145 | } 146 | 147 | unsigned long GetPid() { return (unsigned long)getpid(); } 148 | 149 | size_t GetPeakRSSMb() { 150 | struct rusage usage; 151 | if (getrusage(RUSAGE_SELF, &usage)) 152 | return 0; 153 | if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || 154 | LIBFUZZER_EMSCRIPTEN) { 155 | // ru_maxrss is in KiB 156 | return usage.ru_maxrss >> 10; 157 | } else if (LIBFUZZER_APPLE) { 158 | // ru_maxrss is in bytes 159 | return usage.ru_maxrss >> 20; 160 | } 161 | assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 162 | return 0; 163 | } 164 | 165 | FILE *OpenProcessPipe(const char *Command, const char *Mode) { 166 | return popen(Command, Mode); 167 | } 168 | 169 | int CloseProcessPipe(FILE *F) { 170 | return pclose(F); 171 | } 172 | 173 | const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 174 | size_t PattLen) { 175 | return memmem(Data, DataLen, Patt, PattLen); 176 | } 177 | 178 | std::string DisassembleCmd(const std::string &FileName) { 179 | return "objdump -d " + FileName; 180 | } 181 | 182 | std::string SearchRegexCmd(const std::string &Regex) { 183 | return "grep '" + Regex + "'"; 184 | } 185 | 186 | } // namespace fuzzer 187 | 188 | #endif // LIBFUZZER_POSIX 189 | -------------------------------------------------------------------------------- /libfuzzer-ng/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBFUZZER_SOURCES 2 | FuzzerCrossOver.cpp 3 | FuzzerDataFlowTrace.cpp 4 | FuzzerDriver.cpp 5 | FuzzerExtFunctionsDlsym.cpp 6 | FuzzerExtFunctionsWeak.cpp 7 | FuzzerExtFunctionsWindows.cpp 8 | FuzzerExtraCounters.cpp 9 | FuzzerExtraCountersDarwin.cpp 10 | FuzzerExtraCountersWindows.cpp 11 | FuzzerFork.cpp 12 | FuzzerIO.cpp 13 | FuzzerIOPosix.cpp 14 | FuzzerIOWindows.cpp 15 | FuzzerLoop.cpp 16 | FuzzerMerge.cpp 17 | FuzzerMutate.cpp 18 | FuzzerSHA1.cpp 19 | FuzzerTracePC.cpp 20 | FuzzerUtil.cpp 21 | FuzzerUtilDarwin.cpp 22 | FuzzerUtilFuchsia.cpp 23 | FuzzerUtilLinux.cpp 24 | FuzzerUtilPosix.cpp 25 | FuzzerUtilWindows.cpp) 26 | 27 | set(LIBFUZZER_HEADERS 28 | FuzzerBuiltins.h 29 | FuzzerBuiltinsMsvc.h 30 | FuzzerCommand.h 31 | FuzzerCorpus.h 32 | FuzzerDataFlowTrace.h 33 | FuzzerDefs.h 34 | FuzzerDictionary.h 35 | FuzzerExtFunctions.def 36 | FuzzerExtFunctions.h 37 | FuzzerFlags.def 38 | FuzzerFork.h 39 | FuzzerIO.h 40 | FuzzerInterface.h 41 | FuzzerInternal.h 42 | FuzzerMerge.h 43 | FuzzerMutate.h 44 | FuzzerOptions.h 45 | FuzzerRandom.h 46 | FuzzerSHA1.h 47 | FuzzerTracePC.h 48 | FuzzerUtil.h 49 | FuzzerValueBitMap.h) 50 | 51 | include_directories(../../include) 52 | 53 | CHECK_CXX_SOURCE_COMPILES(" 54 | static thread_local int blah; 55 | int main() { 56 | return 0; 57 | } 58 | " HAS_THREAD_LOCAL) 59 | 60 | set(LIBFUZZER_CFLAGS ${COMPILER_RT_COMMON_CFLAGS}) 61 | 62 | if(OS_NAME MATCHES "Linux|Fuchsia" AND 63 | COMPILER_RT_LIBCXX_PATH AND 64 | COMPILER_RT_LIBCXXABI_PATH) 65 | list(APPEND LIBFUZZER_CFLAGS -D_LIBCPP_ABI_VERSION=Fuzzer) 66 | append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ LIBFUZZER_CFLAGS) 67 | elseif(TARGET cxx-headers OR HAVE_LIBCXX) 68 | # libFuzzer uses C++ standard library headers. 69 | set(LIBFUZZER_DEPS cxx-headers) 70 | endif() 71 | 72 | append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) 73 | 74 | if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") 75 | list(APPEND LIBFUZZER_CFLAGS -fsanitize-coverage=0) 76 | endif() 77 | 78 | if(MSVC) 79 | # Silence warnings by turning off exceptions in MSVC headers and avoid an 80 | # error by unnecessarily defining thread_local when it isn't even used on 81 | # Windows. 82 | list(APPEND LIBFUZZER_CFLAGS -D_HAS_EXCEPTIONS=0) 83 | else() 84 | if(NOT HAS_THREAD_LOCAL) 85 | list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread) 86 | endif() 87 | endif() 88 | 89 | add_compiler_rt_component(fuzzer) 90 | 91 | add_compiler_rt_object_libraries(RTfuzzer 92 | OS ${FUZZER_SUPPORTED_OS} 93 | ARCHS ${FUZZER_SUPPORTED_ARCH} 94 | SOURCES ${LIBFUZZER_SOURCES} 95 | ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS} 96 | CFLAGS ${LIBFUZZER_CFLAGS} 97 | DEPS ${LIBFUZZER_DEPS}) 98 | 99 | add_compiler_rt_object_libraries(RTfuzzer_main 100 | OS ${FUZZER_SUPPORTED_OS} 101 | ARCHS ${FUZZER_SUPPORTED_ARCH} 102 | SOURCES FuzzerMain.cpp 103 | CFLAGS ${LIBFUZZER_CFLAGS} 104 | DEPS ${LIBFUZZER_DEPS}) 105 | 106 | add_compiler_rt_object_libraries(RTfuzzer_interceptors 107 | OS ${FUZZER_SUPPORTED_OS} 108 | ARCHS ${FUZZER_SUPPORTED_ARCH} 109 | SOURCES FuzzerInterceptors.cpp 110 | CFLAGS ${LIBFUZZER_CFLAGS} 111 | DEPS ${LIBFUZZER_DEPS}) 112 | 113 | add_compiler_rt_runtime(clang_rt.fuzzer 114 | STATIC 115 | OS ${FUZZER_SUPPORTED_OS} 116 | ARCHS ${FUZZER_SUPPORTED_ARCH} 117 | OBJECT_LIBS RTfuzzer RTfuzzer_main 118 | CFLAGS ${LIBFUZZER_CFLAGS} 119 | PARENT_TARGET fuzzer) 120 | 121 | add_compiler_rt_runtime(clang_rt.fuzzer_no_main 122 | STATIC 123 | OS ${FUZZER_SUPPORTED_OS} 124 | ARCHS ${FUZZER_SUPPORTED_ARCH} 125 | OBJECT_LIBS RTfuzzer 126 | CFLAGS ${LIBFUZZER_CFLAGS} 127 | PARENT_TARGET fuzzer) 128 | 129 | add_compiler_rt_runtime(clang_rt.fuzzer_interceptors 130 | STATIC 131 | OS ${FUZZER_SUPPORTED_OS} 132 | ARCHS ${FUZZER_SUPPORTED_ARCH} 133 | OBJECT_LIBS RTfuzzer_interceptors 134 | CFLAGS ${LIBFUZZER_CFLAGS} 135 | PARENT_TARGET fuzzer) 136 | 137 | if(OS_NAME MATCHES "Linux|Fuchsia" AND 138 | COMPILER_RT_LIBCXX_PATH AND 139 | COMPILER_RT_LIBCXXABI_PATH) 140 | macro(partially_link_libcxx name dir arch) 141 | if(${arch} MATCHES "i386") 142 | set(EMULATION_ARGUMENT "-m" "elf_i386") 143 | else() 144 | set(EMULATION_ARGUMENT "") 145 | endif() 146 | set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") 147 | file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) 148 | add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD 149 | COMMAND ${CMAKE_LINKER} ${EMULATION_ARGUMENT} --whole-archive "$" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o 150 | COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o 151 | COMMAND ${CMAKE_COMMAND} -E remove "$" 152 | COMMAND ${CMAKE_AR} qcs "$" ${name}.o 153 | WORKING_DIRECTORY ${cxx_${arch}_merge_dir} 154 | ) 155 | endmacro() 156 | 157 | foreach(arch ${FUZZER_SUPPORTED_ARCH}) 158 | get_target_flags_for_arch(${arch} TARGET_CFLAGS) 159 | set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) 160 | add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} 161 | CFLAGS ${TARGET_CFLAGS} 162 | CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON 163 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 164 | -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF 165 | -DLIBCXX_ABI_NAMESPACE=__Fuzzer 166 | -DLIBCXX_ENABLE_EXCEPTIONS=OFF) 167 | target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 168 | add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build) 169 | target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 170 | add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build) 171 | target_compile_options(RTfuzzer_interceptors.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) 172 | add_dependencies(RTfuzzer_interceptors.${arch} libcxx_fuzzer_${arch}-build) 173 | partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch}) 174 | partially_link_libcxx(fuzzer_interceptors ${LIBCXX_${arch}_PREFIX} ${arch}) 175 | partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch}) 176 | endforeach() 177 | endif() 178 | 179 | if(COMPILER_RT_INCLUDE_TESTS) 180 | add_subdirectory(tests) 181 | endif() 182 | -------------------------------------------------------------------------------- /scripts/create-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2016 syzkaller project authors. All rights reserved. 3 | # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 4 | 5 | # create-image.sh creates a minimal Debian Linux image suitable for syzkaller. 6 | 7 | set -eux 8 | 9 | # Create a minimal Debian distribution in a directory. 10 | DIR=chroot 11 | PREINSTALL_PKGS=openssh-server,curl,cron,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros,debian-ports-archive-keyring,make 12 | 13 | # If ADD_PACKAGE is not defined as an external environment variable, use our default packages 14 | if [ -z ${ADD_PACKAGE+x} ]; then 15 | ADD_PACKAGE="make,sysbench,git,vim,tmux,usbutils,tcpdump" 16 | fi 17 | 18 | # Variables affected by options 19 | ARCH=$(uname -m) 20 | RELEASE=bullseye 21 | FEATURE=minimal 22 | SEEK=2047 23 | PERF=false 24 | 25 | # Display help function 26 | display_help() { 27 | echo "Usage: $0 [option...] " >&2 28 | echo 29 | echo " -a, --arch Set architecture" 30 | echo " -d, --distribution Set on which debian distribution to create" 31 | echo " -f, --feature Check what packages to install in the image, options are minimal, full" 32 | echo " -s, --seek Image size (MB), default 2048 (2G)" 33 | echo " -h, --help Display help message" 34 | echo " -p, --add-perf Add perf support with this option enabled. Please set envrionment variable \$KERNEL at first" 35 | echo 36 | } 37 | 38 | while true; do 39 | if [ $# -eq 0 ];then 40 | echo $# 41 | break 42 | fi 43 | case "$1" in 44 | -h | --help) 45 | display_help 46 | exit 0 47 | ;; 48 | -a | --arch) 49 | ARCH=$2 50 | shift 2 51 | ;; 52 | -d | --distribution) 53 | RELEASE=$2 54 | shift 2 55 | ;; 56 | -f | --feature) 57 | FEATURE=$2 58 | shift 2 59 | ;; 60 | -s | --seek) 61 | SEEK=$(($2 - 1)) 62 | shift 2 63 | ;; 64 | -p | --add-perf) 65 | PERF=true 66 | shift 1 67 | ;; 68 | -*) 69 | echo "Error: Unknown option: $1" >&2 70 | exit 1 71 | ;; 72 | *) # No more options 73 | break 74 | ;; 75 | esac 76 | done 77 | 78 | # Handle cases where qemu and Debian use different arch names 79 | case "$ARCH" in 80 | ppc64le) 81 | DEBARCH=ppc64el 82 | ;; 83 | aarch64) 84 | DEBARCH=arm64 85 | ;; 86 | arm) 87 | DEBARCH=armel 88 | ;; 89 | x86_64) 90 | DEBARCH=amd64 91 | ;; 92 | *) 93 | DEBARCH=$ARCH 94 | ;; 95 | esac 96 | 97 | # Foreign architecture 98 | 99 | FOREIGN=false 100 | if [ $ARCH != $(uname -m) ]; then 101 | # i386 on an x86_64 host is exempted, as we can run i386 binaries natively 102 | if [ $ARCH != "i386" -o $(uname -m) != "x86_64" ]; then 103 | FOREIGN=true 104 | fi 105 | fi 106 | 107 | if [ $FOREIGN = "true" ]; then 108 | # Check for according qemu static binary 109 | if ! which qemu-$ARCH-static; then 110 | echo "Please install qemu static binary for architecture $ARCH (package 'qemu-user-static' on Debian/Ubuntu/Fedora)" 111 | exit 1 112 | fi 113 | # Check for according binfmt entry 114 | if [ ! -r /proc/sys/fs/binfmt_misc/qemu-$ARCH ]; then 115 | echo "binfmt entry /proc/sys/fs/binfmt_misc/qemu-$ARCH does not exist" 116 | exit 1 117 | fi 118 | fi 119 | 120 | # Double check KERNEL when PERF is enabled 121 | if [ $PERF = "true" ] && [ -z ${KERNEL+x} ]; then 122 | echo "Please set KERNEL environment variable when PERF is enabled" 123 | exit 1 124 | fi 125 | 126 | # If full feature is chosen, install more packages 127 | if [ $FEATURE = "full" ]; then 128 | PREINSTALL_PKGS=$PREINSTALL_PKGS","$ADD_PACKAGE 129 | fi 130 | 131 | sudo rm -rf $DIR 132 | sudo mkdir -p $DIR 133 | sudo chmod 0755 $DIR 134 | 135 | # 1. debootstrap stage 136 | 137 | DEBOOTSTRAP_PARAMS="--arch=$DEBARCH --include=$PREINSTALL_PKGS --components=main,contrib,non-free $RELEASE $DIR" 138 | if [ $FOREIGN = "true" ]; then 139 | DEBOOTSTRAP_PARAMS="--foreign $DEBOOTSTRAP_PARAMS" 140 | fi 141 | 142 | sudo debootstrap $DEBOOTSTRAP_PARAMS 143 | 144 | # 2. debootstrap stage: only necessary if target != host architecture 145 | 146 | if [ $FOREIGN = "true" ]; then 147 | sudo cp $(which qemu-$ARCH-static) $DIR/$(which qemu-$ARCH-static) 148 | sudo chroot $DIR /bin/bash -c "/debootstrap/debootstrap --second-stage" 149 | fi 150 | 151 | # Set some defaults and enable promtless ssh to the machine for root. 152 | sudo sed -i '/^root/ { s/:x:/::/ }' $DIR/etc/passwd 153 | echo 'T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100' | sudo tee -a $DIR/etc/inittab 154 | printf '\nauto eth0\niface eth0 inet dhcp\n' | sudo tee -a $DIR/etc/network/interfaces 155 | echo '/dev/root / ext4 defaults 0 0' | sudo tee -a $DIR/etc/fstab 156 | echo 'debugfs /sys/kernel/debug debugfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 157 | echo 'securityfs /sys/kernel/security securityfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 158 | echo 'configfs /sys/kernel/config/ configfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 159 | echo 'binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0' | sudo tee -a $DIR/etc/fstab 160 | echo 'host0 /hostshare 9p trans=virtio,rw,_netdev 0 0' | sudo tee -a $DIR/etc/fstab 161 | echo -en "127.0.0.1\tlocalhost\n" | sudo tee $DIR/etc/hosts 162 | echo "nameserver 8.8.8.8" | sudo tee -a $DIR/etc/resolve.conf 163 | echo "syzkaller" | sudo tee $DIR/etc/hostname 164 | echo "@reboot root /hostshare/startup.sh >/dev/ttyS0 2>&1" | sudo tee $DIR/etc/cron.d/onreboot 165 | ssh-keygen -f $RELEASE.id_rsa -t rsa -N '' 166 | sudo mkdir -p $DIR/root/.ssh/ 167 | sudo mkdir -p $DIR/hostshare/ 168 | cat $RELEASE.id_rsa.pub | sudo tee $DIR/root/.ssh/authorized_keys 169 | 170 | # Add udev rules for custom drivers. 171 | # Create a /dev/vim2m symlink for the device managed by the vim2m driver 172 | echo 'ATTR{name}=="vim2m", SYMLINK+="vim2m"' | sudo tee -a $DIR/etc/udev/rules.d/50-udev-default.rules 173 | 174 | # Build a disk image 175 | dd if=/dev/zero of=$RELEASE.img bs=1M seek=$SEEK count=1 176 | sudo mkfs.ext4 -F $RELEASE.img 177 | sudo mkdir -p /mnt/$DIR 178 | sudo mount -o loop $RELEASE.img /mnt/$DIR 179 | sudo cp -a $DIR/. /mnt/$DIR/. 180 | sudo umount /mnt/$DIR 181 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtilDarwin.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils for Darwin. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerPlatform.h" 11 | #if LIBFUZZER_APPLE 12 | #include "FuzzerCommand.h" 13 | #include "FuzzerIO.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | // There is no header for this on macOS so declare here 23 | extern "C" char **environ; 24 | 25 | namespace fuzzer { 26 | 27 | static std::mutex SignalMutex; 28 | // Global variables used to keep track of how signal handling should be 29 | // restored. They should **not** be accessed without holding `SignalMutex`. 30 | static int ActiveThreadCount = 0; 31 | static struct sigaction OldSigIntAction; 32 | static struct sigaction OldSigQuitAction; 33 | static sigset_t OldBlockedSignalsSet; 34 | 35 | // This is a reimplementation of Libc's `system()`. On Darwin the Libc 36 | // implementation contains a mutex which prevents it from being used 37 | // concurrently. This implementation **can** be used concurrently. It sets the 38 | // signal handlers when the first thread enters and restores them when the last 39 | // thread finishes execution of the function and ensures this is not racey by 40 | // using a mutex. 41 | int ExecuteCommand(const Command &Cmd) { 42 | std::string CmdLine = Cmd.toString(); 43 | posix_spawnattr_t SpawnAttributes; 44 | if (posix_spawnattr_init(&SpawnAttributes)) 45 | return -1; 46 | // Block and ignore signals of the current process when the first thread 47 | // enters. 48 | { 49 | std::lock_guard Lock(SignalMutex); 50 | if (ActiveThreadCount == 0) { 51 | static struct sigaction IgnoreSignalAction; 52 | sigset_t BlockedSignalsSet; 53 | memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction)); 54 | IgnoreSignalAction.sa_handler = SIG_IGN; 55 | 56 | if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) { 57 | Printf("Failed to ignore SIGINT\n"); 58 | (void)posix_spawnattr_destroy(&SpawnAttributes); 59 | return -1; 60 | } 61 | if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) { 62 | Printf("Failed to ignore SIGQUIT\n"); 63 | // Try our best to restore the signal handlers. 64 | (void)sigaction(SIGINT, &OldSigIntAction, NULL); 65 | (void)posix_spawnattr_destroy(&SpawnAttributes); 66 | return -1; 67 | } 68 | 69 | (void)sigemptyset(&BlockedSignalsSet); 70 | (void)sigaddset(&BlockedSignalsSet, SIGCHLD); 71 | if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) == 72 | -1) { 73 | Printf("Failed to block SIGCHLD\n"); 74 | // Try our best to restore the signal handlers. 75 | (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL); 76 | (void)sigaction(SIGINT, &OldSigIntAction, NULL); 77 | (void)posix_spawnattr_destroy(&SpawnAttributes); 78 | return -1; 79 | } 80 | } 81 | ++ActiveThreadCount; 82 | } 83 | 84 | // NOTE: Do not introduce any new `return` statements past this 85 | // point. It is important that `ActiveThreadCount` always be decremented 86 | // when leaving this function. 87 | 88 | // Make sure the child process uses the default handlers for the 89 | // following signals rather than inheriting what the parent has. 90 | sigset_t DefaultSigSet; 91 | (void)sigemptyset(&DefaultSigSet); 92 | (void)sigaddset(&DefaultSigSet, SIGQUIT); 93 | (void)sigaddset(&DefaultSigSet, SIGINT); 94 | (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet); 95 | // Make sure the child process doesn't block SIGCHLD 96 | (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet); 97 | short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; 98 | (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags); 99 | 100 | pid_t Pid; 101 | char **Environ = environ; // Read from global 102 | const char *CommandCStr = CmdLine.c_str(); 103 | char *const Argv[] = { 104 | strdup("sh"), 105 | strdup("-c"), 106 | strdup(CommandCStr), 107 | NULL 108 | }; 109 | int ErrorCode = 0, ProcessStatus = 0; 110 | // FIXME: We probably shouldn't hardcode the shell path. 111 | ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes, 112 | Argv, Environ); 113 | (void)posix_spawnattr_destroy(&SpawnAttributes); 114 | if (!ErrorCode) { 115 | pid_t SavedPid = Pid; 116 | do { 117 | // Repeat until call completes uninterrupted. 118 | Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0); 119 | } while (Pid == -1 && errno == EINTR); 120 | if (Pid == -1) { 121 | // Fail for some other reason. 122 | ProcessStatus = -1; 123 | } 124 | } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) { 125 | // Fork failure. 126 | ProcessStatus = -1; 127 | } else { 128 | // Shell execution failure. 129 | ProcessStatus = W_EXITCODE(127, 0); 130 | } 131 | for (unsigned i = 0, n = sizeof(Argv) / sizeof(Argv[0]); i < n; ++i) 132 | free(Argv[i]); 133 | 134 | // Restore the signal handlers of the current process when the last thread 135 | // using this function finishes. 136 | { 137 | std::lock_guard Lock(SignalMutex); 138 | --ActiveThreadCount; 139 | if (ActiveThreadCount == 0) { 140 | bool FailedRestore = false; 141 | if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) { 142 | Printf("Failed to restore SIGINT handling\n"); 143 | FailedRestore = true; 144 | } 145 | if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) { 146 | Printf("Failed to restore SIGQUIT handling\n"); 147 | FailedRestore = true; 148 | } 149 | if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) { 150 | Printf("Failed to unblock SIGCHLD\n"); 151 | FailedRestore = true; 152 | } 153 | if (FailedRestore) 154 | ProcessStatus = -1; 155 | } 156 | } 157 | return ProcessStatus; 158 | } 159 | 160 | void DiscardOutput(int Fd) { 161 | FILE* Temp = fopen("/dev/null", "w"); 162 | if (!Temp) 163 | return; 164 | dup2(fileno(Temp), Fd); 165 | fclose(Temp); 166 | } 167 | 168 | } // namespace fuzzer 169 | 170 | #endif // LIBFUZZER_APPLE 171 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerIO.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerIO.cpp - IO utils. -------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // IO functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerDefs.h" 12 | #include "FuzzerExtFunctions.h" 13 | #include "FuzzerIO.h" 14 | #include "FuzzerUtil.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace fuzzer { 23 | 24 | static FILE *OutputFile = stderr; 25 | 26 | FILE *GetOutputFile() { 27 | return OutputFile; 28 | } 29 | 30 | void SetOutputFile(FILE *NewOutputFile) { 31 | OutputFile = NewOutputFile; 32 | } 33 | 34 | long GetEpoch(const std::string &Path) { 35 | struct stat St; 36 | if (stat(Path.c_str(), &St)) 37 | return 0; // Can't stat, be conservative. 38 | return St.st_mtime; 39 | } 40 | 41 | Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { 42 | std::ifstream T(Path, std::ios::binary); 43 | if (ExitOnError && !T) { 44 | Printf("No such directory: %s; exiting\n", Path.c_str()); 45 | exit(1); 46 | } 47 | 48 | T.seekg(0, T.end); 49 | auto EndPos = T.tellg(); 50 | if (EndPos < 0) return {}; 51 | size_t FileLen = EndPos; 52 | if (MaxSize) 53 | FileLen = std::min(FileLen, MaxSize); 54 | 55 | T.seekg(0, T.beg); 56 | Unit Res(FileLen); 57 | T.read(reinterpret_cast(Res.data()), FileLen); 58 | return Res; 59 | } 60 | 61 | std::string FileToString(const std::string &Path) { 62 | std::ifstream T(Path, std::ios::binary); 63 | return std::string((std::istreambuf_iterator(T)), 64 | std::istreambuf_iterator()); 65 | } 66 | 67 | void CopyFileToErr(const std::string &Path) { 68 | Printf("%s", FileToString(Path).c_str()); 69 | } 70 | 71 | void WriteToFile(const Unit &U, const std::string &Path) { 72 | WriteToFile(U.data(), U.size(), Path); 73 | } 74 | 75 | void WriteToFile(const std::string &Data, const std::string &Path) { 76 | WriteToFile(reinterpret_cast(Data.c_str()), Data.size(), 77 | Path); 78 | } 79 | 80 | void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) { 81 | // Use raw C interface because this function may be called from a sig handler. 82 | FILE *Out = fopen(Path.c_str(), "wb"); 83 | if (!Out) return; 84 | fwrite(Data, sizeof(Data[0]), Size, Out); 85 | fclose(Out); 86 | } 87 | 88 | void AppendToFile(const std::string &Data, const std::string &Path) { 89 | AppendToFile(reinterpret_cast(Data.data()), Data.size(), 90 | Path); 91 | } 92 | 93 | void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) { 94 | FILE *Out = fopen(Path.c_str(), "a"); 95 | if (!Out) 96 | return; 97 | fwrite(Data, sizeof(Data[0]), Size, Out); 98 | fclose(Out); 99 | } 100 | 101 | void ReadDirToVectorOfUnits(const char *Path, std::vector *V, long *Epoch, 102 | size_t MaxSize, bool ExitOnError, 103 | std::vector *VPaths) { 104 | long E = Epoch ? *Epoch : 0; 105 | std::vector Files; 106 | ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); 107 | size_t NumLoaded = 0; 108 | for (size_t i = 0; i < Files.size(); i++) { 109 | auto &X = Files[i]; 110 | if (Epoch && GetEpoch(X) < E) continue; 111 | NumLoaded++; 112 | if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) 113 | Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); 114 | auto S = FileToVector(X, MaxSize, ExitOnError); 115 | if (!S.empty()) { 116 | V->push_back(S); 117 | if (VPaths) 118 | VPaths->push_back(X); 119 | } 120 | } 121 | } 122 | 123 | void GetSizedFilesFromDir(const std::string &Dir, std::vector *V) { 124 | std::vector Files; 125 | ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); 126 | for (auto &File : Files) 127 | if (size_t Size = FileSize(File)) 128 | V->push_back({File, Size}); 129 | } 130 | 131 | std::string DirPlusFile(const std::string &DirPath, 132 | const std::string &FileName) { 133 | return DirPath + GetSeparator() + FileName; 134 | } 135 | 136 | void DupAndCloseStderr() { 137 | int OutputFd = DuplicateFile(2); 138 | if (OutputFd >= 0) { 139 | FILE *NewOutputFile = OpenFile(OutputFd, "w"); 140 | if (NewOutputFile) { 141 | OutputFile = NewOutputFile; 142 | if (EF->__sanitizer_set_report_fd) 143 | EF->__sanitizer_set_report_fd( 144 | reinterpret_cast(GetHandleFromFd(OutputFd))); 145 | DiscardOutput(2); 146 | } 147 | } 148 | } 149 | 150 | void CloseStdout() { 151 | DiscardOutput(1); 152 | } 153 | 154 | void Printf(const char *Fmt, ...) { 155 | va_list ap; 156 | va_start(ap, Fmt); 157 | vfprintf(OutputFile, Fmt, ap); 158 | va_end(ap); 159 | fflush(OutputFile); 160 | } 161 | 162 | void VPrintf(bool Verbose, const char *Fmt, ...) { 163 | if (!Verbose) return; 164 | va_list ap; 165 | va_start(ap, Fmt); 166 | vfprintf(OutputFile, Fmt, ap); 167 | va_end(ap); 168 | fflush(OutputFile); 169 | } 170 | 171 | static bool MkDirRecursiveInner(const std::string &Leaf) { 172 | // Prevent chance of potential infinite recursion 173 | if (Leaf == ".") 174 | return true; 175 | 176 | const std::string &Dir = DirName(Leaf); 177 | 178 | if (IsDirectory(Dir)) { 179 | MkDir(Leaf); 180 | return IsDirectory(Leaf); 181 | } 182 | 183 | bool ret = MkDirRecursiveInner(Dir); 184 | if (!ret) { 185 | // Give up early if a previous MkDir failed 186 | return ret; 187 | } 188 | 189 | MkDir(Leaf); 190 | return IsDirectory(Leaf); 191 | } 192 | 193 | bool MkDirRecursive(const std::string &Dir) { 194 | if (Dir.empty()) 195 | return false; 196 | 197 | if (IsDirectory(Dir)) 198 | return true; 199 | 200 | return MkDirRecursiveInner(Dir); 201 | } 202 | 203 | void RmDirRecursive(const std::string &Dir) { 204 | IterateDirRecursive( 205 | Dir, [](const std::string &Path) {}, 206 | [](const std::string &Path) { RmDir(Path); }, 207 | [](const std::string &Path) { RemoveFile(Path); }); 208 | } 209 | 210 | std::string TempPath(const char *Prefix, const char *Extension) { 211 | return DirPlusFile(TmpDir(), std::string("libFuzzerTemp.") + Prefix + 212 | std::to_string(GetPid()) + Extension); 213 | } 214 | 215 | } // namespace fuzzer 216 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerSHA1.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // This code is taken from public domain 9 | // (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) 10 | // and modified by adding anonymous namespace, adding an interface 11 | // function fuzzer::ComputeSHA1() and removing unnecessary code. 12 | // 13 | // lib/Fuzzer can not use SHA1 implementation from openssl because 14 | // openssl may not be available and because we may be fuzzing openssl itself. 15 | // For the same reason we do not want to depend on SHA1 from LLVM tree. 16 | //===----------------------------------------------------------------------===// 17 | 18 | #include "FuzzerSHA1.h" 19 | #include "FuzzerDefs.h" 20 | #include "FuzzerPlatform.h" 21 | 22 | /* This code is public-domain - it is based on libcrypt 23 | * placed in the public domain by Wei Dai and other contributors. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace { // Added for LibFuzzer 32 | 33 | #ifdef __BIG_ENDIAN__ 34 | # define SHA_BIG_ENDIAN 35 | // Windows is always little endian and MSVC doesn't have 36 | #elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS 37 | /* override */ 38 | #elif defined __BYTE_ORDER 39 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 40 | # define SHA_BIG_ENDIAN 41 | # endif 42 | #else // ! defined __LITTLE_ENDIAN__ 43 | # include // machine/endian.h 44 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 45 | # define SHA_BIG_ENDIAN 46 | # endif 47 | #endif 48 | 49 | 50 | /* header */ 51 | 52 | #define HASH_LENGTH 20 53 | #define BLOCK_LENGTH 64 54 | 55 | typedef struct sha1nfo { 56 | uint32_t buffer[BLOCK_LENGTH/4]; 57 | uint32_t state[HASH_LENGTH/4]; 58 | uint32_t byteCount; 59 | uint8_t bufferOffset; 60 | uint8_t keyBuffer[BLOCK_LENGTH]; 61 | uint8_t innerHash[HASH_LENGTH]; 62 | } sha1nfo; 63 | 64 | /* public API - prototypes - TODO: doxygen*/ 65 | 66 | /** 67 | */ 68 | void sha1_init(sha1nfo *s); 69 | /** 70 | */ 71 | void sha1_writebyte(sha1nfo *s, uint8_t data); 72 | /** 73 | */ 74 | void sha1_write(sha1nfo *s, const char *data, size_t len); 75 | /** 76 | */ 77 | uint8_t* sha1_result(sha1nfo *s); 78 | 79 | 80 | /* code */ 81 | #define SHA1_K0 0x5a827999 82 | #define SHA1_K20 0x6ed9eba1 83 | #define SHA1_K40 0x8f1bbcdc 84 | #define SHA1_K60 0xca62c1d6 85 | 86 | void sha1_init(sha1nfo *s) { 87 | s->state[0] = 0x67452301; 88 | s->state[1] = 0xefcdab89; 89 | s->state[2] = 0x98badcfe; 90 | s->state[3] = 0x10325476; 91 | s->state[4] = 0xc3d2e1f0; 92 | s->byteCount = 0; 93 | s->bufferOffset = 0; 94 | } 95 | 96 | uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 97 | return ((number << bits) | (number >> (32-bits))); 98 | } 99 | 100 | void sha1_hashBlock(sha1nfo *s) { 101 | uint8_t i; 102 | uint32_t a,b,c,d,e,t; 103 | 104 | a=s->state[0]; 105 | b=s->state[1]; 106 | c=s->state[2]; 107 | d=s->state[3]; 108 | e=s->state[4]; 109 | for (i=0; i<80; i++) { 110 | if (i>=16) { 111 | t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 112 | s->buffer[i&15] = sha1_rol32(t,1); 113 | } 114 | if (i<20) { 115 | t = (d ^ (b & (c ^ d))) + SHA1_K0; 116 | } else if (i<40) { 117 | t = (b ^ c ^ d) + SHA1_K20; 118 | } else if (i<60) { 119 | t = ((b & c) | (d & (b | c))) + SHA1_K40; 120 | } else { 121 | t = (b ^ c ^ d) + SHA1_K60; 122 | } 123 | t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 124 | e=d; 125 | d=c; 126 | c=sha1_rol32(b,30); 127 | b=a; 128 | a=t; 129 | } 130 | s->state[0] += a; 131 | s->state[1] += b; 132 | s->state[2] += c; 133 | s->state[3] += d; 134 | s->state[4] += e; 135 | } 136 | 137 | // Adds the least significant byte of |data|. 138 | void sha1_addUncounted(sha1nfo *s, uint32_t data) { 139 | uint8_t *const b = (uint8_t *)s->buffer; 140 | #ifdef SHA_BIG_ENDIAN 141 | b[s->bufferOffset] = static_cast(data); 142 | #else 143 | b[s->bufferOffset ^ 3] = static_cast(data); 144 | #endif 145 | s->bufferOffset++; 146 | if (s->bufferOffset == BLOCK_LENGTH) { 147 | sha1_hashBlock(s); 148 | s->bufferOffset = 0; 149 | } 150 | } 151 | 152 | void sha1_writebyte(sha1nfo *s, uint8_t data) { 153 | ++s->byteCount; 154 | sha1_addUncounted(s, data); 155 | } 156 | 157 | void sha1_write(sha1nfo *s, const char *data, size_t len) { 158 | for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 159 | } 160 | 161 | void sha1_pad(sha1nfo *s) { 162 | // Implement SHA-1 padding (fips180-2 §5.1.1) 163 | 164 | // Pad with 0x80 followed by 0x00 until the end of the block 165 | sha1_addUncounted(s, 0x80); 166 | while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 167 | 168 | // Append length in the last 8 bytes 169 | sha1_addUncounted(s, 0); // We're only using 32 bit lengths 170 | sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 171 | sha1_addUncounted(s, 0); // So zero pad the top bits 172 | sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 173 | sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 174 | sha1_addUncounted(s, s->byteCount >> 13); // byte. 175 | sha1_addUncounted(s, s->byteCount >> 5); 176 | sha1_addUncounted(s, s->byteCount << 3); 177 | } 178 | 179 | uint8_t* sha1_result(sha1nfo *s) { 180 | // Pad to complete the last block 181 | sha1_pad(s); 182 | 183 | #ifndef SHA_BIG_ENDIAN 184 | // Swap byte order back 185 | int i; 186 | for (i=0; i<5; i++) { 187 | s->state[i]= 188 | (((s->state[i])<<24)& 0xff000000) 189 | | (((s->state[i])<<8) & 0x00ff0000) 190 | | (((s->state[i])>>8) & 0x0000ff00) 191 | | (((s->state[i])>>24)& 0x000000ff); 192 | } 193 | #endif 194 | 195 | // Return pointer to hash (20 characters) 196 | return (uint8_t*) s->state; 197 | } 198 | 199 | } // namespace; Added for LibFuzzer 200 | 201 | namespace fuzzer { 202 | 203 | // The rest is added for LibFuzzer 204 | void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { 205 | sha1nfo s; 206 | sha1_init(&s); 207 | sha1_write(&s, (const char*)Data, Len); 208 | memcpy(Out, sha1_result(&s), HASH_LENGTH); 209 | } 210 | 211 | std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { 212 | std::stringstream SS; 213 | for (int i = 0; i < kSHA1NumBytes; i++) 214 | SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; 215 | return SS.str(); 216 | } 217 | 218 | std::string Hash(const Unit &U) { 219 | uint8_t Hash[kSHA1NumBytes]; 220 | ComputeSHA1(U.data(), U.size(), Hash); 221 | return Sha1ToString(Hash); 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerCommand.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // FuzzerCommand represents a command to run in a subprocess. It allows callers 9 | // to manage command line arguments and output and error streams. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef LLVM_FUZZER_COMMAND_H 13 | #define LLVM_FUZZER_COMMAND_H 14 | 15 | #include "FuzzerDefs.h" 16 | #include "FuzzerIO.h" 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace fuzzer { 24 | 25 | class Command final { 26 | public: 27 | // This command line flag is used to indicate that the remaining command line 28 | // is immutable, meaning this flag effectively marks the end of the mutable 29 | // argument list. 30 | static inline const char *ignoreRemainingArgs() { 31 | return "-ignore_remaining_args=1"; 32 | } 33 | 34 | Command() : CombinedOutAndErr(false) {} 35 | 36 | explicit Command(const std::vector &ArgsToAdd) 37 | : Args(ArgsToAdd), CombinedOutAndErr(false) {} 38 | 39 | explicit Command(const Command &Other) 40 | : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr), 41 | OutputFile(Other.OutputFile) {} 42 | 43 | Command &operator=(const Command &Other) { 44 | Args = Other.Args; 45 | CombinedOutAndErr = Other.CombinedOutAndErr; 46 | OutputFile = Other.OutputFile; 47 | return *this; 48 | } 49 | 50 | ~Command() {} 51 | 52 | // Returns true if the given Arg is present in Args. Only checks up to 53 | // "-ignore_remaining_args=1". 54 | bool hasArgument(const std::string &Arg) const { 55 | auto i = endMutableArgs(); 56 | return std::find(Args.begin(), i, Arg) != i; 57 | } 58 | 59 | // Gets all of the current command line arguments, **including** those after 60 | // "-ignore-remaining-args=1". 61 | const std::vector &getArguments() const { return Args; } 62 | 63 | // Adds the given argument before "-ignore_remaining_args=1", or at the end 64 | // if that flag isn't present. 65 | void addArgument(const std::string &Arg) { 66 | Args.insert(endMutableArgs(), Arg); 67 | } 68 | 69 | // Adds all given arguments before "-ignore_remaining_args=1", or at the end 70 | // if that flag isn't present. 71 | void addArguments(const std::vector &ArgsToAdd) { 72 | Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end()); 73 | } 74 | 75 | // Removes the given argument from the command argument list. Ignores any 76 | // occurrences after "-ignore_remaining_args=1", if present. 77 | void removeArgument(const std::string &Arg) { 78 | auto i = endMutableArgs(); 79 | Args.erase(std::remove(Args.begin(), i, Arg), i); 80 | } 81 | 82 | // Like hasArgument, but checks for "-[Flag]=...". 83 | bool hasFlag(const std::string &Flag) const { 84 | std::string Arg("-" + Flag + "="); 85 | auto IsMatch = [&](const std::string &Other) { 86 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 87 | }; 88 | return std::any_of(Args.begin(), endMutableArgs(), IsMatch); 89 | } 90 | 91 | // Returns the value of the first instance of a given flag, or an empty string 92 | // if the flag isn't present. Ignores any occurrences after 93 | // "-ignore_remaining_args=1", if present. 94 | std::string getFlagValue(const std::string &Flag) const { 95 | std::string Arg("-" + Flag + "="); 96 | auto IsMatch = [&](const std::string &Other) { 97 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 98 | }; 99 | auto i = endMutableArgs(); 100 | auto j = std::find_if(Args.begin(), i, IsMatch); 101 | std::string result; 102 | if (j != i) { 103 | result = j->substr(Arg.length()); 104 | } 105 | return result; 106 | } 107 | 108 | // Like AddArgument, but adds "-[Flag]=[Value]". 109 | void addFlag(const std::string &Flag, const std::string &Value) { 110 | addArgument("-" + Flag + "=" + Value); 111 | } 112 | 113 | // Like RemoveArgument, but removes "-[Flag]=...". 114 | void removeFlag(const std::string &Flag) { 115 | std::string Arg("-" + Flag + "="); 116 | auto IsMatch = [&](const std::string &Other) { 117 | return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; 118 | }; 119 | auto i = endMutableArgs(); 120 | Args.erase(std::remove_if(Args.begin(), i, IsMatch), i); 121 | } 122 | 123 | // Returns whether the command's stdout is being written to an output file. 124 | bool hasOutputFile() const { return !OutputFile.empty(); } 125 | 126 | // Returns the currently set output file. 127 | const std::string &getOutputFile() const { return OutputFile; } 128 | 129 | // Configures the command to redirect its output to the name file. 130 | void setOutputFile(const std::string &FileName) { OutputFile = FileName; } 131 | 132 | // Returns whether the command's stderr is redirected to stdout. 133 | bool isOutAndErrCombined() const { return CombinedOutAndErr; } 134 | 135 | // Sets whether to redirect the command's stderr to its stdout. 136 | void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; } 137 | 138 | // Returns a string representation of the command. On many systems this will 139 | // be the equivalent command line. 140 | std::string toString() const { 141 | std::stringstream SS; 142 | for (auto arg : getArguments()) 143 | SS << arg << " "; 144 | if (hasOutputFile()) 145 | SS << ">" << getOutputFile() << " "; 146 | if (isOutAndErrCombined()) 147 | SS << "2>&1 "; 148 | std::string result = SS.str(); 149 | if (!result.empty()) 150 | result = result.substr(0, result.length() - 1); 151 | return result; 152 | } 153 | 154 | private: 155 | Command(Command &&Other) = delete; 156 | Command &operator=(Command &&Other) = delete; 157 | 158 | std::vector::iterator endMutableArgs() { 159 | return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); 160 | } 161 | 162 | std::vector::const_iterator endMutableArgs() const { 163 | return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); 164 | } 165 | 166 | // The command arguments. Args[0] is the command name. 167 | std::vector Args; 168 | 169 | // True indicates stderr is redirected to stdout. 170 | bool CombinedOutAndErr; 171 | 172 | // If not empty, stdout is redirected to the named file. 173 | std::string OutputFile; 174 | }; 175 | 176 | } // namespace fuzzer 177 | 178 | #endif // LLVM_FUZZER_COMMAND_H 179 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerInternal.h: -------------------------------------------------------------------------------- 1 | //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Define the main class fuzzer::Fuzzer and most functions. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LLVM_FUZZER_INTERNAL_H 12 | #define LLVM_FUZZER_INTERNAL_H 13 | 14 | #include "FuzzerDataFlowTrace.h" 15 | #include "FuzzerDefs.h" 16 | #include "FuzzerExtFunctions.h" 17 | #include "FuzzerInterface.h" 18 | #include "FuzzerOptions.h" 19 | #include "FuzzerSHA1.h" 20 | #include "FuzzerValueBitMap.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace fuzzer { 29 | 30 | using namespace std::chrono; 31 | 32 | 33 | typedef struct __attribute__((packed)){ 34 | uint64_t id; 35 | uint16_t start; 36 | uint16_t len; 37 | uint32_t runtime; 38 | uint32_t success; 39 | uint32_t n_copy_from_user; // Number of copy_from_user patterns 40 | } log_entry; 41 | 42 | struct syscall_log{ 43 | size_t len; 44 | log_entry data[]; 45 | }; 46 | 47 | class Fuzzer { 48 | public: 49 | 50 | Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 51 | FuzzingOptions Options); 52 | ~Fuzzer(); 53 | void Loop(std::vector &CorporaFiles); 54 | void ReadAndExecuteSeedCorpora(std::vector &CorporaFiles); 55 | void MinimizeCrashLoop(const Unit &U); 56 | void RereadOutputCorpus(size_t MaxSize); 57 | 58 | size_t secondsSinceProcessStartUp() { 59 | return duration_cast(system_clock::now() - ProcessStartTime) 60 | .count(); 61 | } 62 | 63 | bool TimedOut() { 64 | return Options.MaxTotalTimeSec > 0 && 65 | secondsSinceProcessStartUp() > 66 | static_cast(Options.MaxTotalTimeSec); 67 | } 68 | 69 | size_t execPerSec() { 70 | size_t Seconds = secondsSinceProcessStartUp(); 71 | return Seconds ? TotalNumberOfRuns / Seconds : 0; 72 | } 73 | 74 | size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } 75 | 76 | static void StaticAlarmCallback(); 77 | static void StaticCrashSignalCallback(); 78 | static void StaticExitCallback(); 79 | static void StaticInterruptCallback(); 80 | static void StaticFileSizeExceedCallback(); 81 | static void StaticGracefulExitCallback(); 82 | 83 | void ExecuteCallback(const uint8_t *Data, size_t Size); 84 | bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, 85 | InputInfo *II = nullptr, bool ForceAddToCorpus = false, 86 | bool *FoundUniqFeatures = nullptr); 87 | void TPCUpdateObservedPCs(); 88 | 89 | // Merge Corpora[1:] into Corpora[0]. 90 | void Merge(const std::vector &Corpora); 91 | void CrashResistantMergeInternalStep(const std::string &ControlFilePath, 92 | bool IsSetCoverMerge); 93 | MutationDispatcher &GetMD() { return MD; } 94 | void PrintFinalStats(); 95 | void SetMaxInputLen(size_t MaxInputLen); 96 | void SetMaxMutationLen(size_t MaxMutationLen); 97 | void RssLimitCallback(); 98 | 99 | bool InFuzzingThread() const { return IsMyThread; } 100 | size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; 101 | void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 102 | bool DuringInitialCorpusExecution); 103 | 104 | void HandleMalloc(size_t Size); 105 | static void MaybeExitGracefully(); 106 | std::string WriteToOutputCorpus(const Unit &U); 107 | 108 | void OverwriteUnitData(uint8_t *data, size_t size); 109 | void SetSyscallLog(struct syscall_log *log); 110 | struct syscall_log *SyscallLog = nullptr; 111 | 112 | InputCorpus &Corpus; 113 | 114 | private: 115 | void AlarmCallback(); 116 | void CrashCallback(); 117 | void ExitCallback(); 118 | void CrashOnOverwrittenData(); 119 | void InterruptCallback(); 120 | void MutateAndTestOne(); 121 | void PurgeAllocator(); 122 | void ReportNewCoverage(InputInfo *II, const Unit &U); 123 | void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); 124 | void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); 125 | void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, 126 | size_t Features = 0); 127 | void PrintStatusForNewUnit(const Unit &U, const char *Text); 128 | void CheckExitOnSrcPosOrItem(); 129 | 130 | static void StaticDeathCallback(); 131 | void DumpCurrentUnit(const char *Prefix); 132 | void DeathCallback(); 133 | 134 | void AllocateCurrentUnitData(); 135 | uint8_t *CurrentUnitData = nullptr; 136 | std::atomic CurrentUnitSize; 137 | 138 | std::atomic ModifiedCurrentUnitSize; 139 | uint8_t *ModifiedCurrentUnitData = nullptr; 140 | 141 | 142 | uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. 143 | 144 | bool GracefulExitRequested = false; 145 | 146 | size_t TotalNumberOfRuns = 0; 147 | size_t NumberOfNewUnitsAdded = 0; 148 | 149 | size_t LastCorpusUpdateRun = 0; 150 | 151 | bool HasMoreMallocsThanFrees = false; 152 | size_t NumberOfLeakDetectionAttempts = 0; 153 | 154 | system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); 155 | 156 | UserCallback CB; 157 | MutationDispatcher &MD; 158 | FuzzingOptions Options; 159 | DataFlowTrace DFT; 160 | 161 | system_clock::time_point ProcessStartTime = system_clock::now(); 162 | system_clock::time_point UnitStartTime, UnitStopTime; 163 | long TimeOfLongestUnitInSeconds = 0; 164 | long EpochOfLastReadOfOutputCorpus = 0; 165 | 166 | size_t MaxInputLen = 0; 167 | size_t MaxMutationLen = 0; 168 | size_t TmpMaxMutationLen = 0; 169 | 170 | std::vector UniqFeatureSetTmp; 171 | 172 | // Need to know our own thread. 173 | static thread_local bool IsMyThread; 174 | }; 175 | 176 | struct ScopedEnableMsanInterceptorChecks { 177 | ScopedEnableMsanInterceptorChecks() { 178 | if (EF->__msan_scoped_enable_interceptor_checks) 179 | EF->__msan_scoped_enable_interceptor_checks(); 180 | } 181 | ~ScopedEnableMsanInterceptorChecks() { 182 | if (EF->__msan_scoped_disable_interceptor_checks) 183 | EF->__msan_scoped_disable_interceptor_checks(); 184 | } 185 | }; 186 | 187 | struct ScopedDisableMsanInterceptorChecks { 188 | ScopedDisableMsanInterceptorChecks() { 189 | if (EF->__msan_scoped_disable_interceptor_checks) 190 | EF->__msan_scoped_disable_interceptor_checks(); 191 | } 192 | ~ScopedDisableMsanInterceptorChecks() { 193 | if (EF->__msan_scoped_enable_interceptor_checks) 194 | EF->__msan_scoped_enable_interceptor_checks(); 195 | } 196 | }; 197 | 198 | } // namespace fuzzer 199 | 200 | #endif // LLVM_FUZZER_INTERNAL_H 201 | -------------------------------------------------------------------------------- /agent/bloat.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "fuzz.h" 20 | #include "conveyor.h" 21 | 22 | int uffd; 23 | 24 | size_t ignore_addr; 25 | size_t ignore_addr_end; 26 | size_t min_addr=-1; 27 | size_t max_addr; 28 | int bloated; 29 | 30 | static void uffd_setup(void){ 31 | struct uffdio_api uffdio_api; 32 | int tmpfd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); 33 | uffd = dup2(tmpfd, 100); 34 | close(tmpfd); 35 | debug_printf("UFFD is %d\n", uffd); 36 | if(uffd == -1){ 37 | printf("Failed to open UFFD\n"); 38 | exit(1); 39 | } 40 | uffdio_api.api = UFFD_API; 41 | uffdio_api.features = 0; 42 | if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1){ 43 | printf("ioctl-UFFDIO_API\n"); 44 | exit(1); 45 | } 46 | } 47 | 48 | static void uffd_register(size_t start, size_t len, int mode){ 49 | struct uffdio_register uffdio_register; 50 | uffdio_register.range.start = start; 51 | uffdio_register.range.len = len; 52 | uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING; 53 | if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1){ 54 | printf("ioctl-UFFDIO_REGISTER\n"); 55 | exit(1); 56 | } 57 | 58 | } 59 | 60 | static void* uffd_worker(void* param){ 61 | static int fault_cnt; 62 | static struct uffd_msg msg; /* Data read from userfaultfd */ 63 | static char *page = NULL; 64 | struct uffdio_copy uffdio_copy; 65 | struct uffdio_zeropage uffdio_zeropage; 66 | size_t nread; 67 | 68 | size_t page_size = 4096; 69 | if (page == NULL) { 70 | page = mmap(NULL, page_size, PROT_READ | PROT_WRITE, 71 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 72 | if (page == MAP_FAILED){ 73 | printf("mmap\n"); 74 | exit(1); 75 | } 76 | } 77 | sleep(1); 78 | for (;;) { 79 | 80 | /* See what poll() tells us about the userfaultfd. */ 81 | 82 | struct pollfd pollfd; 83 | int nready; 84 | pollfd.fd = uffd; 85 | pollfd.events = POLLIN; 86 | nready = poll(&pollfd, 1, -1); 87 | if (nready == -1){ 88 | printf("%s\n","poll\n"); 89 | exit(1); 90 | } 91 | 92 | nread = read(uffd, &msg, sizeof(msg)); 93 | if (nread == 0) { 94 | printf("%s\n","EOF on userfaultfd!\n"); 95 | exit(1); 96 | } 97 | 98 | if (nread == -1){ 99 | printf("%s\n","read -1"); 100 | exit(1); 101 | } 102 | 103 | /* We expect only one kind of event; verify that assumption. */ 104 | if (msg.event != UFFD_EVENT_PAGEFAULT) { 105 | fprintf(stderr, "Unexpected event on userfaultfd\n"); 106 | exit(1); 107 | } 108 | 109 | /* Display info about the page-fault event. */ 110 | 111 | // Is it a write? 112 | if(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE) { 113 | debug_printf("%s","UFFD Write... Skipping\n"); 114 | uffdio_zeropage.range.start = (unsigned long) msg.arg.pagefault.address & 115 | ~(page_size - 1); 116 | uffdio_zeropage.range.len = page_size; 117 | ioctl(uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage); 118 | continue; 119 | } 120 | 121 | // Does it match with a CFU cb? 122 | if(msg.arg.pagefault.address >= (ignore_addr & 0x000) && msg.arg.pagefault.address <= (ignore_addr_end | 0xFFF)){ 123 | debug_printf("%s","IN_CFU... Skipping\n"); 124 | uffdio_zeropage.range.start = (unsigned long) msg.arg.pagefault.address & 125 | ~(page_size - 1); 126 | uffdio_zeropage.range.len = page_size; 127 | ioctl(uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage); 128 | continue; 129 | } 130 | fflush(stdout); 131 | 132 | /* Copy the page pointed to by 'page' into the faulting 133 | region. Vary the contents that are copied in, so that it 134 | is more obvious that each fault is handled separately. */ 135 | if(!ic_advance_until_token(SEPARATOR, 4)) 136 | ic_insert(SEPARATOR, 4, ic_get_cursor()); 137 | pattern p; 138 | p.len = 100; 139 | p.data = ic_ingest_buf(&p.len, SEPARATOR, 4, 20, 0); 140 | p.index = 0; 141 | p.stride = 0; 142 | 143 | pattern_alloc(page, page_size, p); 144 | fault_cnt++; 145 | 146 | uffdio_copy.src = (unsigned long) page; 147 | 148 | /* We need to handle page faults in units of pages(!). 149 | So, round faulting address down to page boundary. */ 150 | 151 | uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address & 152 | ~(page_size - 1); 153 | uffdio_copy.len = page_size; 154 | uffdio_copy.mode = 0; 155 | uffdio_copy.copy = 0; 156 | if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1){ 157 | debug_printf("%s","ioctl-UFFDIO_COPY\n"); 158 | exit(1); 159 | } 160 | } 161 | } 162 | static void uffd_start(void){ 163 | pthread_t thr; 164 | int s = pthread_create(&thr, NULL, uffd_worker, NULL); 165 | if (s != 0) { 166 | printf("pthread_create\n"); 167 | exit(1); 168 | } 169 | } 170 | 171 | void bloatme(void){ 172 | uint64_t sz = 4096; 173 | 174 | uffd_setup(); 175 | uffd_start(); 176 | for(int i=0; i<64; i++){ 177 | printf("Trying: %lx... ", sz); 178 | void *ret = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); 179 | if(ret != MAP_FAILED){ 180 | printf("Success! %p\n", ret); 181 | munmap(ret, sz); 182 | } 183 | else{ 184 | printf("Fail!\n"); 185 | break; 186 | } 187 | sz = sz << 1; 188 | } 189 | sz = sz >> 1; 190 | void *good = NULL; 191 | while(1){ 192 | if (sz < 4096<<8) 193 | break; 194 | printf("Trying: %lx... ", sz); 195 | void *ret = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); 196 | if(ret != MAP_FAILED && ret){ 197 | printf("Success! %p\n", ret); 198 | if(ret < (void*)min_addr) 199 | min_addr = (size_t)ret; 200 | if((size_t)ret + sz > max_addr) 201 | max_addr = (size_t)ret + sz; 202 | uffd_register((size_t)ret, sz, UFFDIO_REGISTER_MODE_MISSING); 203 | } else { 204 | printf("Fail!\n"); 205 | sz = sz >> 1; 206 | } 207 | } 208 | printf("MIN_ADDR: %lx MAX_ADDR %lx\n", min_addr, max_addr); 209 | char path[100]; 210 | sprintf(path, "cat /proc/%d/maps", getpid()); 211 | printf("%s\n", path); 212 | system(path); 213 | sprintf(path, "ls -ltrha /proc/%d/fd/", getpid()); 214 | printf("%s\n", path); 215 | system(path); 216 | system("ps -aux"); 217 | bloated = 1; 218 | sleep(1); 219 | fflush(stdout); 220 | } 221 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtilWindows.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils implementation for Windows. 9 | //===----------------------------------------------------------------------===// 10 | #include "FuzzerPlatform.h" 11 | #if LIBFUZZER_WINDOWS 12 | #include "FuzzerCommand.h" 13 | #include "FuzzerIO.h" 14 | #include "FuzzerInternal.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // This must be included after windows.h. 27 | #include 28 | 29 | namespace fuzzer { 30 | 31 | static const FuzzingOptions* HandlerOpt = nullptr; 32 | 33 | static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { 34 | switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { 35 | case EXCEPTION_ACCESS_VIOLATION: 36 | case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 37 | case EXCEPTION_STACK_OVERFLOW: 38 | if (HandlerOpt->HandleSegv) 39 | Fuzzer::StaticCrashSignalCallback(); 40 | break; 41 | case EXCEPTION_DATATYPE_MISALIGNMENT: 42 | case EXCEPTION_IN_PAGE_ERROR: 43 | if (HandlerOpt->HandleBus) 44 | Fuzzer::StaticCrashSignalCallback(); 45 | break; 46 | case EXCEPTION_ILLEGAL_INSTRUCTION: 47 | case EXCEPTION_PRIV_INSTRUCTION: 48 | if (HandlerOpt->HandleIll) 49 | Fuzzer::StaticCrashSignalCallback(); 50 | break; 51 | case EXCEPTION_FLT_DENORMAL_OPERAND: 52 | case EXCEPTION_FLT_DIVIDE_BY_ZERO: 53 | case EXCEPTION_FLT_INEXACT_RESULT: 54 | case EXCEPTION_FLT_INVALID_OPERATION: 55 | case EXCEPTION_FLT_OVERFLOW: 56 | case EXCEPTION_FLT_STACK_CHECK: 57 | case EXCEPTION_FLT_UNDERFLOW: 58 | case EXCEPTION_INT_DIVIDE_BY_ZERO: 59 | case EXCEPTION_INT_OVERFLOW: 60 | if (HandlerOpt->HandleFpe) 61 | Fuzzer::StaticCrashSignalCallback(); 62 | break; 63 | // This is an undocumented exception code corresponding to a Visual C++ 64 | // Exception. 65 | // 66 | // See: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273 67 | case 0xE06D7363: 68 | if (HandlerOpt->HandleWinExcept) 69 | Fuzzer::StaticCrashSignalCallback(); 70 | break; 71 | // TODO: Handle (Options.HandleXfsz) 72 | } 73 | return EXCEPTION_CONTINUE_SEARCH; 74 | } 75 | 76 | BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { 77 | switch (dwCtrlType) { 78 | case CTRL_C_EVENT: 79 | if (HandlerOpt->HandleInt) 80 | Fuzzer::StaticInterruptCallback(); 81 | return TRUE; 82 | case CTRL_BREAK_EVENT: 83 | if (HandlerOpt->HandleTerm) 84 | Fuzzer::StaticInterruptCallback(); 85 | return TRUE; 86 | } 87 | return FALSE; 88 | } 89 | 90 | void CALLBACK AlarmHandler(PVOID, BOOLEAN) { 91 | Fuzzer::StaticAlarmCallback(); 92 | } 93 | 94 | class TimerQ { 95 | HANDLE TimerQueue; 96 | public: 97 | TimerQ() : TimerQueue(NULL) {} 98 | ~TimerQ() { 99 | if (TimerQueue) 100 | DeleteTimerQueueEx(TimerQueue, NULL); 101 | } 102 | void SetTimer(int Seconds) { 103 | if (!TimerQueue) { 104 | TimerQueue = CreateTimerQueue(); 105 | if (!TimerQueue) { 106 | Printf("libFuzzer: CreateTimerQueue failed.\n"); 107 | exit(1); 108 | } 109 | } 110 | HANDLE Timer; 111 | if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, 112 | Seconds*1000, Seconds*1000, 0)) { 113 | Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); 114 | exit(1); 115 | } 116 | } 117 | }; 118 | 119 | static TimerQ Timer; 120 | 121 | static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } 122 | 123 | void SetSignalHandler(const FuzzingOptions& Options) { 124 | HandlerOpt = &Options; 125 | 126 | if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) 127 | Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); 128 | 129 | if (Options.HandleInt || Options.HandleTerm) 130 | if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { 131 | DWORD LastError = GetLastError(); 132 | Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", 133 | LastError); 134 | exit(1); 135 | } 136 | 137 | if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || 138 | Options.HandleFpe || Options.HandleWinExcept) 139 | SetUnhandledExceptionFilter(ExceptionHandler); 140 | 141 | if (Options.HandleAbrt) 142 | if (SIG_ERR == signal(SIGABRT, CrashHandler)) { 143 | Printf("libFuzzer: signal failed with %d\n", errno); 144 | exit(1); 145 | } 146 | } 147 | 148 | void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } 149 | 150 | unsigned long GetPid() { return GetCurrentProcessId(); } 151 | 152 | size_t GetPeakRSSMb() { 153 | PROCESS_MEMORY_COUNTERS info; 154 | if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) 155 | return 0; 156 | return info.PeakWorkingSetSize >> 20; 157 | } 158 | 159 | FILE *OpenProcessPipe(const char *Command, const char *Mode) { 160 | return _popen(Command, Mode); 161 | } 162 | 163 | int CloseProcessPipe(FILE *F) { 164 | return _pclose(F); 165 | } 166 | 167 | int ExecuteCommand(const Command &Cmd) { 168 | std::string CmdLine = Cmd.toString(); 169 | return system(CmdLine.c_str()); 170 | } 171 | 172 | bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { 173 | FILE *Pipe = _popen(Cmd.toString().c_str(), "r"); 174 | if (!Pipe) 175 | return false; 176 | 177 | if (CmdOutput) { 178 | char TmpBuffer[128]; 179 | while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) 180 | CmdOutput->append(TmpBuffer); 181 | } 182 | return _pclose(Pipe) == 0; 183 | } 184 | 185 | const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 186 | size_t PattLen) { 187 | // TODO: make this implementation more efficient. 188 | const char *Cdata = (const char *)Data; 189 | const char *Cpatt = (const char *)Patt; 190 | 191 | if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) 192 | return NULL; 193 | 194 | if (PattLen == 1) 195 | return memchr(Data, *Cpatt, DataLen); 196 | 197 | const char *End = Cdata + DataLen - PattLen + 1; 198 | 199 | for (const char *It = Cdata; It < End; ++It) 200 | if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) 201 | return It; 202 | 203 | return NULL; 204 | } 205 | 206 | std::string DisassembleCmd(const std::string &FileName) { 207 | std::vector command_vector; 208 | command_vector.push_back("dumpbin /summary > nul"); 209 | if (ExecuteCommand(Command(command_vector)) == 0) 210 | return "dumpbin /disasm " + FileName; 211 | Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n"); 212 | exit(1); 213 | } 214 | 215 | std::string SearchRegexCmd(const std::string &Regex) { 216 | return "findstr /r \"" + Regex + "\""; 217 | } 218 | 219 | void DiscardOutput(int Fd) { 220 | FILE* Temp = fopen("nul", "w"); 221 | if (!Temp) 222 | return; 223 | _dup2(_fileno(Temp), Fd); 224 | fclose(Temp); 225 | } 226 | 227 | } // namespace fuzzer 228 | 229 | #endif // LIBFUZZER_WINDOWS 230 | -------------------------------------------------------------------------------- /libfuzzer-ng/FuzzerUtil.cpp: -------------------------------------------------------------------------------- 1 | //===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // Misc utils. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include "FuzzerUtil.h" 12 | #include "FuzzerIO.h" 13 | #include "FuzzerInternal.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace fuzzer { 26 | 27 | void PrintHexArray(const uint8_t *Data, size_t Size, 28 | const char *PrintAfter) { 29 | for (size_t i = 0; i < Size; i++) 30 | Printf("0x%x,", (unsigned)Data[i]); 31 | Printf("%s", PrintAfter); 32 | } 33 | 34 | void Print(const Unit &v, const char *PrintAfter) { 35 | PrintHexArray(v.data(), v.size(), PrintAfter); 36 | } 37 | 38 | void PrintASCIIByte(uint8_t Byte) { 39 | if (Byte == '\\') 40 | Printf("\\\\"); 41 | else if (Byte == '"') 42 | Printf("\\\""); 43 | else if (Byte >= 32 && Byte < 127) 44 | Printf("%c", Byte); 45 | else 46 | Printf("\\%03o", Byte); 47 | } 48 | 49 | void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { 50 | for (size_t i = 0; i < Size; i++) 51 | PrintASCIIByte(Data[i]); 52 | Printf("%s", PrintAfter); 53 | } 54 | 55 | void PrintASCII(const Unit &U, const char *PrintAfter) { 56 | PrintASCII(U.data(), U.size(), PrintAfter); 57 | } 58 | 59 | bool ToASCII(uint8_t *Data, size_t Size) { 60 | bool Changed = false; 61 | for (size_t i = 0; i < Size; i++) { 62 | uint8_t &X = Data[i]; 63 | auto NewX = X; 64 | NewX &= 127; 65 | if (!isspace(NewX) && !isprint(NewX)) 66 | NewX = ' '; 67 | Changed |= NewX != X; 68 | X = NewX; 69 | } 70 | return Changed; 71 | } 72 | 73 | bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } 74 | 75 | bool IsASCII(const uint8_t *Data, size_t Size) { 76 | for (size_t i = 0; i < Size; i++) 77 | if (!(isprint(Data[i]) || isspace(Data[i]))) return false; 78 | return true; 79 | } 80 | 81 | bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { 82 | U->clear(); 83 | if (Str.empty()) return false; 84 | size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. 85 | // Skip spaces from both sides. 86 | while (L < R && isspace(Str[L])) L++; 87 | while (R > L && isspace(Str[R])) R--; 88 | if (R - L < 2) return false; 89 | // Check the closing " 90 | if (Str[R] != '"') return false; 91 | R--; 92 | // Find the opening " 93 | while (L < R && Str[L] != '"') L++; 94 | if (L >= R) return false; 95 | assert(Str[L] == '\"'); 96 | L++; 97 | assert(L <= R); 98 | for (size_t Pos = L; Pos <= R; Pos++) { 99 | uint8_t V = (uint8_t)Str[Pos]; 100 | if (!isprint(V) && !isspace(V)) return false; 101 | if (V =='\\') { 102 | // Handle '\\' 103 | if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { 104 | U->push_back(Str[Pos + 1]); 105 | Pos++; 106 | continue; 107 | } 108 | // Handle '\xAB' 109 | if (Pos + 3 <= R && Str[Pos + 1] == 'x' 110 | && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { 111 | char Hex[] = "0xAA"; 112 | Hex[2] = Str[Pos + 2]; 113 | Hex[3] = Str[Pos + 3]; 114 | U->push_back(static_cast(strtol(Hex, nullptr, 16))); 115 | Pos += 3; 116 | continue; 117 | } 118 | return false; // Invalid escape. 119 | } else { 120 | // Any other character. 121 | U->push_back(V); 122 | } 123 | } 124 | return true; 125 | } 126 | 127 | bool ParseDictionaryFile(const std::string &Text, std::vector *Units) { 128 | if (Text.empty()) { 129 | Printf("ParseDictionaryFile: file does not exist or is empty\n"); 130 | return false; 131 | } 132 | std::istringstream ISS(Text); 133 | Units->clear(); 134 | Unit U; 135 | int LineNo = 0; 136 | std::string S; 137 | while (std::getline(ISS, S, '\n')) { 138 | LineNo++; 139 | size_t Pos = 0; 140 | while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. 141 | if (Pos == S.size()) continue; // Empty line. 142 | if (S[Pos] == '#') continue; // Comment line. 143 | if (ParseOneDictionaryEntry(S, &U)) { 144 | Units->push_back(U); 145 | } else { 146 | Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, 147 | S.c_str()); 148 | return false; 149 | } 150 | } 151 | return true; 152 | } 153 | 154 | // Code duplicated (and tested) in llvm/include/llvm/Support/Base64.h 155 | std::string Base64(const Unit &U) { 156 | static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 157 | "abcdefghijklmnopqrstuvwxyz" 158 | "0123456789+/"; 159 | std::string Buffer; 160 | Buffer.resize(((U.size() + 2) / 3) * 4); 161 | 162 | size_t i = 0, j = 0; 163 | for (size_t n = U.size() / 3 * 3; i < n; i += 3, j += 4) { 164 | uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8) | 165 | (unsigned char)U[i + 2]; 166 | Buffer[j + 0] = Table[(x >> 18) & 63]; 167 | Buffer[j + 1] = Table[(x >> 12) & 63]; 168 | Buffer[j + 2] = Table[(x >> 6) & 63]; 169 | Buffer[j + 3] = Table[x & 63]; 170 | } 171 | if (i + 1 == U.size()) { 172 | uint32_t x = ((unsigned char)U[i] << 16); 173 | Buffer[j + 0] = Table[(x >> 18) & 63]; 174 | Buffer[j + 1] = Table[(x >> 12) & 63]; 175 | Buffer[j + 2] = '='; 176 | Buffer[j + 3] = '='; 177 | } else if (i + 2 == U.size()) { 178 | uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8); 179 | Buffer[j + 0] = Table[(x >> 18) & 63]; 180 | Buffer[j + 1] = Table[(x >> 12) & 63]; 181 | Buffer[j + 2] = Table[(x >> 6) & 63]; 182 | Buffer[j + 3] = '='; 183 | } 184 | return Buffer; 185 | } 186 | 187 | static std::mutex SymbolizeMutex; 188 | 189 | std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { 190 | std::unique_lock l(SymbolizeMutex, std::try_to_lock); 191 | if (!EF->__sanitizer_symbolize_pc || !l.owns_lock()) 192 | return ""; 193 | char PcDescr[1024] = {}; 194 | EF->__sanitizer_symbolize_pc(reinterpret_cast(PC), 195 | SymbolizedFMT, PcDescr, sizeof(PcDescr)); 196 | PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case. 197 | return PcDescr; 198 | } 199 | 200 | void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) { 201 | if (EF->__sanitizer_symbolize_pc) 202 | Printf("%s", DescribePC(SymbolizedFMT, PC).c_str()); 203 | else 204 | Printf(FallbackFMT, PC); 205 | } 206 | 207 | void PrintStackTrace() { 208 | std::unique_lock l(SymbolizeMutex, std::try_to_lock); 209 | if (EF->__sanitizer_print_stack_trace && l.owns_lock()) 210 | EF->__sanitizer_print_stack_trace(); 211 | } 212 | 213 | void PrintMemoryProfile() { 214 | std::unique_lock l(SymbolizeMutex, std::try_to_lock); 215 | if (EF->__sanitizer_print_memory_profile && l.owns_lock()) 216 | EF->__sanitizer_print_memory_profile(95, 8); 217 | } 218 | 219 | unsigned NumberOfCpuCores() { 220 | unsigned N = std::thread::hardware_concurrency(); 221 | if (!N) { 222 | Printf("WARNING: std::thread::hardware_concurrency not well defined for " 223 | "your platform. Assuming CPU count of 1.\n"); 224 | N = 1; 225 | } 226 | return N; 227 | } 228 | 229 | uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial) { 230 | uint64_t Res = Initial; 231 | const uint8_t *Bytes = static_cast(Data); 232 | for (size_t i = 0; i < Size; i++) 233 | Res = Res * 11 + Bytes[i]; 234 | return Res; 235 | } 236 | 237 | } // namespace fuzzer 238 | -------------------------------------------------------------------------------- /libfuzzer-ng/dataflow/DataFlow.cpp: -------------------------------------------------------------------------------- 1 | /*===- DataFlow.cpp - a standalone DataFlow tracer -------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // An experimental data-flow tracer for fuzz targets. 9 | // It is based on DFSan and SanitizerCoverage. 10 | // https://clang.llvm.org/docs/DataFlowSanitizer.html 11 | // https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow 12 | // 13 | // It executes the fuzz target on the given input while monitoring the 14 | // data flow for every instrumented comparison instruction. 15 | // 16 | // The output shows which functions depend on which bytes of the input, 17 | // and also provides basic-block coverage for every input. 18 | // 19 | // Build: 20 | // 1. Compile this file (DataFlow.cpp) with -fsanitize=dataflow and -O2. 21 | // 2. Compile DataFlowCallbacks.cpp with -O2 -fPIC. 22 | // 3. Build the fuzz target with -g -fsanitize=dataflow 23 | // -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp 24 | // 4. Link those together with -fsanitize=dataflow 25 | // 26 | // -fsanitize-coverage=trace-cmp inserts callbacks around every comparison 27 | // instruction, DFSan modifies the calls to pass the data flow labels. 28 | // The callbacks update the data flow label for the current function. 29 | // See e.g. __dfsw___sanitizer_cov_trace_cmp1 below. 30 | // 31 | // -fsanitize-coverage=trace-pc-guard,pc-table,bb instruments function 32 | // entries so that the comparison callback knows that current function. 33 | // -fsanitize-coverage=...,bb also allows to collect basic block coverage. 34 | // 35 | // 36 | // Run: 37 | // # Collect data flow and coverage for INPUT_FILE 38 | // # write to OUTPUT_FILE (default: stdout) 39 | // export DFSAN_OPTIONS=warn_unimplemented=0 40 | // ./a.out INPUT_FILE [OUTPUT_FILE] 41 | // 42 | // # Print all instrumented functions. llvm-symbolizer must be present in PATH 43 | // ./a.out 44 | // 45 | // Example output: 46 | // =============== 47 | // F0 11111111111111 48 | // F1 10000000000000 49 | // C0 1 2 3 4 5 50 | // C1 8 51 | // =============== 52 | // "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on. 53 | // "CN X Y Z T": tells that a function N has basic blocks X, Y, and Z covered 54 | // in addition to the function's entry block, out of T total instrumented 55 | // blocks. 56 | // 57 | //===----------------------------------------------------------------------===*/ 58 | 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | 65 | #include // backtrace_symbols_fd 66 | 67 | #include "DataFlow.h" 68 | 69 | extern "C" { 70 | extern int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); 71 | __attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); 72 | } // extern "C" 73 | 74 | CallbackData __dft; 75 | static size_t InputLen; 76 | static size_t NumIterations; 77 | static dfsan_label **FuncLabelsPerIter; // NumIterations x NumFuncs; 78 | 79 | static inline bool BlockIsEntry(size_t BlockIdx) { 80 | return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY; 81 | } 82 | 83 | const int kNumLabels = 8; 84 | 85 | // Prints all instrumented functions. 86 | static int PrintFunctions() { 87 | // We don't have the symbolizer integrated with dfsan yet. 88 | // So use backtrace_symbols_fd and pipe it through llvm-symbolizer. 89 | // TODO(kcc): this is pretty ugly and may break in lots of ways. 90 | // We'll need to make a proper in-process symbolizer work with DFSan. 91 | FILE *Pipe = popen("sed 's/(+/ /g; s/).*//g' " 92 | "| llvm-symbolizer " 93 | "| grep '\\.dfsan' " 94 | "| sed 's/\\.dfsan//g' " 95 | "| c++filt", 96 | "w"); 97 | for (size_t I = 0; I < __dft.NumGuards; I++) { 98 | uintptr_t PC = __dft.PCsBeg[I * 2]; 99 | if (!BlockIsEntry(I)) continue; 100 | void *const Buf[1] = {(void*)PC}; 101 | backtrace_symbols_fd(Buf, 1, fileno(Pipe)); 102 | } 103 | pclose(Pipe); 104 | return 0; 105 | } 106 | 107 | static void PrintBinary(FILE *Out, dfsan_label L, size_t Len) { 108 | char buf[kNumLabels + 1]; 109 | assert(Len <= kNumLabels); 110 | for (int i = 0; i < kNumLabels; i++) 111 | buf[i] = (L & (1 << i)) ? '1' : '0'; 112 | buf[Len] = 0; 113 | fprintf(Out, "%s", buf); 114 | } 115 | 116 | static void PrintDataFlow(FILE *Out) { 117 | for (size_t Func = 0; Func < __dft.NumFuncs; Func++) { 118 | bool HasAny = false; 119 | for (size_t Iter = 0; Iter < NumIterations; Iter++) 120 | if (FuncLabelsPerIter[Iter][Func]) 121 | HasAny = true; 122 | if (!HasAny) 123 | continue; 124 | fprintf(Out, "F%zd ", Func); 125 | size_t LenOfLastIteration = kNumLabels; 126 | if (auto Tail = InputLen % kNumLabels) 127 | LenOfLastIteration = Tail; 128 | for (size_t Iter = 0; Iter < NumIterations; Iter++) 129 | PrintBinary(Out, FuncLabelsPerIter[Iter][Func], 130 | Iter == NumIterations - 1 ? LenOfLastIteration : kNumLabels); 131 | fprintf(Out, "\n"); 132 | } 133 | } 134 | 135 | static void PrintCoverage(FILE *Out) { 136 | ssize_t CurrentFuncGuard = -1; 137 | ssize_t CurrentFuncNum = -1; 138 | ssize_t NumBlocksInCurrentFunc = -1; 139 | for (size_t FuncBeg = 0; FuncBeg < __dft.NumGuards;) { 140 | CurrentFuncNum++; 141 | assert(BlockIsEntry(FuncBeg)); 142 | size_t FuncEnd = FuncBeg + 1; 143 | for (; FuncEnd < __dft.NumGuards && !BlockIsEntry(FuncEnd); FuncEnd++) 144 | ; 145 | if (__dft.BBExecuted[FuncBeg]) { 146 | fprintf(Out, "C%zd", CurrentFuncNum); 147 | for (size_t I = FuncBeg + 1; I < FuncEnd; I++) 148 | if (__dft.BBExecuted[I]) 149 | fprintf(Out, " %zd", I - FuncBeg); 150 | fprintf(Out, " %zd\n", FuncEnd - FuncBeg); 151 | } 152 | FuncBeg = FuncEnd; 153 | } 154 | } 155 | 156 | int main(int argc, char **argv) { 157 | if (LLVMFuzzerInitialize) 158 | LLVMFuzzerInitialize(&argc, &argv); 159 | if (argc == 1) 160 | return PrintFunctions(); 161 | assert(argc == 2 || argc == 3); 162 | 163 | const char *Input = argv[1]; 164 | fprintf(stderr, "INFO: reading '%s'\n", Input); 165 | FILE *In = fopen(Input, "r"); 166 | assert(In); 167 | fseek(In, 0, SEEK_END); 168 | InputLen = ftell(In); 169 | fseek(In, 0, SEEK_SET); 170 | unsigned char *Buf = (unsigned char*)malloc(InputLen); 171 | size_t NumBytesRead = fread(Buf, 1, InputLen, In); 172 | assert(NumBytesRead == InputLen); 173 | fclose(In); 174 | 175 | NumIterations = (NumBytesRead + kNumLabels - 1) / kNumLabels; 176 | FuncLabelsPerIter = 177 | (dfsan_label **)calloc(NumIterations, sizeof(dfsan_label *)); 178 | for (size_t Iter = 0; Iter < NumIterations; Iter++) 179 | FuncLabelsPerIter[Iter] = 180 | (dfsan_label *)calloc(__dft.NumFuncs, sizeof(dfsan_label)); 181 | 182 | for (size_t Iter = 0; Iter < NumIterations; Iter++) { 183 | fprintf(stderr, "INFO: running '%s' %zd/%zd\n", Input, Iter, NumIterations); 184 | dfsan_flush(); 185 | dfsan_set_label(0, Buf, InputLen); 186 | __dft.FuncLabels = FuncLabelsPerIter[Iter]; 187 | 188 | size_t BaseIdx = Iter * kNumLabels; 189 | size_t LastIdx = BaseIdx + kNumLabels < NumBytesRead ? BaseIdx + kNumLabels 190 | : NumBytesRead; 191 | assert(BaseIdx < LastIdx); 192 | for (size_t Idx = BaseIdx; Idx < LastIdx; Idx++) 193 | dfsan_set_label(1 << (Idx - BaseIdx), Buf + Idx, 1); 194 | LLVMFuzzerTestOneInput(Buf, InputLen); 195 | } 196 | free(Buf); 197 | 198 | bool OutIsStdout = argc == 2; 199 | fprintf(stderr, "INFO: writing dataflow to %s\n", 200 | OutIsStdout ? "" : argv[2]); 201 | FILE *Out = OutIsStdout ? stdout : fopen(argv[2], "w"); 202 | PrintDataFlow(Out); 203 | PrintCoverage(Out); 204 | if (!OutIsStdout) fclose(Out); 205 | } 206 | -------------------------------------------------------------------------------- /agent/conveyor.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include "conveyor.h" 6 | #include 7 | #include 8 | #include "fuzz.h" 9 | 10 | 11 | static uint8_t *input; 12 | static uint8_t *input_cursor; 13 | static size_t input_len; 14 | 15 | static uint8_t *output; 16 | static uint8_t *output_cursor; 17 | static size_t *output_len; 18 | 19 | static uint8_t *last_token; 20 | static size_t bufsize; 21 | 22 | 23 | static uint8_t *zeros; 24 | 25 | void ic_setup(size_t max_input){ 26 | output = malloc(max_input); 27 | zeros = calloc(1, max_input); 28 | bufsize = max_input; 29 | } 30 | 31 | // Ingest a new input 32 | void ic_new_input(uint8_t* in, size_t len) { 33 | input = in; 34 | input_cursor = input; 35 | input_len = len; 36 | 37 | assert(output); 38 | output_cursor = output; 39 | *output_len = 0; 40 | last_token = output; 41 | } 42 | 43 | size_t ic_get_cursor(void){ 44 | return output_cursor - output; 45 | } 46 | size_t ic_get_last_token(void){ 47 | return last_token-output; 48 | } 49 | 50 | size_t ic_lookahead(uint8_t* token, size_t token_len) { 51 | size_t ret = 0; 52 | uint8_t *next_token = memmem(input_cursor, 53 | input + input_len - input_cursor, 54 | token, 55 | token_len); 56 | if(!next_token || next_token+token_len >= input+input_len) 57 | return ret; 58 | uint8_t *after_next_token = memmem(next_token+token_len, 59 | input + input_len - next_token - token_len, 60 | token, 61 | token_len); 62 | if(!after_next_token) 63 | return (input+input_len-next_token-token_len); 64 | return after_next_token - next_token - token_len; 65 | } 66 | 67 | static inline void* append(void* src, size_t len){ 68 | if(!(output_cursor && output_cursor - output + len < bufsize)){ 69 | debug_printf("append: %s", "Assert: (output_cursor && output_cursor - output + len < bufsize)\n"); 70 | abort_input(); 71 | } 72 | memcpy(output_cursor, src, len); 73 | output_cursor += len; 74 | *output_len = output_cursor - output; 75 | return output_cursor; 76 | } 77 | 78 | void* ic_insert(void* src, size_t len, size_t pos){ 79 | if(!(output_cursor && output_cursor - output + len < bufsize)) { 80 | debug_printf("ic_insert: %s", "Assert: (output_cursor && output_cursor - output + len < bufsize)\n"); 81 | abort_input(); 82 | } 83 | if(!((output_cursor - output) + len < bufsize) ) { 84 | debug_printf("ic_insert: %s", "Assert: ((output_cursor - output) + len < bufsize)\n"); 85 | abort_input(); 86 | } 87 | if(!(pos < bufsize)) { 88 | debug_printf("ic_insert: %s", "Assert: (pos < bufsize)\n"); 89 | abort_input(); 90 | } 91 | memmove(output+pos+len, output+pos, len); 92 | memcpy(output+pos, src, len); 93 | output_cursor += len; 94 | *output_len = output_cursor - output; 95 | return output_cursor; 96 | } 97 | 98 | static inline void* size_ptr(size_t len){ 99 | if (input_cursor + len > input + input_len) 100 | return NULL; 101 | input_cursor += len; 102 | return input_cursor - len; 103 | } 104 | 105 | // Return a "cannonical input": one with extraneous bytes removed, and missing 106 | // bytes inserted (where needed). 107 | void ic_output(uint8_t *out, size_t *len, size_t max_len) 108 | { 109 | output = out; 110 | output_len = len; 111 | } 112 | 113 | int ic_ingest8(uint8_t *result, uint8_t min, uint8_t max) { 114 | void *src = size_ptr(sizeof(uint8_t)); 115 | assert(max > min); 116 | if(src){ 117 | memcpy(result, src, sizeof(uint8_t)); 118 | *result = min + ((*result - min) % (max - min)); 119 | append(result, sizeof(uint8_t)); 120 | return 0; 121 | } 122 | return -1; 123 | } 124 | int ic_ingest16(uint16_t *result, uint16_t min, uint16_t max) { 125 | void *src = size_ptr(sizeof(*result)); 126 | assert(max > min); 127 | if(src){ 128 | memcpy(result, src, sizeof(*result)); 129 | *result = min + ((*result - min) % (max - min)); 130 | append(result, sizeof(*result)); 131 | return 0; 132 | } 133 | return -1; 134 | } 135 | int ic_ingest32(uint32_t *result,uint32_t min, uint32_t max, uint32_t mask) { 136 | 137 | void *src = size_ptr(sizeof(*result)); 138 | assert(max > min); 139 | if(src){ 140 | memcpy(result, src, sizeof(*result)); 141 | //*result = min + ((*result - min) % (max - min)); 142 | *result = (*result) & mask; 143 | append(result, sizeof(*result)); 144 | return 0; 145 | } 146 | return -1; 147 | } 148 | 149 | int ic_ingest64(uint64_t *result, uint64_t min, uint64_t max) { 150 | 151 | void *src = size_ptr(sizeof(*result)); 152 | assert(max > min); 153 | if(src){ 154 | memcpy(result, src, sizeof(*result)); 155 | *result = min + ((*result - min) % (max - min)); 156 | append(result, sizeof(*result)); 157 | return 0; 158 | } 159 | return -1; 160 | } 161 | 162 | uint8_t* ic_ingest_buf(size_t *len, uint8_t* token, size_t token_len, int minlen, int string) { 163 | debug_printf("INGEST: %ld %d. CURSOR: %p INPUT_END: %p\n", *len, minlen, input_cursor, input+input_len); 164 | uint8_t *result = output_cursor; 165 | uint8_t *token_position; 166 | size_t maxlen, until_token_len; 167 | maxlen = *len; 168 | size_t remaining_len = maxlen; 169 | size_t filled = 0; 170 | 171 | token_position = memmem(input_cursor, 172 | input + input_len - input_cursor, 173 | token, 174 | token_len); 175 | debug_printf("TOKEN_POSITION: %lx (%p)\n", token_position - input_cursor, token_position); 176 | if(token_position && token_position - input_cursor < maxlen) { 177 | until_token_len = token_position - input_cursor; 178 | } else if(token_position) { 179 | until_token_len = maxlen; 180 | } else if(input+input_len-input_cursor > maxlen) { 181 | until_token_len = maxlen; 182 | } else { 183 | until_token_len = input+input_len-input_cursor; 184 | } 185 | 186 | debug_printf("UNTIL_TOKEN_LEN: %ld\n", until_token_len); 187 | // First try to read data from the actual buffer (until token) 188 | uint8_t* ret = size_ptr(until_token_len); 189 | if(ret) { 190 | append(ret, until_token_len); 191 | filled += until_token_len; 192 | remaining_len -= until_token_len; 193 | } 194 | 195 | // Next, fill the rest with random data. 196 | // Cap the total len at minlen 197 | if(minlen != -1 && remaining_len + filled > minlen) { 198 | if(minlen > filled) 199 | remaining_len = minlen - filled; 200 | else 201 | remaining_len = 0; 202 | } 203 | srand(__rdtsc()); 204 | memset(zeros, 0, remaining_len); 205 | 206 | if(string) { // Fill it with random ascii 207 | for(int i=0; i= Size. 110 | size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, 111 | const std::vector &Mask); 112 | 113 | /// Applies one of the default mutations. Provided as a service 114 | /// to mutation authors. 115 | size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); 116 | 117 | /// Creates a cross-over of two pieces of Data, returns its size. 118 | size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, 119 | size_t Size2, uint8_t *Out, size_t MaxOutSize); 120 | 121 | void AddWordToManualDictionary(const Word &W); 122 | 123 | void PrintRecommendedDictionary(); 124 | 125 | void SetCrossOverWith(const Unit *U) { CrossOverWith = U; } 126 | 127 | void SetBaseII(const InputInfo *II) { OurBaseII = II; } 128 | 129 | Random &GetRand() { return Rand; } 130 | 131 | uint16_t LastChangedIdx; 132 | 133 | private: 134 | struct Mutator { 135 | size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); 136 | const char *Name; 137 | }; 138 | 139 | size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, 140 | size_t MaxSize); 141 | void TestSyscallMutateImpl(uint8_t *Data, size_t Size, 142 | size_t MaxSize); 143 | size_t SyscallMutateImpl(uint8_t *Data, size_t Size, size_t MaxSize); 144 | size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, 145 | std::vector &Mutators); 146 | 147 | size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 148 | size_t ToSize, size_t MaxToSize); 149 | size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, 150 | size_t ToSize); 151 | size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, 152 | DictionaryEntry &DE); 153 | 154 | template 155 | DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, 156 | const uint8_t *Data, size_t Size); 157 | DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2, 158 | const uint8_t *Data, size_t Size); 159 | DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2, 160 | const void *Arg1Mutation, 161 | const void *Arg2Mutation, 162 | size_t ArgSize, 163 | const uint8_t *Data, size_t Size); 164 | 165 | Random &Rand; 166 | const FuzzingOptions Options; 167 | 168 | // Dictionary provided by the user via -dict=DICT_FILE. 169 | Dictionary ManualDictionary; 170 | // Persistent dictionary modified by the fuzzer, consists of 171 | // entries that led to successful discoveries in the past mutations. 172 | Dictionary PersistentAutoDictionary; 173 | 174 | std::vector CurrentDictionaryEntrySequence; 175 | 176 | static const size_t kCmpDictionaryEntriesDequeSize = 16; 177 | DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; 178 | size_t CmpDictionaryEntriesDequeIdx = 0; 179 | 180 | const Unit *CrossOverWith = nullptr; 181 | const InputInfo *OurBaseII = nullptr; 182 | std::vector MutateInPlaceHere; 183 | std::vector MutateWithMaskTemp; 184 | // CustomCrossOver needs its own buffer as a custom implementation may call 185 | // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere. 186 | std::vector CustomCrossOverInPlaceHere; 187 | 188 | std::vector Mutators; 189 | std::vector DefaultMutators; 190 | std::vector CurrentMutatorSequence; 191 | 192 | std::vector NonDestructiveMutators; 193 | std::vector DestructiveMutators; 194 | 195 | }; 196 | 197 | } // namespace fuzzer 198 | 199 | #endif // LLVM_FUZZER_MUTATE_H 200 | --------------------------------------------------------------------------------