Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
Robert Swiecki committed Oct 9, 2015
1 parent 36da498 commit c8c32db
Showing 18 changed files with 464 additions and 799 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
BIN := honggfuzz
COMMON_CFLAGS := -D_GNU_SOURCE -Wall -Werror
COMMON_LDFLAGS := -lm
COMMON_SRCS := honggfuzz.c display.c log.c files.c fuzz.c report.c mangle.c util.c
COMMON_SRCS := honggfuzz.c cmdline.c display.c log.c files.c fuzz.c report.c mangle.c util.c
INTERCEPTOR_SRCS := $(wildcard interceptor/*.c)

OS ?= $(shell uname -s)
3 changes: 0 additions & 3 deletions display.c
Original file line number Diff line number Diff line change
@@ -133,8 +133,5 @@ static void display_displayLocked(honggfuzz_t * hfuzz)

extern void display_display(honggfuzz_t * hfuzz)
{
/* Don't mix up logs and display at this point */
log_mutexLock();
display_displayLocked(hfuzz);
log_mutexUnLock();
}
12 changes: 6 additions & 6 deletions docs/FeedbackDrivenFuzzing.md
Original file line number Diff line number Diff line change
@@ -13,10 +13,10 @@ Developers can provide their own initial file (-f flag) which will be gradually
# Examples #
The main fuzzing strategy is quite simple. It tries to maximize the number of perf events while mangling the file which servers as an input for fuzzing.

## Instruction counting (-LD i) ##
## Instruction counting (-LDi) ##

```
$ honggfuzz -q -LD i -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
$ honggfuzz -q -LDi -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
...
[INFO] Launched new process, pid: 21168, (5/5)
[INFO] File size (New/Best): 2789/2789, Perf feedback: Best: 1 / New: 1174343
@@ -36,12 +36,12 @@ $ honggfuzz -q -LD i -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- .

It will start with some initial file (or with no file at all), and subsequent fuzzing iterations will try to maximize the number of instructions spent on parsing it.

## Branch counting (-LD b) ##
## Branch counting (-LDb) ##

As above, it will try to maximize the number of branches taken by CPU on behalf of the fuzzed process (here: djpeg.static) while performing the fuzzing process.

```
$ honggfuzz -q -LD b -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
$ honggfuzz -q -LDb -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
...
[INFO] Launched new process, pid: 21391, (5/5)
[INFO] File size (New/Best): 2789/2789, Perf feedback: Best: 1 / New: 115586
@@ -58,11 +58,11 @@ $ honggfuzz -q -LD b -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- .
```

## Unique branch points counting (-LD p) / Unique branch pair (edges) counting (-LD e) ##
## Unique branch points counting (-LDp) / Unique branch pair (edges) counting (-LDe) ##
This is the most powerfull mode of feedback-driven counting that honggfuzz supports. It utilizes Intel's BTS (Branch Trace Store) feature to record all branch events (edges) inside the fuzzed process. Later, honggfuzz will de-duplicate those entries. The resulting number of branch pairs (edges) is good approximation of how much code of a given tool have been actively executed/used (code coverage).

```
$ honggfuzz -q -LD p -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
$ honggfuzz -q -LDp -f /usr/share/doc/texlive-doc/latex/ctable/penguin.jpg -- ./djpeg.static ___FILE___
...
[INFO] Launched new process, pid: 21715, (5/5)
[INFO] Launched new process, pid: 21719, (5/5)
112 changes: 54 additions & 58 deletions files.c
Original file line number Diff line number Diff line change
@@ -43,33 +43,32 @@ size_t files_readFileToBufMax(char *fileName, uint8_t * buf, size_t fileMaxSz)
{
int fd = open(fileName, O_RDONLY);
if (fd == -1) {
LOGMSG_P(l_ERROR, "Couldn't open '%s' for R/O", fileName);
PLOG_E("Couldn't open '%s' for R/O", fileName);
return 0UL;
}

struct stat st;
if (fstat(fd, &st) == -1) {
LOGMSG_P(l_ERROR, "Couldn't fstat(fd='%d' fileName='%s')", fd, fileName);
PLOG_E("Couldn't fstat(fd='%d' fileName='%s')", fd, fileName);
close(fd);
return 0UL;
}

if (st.st_size > (off_t) fileMaxSz) {
LOGMSG(l_ERROR, "File '%s' size to big (%zu > %" PRId64 ")", fileName, (int64_t) st.st_size,
fileMaxSz);
LOG_E("File '%s' size to big (%zu > %" PRId64 ")", fileName, (int64_t) st.st_size,
fileMaxSz);
close(fd);
return 0UL;
}

if (files_readFromFd(fd, buf, (size_t) st.st_size) == false) {
LOGMSG(l_ERROR, "Couldn't read '%s' to a buf", fileName);
LOG_E("Couldn't read '%s' to a buf", fileName);
close(fd);
return 0UL;
}
close(fd);

LOGMSG(l_DEBUG, "Read '%zu' bytes (max: '%zu') from '%s'", (size_t) st.st_size, fileMaxSz,
fileName);
LOG_D("Read '%zu' bytes (max: '%zu') from '%s'", (size_t) st.st_size, fileMaxSz, fileName);

return (size_t) st.st_size;
}
@@ -78,20 +77,19 @@ bool files_writeBufToFile(char *fileName, uint8_t * buf, size_t fileSz, int flag
{
int fd = open(fileName, flags, 0644);
if (fd == -1) {
LOGMSG_P(l_ERROR, "Couldn't open '%s' for R/O", fileName);
PLOG_E("Couldn't open '%s' for R/O", fileName);
return false;
}

if (files_writeToFd(fd, buf, fileSz) == false) {
LOGMSG_P(l_ERROR, "Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName,
fd);
PLOG_E("Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName, fd);
close(fd);
unlink(fileName);
return false;
}
close(fd);

LOGMSG(l_DEBUG, "Written '%zu' bytes to '%s'", fileSz, fileName);
LOG_D("Written '%zu' bytes to '%s'", fileSz, fileName);

return true;
}
@@ -142,7 +140,7 @@ bool files_writePatternToFd(int fd, off_t size, unsigned char p)
{
void *buf = malloc(size);
if (!buf) {
LOGMSG_P(l_WARN, "Couldn't allocate memory");
PLOG_W("Couldn't allocate memory");
return false;
}

@@ -157,27 +155,27 @@ static bool files_readdir(honggfuzz_t * hfuzz)
{
DIR *dir = opendir(hfuzz->inputFile);
if (!dir) {
LOGMSG_P(l_ERROR, "Couldn't open dir '%s'", hfuzz->inputFile);
PLOG_E("Couldn't open dir '%s'", hfuzz->inputFile);
return false;
}

int count = 0;
for (;;) {
struct dirent de, *res;
if (readdir_r(dir, &de, &res) > 0) {
LOGMSG_P(l_ERROR, "Couldn't read the '%s' dir", hfuzz->inputFile);
PLOG_E("Couldn't read the '%s' dir", hfuzz->inputFile);
closedir(dir);
return false;
}

if (res == NULL && count > 0) {
LOGMSG(l_INFO, "%d input files have been added to the list", hfuzz->fileCnt);
LOG_I("%d input files have been added to the list", hfuzz->fileCnt);
closedir(dir);
return true;
}

if (res == NULL && count == 0) {
LOGMSG(l_ERROR, "Directory '%s' doesn't contain any regular files", hfuzz->inputFile);
LOG_E("Directory '%s' doesn't contain any regular files", hfuzz->inputFile);
closedir(dir);
return false;
}
@@ -186,41 +184,40 @@ static bool files_readdir(honggfuzz_t * hfuzz)
snprintf(path, sizeof(path), "%s/%s", hfuzz->inputFile, res->d_name);
struct stat st;
if (stat(path, &st) == -1) {
LOGMSG(l_WARN, "Couldn't stat() the '%s' file", path);
LOG_W("Couldn't stat() the '%s' file", path);
continue;
}

if (!S_ISREG(st.st_mode)) {
LOGMSG(l_DEBUG, "'%s' is not a regular file, skipping", path);
LOG_D("'%s' is not a regular file, skipping", path);
continue;
}

if (st.st_size == 0ULL) {
LOGMSG(l_DEBUG, "'%s' is empty", path);
LOG_D("'%s' is empty", path);
continue;
}

if (st.st_size > (off_t) hfuzz->maxFileSz) {
LOGMSG(l_WARN,
"File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %"
PRId64, path, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
LOG_W("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %"
PRId64, path, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
continue;
}

if (!(hfuzz->files = realloc(hfuzz->files, sizeof(char *) * (count + 1)))) {
LOGMSG_P(l_ERROR, "Couldn't allocate memory");
PLOG_E("Couldn't allocate memory");
closedir(dir);
return false;
}

hfuzz->files[count] = strdup(path);
if (!hfuzz->files[count]) {
LOGMSG_P(l_ERROR, "Couldn't allocate memory");
PLOG_E("Couldn't allocate memory");
closedir(dir);
return false;
}
hfuzz->fileCnt = ++count;
LOGMSG(l_DEBUG, "Added '%s' to the list of input files", path);
LOG_D("Added '%s' to the list of input files", path);
}

abort(); /* NOTREACHED */
@@ -238,25 +235,25 @@ bool files_init(honggfuzz_t * hfuzz)
if (hfuzz->externalCommand && !hfuzz->inputFile) {
hfuzz->fileCnt = 1;
hfuzz->files[0] = "CREATED";
LOGMSG(l_INFO,
"No input file corpus specified, the external command '%s' is responsible for creating the fuzz files",
hfuzz->externalCommand);
LOG_I
("No input file corpus specified, the external command '%s' is responsible for creating the fuzz files",
hfuzz->externalCommand);
return true;
}

if (!hfuzz->files) {
LOGMSG_P(l_ERROR, "Couldn't allocate memory");
PLOG_E("Couldn't allocate memory");
return false;
}

if (!hfuzz->inputFile) {
LOGMSG(l_ERROR, "No input file/dir specified");
LOG_E("No input file/dir specified");
return false;
}

struct stat st;
if (stat(hfuzz->inputFile, &st) == -1) {
LOGMSG_P(l_ERROR, "Couldn't stat the input file/dir '%s'", hfuzz->inputFile);
PLOG_E("Couldn't stat the input file/dir '%s'", hfuzz->inputFile);
return false;
}

@@ -265,14 +262,13 @@ bool files_init(honggfuzz_t * hfuzz)
}

if (!S_ISREG(st.st_mode)) {
LOGMSG(l_ERROR, "'%s' is not a regular file, nor a directory", hfuzz->inputFile);
LOG_E("'%s' is not a regular file, nor a directory", hfuzz->inputFile);
return false;
}

if (st.st_size > (off_t) hfuzz->maxFileSz) {
LOGMSG(l_ERROR,
"File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %" PRId64,
hfuzz->inputFile, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
LOG_E("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %" PRId64,
hfuzz->inputFile, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
return false;
}

@@ -291,7 +287,7 @@ bool files_parseDictionary(honggfuzz_t * hfuzz)
{
FILE *fDict = fopen(hfuzz->dictionaryFile, "rb");
if (fDict == NULL) {
LOGMSG_P(l_ERROR, "Couldn't open '%s' - R/O mode", hfuzz->dictionaryFile);
PLOG_E("Couldn't open '%s' - R/O mode", hfuzz->dictionaryFile);
return false;
}

@@ -304,18 +300,18 @@ bool files_parseDictionary(honggfuzz_t * hfuzz)
if ((hfuzz->dictionary =
realloc(hfuzz->dictionary,
(hfuzz->dictionaryCnt + 1) * sizeof(hfuzz->dictionary[0]))) == NULL) {
LOGMSG_P(l_ERROR, "Realloc failed (sz=%zu)",
(hfuzz->dictionaryCnt + 1) * sizeof(hfuzz->dictionary[0]));
PLOG_E("Realloc failed (sz=%zu)",
(hfuzz->dictionaryCnt + 1) * sizeof(hfuzz->dictionary[0]));
fclose(fDict);
return false;
}
hfuzz->dictionary[hfuzz->dictionaryCnt] = lineptr;
LOGMSG(l_DEBUG, "Dictionary: loaded word: '%s' (len=%zu)",
hfuzz->dictionary[hfuzz->dictionaryCnt],
strlen(hfuzz->dictionary[hfuzz->dictionaryCnt]));
LOG_D("Dictionary: loaded word: '%s' (len=%zu)",
hfuzz->dictionary[hfuzz->dictionaryCnt],
strlen(hfuzz->dictionary[hfuzz->dictionaryCnt]));
hfuzz->dictionaryCnt += 1;
}
LOGMSG(l_INFO, "Loaded %zu words from the dictionary", hfuzz->dictionaryCnt);
LOG_I("Loaded %zu words from the dictionary", hfuzz->dictionaryCnt);
fclose(fDict);
return true;
}
@@ -337,7 +333,7 @@ bool files_copyFile(const char *source, const char *destination, bool * dstExist
*dstExists = true;
return false;
} else {
LOGMSG_P(l_DEBUG, "Couldn't link '%s' as '%s'", source, destination);
PLOG_D("Couldn't link '%s' as '%s'", source, destination);
/*
* Don't fail yet as we might have a running env which doesn't allow
* hardlinks (e.g. SELinux)
@@ -355,13 +351,13 @@ bool files_copyFile(const char *source, const char *destination, bool * dstExist

inFD = open(source, O_RDONLY);
if (inFD == -1) {
LOGMSG_P(l_DEBUG, "Couldn't open '%s' source", source);
PLOG_D("Couldn't open '%s' source", source);
return false;
}

struct stat inSt;
if (fstat(inFD, &inSt) == -1) {
LOGMSG_P(l_ERROR, "Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
PLOG_E("Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
close(inFD);
return false;
}
@@ -372,30 +368,30 @@ bool files_copyFile(const char *source, const char *destination, bool * dstExist
if (dstExists)
*dstExists = true;
}
LOGMSG_P(l_DEBUG, "Couldn't open '%s' destination", destination);
PLOG_D("Couldn't open '%s' destination", destination);
close(inFD);
return false;
}

uint8_t *inFileBuf = malloc(inSt.st_size);
if (!inFileBuf) {
LOGMSG_P(l_ERROR, "malloc(%zu) failed", inSt.st_size);
PLOG_E("malloc(%zu) failed", inSt.st_size);
close(inFD);
close(outFD);
return false;
}

if (files_readFromFd(inFD, inFileBuf, (size_t) inSt.st_size) == false) {
LOGMSG_P(l_ERROR, "Couldn't read '%s' to a buf", source);
PLOG_E("Couldn't read '%s' to a buf", source);
free(inFileBuf);
close(inFD);
close(outFD);
return false;
}

if (files_writeToFd(outFD, inFileBuf, inSt.st_size) == false) {
LOGMSG_P(l_ERROR, "Couldn't write '%zu' bytes to file '%s' (fd='%d')", inSt.st_size,
destination, outFD);
PLOG_E("Couldn't write '%zu' bytes to file '%s' (fd='%d')", inSt.st_size,
destination, outFD);
free(inFileBuf);
close(inFD);
close(outFD);
@@ -413,7 +409,7 @@ bool files_parseBlacklist(honggfuzz_t * hfuzz)
{
FILE *fBl = fopen(hfuzz->blacklistFile, "rb");
if (fBl == NULL) {
LOGMSG_P(l_ERROR, "Couldn't open '%s' - R/O mode", hfuzz->blacklistFile);
PLOG_E("Couldn't open '%s' - R/O mode", hfuzz->blacklistFile);
return false;
}

@@ -427,20 +423,20 @@ bool files_parseBlacklist(honggfuzz_t * hfuzz)
if ((hfuzz->blacklist =
realloc(hfuzz->blacklist,
(hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]))) == NULL) {
LOGMSG_P(l_ERROR, "realloc failed (sz=%zu)",
(hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]));
PLOG_E("realloc failed (sz=%zu)",
(hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]));
fclose(fBl);
return false;
}

hfuzz->blacklist[hfuzz->blacklistCnt] = strtoull(lineptr, 0, 16);
LOGMSG(l_DEBUG, "Blacklist: loaded '%llu'", hfuzz->blacklist[hfuzz->blacklistCnt]);
LOG_D("Blacklist: loaded %'" PRId64 "'", hfuzz->blacklist[hfuzz->blacklistCnt]);

// Verify entries are sorted so we can use interpolation search
if (hfuzz->blacklistCnt > 1) {
if (hfuzz->blacklist[hfuzz->blacklistCnt - 1] > hfuzz->blacklist[hfuzz->blacklistCnt]) {
LOGMSG(l_FATAL,
"Blacklist file not sorted. Use 'tools/createStackBlacklist.sh' to sort records");
LOG_F
("Blacklist file not sorted. Use 'tools/createStackBlacklist.sh' to sort records");
fclose(fBl);
return false;
}
@@ -449,9 +445,9 @@ bool files_parseBlacklist(honggfuzz_t * hfuzz)
}

if (hfuzz->blacklistCnt > 0) {
LOGMSG(l_INFO, "Loaded %zu stack hash(es) from the blacklist file", hfuzz->blacklistCnt);
LOG_I("Loaded %zu stack hash(es) from the blacklist file", hfuzz->blacklistCnt);
} else {
LOGMSG(l_FATAL, "Empty stack hashes blacklist file '%s'", hfuzz->blacklistFile);
LOG_F("Empty stack hashes blacklist file '%s'", hfuzz->blacklistFile);
}
fclose(fBl);
return true;
88 changes: 43 additions & 45 deletions fuzz.c
Original file line number Diff line number Diff line change
@@ -90,15 +90,15 @@ static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer,
hfuzz->maxFileSz);
if (fileSz == 0) {
MX_UNLOCK(&hfuzz->dynamicFile_mutex);
LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
LOG_E("Couldn't read '%s'", hfuzz->files[rnd_index]);
return false;
}
hfuzz->dynamicFileBestSz = fileSz;
}

if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) {
LOGMSG(l_FATAL, "Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz,
hfuzz->maxFileSz);
LOG_F("Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz,
hfuzz->maxFileSz);
}

fuzzer->dynamicFileSz = hfuzz->dynamicFileBestSz;
@@ -116,7 +116,7 @@ static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer,
if (files_writeBufToFile
(fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
O_WRONLY | O_CREAT | O_EXCL | O_TRUNC) == false) {
LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName);
return false;
}

@@ -128,7 +128,7 @@ static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_ind
size_t fileSz =
files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
if (fileSz == 0UL) {
LOGMSG(l_ERROR, "Couldn't read contents of '%s'", hfuzz->files[rnd_index]);
LOG_E("Couldn't read contents of '%s'", hfuzz->files[rnd_index]);
return false;
}

@@ -137,7 +137,7 @@ static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_ind

if (files_writeBufToFile
(fuzzer->fileName, fuzzer->dynamicFile, fileSz, O_WRONLY | O_CREAT | O_EXCL) == false) {
LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName);
return false;
}

@@ -148,17 +148,17 @@ static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, i
{
int dstfd = open(fuzzer->fileName, O_CREAT | O_EXCL | O_RDWR, 0644);
if (dstfd == -1) {
LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s'", fuzzer->fileName);
PLOG_E("Couldn't create a temporary file '%s'", fuzzer->fileName);
return false;
}

LOGMSG(l_DEBUG, "Created '%f' as an input file", fuzzer->fileName);
LOG_D("Created '%s' as an input file", fuzzer->fileName);

if (hfuzz->inputFile) {
size_t fileSz =
files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
if (fileSz == 0UL) {
LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
LOG_E("Couldn't read '%s'", hfuzz->files[rnd_index]);
unlink(fuzzer->fileName);
return false;
}
@@ -174,7 +174,7 @@ static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, i

pid_t pid = fork();
if (pid == -1) {
LOGMSG_P(l_ERROR, "Couldn't fork");
PLOG_E("Couldn't fork");
return false;
}

@@ -183,7 +183,7 @@ static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, i
* child performs the external file modifications
*/
execl(hfuzz->externalCommand, hfuzz->externalCommand, fuzzer->fileName, NULL);
LOGMSG_P(l_FATAL, "Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName);
PLOG_F("Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName);
return false;
}

@@ -197,14 +197,14 @@ static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, i
#endif /* defined(__WNOTHREAD) */
while (wait4(pid, &childStatus, flags, NULL) != pid) ;
if (WIFEXITED(childStatus)) {
LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus));
LOG_D("External command exited with status %d", WEXITSTATUS(childStatus));
return true;
}
if (WIFSIGNALED(childStatus)) {
LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus));
LOG_E("External command terminated with signal %d", WTERMSIG(childStatus));
return false;
}
LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus);
LOG_F("External command terminated abnormally, status: %d", childStatus);
return false;

abort(); /* NOTREACHED */
@@ -231,7 +231,7 @@ static void fuzz_fuzzLoop(honggfuzz_t * hfuzz)
.report = {'\0'}
};
if (fuzzer.dynamicFile == NULL) {
LOGMSG(l_FATAL, "malloc(%zu) failed", hfuzz->maxFileSz);
LOG_F("malloc(%zu) failed", hfuzz->maxFileSz);
}

int rnd_index = util_rndGet(0, hfuzz->fileCnt - 1);
@@ -254,7 +254,7 @@ static void fuzz_fuzzLoop(honggfuzz_t * hfuzz)

fuzzer.pid = arch_fork(hfuzz);
if (fuzzer.pid == -1) {
LOGMSG_P(l_FATAL, "Couldn't fork");
PLOG_F("Couldn't fork");
exit(EXIT_FAILURE);
}

@@ -263,26 +263,25 @@ static void fuzz_fuzzLoop(honggfuzz_t * hfuzz)
* Ok, kill the parent if this fails
*/
if (!arch_launchChild(hfuzz, fuzzer.fileName)) {
LOGMSG(l_ERROR, "Error launching child process, killing parent");
LOG_E("Error launching child process, killing parent");
exit(EXIT_FAILURE);
}
}

LOGMSG(l_DEBUG, "Launched new process, pid: %d, (concurrency: %d)", fuzzer.pid,
hfuzz->threadsMax);
LOG_D("Launched new process, pid: %d, (concurrency: %zd)", fuzzer.pid, hfuzz->threadsMax);

arch_reapChild(hfuzz, &fuzzer);
unlink(fuzzer.fileName);

if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
LOGMSG(l_DEBUG,
"File size (New/Best): %zu/%zu, Perf feedback (instr/branch/block/block-edge/custom): Best: [%"
PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "] / New: [%" PRIu64 ",%"
PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]", fuzzer.dynamicFileSz,
hfuzz->dynamicFileBestSz, hfuzz->hwCnts.cpuInstrCnt, hfuzz->hwCnts.cpuBranchCnt,
hfuzz->hwCnts.pcCnt, hfuzz->hwCnts.pathCnt, hfuzz->hwCnts.customCnt,
fuzzer.hwCnts.cpuInstrCnt, fuzzer.hwCnts.cpuBranchCnt, fuzzer.hwCnts.pcCnt,
fuzzer.hwCnts.pathCnt, fuzzer.hwCnts.customCnt);
LOG_D
("File size (New/Best): %zu/%zu, Perf feedback (instr/branch/block/block-edge/custom): Best: [%"
PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "] / New: [%" PRIu64 ",%" PRIu64
",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "]", fuzzer.dynamicFileSz,
hfuzz->dynamicFileBestSz, hfuzz->hwCnts.cpuInstrCnt, hfuzz->hwCnts.cpuBranchCnt,
hfuzz->hwCnts.pcCnt, hfuzz->hwCnts.pathCnt, hfuzz->hwCnts.customCnt,
fuzzer.hwCnts.cpuInstrCnt, fuzzer.hwCnts.cpuBranchCnt, fuzzer.hwCnts.pcCnt,
fuzzer.hwCnts.pathCnt, fuzzer.hwCnts.customCnt);

