From 0cedc8014bed28e0f2ae041373d1b57271d0e6f8 Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 10:51:34 +0200 Subject: Support filename pattern matching in whitelist Allow the whitelist specified by AFL_LLVM_WHITELIST contain entries with UNIX shell-style wildcard pattern matching. --- llvm_mode/afl-llvm-common.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'llvm_mode/afl-llvm-common.cc') diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 35eabbf0..e97423a0 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -155,9 +156,8 @@ bool isInWhitelist(llvm::Function *F) { * specified in the list. */ if (instFilename.str().length() >= it->length()) { - if (instFilename.str().compare( - instFilename.str().length() - it->length(), it->length(), - *it) == 0) { + if (fnmatch((*it).c_str(), + instFilename.str().c_str(), FNM_PATHNAME) == 0) { return true; -- cgit 1.4.1 From 8316425375031cedbf7e3ea6d6b116a376f01589 Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 11:51:11 +0200 Subject: Add AFL_LLVM_WHITELIST_FNMATCH env var Only enable UNIX pattern matching on the whitelist when AFL_LLVM_WHITELIST_FNMATCH is set. The reason being that we keep backwards compatibility with old whitelists. --- llvm_mode/README.whitelist.md | 29 +++++++++++++++++++++++++++++ llvm_mode/afl-llvm-common.cc | 35 ++++++++++++++++++++++------------- src/afl-common.c | 9 +++++---- 3 files changed, 56 insertions(+), 17 deletions(-) (limited to 'llvm_mode/afl-llvm-common.cc') diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md index 72fb5d09..6752797e 100644 --- a/llvm_mode/README.whitelist.md +++ b/llvm_mode/README.whitelist.md @@ -73,3 +73,32 @@ For old LLVM versions this feature might require to be compiled with debug information (-g), however at least from llvm version 6.0 onwards this is not required anymore (and might hurt performance and crash detection, so better not use -g). + +## 4) UNIX-style file name pattern matching +By default you need to add all the files you want to whitelist to the file +specified by AFL_LLVM_WHITELIST. By setting the env variable +AFL_LLVM_WHITELIST_FNMATCH, afl++ will allows use of wildcards and other +matching features available through `fnmatch` (we use `fnmatch` with no flags +set). Note that setting AFL_LLVM_WHITELIST_FNMATCH might +break backwards-compatibility, since it does not match on the end of the file +entry anymore, but rather matches on the full filename path. + +The behavior should be the same if you prepend `*/` to every line. + +For example, the entry: +``` +*/a*.cpp +``` + +Would now match: +``` +feature_a/a1.cpp +feature_a/a2.cpp +``` + +But +``` +a*.cpp +``` + +Would not match any of the files in the previous example. diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index e97423a0..42f2b774 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -147,20 +147,25 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { + char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); + for (std::list::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 (fnmatch((*it).c_str(), - instFilename.str().c_str(), FNM_PATHNAME) == 0) { + * specified in the list. Enable UNIX-style pattern + * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + if (instFilename.str().length() >= it->length()) { + if (enable_fnmatch && fnmatch((*it).c_str(), + instFilename.str().c_str(), 0) == 0) { + return true; + } else if (!enable_fnmatch && instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { return true; - } } @@ -183,21 +188,25 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { + char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); + for (std::list::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) { + * specified in the list. Enable UNIX-style pattern + * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + if (instFilename.str().length() >= it->length()) { + if (enable_fnmatch && fnmatch((*it).c_str(), + instFilename.str().c_str(), 0) == 0) { + return true; + } else if (!enable_fnmatch && instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { return true; - } } diff --git a/src/afl-common.c b/src/afl-common.c index 1bb58a60..c17f9789 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,10 +69,11 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", - "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", - "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", - "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST" , "AFL_LLVM_WHITELIST_FNMATCH", + "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", + "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", + "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1 From 84df805ed3e14fb42f0c02420d6ae538a427fa2f Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 12:11:19 +0200 Subject: Do clang-format --- llvm_mode/afl-llvm-common.cc | 34 ++++++++++++++++++++++++---------- src/afl-common.c | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'llvm_mode/afl-llvm-common.cc') diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 42f2b774..76de1d0f 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -159,13 +159,20 @@ bool isInWhitelist(llvm::Function *F) { * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && fnmatch((*it).c_str(), - instFilename.str().c_str(), 0) == 0) { + + if (enable_fnmatch && + fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { + return true; - } else if (!enable_fnmatch && instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + + } else if (!enable_fnmatch && + + instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { + return true; + } } @@ -200,13 +207,20 @@ bool isInWhitelist(llvm::Function *F) { * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && fnmatch((*it).c_str(), - instFilename.str().c_str(), 0) == 0) { + + if (enable_fnmatch && + fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { + return true; - } else if (!enable_fnmatch && instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + + } else if (!enable_fnmatch && + + instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { + return true; + } } diff --git a/src/afl-common.c b/src/afl-common.c index c17f9789..6675564e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,7 +69,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST" , "AFL_LLVM_WHITELIST_FNMATCH", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_WHITELIST_FNMATCH", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", -- cgit 1.4.1 From 8bb0232ace731c596e9e4e083a048784e35221cd Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 15:47:34 +0200 Subject: Remove AFL_LLVM_WHITELIST_FNMATCH env variable --- llvm_mode/README.whitelist.md | 30 ++---------------------------- llvm_mode/afl-llvm-common.cc | 36 ++++++++---------------------------- src/afl-common.c | 9 ++++----- 3 files changed, 14 insertions(+), 61 deletions(-) (limited to 'llvm_mode/afl-llvm-common.cc') diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md index 12f2e5c3..6393fae8 100644 --- a/llvm_mode/README.whitelist.md +++ b/llvm_mode/README.whitelist.md @@ -75,31 +75,5 @@ required anymore (and might hurt performance and crash detection, so better not use -g). ## 4) UNIX-style filename pattern matching -By default you need to add all the files you want to whitelist to the file -specified by AFL_LLVM_WHITELIST. By setting the env variable -AFL_LLVM_WHITELIST_FNMATCH, afl++ allows use of wildcards and other -matching features available through `fnmatch` (we use `fnmatch` with no flags -set). Note that setting AFL_LLVM_WHITELIST_FNMATCH might -break backwards-compatibility with existing whitelists, since it does not match -on the end of the file entry anymore, but rather matches on the full filename -path. - -The behavior should be the same if you prepend `*/` to every line. - -For example, the entry: -``` -*/a*.cpp -``` - -Would now match: -``` -feature_a/a1.cpp -feature_a/a2.cpp -``` - -But -``` -a*.cpp -``` - -Would not match any of the files in the previous example. +You can add UNIX-style pattern matching in the whitelist entries. See `man +fnmatch` for the syntax. We do not set any of the `fnmatch` flags. diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 76de1d0f..6c7222cd 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -147,29 +147,19 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); - for (std::list::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. Enable UNIX-style pattern - * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + * specified in the list. We also allow UNIX-style pattern + * matching */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && - fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { - - return true; - - } else if (!enable_fnmatch && - - instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; @@ -195,29 +185,19 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); - for (std::list::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. Enable UNIX-style pattern - * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + * specified in the list. We also allow UNIX-style pattern + * matching */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && - fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { - - return true; - - } else if (!enable_fnmatch && - - instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; diff --git a/src/afl-common.c b/src/afl-common.c index 6675564e..1bb58a60 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,11 +69,10 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_WHITELIST_FNMATCH", - "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", - "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", - "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", - "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", + "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", + "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", + "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1