diff options
Diffstat (limited to 'instrumentation')
-rw-r--r-- | instrumentation/SanitizerCoverageLTO.so.cc | 29 | ||||
-rw-r--r-- | instrumentation/SanitizerCoveragePCGUARD.so.cc | 44 | ||||
-rw-r--r-- | instrumentation/afl-compiler-rt.o.c | 130 | ||||
-rw-r--r-- | instrumentation/afl-llvm-dict2file.so.cc | 7 |
4 files changed, 135 insertions, 75 deletions
diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index a09f28a9..63ea71c1 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -214,8 +214,12 @@ class ModuleSanitizerCoverageLTO void SetNoSanitizeMetadata(Instruction *I) { +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), MDNode::get(*C, None)); +#endif } @@ -225,7 +229,7 @@ class ModuleSanitizerCoverageLTO FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -416,6 +420,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); /* AFL++ START */ char *ptr; @@ -1350,7 +1355,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; - if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -1372,6 +1377,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( if (F.hasPersonalityFn() && isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; + if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif // if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName())) // return; // if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) @@ -2023,16 +2032,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); +#if LLVM_VERSION_MAJOR >= 16 + PCs.push_back(Constant::getNullValue(PtrTy)); +#else + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy)); +#endif } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 01881f28..49fe904b 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -161,7 +161,9 @@ class ModuleSanitizerCoverageAFL void SetNoSanitizeMetadata(Instruction *I) { -#if LLVM_VERSION_MAJOR >= 16 +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#elif LLVM_VERSION_MAJOR >= 16 I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt)); #else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -179,7 +181,7 @@ class ModuleSanitizerCoverageAFL FunctionCallee SanCovTraceSwitchFunction; GlobalVariable *SanCovLowestStack; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -272,13 +274,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd( if (!TargetTriple.isOSBinFormatCOFF()) return std::make_pair(SecStart, SecEnd); - // Account for the fact that on windows-msvc __start_* symbols actually - // point to a uint64_t before the start of the array. + // Account for the fact that on windows-msvc __start_* symbols actually + // point to a uint64_t before the start of the array. +#if LLVM_VERSION_MAJOR >= 19 + auto GEP = + IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t))); + return std::make_pair(GEP, SecEnd); +#else auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, ConstantInt::get(IntptrTy, sizeof(uint64_t))); return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)), SecEnd); +#endif } @@ -370,6 +378,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); LLVMContext &Ctx = M.getContext(); AFLMapPtr = @@ -572,7 +581,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( if (F.empty()) return; if (!isInInstrumentList(&F, FMNAME)) return; - if (F.getName().find(".module_ctor") != std::string::npos) + // if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -595,6 +605,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); @@ -692,16 +705,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); #if LLVM_VERSION_MAJOR >= 16 - PCs.push_back(Constant::getNullValue(IntptrPtrTy)); + PCs.push_back(Constant::getNullValue(PtrTy)); #else PCs.push_back((Constant *)IRB.CreateIntToPtr( ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); @@ -711,10 +724,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( } - auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, - SanCovPCsSectionName); + auto *PCArray = + CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName); PCArray->setInitializer( - ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); + ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs)); PCArray->setConstant(true); return PCArray; @@ -822,7 +835,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( StringRef FuncName = Callee->getName(); if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; +#if LLVM_VERSION_MAJOR >= 20 + // test canary + InstrumentationIRBuilder IRB(callInst); +#else IRBuilder<> IRB(callInst); +#endif if (!FunctionGuardArray) { diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c08e6380..0da689b2 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE; u32 __afl_dictionary_len; u64 __afl_map_addr; u32 __afl_first_final_loc; +u32 __afl_old_forkserver; #ifdef __AFL_CODE_COVERAGE typedef struct afl_module_info_t afl_module_info_t; @@ -616,7 +617,7 @@ static void __afl_map_shm(void) { fprintf(stderr, "DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, " "__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE " - "%u, __afl_final_loc %u, __afl_map_size %u", + "%u, __afl_final_loc %u, __afl_map_size %u\n", id_str == NULL ? "<null>" : id_str, __afl_area_ptr, __afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc, __afl_map_size); @@ -856,7 +857,7 @@ static void __afl_start_forkserver(void) { signal(SIGTERM, at_exit); u32 already_read_first = 0; - u32 was_killed; + u32 was_killed = 0; u32 version = 0x41464c00 + FS_NEW_VERSION_MAX; u32 tmp = version ^ 0xffffffff, status2, status = version; u8 *msg = (u8 *)&status; @@ -866,75 +867,95 @@ static void __afl_start_forkserver(void) { void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); - /* Phone home and tell the parent that we're OK. If parent isn't there, - assume we're not running in forkserver mode and just execute program. */ + if (getenv("AFL_OLD_FORKSERVER")) { - // return because possible non-forkserver usage - if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; } + __afl_old_forkserver = 1; + status = 0; - if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } - if (tmp != status2) { + if (__afl_final_loc > MAP_SIZE) { - write_error("wrong forkserver message from AFL++ tool"); - _exit(1); + fprintf(stderr, + "Warning: AFL_OLD_FORKSERVER is used with a target compiled with " + "non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - " + "this target may crash!\n"); + + } } - // send the set/requested options to forkserver - status = FS_NEW_OPT_MAPSIZE; // we always send the map size - if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } - if (__afl_dictionary_len && __afl_dictionary) { + /* Phone home and tell the parent that we're OK. If parent isn't there, + assume we're not running in forkserver mode and just execute program. */ - status |= FS_NEW_OPT_AUTODICT; + if (!__afl_old_forkserver) { - } + // return because possible non-forkserver usage + if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; } - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } + if (tmp != status2) { - // Now send the parameters for the set options, increasing by option number + write_error("wrong forkserver message from AFL++ tool"); + _exit(1); - // FS_NEW_OPT_MAPSIZE - we always send the map size - status = __afl_map_size; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } - // FS_NEW_OPT_SHDMEM_FUZZ - no data + // send the set/requested options to forkserver + status = FS_NEW_OPT_MAPSIZE; // we always send the map size + if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } + if (__afl_dictionary_len && __afl_dictionary) { - // FS_NEW_OPT_AUTODICT - send autodictionary - if (__afl_dictionary_len && __afl_dictionary) { + status |= FS_NEW_OPT_AUTODICT; - // pass the dictionary through the forkserver FD - u32 len = __afl_dictionary_len, offset = 0; + } - if (write(FORKSRV_FD + 1, &len, 4) != 4) { + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - write(2, "Error: could not send dictionary len\n", - strlen("Error: could not send dictionary len\n")); - _exit(1); + // Now send the parameters for the set options, increasing by option number - } + // FS_NEW_OPT_MAPSIZE - we always send the map size + status = __afl_map_size; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + + // FS_NEW_OPT_SHDMEM_FUZZ - no data - while (len != 0) { + // FS_NEW_OPT_AUTODICT - send autodictionary + if (__afl_dictionary_len && __afl_dictionary) { - s32 ret; - ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + // pass the dictionary through the forkserver FD + u32 len = __afl_dictionary_len, offset = 0; - if (ret < 1) { + if (write(FORKSRV_FD + 1, &len, 4) != 4) { - write_error("could not send dictionary"); + write(2, "Error: could not send dictionary len\n", + strlen("Error: could not send dictionary len\n")); _exit(1); } - len -= ret; - offset += ret; + while (len != 0) { + + s32 ret; + ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + + if (ret < 1) { + + write_error("could not send dictionary"); + _exit(1); + + } + + len -= ret; + offset += ret; + + } } - } + // send welcome message as final message + status = version; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - // send welcome message as final message - status = version; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } // END forkserver handshake @@ -948,13 +969,13 @@ static void __afl_start_forkserver(void) { /* Wait for parent by reading from the pipe. Abort if read fails. */ - if (already_read_first) { + if (unlikely(already_read_first)) { already_read_first = 0; } else { - if (read(FORKSRV_FD, &was_killed, 4) != 4) { + if (unlikely(read(FORKSRV_FD, &was_killed, 4) != 4)) { write_error("read from AFL++ tool"); _exit(1); @@ -993,10 +1014,10 @@ static void __afl_start_forkserver(void) { condition and afl-fuzz already issued SIGKILL, write off the old process. */ - if (child_stopped && was_killed) { + if (unlikely(child_stopped && was_killed)) { child_stopped = 0; - if (waitpid(child_pid, &status, 0) < 0) { + if (unlikely(waitpid(child_pid, &status, 0) < 0)) { write_error("child_stopped && was_killed"); _exit(1); @@ -1005,12 +1026,12 @@ static void __afl_start_forkserver(void) { } - if (!child_stopped) { + if (unlikely(!child_stopped)) { /* Once woken up, create a clone of our process. */ child_pid = fork(); - if (child_pid < 0) { + if (unlikely(child_pid < 0)) { write_error("fork"); _exit(1); @@ -1019,7 +1040,7 @@ static void __afl_start_forkserver(void) { /* In child process: close fds, resume execution. */ - if (!child_pid) { + if (unlikely(!child_pid)) { // just to signal afl-fuzz faster //(void)nice(-20); @@ -1044,14 +1065,15 @@ static void __afl_start_forkserver(void) { /* In parent process: write PID to pipe, then wait for child. */ - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { + if (unlikely(write(FORKSRV_FD + 1, &child_pid, 4) != 4)) { write_error("write to afl-fuzz"); _exit(1); } - if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) { + if (unlikely(waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < + 0)) { write_error("waitpid"); _exit(1); @@ -1062,11 +1084,11 @@ static void __afl_start_forkserver(void) { a successful run. In this case, we want to wake it up without forking again. */ - if (WIFSTOPPED(status)) child_stopped = 1; + if (likely(WIFSTOPPED(status))) { child_stopped = 1; } /* Relay wait status to pipe, then loop back. */ - if (write(FORKSRV_FD + 1, &status, 4) != 4) { + if (unlikely(write(FORKSRV_FD + 1, &status, 4) != 4)) { write_error("writing to afl-fuzz"); _exit(1); @@ -2704,7 +2726,7 @@ void __afl_coverage_skip() { // mark this area as especially interesting void __afl_coverage_interesting(u8 val, u32 id) { - __afl_area_ptr[id] = val; + __afl_area_ptr[id % __afl_map_size] = val; } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index b93f61f0..6559bc84 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -661,6 +661,13 @@ bool AFLdict2filePass::runOnModule(Module &M) { Value *op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast<ConstantInt>(op2); + if (!ilen) { + + op2 = callInst->getArgOperand(1); + ilen = dyn_cast<ConstantInt>(op2); + + } + if (ilen) { uint64_t literalLength = optLen; |