erofs-utils: add a prelimitary fuzzer
Signed-off-by: Gao Xiang <hsiangkao@aol.com>
diff --git a/include/erofs/config.h b/include/erofs/config.h
index 05fe6b2..9eab8c7 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -14,6 +14,7 @@
struct erofs_configure {
const char *c_version;
int c_dbg_lvl;
+ unsigned int c_fuzz_trapcount;
bool c_dry_run;
bool c_legacy_compress;
diff --git a/include/erofs/fuzzer.h b/include/erofs/fuzzer.h
new file mode 100644
index 0000000..9be456f
--- /dev/null
+++ b/include/erofs/fuzzer.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * erofs_utils/include/erofs/fuzzer.h
+ *
+ * Copyright (C) 2018 HUAWEI, Inc.
+ * http://www.huawei.com/
+ */
+#ifndef __EROFS_FUZZER_H
+#define __EROFS_FUZZER_H
+
+#include "internal.h"
+
+void erofs_fuzz(void *buf, unsigned int length);
+
+#endif
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
index dea82f7..72a8b05 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,7 +2,7 @@
# Makefile.am
noinst_LTLIBRARIES = liberofs.la
-liberofs_la_SOURCES = config.c io.c cache.c inode.c compress.c compressor.c
+liberofs_la_SOURCES = config.c io.c cache.c inode.c compress.c compressor.c fuzzer.c
liberofs_la_CFLAGS = -Wall -Werror -I$(top_srcdir)/include
if ENABLE_LZ4
liberofs_la_CFLAGS += ${LZ4_CFLAGS}
diff --git a/lib/compress.c b/lib/compress.c
index a977c87..437e816 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -16,6 +16,7 @@
#include "erofs/cache.h"
#include "erofs/compress.h"
#include "compressor.h"
+#include "erofs/fuzzer.h"
static struct erofs_compress compresshandle;
static int compressionlevel;
@@ -478,6 +479,8 @@
legacymetasize, 12);
DBG_BUGON(ret);
}
+
+ erofs_fuzz(inode->compressmeta, inode->extent_isize);
return 0;
err_bdrop:
diff --git a/lib/config.c b/lib/config.c
index 2e91b92..ee72e83 100644
--- a/lib/config.c
+++ b/lib/config.c
@@ -20,6 +20,7 @@
cfg.c_version = PACKAGE_VERSION;
cfg.c_dry_run = false;
cfg.c_legacy_compress = false;
+ cfg.c_fuzz_trapcount = 0;
cfg.c_compr_level_master = -1;
sbi.requirements = EROFS_REQUIREMENT_LZ4_0PADDING;
}
diff --git a/lib/fuzzer.c b/lib/fuzzer.c
new file mode 100644
index 0000000..079d38d
--- /dev/null
+++ b/lib/fuzzer.c
@@ -0,0 +1,39 @@
+#include <unistd.h>
+#include "erofs/config.h"
+#include "erofs/fuzzer.h"
+#include "erofs/print.h"
+
+void erofs_fuzz(void *buf, unsigned int length)
+{
+ int fd, ret;
+ unsigned int a1, a2;
+
+ /* whether the fuzzer is disabled */
+ if (!cfg.c_fuzz_trapcount)
+ return;
+
+ /* whether this field should be fuzzed */
+ if (cfg.c_fuzz_trapcount-- != 1)
+ return;
+
+ fd = open("/dev/urandom", O_RDONLY);
+
+ do {
+ ret = read(fd, &a1, sizeof(a1));
+ a1 %= length;
+
+ ret = read(fd, &a2, sizeof(a2));
+ a2 %= length;
+ } while (a1 == a2);
+
+ if (a1 > a2) {
+ const unsigned int t = a1;
+
+ a1 = a2;
+ a2 = t;
+ }
+ ret = read(fd, buf + a1, a2 - a1);
+ erofs_err("fuzzed!");
+ close(fd);
+}
+
diff --git a/lib/inode.c b/lib/inode.c
index 581f263..202c757 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -18,6 +18,7 @@
#include "erofs/cache.h"
#include "erofs/io.h"
#include "erofs/compress.h"
+#include "erofs/fuzzer.h"
struct erofs_sb_info sbi;
@@ -213,6 +214,8 @@
head = list_next_entry(head, d_child);
}
memset(buf + q, 0, size - q);
+
+ erofs_fuzz(buf, size);
}
static int write_dirblock(unsigned int q, struct erofs_dentry *head,
@@ -393,6 +396,8 @@
break;
}
+ erofs_fuzz(&v1, sizeof(struct erofs_inode_v1));
+
ret = dev_write(&v1, off, sizeof(struct erofs_inode_v1));
if (ret)
return false;
diff --git a/mkfs/main.c b/mkfs/main.c
index 75e1d47..941a2a3 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -19,6 +19,7 @@
#include "erofs/inode.h"
#include "erofs/io.h"
#include "erofs/compress.h"
+#include "erofs/fuzzer.h"
#define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block))
@@ -79,7 +80,7 @@
{
int opt, i;
- while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
+ while ((opt = getopt(argc, argv, "d:z:E:F:")) != -1) {
switch (opt) {
case 'z':
if (!optarg) {
@@ -113,6 +114,9 @@
return opt;
break;
+ case 'F':
+ cfg.c_fuzz_trapcount = atoi(optarg);
+ break;
default: /* '?' */
return -EINVAL;
}
@@ -175,6 +179,7 @@
erofs_strerror(-errno));
return -ENOMEM;
}
+ erofs_fuzz(&sb, sizeof(struct erofs_super_block));
memcpy(buf + EROFS_SUPER_OFFSET, &sb, sizeof(sb));
bh->fsprivate = buf;