LTO whitelist functionality rewritten, now anything can be skipped

This commit is contained in:
van Hauser
2020-05-23 17:00:02 +02:00
parent 0245f8438d
commit 38df6eb3a9
5 changed files with 83 additions and 71 deletions

View File

@ -25,6 +25,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
which needs 3.8.0) which needs 3.8.0)
- small change to cmplog to make it work with current llvm 11-dev - small change to cmplog to make it work with current llvm 11-dev
- added AFL_LLVM_LAF_ALL, sets all laf-intel settings - added AFL_LLVM_LAF_ALL, sets all laf-intel settings
- LTO whitelist functionality rewritten, now main, _init etc functions
need not to be whitelisted anymore
- fixed afl-gcc/afl-as that could break on fast systems reusing pids in - fixed afl-gcc/afl-as that could break on fast systems reusing pids in
the same second the same second
- added lots of dictionaries from oss-fuzz, go-fuzz and Jakub Wilk - added lots of dictionaries from oss-fuzz, go-fuzz and Jakub Wilk

View File

@ -190,11 +190,6 @@ target will likely crash when started. This can be avoided by compiling with
This can e.g. happen with OpenSSL. This can e.g. happen with OpenSSL.
## Upcoming Work
1. Currently the LTO whitelist feature does not allow to instrument main,
start and init functions
## History ## History
This was originally envisioned by hexcoder- in Summer 2019, however we saw no This was originally envisioned by hexcoder- in Summer 2019, however we saw no

View File

@ -561,6 +561,17 @@ struct InsTrimLTO : public ModulePass {
if (F.size() < function_minimum_size) continue; if (F.size() < function_minimum_size) continue;
if (isBlacklisted(&F)) continue; if (isBlacklisted(&F)) continue;
// whitelist check
AttributeList Attrs = F.getAttributes();
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
if (debug)
fprintf(stderr, "DEBUG: Function %s is not whitelisted\n",
F.getName().str().c_str());
continue;
}
std::unordered_set<BasicBlock *> MS; std::unordered_set<BasicBlock *> MS;
if (!MarkSetOpt) { if (!MarkSetOpt) {

View File

@ -197,6 +197,17 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (F.size() < function_minimum_size) continue; if (F.size() < function_minimum_size) continue;
if (isBlacklisted(&F)) continue; if (isBlacklisted(&F)) continue;
// whitelist check
AttributeList Attrs = F.getAttributes();
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
if (debug)
fprintf(stderr, "DEBUG: Function %s is not whitelisted\n",
F.getName().str().c_str());
continue;
}
std::vector<BasicBlock *> InsBlocks; std::vector<BasicBlock *> InsBlocks;
if (autodictionary) { if (autodictionary) {

View File

@ -122,64 +122,65 @@ bool AFLwhitelist::runOnModule(Module &M) {
for (auto &F : M) { for (auto &F : M) {
if (F.size() < 1) continue;
// fprintf(stderr, "F:%s\n", F.getName().str().c_str());
if (isBlacklisted(&F)) continue; if (isBlacklisted(&F)) continue;
for (auto &BB : F) { BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
IRBuilder<> IRB(&(*IP));
BasicBlock::iterator IP = BB.getFirstInsertionPt(); if (!myWhitelist.empty()) {
IRBuilder<> IRB(&(*IP));
if (!myWhitelist.empty()) { bool instrumentFunction = false;
bool instrumentBlock = false; /* Get the current location using debug information.
* For now, just instrument the block if we are not able
* to determine our location. */
DebugLoc Loc = IP->getDebugLoc();
if (Loc) {
/* Get the current location using debug information. DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
* For now, just instrument the block if we are not able
* to determine our location. */
DebugLoc Loc = IP->getDebugLoc();
if (Loc) {
DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode()); unsigned int instLine = cDILoc->getLine();
StringRef instFilename = cDILoc->getFilename();
unsigned int instLine = cDILoc->getLine(); if (instFilename.str().empty()) {
StringRef instFilename = cDILoc->getFilename();
if (instFilename.str().empty()) { /* If the original location is empty, try using the inlined location
*/
DILocation *oDILoc = cDILoc->getInlinedAt();
if (oDILoc) {
/* If the original location is empty, try using the inlined location instFilename = oDILoc->getFilename();
*/ instLine = oDILoc->getLine();
DILocation *oDILoc = cDILoc->getInlinedAt();
if (oDILoc) {
instFilename = oDILoc->getFilename();
instLine = oDILoc->getLine();
}
} }
(void)instLine; }
/* Continue only if we know where we actually are */ (void)instLine;
if (!instFilename.str().empty()) {
for (std::list<std::string>::iterator it = myWhitelist.begin(); if (debug)
it != myWhitelist.end(); ++it) { SAYF(cMGN "[D] " cRST "function %s is in file %s\n",
F.getName().str().c_str(), instFilename.str().c_str());
/* Continue only if we know where we actually are */
if (!instFilename.str().empty()) {
/* We don't check for filename equality here because for (std::list<std::string>::iterator it = myWhitelist.begin();
* filenames might actually be full paths. Instead we it != myWhitelist.end(); ++it) {
* check that the actual filename ends in the filename
* specified in the list. */
if (instFilename.str().length() >= it->length()) {
if (instFilename.str().compare( /* We don't check for filename equality here because
instFilename.str().length() - it->length(), * filenames might actually be full paths. Instead we
it->length(), *it) == 0) { * check that the actual filename ends in the filename
* specified in the list. */
if (instFilename.str().length() >= it->length()) {
instrumentBlock = true; if (instFilename.str().compare(
break; instFilename.str().length() - it->length(), it->length(),
*it) == 0) {
} instrumentFunction = true;
break;
} }
@ -189,43 +190,35 @@ bool AFLwhitelist::runOnModule(Module &M) {
} }
/* Either we couldn't figure out our location or the location is }
* not whitelisted, so we skip instrumentation.
* We do this by renaming the function. */
if (!instrumentBlock) {
if (F.getName().compare("main") == 0 || /* Either we couldn't figure out our location or the location is
F.getName().compare("start") == 0 || * not whitelisted, so we skip instrumentation.
F.getName().compare("_start") == 0 || * We do this by renaming the function. */
F.getName().compare("init") == 0 || if (instrumentFunction == true) {
F.getName().compare("_init") == 0) {
// We do not honor be_quiet for this one
WARNF("Cannot ignore functions main/init/start");
} else {
// StringRef newName = StringRef("ign.") + F.getName();
if (debug)
SAYF(cMGN "[D] " cRST "renamed %s to ign.%s\n",
F.getName().str().c_str(), F.getName().str().c_str());
Function *_F(&F);
_F->setName("ign." + F.getName());
}
} else if (debug)
if (debug)
SAYF(cMGN "[D] " cRST "function %s is in whitelist\n", SAYF(cMGN "[D] " cRST "function %s is in whitelist\n",
F.getName().str().c_str()); F.getName().str().c_str());
} else { } else {
PFATAL("Whitelist is empty"); if (debug)
SAYF(cMGN "[D] " cRST "function %s is NOT in whitelist\n",
F.getName().str().c_str());
auto & Ctx = F.getContext();
AttributeList Attrs = F.getAttributes();
AttrBuilder NewAttrs;
NewAttrs.addAttribute("skipinstrument");
F.setAttributes(
Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
} }
break; } else {
PFATAL("Whitelist is empty");
} }