MX_LOCK(&hfuzz->dynamicFile_mutex);

@@ -294,14 +293,13 @@ static void fuzz_fuzzLoop(honggfuzz_t * hfuzz)

if (diff0 <= 0 && diff1 <= 0 && diff2 <= 0 && diff3 <= 0 && diff4 <= 0) {

LOGMSG(l_INFO,
"New: (Size New,Old): %zu,%zu, Perf (Cur,New): %"
PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ",%" PRId64 "/%" PRId64
"/%" PRId64 "/%" PRId64 "/%" PRId64, fuzzer.dynamicFileSz,
hfuzz->dynamicFileBestSz, hfuzz->hwCnts.cpuInstrCnt, hfuzz->hwCnts.cpuBranchCnt,
hfuzz->hwCnts.pcCnt, hfuzz->hwCnts.pathCnt, hfuzz->hwCnts.customCnt,
fuzzer.hwCnts.cpuInstrCnt, fuzzer.hwCnts.cpuBranchCnt, fuzzer.hwCnts.pcCnt,
fuzzer.hwCnts.pathCnt, fuzzer.hwCnts.customCnt);
LOG_I("New: (Size New,Old): %zu,%zu, Perf (Cur,New): %"
PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ",%" PRId64 "/%" PRId64
"/%" PRId64 "/%" PRId64 "/%" PRId64, fuzzer.dynamicFileSz,
hfuzz->dynamicFileBestSz, hfuzz->hwCnts.cpuInstrCnt, hfuzz->hwCnts.cpuBranchCnt,
hfuzz->hwCnts.pcCnt, hfuzz->hwCnts.pathCnt, hfuzz->hwCnts.customCnt,
fuzzer.hwCnts.cpuInstrCnt, fuzzer.hwCnts.cpuBranchCnt, fuzzer.hwCnts.pcCnt,
fuzzer.hwCnts.pathCnt, fuzzer.hwCnts.customCnt);

memcpy(hfuzz->dynamicFileBest, fuzzer.dynamicFile, fuzzer.dynamicFileSz);

@@ -357,7 +355,7 @@ static void fuzz_runThread(honggfuzz_t * hfuzz, void *(*thread) (void *))

pthread_t t;
if (pthread_create(&t, &attr, thread, (void *)hfuzz) < 0) {
LOGMSG_P(l_FATAL, "Couldn't create a new thread");
PLOG_F("Couldn't create a new thread");
}

return;
@@ -370,7 +368,7 @@ bool fuzz_setupTimer(void)
.it_interval = {.tv_sec = 1,.tv_usec = 0},
};
if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
LOGMSG_P(l_ERROR, "setitimer(ITIMER_REAL)");
PLOG_E("setitimer(ITIMER_REAL)");
return false;
}
return true;
@@ -386,23 +384,23 @@ void fuzz_main(honggfuzz_t * hfuzz)
};
sigemptyset(&sa.sa_mask);
if (sigaction(SIGTERM, &sa, NULL) == -1) {
LOGMSG_P(l_FATAL, "sigaction(SIGTERM) failed");
PLOG_F("sigaction(SIGTERM) failed");
}
if (sigaction(SIGINT, &sa, NULL) == -1) {
LOGMSG_P(l_FATAL, "sigaction(SIGINT) failed");
PLOG_F("sigaction(SIGINT) failed");
}
if (sigaction(SIGQUIT, &sa, NULL) == -1) {
LOGMSG_P(l_FATAL, "sigaction(SIGQUIT) failed");
PLOG_F("sigaction(SIGQUIT) failed");
}
if (sigaction(SIGALRM, &sa, NULL) == -1) {
LOGMSG_P(l_FATAL, "sigaction(SIGALRM) failed");
PLOG_F("sigaction(SIGALRM) failed");
}
if (fuzz_setupTimer() == false) {
LOGMSG(l_FATAL, "fuzz_setupTimer()");
LOG_F("fuzz_setupTimer()");
}

