bool files_writePatternToFd(int fd, off_t size, unsigned char p) { void *buf = malloc(size); if (!buf) { PLOG_W("Couldn't allocate memory"); return false; } defer { free(buf); }; memset(buf, p, (size_t) size); int ret = files_writeToFd(fd, buf, size); return ret; }
bool files_writeBufToFile(char *fileName, uint8_t * buf, size_t fileSz, int flags) { int fd = open(fileName, flags, 0644); if (fd == -1) { PLOG_W("Couldn't open '%s' for R/O", fileName); return false; } defer { close(fd); }; if (files_writeToFd(fd, buf, fileSz) == false) { PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName, fd); unlink(fileName); return false; } LOG_D("Written '%zu' bytes to '%s'", fileSz, fileName); return true; }
static bool fuzz_prepareFile(honggfuzz_t * hfuzz, char *fileName) { int rnd_index = util_rndGet(0, hfuzz->fileCnt - 1); off_t fileSz; int srcfd; uint8_t *buf = files_mapFileToRead(hfuzz->files[rnd_index], &fileSz, &srcfd); if (buf == NULL) { LOGMSG(l_ERROR, "Couldn't open and map '%s' in R/O mode", hfuzz->files[rnd_index]); return false; } LOGMSG(l_DEBUG, "Mmaped '%s' in R/O mode, size: %d", hfuzz->files[rnd_index], fileSz); int dstfd = open(fileName, O_CREAT | O_EXCL | O_RDWR, 0644); if (dstfd == -1) { LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s' in the current directory", fileName); munmap(buf, fileSz); close(srcfd); return false; } fuzz_mangleContent(hfuzz, buf, fileSz); if (!files_writeToFd(dstfd, buf, fileSz)) { munmap(buf, fileSz); close(srcfd); close(dstfd); return false; } munmap(buf, fileSz); close(srcfd); close(dstfd); return true; }
static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { 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' in the current directory", fuzzer->fileName); return false; } LOGMSG(l_DEBUG, "Created '%f' 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]); unlink(fuzzer->fileName); return false; } if (files_writeToFd(dstfd, fuzzer->dynamicFile, fileSz) == false) { close(dstfd); unlink(fuzzer->fileName); return false; } } close(dstfd); pid_t pid = fork(); if (pid == -1) { LOGMSG_P(l_ERROR, "Couldn't vfork"); return false; } if (!pid) { /* * 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); return false; } /* * parent waits until child is done fuzzing the input file */ int childStatus; int flags = 0; #if defined(__WNOTHREAD) flags |= __WNOTHREAD; #endif /* defined(__WNOTHREAD) */ while (wait4(pid, &childStatus, flags, NULL) != pid) ; if (WIFEXITED(childStatus)) { LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus)); return true; } if (WIFSIGNALED(childStatus)) { LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus)); return false; } LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus); return false; abort(); /* NOTREACHED */ }
/* * dstExists argument can be used by caller for cases where existing destination * file requires special handling (e.g. save unique crashes) */ bool files_copyFile(const char *source, const char *destination, bool * dstExists) { if (dstExists) *dstExists = false; if (link(source, destination) == 0) { return true; } else { if (errno == EEXIST) { // Should kick-in before MAC, so avoid the hassle if (dstExists) *dstExists = true; return false; } else { 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) */ } } // Now try with a verbose POSIX alternative int inFD, outFD, dstOpenFlags; mode_t dstFilePerms; // O_EXCL is important for saving unique crashes dstOpenFlags = O_CREAT | O_WRONLY | O_EXCL; dstFilePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; inFD = open(source, O_RDONLY); if (inFD == -1) { PLOG_D("Couldn't open '%s' source", source); return false; } defer { close(inFD); }; struct stat inSt; if (fstat(inFD, &inSt) == -1) { PLOG_W("Couldn't fstat(fd='%d' fileName='%s')", inFD, source); return false; } outFD = open(destination, dstOpenFlags, dstFilePerms); if (outFD == -1) { if (errno == EEXIST) { if (dstExists) *dstExists = true; } PLOG_D("Couldn't open '%s' destination", destination); return false; } defer { close(outFD); }; uint8_t *inFileBuf = malloc(inSt.st_size); if (!inFileBuf) { PLOG_W("malloc(%zu) failed", (size_t) inSt.st_size); return false; } defer { free(inFileBuf); }; ssize_t readSz = files_readFromFd(inFD, inFileBuf, (size_t) inSt.st_size); if (readSz < 0) { PLOG_W("Couldn't read '%s' to a buf", source); return false; } if (files_writeToFd(outFD, inFileBuf, readSz) == false) { PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", (size_t) readSz, destination, outFD); unlink(destination); return false; } return true; }
bool files_writeStrToFd(int fd, char *str) { return files_writeToFd(fd, (uint8_t *) str, strlen(str)); }
static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, char *fileName) { int rnd_index = util_rndGet(0, hfuzz->fileCnt - 1); off_t fileSz; int srcfd; int dstfd = open(fileName, O_CREAT | O_EXCL | O_RDWR, 0644); if (dstfd == -1) { LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s' in the current directory", fileName); return false; } LOGMSG(l_DEBUG, "Created '%f' as an input file", fileName); if (hfuzz->inputFile) { uint8_t *buf = files_mapFileToRead(hfuzz->files[rnd_index], &fileSz, &srcfd); if (buf == NULL) { LOGMSG(l_ERROR, "Couldn't open and map '%s' in R/O mode", hfuzz->files[rnd_index]); close(dstfd); return false; } LOGMSG(l_DEBUG, "Mmaped '%s' in R/O mode, size: %d", hfuzz->files[rnd_index], fileSz); bool ret = files_writeToFd(dstfd, buf, fileSz); munmap(buf, fileSz); close(srcfd); if (!ret) { close(dstfd); return false; } } close(dstfd); pid_t pid = fork(); if (pid == -1) { LOGMSG_P(l_ERROR, "Couldn't fork"); return false; } if (!pid) { /* * child does the external file modifications */ execl(hfuzz->externalCommand, hfuzz->externalCommand, fileName, NULL); LOGMSG_P(l_FATAL, "Couldn't execute '%s %s'", hfuzz->externalCommand, fileName); return false; } else { /* * parent waits until child is done fuzzing the input file */ int childStatus; pid_t terminatedPid; do { terminatedPid = wait(&childStatus); } while (terminatedPid != pid); if (WIFEXITED(childStatus)) { LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus)); return true; } else if (WIFSIGNALED(childStatus)) { LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus)); return false; } LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus); return false; } abort(); /* NOTREACHED */ }