commit fdd1a1c13ee619f6b23c76b67237b65f09a6920d
Author: sin <sin@2f30.org>
Date: Tue, 25 Jun 2013 23:37:02 +0100
Initial commit
Diffstat:
12 files changed, 510 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,27 @@
+bin = fsfuzz
+ver = 0.1
+CC = gcc
+CFLAGS = -Wall -Wextra
+
+obj = fsfuzz.o \
+ btrfs.o \
+ xfs.o \
+ jfs.o \
+ ext4.o \
+ reiserfs.o
+
+$(bin): $(obj)
+ @echo -e " LD\t"$@
+ @$(CC) -o $@ $(obj)
+
+%.o: %.c
+ @echo -e " CC\t"$<
+ @$(CC) $(CFLAGS) -c -o $@ $<
+
+.PHONY: clean
+clean:
+ @rm -rf $(bin) $(obj)
+
+.PHONY: all
+all:
+ @make clean && make
diff --git a/btrfs.c b/btrfs.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <err.h>
+
+#include "fsfuzz.h"
+
+int
+btrfs_init(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ srand((unsigned int)time(NULL));
+ return 0;
+}
+
+int
+btrfs_fuzz(struct fsfuzz_info *fs_info)
+{
+ char *p;
+ size_t offset;
+ size_t i;
+
+ p = fs_info->img;
+ for (i = 0; i < 32; i++) {
+ /* The superblock in btrfs is at 0x10000 */
+ offset = 0x10000 + (rand() % 4096);
+ if (offset + 3 >= fs_info->size) {
+ warnx("Wrong offset, ignoring");
+ continue;
+ }
+ if (fs_info->verbosity)
+ printf("[+] Patching offset %#lx with 0xffffffff\n",
+ (long)offset);
+ p[offset + 0] = 0xff;
+ p[offset + 1] = 0xff;
+ p[offset + 2] = 0xff;
+ p[offset + 3] = 0xff;
+ }
+ return 0;
+}
+
+static struct fsfuzz_ops btrfs_fuzz_ops = {
+ .name = "btrfs",
+ .init = btrfs_init,
+ .fuzz = btrfs_fuzz
+};
+
+__attribute__ ((constructor))
+static void
+btrfs_register(void)
+{
+ fsfuzz_register(&btrfs_fuzz_ops);
+}
diff --git a/ext4.c b/ext4.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <err.h>
+
+#include "fsfuzz.h"
+
+int
+ext4_init(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+int
+ext4_fuzz(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static struct fsfuzz_ops ext4_fuzz_ops = {
+ .name = "ext4",
+ .init = ext4_init,
+ .fuzz = ext4_fuzz
+};
+
+__attribute__ ((constructor))
+static void
+ext4_register(void)
+{
+ fsfuzz_register(&ext4_fuzz_ops);
+}
diff --git a/fsfuzz.c b/fsfuzz.c
@@ -0,0 +1,151 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <string.h>
+
+#include "fsfuzz.h"
+
+/* All register fuzzer operations */
+static struct fsfuzz_ops *fsfuzz_ops[16];
+/* Flag to select the filesystem type */
+static int fs_flag;
+static int verbose_flag;
+
+void
+fsfuzz_register(struct fsfuzz_ops *ops)
+{
+ size_t i;
+
+ if (!ops)
+ errx(1, "Invalid ops structure");
+ if (!ops->fuzz)
+ errx(1, "Unimplemented fuzz() callback, aborting");
+
+ for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
+ if (!fsfuzz_ops[i])
+ break;
+ if (i == ARRAY_SIZE(fsfuzz_ops))
+ errx(1, "Blah, not enough space in fsfuzz_ops array");
+
+ fsfuzz_ops[i] = ops;
+}
+
+static void
+usage(const char *prog)
+{
+ fprintf(stderr, "usage: %s [l | f: | v | h] fs-img\n", prog);
+ fprintf(stderr, " -l\tlist registered fuzzers\n");
+ fprintf(stderr, " -f\tfilesystem type\n");
+ fprintf(stderr, " -v\tverbose output\n");
+ fprintf(stderr, " -h\tthis help menu\n");
+ exit(EXIT_FAILURE);
+}
+
+static void
+dump_fuzzers(void)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
+ if (fsfuzz_ops[i])
+ printf("%s\n", fsfuzz_ops[i]->name);
+}
+
+static struct fsfuzz_ops *
+match_fs(const char *fs)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
+ if (fsfuzz_ops[i])
+ if (!strcmp(fsfuzz_ops[i]->name, fs))
+ return fsfuzz_ops[i];
+ return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ struct stat buf;
+ char *p;
+ int c;
+ const char *prog;
+ char *fs = NULL;
+ struct fsfuzz_ops *fs_ops;
+ struct fsfuzz_info fs_info;
+
+ setbuf(stdout, NULL);
+
+ prog = *argv;
+ while ((c = getopt(argc, argv, "lhf:v")) != -1) {
+ switch (c) {
+ case 'l':
+ dump_fuzzers();
+ return EXIT_SUCCESS;
+ case 'f':
+ fs_flag = 1;
+ fs = strdup(optarg);
+ if (!fs)
+ err(1, "strdup");
+ break;
+ case 'v':
+ verbose_flag = 1;
+ break;
+ case 'h':
+ usage(prog);
+ break;
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+ if (optind >= argc)
+ usage(prog);
+
+ if (!fs_flag)
+ errx(1, "Please select the fs type via the -f flag");
+
+ fs_ops = match_fs(fs);
+ if (!fs_ops)
+ errx(1, "No fuzzer available for filesystem %s", fs);
+
+ fd = open(argv[optind], O_RDWR);
+ if (fd < 0)
+ err(1, "Can't open %s", argv[optind]);
+
+ if (fstat(fd, &buf) < 0)
+ err(1, "fstat");
+
+ p = mmap(0, buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+ if (p == MAP_FAILED)
+ err(1, "mmap");
+
+ fs_info.img = p;
+ fs_info.size = buf.st_size;
+ fs_info.verbosity = verbose_flag;
+
+ /* We don't require init/free to be implemented */
+ if (fs_ops->init)
+ fs_ops->init(&fs_info);
+
+ fs_ops->fuzz(&fs_info);
+
+ if (fs_ops->free)
+ fs_ops->free(&fs_info);
+
+ if (munmap(p, buf.st_size) < 0)
+ err(1, "munmap");
+
+ close(fd);
+ free(fs);
+ return EXIT_SUCCESS;
+}
diff --git a/fsfuzz.h b/fsfuzz.h
@@ -0,0 +1,31 @@
+#ifndef FSFUZZ_H
+#define FSFUZZ_H
+
+#include <stddef.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct fsfuzz_info {
+ /* Pointer to actual image */
+ void *img;
+ /* Size of image on disk */
+ size_t size;
+ /* Number of completed fuzzing sessions */
+ int genertion;
+ /* Verbose level */
+ int verbosity;
+ /* Private data */
+ void *priv_data;
+};
+
+struct fsfuzz_ops {
+ const char *name;
+
+ int (*init)(struct fsfuzz_info *fs_info);
+ int (*free)(struct fsfuzz_info *fs_info);
+ int (*fuzz)(struct fsfuzz_info *fs_info);
+};
+
+void fsfuzz_register(struct fsfuzz_ops *ops);
+
+#endif
diff --git a/fuzz-scripts/btrfs-fuzz.sh b/fuzz-scripts/btrfs-fuzz.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+i=0
+while :; do
+ dd if=/dev/zero of=btrfs-own bs=1M count=8 &>/dev/null
+ mkfs.btrfs btrfs-own &>/dev/null
+ ../fsfuzz -f btrfs btrfs-own
+ mount -t btrfs btrfs-own mnt/
+ umount mnt/
+ mv btrfs-own btrfs/btrfs-own.$i
+ ((i++))
+done
diff --git a/fuzz-scripts/jfs-fuzz.sh b/fuzz-scripts/jfs-fuzz.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+i=0
+while :; do
+ dd if=/dev/zero of=jfs-own bs=1M count=16 &>/dev/null
+ mkfs.jfs -q jfs-own &> /dev/null
+ ../fsfuzz -f jfs jfs-own
+ mount -t jfs jfs-own mnt/
+ umount mnt/
+ mv jfs-own jfs/jfs-own.$i
+ ((i++))
+done
diff --git a/fuzz-scripts/reiserfs-fuzz.sh b/fuzz-scripts/reiserfs-fuzz.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+i=0
+while :; do
+ dd if=/dev/zero of=reiserfs-own bs=1M count=32 &>/dev/null
+ mkfs.reiserfs reiserfs-own &>/dev/null
+ ../fsfuzz -f reiserfs reiserfs-own
+ mount -t reiserfs reiserfs-own mnt/
+ umount mnt/
+ mv reiserfs-own reiserfs/reiserfs-own.$i
+ ((i++))
+done
diff --git a/fuzz-scripts/xfs-fuzz.sh b/fuzz-scripts/xfs-fuzz.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+i=0
+while :; do
+ dmesg -c &>/dev/null
+ dd if=/dev/zero of=xfs-own bs=1M count=32 &>/dev/null
+ mkfs.xfs xfs-own &>/dev/null
+ ../fsfuzz -f xfs xfs-own
+ sync
+ mount -t xfs xfs-own mnt/ &>/dev/null
+ umount mnt/ &>/dev/null
+ dmesg | grep -iq 'eip' # anything that looks like a bug really
+ if [ "$?" -eq 0 ]; then
+ echo Found 0day ...
+ cp xfs-own xfs/xfs-own.$i
+ dmesg &> xfs/xfs-own-log.$i
+ sync
+ ((i++))
+ fi
+done
diff --git a/jfs.c b/jfs.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <err.h>
+
+#include "fsfuzz.h"
+
+int
+jfs_init(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ srand((unsigned int)time(NULL));
+ return 0;
+}
+
+int
+jfs_fuzz(struct fsfuzz_info *fs_info)
+{
+ char *p;
+ size_t offset;
+ size_t i;
+
+ p = fs_info->img;
+ for (i = 0; i < 128; i++) {
+ do {
+ offset = 4096 + rand();
+ offset %= 65536;
+ if (offset + 3 < fs_info->size)
+ break;
+ } while (1);
+ if (fs_info->verbosity)
+ printf("[+] Patching offset %#lx with 0xffffffff\n",
+ (long)offset);
+ p[offset + 0] = 0xff;
+ p[offset + 1] = 0xff;
+ p[offset + 2] = 0xff;
+ p[offset + 3] = 0xff;
+ }
+ return 0;
+}
+
+static struct fsfuzz_ops jfs_fuzz_ops = {
+ .name = "jfs",
+ .init = jfs_init,
+ .fuzz = jfs_fuzz
+};
+
+__attribute__ ((constructor))
+static void
+jfs_register(void)
+{
+ fsfuzz_register(&jfs_fuzz_ops);
+}
diff --git a/reiserfs.c b/reiserfs.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <err.h>
+
+#include "fsfuzz.h"
+
+int
+reiserfs_init(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ srand((unsigned int)time(NULL));
+ return 0;
+}
+
+int
+reiserfs_fuzz(struct fsfuzz_info *fs_info)
+{
+ char *p;
+ size_t offset;
+ size_t i;
+
+ p = fs_info->img;
+ for (i = 0; i < 32; i++) {
+ /* The superblock in reiserfs is at 0x10000 */
+ offset = 0x10000 + (rand() % 4096);
+ if (offset + 3 >= fs_info->size) {
+ warnx("Wrong offset, ignoring");
+ continue;
+ }
+ if (fs_info->verbosity)
+ printf("[+] Patching offset %#lx with 0xffffffff\n",
+ (long)offset);
+ p[offset + 0] = 0xff;
+ p[offset + 1] = 0xff;
+ p[offset + 2] = 0xff;
+ p[offset + 3] = 0xff;
+ }
+ return 0;
+}
+
+static struct fsfuzz_ops reiserfs_fuzz_ops = {
+ .name = "reiserfs",
+ .init = reiserfs_init,
+ .fuzz = reiserfs_fuzz
+};
+
+__attribute__ ((constructor))
+static void
+reiserfs_register(void)
+{
+ fsfuzz_register(&reiserfs_fuzz_ops);
+}
diff --git a/xfs.c b/xfs.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <err.h>
+
+#include "fsfuzz.h"
+
+int
+xfs_init(struct fsfuzz_info *fs_info
+ __attribute__ ((unused)))
+{
+ srand((unsigned int)time(NULL));
+ return 0;
+}
+
+int
+xfs_fuzz(struct fsfuzz_info *fs_info)
+{
+ char *p;
+ size_t offset;
+ size_t i;
+
+ p = fs_info->img;
+ for (i = 0; i < 64 * 4; i++) {
+ /* The superblock in xfs is at offset 0 */
+ offset = rand() % (65536 * 4);
+ if (offset + 3 >= fs_info->size) {
+ warnx("Wrong offset, ignoring");
+ continue;
+ }
+ if (fs_info->verbosity)
+ printf("[+] Patching offset %#lx with 0xffffffff\n",
+ (long)offset);
+ p[offset + 0] = 0xff;
+ p[offset + 1] = 0xff;
+ p[offset + 2] = 0xff;
+ p[offset + 3] = 0xff;
+ }
+ return 0;
+}
+
+static struct fsfuzz_ops xfs_fuzz_ops = {
+ .name = "xfs",
+ .init = xfs_init,
+ .fuzz = xfs_fuzz
+};
+
+__attribute__ ((constructor))
+static void
+xfs_register(void)
+{
+ fsfuzz_register(&xfs_fuzz_ops);
+}