if (!arch_archInit(hfuzz)) {
LOGMSG(l_FATAL, "Couldn't prepare arch for fuzzing");
LOG_F("Couldn't prepare arch for fuzzing");
}

for (size_t i = 0; i < hfuzz->threadsMax; i++) {
@@ -423,8 +421,8 @@ void fuzz_main(honggfuzz_t * hfuzz)
}

if (fuzz_sigReceived > 0) {
LOGMSG(l_INFO, "Signal %d (%s) received, terminating", fuzz_sigReceived,
strsignal(fuzz_sigReceived));
LOG_I("Signal %d (%s) received, terminating", fuzz_sigReceived,
strsignal(fuzz_sigReceived));
}

free(hfuzz->files);
330 changes: 8 additions & 322 deletions honggfuzz.c
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
*
*/

#include <inttypes.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,345 +32,30 @@
#include <unistd.h>

#include "common.h"
#include "cmdline.h"
#include "log.h"
#include "files.h"
#include "fuzz.h"
#include "util.h"

#define AB ANSI_BOLD
#define AC ANSI_CLEAR
#define ANSI_BOLD "\033[1m"
#define ANSI_CLEAR "\033[0m"

static bool checkFor_FILE_PLACEHOLDER(char **args)
{
for (int x = 0; args[x]; x++) {
if (strstr(args[x], _HF_FILE_PLACEHOLDER))
return true;
}
return false;
}

static void usage(bool exit_success)
{
/* *INDENT-OFF* */
printf(AB PROG_NAME " version " PROG_VERSION " by " PROG_AUTHORS AC "\n");
printf("%s",
" [" AB "-f val" AC "] : Input file corpus directory\n"
" (or a path to a single input file)\n"
" [" AB "-h" AC "] : This help\n"
" [" AB "-q" AC "] : Null-ify children's stdin, stdout, stderr; make them quiet\n"
" [" AB "-s" AC "] : Provide fuzzing input on STDIN, instead of ___FILE___\n"
" [" AB "-u" AC "] : Save all test-cases (not only the unique ones) by appending\n"
" the current time-stamp to the filenames\n"
" [" AB "-v" AC "] : Disable ANSI console; use simple log output\n"
" [" AB "-d val" AC "] : Debug level (0 - FATAL ... 4 - DEBUG), (default: '" AB "3" AC
"' [INFO])\n"
" [" AB "-e val" AC "] : File extension (e.g. 'swf'), (default: '" AB "fuzz" AC "')\n"
" [" AB "-W val" AC "] : Workspace directory to save crashes & runtime files\n"
" (default: current '.')\n"
" [" AB "-r val" AC "] : Maximal flip rate, (default: '" AB "0.001" AC "')\n"
" [" AB "-w val" AC "] : Wordlist file (tokens delimited by NUL-bytes)\n"
" [" AB "-B val" AC "] : Stackhashes blacklist file (one entry per line)\n"
" [" AB "-c val" AC "] : Rxternal command modifying the input corpus of files,\n"
" instead of -r/-m (default: " AB "none" AC ")\n"
" [" AB "-t val" AC "] : Timeout (in secs), (default: '" AB "3" AC "') [0 - no timeout]\n"
" [" AB "-a val" AC "] : Address limit (from si.si_addr) below which crashes\n"
" are not reported, (default: '" AB "0" AC "') [suggested: 65535]\n"
" [" AB "-n val" AC "] : Number of concurrent fuzzing threads, (default: '" AB "2" AC "')\n"
" [" AB "-N val" AC "] : Number of fuzzing iterations, (default: '" AB "0" AC "' [infinite])\n"
" [" AB "-l val" AC "] : Per process memory limit in MiB, (default: '" AB "0" AC "' [no limit])\n"
" [" AB "-R val" AC "] : Write report to this file, (default: '" AB _HF_REPORT_FILE AC "')\n"
" [" AB "-F val" AC "] : Maximal size of files processed by the fuzzer (default '" AB "1048576" AC "')\n"
" [" AB "-E val" AC "] : Pass this environment variable, can be used multiple times\n"
#if defined(_HF_ARCH_LINUX)
" [" AB "-p val" AC "] : [Linux] Attach to a pid (and its thread group), instead of \n"
" monitoring a previously created process, (default: '" AB "0" AC "' [none])\n"
" [" AB "-LR" AC "] : [Linux] Don't disable ASLR randomization, might be useful with MSAN\n"
" [" AB "-LU" AC "] : [Linux] Report MSAN's UMRS (uninitialized memory access)\n"
" [" AB "-LC val" AC "]: [Linux] Cut-off address, don't record branches above that address\n"
" [" AB "-LD val" AC "]: [Linux] Create a file dynamically with Linux perf counters,\n"
" can be used with or without the '-f' flag (initial file contents)\n"
" Available counters: \n"
" " AB "'i' " AC "- PERF_COUNT_HW_INSTRUCTIONS (total IPs)\n"
" " AB "'b' " AC "- PERF_COUNT_HW_BRANCH_INSTRUCTIONS (total jumps/calls)\n"
" " AB "'p' " AC "- PERF_SAMPLE_IP (unique code blocks)\n"
" (newer Intel CPUs only)\n"
" " AB "'e' " AC "- PERF_SAMPLE_IP/PERF_SAMPLE_ADDR (unique branch edges)\n"
" (newer Intel CPUs only)\n"
" " AB "'f' " AC "- Custom counter (see interceptor directory for examples)\n"
#endif /* defined(_HF_ARCH_LINUX) */
"\nExamples:\n"
" Run the binary over a mutated file chosen from the directory:\n"
AB " " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
" As above, provide input over STDIN:\n"
AB " " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg\n" AC
#if defined(_HF_ARCH_LINUX)
" Run the binary over a dynamic file, maximize total no. of instructions:\n"
AB " " PROG_NAME " -LD i -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
" Run the binary over a dynamic file, maximize total no. of branches:\n"
AB " " PROG_NAME " -LD b -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
" Run the binary over a dynamic file, maximize unique code blocks (coverage):\n"
AB " " PROG_NAME " -LD p -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
" Run the binary over a dynamic file, maximize unique branches (edges):\n"
AB " " PROG_NAME " -LD e -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
" Run the binary over a dynamic file, maximize custom counters (experimental):\n"
AB " " PROG_NAME " -LD f -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n"
#endif /* defined(_HF_ARCH_LINUX) */
);
/* *INDENT-ON* */

if (exit_success) {
exit(EXIT_SUCCESS);
} else {
exit(EXIT_FAILURE);
}
}

int main(int argc, char **argv)
{
int c;
int ll = l_INFO;
honggfuzz_t hfuzz = {
.cmdline = NULL,
.inputFile = NULL,
.nullifyStdio = false,
.useScreen = true,
.fuzzStdin = false,
.saveUnique = true,
.fileExtn = "fuzz",
.workDir = ".",
.flipRate = 0.001f,
.externalCommand = NULL,
.dictionaryFile = NULL,
.dictionary = NULL,
.dictionaryCnt = 0,
.blacklistFile = NULL,
.blacklistCnt = 0,
.blacklist = NULL,
.maxFileSz = (1024 * 1024),
.tmOut = 3,
.mutationsMax = 0,
.threadsFinished = 0,
.threadsMax = 2,
.ignoreAddr = NULL,
.reportFile = NULL,
.asLimit = 0ULL,
.files = NULL,
.fileCnt = 0,
.pid = 0,
.envs = {[0 ... (ARRAYSIZE(hfuzz.envs) - 1)] = NULL,},

.timeStart = time(NULL),
.mutationsCnt = 0,
.crashesCnt = 0,
.uniqueCrashesCnt = 0,
.blCrashesCnt = 0,
.timeoutedCnt = 0,

.dynFileMethod = _HF_DYNFILE_NONE,
.dynamicFileBest = NULL,
.dynamicFileBestSz = 1,
.hwCnts = {
.cpuInstrCnt = 0ULL,
.cpuBranchCnt = 0ULL,
.pcCnt = 0ULL,
.pathCnt = 0ULL,
.customCnt = 0ULL,
},
.dynamicCutOffAddr = ~(0ULL),
.dynamicFile_mutex = PTHREAD_MUTEX_INITIALIZER,

.disableRandomization = true,
.msanReportUMRS = false,
};

if (argc < 2) {
usage(true);
}

for (;;) {
c = getopt(argc, argv, "-?hqvsuf:d:e:W:r:c:F:t:a:R:n:N:l:p:g:E:w:B:L:");
if (c < 0)
break;

switch (c) {
case 'f':
hfuzz.inputFile = optarg;
break;
case 'h':
case '?':
usage(true);
break;
case 'q':
hfuzz.nullifyStdio = true;
break;
case 'v':
hfuzz.useScreen = false;
break;
case 's':
hfuzz.fuzzStdin = true;
break;
case 'u':
hfuzz.saveUnique = false;
break;
case 'd':
ll = atoi(optarg);
break;
case 'e':
hfuzz.fileExtn = optarg;
break;
case 'W':
hfuzz.workDir = optarg;
break;
case 'r':
hfuzz.flipRate = strtod(optarg, NULL);
break;
case 'c':
hfuzz.externalCommand = optarg;
break;
case 'F':
hfuzz.maxFileSz = strtoul(optarg, NULL, 0);
break;
case 't':
hfuzz.tmOut = atol(optarg);
break;
case 'a':
hfuzz.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
break;
case 'R':
hfuzz.reportFile = optarg;
break;
case 'n':
hfuzz.threadsMax = atol(optarg);
break;
case 'N':
hfuzz.mutationsMax = atol(optarg);
break;
case 'l':
hfuzz.asLimit = strtoull(optarg, NULL, 0);
break;
case 'p':
hfuzz.pid = atoi(optarg);
break;
case 'o':
break;
case 'E':
for (size_t i = 0; i < ARRAYSIZE(hfuzz.envs); i++) {
if (hfuzz.envs[i] == NULL) {
hfuzz.envs[i] = optarg;
break;
}
}
break;
case 'w':
hfuzz.dictionaryFile = optarg;
break;
case 'B':
hfuzz.blacklistFile = optarg;
break;
case 'L':
switch (optarg[0]) {
case 'R':
hfuzz.disableRandomization = false;
break;
case 'U':
hfuzz.msanReportUMRS = true;
break;
case 'C':
hfuzz.dynamicCutOffAddr = strtoull(optarg + 2, NULL, 0);
break;
case 'D':{
switch (optarg[2]) {
case 'i':
hfuzz.dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
break;
case 'b':
hfuzz.dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
break;
case 'p':
hfuzz.dynFileMethod |= _HF_DYNFILE_UNIQUE_BLOCK_COUNT;
break;
case 'e':
hfuzz.dynFileMethod |= _HF_DYNFILE_UNIQUE_EDGE_COUNT;
break;
case 'f':
hfuzz.dynFileMethod |= _HF_DYNFILE_CUSTOM;
break;
default:
LOGMSG(l_ERROR, "Unknown -D mode '%c'", optarg[2]);
usage(false);
break;
}
}
break;
default:
LOGMSG(l_ERROR, "Unknown -L switch");
usage(false);
}
default:
break;
}
}
hfuzz.cmdline = &argv[optind];

log_setMinLevel(ll);

if (hfuzz.dynamicFileBestSz > hfuzz.maxFileSz) {
LOGMSG(l_FATAL,
"Initial dynamic file size cannot be larger than maximum file size (%zu > %zu)",
hfuzz.dynamicFileBestSz, hfuzz.maxFileSz);
}

if ((hfuzz.dynamicFileBest = malloc(hfuzz.maxFileSz)) == NULL) {
LOGMSG(l_FATAL, "malloc(%zu) failed", hfuzz.maxFileSz);
}

if (!hfuzz.cmdline[0]) {
LOGMSG(l_FATAL, "Please specify a binary to fuzz");
usage(false);
}

if (!hfuzz.fuzzStdin && !checkFor_FILE_PLACEHOLDER(hfuzz.cmdline)) {
LOGMSG(l_FATAL,
"You must specify '" _HF_FILE_PLACEHOLDER
"' when the -s (stdin fuzzing) option is not set");
usage(false);
}

if (strchr(hfuzz.fileExtn, '/')) {
LOGMSG(l_FATAL, "The file extension contains the '/' character: '%s'", hfuzz.fileExtn);
usage(false);
}

if (hfuzz.pid > 0) {
LOGMSG(l_INFO, "PID=%d specified, lowering maximum number of concurrent threads to 1",
hfuzz.pid);
hfuzz.threadsMax = 1;
honggfuzz_t hfuzz;
if (cmdlineParse(argc, argv, &hfuzz) == false) {
LOG_F("Parsing of the cmd-line arguments failed");
}

LOGMSG(l_INFO,
"debugLevel: %d, inputFile '%s', nullifyStdio: %d, fuzzStdin: %d, saveUnique: %d, flipRate: %lf, "
"externalCommand: '%s', tmOut: %ld, mutationsMax: %ld, threadsMax: %ld, fileExtn '%s', ignoreAddr: %p, "
"memoryLimit: %llu (MiB), fuzzExe: '%s', fuzzedPid: %d",
ll, hfuzz.inputFile, hfuzz.nullifyStdio ? 1 : 0,
hfuzz.fuzzStdin ? 1 : 0, hfuzz.saveUnique ? 1 : 0,
hfuzz.flipRate,
hfuzz.externalCommand == NULL ? "NULL" : hfuzz.externalCommand,
hfuzz.tmOut, hfuzz.mutationsMax, hfuzz.threadsMax,
hfuzz.fileExtn, hfuzz.ignoreAddr, hfuzz.asLimit, hfuzz.cmdline[0], hfuzz.pid);

if (!files_init(&hfuzz)) {
LOGMSG(l_FATAL, "Couldn't load input files");
LOG_F("Couldn't load input files");
exit(EXIT_FAILURE);
}

if (hfuzz.dictionaryFile && (files_parseDictionary(&hfuzz) == false)) {
LOGMSG(l_FATAL, "Couldn't parse dictionary file ('%s')", hfuzz.dictionaryFile);
LOG_F("Couldn't parse dictionary file ('%s')", hfuzz.dictionaryFile);
}

if (hfuzz.blacklistFile && (files_parseBlacklist(&hfuzz) == false)) {
LOGMSG(l_FATAL, "Couldn't parse stackhash blacklist file ('%s')", hfuzz.blacklistFile);
LOG_F("Couldn't parse stackhash blacklist file ('%s')", hfuzz.blacklistFile);
}

/*
56 changes: 28 additions & 28 deletions linux/arch.c
Original file line number Diff line number Diff line change
@@ -70,15 +70,15 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
* Kill the children when fuzzer dies (e.g. due to Ctrl+C)
*/
if (prctl(PR_SET_PDEATHSIG, (long)SIGKILL, 0L, 0L, 0L) == -1) {
LOGMSG_P(l_ERROR, "prctl(PR_SET_PDEATHSIG, SIGKILL) failed");
PLOG_E("prctl(PR_SET_PDEATHSIG, SIGKILL) failed");
return false;
}

/*
* Kill a process which corrupts its own heap (with ABRT)
*/
if (setenv("MALLOC_CHECK_", "3", 1) == -1) {
LOGMSG_P(l_ERROR, "setenv(MALLOC_CHECK_=3) failed");
PLOG_E("setenv(MALLOC_CHECK_=3) failed");
return false;
}

@@ -89,7 +89,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
("ASAN_OPTIONS",
"allow_user_segv_handler=1:handle_segv=0:abort_on_error=1:allocator_may_return_null=1",
1) == -1) {
LOGMSG_P(l_ERROR, "setenv(ASAN_OPTIONS) failed");
PLOG_E("setenv(ASAN_OPTIONS) failed");
return false;
}

@@ -100,15 +100,15 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
"exit_code=" HF_MSAN_EXIT_CODE_STR ":report_umrs=1:wrap_signals=0:print_stats=1";
}
if (setenv("MSAN_OPTIONS", msan_options, 1) == -1) {
LOGMSG_P(l_ERROR, "setenv(MSAN_OPTIONS) failed");
PLOG_E("setenv(MSAN_OPTIONS) failed");
return false;
}

