1 /* $NetBSD: t_fuzz.c,v 1.6 2017/01/13 21:30:40 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Fuzztest puffs mount. There are n different levels of testing: 31 * each one pours more and more sane garbage into the args to that 32 * the mount progresses further and further. Level 8 (at least when 33 * writing this comment) should be the one where mounting actually 34 * succeeds. 35 * 36 * Our metric of success is crash / no crash. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/mount.h> 41 #include <sys/poll.h> 42 43 #include <assert.h> 44 #include <atf-c.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <fcntl.h> 48 #include <pthread.h> 49 #include <stdio.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <stdlib.h> 53 54 #include <fs/puffs/puffs_msgif.h> 55 56 #include <rump/rump.h> 57 #include <rump/rump_syscalls.h> 58 59 #include "h_macros.h" 60 61 #define ITERATIONS 100 62 63 static void 64 fixversion(struct puffs_kargs *kargs) 65 { 66 67 kargs->pa_vers = PUFFSVERSION; 68 } 69 70 static void 71 fixkflag(struct puffs_kargs *kargs) 72 { 73 74 kargs->pa_flags &= PUFFS_KFLAG_MASK; 75 76 /* 77 * PUFFS_KFLAG_CACHE_FS_TTL require extended behavior 78 * from the filesystem for which we have no test right now. 79 */ 80 kargs->pa_flags &= ~PUFFS_KFLAG_CACHE_FS_TTL; 81 } 82 83 static void 84 fixfhflag(struct puffs_kargs *kargs) 85 { 86 87 kargs->pa_fhflags &= PUFFS_FHFLAG_MASK; 88 } 89 90 static void 91 fixspare(struct puffs_kargs *kargs) 92 { 93 94 memset(&kargs->pa_spare, 0, sizeof(kargs->pa_spare)); 95 } 96 97 static void 98 fixhandsize(struct puffs_kargs *kargs) 99 { 100 101 kargs->pa_fhsize %= PUFFS_FHSIZE_MAX+4; 102 } 103 104 static void 105 fixhandsize2(struct puffs_kargs *kargs) 106 { 107 108 /* XXX: values */ 109 if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV3) 110 kargs->pa_fhsize %= 60; 111 if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV2) 112 kargs->pa_fhsize %= 28; 113 } 114 115 static void 116 fixputter(struct puffs_kargs *kargs) 117 { 118 119 kargs->pa_fd = rump_sys_open("/dev/putter", O_RDWR); 120 if (kargs->pa_fd == -1) 121 atf_tc_fail_errno("open putter"); 122 } 123 124 static void 125 fixroot(struct puffs_kargs *kargs) 126 { 127 128 kargs->pa_root_vtype %= VBAD; 129 } 130 131 static void 132 unfixputter(struct puffs_kargs *kargs) 133 { 134 135 rump_sys_close(kargs->pa_fd); 136 } 137 138 typedef void (*fixfn)(struct puffs_kargs *); 139 static fixfn fixstack[] = { 140 fixversion, 141 fixkflag, 142 fixfhflag, 143 fixspare, 144 fixhandsize, 145 fixhandsize2, 146 fixputter, 147 fixroot, 148 }; 149 150 static void 151 fixup(int nfix, struct puffs_kargs *kargs) 152 { 153 int i; 154 155 assert(nfix <= __arraycount(fixstack)); 156 for (i = 0; i < nfix; i++) 157 fixstack[i](kargs); 158 } 159 160 static void 161 unfixup(int nfix, struct puffs_kargs *kargs) 162 { 163 164 if (nfix >= 7) 165 unfixputter(kargs); 166 } 167 168 static pthread_mutex_t damtx; 169 static pthread_cond_t dacv; 170 static int dafd = -1; 171 172 static void * 173 respondthread(void *arg) 174 { 175 char buf[PUFFS_MSG_MAXSIZE]; 176 struct puffs_req *preq = (void *)buf; 177 struct pollfd pfd; 178 ssize_t n; 179 180 pthread_mutex_lock(&damtx); 181 for (;;) { 182 while (dafd == -1) 183 pthread_cond_wait(&dacv, &damtx); 184 185 while (dafd != -1) { 186 pthread_mutex_unlock(&damtx); 187 pfd.fd = dafd; 188 pfd.events = POLLIN; 189 pfd.revents = 0; 190 if (rump_sys_poll(&pfd, 1, 10) == 0) { 191 pthread_mutex_lock(&damtx); 192 continue; 193 } 194 n = rump_sys_read(dafd, buf, sizeof(buf)); 195 if (n <= 0) { 196 pthread_mutex_lock(&damtx); 197 break; 198 } 199 200 /* just say it was succesful */ 201 preq->preq_rv = 0; 202 rump_sys_write(dafd, buf, n); 203 pthread_mutex_lock(&damtx); 204 } 205 } 206 207 return NULL; 208 } 209 210 static void 211 testbody(int nfix) 212 { 213 pthread_t pt; 214 struct puffs_kargs kargs; 215 unsigned long seed; 216 int i; 217 218 seed = time(NULL); 219 srandom(seed); 220 printf("test seeded RNG with %lu\n", seed); 221 222 rump_init(); 223 224 pthread_mutex_init(&damtx, NULL); 225 pthread_cond_init(&dacv, NULL); 226 pthread_create(&pt, NULL, respondthread, NULL); 227 228 ATF_REQUIRE(rump_sys_mkdir("/mnt", 0777) == 0); 229 230 for (i = 0; i < ITERATIONS; i++) { 231 tests_makegarbage(&kargs, sizeof(kargs)); 232 fixup(nfix, &kargs); 233 if (rump_sys_mount(MOUNT_PUFFS, "/mnt", 0, 234 &kargs, sizeof(kargs)) == 0) { 235 struct stat sb; 236 237 pthread_mutex_lock(&damtx); 238 dafd = kargs.pa_fd; 239 pthread_cond_signal(&dacv); 240 pthread_mutex_unlock(&damtx); 241 242 rump_sys_stat("/mnt", &sb); 243 rump_sys_unmount("/mnt", MNT_FORCE); 244 } 245 unfixup(nfix, &kargs); 246 247 pthread_mutex_lock(&damtx); 248 dafd = -1; 249 pthread_mutex_unlock(&damtx); 250 } 251 } 252 253 #define MAKETEST(_n_) \ 254 ATF_TC(mountfuzz##_n_); \ 255 ATF_TC_HEAD(mountfuzz##_n_, tc) \ 256 {atf_tc_set_md_var(tc, "descr", "garbage kargs, " # _n_ " fix(es)");} \ 257 ATF_TC_BODY(mountfuzz##_n_, tc) {testbody(_n_);} 258 259 MAKETEST(0); 260 MAKETEST(1); 261 MAKETEST(2); 262 MAKETEST(3); 263 MAKETEST(4); 264 MAKETEST(5); 265 MAKETEST(6); 266 MAKETEST(7); 267 MAKETEST(8); 268 269 ATF_TP_ADD_TCS(tp) 270 { 271 272 ATF_TP_ADD_TC(tp, mountfuzz0); 273 ATF_TP_ADD_TC(tp, mountfuzz1); 274 ATF_TP_ADD_TC(tp, mountfuzz2); 275 ATF_TP_ADD_TC(tp, mountfuzz3); 276 ATF_TP_ADD_TC(tp, mountfuzz4); 277 ATF_TP_ADD_TC(tp, mountfuzz5); 278 ATF_TP_ADD_TC(tp, mountfuzz6); 279 ATF_TP_ADD_TC(tp, mountfuzz7); 280 ATF_TP_ADD_TC(tp, mountfuzz8); 281 282 return atf_no_error(); 283 } 284