fsfuzz

small fs fuzzer
git clone git://git.2f30.org/fsfuzz
Log | Files | Refs

fsfuzz.c (2827B)


      1 #include <sys/types.h>
      2 #include <sys/stat.h>
      3 #include <sys/mman.h>
      4 #include <fcntl.h>
      5 #include <unistd.h>
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <err.h>
     10 #include <errno.h>
     11 #include <getopt.h>
     12 #include <string.h>
     13 
     14 #include "fsfuzz.h"
     15 
     16 /* All register fuzzer operations */
     17 static struct fsfuzz_ops *fsfuzz_ops[16];
     18 /* Flag to select the filesystem type */
     19 static int fs_flag;
     20 static int verbose_flag;
     21 
     22 void
     23 fsfuzz_register(struct fsfuzz_ops *ops)
     24 {
     25 	size_t i;
     26 
     27 	if (!ops)
     28 		errx(1, "Invalid ops structure");
     29 	if (!ops->fuzz)
     30 		errx(1, "Unimplemented fuzz() callback, aborting");
     31 
     32 	for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
     33 		if (!fsfuzz_ops[i])
     34 			break;
     35 	if (i == ARRAY_SIZE(fsfuzz_ops))
     36 		errx(1, "Blah, not enough space in fsfuzz_ops array");
     37 
     38 	fsfuzz_ops[i] = ops;
     39 }
     40 
     41 static void
     42 usage(const char *prog)
     43 {
     44 	fprintf(stderr, "usage: %s [l | f: | v | h] fs-img\n", prog);
     45 	fprintf(stderr, "  -l\tlist registered fuzzers\n");
     46 	fprintf(stderr, "  -f\tfilesystem type\n");
     47 	fprintf(stderr, "  -v\tverbose output\n");
     48 	fprintf(stderr, "  -h\tthis help menu\n");
     49 	exit(EXIT_FAILURE);
     50 }
     51 
     52 static void
     53 dump_fuzzers(void)
     54 {
     55 	size_t i;
     56 
     57 	for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
     58 		if (fsfuzz_ops[i])
     59 			printf("%s\n", fsfuzz_ops[i]->name);
     60 }
     61 
     62 static struct fsfuzz_ops *
     63 match_fs(const char *fs)
     64 {
     65 	size_t i;
     66 
     67 	for (i = 0; i < ARRAY_SIZE(fsfuzz_ops); i++)
     68 		if (fsfuzz_ops[i])
     69 			if (!strcmp(fsfuzz_ops[i]->name, fs))
     70 				return fsfuzz_ops[i];
     71 	return NULL;
     72 }
     73 
     74 int
     75 main(int argc, char *argv[])
     76 {
     77 	int fd;
     78 	struct stat buf;
     79 	char *p;
     80 	int c;
     81 	const char *prog;
     82 	char *fs = NULL;
     83 	struct fsfuzz_ops *fs_ops;
     84 	struct fsfuzz_info fs_info;
     85 
     86 	setbuf(stdout, NULL);
     87 
     88 	prog = *argv;
     89 	while ((c = getopt(argc, argv, "lhf:v")) != -1) {
     90 		switch (c) {
     91 		case 'l':
     92 			dump_fuzzers();
     93 			return EXIT_SUCCESS;
     94 		case 'f':
     95 			fs_flag = 1;
     96 			fs = strdup(optarg);
     97 			if (!fs)
     98 				err(1, "strdup");
     99 			break;
    100 		case 'v':
    101 			verbose_flag = 1;
    102 			break;
    103 		case 'h':
    104 			usage(prog);
    105 			break;
    106 		default:
    107 			return EXIT_FAILURE;
    108 		}
    109 	}
    110 	if (optind >= argc)
    111 		usage(prog);
    112 
    113 	if (!fs_flag)
    114 		errx(1, "Please select the fs type via the -f flag");
    115 
    116 	fs_ops = match_fs(fs);
    117 	if (!fs_ops)
    118 		errx(1, "No fuzzer available for filesystem %s", fs);
    119 
    120 	fd = open(argv[optind], O_RDWR);
    121 	if (fd < 0)
    122 		err(1, "Can't open %s", argv[optind]);
    123 
    124 	if (fstat(fd, &buf) < 0)
    125 		err(1, "fstat");
    126 
    127 	p = mmap(0, buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
    128 		 fd, 0);
    129 	if (p == MAP_FAILED)
    130 		err(1, "mmap");
    131 
    132 	fs_info.img = p;
    133 	fs_info.size = buf.st_size;
    134 	fs_info.verbosity = verbose_flag;
    135 
    136 	/* We don't require init/free to be implemented */
    137 	if (fs_ops->init)
    138 		fs_ops->init(&fs_info);
    139 
    140 	fs_ops->fuzz(&fs_info);
    141 
    142 	if (fs_ops->free)
    143 		fs_ops->free(&fs_info);
    144 
    145 	if (munmap(p, buf.st_size) < 0)
    146 		err(1, "munmap");
    147 
    148 	close(fd);
    149 	free(fs);
    150 	return EXIT_SUCCESS;
    151 }