/*
* Disable ASLR
*/
if (hfuzz->disableRandomization && personality(ADDR_NO_RANDOMIZE) == -1) {
LOGMSG_P(l_ERROR, "personality(ADDR_NO_RANDOMIZE) failed");
PLOG_E("personality(ADDR_NO_RANDOMIZE) failed");
return false;
}
#define ARGS_MAX 512
@@ -131,7 +131,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)

args[x++] = NULL;

LOGMSG(l_DEBUG, "Launching '%s' on file '%s'", args[0], fileName);
LOG_D("Launching '%s' on file '%s'", args[0], fileName);

/*
* Set timeout (prof), real timeout (2*prof), and rlimit_cpu (2*prof)
@@ -145,7 +145,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
.rlim_max = hfuzz->tmOut * 2,
};
if (setrlimit(RLIMIT_CPU, &rl) == -1) {
LOGMSG_P(l_ERROR, "Couldn't enforce the RLIMIT_CPU resource limit");
PLOG_E("Couldn't enforce the RLIMIT_CPU resource limit");
return false;
}
}
@@ -159,7 +159,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
.rlim_max = hfuzz->asLimit * 1024ULL * 1024ULL,
};
if (prlimit64(getpid(), RLIMIT_AS, &rl, NULL) == -1) {
LOGMSG_P(l_DEBUG, "Couldn't enforce the RLIMIT_AS resource limit, ignoring");
PLOG_D("Couldn't enforce the RLIMIT_AS resource limit, ignoring");
}
}

@@ -186,14 +186,14 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
execvp(args[0], args);

util_recoverStdio();
LOGMSG(l_FATAL, "Failed to create new '%s' process", args[0]);
LOG_F("Failed to create new '%s' process", args[0]);
return false;
}

static void arch_sigFunc(int signo, siginfo_t * si, void *dummy)
{
if (signo != SIGALRM) {
LOGMSG(l_ERROR, "Signal != SIGALRM (%d)", signo);
LOG_E("Signal != SIGALRM (%d)", signo);
}
return;
if (si == NULL) {
@@ -218,7 +218,7 @@ static bool arch_setTimer(timer_t * timerid)
._sigev_un._tid = syscall(__NR_gettid),
};
if (timer_create(CLOCK_REALTIME, &sevp, timerid) == -1) {
LOGMSG_P(l_ERROR, "timer_create(CLOCK_REALTIME) failed");
PLOG_E("timer_create(CLOCK_REALTIME) failed");
return false;
}
/*
@@ -229,7 +229,7 @@ static bool arch_setTimer(timer_t * timerid)
.it_interval = {.tv_sec = 0,.tv_nsec = 200000000,},
};
if (timer_settime(*timerid, 0, &ts, NULL) == -1) {
LOGMSG_P(l_ERROR, "timer_settime() failed");
PLOG_E("timer_settime() failed");
timer_delete(*timerid);
return false;
}
@@ -243,7 +243,7 @@ static bool arch_setTimer(timer_t * timerid)
.sa_restorer = NULL,
};
if (sigaction(SIGALRM, &sa, NULL) == -1) {
LOGMSG_P(l_ERROR, "sigaction(SIGALRM) failed");
PLOG_E("sigaction(SIGALRM) failed");
return false;
}

@@ -255,8 +255,8 @@ static void arch_checkTimeLimit(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
int64_t curMillis = util_timeNowMillis();
int64_t diffMillis = curMillis - fuzzer->timeStartedMillis;
if (diffMillis > (hfuzz->tmOut * 1000)) {
LOGMSG(l_WARN, "PID %d took too much time (limit %ld s). Sending SIGKILL",
fuzzer->pid, hfuzz->tmOut);
LOG_W("PID %d took too much time (limit %ld s). Sending SIGKILL",
fuzzer->pid, hfuzz->tmOut);
kill(fuzzer->pid, SIGKILL);
__sync_fetch_and_add(&hfuzz->timeoutedCnt, 1UL);
}
@@ -269,7 +269,7 @@ void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)

timer_t timerid;
if (arch_setTimer(&timerid) == false) {
LOGMSG(l_FATAL, "Couldn't set timer");
LOG_F("Couldn't set timer");
}

perfFd_t perfFds;
@@ -281,18 +281,18 @@ void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
continue;
}
if (pid != childPid) {
LOGMSG_P(l_FATAL, "wait4()=%d =! %d", pid, childPid);
PLOG_F("wait4()=%d =! %d", pid, childPid);
}
if (WIFSTOPPED(status)) {
break;
}
LOGMSG_P(l_FATAL, "PID '%d' is not in a stopped state", pid);
PLOG_F("PID '%d' is not in a stopped state", pid);
}
if (arch_perfEnable(ptracePid, hfuzz, &perfFds) == false) {
LOGMSG(l_FATAL, "Couldn't enable perf counters for pid %d", ptracePid);
LOG_F("Couldn't enable perf counters for pid %d", ptracePid);
}
if (arch_ptraceAttach(ptracePid) == false) {
LOGMSG(l_FATAL, "Couldn't attach to pid %d", ptracePid);
LOG_F("Couldn't attach to pid %d", ptracePid);
}
kill(childPid, SIGCONT);

@@ -312,17 +312,17 @@ void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
continue;
}
if (pid == -1 && errno == ECHILD) {
LOGMSG(l_DEBUG, "No more processes to track");
LOG_D("No more processes to track");
break;
}
if (pid == -1) {
#if !defined(__ANDROID__)
LOGMSG_P(l_FATAL, "wait3() failed");
PLOG_F("wait3() failed");
#else
LOGMSG_P(l_FATAL, "wait4() failed");
PLOG_F("wait4() failed");
#endif
}
LOGMSG(l_DEBUG, "PID '%d' returned with status '%d'", pid, status);
LOG_D("PID '%d' returned with status '%d'", pid, status);

arch_ptraceGetCustomPerf(hfuzz, ptracePid, &fuzzer->hwCnts.customCnt);

@@ -366,20 +366,20 @@ bool arch_archInit(honggfuzz_t * hfuzz)
*/
struct utsname uts;
if (uname(&uts) == -1) {
LOGMSG_P(l_FATAL, "uname() failed");
PLOG_F("uname() failed");
return false;
}

p = uts.release;
major = strtoul(p, &p, 10);
if (*p++ != '.') {
LOGMSG(l_FATAL, "Unsupported kernel version (%s)", uts.release);
LOG_F("Unsupported kernel version (%s)", uts.release);
return false;
}

minor = strtoul(p, &p, 10);
if ((major < 3) || ((major == 3) && (minor < 7))) {
LOGMSG(l_ERROR, "Unsupported kernel version (%s)", uts.release);
LOG_E("Unsupported kernel version (%s)", uts.release);
return false;
}
}
@@ -391,7 +391,7 @@ bool arch_archInit(honggfuzz_t * hfuzz)
* Setups using BoringSSL (API >= 22) are not affected.
*/
if (setenv("OPENSSL_armcap", OPENSSL_ARMCAP_ABI, 1) == -1) {
LOGMSG_P(l_ERROR, "setenv(OPENSSL_armcap) failed");
PLOG_E("setenv(OPENSSL_armcap) failed");
return false;
}
#endif
16 changes: 8 additions & 8 deletions linux/bfd.c
Original file line number Diff line number Diff line change
@@ -53,29 +53,29 @@ static bool arch_bfdInit(pid_t pid, bfd_t * bfdParams)
char fname[PATH_MAX];
snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
if ((bfdParams->bfdh = bfd_openr(fname, 0)) == NULL) {
LOGMSG(l_ERROR, "bfd_openr(%s) failed", fname);
LOG_E("bfd_openr(%s) failed", fname);
return false;
}

if (!bfd_check_format(bfdParams->bfdh, bfd_object)) {
LOGMSG(l_ERROR, "bfd_check_format() failed");
LOG_E("bfd_check_format() failed");
return false;
}

int storage_needed = bfd_get_symtab_upper_bound(bfdParams->bfdh);
if (storage_needed <= 0) {
LOGMSG(l_ERROR, "bfd_get_symtab_upper_bound() returned '%d'", storage_needed);
LOG_E("bfd_get_symtab_upper_bound() returned '%d'", storage_needed);
return false;
}

if ((bfdParams->syms = (asymbol **) malloc(storage_needed)) == NULL) {
LOGMSG_P(l_ERROR, "malloc(%d) failed", storage_needed);
PLOG_E("malloc(%d) failed", storage_needed);
return false;
}
bfd_canonicalize_symtab(bfdParams->bfdh, bfdParams->syms);

if ((bfdParams->section = bfd_get_section_by_name(bfdParams->bfdh, ".text")) == NULL) {
LOGMSG(l_ERROR, "bfd_get_section_by_name('.text') failed");
LOG_E("bfd_get_section_by_name('.text') failed");
return false;
}

@@ -156,18 +156,18 @@ void arch_bfdDisasm(pid_t pid, uint8_t * mem, size_t size, char *instr)
snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
bfd *bfdh = bfd_openr(fname, NULL);
if (bfdh == NULL) {
LOGMSG(l_WARN, "bfd_openr('/proc/%d/exe') failed", pid);
LOG_W("bfd_openr('/proc/%d/exe') failed", pid);
goto out;
}

if (!bfd_check_format(bfdh, bfd_object)) {
LOGMSG(l_WARN, "bfd_check_format() failed");
LOG_W("bfd_check_format() failed");
goto out;
}

disassembler_ftype disassemble = disassembler(bfdh);
if (disassemble == NULL) {
LOGMSG(l_WARN, "disassembler() failed");
LOG_W("disassembler() failed");
goto out;
}

