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 }