aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-05-23 17:00:02 +0200
committervan Hauser <vh@thc.org>2020-05-23 17:00:02 +0200
commit38df6eb3a9d572d13a0554f6d511723feb644be6 (patch)
treedcd5461614c851361dbb8eb1f5af65783f87353c
parent0245f8438d71b07e2a2415e8880bd4bbd70b5859 (diff)
downloadafl++-38df6eb3a9d572d13a0554f6d511723feb644be6.tar.gz
LTO whitelist functionality rewritten, now anything can be skipped
-rw-r--r--docs/Changelog.md2
-rw-r--r--llvm_mode/README.lto.md5
-rw-r--r--llvm_mode/afl-llvm-lto-instrim.so.cc11
-rw-r--r--llvm_mode/afl-llvm-lto-instrumentation.so.cc11
-rw-r--r--llvm_mode/afl-llvm-lto-whitelist.so.cc125
5 files changed, 83 insertions, 71 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 08952717..ae398b66 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -25,6 +25,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
which needs 3.8.0)
- small change to cmplog to make it work with current llvm 11-dev
- 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
the same second
- added lots of dictionaries from oss-fuzz, go-fuzz and Jakub Wilk
diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md
index 0415076a..4790c167 100644
--- a/llvm_mode/README.lto.md
+++ b/llvm_mode/README.lto.md
@@ -190,11 +190,6 @@ target will likely crash when started. This can be avoided by compiling with
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
This was originally envisioned by hexcoder- in Summer 2019, however we saw no
diff --git a/llvm_mode/afl-llvm-lto-instrim.so.cc b/llvm_mode/afl-llvm-lto-instrim.so.cc
index a7d9b756..27504e8d 100644
--- a/llvm_mode/afl-llvm-lto-instrim.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrim.so.cc
@@ -561,6 +561,17 @@ struct InsTrimLTO : public ModulePass {
if (F.size() < function_minimum_size) 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;
if (!MarkSetOpt) {
diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
index f44b336e..cbe68171 100644
--- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc
+++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc
@@ -197,6 +197,17 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (F.size() < function_minimum_size) 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;
if (autodictionary) {
diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc
index a116c4ea..8856ce21 100644
--- a/llvm_mode/afl-llvm-lto-whitelist.so.cc
+++ b/llvm_mode/afl-llvm-lto-whitelist.so.cc
@@ -122,64 +122,65 @@ bool AFLwhitelist::runOnModule(Module &M) {
for (auto &F : M) {
+ if (F.size() < 1) continue;
+ // fprintf(stderr, "F:%s\n", F.getName().str().c_str());
if (isBlacklisted(&F)) continue;
- for (auto &BB : F) {
+ BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
+ IRBuilder<> IRB(&(*IP));
- BasicBlock::iterator IP = BB.getFirstInsertionPt();
- IRBuilder<> IRB(&(*IP));
+ if (!myWhitelist.empty()) {
- 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.
- * 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());
- DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+ unsigned int instLine = cDILoc->getLine();
+ StringRef instFilename = cDILoc->getFilename();
- unsigned int instLine = cDILoc->getLine();
- StringRef instFilename = cDILoc->getFilename();
+ if (instFilename.str().empty()) {
- 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
- */
- DILocation *oDILoc = cDILoc->getInlinedAt();
- if (oDILoc) {
-
- instFilename = oDILoc->getFilename();
- instLine = oDILoc->getLine();
-
- }
+ instFilename = oDILoc->getFilename();
+ instLine = oDILoc->getLine();
}
- (void)instLine;
+ }
- /* Continue only if we know where we actually are */
- if (!instFilename.str().empty()) {
+ (void)instLine;
- for (std::list<std::string>::iterator it = myWhitelist.begin();
- it != myWhitelist.end(); ++it) {
+ if (debug)
+ 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
- * filenames might actually be full paths. Instead we
- * check that the actual filename ends in the filename
- * specified in the list. */
- if (instFilename.str().length() >= it->length()) {
+ for (std::list<std::string>::iterator it = myWhitelist.begin();
+ it != myWhitelist.end(); ++it) {
- if (instFilename.str().compare(
- instFilename.str().length() - it->length(),
- it->length(), *it) == 0) {
+ /* We don't check for filename equality here because
+ * filenames might actually be full paths. Instead we
+ * check that the actual filename ends in the filename
+ * specified in the list. */
+ if (instFilename.str().length() >= it->length()) {
- instrumentBlock = true;
- break;
+ if (instFilename.str().compare(
+ 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 ||
- F.getName().compare("start") == 0 ||
- F.getName().compare("_start") == 0 ||
- F.getName().compare("init") == 0 ||
- 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)
+ /* 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 (instrumentFunction == true) {
+ if (debug)
SAYF(cMGN "[D] " cRST "function %s is in whitelist\n",
F.getName().str().c_str());
} 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");
}