81 changes: 38 additions & 43 deletions linux/perf.c
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ static __thread uint64_t perfCutOffAddr = ~(0ULL);
static __thread dynFileMethod_t perfDynamicMethod = _HF_DYNFILE_NONE;

#if __BITS_PER_LONG == 64
#define _HF_PERF_BLOOM_SZ (1024ULL * 1024ULL * 1024ULL)
#define _HF_PERF_BLOOM_SZ (size_t)(1024ULL * 1024ULL * 1024ULL)
#elif __BITS_PER_LONG == 32
#define _HF_PERF_BLOOM_SZ (1024ULL * 1024ULL * 128ULL)
#else
@@ -79,7 +79,7 @@ static inline void arch_perfAddBranch(uint64_t from, uint64_t to)
*/
if (__builtin_expect(from > 0xFFFFFFFF00000000, false)
|| __builtin_expect(to > 0xFFFFFFFF00000000, false)) {
LOGMSG(l_DEBUG, "Adding branch %#018" PRIx64 " - %#018" PRIx64, from, to);
LOG_D("Adding branch %#018" PRIx64 " - %#018" PRIx64, from, to);
return;
}
if (from >= perfCutOffAddr || to >= perfCutOffAddr) {
@@ -116,7 +116,7 @@ static inline uint64_t arch_perfGetMmap64(bool fatal)

if (__builtin_expect(dataHeadOff == dataTailOff, false)) {
if (fatal) {
LOGMSG(l_FATAL, "No data in the mmap buffer");
LOG_F("No data in the mmap buffer");
}
return ~(0ULL);
}
@@ -145,14 +145,13 @@ static inline void arch_perfMmapParse(void)
continue;
}
if (__builtin_expect(peh->type != PERF_RECORD_SAMPLE, false)) {
LOGMSG(l_FATAL, "(struct perf_event_header)->type != PERF_RECORD_SAMPLE (%" PRIu16 ")",
peh->type);
LOG_F("(struct perf_event_header)->type != PERF_RECORD_SAMPLE (%" PRIu16 ")",
peh->type);
}
if (__builtin_expect
(peh->misc != PERF_RECORD_MISC_USER && peh->misc != PERF_RECORD_MISC_KERNEL, false)) {
LOGMSG(l_FATAL,
"(struct perf_event_header)->type != PERF_RECORD_MISC_USER (%" PRIu16 ")",
peh->misc);
LOG_F("(struct perf_event_header)->type != PERF_RECORD_MISC_USER (%" PRIu16 ")",
peh->misc);
}

register uint64_t from = arch_perfGetMmap64(true /* fatal */ );
@@ -193,8 +192,7 @@ static size_t arch_perfGetMmapBufSz(honggfuzz_t * hfuzz)
ret >>= 1;
}
if (ret < (size_t) getpagesize()) {
LOGMSG(l_FATAL, "Too many fuzzing threads for hardware support (%d)",
hfuzz->threadsMax);
LOG_F("Too many fuzzing threads for hardware support (%td)", hfuzz->threadsMax);
}
}
}
@@ -203,7 +201,7 @@ static size_t arch_perfGetMmapBufSz(honggfuzz_t * hfuzz)

static bool arch_perfOpen(pid_t pid, dynFileMethod_t method, int *perfFd)
{
LOGMSG(l_DEBUG, "Enabling PERF for PID=%d (mmapBufSz=%zu), method=%x", pid, perfMmapSz, method);
LOG_D("Enabling PERF for PID=%d (mmapBufSz=%zu), method=%x", pid, perfMmapSz, method);

perfDynamicMethod = method;
perfBranchesCnt = 0;
@@ -221,44 +219,43 @@ static bool arch_perfOpen(pid_t pid, dynFileMethod_t method, int *perfFd)

switch (method) {
case _HF_DYNFILE_INSTR_COUNT:
LOGMSG(l_DEBUG, "Using: PERF_COUNT_HW_INSTRUCTIONS for PID: %d", pid);
LOG_D("Using: PERF_COUNT_HW_INSTRUCTIONS for PID: %d", pid);
pe.config = PERF_COUNT_HW_INSTRUCTIONS;
pe.inherit = 1;
break;
case _HF_DYNFILE_BRANCH_COUNT:
LOGMSG(l_DEBUG, "Using: PERF_COUNT_HW_BRANCH_INSTRUCTIONS for PID: %d", pid);
LOG_D("Using: PERF_COUNT_HW_BRANCH_INSTRUCTIONS for PID: %d", pid);
pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
pe.inherit = 1;
break;
case _HF_DYNFILE_UNIQUE_BLOCK_COUNT:
LOGMSG(l_DEBUG, "Using: PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_IP for PID: %d", pid);
LOG_D("Using: PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_IP for PID: %d", pid);
pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
pe.sample_type = PERF_SAMPLE_IP;
pe.sample_period = 1; /* It's BTS based, so must be equal to 1 */
pe.wakeup_events = 0;
break;
case _HF_DYNFILE_UNIQUE_EDGE_COUNT:
LOGMSG(l_DEBUG,
"Using: PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_IP|PERF_SAMPLE_ADDR for PID: %d", pid);
LOG_D("Using: PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_IP|PERF_SAMPLE_ADDR for PID: %d", pid);
pe.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
pe.sample_period = 1; /* It's BTS based, so must be equal to 1 */
pe.wakeup_events = 0;
break;
default:
LOGMSG(l_ERROR, "Unknown perf mode: '%d' for PID: %d", method, pid);
LOG_E("Unknown perf mode: '%d' for PID: %d", method, pid);
return false;
break;
}

*perfFd = perf_event_open(&pe, pid, -1, -1, 0);
if (*perfFd == -1) {
if (method == _HF_DYNFILE_UNIQUE_BLOCK_COUNT || method == _HF_DYNFILE_UNIQUE_EDGE_COUNT) {
LOGMSG(l_ERROR,
"'-LD p'/'-LD e' mode (sample IP/jump) requires LBR/BTS, which present in Intel Haswell "
"and newer CPUs (i.e. not in AMD CPUs)");
LOG_E
("'-LDp'/'-LDe' mode (sample IP/jump) requires LBR/BTS, which present in Intel Haswell "
"and newer CPUs (i.e. not in AMD CPUs)");
}
LOGMSG_P(l_FATAL, "perf_event_open() failed");
PLOG_F("perf_event_open() failed");
return false;
}

@@ -270,14 +267,14 @@ static bool arch_perfOpen(pid_t pid, dynFileMethod_t method, int *perfFd)
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
if (perfBloom == MAP_FAILED) {
perfBloom = NULL;
LOGMSG_P(l_ERROR, "mmap(size=%zu) failed", _HF_PERF_BLOOM_SZ);
PLOG_E("mmap(size=%zu) failed", _HF_PERF_BLOOM_SZ);
}

perfMmapBuf =
mmap(NULL, perfMmapSz + getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, *perfFd, 0);
if (perfMmapBuf == MAP_FAILED) {
perfMmapBuf = NULL;
LOGMSG_P(l_ERROR, "mmap() failed");
PLOG_E("mmap() failed");
close(*perfFd);
return false;
}
@@ -288,17 +285,17 @@ static bool arch_perfOpen(pid_t pid, dynFileMethod_t method, int *perfFd)
};
sigemptyset(&sa.sa_mask);
if (sigaction(_HF_RT_SIG, &sa, NULL) == -1) {
LOGMSG_P(l_ERROR, "sigaction() failed");
PLOG_E("sigaction() failed");
return false;
}

if (fcntl(*perfFd, F_SETFL, O_RDWR | O_NONBLOCK | O_ASYNC) == -1) {
LOGMSG_P(l_ERROR, "fnctl(F_SETFL)");
PLOG_E("fnctl(F_SETFL)");
close(*perfFd);
return false;
}
if (fcntl(*perfFd, F_SETSIG, _HF_RT_SIG) == -1) {
LOGMSG_P(l_ERROR, "fnctl(F_SETSIG)");
PLOG_E("fnctl(F_SETSIG)");
close(*perfFd);
return false;
}
@@ -307,7 +304,7 @@ static bool arch_perfOpen(pid_t pid, dynFileMethod_t method, int *perfFd)
.pid = syscall(__NR_gettid)
};
if (fcntl(*perfFd, F_SETOWN_EX, &foe) == -1) {
LOGMSG_P(l_ERROR, "fnctl(F_SETOWN_EX)");
PLOG_E("fnctl(F_SETOWN_EX)");
close(*perfFd);
return false;
}
@@ -321,8 +318,8 @@ bool arch_perfEnable(pid_t pid, honggfuzz_t * hfuzz, perfFd_t * perfFds)
}
if ((hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_BLOCK_COUNT)
&& (hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_EDGE_COUNT)) {
LOGMSG(l_FATAL,
"_HF_DYNFILE_UNIQUE_BLOCK_COUNT and _HF_DYNFILE_UNIQUE_EDGE_COUNT cannot be specified together");
LOG_F
("_HF_DYNFILE_UNIQUE_BLOCK_COUNT and _HF_DYNFILE_UNIQUE_EDGE_COUNT cannot be specified together");
}

perfBloom = NULL;
@@ -337,25 +334,25 @@ bool arch_perfEnable(pid_t pid, honggfuzz_t * hfuzz, perfFd_t * perfFds)

if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
if (arch_perfOpen(pid, _HF_DYNFILE_INSTR_COUNT, &perfFds->cpuInstrFd) == false) {
LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_INSTR_COUNT)", pid);
LOG_E("Cannot set up perf for PID=%d (_HF_DYNFILE_INSTR_COUNT)", pid);
goto out;
}
}
if (hfuzz->dynFileMethod & _HF_DYNFILE_BRANCH_COUNT) {
if (arch_perfOpen(pid, _HF_DYNFILE_BRANCH_COUNT, &perfFds->cpuBranchFd) == false) {
LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_BRANCH_COUNT)", pid);
LOG_E("Cannot set up perf for PID=%d (_HF_DYNFILE_BRANCH_COUNT)", pid);
goto out;
}
}
if (hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_BLOCK_COUNT) {
if (arch_perfOpen(pid, _HF_DYNFILE_UNIQUE_BLOCK_COUNT, &perfFds->uniquePcFd) == false) {
LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_UNIQUE_BLOCK_COUNT)", pid);
LOG_E("Cannot set up perf for PID=%d (_HF_DYNFILE_UNIQUE_BLOCK_COUNT)", pid);
goto out;
}
}
if (hfuzz->dynFileMethod & _HF_DYNFILE_UNIQUE_EDGE_COUNT) {
if (arch_perfOpen(pid, _HF_DYNFILE_UNIQUE_EDGE_COUNT, &perfFds->uniqueEdgeFd) == false) {
LOGMSG(l_ERROR, "Cannot set up perf for PID=%d (_HF_DYNFILE_UNIQUE_EDGE_COUNT)", pid);
LOG_E("Cannot set up perf for PID=%d (_HF_DYNFILE_UNIQUE_EDGE_COUNT)", pid);
goto out;
}
}
@@ -379,7 +376,7 @@ void arch_perfAnalyze(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, perfFd_t * perfFds
if (hfuzz->dynFileMethod & _HF_DYNFILE_INSTR_COUNT) {
ioctl(perfFds->cpuInstrFd, PERF_EVENT_IOC_DISABLE, 0);
if (read(perfFds->cpuInstrFd, &instrCount, sizeof(instrCount)) != sizeof(instrCount)) {
LOGMSG_P(l_ERROR, "read(perfFd='%d') failed", perfFds->cpuInstrFd);
PLOG_E("read(perfFd='%d') failed", perfFds->cpuInstrFd);
}
close(perfFds->cpuInstrFd);
}
@@ -388,7 +385,7 @@ void arch_perfAnalyze(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, perfFd_t * perfFds
if (hfuzz->dynFileMethod & _HF_DYNFILE_BRANCH_COUNT) {
ioctl(perfFds->cpuBranchFd, PERF_EVENT_IOC_DISABLE, 0);
if (read(perfFds->cpuBranchFd, &branchCount, sizeof(branchCount)) != sizeof(branchCount)) {
LOGMSG_P(l_ERROR, "read(perfFd='%d') failed", perfFds->cpuBranchFd);
PLOG_E("read(perfFd='%d') failed", perfFds->cpuBranchFd);
}
close(perfFds->cpuBranchFd);
}
@@ -401,10 +398,9 @@ void arch_perfAnalyze(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, perfFd_t * perfFds
pathCount = arch_perfCountBranches();

if (perfRecordsLost > 0UL) {
LOGMSG(l_WARN,
"%" PRId64
" PERF_RECORD_LOST events received, possibly too many concurrent fuzzing threads in progress",
perfRecordsLost);
LOG_W("%" PRId64
" PERF_RECORD_LOST events received, possibly too many concurrent fuzzing threads in progress",
perfRecordsLost);
}
}

@@ -416,10 +412,9 @@ void arch_perfAnalyze(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, perfFd_t * perfFds
edgeCount = arch_perfCountBranches();

if (perfRecordsLost > 0UL) {
LOGMSG(l_WARN,
"%" PRId64
" PERF_RECORD_LOST events received, possibly too many concurrent fuzzing threads in progress",
perfRecordsLost);
LOG_W("%" PRId64
" PERF_RECORD_LOST events received, possibly too many concurrent fuzzing threads in progress",
perfRecordsLost);
}
}

102 changes: 48 additions & 54 deletions linux/ptrace_utils.c
Original file line number Diff line number Diff line change
@@ -379,7 +379,7 @@ static size_t arch_getProcMem(pid_t pid, uint8_t * buf, size_t len, REG_TYPE pc)
return len;
}
// Debug if failed since it shouldn't happen very often
LOGMSG_P(l_DEBUG, "process_vm_readv() failed");
PLOG_D("process_vm_readv() failed");

/*
* Ok, let's do it via ptrace() then.
@@ -393,7 +393,7 @@ static size_t arch_getProcMem(pid_t pid, uint8_t * buf, size_t len, REG_TYPE pc)
long ret = ptrace(PT_READ_D, pid, addr, NULL);

if (errno != 0) {
LOGMSG_P(l_WARN, "Couldn't PT_READ_D on pid %d, addr: %p", pid, addr);
PLOG_W("Couldn't PT_READ_D on pid %d, addr: %p", pid, addr);
break;
}

@@ -419,14 +419,13 @@ void arch_ptraceGetCustomPerf(honggfuzz_t * hfuzz, pid_t pid, uint64_t * cnt)
};

if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &pt_iov) == -1L) {
LOGMSG_P(l_DEBUG, "ptrace(PTRACE_GETREGSET) failed");
PLOG_D("ptrace(PTRACE_GETREGSET) failed");

// If PTRACE_GETREGSET fails, try PTRACE_GETREGS if available
#if PTRACE_GETREGS_AVAILABLE
if (ptrace(PTRACE_GETREGS, pid, 0, &regs)) {
LOGMSG_P(l_DEBUG, "ptrace(PTRACE_GETREGS) failed");
LOGMSG(l_WARN, "ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to"
" extract target registers");
PLOG_D("ptrace(PTRACE_GETREGS) failed");
LOG_W("ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to" " extract target registers");
return;
}
#else
@@ -452,7 +451,7 @@ void arch_ptraceGetCustomPerf(honggfuzz_t * hfuzz, pid_t pid, uint64_t * cnt)
return;
}

LOGMSG(l_WARN, "Unknown registers structure size: '%d'", pt_iov.iov_len);
LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len);
#endif /* defined(__i386__) || defined(__x86_64__) */
}

