Merge pull request #2450 from AFLplusplus/dev

push to stable
This commit is contained in:
van Hauser
2025-05-24 13:24:03 +02:00
committed by GitHub
14 changed files with 670 additions and 400 deletions

View File

@ -15,6 +15,10 @@
(thanks to @kcwu for raising the issues and providing support!) (thanks to @kcwu for raising the issues and providing support!)
- more 64 bit archicture support by @maribu - more 64 bit archicture support by @maribu
- afl-cc: - afl-cc:
- Added instrumenting hidden edges (approx 5% edges were not instrumented,
LLVM sancov overall misses 8% of edges compared to our implementation)
Note that is is currently only implemented for our PCGUARD plugin, not
LTO, CLASSIC, etc.!
- Fix to make AFL_SAN_NO_INST work with gcc_plugin - Fix to make AFL_SAN_NO_INST work with gcc_plugin
- MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation) - MacOS aflpp driver compilation fix (-fsanitize=fuzzer implementation)
- Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues - Make AFL_DUMP_MAP_SIZE work even if the target has sanitizer issues

View File

@ -869,10 +869,11 @@ Here are some of the most important caveats for AFL++:
- There is no direct support for fuzzing network services, background daemons, - There is no direct support for fuzzing network services, background daemons,
or interactive apps that require UI interaction to work. You may need to make or interactive apps that require UI interaction to work. You may need to make
simple code changes to make them behave in a more traditional way. Preeny or simple code changes to make them behave in a more traditional way. Preeny,
libdesock may offer a relatively simple option, too - see: libdesock or desockmulti may offer a relatively simple option, too - see:
[https://github.com/zardus/preeny](https://github.com/zardus/preeny) or [https://github.com/zardus/preeny](https://github.com/zardus/preeny) or
[https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock) [https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
[https://github.com/zyingp/desockmulti](https://github.com/zyingp/desockmulti)
Some useful tips for modifying network-based services can be also found at: Some useful tips for modifying network-based services can be also found at:
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop) [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)

View File

@ -1216,7 +1216,6 @@ u8 *describe_op(afl_state_t *, u8, size_t);
#endif #endif
u8 save_if_interesting(afl_state_t *, void *, u32, u8); u8 save_if_interesting(afl_state_t *, void *, u32, u8);
u8 has_new_bits(afl_state_t *, u8 *); u8 has_new_bits(afl_state_t *, u8 *);
u8 has_new_bits_unclassified(afl_state_t *, u8 *);
#ifndef AFL_SHOWMAP #ifndef AFL_SHOWMAP
void classify_counts(afl_forkserver_t *); void classify_counts(afl_forkserver_t *);
#endif #endif

View File

@ -242,6 +242,7 @@ typedef enum fsrv_run_result {
void afl_fsrv_init(afl_forkserver_t *fsrv); void afl_fsrv_init(afl_forkserver_t *fsrv);
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
void afl_fsrv_setup_preload(afl_forkserver_t *fsrv, char *argv0);
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output); volatile u8 *stop_soon_p, u8 debug_child_output);
u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,

View File

@ -333,7 +333,7 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
} else { } else {
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); } if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); }
return false; return false;
} }
@ -396,7 +396,7 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
} else { } else {
if (debug) { DEBUGF("Instrument disabled\n"); } if (debug) { DEBUGF("Instrumentation disabled\n"); }
} }

View File

