aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-01-25 16:11:42 +0100
committervan Hauser <vh@thc.org>2020-01-25 16:11:42 +0100
commit2c6847bfa0b57f3330b1aab9b91d935757db51b7 (patch)
tree1704704bee3fe3ce4603373f30d503c2e353ff18
parent5d2330f04e45225588a11c64b26a7dbb1a2fbe1a (diff)
downloadafl++-2c6847bfa0b57f3330b1aab9b91d935757db51b7.tar.gz
added whitelist+blacklist to all llvm_mode passes
-rw-r--r--docs/ChangeLog2
-rw-r--r--llvm_mode/LLVMInsTrim.so.cc29
-rw-r--r--llvm_mode/MarkNodes.cc19
-rw-r--r--llvm_mode/compare-transform-pass.so.cc94
-rw-r--r--llvm_mode/split-compares-pass.so.cc118
-rw-r--r--llvm_mode/split-switches-pass.so.cc113
-rwxr-xr-xtest/test.sh16
7 files changed, 343 insertions, 48 deletions
diff --git a/docs/ChangeLog b/docs/ChangeLog
index 33c6f618..c1d53379 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -27,7 +27,7 @@ Version ++2.60d (develop):
instrumentation. compile normally and set AFL_LLVM_USE_TRACE_PC :)
- afl-cmin is now a sh script (invoking awk) instead of bash for portability
the original script is still present as afl-cmin.bash
- - added blacklisted function check in all modules of llvm_mode
+ - added blacklist and whitelisting function check in all modules of llvm_mode
- added fix from Debian project to compile libdislocator and libtokencap
diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc
index 11451b43..24df6d42 100644
--- a/llvm_mode/LLVMInsTrim.so.cc
+++ b/llvm_mode/LLVMInsTrim.so.cc
@@ -144,19 +144,6 @@ struct InsTrim : public ModulePass {
// this is our default
MarkSetOpt = true;
- /* // I dont think this makes sense to port into LLVMInsTrim
- char* inst_ratio_str = getenv("AFL_INST_RATIO");
- unsigned int inst_ratio = 100;
- if (inst_ratio_str) {
-
- if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
- inst_ratio > 100) FATAL("Bad value of AFL_INST_RATIO (must be between 1
- and 100)");
-
- }
-
- */
-
LLVMContext &C = M.getContext();
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
@@ -203,8 +190,7 @@ struct InsTrim : public ModulePass {
if (instFilename.str().empty()) {
- /* If the original location is empty, try using the inlined location
- */
+ /* If the original location is empty, try using the inlined location */
DILocation *oDILoc = cDILoc->getInlinedAt();
if (oDILoc) {
@@ -432,28 +418,19 @@ struct InsTrim : public ModulePass {
IRB.CreateStore(Incr, MapPtrIdx)
->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
- /* Set prev_loc to cur_loc >> 1 */
- /*
- StoreInst *Store = IRB.CreateStore(ConstantInt::get(Int32Ty, L >> 1),
- OldPrev); Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C,
- None));
- */
-
total_instr++;
}
}
- OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n" /*", ratio
- %u%%)."*/
- ,
+ OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n",
total_instr, total_rs, total_hs,
getenv("AFL_HARDEN")
? "hardened"
: ((getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN"))
? "ASAN/MSAN"
- : "non-hardened") /*, inst_ratio*/);
+ : "non-hardened"));
return false;
}
diff --git a/llvm_mode/MarkNodes.cc b/llvm_mode/MarkNodes.cc
index 2aeeda8d..caa8cede 100644
--- a/llvm_mode/MarkNodes.cc
+++ b/llvm_mode/MarkNodes.cc
@@ -65,16 +65,11 @@ void buildCFG(Function *F) {
}
- // uint32_t FakeID = 0;
for (auto S = F->begin(), E = F->end(); S != E; ++S) {
BasicBlock *BB = &*S;
uint32_t MyID = LMap[BB];
- // if (succ_begin(BB) == succ_end(BB)) {
- // Succs[MyID].push_back(FakeID);
- // Marked.insert(MyID);
- //}
for (auto I = succ_begin(BB), E = succ_end(BB); I != E; ++I) {
Succs[MyID].push_back(LMap[*I]);
@@ -113,7 +108,7 @@ void DFStree(size_t now_id) {
}
-void turnCFGintoDAG(Function *F) {
+void turnCFGintoDAG() {
tSuccs = Succs;
tag.resize(Blocks.size());
@@ -176,7 +171,7 @@ void DFS(uint32_t now) {
}
-void DominatorTree(Function *F) {
+void DominatorTree() {
if (Blocks.empty()) return;
uint32_t s = start_point;
@@ -390,7 +385,7 @@ void MarkSubGraph(uint32_t ss, uint32_t tt) {
}
-void MarkVertice(Function *F) {
+void MarkVertice() {
uint32_t s = start_point;
@@ -411,8 +406,6 @@ void MarkVertice(Function *F) {
timeStamp = 0;
uint32_t t = 0;
- // MarkSubGraph(s, t);
- // return;
while (s != t) {
@@ -432,9 +425,9 @@ std::pair<std::vector<BasicBlock *>, std::vector<BasicBlock *> > markNodes(
reset();
labelEachBlock(F);
buildCFG(F);
- turnCFGintoDAG(F);
- DominatorTree::DominatorTree(F);
- MarkVertice(F);
+ turnCFGintoDAG();
+ DominatorTree::DominatorTree();
+ MarkVertice();
std::vector<BasicBlock *> Result, ResultAbove;
for (uint32_t x : Markabove) {
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
index 0ccce875..5d924b63 100644
--- a/llvm_mode/compare-transform-pass.so.cc
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -18,7 +18,13 @@
#include <stdlib.h>
#include <unistd.h>
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+
#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
@@ -42,6 +48,23 @@ class CompareTransform : public ModulePass {
static char ID;
CompareTransform() : ModulePass(ID) {
+ char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+ if (instWhiteListFilename) {
+
+ std::string line;
+ std::ifstream fileStream;
+ fileStream.open(instWhiteListFilename);
+ if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+ getline(fileStream, line);
+ while (fileStream) {
+
+ myWhitelist.push_back(line);
+ getline(fileStream, line);
+
+ }
+
+ }
+
}
bool runOnModule(Module &M) override;
@@ -57,6 +80,9 @@ class CompareTransform : public ModulePass {
}
+ protected:
+ std::list<std::string> myWhitelist;
+
private:
bool transformCmps(Module &M, const bool processStrcmp,
const bool processMemcmp, const bool processStrncmp,
@@ -104,6 +130,74 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
for (auto &BB : F) {
+ if (!myWhitelist.empty()) {
+
+ BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+ 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) {
+
+ DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
+
+ unsigned int instLine = cDILoc->getLine();
+ 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) {
+
+ instFilename = oDILoc->getFilename();
+ instLine = oDILoc->getLine();
+
+ }
+
+ }
+
+ (void)instLine;
+
+ /* Continue only if we know where we actually are */
+ if (!instFilename.str().empty()) {
+
+ for (std::list<std::string>::iterator it = myWhitelist.begin();
+ it != myWhitelist.end(); ++it) {
+
+ /* 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()) {
+
+ if (instFilename.str().compare(
+ instFilename.str().length() - it->length(),
+ it->length(), *it) == 0) {
+
+ instrumentBlock = true;
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Either we couldn't figure out our location or the location is
+ * not whitelisted, so we skip instrumentation. */
+ if (!instrumentBlock) continue;
+
+ }
+
for (auto &IN : BB) {
CallInst *callInst = nullptr;
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
index eeac4a55..bc25b322 100644
--- a/llvm_mode/split-compares-pass.so.cc
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -15,7 +15,17 @@
* limitations under the License.
*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+
#include "llvm/Pass.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
@@ -35,6 +45,41 @@ class SplitComparesTransform : public ModulePass {
static char ID;
SplitComparesTransform() : ModulePass(ID) {
+ char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+ if (instWhiteListFilename) {
+
+ std::string line;
+ std::ifstream fileStream;
+ fileStream.open(instWhiteListFilename);
+ if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+ getline(fileStream, line);
+ while (fileStream) {
+
+ myWhitelist.push_back(line);
+ getline(fileStream, line);
+
+ }
+
+ }
+
+ }
+
+ static bool isBlacklisted(const Function *F) {
+
+ static const SmallVector<std::string, 5> Blacklist = {
+
+ "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign."
+
+ };
+
+ for (auto const &BlacklistFunc : Blacklist) {
+
+ if (F->getName().startswith(BlacklistFunc)) { return true; }
+
+ }
+
+ return false;
+
}
bool runOnModule(Module &M) override;
@@ -49,6 +94,9 @@ class SplitComparesTransform : public ModulePass {
}
+ protected:
+ std::list<std::string> myWhitelist;
+
private:
int enableFPSplit;
@@ -77,8 +125,78 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
* all integer comparisons with >= and <= predicates to the icomps vector */
for (auto &F : M) {
+ if (isBlacklisted(&F)) continue;
+
for (auto &BB : F) {
+ if (!myWhitelist.empty()) {
+
+ bool instrumentBlock = false;
+
+ BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+ /* 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());
+
+ unsigned int instLine = cDILoc->getLine();
+ 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) {
+
+ instFilename = oDILoc->getFilename();
+ instLine = oDILoc->getLine();
+
+ }
+
+ }
+
+ (void)instLine;
+
+ /* Continue only if we know where we actually are */
+ if (!instFilename.str().empty()) {
+
+ for (std::list<std::string>::iterator it = myWhitelist.begin();
+ it != myWhitelist.end(); ++it) {
+
+ /* 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()) {
+
+ if (instFilename.str().compare(
+ instFilename.str().length() - it->length(),
+ it->length(), *it) == 0) {
+
+ instrumentBlock = true;
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Either we couldn't figure out our location or the location is
+ * not whitelisted, so we skip instrumentation. */
+ if (!instrumentBlock) continue;
+
+ }
+
for (auto &IN : BB) {
CmpInst *selectcmpInst = nullptr;
diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc
index 2743a71a..3a2838c0 100644
--- a/llvm_mode/split-switches-pass.so.cc
+++ b/llvm_mode/split-switches-pass.so.cc
@@ -18,7 +18,13 @@
#include <stdlib.h>
#include <unistd.h>
+#include <list>
+#include <string>
+#include <fstream>
+#include <sys/time.h>
+
#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
@@ -42,6 +48,41 @@ class SplitSwitchesTransform : public ModulePass {
static char ID;
SplitSwitchesTransform() : ModulePass(ID) {
+ char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST");
+ if (instWhiteListFilename) {
+
+ std::string line;
+ std::ifstream fileStream;
+ fileStream.open(instWhiteListFilename);
+ if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST");
+ getline(fileStream, line);
+ while (fileStream) {
+
+ myWhitelist.push_back(line);
+ getline(fileStream, line);
+
+ }
+
+ }
+
+ }
+
+ static bool isBlacklisted(const Function *F) {
+
+ static const SmallVector<std::string, 5> Blacklist = {
+
+ "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign."
+
+ };
+
+ for (auto const &BlacklistFunc : Blacklist) {
+
+ if (F->getName().startswith(BlacklistFunc)) { return true; }
+
+ }
+
+ return false;
+
}
bool runOnModule(Module &M) override;
@@ -71,6 +112,9 @@ class SplitSwitchesTransform : public ModulePass {
typedef std::vector<CaseExpr> CaseVector;
+ protected:
+ std::list<std::string> myWhitelist;
+
private:
bool splitSwitches(Module &M);
bool transformCmps(Module &M, const bool processStrcmp,
@@ -268,10 +312,79 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
* all switches to switches vector for later processing */
for (auto &F : M) {
+ if (isBlacklisted(&F)) continue;
+
for (auto &BB : F) {
SwitchInst *switchInst = nullptr;
+ if (!myWhitelist.empty()) {
+
+ bool instrumentBlock = false;
+ BasicBlock::iterator IP = BB.getFirstInsertionPt();
+
+ /* 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());
+
+ unsigned int instLine = cDILoc->getLine();
+ 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) {
+
+ instFilename = oDILoc->getFilename();
+ instLine = oDILoc->getLine();
+
+ }
+
+ }
+
+ (void)instLine;
+
+ /* Continue only if we know where we actually are */
+ if (!instFilename.str().empty()) {
+
+ for (std::list<std::string>::iterator it = myWhitelist.begin();
+ it != myWhitelist.end(); ++it) {
+
+ /* 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()) {
+
+ if (instFilename.str().compare(
+ instFilename.str().length() - it->length(),
+ it->length(), *it) == 0) {
+
+ instrumentBlock = true;
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Either we couldn't figure out our location or the location is
+ * not whitelisted, so we skip instrumentation. */
+ if (!instrumentBlock) continue;
+
+ }
+
if ((switchInst = dyn_cast<SwitchInst>(BB.getTerminator()))) {
if (switchInst->getNumCases() < 1) continue;
diff --git a/test/test.sh b/test/test.sh
index 93a4e008..9676d22d 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -153,10 +153,10 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
../afl-cmin -i in -o in2 -- ./test-instr.plain > /dev/null
CNT=`ls in2/ | wc -l`
case "$CNT" in
-1| *1) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
-*) $ECHO "$RED[!] afl-cmin did not correctly minimizethe number of testcases"
- CODE=1
- ;;
+ *1) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
+ *) $ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases"
+ CODE=1
+ ;;
esac
../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`
@@ -259,10 +259,10 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
../afl-cmin -i in -o in2 -- ./test-instr.plain > /dev/null
CNT=`ls in2/ | wc -l`
case "$CNT" in
-1| *1) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
-*) $ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases"
- CODE=1
- ;;
+ *1) $ECHO "$GREEN[+] afl-cmin correctly minimized the number of testcases" ;;
+ *) $ECHO "$RED[!] afl-cmin did not correctly minimize the number of testcases"
+ CODE=1
+ ;;
esac
../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`