@@ -478,14 +477,13 @@ static size_t arch_getPC(pid_t pid, REG_TYPE * pc, REG_TYPE * status_reg)
};

if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &pt_iov) == -1L) {
LOGMSG_P(l_DEBUG, "ptrace(PTRACE_GETREGSET) failed");
PLOG_D("ptrace(PTRACE_GETREGSET) failed");

// If PTRACE_GETREGSET fails, try PTRACE_GETREGS if available
#if PTRACE_GETREGS_AVAILABLE
if (ptrace(PTRACE_GETREGS, pid, 0, &regs)) {
LOGMSG_P(l_DEBUG, "ptrace(PTRACE_GETREGS) failed");
LOGMSG(l_WARN, "ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to"
" extract target registers");
PLOG_D("ptrace(PTRACE_GETREGS) failed");
LOG_W("ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to" " extract target registers");
return 0;
}
#else
@@ -512,7 +510,7 @@ static size_t arch_getPC(pid_t pid, REG_TYPE * pc, REG_TYPE * status_reg)
*status_reg = r64->flags;
return pt_iov.iov_len;
}
LOGMSG(l_WARN, "Unknown registers structure size: '%d'", pt_iov.iov_len);
LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len);
return 0;
#endif /* defined(__i386__) || defined(__x86_64__) */

@@ -541,7 +539,7 @@ static size_t arch_getPC(pid_t pid, REG_TYPE * pc, REG_TYPE * status_reg)
*status_reg = r64->pstate;
return pt_iov.iov_len;
}
LOGMSG(l_WARN, "Unknown registers structure size: '%d'", pt_iov.iov_len);
LOG_W("Unknown registers structure size: '%d'", pt_iov.iov_len);
return 0;
#endif /* defined(__arm__) || defined(__aarch64__) */

@@ -564,11 +562,11 @@ static size_t arch_getPC(pid_t pid, REG_TYPE * pc, REG_TYPE * status_reg)
return pt_iov.iov_len;
}

LOGMSG(l_WARN, "Unknown registers structure size: '%d'", pt_iov.iov_len);
LOG_W("Unknown registers structure size: '%d'", pt_iov.iov_len);
return 0;
#endif /* defined(__powerpc64__) || defined(__powerpc__) */

LOGMSG(l_DEBUG, "Unknown/unsupported CPU architecture");
LOG_D("Unknown/unsupported CPU architecture");
return 0;
}

@@ -586,7 +584,7 @@ static void arch_getInstrStr(pid_t pid, REG_TYPE * pc, char *instr)

size_t pcRegSz = arch_getPC(pid, pc, &status_reg);
if (!pcRegSz) {
LOGMSG(l_WARN, "Current architecture not supported for disassembly");
LOG_W("Current architecture not supported for disassembly");
return;
}

@@ -610,22 +608,22 @@ static void arch_getInstrStr(pid_t pid, REG_TYPE * pc, char *instr)
arch = CS_ARCH_X86;
mode = (pcRegSz == sizeof(struct user_regs_struct_64)) ? CS_MODE_64 : CS_MODE_32;
#else
LOGMSG(l_ERROR, "Unknown/unsupported Android CPU architecture");
LOG_E("Unknown/unsupported Android CPU architecture");
#endif

csh handle;
cs_err err = cs_open(arch, mode, &handle);
if (err != CS_ERR_OK) {
LOGMSG(l_WARN, "Capstone initialization failed: '%s'", cs_strerror(err));
LOG_W("Capstone initialization failed: '%s'", cs_strerror(err));
return;
}

cs_insn *insn;
size_t count = cs_disasm(handle, buf, sizeof(buf), *pc, 0, &insn);

if (count < 1) {
LOGMSG(l_WARN, "Couldn't disassemble the assembler instructions' stream: '%s'",
cs_strerror(cs_errno(handle)));
LOG_W("Couldn't disassemble the assembler instructions' stream: '%s'",
cs_strerror(cs_errno(handle)));
cs_close(&handle);
return;
}
@@ -715,20 +713,17 @@ static void arch_ptraceSaveData(honggfuzz_t * hfuzz, pid_t pid, fuzzer_t * fuzze
bzero(&si, sizeof(si));

if (ptrace(PT_GETSIGINFO, pid, 0, &si) == -1) {
LOGMSG_P(l_WARN, "Couldn't get siginfo for pid %d", pid);
PLOG_W("Couldn't get siginfo for pid %d", pid);
}

arch_getInstrStr(pid, &pc, instr);

LOGMSG(l_DEBUG,
"Pid: %d, signo: %d, errno: %d, code: %d, addr: %p, pc: %"
REG_PM ", instr: '%s'", pid, si.si_signo, si.si_errno, si.si_code, si.si_addr, pc,
instr);
LOG_D("Pid: %d, signo: %d, errno: %d, code: %d, addr: %p, pc: %"
REG_PM ", instr: '%s'", pid, si.si_signo, si.si_errno, si.si_code, si.si_addr, pc, instr);

if (si.si_addr < hfuzz->ignoreAddr) {
LOGMSG(l_INFO,
"'%s' is interesting (%s), but the si.si_addr is %p (below %p), skipping",
fuzzer->fileName, arch_sigs[si.si_signo].descr, si.si_addr, hfuzz->ignoreAddr);
LOG_I("'%s' is interesting (%s), but the si.si_addr is %p (below %p), skipping",
fuzzer->fileName, arch_sigs[si.si_signo].descr, si.si_addr, hfuzz->ignoreAddr);
return;
}

@@ -759,7 +754,7 @@ static void arch_ptraceSaveData(honggfuzz_t * hfuzz, pid_t pid, fuzzer_t * fuzze
*/
if (hfuzz->blacklist
&& (fastArray64Search(hfuzz->blacklist, hfuzz->blacklistCnt, fuzzer->backtrace) != -1)) {
LOGMSG(l_INFO, "Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace);
LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace);
__sync_fetch_and_add(&hfuzz->blCrashesCnt, 1UL);
return;
}
@@ -787,15 +782,15 @@ static void arch_ptraceSaveData(honggfuzz_t * hfuzz, pid_t pid, fuzzer_t * fuzze

bool dstFileExists = false;
if (files_copyFile(fuzzer->fileName, newname, &dstFileExists)) {
LOGMSG(l_INFO, "Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, newname);
LOG_I("Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, newname);
__sync_fetch_and_add(&hfuzz->uniqueCrashesCnt, 1UL);
} else {
if (dstFileExists) {
LOGMSG(l_INFO, "It seems that '%s' already exists, skipping", newname);
LOG_I("It seems that '%s' already exists, skipping", newname);
// Don't bother unwinding & generating reports for duplicate crashes
return;
} else {
LOGMSG(l_ERROR, "Couldn't copy '%s' to '%s'", fuzzer->fileName, newname);
LOG_E("Couldn't copy '%s' to '%s'", fuzzer->fileName, newname);
}
}

@@ -805,25 +800,25 @@ static void arch_ptraceSaveData(honggfuzz_t * hfuzz, pid_t pid, fuzzer_t * fuzze
#define __WEVENT(status) ((status & 0xFF0000) >> 16)
static void arch_ptraceEvent(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int status, pid_t pid)
{
LOGMSG(l_DEBUG, "PID: %d, Ptrace event: %d", pid, __WEVENT(status));
LOG_D("PID: %d, Ptrace event: %d", pid, __WEVENT(status));
switch (__WEVENT(status)) {
case PTRACE_EVENT_EXIT:
{
unsigned long event_msg;
if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &event_msg) == -1) {
LOGMSG(l_ERROR, "ptrace(PTRACE_GETEVENTMSG,%d) failed", pid);
LOG_E("ptrace(PTRACE_GETEVENTMSG,%d) failed", pid);
return;
}

if (WIFEXITED(event_msg)) {
LOGMSG(l_DEBUG, "PID: %d exited with exit_code: %d", pid, WEXITSTATUS(event_msg));
LOG_D("PID: %d exited with exit_code: %d", pid, WEXITSTATUS(event_msg));
if (WEXITSTATUS(event_msg) == HF_MSAN_EXIT_CODE) {
arch_ptraceSaveData(hfuzz, pid, fuzzer);
}
} else if (WIFSIGNALED(event_msg)) {
LOGMSG(l_DEBUG, "PID: %d terminated with signal: %d", pid, WTERMSIG(event_msg));
LOG_D("PID: %d terminated with signal: %d", pid, WTERMSIG(event_msg));
} else {
LOGMSG(l_DEBUG, "PID: %d exited with unknown status: %ld", pid, event_msg);
LOG_D("PID: %d exited with unknown status: %ld", pid, event_msg);
}
}
break;
@@ -896,14 +891,14 @@ static bool arch_listThreads(int tasks[], size_t thrSz, int pid)
snprintf(path, sizeof(path), "/proc/%d/task", pid);
DIR *dir = opendir(path);
if (!dir) {
LOGMSG_P(l_ERROR, "Couldn't open dir '%s'", path);
PLOG_E("Couldn't open dir '%s'", path);
return false;
}

for (;;) {
struct dirent de, *res;
if (readdir_r(dir, &de, &res) > 0) {
LOGMSG_P(l_ERROR, "Couldn't read contents of '%s'", path);
PLOG_E("Couldn't read contents of '%s'", path);
closedir(dir);
return false;
}
@@ -914,20 +909,19 @@ static bool arch_listThreads(int tasks[], size_t thrSz, int pid)

pid_t pid = (pid_t) strtol(res->d_name, (char **)NULL, 10);
if (pid == 0) {
LOGMSG(l_DEBUG, "The following dir entry couldn't be converted to pid_t '%s'",
res->d_name);
LOG_D("The following dir entry couldn't be converted to pid_t '%s'", res->d_name);
continue;
}

tasks[count++] = pid;
LOGMSG(l_DEBUG, "Added pid '%d' from '%s/%s'", pid, path, res->d_name);
LOG_D("Added pid '%d' from '%s/%s'", pid, path, res->d_name);

if (count >= thrSz) {
break;
}
}
closedir(dir);
LOGMSG_P(l_DEBUG, "Total number of threads in pid '%d': '%d'", pid, count);
PLOG_D("Total number of threads in pid '%d': '%zd'", pid, count);
tasks[count + 1] = 0;
if (count < 1) {
return false;
@@ -941,14 +935,14 @@ static void arch_ptraceWaitForPid(pid_t pid)
int status;
pid_t ret = wait4(pid, &status, __WALL | WUNTRACED, NULL);
if (ret == -1 && errno == ESRCH) {
LOGMSG(l_WARN, "PID %d doesn't exist", pid);
LOG_W("PID %d doesn't exist", pid);
return;
}
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret == -1) {
LOGMSG(l_FATAL, "wait4(pid=%d) failed");
LOG_F("wait4(pid=%d) failed", pid);
return;
}
if (ret == pid) {
@@ -964,18 +958,18 @@ bool arch_ptraceAttach(pid_t pid)
PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXIT;

if (ptrace(PTRACE_SEIZE, pid, NULL, seize_options) == -1) {
LOGMSG_P(l_ERROR, "Couldn't ptrace(PTRACE_SEIZE) to pid: %d", pid);
PLOG_E("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", pid);
return false;
}
if (ptrace(PTRACE_INTERRUPT, pid, NULL, NULL) == -1) {
LOGMSG_P(l_ERROR, "Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", pid);
PLOG_E("Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", pid);
return false;
}
arch_ptraceWaitForPid(pid);

int tasks[MAX_THREAD_IN_TASK + 1] = { 0 };
if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, pid)) {
LOGMSG(l_ERROR, "Couldn't read thread list for pid '%d'", pid);
LOG_E("Couldn't read thread list for pid '%d'", pid);
return false;
}

@@ -984,19 +978,19 @@ bool arch_ptraceAttach(pid_t pid)
continue;
}
if (ptrace(PTRACE_SEIZE, tasks[i], NULL, seize_options) == -1) {
LOGMSG_P(l_WARN, "Couldn't ptrace(PTRACE_SEIZE) to pid: %d", tasks[i]);
PLOG_W("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", tasks[i]);
continue;
}
if (ptrace(PTRACE_INTERRUPT, tasks[i], NULL, NULL) == -1) {
LOGMSG_P(l_WARN, "Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", tasks[i]);
PLOG_W("Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", tasks[i]);
continue;
}
arch_ptraceWaitForPid(tasks[i]);
ptrace(PTRACE_CONT, tasks[i], NULL, NULL);
}

if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1) {
LOGMSG_P(l_WARN, "Couldn't ptrace(PTRACE_CONT) to pid: %d", pid);
PLOG_W("Couldn't ptrace(PTRACE_CONT) to pid: %d", pid);
return false;
}

@@ -1006,19 +1000,19 @@ bool arch_ptraceAttach(pid_t pid)
void arch_ptraceDetach(pid_t pid)
{
if (kill(pid, 0) == -1 && errno == ESRCH) {
LOGMSG(l_DEBUG, "PID: %d no longer exists", pid);
LOG_D("PID: %d no longer exists", pid);
return;
}

if (ptrace(PTRACE_INTERRUPT, pid, NULL, NULL) == -1) {
LOGMSG_P(l_ERROR, "Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", pid);
PLOG_E("Couldn't ptrace(PTRACE_INTERRUPT) to pid: %d", pid);
return;
}
arch_ptraceWaitForPid(pid);

int tasks[MAX_THREAD_IN_TASK + 1] = { 0 };
if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, pid)) {
LOGMSG(l_ERROR, "Couldn't read thread list for pid '%d'", pid);
LOG_E("Couldn't read thread list for pid '%d'", pid);
return;
}

24 changes: 10 additions & 14 deletions linux/unwind.c
Original file line number Diff line number Diff line change
@@ -60,29 +60,28 @@ size_t arch_unwindStack(pid_t pid, funcs_t * funcs)

unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, __BYTE_ORDER);
if (!as) {
LOGMSG(l_ERROR, "[pid='%d'] unw_create_addr_space failed", pid);
LOG_E("[pid='%d'] unw_create_addr_space failed", pid);
goto out;
}