@ -13,6 +13,7 @@
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
// #include "llvm/IR/Verifier.h"
#if LLVM_VERSION_MAJOR >= 15 #if LLVM_VERSION_MAJOR >= 15
#if LLVM_VERSION_MAJOR < 17 #if LLVM_VERSION_MAJOR < 17
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
@ -76,9 +77,9 @@
#else #else
#include "llvm/Transforms/Utils/Instrumentation.h" #include "llvm/Transforms/Utils/Instrumentation.h"
#endif #endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "config.h" #include "config.h"
#include "debug.h" #include "debug.h"
@ -206,7 +207,8 @@ class ModuleSanitizerCoverageAFL
SanitizerCoverageOptions Options; SanitizerCoverageOptions Options;
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0; uint32_t instr = 0, selects = 0, hidden = 0, unhandled = 0, skippedbb = 0,
dump_cc = 0;
GlobalVariable *AFLMapPtr = NULL; GlobalVariable *AFLMapPtr = NULL;
ConstantInt *One = NULL; ConstantInt *One = NULL;
ConstantInt *Zero = NULL; ConstantInt *Zero = NULL;
@ -279,7 +281,7 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
} else { } else {
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); } if (getenv("AFL_DEBUG")) { DEBUGF("Instrumentation disabled\n"); }
} }
@ -505,9 +507,16 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
getenv("AFL_USE_TSAN") ? ", TSAN" : "", getenv("AFL_USE_TSAN") ? ", TSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
char buf[32] = "";
if (skippedbb) {
snprintf(buf, sizeof(buf), " %u instrumentations saved.", skippedbb);
}
OKF("Instrumented %u locations with no collisions (%s mode) of which are " OKF("Instrumented %u locations with no collisions (%s mode) of which are "
"%u handled and %u unhandled selects.", "%u handled and %u unhandled special instructions.%s",
instr, modeline, selects, unhandled); instr, modeline, selects + hidden, unhandled, buf);
} }
@ -781,11 +790,14 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
if (AllBlocks.empty()) return false; if (AllBlocks.empty()) return false;
uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0, cnt_hidden_sel = 0,
cnt_hidden_sel_inc = 0, skip_blocks = 0;
static uint32_t first = 1; static uint32_t first = 1;
for (auto &BB : F) { for (auto &BB : F) {
bool block_is_instrumented = false;
for (auto &IN : BB) { for (auto &IN : BB) {
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
@ -799,11 +811,11 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
if (!FuncName.compare(StringRef("dlopen")) || if (!FuncName.compare(StringRef("dlopen")) ||
!FuncName.compare(StringRef("_dlopen"))) { !FuncName.compare(StringRef("_dlopen"))) {
fprintf(stderr, WARNF(
"WARNING: dlopen() detected. To have coverage for a library " "dlopen() detected. To have coverage for a library that your "
"that your target dlopen()'s this must either happen before " "target dlopen()'s this must either happen before __AFL_INIT() "
"__AFL_INIT() or you must use AFL_PRELOAD to preload all " "or you must use AFL_PRELOAD to preload all dlopen()'ed "
"dlopen()'ed libraries!\n"); "libraries!\n");
continue; continue;
} }
@ -811,53 +823,183 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
if (!FuncName.compare(StringRef("__afl_coverage_interesting"))) { if (!FuncName.compare(StringRef("__afl_coverage_interesting"))) {
cnt_cov++; cnt_cov++;
block_is_instrumented = true;
} }
} }
SelectInst *selectInst = nullptr; bool instrumentInst = false;
ICmpInst *icmp;
FCmpInst *fcmp;
if ((selectInst = dyn_cast<SelectInst>(&IN))) { if ((icmp = dyn_cast<ICmpInst>(&IN)) ||
(fcmp = dyn_cast<FCmpInst>(&IN)) || isa<SelectInst>(&IN)) {
Value *c = selectInst->getCondition(); // || isa<PHINode>(&IN)
auto t = c->getType();
if (t->getTypeID() == llvm::Type::IntegerTyID) {
cnt_sel++; bool usedInBranch = false, usedInSelectDecision = false;
cnt_sel_inc += 2;
} for (auto *U : IN.users()) {
else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { if (isa<BranchInst>(U)) {
FixedVectorType *tt = dyn_cast<FixedVectorType>(t); usedInBranch = true;
if (tt) { break;
cnt_sel++; }
cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2);
if (auto *sel = dyn_cast<SelectInst>(U)) {
if (icmp && sel->getCondition() == icmp) {
usedInSelectDecision = true;
} else if (fcmp && sel->getCondition() == fcmp) {
usedInSelectDecision = true;
}
} }
} }
if (!usedInBranch && !usedInSelectDecision) {
// errs() << "Instrument! " << *(&IN) << "\n";
instrumentInst = true;
}
} }
if (instrumentInst) {
block_is_instrumented = true;
SelectInst *selectInst;
ICmpInst *icmp;
FCmpInst *fcmp;
// PHINode *phiInst;
// errs() << "IN: " << *(&IN) << "\n";
/* if ((phiInst = dyn_cast<PHINode>(&IN))) {
cnt_hidden_sel++;
cnt_hidden_sel_inc += phiInst->getNumIncomingValues();
} else*/
if ((icmp = dyn_cast<ICmpInst>(&IN))) {
if (icmp->getType()->isIntegerTy(1)) {
cnt_sel++;
cnt_sel_inc += 2;
} else {
unhandled++;
}
} else if ((fcmp = dyn_cast<FCmpInst>(&IN))) {
if (fcmp->getType()->isIntegerTy(1)) {
cnt_sel++;
cnt_sel_inc += 2;
} else {
unhandled++;
}
} else if ((selectInst = dyn_cast<SelectInst>(&IN))) {
Value *c = selectInst->getCondition();
auto t = c->getType();
if (t->getTypeID() == llvm::Type::IntegerTyID) {
cnt_sel++;
cnt_sel_inc += 2;
} else if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
if (tt) {
cnt_sel++;
cnt_sel_inc += (tt->getElementCount().getKnownMinValue() * 2);
}
} else {
if (!be_quiet) {
WARNF("unknown select ID type: %u\n", t->getTypeID());
}
}
} /*else {
cnt_hidden_sel++;
cnt_hidden_sel_inc += 2;
}*/
}
}
if (block_is_instrumented && &BB != &BB.getParent()->getEntryBlock() &&
llvm::is_contained(AllBlocks, &BB)) {
Instruction *instr = &*BB.begin();
LLVMContext &Ctx = BB.getContext();
MDNode *md = MDNode::get(Ctx, MDString::get(Ctx, "skipinstrument"));
instr->setMetadata("tag", md);
skip_blocks++;
} }
} }
CreateFunctionLocalArrays(F, AllBlocks, first + cnt_cov + cnt_sel_inc); uint32_t xtra = 0;
if (skip_blocks < first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc) {
xtra = first + cnt_cov + cnt_sel_inc + cnt_hidden_sel_inc - skip_blocks;
}
CreateFunctionLocalArrays(F, AllBlocks, xtra);
if (!FunctionGuardArray) {
WARNF(
"SANCOV: FunctionGuardArray is NULL, failed to emit instrumentation.");
return false;
}
if (first) { first = 0; } if (first) { first = 0; }
selects += cnt_sel; selects += cnt_sel;
hidden += cnt_hidden_sel;
uint32_t special = 0, local_selects = 0, skip_next = 0; uint32_t special = 0, local_selects = 0, skip_select = 0, skip_icmp = 0;
// uint32_t skip_phi = 0;
for (auto &BB : F) { for (auto &BB : F) {
// errs() << *(&BB) << "\n";
for (auto &IN : BB) { for (auto &IN : BB) {
// errs() << *(&IN) << "\n";
CallInst *callInst = nullptr; CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) { if ((callInst = dyn_cast<CallInst>(&IN))) {
@ -875,15 +1017,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
IRBuilder<> IRB(callInst); IRBuilder<> IRB(callInst);
#endif #endif
if (!FunctionGuardArray) {
fprintf(stderr,
"SANCOV: FunctionGuardArray is NULL, failed to emit "
"instrumentation.");
continue;
}
Value *GuardPtr = IRB.CreateIntToPtr( Value *GuardPtr = IRB.CreateIntToPtr(
IRB.CreateAdd( IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
@ -897,132 +1030,324 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
} }
SelectInst *selectInst = nullptr; bool instrumentInst = false;
ICmpInst *icmp;
FCmpInst *fcmp;
if (!skip_next && (selectInst = dyn_cast<SelectInst>(&IN))) { if ((icmp = dyn_cast<ICmpInst>(&IN)) ||
(fcmp = dyn_cast<FCmpInst>(&IN)) || isa<SelectInst>(&IN)) {
uint32_t vector_cnt = 0; // || isa<PHINode>(&IN)
Value *condition = selectInst->getCondition();
Value *result;
auto t = condition->getType();
IRBuilder<> IRB(selectInst->getNextNode());
if (t->getTypeID() == llvm::Type::IntegerTyID) { bool usedInBranch = false, usedInSelectDecision = false;
if (!FunctionGuardArray) { for (auto *U : IN.users()) {
fprintf(stderr, if (isa<BranchInst>(U)) {
"SANCOV: FunctionGuardArray is NULL, failed to emit "
"instrumentation."); usedInBranch = true;
continue; break;
} }
auto GuardPtr1 = IRB.CreateIntToPtr( if (auto *sel = dyn_cast<SelectInst>(U)) {
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
auto GuardPtr2 = IRB.CreateIntToPtr( if (icmp && sel->getCondition() == icmp) {
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); usedInSelectDecision = true;
break;
} else } else if (fcmp && sel->getCondition() == fcmp) {
#if LLVM_VERSION_MAJOR >= 14 usedInSelectDecision = true;
if (t->getTypeID() == llvm::Type::FixedVectorTyID) { break;
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
if (tt) {
uint32_t elements = tt->getElementCount().getFixedValue();
vector_cnt = elements;
if (elements) {
FixedVectorType *GuardPtr1 =
FixedVectorType::get(Int32PtrTy, elements);
FixedVectorType *GuardPtr2 =
FixedVectorType::get(Int32PtrTy, elements);
Value *x, *y;
if (!FunctionGuardArray) {
fprintf(stderr,
"SANCOV: FunctionGuardArray is NULL, failed to emit "
"instrumentation.");
continue;
}
Value *val1 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0);
Value *val2 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0);
for (uint64_t i = 1; i < elements; i++) {
val1 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
AllBlocks.size()) *
4)),
Int32PtrTy);
x = IRB.CreateInsertElement(x, val1, i);
val2 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
AllBlocks.size()) *
4)),
Int32PtrTy);
y = IRB.CreateInsertElement(y, val2, i);
}
result = IRB.CreateSelect(condition, x, y);
} }
} }
} else }
if (!usedInBranch && !usedInSelectDecision) {
// errs() << "Instrument! " << *(&IN) << "\n";
instrumentInst = true;
}
}
if (instrumentInst) {
Value *result = nullptr;
uint32_t vector_cnt = 0;
SelectInst *selectInst;
// PHINode *phi = nullptr, *newPhi = nullptr;
IRBuilder<> IRB(IN.getNextNode());
if ((icmp = dyn_cast<ICmpInst>(&IN))) {
if (!icmp->getType()->isIntegerTy(1)) { continue; }
if (skip_icmp) {
skip_icmp--;
continue;
}
if (debug) {
if (DILocation *Loc = IN.getDebugLoc()) {
llvm::errs() << "DEBUG " << Loc->getFilename() << ":"
<< Loc->getLine() << ":";
std::string path =
Loc->getDirectory().str() + "/" + Loc->getFilename().str();
std::ifstream sourceFile(path);
std::string lineContent;
for (unsigned line = 1; line <= Loc->getLine(); ++line)
std::getline(sourceFile, lineContent);
llvm::errs() << lineContent << "\n";
}
errs() << *(&IN) << "\n";
}
auto res = icmp;
auto GuardPtr1 = IRB.CreateInBoundsGEP(
FunctionGuardArray->getValueType(), FunctionGuardArray,
{IRB.getInt64(0),
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
auto GuardPtr2 = IRB.CreateInBoundsGEP(
FunctionGuardArray->getValueType(), FunctionGuardArray,
{IRB.getInt64(0),
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2);
skip_select = 1;
// fprintf(stderr, "Icmp!\n");
} else if ((fcmp = dyn_cast<FCmpInst>(&IN))) {
if (!fcmp->getType()->isIntegerTy(1)) { continue; }
if (debug) {
if (DILocation *Loc = IN.getDebugLoc()) {
llvm::errs() << "DEBUG " << Loc->getFilename() << ":"
<< Loc->getLine() << ":";
std::string path =
Loc->getDirectory().str() + "/" + Loc->getFilename().str();
std::ifstream sourceFile(path);
std::string lineContent;
for (unsigned line = 1; line <= Loc->getLine(); ++line)
std::getline(sourceFile, lineContent);
llvm::errs() << lineContent << "\n";
}
errs() << *(&IN) << "\n";
}
auto res = fcmp;
auto GuardPtr1 = IRB.CreateInBoundsGEP(
FunctionGuardArray->getValueType(), FunctionGuardArray,
{IRB.getInt64(0),
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
auto GuardPtr2 = IRB.CreateInBoundsGEP(
FunctionGuardArray->getValueType(), FunctionGuardArray,
{IRB.getInt64(0),
IRB.getInt32((cnt_cov + local_selects++ + AllBlocks.size()))});
result = IRB.CreateSelect(res, GuardPtr1, GuardPtr2);
skip_select = 1;
// fprintf(stderr, "Fcmp!\n");
/*} else if ((phi = dyn_cast<PHINode>(&IN))) {
if (skip_phi) {
skip_phi = 0;
// errs() << "SKIP: " << *(&IN) << "\n";
continue;
}
// errs() << "-->PHI: " << *(&IN) << "\n";
// continue;
Instruction *insertBefore =
&*phi->getParent()->getFirstInsertionPt(); newPhi =
PHINode::Create(Int32PtrTy, 0, "", insertBefore); BasicBlock
*phiBlock = phi->getParent();
for (BasicBlock *pred : predecessors(phiBlock)) {
IRBuilder<> predBuilder(pred->getTerminator());
Value *ptr = predBuilder.CreateInBoundsGEP(
FunctionGuardArray->getValueType(), FunctionGuardArray,
ConstantInt::get(
IntptrTy, (cnt_cov + local_selects++ +
AllBlocks.size()))); newPhi->addIncoming(ptr, pred);
}
result = newPhi;
skip_phi = 1;
// fprintf(stderr, "Phi!\n");
*/
} else if ((selectInst = dyn_cast<SelectInst>(&IN))) {
if (skip_select) {
skip_select = 0;
continue;
} else {
// fprintf(stderr, "Select!\n");
}
Value *condition = selectInst->getCondition();
auto t = condition->getType();
if (t->getTypeID() == llvm::Type::IntegerTyID) {
auto GuardPtr1 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
auto GuardPtr2 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) * 4)),
Int32PtrTy);
result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2);
skip_select = 1;
} else
#if LLVM_VERSION_MAJOR >= 14
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
if (tt) {
uint32_t elements = tt->getElementCount().getFixedValue();
vector_cnt = elements;
if (elements) {
FixedVectorType *GuardPtr1 =
FixedVectorType::get(Int32PtrTy, elements);
FixedVectorType *GuardPtr2 =
FixedVectorType::get(Int32PtrTy, elements);
Value *x, *y;
Value *val1 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
AllBlocks.size()) *
4)),
Int32PtrTy);
x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0);
Value *val2 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, (cnt_cov + local_selects++ +
AllBlocks.size()) *
4)),
Int32PtrTy);
y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0);
for (uint64_t i = 1; i < elements; i++) {
val1 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) *
4)),
Int32PtrTy);
x = IRB.CreateInsertElement(x, val1, i);
val2 = IRB.CreateIntToPtr(
IRB.CreateAdd(
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(
IntptrTy,
(cnt_cov + local_selects++ + AllBlocks.size()) *
4)),
Int32PtrTy);
y = IRB.CreateInsertElement(y, val2, i);
}
result = IRB.CreateSelect(condition, x, y);
skip_select = 1;
}
}
} else
#endif #endif
{ {
// fprintf(stderr, "UNHANDLED: %u\n", t->getTypeID()); if (!be_quiet) {
unhandled++;
continue; WARNF("Warning: Unhandled ID type: %u\n", t->getTypeID());
}
unhandled++;
continue;
}
} }
uint32_t vector_cur = 0; uint32_t vector_cur = 0;
/* Load SHM pointer */ /* Load SHM pointer */
/*
if (newPhi) {
auto *inst = dyn_cast<Instruction>(result);
PHINode *nphi;
while ((nphi = dyn_cast<PHINode>(inst))) {
// fprintf(stderr, "NEXT!\n");
inst = inst->getNextNode();
}
IRB.SetInsertPoint(inst);
}
*/
LoadInst *MapPtr = LoadInst *MapPtr =
IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
@ -1073,6 +1398,7 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
auto cf = IRB.CreateICmpEQ(Incr, Zero); auto cf = IRB.CreateICmpEQ(Incr, Zero);
auto carry = IRB.CreateZExt(cf, Int8Ty); auto carry = IRB.CreateZExt(cf, Int8Ty);
Incr = IRB.CreateAdd(Incr, carry); Incr = IRB.CreateAdd(Incr, carry);
skip_icmp++;
} }
@ -1094,13 +1420,8 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
} }
skip_next = 1;
instr += vector_cnt; instr += vector_cnt;
} else {
skip_next = 0;
} }
} }
@ -1109,9 +1430,40 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
if (AllBlocks.empty() && !special && !local_selects) return false; if (AllBlocks.empty() && !special && !local_selects) return false;
if (!AllBlocks.empty()) uint32_t skipped = 0;
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); if (!AllBlocks.empty()) {
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
auto instr = AllBlocks[i]->begin();
if (instr->getMetadata("skipinstrument")) {
skipped++;
// fprintf(stderr, "Skipped!\n");
} else {
InjectCoverageAtBlock(F, *AllBlocks[i], i - skipped, IsLeafFunc);
}
}
}
skippedbb += skipped;
/*
if (verifyFunction(F, &errs())) {
errs() << "Broken function after instrumentation\n";
F.print(errs(), nullptr);
report_fatal_error("Invalid IR");
}
*/
return true; return true;

