blob: 2e03621a931d97f07007dfe0d05fbedb83e0f7a8 [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com81189852015-02-14 23:44:55 +00003 * honggfuzz - file operations
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00006 * Author: Robert Swiecki <swiecki@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00007 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00008 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000012 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000013 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000021 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000022 */
robert.swiecki3bb518c2010-10-14 00:48:24 +000023
robert.swiecki3bb518c2010-10-14 00:48:24 +000024#include "common.h"
25#include "files.h"
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000026
27#include <dirent.h>
28#include <errno.h>
29#include <fcntl.h>
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +000030#include <inttypes.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000031#include <stdint.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/mman.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <unistd.h>
39
robert.swiecki3bb518c2010-10-14 00:48:24 +000040#include "log.h"
Robert Swiecki0fc5e942016-03-15 15:49:12 +010041#include "util.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000042
Robert Swieckidecf14b2016-03-31 15:09:28 +020043ssize_t files_readFileToBufMax(char *fileName, uint8_t * buf, size_t fileMaxSz)
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000044{
45 int fd = open(fileName, O_RDONLY);
46 if (fd == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +020047 PLOG_W("Couldn't open '%s' for R/O", fileName);
Robert Swieckidecf14b2016-03-31 15:09:28 +020048 return -1;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000049 }
Jagger4fe18692016-04-22 23:15:07 +020050 defer {
51 close(fd);
52 };
Robert Swieckia9db9dd2016-03-09 16:29:37 +010053
Robert Swieckidecf14b2016-03-31 15:09:28 +020054 ssize_t readSz = files_readFromFd(fd, buf, fileMaxSz);
55 if (readSz < 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +020056 LOG_W("Couldn't read '%s' to a buf", fileName);
Jagger1aa94d72016-04-02 02:37:35 +020057 return -1;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000058 }
59
Jagger4d109852016-02-04 02:28:44 +010060 LOG_D("Read '%zu' bytes from '%s'", readSz, fileName);
Jagger4d109852016-02-04 02:28:44 +010061 return readSz;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000062}
63
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000064bool files_writeBufToFile(char *fileName, uint8_t * buf, size_t fileSz, int flags)
65{
66 int fd = open(fileName, flags, 0644);
67 if (fd == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +020068 PLOG_W("Couldn't open '%s' for R/O", fileName);
robert.swiecki@gmail.com276f9f12015-03-01 01:39:47 +000069 return false;
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000070 }
Jagger4fe18692016-04-22 23:15:07 +020071 defer {
72 close(fd);
73 };
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000074
75 if (files_writeToFd(fd, buf, fileSz) == false) {
Robert Swieckibc7532e2016-08-20 00:34:17 +020076 PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName, fd);
robert.swiecki@gmail.com9be63de2015-03-02 07:08:45 +000077 unlink(fileName);
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000078 return false;
79 }
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000080
Robert Swieckic8c32db2015-10-09 18:06:22 +020081 LOG_D("Written '%zu' bytes to '%s'", fileSz, fileName);
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000082 return true;
83}
84
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000085bool files_writeToFd(int fd, uint8_t * buf, size_t fileSz)
robert.swiecki3bb518c2010-10-14 00:48:24 +000086{
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000087 size_t writtenSz = 0;
88 while (writtenSz < fileSz) {
89 ssize_t sz = write(fd, &buf[writtenSz], fileSz - writtenSz);
robert.swiecki3bb518c2010-10-14 00:48:24 +000090 if (sz < 0 && errno == EINTR)
91 continue;
92
93 if (sz < 0)
94 return false;
95
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000096 writtenSz += sz;
robert.swiecki3bb518c2010-10-14 00:48:24 +000097 }
robert.swiecki3bb518c2010-10-14 00:48:24 +000098 return true;
99}
100
robert.swiecki@gmail.comad6af222015-02-14 01:56:08 +0000101bool files_writeStrToFd(int fd, char *str)
102{
103 return files_writeToFd(fd, (uint8_t *) str, strlen(str));
104}
105
Robert Swieckidecf14b2016-03-31 15:09:28 +0200106ssize_t files_readFromFd(int fd, uint8_t * buf, size_t fileSz)
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000107{
108 size_t readSz = 0;
109 while (readSz < fileSz) {
110 ssize_t sz = read(fd, &buf[readSz], fileSz - readSz);
111 if (sz < 0 && errno == EINTR)
112 continue;
113
Robert Swieckidecf14b2016-03-31 15:09:28 +0200114 if (sz == 0)
Jagger4d109852016-02-04 02:28:44 +0100115 break;
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000116
Robert Swieckidecf14b2016-03-31 15:09:28 +0200117 if (sz < 0)
118 return -1;
119
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000120 readSz += sz;
121 }
Robert Swieckidecf14b2016-03-31 15:09:28 +0200122 return (ssize_t) readSz;
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000123}
124
groebert@google.com1bd4c212013-06-19 11:13:56 +0000125bool files_exists(char *fileName)
126{
127 return (access(fileName, F_OK) != -1);
128}
129
robert.swiecki3bb518c2010-10-14 00:48:24 +0000130bool files_writePatternToFd(int fd, off_t size, unsigned char p)
131{
132 void *buf = malloc(size);
133 if (!buf) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200134 PLOG_W("Couldn't allocate memory");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000135 return false;
136 }
Jagger4fe18692016-04-22 23:15:07 +0200137 defer {
138 free(buf);
139 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000140
141 memset(buf, p, (size_t) size);
142 int ret = files_writeToFd(fd, buf, size);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000143
144 return ret;
145}
146
robert.swiecki3bb518c2010-10-14 00:48:24 +0000147static bool files_readdir(honggfuzz_t * hfuzz)
148{
Jagger1b2d4822016-09-25 16:19:45 +0200149 DIR *dir = opendir(hfuzz->inputDir);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000150 if (!dir) {
Jagger1b2d4822016-09-25 16:19:45 +0200151 PLOG_W("Couldn't open dir '%s'", hfuzz->inputDir);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000152 return false;
153 }
Jagger4fe18692016-04-22 23:15:07 +0200154 defer {
155 closedir(dir);
156 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000157
Jaggerf4a60562016-09-25 15:40:23 +0200158 size_t maxSize = 0UL;
159 unsigned count = 0;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000160 for (;;) {
Jaggerad076932016-08-24 02:40:19 +0200161 errno = 0;
Jaggerf2723e12016-08-23 23:47:19 +0200162 struct dirent *res = readdir(dir);
163 if (res == NULL && errno != 0) {
Jagger1b2d4822016-09-25 16:19:45 +0200164 PLOG_W("Couldn't read the '%s' dir", hfuzz->inputDir);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000165 return false;
166 }
167
Jaggerf4a60562016-09-25 15:40:23 +0200168 if (res == NULL) {
169 break;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000170 }
171
172 char path[PATH_MAX];
Jagger1b2d4822016-09-25 16:19:45 +0200173 snprintf(path, sizeof(path), "%s/%s", hfuzz->inputDir, res->d_name);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000174 struct stat st;
175 if (stat(path, &st) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200176 LOG_W("Couldn't stat() the '%s' file", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000177 continue;
178 }
179
180 if (!S_ISREG(st.st_mode)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200181 LOG_D("'%s' is not a regular file, skipping", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000182 continue;
183 }
184
robert.swiecki@gmail.comc1b759b2015-03-01 18:41:15 +0000185 if (st.st_size == 0ULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200186 LOG_D("'%s' is empty", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000187 continue;
188 }
189
Jaggerf4a60562016-09-25 15:40:23 +0200190 if (hfuzz->maxFileSz != 0UL && st.st_size > (off_t) hfuzz->maxFileSz) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200191 LOG_W("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %"
192 PRId64, path, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +0000193 continue;
194 }
195
Jaggerf4a60562016-09-25 15:40:23 +0200196 if ((size_t) st.st_size > maxSize) {
197 maxSize = st.st_size;
198 }
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200199
200 struct paths_t *file = (struct paths_t *)util_Malloc(sizeof(struct paths_t));
201 snprintf(file->path, sizeof(file->path), "%s", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000202 hfuzz->fileCnt = ++count;
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200203 TAILQ_INSERT_TAIL(&hfuzz->fileq, file, pointers);
204
Robert Swieckic8c32db2015-10-09 18:06:22 +0200205 LOG_D("Added '%s' to the list of input files", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000206 }
207
Jaggerf4a60562016-09-25 15:40:23 +0200208 if (count == 0) {
Jagger1b2d4822016-09-25 16:19:45 +0200209 LOG_W("Directory '%s' doesn't contain any regular files", hfuzz->inputDir);
Jaggerf4a60562016-09-25 15:40:23 +0200210 return false;
211 }
212
213 if (hfuzz->maxFileSz == 0UL) {
214 hfuzz->maxFileSz = maxSize;
215 }
216 LOG_I("%zu input files have been added to the list. Max file size: %zu", hfuzz->fileCnt,
217 hfuzz->maxFileSz);
218 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000219}
220
221bool files_init(honggfuzz_t * hfuzz)
222{
Jaggera34b3022016-04-02 02:20:40 +0200223 if (hfuzz->externalCommand) {
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200224 struct paths_t *file = (struct paths_t *)util_Malloc(sizeof(struct paths_t));
225 snprintf(file->path, sizeof(file->path), "NONE");
226 hfuzz->fileCnt = 1;
227 TAILQ_INSERT_TAIL(&hfuzz->fileq, file, pointers);
228
Robert Swieckic8c32db2015-10-09 18:06:22 +0200229 LOG_I
Jaggera34b3022016-04-02 02:20:40 +0200230 ("No input file corpus loaded, the external command '%s' is responsible for creating the fuzz files",
Robert Swieckic8c32db2015-10-09 18:06:22 +0200231 hfuzz->externalCommand);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000232 return true;
233 }
234
Jagger1b2d4822016-09-25 16:19:45 +0200235 if (!hfuzz->inputDir) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200236 LOG_W("No input file/dir specified");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000237 return false;
238 }
239
240 struct stat st;
Jagger1b2d4822016-09-25 16:19:45 +0200241 if (stat(hfuzz->inputDir, &st) == -1) {
242 PLOG_W("Couldn't stat the input dir '%s'", hfuzz->inputDir);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000243 return false;
244 }
245
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200246 if (!S_ISDIR(st.st_mode)) {
247 LOG_W("The initial corpus directory '%s' is not a directory", hfuzz->inputDir);
248 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000249 }
250
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200251 return files_readdir(hfuzz);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000252}
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000253
Robert Swieckidecf14b2016-03-31 15:09:28 +0200254const char *files_basename(char *path)
groebert@google.com1bd4c212013-06-19 11:13:56 +0000255{
Robert Swieckidecf14b2016-03-31 15:09:28 +0200256 const char *base = strrchr(path, '/');
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000257 return base ? base + 1 : path;
258}
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000259
260bool files_parseDictionary(honggfuzz_t * hfuzz)
261{
262 FILE *fDict = fopen(hfuzz->dictionaryFile, "rb");
263 if (fDict == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200264 PLOG_W("Couldn't open '%s' - R/O mode", hfuzz->dictionaryFile);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000265 return false;
266 }
Jagger4fe18692016-04-22 23:15:07 +0200267 defer {
268 fclose(fDict);
269 };
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000270
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000271 for (;;) {
Robert Swieckicaf9d762016-03-10 16:13:18 +0100272 char *lineptr = NULL;
273 size_t n = 0;
Jaggerc64c9eb2016-09-22 04:04:34 +0200274 ssize_t len = getdelim(&lineptr, &n, '\n', fDict);
275 if (len == -1) {
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000276 break;
277 }
Jaggerc64c9eb2016-09-22 04:04:34 +0200278 if (n > 1 && lineptr[len - 1] == '\n') {
Robert Swieckidfef8542016-09-13 18:06:46 +0200279 lineptr[len - 1] = '\0';
Jaggerc64c9eb2016-09-22 04:04:34 +0200280 len--;
Robert Swieckidfef8542016-09-13 18:06:46 +0200281 }
Robert Swiecki531438a2016-09-13 19:05:11 +0200282
283 struct strings_t *str = (struct strings_t *)util_Malloc(sizeof(struct strings_t));
Jaggerd619ed12016-09-22 04:08:49 +0200284 str->len = util_decodeCString(lineptr);
285 str->s = lineptr;
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000286 hfuzz->dictionaryCnt += 1;
Robert Swiecki3a572262016-10-04 01:48:34 +0200287 TAILQ_INSERT_TAIL(&hfuzz->dictq, str, pointers);
Robert Swiecki531438a2016-09-13 19:05:11 +0200288
Jaggerc64c9eb2016-09-22 04:04:34 +0200289 LOG_D("Dictionary: loaded word: '%s' (len=%zu)", str->s, str->len);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000290 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200291 LOG_I("Loaded %zu words from the dictionary", hfuzz->dictionaryCnt);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000292 return true;
293}
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300294
295/*
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300296 * dstExists argument can be used by caller for cases where existing destination
297 * file requires special handling (e.g. save unique crashes)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300298 */
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300299bool files_copyFile(const char *source, const char *destination, bool * dstExists)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300300{
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300301 if (dstExists)
302 *dstExists = false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300303 if (link(source, destination) == 0) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300304 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300305 } else {
306 if (errno == EEXIST) {
307 // Should kick-in before MAC, so avoid the hassle
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300308 if (dstExists)
309 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300310 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300311 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200312 PLOG_D("Couldn't link '%s' as '%s'", source, destination);
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300313 /*
314 * Don't fail yet as we might have a running env which doesn't allow
315 * hardlinks (e.g. SELinux)
316 */
317 }
318 }
319
320 // Now try with a verbose POSIX alternative
321 int inFD, outFD, dstOpenFlags;
322 mode_t dstFilePerms;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300323
324 // O_EXCL is important for saving unique crashes
325 dstOpenFlags = O_CREAT | O_WRONLY | O_EXCL;
326 dstFilePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
327
328 inFD = open(source, O_RDONLY);
329 if (inFD == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200330 PLOG_D("Couldn't open '%s' source", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300331 return false;
332 }
Jagger4fe18692016-04-22 23:15:07 +0200333 defer {
334 close(inFD);
335 };
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300336
337 struct stat inSt;
338 if (fstat(inFD, &inSt) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200339 PLOG_W("Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300340 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300341 }
342
343 outFD = open(destination, dstOpenFlags, dstFilePerms);
344 if (outFD == -1) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300345 if (errno == EEXIST) {
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300346 if (dstExists)
347 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300348 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200349 PLOG_D("Couldn't open '%s' destination", destination);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300350 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300351 }
Jagger4fe18692016-04-22 23:15:07 +0200352 defer {
353 close(outFD);
354 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300355
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300356 uint8_t *inFileBuf = malloc(inSt.st_size);
357 if (!inFileBuf) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200358 PLOG_W("malloc(%zu) failed", (size_t) inSt.st_size);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300359 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300360 }
Jagger4fe18692016-04-22 23:15:07 +0200361 defer {
362 free(inFileBuf);
363 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300364
Robert Swieckidecf14b2016-03-31 15:09:28 +0200365 ssize_t readSz = files_readFromFd(inFD, inFileBuf, (size_t) inSt.st_size);
366 if (readSz < 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200367 PLOG_W("Couldn't read '%s' to a buf", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300368 return false;
369 }
370
Jagger4d109852016-02-04 02:28:44 +0100371 if (files_writeToFd(outFD, inFileBuf, readSz) == false) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200372 PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", (size_t) readSz,
Robert Swieckic8c32db2015-10-09 18:06:22 +0200373 destination, outFD);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300374 unlink(destination);
375 return false;
376 }
377
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300378 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300379}
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300380
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300381bool files_parseBlacklist(honggfuzz_t * hfuzz)
382{
383 FILE *fBl = fopen(hfuzz->blacklistFile, "rb");
384 if (fBl == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200385 PLOG_W("Couldn't open '%s' - R/O mode", hfuzz->blacklistFile);
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300386 return false;
387 }
Jagger4fe18692016-04-22 23:15:07 +0200388 defer {
389 fclose(fBl);
390 };
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300391
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200392 char *lineptr = NULL;
Jagger1dad1822016-03-29 23:56:14 +0200393 /* lineptr can be NULL, but it's fine for free() */
Jagger4fe18692016-04-22 23:15:07 +0200394 defer {
395 free(lineptr);
396 };
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200397 size_t n = 0;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300398 for (;;) {
Anestis Bechtsoudis7d6185c2015-09-21 15:59:56 +0300399 if (getline(&lineptr, &n, fBl) == -1) {
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300400 break;
401 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300402
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300403 if ((hfuzz->blacklist =
Jaggerf49962d2016-07-21 22:49:54 +0200404 util_Realloc(hfuzz->blacklist,
405 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]))) == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200406 PLOG_W("realloc failed (sz=%zu)",
Robert Swieckic8c32db2015-10-09 18:06:22 +0200407 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]));
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300408 return false;
409 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300410
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300411 hfuzz->blacklist[hfuzz->blacklistCnt] = strtoull(lineptr, 0, 16);
Anestis Bechtsoudis07e14ce2015-12-30 14:15:42 +0200412 LOG_D("Blacklist: loaded %'" PRIu64 "'", hfuzz->blacklist[hfuzz->blacklistCnt]);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300413
414 // Verify entries are sorted so we can use interpolation search
415 if (hfuzz->blacklistCnt > 1) {
416 if (hfuzz->blacklist[hfuzz->blacklistCnt - 1] > hfuzz->blacklist[hfuzz->blacklistCnt]) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200417 LOG_F
418 ("Blacklist file not sorted. Use 'tools/createStackBlacklist.sh' to sort records");
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300419 return false;
420 }
421 }
Anestis Bechtsoudis612baa52015-09-23 18:21:43 +0300422 hfuzz->blacklistCnt += 1;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300423 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300424
Anestis Bechtsoudisebf879e2015-09-27 18:11:25 +0300425 if (hfuzz->blacklistCnt > 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200426 LOG_I("Loaded %zu stack hash(es) from the blacklist file", hfuzz->blacklistCnt);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300427 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200428 LOG_F("Empty stack hashes blacklist file '%s'", hfuzz->blacklistFile);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300429 }
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300430 return true;
431}
Anestis Bechtsoudisee5316d2015-09-27 19:11:48 +0300432
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300433uint8_t *files_mapFile(char *fileName, off_t * fileSz, int *fd, bool isWritable)
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300434{
435 int mmapProt = PROT_READ;
436 if (isWritable) {
437 mmapProt |= PROT_WRITE;
438 }
439
440 if ((*fd = open(fileName, O_RDONLY)) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200441 PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300442 return NULL;
443 }
444
445 struct stat st;
446 if (fstat(*fd, &st) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200447 PLOG_W("Couldn't stat() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300448 close(*fd);
449 return NULL;
450 }
451
452 uint8_t *buf;
453 if ((buf = mmap(NULL, st.st_size, mmapProt, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200454 PLOG_W("Couldn't mmap() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300455 close(*fd);
456 return NULL;
457 }
458
459 *fileSz = st.st_size;
460 return buf;
461}
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200462
Jagger41e7ffc2016-07-23 03:50:32 +0200463uint8_t *files_mapFileShared(char *fileName, off_t * fileSz, int *fd)
464{
465 if ((*fd = open(fileName, O_RDONLY)) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200466 PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200467 return NULL;
468 }
469
470 struct stat st;
471 if (fstat(*fd, &st) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200472 PLOG_W("Couldn't stat() the '%s' file", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200473 close(*fd);
474 return NULL;
475 }
476
477 uint8_t *buf;
478 if ((buf = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, *fd, 0)) == MAP_FAILED) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200479 PLOG_W("Couldn't mmap() the '%s' file", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200480 close(*fd);
481 return NULL;
482 }
483
484 *fileSz = st.st_size;
485 return buf;
486}
487
Jagger5b81a502016-09-07 20:48:32 +0200488void *files_mapSharedMem(size_t sz, int *fd, const char *dir)
Jagger08a7e272016-08-28 17:25:41 +0200489{
Jagger5b81a502016-09-07 20:48:32 +0200490 char template[PATH_MAX];
491 snprintf(template, sizeof(template), "%s/hfuzz.XXXXXX", dir);
Jagger08a7e272016-08-28 17:25:41 +0200492 if ((*fd = mkstemp(template)) == -1) {
493 PLOG_W("mkstemp('%s')", template);
494 return MAP_FAILED;
495 }
496 unlink(template);
497 if (ftruncate(*fd, sz) == -1) {
498 PLOG_W("ftruncate(%d, %zu)", *fd, sz);
499 close(*fd);
Robert Swiecki19fa37a2016-10-27 19:20:13 +0200500 *fd = -1;
Jagger08a7e272016-08-28 17:25:41 +0200501 return MAP_FAILED;
502 }
503 void *ret = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
504 if (ret == MAP_FAILED) {
505 PLOG_W("mmap(sz=%zu, fd=%d)", sz, *fd);
Robert Swiecki19fa37a2016-10-27 19:20:13 +0200506 *fd = -1;
Jagger08a7e272016-08-28 17:25:41 +0200507 close(*fd);
508 return MAP_FAILED;
509 }
510 return ret;
511}
512
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200513bool files_readPidFromFile(const char *fileName, pid_t * pidPtr)
514{
Jaggerff2d20c2016-09-10 03:38:58 +0200515 FILE *fPID = fopen(fileName, "rbe");
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200516 if (fPID == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200517 PLOG_W("Couldn't open '%s' - R/O mode", fileName);
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200518 return false;
519 }
Jagger4fe18692016-04-22 23:15:07 +0200520 defer {
521 fclose(fPID);
522 };
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200523
524 char *lineptr = NULL;
525 size_t lineSz = 0;
Jaggerebaf01e2016-05-15 15:13:34 +0200526 defer {
527 free(lineptr);
528 };
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200529 if (getline(&lineptr, &lineSz, fPID) == -1) {
530 if (lineSz == 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200531 LOG_W("Empty PID file (%s)", fileName);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100532 return false;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200533 }
534 }
535
536 *pidPtr = atoi(lineptr);
537 if (*pidPtr < 1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200538 LOG_W("Invalid PID read from '%s' file", fileName);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100539 return false;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200540 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200541
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100542 return true;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200543}
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200544
545struct paths_t *files_getFileFromFileq(honggfuzz_t * hfuzz, size_t index)
546{
547 if (index >= hfuzz->fileCnt) {
548 LOG_F("File index: %zu >= fileCnt: %zu", index, hfuzz->fileCnt);
549 }
550
551 struct paths_t *file;
552 size_t i = 0;
553 TAILQ_FOREACH(file, &hfuzz->fileq, pointers) {
554 if (i++ == index) {
555 return file;
556 }
557 }
558
559 LOG_F("File index: %zu bigger than fileq size", index);
560 return NULL;
561}