ui = _UPT_create(pid);
if (ui == NULL) {
LOGMSG(l_ERROR, "[pid='%d'] _UPT_create failed", pid);
LOG_E("[pid='%d'] _UPT_create failed", pid);
goto out;
}

unw_cursor_t c;
int ret = unw_init_remote(&c, as, ui);
if (ret < 0) {
LOGMSG(l_ERROR, "[pid='%d'] unw_init_remote failed (%s)", pid, UNW_ER[-ret]);
LOG_E("[pid='%d'] unw_init_remote failed (%s)", pid, UNW_ER[-ret]);
goto out;
}

for (num_frames = 0; unw_step(&c) > 0 && num_frames < _HF_MAX_FUNCS; num_frames++) {
unw_word_t ip;
ret = unw_get_reg(&c, UNW_REG_IP, &ip);
if (ret < 0) {
LOGMSG(l_ERROR, "[pid='%d'] [%d] failed to read IP (%s)", pid, num_frames,
UNW_ER[-ret]);
LOG_E("[pid='%d'] [%zd] failed to read IP (%s)", pid, num_frames, UNW_ER[-ret]);
funcs[num_frames].pc = 0;
} else
funcs[num_frames].pc = (void *)ip;
@@ -103,20 +102,20 @@ size_t arch_unwindStack(pid_t pid, funcs_t * funcs)

as = unw_create_addr_space(&_UPT_accessors, __BYTE_ORDER);
if (!as) {
LOGMSG(l_ERROR, "[pid='%d'] unw_create_addr_space failed", pid);
LOG_E("[pid='%d'] unw_create_addr_space failed", pid);
goto out;
}

ui = (struct UPT_info *)_UPT_create(pid);
if (ui == NULL) {
LOGMSG(l_ERROR, "[pid='%d'] _UPT_create failed", pid);
LOG_E("[pid='%d'] _UPT_create failed", pid);
goto out;
}

unw_cursor_t cursor;
int ret = unw_init_remote(&cursor, as, ui);
if (ret < 0) {
LOGMSG(l_ERROR, "[pid='%d'] unw_init_remote failed (%s)", pid, UNW_ER[-ret]);
LOG_E("[pid='%d'] unw_init_remote failed (%s)", pid, UNW_ER[-ret]);
goto out;
}

@@ -126,8 +125,7 @@ size_t arch_unwindStack(pid_t pid, funcs_t * funcs)

ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
if (ret < 0) {
LOGMSG(l_ERROR, "[pid='%d'] [%d] failed to read IP (%s)",
pid, num_frames, UNW_ER[-ret]);
LOG_E("[pid='%d'] [%d] failed to read IP (%s)", pid, num_frames, UNW_ER[-ret]);
// We don't want to try to extract info from an arbitrary IP
// TODO: Maybe abort completely (goto out))
goto skip_frame_info;
@@ -136,16 +134,14 @@ size_t arch_unwindStack(pid_t pid, funcs_t * funcs)
unw_proc_info_t frameInfo;
ret = unw_get_proc_info(&cursor, &frameInfo);
if (ret < 0) {
LOGMSG(l_DEBUG, "[pid='%d'] [%d] unw_get_proc_info (%s)",
pid, num_frames, UNW_ER[-ret]);
LOG_D("[pid='%d'] [%d] unw_get_proc_info (%s)", pid, num_frames, UNW_ER[-ret]);
// Not safe to keep parsing frameInfo
goto skip_frame_info;
}

ret = unw_get_proc_name(&cursor, buf, sizeof(buf), &offset);
if (ret < 0) {
LOGMSG(l_DEBUG, "[pid='%d'] [%d] unw_get_proc_name() failed (%s)",
pid, num_frames, UNW_ER[-ret]);
LOG_D("[pid='%d'] [%d] unw_get_proc_name() failed (%s)", pid, num_frames, UNW_ER[-ret]);
buf[0] = '\0';
}

202 changes: 98 additions & 104 deletions log.c
Original file line number Diff line number Diff line change
@@ -1,142 +1,136 @@
/*
*
* honggfuzz - log messages
* -----------------------------------------
*
* Author: Robert Swiecki <swiecki@google.com>
*
* Copyright 2010-2015 by Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
*/
#include "common.h"
nsjail - logging
-----------------------------------------
Copyright 2014 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "log.h"

#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>

#include "util.h"

static unsigned int log_minLevel = l_INFO;
static bool log_isStdioTTY;
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

/* *INDENT-OFF* */
static const struct {
const char *descr;
const char *prefix;
} logLevels[] = {
{ "[FATAL]", "\033[1;41m" },
{ "[ERROR]", "\033[1;31m" },
{ "[WARNING]", "\033[1;35m" },
{ "[INFO]", "\033[1m" },
{ "[DEBUG]", "\033[0;37m" },
};
/* *INDENT-ON* */

__attribute__ ((constructor))
void log_init(void)
{
log_isStdioTTY = (isatty(STDOUT_FILENO) == 1);
}
static int log_fd = STDERR_FILENO;
static bool log_fd_isatty = true;
static bool log_level = INFO;

void log_setMinLevel(log_level_t dl)
enum llevel_t logGetLogLevel(void)
{
log_minLevel = dl;
return log_level;
}

log_level_t log_getMinLevel(void)
{
return log_minLevel;
}

void log_mutexLock(void)
{
while (pthread_mutex_lock(&log_mutex)) ;
}

void log_mutexUnLock(void)
/*
* Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
* connection socket with fd (0, 1, 2).
*/
bool logInitLogFile(const char *logfile, enum llevel_t ll)
{
while (pthread_mutex_unlock(&log_mutex)) ;
log_level = ll;
if (logfile == NULL) {
log_fd = STDERR_FILENO;
return true;
}
log_fd = open(logfile, O_CREAT | O_RDWR | O_APPEND, 0640);
if (log_fd == -1) {
log_fd = STDERR_FILENO;
PLOG_E("Couldn't open logfile open('%s')", logfile);
return false;
}
log_fd_isatty = (isatty(log_fd) == 1 ? true : false);
return true;
}

void log_msg(log_level_t dl, bool perr, const char *file, const char *func, int line,
const char *fmt, ...)
void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
{
char msg[8192] = { "\0" };
char strerr[512];
if (perr) {
if (perr == true) {
snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
}
struct ll_t {
char *descr;
char *prefix;
bool print_funcline;
};
struct ll_t logLevels[] = {
{"HR", "\033[0m", false},
{"HB", "\033[1m", false},
{"D", "\033[0;4m", true},
{"I", "\033[1m", true},
{"W", "\033[0;33m", true},
{"E", "\033[1;31m", true},
{"F", "\033[7;35m", true},
};

time_t ltstamp = time(NULL);
struct tm utctime;
localtime_r(&ltstamp, &utctime);
char timestr[32];
if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
timestr[0] = '\0';
}

struct tm tm;
struct timeval tv;

gettimeofday(&tv, NULL);
localtime_r((const time_t *)&tv.tv_sec, &tm);

if (log_isStdioTTY == true) {
util_ssnprintf(msg, sizeof(msg), "%s", logLevels[dl].prefix);
/* Start printing logs */
if (log_fd_isatty) {
dprintf(log_fd, "%s", logLevels[ll].prefix);
}
#if defined(_HF_ARCH_LINUX)
#include <unistd.h>
#include <sys/syscall.h>
pid_t pid = (pid_t) syscall(__NR_gettid);
#else /* defined(_HF_ARCH_LINUX) */
pid_t pid = getpid();
#endif /* defined(_HF_ARCH_LINUX) */

if (log_minLevel != l_INFO || !log_isStdioTTY) {
util_ssnprintf(msg, sizeof(msg), "%s [%d] %d/%02d/%02d %02d:%02d:%02d (%s:%s %d) ",
logLevels[dl].descr, pid, tm.tm_year + 1900,
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, file, func,
line);
} else {
util_ssnprintf(msg, sizeof(msg), "%s ", logLevels[dl].descr);
if (logLevels[ll].print_funcline) {
dprintf(log_fd, "[%s][%s][%ld] %s():%d ", timestr, logLevels[ll].descr,
syscall(__NR_getpid), fn, ln);
}

va_list args;
va_start(args, fmt);
util_vssnprintf(msg, sizeof(msg), fmt, args);
vdprintf(log_fd, fmt, args);
va_end(args);

if (perr) {
util_ssnprintf(msg, sizeof(msg), ": %s", strerr);
if (perr == true) {
dprintf(log_fd, ": %s", strerr);
}
if (log_fd_isatty) {
dprintf(log_fd, "\033[0m");
}
dprintf(log_fd, "\n");
/* End printing logs */

if (log_isStdioTTY == true) {
util_ssnprintf(msg, sizeof(msg), "\033[0m");
if (ll == FATAL) {
exit(1);
}
}

util_ssnprintf(msg, sizeof(msg), "\n");
void logStop(int sig)
{
LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
}

log_mutexLock();
if (write(STDOUT_FILENO, msg, strlen(msg)) == -1) {
}
log_mutexUnLock();
void logRedirectLogFD(int fd)
{
log_fd = fd;
}

if (dl == l_FATAL) {
exit(EXIT_FAILURE);
}
void logDirectlyToFD(const char *msg)
{
dprintf(log_fd, "%s", msg);
}
104 changes: 59 additions & 45 deletions log.h
Original file line number Diff line number Diff line change
@@ -1,46 +1,60 @@
/*
*
* honggfuzz - log messages
* -----------------------------------------
*
* Author: Robert Swiecki <swiecki@google.com>
*
* Copyright 2010-2015 by Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
*/

#ifndef _LOG_H_
#define _LOG_H_

#include <pthread.h>

typedef enum {
l_FATAL = 0, l_ERROR, l_WARN, l_INFO, l_DEBUG
} log_level_t;

extern void log_setMinLevel(log_level_t dl);

extern log_level_t log_getMinLevel(void);

extern void log_msg(log_level_t dl, bool perr, const char *file, const char *func, int line,
const char *fmt, ...);

extern void log_mutexLock(void);
extern void log_mutexUnLock(void);

#define LOGMSG(ll, ...) if (ll <= log_getMinLevel()) { log_msg(ll, false, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); };
#define LOGMSG_P(ll, ...) if (ll <= log_getMinLevel()) { log_msg(ll, true, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); };

#endif
honggfuzz - logging
-----------------------------------------
Copyright 2014 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef _LOG_H
#define _LOG_H

#include <getopt.h>
#include <stdbool.h>

#include "common.h"

#define LOG_HELP(...) logLog(HELP, __FUNCTION__, __LINE__, false, __VA_ARGS__);
#define LOG_HELP_BOLD(...) logLog(HELP_BOLD, __FUNCTION__, __LINE__, false, __VA_ARGS__);

#define LOG_D(...) logLog(DEBUG, __FUNCTION__, __LINE__, false, __VA_ARGS__);
#define LOG_I(...) logLog(INFO, __FUNCTION__, __LINE__, false, __VA_ARGS__);
#define LOG_W(...) logLog(WARNING, __FUNCTION__, __LINE__, false, __VA_ARGS__);
#define LOG_E(...) logLog(ERROR, __FUNCTION__, __LINE__, false, __VA_ARGS__);
#define LOG_F(...) logLog(FATAL, __FUNCTION__, __LINE__, false, __VA_ARGS__);

#define PLOG_D(...) logLog(DEBUG, __FUNCTION__, __LINE__, true, __VA_ARGS__);
#define PLOG_I(...) logLog(INFO, __FUNCTION__, __LINE__, true, __VA_ARGS__);
#define PLOG_W(...) logLog(WARNING, __FUNCTION__, __LINE__, true, __VA_ARGS__);
#define PLOG_E(...) logLog(ERROR, __FUNCTION__, __LINE__, true, __VA_ARGS__);
#define PLOG_F(...) logLog(FATAL, __FUNCTION__, __LINE__, true, __VA_ARGS__);

enum llevel_t {
HELP = 0,
HELP_BOLD,
DEBUG,
INFO,
WARNING,
ERROR,
FATAL
};

bool logInitLogFile(const char *logfile, enum llevel_t ll);
void logLog(enum llevel_t ll, const char *fn, int ln, bool perr, const char *fmt, ...)
__attribute__ ((format(printf, 5, 6)));
void logStop(int sig);

#endif /* _LOG_H */
69 changes: 33 additions & 36 deletions mac/arch.c
Original file line number Diff line number Diff line change
@@ -161,26 +161,23 @@ static bool arch_analyzeSignal(honggfuzz_t * hfuzz, int status, fuzzer_t * fuzze
* Boring, the process just exited
*/
if (WIFEXITED(status)) {
LOGMSG(l_DEBUG, "Process (pid %d) exited normally with status %d", fuzzer->pid,
WEXITSTATUS(status));
LOG_D("Process (pid %d) exited normally with status %d", fuzzer->pid, WEXITSTATUS(status));
return true;
}

/*
* Shouldn't really happen, but, well..
*/
if (!WIFSIGNALED(status)) {
LOGMSG(l_ERROR,
"Process (pid %d) exited with the following status %d, please report that as a bug",
fuzzer->pid, status);
LOG_E("Process (pid %d) exited with the following status %d, please report that as a bug",
fuzzer->pid, status);
return true;
}

int termsig = WTERMSIG(status);
LOGMSG(l_DEBUG, "Process (pid %d) killed by signal %d '%s'", fuzzer->pid, termsig,
strsignal(termsig));
LOG_D("Process (pid %d) killed by signal %d '%s'", fuzzer->pid, termsig, strsignal(termsig));
if (!arch_sigs[termsig].important) {
LOGMSG(l_DEBUG, "It's not that important signal, skipping");
LOG_D("It's not that important signal, skipping");
return true;
}

@@ -226,21 +223,21 @@ static bool arch_analyzeSignal(honggfuzz_t * hfuzz, int status, fuzzer_t * fuzze
*/
if (hfuzz->blacklist
&& (fastArray64Search(hfuzz->blacklist, hfuzz->blacklistCnt, fuzzer->backtrace) != -1)) {
LOGMSG(l_INFO, "Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace);
LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace);
__sync_fetch_and_add(&hfuzz->blCrashesCnt, 1UL);
return true;
}

bool dstFileExists = false;
if (files_copyFile(fuzzer->fileName, newname, &dstFileExists)) {
LOGMSG(l_INFO, "Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, newname);
LOG_I("Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, newname);
// Unique crashes
__sync_fetch_and_add(&hfuzz->uniqueCrashesCnt, 1UL);
} else {
if (dstFileExists) {
LOGMSG(l_INFO, "It seems that '%s' already exists, skipping", newname);
LOG_I("It seems that '%s' already exists, skipping", newname);
} else {
LOGMSG(l_ERROR, "Couldn't copy '%s' to '%s'", fuzzer->fileName, newname);
LOG_E("Couldn't copy '%s' to '%s'", fuzzer->fileName, newname);
}
}

@@ -277,7 +274,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)

args[x++] = NULL;

LOGMSG(l_DEBUG, "Launching '%s' on file '%s'", args[0], fileName);
LOG_D("Launching '%s' on file '%s'", args[0], fileName);

/*
* Get child's bootstrap port.
@@ -322,7 +319,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
if (setitimer(ITIMER_PROF, &it, NULL) == -1) {
LOGMSG_P(l_ERROR, "Couldn't set the ITIMER_PROF timer");
PLOG_E("Couldn't set the ITIMER_PROF timer");
return false;
}

@@ -335,7 +332,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
LOGMSG_P(l_ERROR, "Couldn't set the ITIMER_REAL timer");
PLOG_E("Couldn't set the ITIMER_REAL timer");
return false;
}

@@ -350,7 +347,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
rl.rlim_cur = hfuzz->tmOut + 1;
rl.rlim_max = hfuzz->tmOut + 1;
if (setrlimit(RLIMIT_CPU, &rl) == -1) {
LOGMSG_P(l_ERROR, "Couldn't enforce the RLIMIT_CPU resource limit");
PLOG_E("Couldn't enforce the RLIMIT_CPU resource limit");
return false;
}
}
@@ -364,7 +361,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
rl.rlim_cur = hfuzz->asLimit * 1024UL * 1024UL;
rl.rlim_max = hfuzz->asLimit * 1024UL * 1024UL;
if (setrlimit(RLIMIT_AS, &rl) == -1) {
LOGMSG_P(l_DEBUG, "Couldn't enforce the RLIMIT_AS resource limit, ignoring");
PLOG_D("Couldn't enforce the RLIMIT_AS resource limit, ignoring");
}
}

@@ -388,7 +385,7 @@ bool arch_launchChild(honggfuzz_t * hfuzz, char *fileName)
execvp(args[0], args);

util_recoverStdio();
LOGMSG(l_FATAL, "Failed to create new '%s' process", args[0]);
LOG_F("Failed to create new '%s' process", args[0]);
return false;
}

@@ -400,8 +397,8 @@ static void arch_checkTimeLimit(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
int64_t curMillis = util_timeNowMillis();
int64_t diffMillis = curMillis - fuzzer->timeStartedMillis;
if (diffMillis > ((hfuzz->tmOut + 2) * 1000)) {
LOGMSG(l_WARN, "PID %d took too much time (limit %ld s). Sending SIGKILL",
fuzzer->pid, hfuzz->tmOut);
LOG_W("PID %d took too much time (limit %ld s). Sending SIGKILL",
fuzzer->pid, hfuzz->tmOut);
kill(fuzzer->pid, SIGKILL);
}
}
@@ -429,7 +426,7 @@ void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
usleep(0.20 * 1000000);
}
}
LOGMSG(l_DEBUG, "Process (pid %d) came back with status %d", fuzzer->pid, status);
LOG_D("Process (pid %d) came back with status %d", fuzzer->pid, status);

if (arch_analyzeSignal(hfuzz, status, fuzzer)) {
return;
@@ -454,8 +451,8 @@ bool arch_archInit(honggfuzz_t * hfuzz)
getlogin());

if (files_exists(plist)) {
LOGMSG(l_WARN,
"honggfuzz won't work if DBGShellCommands are set in ~/Library/Preferences/com.apple.DebugSymbols.plist");
LOG_W
("honggfuzz won't work if DBGShellCommands are set in ~/Library/Preferences/com.apple.DebugSymbols.plist");
}

/*
@@ -499,12 +496,12 @@ bool arch_archInit(honggfuzz_t * hfuzz)
pthread_t exception_thread;

if (pthread_create(&exception_thread, NULL, wait_for_exception, 0)) {
LOGMSG(l_FATAL, "Parent: could not create thread to wait for child's exception");
LOG_F("Parent: could not create thread to wait for child's exception");
return false;
}

if (pthread_detach(exception_thread)) {
LOGMSG(l_FATAL, "Parent: could not detach thread to wait for child's exception");
LOG_F("Parent: could not detach thread to wait for child's exception");
return false;
}

@@ -540,7 +537,7 @@ write_crash_report(thread_port_t thread,
NSString *crashDescription =[_crashReport description];
char *description = (char *)[crashDescription UTF8String];

LOGMSG(l_DEBUG, "CrashReport: %s", description);
LOG_D("CrashReport: %s", description);

[_crashReport release];
[pool drain];
@@ -579,7 +576,7 @@ uint64_t hash_callstack(thread_port_t thread,
char *callstack = strstr(description, "Crashed:");

if (callstack == NULL) {
LOGMSG(l_FATAL, "Could not find callstack in crash report %s", description);
LOG_F("Could not find callstack in crash report %s", description);
}

/*
@@ -588,7 +585,7 @@ uint64_t hash_callstack(thread_port_t thread,
char *callstack_start = strstr(callstack, "\n");

if (callstack_start == NULL) {
LOGMSG(l_FATAL, "Could not find callstack start in crash report %s", description);
LOG_F("Could not find callstack start in crash report %s", description);
}

/*
@@ -602,7 +599,7 @@ uint64_t hash_callstack(thread_port_t thread,
char *callstack_end = strstr(callstack, "\n\nThread");

if (callstack_end == NULL) {
LOGMSG(l_FATAL, "Could not find callstack end in crash report %s", description);
LOG_F("Could not find callstack end in crash report %s", description);
}

/*
@@ -671,7 +668,7 @@ uint64_t hash_callstack(thread_port_t thread,
pos++;
}

LOGMSG(l_DEBUG, "Callstack hash %u", hash);
LOG_D("Callstack hash %u", hash);

[_crashReport release];
[pool drain];
@@ -686,7 +683,7 @@ catch_mach_exception_raise(mach_port_t exception_port,
exception_type_t exception, mach_exception_data_t code,
mach_msg_type_number_t codeCnt)
{
LOGMSG(l_FATAL, "This function should never get called");
LOG_F("This function should never get called");
return KERN_SUCCESS;
}

@@ -700,7 +697,7 @@ catch_mach_exception_raise_state(mach_port_t exception_port,
mach_msg_type_number_t old_stateCnt,
thread_state_t new_state, mach_msg_type_number_t * new_stateCnt)
{
LOGMSG(l_FATAL, "This function should never get called");
LOG_F("This function should never get called");
return KERN_SUCCESS;
}

@@ -719,15 +716,15 @@ kern_return_t catch_mach_exception_raise_state_identity( __attribute__ ((unused)
mach_msg_type_number_t * out_state_count)
{
if (exception != EXC_CRASH) {
LOGMSG(l_FATAL, "Got non EXC_CRASH! This should not happen.");
LOG_F("Got non EXC_CRASH! This should not happen.");
}

/*
* We will save our results to the honggfuzz_t global
*/
pid_t pid;
pid_for_task(task, &pid);
LOGMSG(l_DEBUG, "Crash of pid %d", pid);
LOG_D("Crash of pid %d", pid);

fuzzer_t *fuzzer = &g_fuzzer_crash_information[pid];

@@ -782,11 +779,11 @@ kern_return_t catch_mach_exception_raise_state_identity( __attribute__ ((unused)
*/

if (mach_port_deallocate(mach_task_self(), task) != KERN_SUCCESS) {
LOGMSG(l_WARN, "Exception Handler: Could not deallocate task");
LOG_W("Exception Handler: Could not deallocate task");
}

if (mach_port_deallocate(mach_task_self(), thread) != KERN_SUCCESS) {
LOGMSG(l_WARN, "Exception Handler: Could not deallocate thread");
LOG_W("Exception Handler: Could not deallocate thread");
}

return KERN_SUCCESS; // KERN_SUCCESS indicates that this should
8 changes: 4 additions & 4 deletions mangle.c
Original file line number Diff line number Diff line change
@@ -286,7 +286,7 @@ static void mangle_AddSub(honggfuzz_t * hfuzz, uint8_t * buf, size_t bufSz, size
}
default:
{
LOGMSG(l_FATAL, "Unknown variable length size: %" PRId64, varLen);
LOG_F("Unknown variable length size: %" PRId64, varLen);
break;
}
}
@@ -409,7 +409,7 @@ bool mangle_Resize(honggfuzz_t * hfuzz, uint8_t * buf, size_t * bufSz)
delta -= (int)(mangle_ExpDist() * (double)(*bufSz));
break;
default:
LOGMSG(l_FATAL, "Random value out of scope %u", val);
LOG_F("Random value out of scope %u", val);
break;
}

@@ -426,8 +426,8 @@ bool mangle_Resize(honggfuzz_t * hfuzz, uint8_t * buf, size_t * bufSz)
util_rndBuf(&buf[*bufSz], newSz - *bufSz);
}

LOGMSG(l_DEBUG, "Current size: %zu, Maximal size: %zu, New Size: %zu, Delta: %d", *bufSz,
hfuzz->maxFileSz, newSz, delta);
LOG_D("Current size: %zu, Maximal size: %zu, New Size: %zu, Delta: %d", *bufSz,
hfuzz->maxFileSz, newSz, delta);

*bufSz = (size_t) newSz;
return true;
Loading

0 comments on commit c8c32db

Please sign in to comment.