View File

@ -227,7 +227,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
if (getenv("AFL_LLVM_ONLY_FSRV")) { if (getenv("AFL_LLVM_ONLY_FSRV")) {
if (debug) { fprintf(stderr, "Instrument disabled\n"); } if (debug) { fprintf(stderr, "Instrumentation disabled\n"); }
return PreservedAnalyses::all(); return PreservedAnalyses::all();
} }
@ -235,7 +235,7 @@ bool AFLCoverage::runOnModule(Module &M) {
#else #else
if (getenv("AFL_LLVM_ONLY_FSRV")) { if (getenv("AFL_LLVM_ONLY_FSRV")) {
if (debug) { fprintf(stderr, "Instrument disabled\n"); } if (debug) { fprintf(stderr, "Instrumentation disabled\n"); }
return true; return true;
} }

View File

@ -64,6 +64,8 @@ using namespace llvm;
namespace { namespace {
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
#if LLVM_MAJOR >= 11 /* use new pass manager */ #if LLVM_MAJOR >= 11 /* use new pass manager */
class CmpLogInstructions : public PassInfoMixin<CmpLogInstructions> { class CmpLogInstructions : public PassInfoMixin<CmpLogInstructions> {
@ -92,6 +94,8 @@ class CmpLogInstructions : public ModulePass {
#else #else
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT);
#if LLVM_VERSION_MAJOR >= 4 #if LLVM_VERSION_MAJOR >= 4
StringRef getPassName() const override { StringRef getPassName() const override {
@ -106,7 +110,7 @@ class CmpLogInstructions : public ModulePass {
#endif #endif
private: private:
bool hookInstrs(Module &M); bool hookInstrs(Module &M, DomTreeCallback DTCallback);
}; };
@ -158,7 +162,16 @@ Iterator Unique(Iterator first, Iterator last) {
} }
bool CmpLogInstructions::hookInstrs(Module &M) { bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) {
if (DT->dominates(To, From)) return true;
if (auto Next = To->getUniqueSuccessor())
if (DT->dominates(Next, From)) return true;
return false;
}
bool CmpLogInstructions::hookInstrs(Module &M, DomTreeCallback DTCallback) {
std::vector<Instruction *> icomps; std::vector<Instruction *> icomps;
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
@ -296,6 +309,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
for (auto &F : M) { for (auto &F : M) {
if (!isInInstrumentList(&F, MNAME)) continue; if (!isInInstrumentList(&F, MNAME)) continue;
const DominatorTree *DT = DTCallback(F);
for (auto &BB : F) { for (auto &BB : F) {
@ -304,6 +318,12 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
CmpInst *selectcmpInst = nullptr; CmpInst *selectcmpInst = nullptr;
if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) { if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
// skip loop comparisons
if (selectcmpInst->hasOneUse())
if (auto BR = dyn_cast<BranchInst>(selectcmpInst->user_back()))
for (BasicBlock *B : BR->successors())
if (IsBackEdge(BR->getParent(), B, DT)) continue;
icomps.push_back(selectcmpInst); icomps.push_back(selectcmpInst);
} }
@ -681,11 +701,19 @@ bool CmpLogInstructions::runOnModule(Module &M) {
#endif #endif
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
return &FAM.getResult<DominatorTreeAnalysis>(F);
};
if (getenv("AFL_QUIET") == NULL) if (getenv("AFL_QUIET") == NULL)
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n"); printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
else else
be_quiet = 1; be_quiet = 1;
bool ret = hookInstrs(M);
bool ret = hookInstrs(M, DTCallback);
verifyModule(M); verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */ #if LLVM_MAJOR >= 11 /* use new pass manager */

View File

@ -75,7 +75,6 @@ static bool edges_only, /* Ignore hit counts? */
static volatile u8 stop_soon; /* Ctrl-C pressed? */ static volatile u8 stop_soon; /* Ctrl-C pressed? */
static u8 *target_path; static u8 *target_path;
static u8 frida_mode;
static u8 qemu_mode; static u8 qemu_mode;
static u8 cs_mode; static u8 cs_mode;
static u32 map_size = MAP_SIZE; static u32 map_size = MAP_SIZE;
@ -628,9 +627,7 @@ static void handle_stop_sig(int sig) {
static void set_up_environment(char **argv) { static void set_up_environment(char **argv) {
u8 *x; u8 *x;
char *afl_preload;
char *frida_afl_preload = NULL;
fsrv.dev_null_fd = open("/dev/null", O_RDWR); fsrv.dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@ -672,57 +669,7 @@ static void set_up_environment(char **argv) {
} }
set_sanitizer_defaults(); set_sanitizer_defaults();
afl_fsrv_setup_preload(&fsrv, argv[0]);
if (get_afl_env("AFL_PRELOAD")) {
if (qemu_mode) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else if (frida_mode) {
afl_preload = getenv("AFL_PRELOAD");
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
if (afl_preload) {
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
} else {
frida_afl_preload = alloc_printf("%s", frida_binary);
}
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
} else if (frida_mode) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}
if (frida_afl_preload) { ck_free(frida_afl_preload); }
} }
@ -936,10 +883,9 @@ int main(int argc, char **argv_orig, char **envp) {
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
if (frida_mode) { FATAL("Multiple -O options not supported"); } if (fsrv.frida_mode) { FATAL("Multiple -O options not supported"); }
frida_mode = 1; fsrv.frida_mode = true;
fsrv.frida_mode = frida_mode;
setenv("AFL_FRIDA_INST_SEED", "1", 1); setenv("AFL_FRIDA_INST_SEED", "1", 1);
break; break;

View File

@ -320,6 +320,38 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
} }
void afl_fsrv_setup_preload(afl_forkserver_t *fsrv, char *argv0) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
if (fsrv->qemu_mode) return;
u8 *afl_preload = getenv("AFL_PRELOAD");
u8 *preload_path = NULL;
u8 *frida_binary = NULL;
if (fsrv->frida_mode)
frida_binary = find_afl_binary(argv0, "afl-frida-trace.so");
if (afl_preload && frida_binary)
preload_path = alloc_printf("%s:%s", afl_preload, frida_binary);
else if (afl_preload)
preload_path = ck_strdup(afl_preload);
else if (frida_binary)
preload_path = ck_strdup(frida_binary);
ck_free(frida_binary);
if (preload_path) {
setenv("LD_PRELOAD", preload_path, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", preload_path, 1);
#endif
ck_free(preload_path);
}
}
/* Wrapper for select() and read(), reading a 32 bit var. /* Wrapper for select() and read(), reading a 32 bit var.
Returns the time passed to read. Returns the time passed to read.
If the wait times out, returns timeout_ms + 1; If the wait times out, returns timeout_ms + 1;

View File

@ -255,7 +255,8 @@ inline u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
* on rare cases it fall backs to the slow path: classify_counts() first, then * on rare cases it fall backs to the slow path: classify_counts() first, then
* return has_new_bits(). */ * return has_new_bits(). */
inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) { static inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map,
bool *classified) {
/* Handle the hot path first: no new coverage */ /* Handle the hot path first: no new coverage */
u8 *end = afl->fsrv.trace_bits + afl->fsrv.map_size; u8 *end = afl->fsrv.trace_bits + afl->fsrv.map_size;
@ -272,6 +273,7 @@ inline u8 has_new_bits_unclassified(afl_state_t *afl, u8 *virgin_map) {
#endif /* ^WORD_SIZE_64 */ #endif /* ^WORD_SIZE_64 */
classify_counts(&afl->fsrv); classify_counts(&afl->fsrv);
*classified = true;
return has_new_bits(afl, virgin_map); return has_new_bits(afl, virgin_map);
} }
@ -470,6 +472,46 @@ void write_crash_readme(afl_state_t *afl) {
} }
static inline void classify_if_necessary(afl_state_t *afl, bool *classified) {
if (*classified) return;
classify_counts(&afl->fsrv);
*classified = true;
}
static inline void calculate_cksum_if_necessary(afl_state_t *afl, u64 *cksum,
bool *cksumed,
bool *classified) {
if (*cksumed) return;
classify_if_necessary(afl, classified);
*cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
*cksumed = true;
}
static inline void calculate_new_bits_if_necessary(afl_state_t *afl,
u8 *new_bits,
bool *bits_counted,
bool *classified) {
if (*bits_counted) return;
if (*classified) {
*new_bits = has_new_bits(afl, afl->virgin_bits);
} else {
*new_bits = has_new_bits_unclassified(afl, afl->virgin_bits, classified);
}
*bits_counted = true;
}
/* Check if the result of an execve() during routine fuzzing is interesting, /* Check if the result of an execve() during routine fuzzing is interesting,
save or queue the input test case for further analysis if so. Returns 1 if save or queue the input test case for further analysis if so. Returns 1 if
entry is saved, 0 otherwise. */ entry is saved, 0 otherwise. */
@ -498,13 +540,15 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
u8 fn[PATH_MAX]; u8 fn[PATH_MAX];
u8 *queue_fn = ""; u8 *queue_fn = "";
u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1; u8 keeping = 0, res, is_timeout = 0;
u8 classified = 0;
u8 san_fault = 0, san_idx = 0, feed_san = 0; u8 san_fault = 0, san_idx = 0, feed_san = 0;
s32 fd; s32 fd;
u64 cksum = 0;
u32 cksum_simplified = 0, cksum_unique = 0; u32 cksum_simplified = 0, cksum_unique = 0;
bool classified = false, bits_counted = false, cksumed = false;
u8 new_bits = 0; /* valid if bits_counted is true */
u64 cksum = 0; /* valid if cksumed is true */
afl->san_case_status = 0; afl->san_case_status = 0;
/* Update path frequency. */ /* Update path frequency. */
@ -513,11 +557,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
only be used for special schedules */ only be used for special schedules */
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv); calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified);
classified = 1;
need_hash = 0;
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
/* Saturated increment */ /* Saturated increment */
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)) if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
@ -551,17 +591,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->san_binary_length) && if (unlikely(afl->san_binary_length) &&
unlikely(afl->san_abstraction == COVERAGE_INCREASE)) { unlikely(afl->san_abstraction == COVERAGE_INCREASE)) {
if (classified) { /* Check if the input increase the coverage */
calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted,
/* We could have classified the bits in SAND with COVERAGE_INCREASE */ &classified);
new_bits = has_new_bits(afl, afl->virgin_bits);
} else {
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
classified = 1;
}
if (unlikely(new_bits)) { feed_san = 1; } if (unlikely(new_bits)) { feed_san = 1; }
@ -570,15 +602,9 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
if (unlikely(afl->san_binary_length) && if (unlikely(afl->san_binary_length) &&
likely(afl->san_abstraction == UNIQUE_TRACE)) { likely(afl->san_abstraction == UNIQUE_TRACE)) {
// If schedule is not FAST..RARE, we need to classify counts here
// Note: SAND was evaluated under FAST schedule but should also work // Note: SAND was evaluated under FAST schedule but should also work
// with other scedules. // with other scedules.
if (!classified) { classify_if_necessary(afl, &classified);
classify_counts(&afl->fsrv);
classified = 1;
}
cksum_unique = cksum_unique =
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@ -638,23 +664,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
/* Keep only if there are new bits in the map, add to queue for /* Keep only if there are new bits in the map, add to queue for
future fuzzing, etc. */ future fuzzing, etc. */
if (!unlikely(afl->san_abstraction == COVERAGE_INCREASE && feed_san)) { calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified);
/* If we are in coverage increasing abstraction and have fed input to
sanitizers, we are sure it has new bits.*/
if (classified) {
/* We could have classified the bits in SAND with UNIQUE_TRACE */
new_bits = has_new_bits(afl, afl->virgin_bits);
} else {
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
classified = 1;
}
}
if (likely(!new_bits)) { if (likely(!new_bits)) {
@ -677,6 +687,11 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
save_to_queue: save_to_queue:
/* these calculations are necessary because some code flow may jump here via
goto */
calculate_cksum_if_necessary(afl, &cksum, &cksumed, &classified);
calculate_new_bits_if_necessary(afl, &new_bits, &bits_counted, &classified);
#ifndef SIMPLE_FILES #ifndef SIMPLE_FILES
if (!afl->afl_env.afl_sha1_filenames) { if (!afl->afl_env.afl_sha1_filenames) {
@ -758,6 +773,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
#endif #endif
afl->queue_top->exec_cksum = cksum;
if (new_bits == 2) { if (new_bits == 2) {
afl->queue_top->has_new_cov = 1; afl->queue_top->has_new_cov = 1;
@ -765,17 +782,8 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
} }
if (unlikely(need_hash && new_bits)) {
/* due to classify counts we have to recalculate the checksum */
afl->queue_top->exec_cksum =
hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
need_hash = 0;
}
/* For AFLFast schedules we update the new queue entry */ /* For AFLFast schedules we update the new queue entry */
if (likely(cksum)) { if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE; afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1; afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
@ -874,12 +882,9 @@ may_save_fault:
} }
new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout); new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
if (!classified) { classified = false;
bits_counted = false;
classify_counts(&afl->fsrv); cksumed = false;
classified = 1;
}
/* A corner case that one user reported bumping into: increasing the /* A corner case that one user reported bumping into: increasing the
timeout actually uncovers a crash. Make sure we don't discard it if timeout actually uncovers a crash. Make sure we don't discard it if

View File

@ -495,36 +495,41 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
afl->afl_env.afl_post_process_keep_original = 1; afl->afl_env.afl_post_process_keep_original = 1;
/* we need a dummy run if this is LTO + cmplog */ /* we need a dummy run if this is LTO + cmplog */
if (unlikely(afl->shm.cmplog_mode)) { /*
if (unlikely(afl->shm.cmplog_mode)) {
(void)write_to_testcase(afl, (void **)&use_mem, q->len, 1); (void)write_to_testcase(afl, (void **)&use_mem, q->len, 1);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, // afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */ // we want to bail out quickly.
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration;
if (!afl->non_instrumented_mode && !afl->stage_cur && }
!count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FSRV_RUN_NOINST; if (!afl->non_instrumented_mode &&
goto abort_calibration; !count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FSRV_RUN_NOINST;
goto abort_calibration;
}
#ifdef INTROSPECTION
if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; }
#endif
} }
#ifdef INTROSPECTION */
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
#endif
}
if (q->exec_cksum) { if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
hnb = has_new_bits(afl, afl->virgin_bits); hnb = has_new_bits(afl, afl->virgin_bits);
if (hnb > new_bits) { new_bits = hnb; } if (unlikely(hnb > new_bits)) { new_bits = hnb; }
} }
@ -553,7 +558,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
if (!afl->non_instrumented_mode && !afl->stage_cur && if (!afl->non_instrumented_mode &&
!count_bytes(afl, afl->fsrv.trace_bits)) { !count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FSRV_RUN_NOINST; fault = FSRV_RUN_NOINST;
@ -562,17 +567,19 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
} }
#ifdef INTROSPECTION #ifdef INTROSPECTION
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size; if (unlikely(!q->bitsmap_size)) { q->bitsmap_size = afl->bitsmap_size; }
#endif #endif
classify_counts(&afl->fsrv); classify_counts(&afl->fsrv);
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
if (q->exec_cksum != cksum) {
if (unlikely(q->exec_cksum != cksum)) {
hnb = has_new_bits(afl, afl->virgin_bits); hnb = has_new_bits(afl, afl->virgin_bits);
if (hnb > new_bits) { new_bits = hnb; }
if (q->exec_cksum) { if (unlikely(hnb > new_bits)) { new_bits = hnb; }
if (likely(q->exec_cksum)) {
u32 i; u32 i;

View File

@ -714,61 +714,8 @@ static void handle_stop_sig(int sig) {
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
char *afl_preload;
char *frida_afl_preload = NULL;
set_sanitizer_defaults(); set_sanitizer_defaults();
afl_fsrv_setup_preload(fsrv, argv[0]);
if (get_afl_env("AFL_PRELOAD")) {
if (fsrv->qemu_mode) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else if (fsrv->frida_mode) {
afl_preload = getenv("AFL_PRELOAD");
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
if (afl_preload) {
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
} else {
frida_afl_preload = alloc_printf("%s", frida_binary);
}
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
} else if (fsrv->frida_mode) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}
if (frida_afl_preload) { ck_free(frida_afl_preload); }
} }

View File

@ -899,9 +899,7 @@ static void handle_stop_sig(int sig) {
static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
u8 *x; u8 *x;
char *afl_preload;
char *frida_afl_preload = NULL;
fsrv->dev_null_fd = open("/dev/null", O_RDWR); fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@ -945,57 +943,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} }
set_sanitizer_defaults(); set_sanitizer_defaults();
afl_fsrv_setup_preload(fsrv, argv[0]);
if (get_afl_env("AFL_PRELOAD")) {
if (fsrv->qemu_mode) {
/* afl-qemu-trace takes care of converting AFL_PRELOAD. */
} else if (fsrv->frida_mode) {
afl_preload = getenv("AFL_PRELOAD");
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
if (afl_preload) {
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
} else {
frida_afl_preload = alloc_printf("%s", frida_binary);
}
ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
#endif
} else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
#endif
}
} else if (fsrv->frida_mode) {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
setenv("LD_PRELOAD", frida_binary, 1);
#ifdef __APPLE__
setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
#endif
ck_free(frida_binary);
}
if (frida_afl_preload) { ck_free(frida_afl_preload); }
} }