mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 10:23:17 +00:00
fuzz: stability of parallel fuzz testing
The fuzz targets that write a temp file currently use the same filename every time. One of the users identified that if the tests are running in parallel mode, many processes are accessing the same file. This results in unstable input to the API being tested, where the file may be overwritten as the function is being tested. This commit fixes it by putting the fuzz process PID in the filenames for the scanfile and dbload fuzz targets. Resolves: https://github.com/Cisco-Talos/clamav/issues/432 Also fixed a CMake bug that built an extra fuzz target file that doesn't serve any purpose. Resolves: https://github.com/Cisco-Talos/clamav/issues/431
This commit is contained in:
parent
0d96061e2f
commit
2d99b49797
3 changed files with 65 additions and 75 deletions
|
@ -43,7 +43,7 @@ target_sources(clamav_scanfile_fuzzer
|
|||
target_link_libraries(clamav_scanfile_fuzzer ClamAV::libclamav)
|
||||
set_target_properties(clamav_scanfile_fuzzer PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
|
||||
foreach(TARGET in ${SCAN_TARGETS})
|
||||
foreach(TARGET ${SCAN_TARGETS})
|
||||
add_executable(clamav_scanmap_${TARGET}_fuzzer)
|
||||
target_sources(clamav_scanmap_${TARGET}_fuzzer
|
||||
PRIVATE clamav_scanmap_fuzzer.cpp)
|
||||
|
@ -59,7 +59,7 @@ foreach(TARGET in ${SCAN_TARGETS})
|
|||
set_target_properties(clamav_scanfile_${TARGET}_fuzzer PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
endforeach()
|
||||
|
||||
foreach(TARGET in ${DBLOAD_TARGETS})
|
||||
foreach(TARGET ${DBLOAD_TARGETS})
|
||||
add_executable(clamav_dbload_${TARGET}_fuzzer)
|
||||
target_sources(clamav_dbload_${TARGET}_fuzzer
|
||||
PRIVATE clamav_dbload_fuzzer.cpp)
|
||||
|
|
|
@ -51,59 +51,11 @@ class ClamAVState
|
|||
cl_set_clcb_msg(clamav_message_callback);
|
||||
|
||||
cl_init(CL_INIT_DEFAULT);
|
||||
|
||||
dboptions =
|
||||
CL_DB_PHISHING | CL_DB_PHISHING_URLS |
|
||||
CL_DB_BYTECODE | CL_DB_PUA | CL_DB_ENHANCED;
|
||||
|
||||
#if defined(CLAMAV_FUZZ_CDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.cdb";
|
||||
#elif defined(CLAMAV_FUZZ_CFG)
|
||||
tmp_db_name = "dbload_tmp_fuzz.cfg";
|
||||
#elif defined(CLAMAV_FUZZ_CRB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.crb";
|
||||
#elif defined(CLAMAV_FUZZ_FP)
|
||||
tmp_db_name = "dbload_tmp_fuzz.fp";
|
||||
#elif defined(CLAMAV_FUZZ_FTM)
|
||||
tmp_db_name = "dbload_tmp_fuzz.ftm";
|
||||
#elif defined(CLAMAV_FUZZ_HDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.hdb";
|
||||
#elif defined(CLAMAV_FUZZ_HSB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.hsb";
|
||||
#elif defined(CLAMAV_FUZZ_IDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.idb";
|
||||
#elif defined(CLAMAV_FUZZ_IGN)
|
||||
tmp_db_name = "dbload_tmp_fuzz.ign";
|
||||
#elif defined(CLAMAV_FUZZ_IGN2)
|
||||
tmp_db_name = "dbload_tmp_fuzz.ign2";
|
||||
#elif defined(CLAMAV_FUZZ_LDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.ldb";
|
||||
#elif defined(CLAMAV_FUZZ_MDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.mdb";
|
||||
#elif defined(CLAMAV_FUZZ_MSB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.msb";
|
||||
#elif defined(CLAMAV_FUZZ_NDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.ndb";
|
||||
#elif defined(CLAMAV_FUZZ_PDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.pdb";
|
||||
#elif defined(CLAMAV_FUZZ_WDB)
|
||||
tmp_db_name = "dbload_tmp_fuzz.wdb";
|
||||
#elif defined(CLAMAV_FUZZ_YARA)
|
||||
tmp_db_name = "dbload_tmp_fuzz.yara";
|
||||
#else
|
||||
tmp_db_name = "dbload_tmp_fuzz";
|
||||
#endif
|
||||
}
|
||||
|
||||
~ClamAVState()
|
||||
{
|
||||
if (NULL != tmp_db_name) {
|
||||
unlink(tmp_db_name);
|
||||
}
|
||||
}
|
||||
|
||||
const char* tmp_db_name;
|
||||
unsigned int dboptions;
|
||||
};
|
||||
|
||||
// Global with static initializer to setup an engine so we don't need to do
|
||||
|
@ -113,11 +65,57 @@ ClamAVState kClamAVState;
|
|||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
cl_error_t ret;
|
||||
char tmp_file_name[200] = {0};
|
||||
unsigned int sigs = 0;
|
||||
FILE* fuzzdb = NULL;
|
||||
struct cl_engine* engine = NULL;
|
||||
unsigned int dboptions;
|
||||
|
||||
fuzzdb = fopen(kClamAVState.tmp_db_name, "w");
|
||||
__pid_t pid = getpid();
|
||||
|
||||
dboptions =
|
||||
CL_DB_PHISHING | CL_DB_PHISHING_URLS |
|
||||
CL_DB_BYTECODE | CL_DB_PUA | CL_DB_ENHANCED;
|
||||
|
||||
#if defined(CLAMAV_FUZZ_CDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.cdb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_CFG)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.cfg", pid);
|
||||
#elif defined(CLAMAV_FUZZ_CRB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.crb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_FP)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.fp", pid);
|
||||
#elif defined(CLAMAV_FUZZ_FTM)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.ftm", pid);
|
||||
#elif defined(CLAMAV_FUZZ_HDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.hdb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_HSB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.hsb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_IDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.idb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_IGN)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.ign", pid);
|
||||
#elif defined(CLAMAV_FUZZ_IGN2)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.ign2", pid);
|
||||
#elif defined(CLAMAV_FUZZ_LDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.ldb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_MDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.mdb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_MSB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.msb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_NDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.ndb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_PDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.pdb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_WDB)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.wdb", pid);
|
||||
#elif defined(CLAMAV_FUZZ_YARA)
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d.yara", pid);
|
||||
#else
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.dbload.%d", pid);
|
||||
#endif
|
||||
|
||||
fuzzdb = fopen(tmp_file_name, "w");
|
||||
fwrite(data, size, 1, fuzzdb);
|
||||
fclose(fuzzdb);
|
||||
|
||||
|
@ -125,11 +123,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|||
engine = cl_engine_new();
|
||||
|
||||
/* load the fuzzer-generated sig db */
|
||||
if (CL_SUCCESS != (ret = cl_load(
|
||||
kClamAVState.tmp_db_name,
|
||||
engine,
|
||||
&sigs,
|
||||
kClamAVState.dboptions))) {
|
||||
if (CL_SUCCESS != (ret = cl_load(tmp_file_name,
|
||||
engine,
|
||||
&sigs,
|
||||
dboptions))) {
|
||||
printf("cl_load: %s\n", cl_strerror(ret));
|
||||
goto done;
|
||||
}
|
||||
|
@ -147,5 +144,7 @@ done:
|
|||
cl_engine_free(engine);
|
||||
}
|
||||
|
||||
unlink(tmp_file_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -58,37 +58,26 @@ class ClamAVState
|
|||
memset(&scanopts, 0, sizeof(struct cl_scan_options));
|
||||
|
||||
#if defined(CLAMAV_FUZZ_ARCHIVE)
|
||||
tmp_file_name = "tmp.scanfile.archive";
|
||||
scanopts.parse |= CL_SCAN_PARSE_ARCHIVE;
|
||||
#elif defined(CLAMAV_FUZZ_MAIL)
|
||||
tmp_file_name = "tmp.scanfile.eml";
|
||||
scanopts.parse |= CL_SCAN_PARSE_MAIL;
|
||||
#elif defined(CLAMAV_FUZZ_OLE2)
|
||||
tmp_file_name = "tmp.scanfile.ole2";
|
||||
scanopts.parse |= CL_SCAN_PARSE_OLE2;
|
||||
#elif defined(CLAMAV_FUZZ_PDF)
|
||||
tmp_file_name = "tmp.scanfile.pdf";
|
||||
scanopts.parse |= CL_SCAN_PARSE_PDF;
|
||||
#elif defined(CLAMAV_FUZZ_HTML)
|
||||
tmp_file_name = "tmp.scanfile.html";
|
||||
scanopts.parse |= CL_SCAN_PARSE_HTML;
|
||||
#elif defined(CLAMAV_FUZZ_PE)
|
||||
tmp_file_name = "tmp.scanfile.pe";
|
||||
scanopts.parse |= CL_SCAN_PARSE_PE;
|
||||
#elif defined(CLAMAV_FUZZ_ELF)
|
||||
tmp_file_name = "tmp.scanfile.elf";
|
||||
scanopts.parse |= CL_SCAN_PARSE_ELF;
|
||||
#elif defined(CLAMAV_FUZZ_SWF)
|
||||
tmp_file_name = "tmp.scanfile.swf";
|
||||
scanopts.parse |= CL_SCAN_PARSE_SWF;
|
||||
#elif defined(CLAMAV_FUZZ_XMLDOCS)
|
||||
tmp_file_name = "tmp.scanfile.docx";
|
||||
scanopts.parse |= CL_SCAN_PARSE_XMLDOCS;
|
||||
#elif defined(CLAMAV_FUZZ_HWP3)
|
||||
tmp_file_name = "tmp.scanfile.hwp";
|
||||
scanopts.parse |= CL_SCAN_PARSE_HWP3;
|
||||
#else
|
||||
tmp_file_name = "tmp.scanfile";
|
||||
scanopts.parse |= ~(0);
|
||||
#endif
|
||||
scanopts.general |= CL_SCAN_GENERAL_HEURISTICS;
|
||||
|
@ -100,14 +89,9 @@ class ClamAVState
|
|||
~ClamAVState()
|
||||
{
|
||||
cl_engine_free(engine);
|
||||
|
||||
if (NULL != tmp_file_name) {
|
||||
unlink(tmp_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
struct cl_engine* engine;
|
||||
const char* tmp_file_name;
|
||||
struct cl_scan_options scanopts;
|
||||
};
|
||||
|
||||
|
@ -117,9 +101,14 @@ ClamAVState kClamAVState;
|
|||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
FILE* fuzzfile = NULL;
|
||||
FILE* fuzzfile = NULL;
|
||||
char tmp_file_name[200] = {0};
|
||||
|
||||
fuzzfile = fopen(kClamAVState.tmp_file_name, "w");
|
||||
__pid_t pid = getpid();
|
||||
|
||||
snprintf(tmp_file_name, sizeof(tmp_file_name), "tmp.scanfile.%d", pid);
|
||||
|
||||
fuzzfile = fopen(tmp_file_name, "w");
|
||||
fwrite(data, size, 1, fuzzfile);
|
||||
fclose(fuzzfile);
|
||||
|
||||
|
@ -127,11 +116,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|||
unsigned long scanned = 0;
|
||||
|
||||
cl_scanfile(
|
||||
kClamAVState.tmp_file_name,
|
||||
tmp_file_name,
|
||||
&virus_name,
|
||||
&scanned,
|
||||
kClamAVState.engine,
|
||||
&kClamAVState.scanopts);
|
||||
|
||||
unlink(tmp_file_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue