blob: f20d1f3294e84b8f41a21571fc6691276c866f8f [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{
149 DIR *dir = opendir(hfuzz->inputFile);
150 if (!dir) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200151 PLOG_W("Couldn't open dir '%s'", hfuzz->inputFile);
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
158 int count = 0;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000159 for (;;) {
Jaggerad076932016-08-24 02:40:19 +0200160 errno = 0;
Jaggerf2723e12016-08-23 23:47:19 +0200161 struct dirent *res = readdir(dir);
162 if (res == NULL && errno != 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200163 PLOG_W("Couldn't read the '%s' dir", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000164 return false;
165 }
166
167 if (res == NULL && count > 0) {
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200168 LOG_I("%zu input files have been added to the list", hfuzz->fileCnt);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000169 return true;
170 }
171
172 if (res == NULL && count == 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200173 LOG_W("Directory '%s' doesn't contain any regular files", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000174 return false;
175 }
176
177 char path[PATH_MAX];
178 snprintf(path, sizeof(path), "%s/%s", hfuzz->inputFile, res->d_name);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000179 struct stat st;
180 if (stat(path, &st) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200181 LOG_W("Couldn't stat() the '%s' file", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000182 continue;
183 }
184
185 if (!S_ISREG(st.st_mode)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200186 LOG_D("'%s' is not a regular file, skipping", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000187 continue;
188 }
189
robert.swiecki@gmail.comc1b759b2015-03-01 18:41:15 +0000190 if (st.st_size == 0ULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200191 LOG_D("'%s' is empty", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000192 continue;
193 }
194
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +0000195 if (st.st_size > (off_t) hfuzz->maxFileSz) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200196 LOG_W("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %"
197 PRId64, path, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +0000198 continue;
199 }
200
Jaggerf49962d2016-07-21 22:49:54 +0200201 if (!(hfuzz->files = util_Realloc(hfuzz->files, sizeof(char *) * (count + 1)))) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200202 PLOG_W("Couldn't allocate memory");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000203 return false;
204 }
205
Jagger6539b3a2016-04-06 02:32:50 +0200206 hfuzz->files[count] = util_StrDup(path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000207 hfuzz->fileCnt = ++count;
Robert Swieckic8c32db2015-10-09 18:06:22 +0200208 LOG_D("Added '%s' to the list of input files", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000209 }
210
211 abort(); /* NOTREACHED */
212 return false;
213}
214
215bool files_init(honggfuzz_t * hfuzz)
216{
Robert Swiecki3a94db72016-03-15 15:48:33 +0100217 hfuzz->files = util_Malloc(sizeof(char *));
Jaggera34b3022016-04-02 02:20:40 +0200218 hfuzz->files[0] = "NONE";
Jagger30384ec2016-04-02 02:30:32 +0200219 hfuzz->fileCnt = 1;
Jaggera34b3022016-04-02 02:20:40 +0200220
221 if (hfuzz->externalCommand) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200222 LOG_I
Jaggera34b3022016-04-02 02:20:40 +0200223 ("No input file corpus loaded, the external command '%s' is responsible for creating the fuzz files",
Robert Swieckic8c32db2015-10-09 18:06:22 +0200224 hfuzz->externalCommand);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000225 return true;
226 }
227
robert.swiecki3bb518c2010-10-14 00:48:24 +0000228 if (!hfuzz->inputFile) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200229 LOG_W("No input file/dir specified");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000230 return false;
231 }
232
233 struct stat st;
234 if (stat(hfuzz->inputFile, &st) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200235 PLOG_W("Couldn't stat the input file/dir '%s'", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000236 return false;
237 }
238
239 if (S_ISDIR(st.st_mode)) {
240 return files_readdir(hfuzz);
241 }
242
243 if (!S_ISREG(st.st_mode)) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200244 LOG_W("'%s' is not a regular file, nor a directory", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000245 return false;
246 }
247
robert.swiecki@gmail.com2e0103f2015-03-30 01:38:12 +0000248 if (st.st_size > (off_t) hfuzz->maxFileSz) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200249 LOG_W("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %" PRId64,
Robert Swieckic8c32db2015-10-09 18:06:22 +0200250 hfuzz->inputFile, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
robert.swiecki@gmail.com2e0103f2015-03-30 01:38:12 +0000251 return false;
252 }
253
robert.swiecki3bb518c2010-10-14 00:48:24 +0000254 hfuzz->files[0] = hfuzz->inputFile;
255 hfuzz->fileCnt = 1;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000256 return true;
257}
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000258
Robert Swieckidecf14b2016-03-31 15:09:28 +0200259const char *files_basename(char *path)
groebert@google.com1bd4c212013-06-19 11:13:56 +0000260{
Robert Swieckidecf14b2016-03-31 15:09:28 +0200261 const char *base = strrchr(path, '/');
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000262 return base ? base + 1 : path;
263}
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000264
265bool files_parseDictionary(honggfuzz_t * hfuzz)
266{
267 FILE *fDict = fopen(hfuzz->dictionaryFile, "rb");
268 if (fDict == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200269 PLOG_W("Couldn't open '%s' - R/O mode", hfuzz->dictionaryFile);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000270 return false;
271 }
Jagger4fe18692016-04-22 23:15:07 +0200272 defer {
273 fclose(fDict);
274 };
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000275
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000276 for (;;) {
Robert Swieckicaf9d762016-03-10 16:13:18 +0100277 char *lineptr = NULL;
278 size_t n = 0;
Robert Swieckife8d2892016-09-13 17:57:27 +0200279 if (getdelim(&lineptr, &n, '\n', fDict) == -1) {
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000280 break;
281 }
Robert Swieckidfef8542016-09-13 18:06:46 +0200282 size_t len = strlen(lineptr);
283 if (len > 1 && lineptr[len - 1] == '\n') {
284 lineptr[len - 1] = '\0';
285 }
Robert Swiecki531438a2016-09-13 19:05:11 +0200286
287 struct strings_t *str = (struct strings_t *)util_Malloc(sizeof(struct strings_t));
288 str->s = util_decodeCString(lineptr);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000289 hfuzz->dictionaryCnt += 1;
Robert Swiecki531438a2016-09-13 19:05:11 +0200290
291 LOG_D("Dictionary: loaded word: '%s' (len=%zu)", str->s, strlen(str->s));
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000292 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200293 LOG_I("Loaded %zu words from the dictionary", hfuzz->dictionaryCnt);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000294 return true;
295}
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300296
297/*
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300298 * dstExists argument can be used by caller for cases where existing destination
299 * file requires special handling (e.g. save unique crashes)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300300 */
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300301bool files_copyFile(const char *source, const char *destination, bool * dstExists)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300302{
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300303 if (dstExists)
304 *dstExists = false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300305 if (link(source, destination) == 0) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300306 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300307 } else {
308 if (errno == EEXIST) {
309 // Should kick-in before MAC, so avoid the hassle
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300310 if (dstExists)
311 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300312 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300313 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200314 PLOG_D("Couldn't link '%s' as '%s'", source, destination);
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300315 /*
316 * Don't fail yet as we might have a running env which doesn't allow
317 * hardlinks (e.g. SELinux)
318 */
319 }
320 }
321
322 // Now try with a verbose POSIX alternative
323 int inFD, outFD, dstOpenFlags;
324 mode_t dstFilePerms;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300325
326 // O_EXCL is important for saving unique crashes
327 dstOpenFlags = O_CREAT | O_WRONLY | O_EXCL;
328 dstFilePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
329
330 inFD = open(source, O_RDONLY);
331 if (inFD == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200332 PLOG_D("Couldn't open '%s' source", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300333 return false;
334 }
Jagger4fe18692016-04-22 23:15:07 +0200335 defer {
336 close(inFD);
337 };
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300338
339 struct stat inSt;
340 if (fstat(inFD, &inSt) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200341 PLOG_W("Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300342 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300343 }
344
345 outFD = open(destination, dstOpenFlags, dstFilePerms);
346 if (outFD == -1) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300347 if (errno == EEXIST) {
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300348 if (dstExists)
349 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300350 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200351 PLOG_D("Couldn't open '%s' destination", destination);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300352 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300353 }
Jagger4fe18692016-04-22 23:15:07 +0200354 defer {
355 close(outFD);
356 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300357
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300358 uint8_t *inFileBuf = malloc(inSt.st_size);
359 if (!inFileBuf) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200360 PLOG_W("malloc(%zu) failed", (size_t) inSt.st_size);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300361 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300362 }
Jagger4fe18692016-04-22 23:15:07 +0200363 defer {
364 free(inFileBuf);
365 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300366
Robert Swieckidecf14b2016-03-31 15:09:28 +0200367 ssize_t readSz = files_readFromFd(inFD, inFileBuf, (size_t) inSt.st_size);
368 if (readSz < 0) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200369 PLOG_W("Couldn't read '%s' to a buf", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300370 return false;
371 }
372
Jagger4d109852016-02-04 02:28:44 +0100373 if (files_writeToFd(outFD, inFileBuf, readSz) == false) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200374 PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", (size_t) readSz,
Robert Swieckic8c32db2015-10-09 18:06:22 +0200375 destination, outFD);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300376 unlink(destination);
377 return false;
378 }
379
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300380 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300381}
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300382
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300383bool files_parseBlacklist(honggfuzz_t * hfuzz)
384{
385 FILE *fBl = fopen(hfuzz->blacklistFile, "rb");
386 if (fBl == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200387 PLOG_W("Couldn't open '%s' - R/O mode", hfuzz->blacklistFile);
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300388 return false;
389 }
Jagger4fe18692016-04-22 23:15:07 +0200390 defer {
391 fclose(fBl);
392 };
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300393
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200394 char *lineptr = NULL;
Jagger1dad1822016-03-29 23:56:14 +0200395 /* lineptr can be NULL, but it's fine for free() */
Jagger4fe18692016-04-22 23:15:07 +0200396 defer {
397 free(lineptr);
398 };
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200399 size_t n = 0;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300400 for (;;) {
Anestis Bechtsoudis7d6185c2015-09-21 15:59:56 +0300401 if (getline(&lineptr, &n, fBl) == -1) {
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300402 break;
403 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300404
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300405 if ((hfuzz->blacklist =
Jaggerf49962d2016-07-21 22:49:54 +0200406 util_Realloc(hfuzz->blacklist,
407 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]))) == NULL) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200408 PLOG_W("realloc failed (sz=%zu)",
Robert Swieckic8c32db2015-10-09 18:06:22 +0200409 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]));
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300410 return false;
411 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300412
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300413 hfuzz->blacklist[hfuzz->blacklistCnt] = strtoull(lineptr, 0, 16);
Anestis Bechtsoudis07e14ce2015-12-30 14:15:42 +0200414 LOG_D("Blacklist: loaded %'" PRIu64 "'", hfuzz->blacklist[hfuzz->blacklistCnt]);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300415
416 // Verify entries are sorted so we can use interpolation search
417 if (hfuzz->blacklistCnt > 1) {
418 if (hfuzz->blacklist[hfuzz->blacklistCnt - 1] > hfuzz->blacklist[hfuzz->blacklistCnt]) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200419 LOG_F
420 ("Blacklist file not sorted. Use 'tools/createStackBlacklist.sh' to sort records");
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300421 return false;
422 }
423 }
Anestis Bechtsoudis612baa52015-09-23 18:21:43 +0300424 hfuzz->blacklistCnt += 1;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300425 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300426
Anestis Bechtsoudisebf879e2015-09-27 18:11:25 +0300427 if (hfuzz->blacklistCnt > 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200428 LOG_I("Loaded %zu stack hash(es) from the blacklist file", hfuzz->blacklistCnt);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300429 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200430 LOG_F("Empty stack hashes blacklist file '%s'", hfuzz->blacklistFile);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300431 }
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300432 return true;
433}
Anestis Bechtsoudisee5316d2015-09-27 19:11:48 +0300434
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300435uint8_t *files_mapFile(char *fileName, off_t * fileSz, int *fd, bool isWritable)
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300436{
437 int mmapProt = PROT_READ;
438 if (isWritable) {
439 mmapProt |= PROT_WRITE;
440 }
441
442 if ((*fd = open(fileName, O_RDONLY)) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200443 PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300444 return NULL;
445 }
446
447 struct stat st;
448 if (fstat(*fd, &st) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200449 PLOG_W("Couldn't stat() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300450 close(*fd);
451 return NULL;
452 }
453
454 uint8_t *buf;
455 if ((buf = mmap(NULL, st.st_size, mmapProt, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200456 PLOG_W("Couldn't mmap() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300457 close(*fd);
458 return NULL;
459 }
460
461 *fileSz = st.st_size;
462 return buf;
463}
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200464
Jagger41e7ffc2016-07-23 03:50:32 +0200465uint8_t *files_mapFileShared(char *fileName, off_t * fileSz, int *fd)
466{
467 if ((*fd = open(fileName, O_RDONLY)) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200468 PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200469 return NULL;
470 }
471
472 struct stat st;
473 if (fstat(*fd, &st) == -1) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200474 PLOG_W("Couldn't stat() the '%s' file", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200475 close(*fd);
476 return NULL;
477 }
478
479 uint8_t *buf;
480 if ((buf = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, *fd, 0)) == MAP_FAILED) {
Robert Swieckibc7532e2016-08-20 00:34:17 +0200481 PLOG_W("Couldn't mmap() the '%s' file", fileName);
Jagger41e7ffc2016-07-23 03:50:32 +0200482 close(*fd);
483 return NULL;
484 }
485
486 *fileSz = st.st_size;
487 return buf;
488}
489
Jagger5b81a502016-09-07 20:48:32 +0200490void *files_mapSharedMem(size_t sz, int *fd, const char *dir)
Jagger08a7e272016-08-28 17:25:41 +0200491{
Jagger5b81a502016-09-07 20:48:32 +0200492 char template[PATH_MAX];
493 snprintf(template, sizeof(template), "%s/hfuzz.XXXXXX", dir);
Jagger08a7e272016-08-28 17:25:41 +0200494 if ((*fd = mkstemp(template)) == -1) {
495 PLOG_W("mkstemp('%s')", template);
496 return MAP_FAILED;
497 }
498 unlink(template);
499 if (ftruncate(*fd, sz) == -1) {
500 PLOG_W("ftruncate(%d, %zu)", *fd, sz);
501 close(*fd);
502 return MAP_FAILED;
503 }
504 void *ret = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
505 if (ret == MAP_FAILED) {
506 PLOG_W("mmap(sz=%zu, fd=%d)", sz, *fd);
507 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}