1 /* $NetBSD: t_fuzz.c,v 1.4 2010/08/27 12:42:21 pooka 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 static void 78 fixfhflag(struct puffs_kargs *kargs) 79 { 80 81 kargs->pa_fhflags &= PUFFS_FHFLAG_MASK; 82 } 83 84 static void 85 fixspare(struct puffs_kargs *kargs) 86 { 87 88 memset(&kargs->pa_spare, 0, sizeof(kargs->pa_spare)); 89 } 90 91 static void 92 fixhandsize(struct puffs_kargs *kargs) 93 { 94 95 kargs->pa_fhsize %= PUFFS_FHSIZE_MAX+4; 96 } 97 98 static void 99 fixhandsize2(struct puffs_kargs *kargs) 100 { 101 102 /* XXX: values */ 103 if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV3) 104 kargs->pa_fhsize %= 60; 105 if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV2) 106 kargs->pa_fhsize %= 28; 107 } 108 109 static void 110 fixputter(struct puffs_kargs *kargs) 111 { 112 113 kargs->pa_fd = rump_sys_open("/dev/putter", O_RDWR); 114 if (kargs->pa_fd == -1) 115 atf_tc_fail_errno("open putter"); 116 } 117 118 static void 119 fixroot(struct puffs_kargs *kargs) 120 { 121 122 kargs->pa_root_vtype %= VBAD; 123 } 124 125 static void 126 unfixputter(struct puffs_kargs *kargs) 127 { 128 129 rump_sys_close(kargs->pa_fd); 130 } 131 132 typedef void (*fixfn)(struct puffs_kargs *); 133 static fixfn fixstack[] = { 134 fixversion, 135 fixkflag, 136 fixfhflag, 137 fixspare, 138 fixhandsize, 139 fixhandsize2, 140 fixputter, 141 fixroot, 142 }; 143 144 static void 145 fixup(int nfix, struct puffs_kargs *kargs) 146 { 147 int i; 148 149 assert(nfix <= __arraycount(fixstack)); 150 for (i = 0; i < nfix; i++) 151 fixstack[i](kargs); 152 } 153 154 static void 155 unfixup(int nfix, struct puffs_kargs *kargs) 156 { 157 158 if (nfix >= 7) 159 unfixputter(kargs); 160 } 161 162 static pthread_mutex_t damtx; 163 static pthread_cond_t dacv; 164 static int dafd = -1; 165 166 static void * 167 respondthread(void *arg) 168 { 169 char buf[PUFFS_MSG_MAXSIZE]; 170 struct puffs_req *preq = (void *)buf; 171 struct pollfd pfd; 172 ssize_t n; 173 174 pthread_mutex_lock(&damtx); 175 for (;;) { 176 while (dafd == -1) 177 pthread_cond_wait(&dacv, &damtx); 178 179 while (dafd != -1) { 180 pthread_mutex_unlock(&damtx); 181 pfd.fd = dafd; 182 pfd.events = POLLIN; 183 pfd.revents = 0; 184 if (rump_sys_poll(&pfd, 1, 10) == 0) { 185 pthread_mutex_lock(&damtx); 186 continue; 187 } 188 n = rump_sys_read(dafd, buf, sizeof(buf)); 189 if (n <= 0) { 190 pthread_mutex_lock(&damtx); 191 break; 192 } 193 194 /* just say it was succesful */ 195 preq->preq_rv = 0; 196 rump_sys_write(dafd, buf, n); 197 pthread_mutex_lock(&damtx); 198 } 199 } 200 201 return NULL; 202 } 203 204 static void 205 testbody(int nfix) 206 { 207 pthread_t pt; 208 struct puffs_kargs kargs; 209 unsigned long seed; 210 int i; 211 212 seed = time(NULL); 213 srandom(seed); 214 printf("test seeded RNG with %lu\n", seed); 215 216 rump_init(); 217 218 pthread_mutex_init(&damtx, NULL); 219 pthread_cond_init(&dacv, NULL); 220 pthread_create(&pt, NULL, respondthread, NULL); 221 222 ATF_REQUIRE(rump_sys_mkdir("/mnt", 0777) == 0); 223 224 for (i = 0; i < ITERATIONS; i++) { 225 tests_makegarbage(&kargs, sizeof(kargs)); 226 fixup(nfix, &kargs); 227 if (rump_sys_mount(MOUNT_PUFFS, "/mnt", 0, 228 &kargs, sizeof(kargs)) == 0) { 229 struct stat sb; 230 231 pthread_mutex_lock(&damtx); 232 dafd = kargs.pa_fd; 233 pthread_cond_signal(&dacv); 234 pthread_mutex_unlock(&damtx); 235 236 rump_sys_stat("/mnt", &sb); 237 rump_sys_unmount("/mnt", MNT_FORCE); 238 } 239 unfixup(nfix, &kargs); 240 241 pthread_mutex_lock(&damtx); 242 dafd = -1; 243 pthread_mutex_unlock(&damtx); 244 } 245 } 246 247 #define MAKETEST(_n_) \ 248 ATF_TC(mountfuzz##_n_); \ 249 ATF_TC_HEAD(mountfuzz##_n_, tc) \ 250 {atf_tc_set_md_var(tc, "descr", "garbage kargs, " # _n_ " fix(es)");} \ 251 ATF_TC_BODY(mountfuzz##_n_, tc) {testbody(_n_);} 252 253 MAKETEST(0); 254 MAKETEST(1); 255 MAKETEST(2); 256 MAKETEST(3); 257 MAKETEST(4); 258 MAKETEST(5); 259 MAKETEST(6); 260 MAKETEST(7); 261 MAKETEST(8); 262 263 ATF_TP_ADD_TCS(tp) 264 { 265 266 ATF_TP_ADD_TC(tp, mountfuzz0); 267 ATF_TP_ADD_TC(tp, mountfuzz1); 268 ATF_TP_ADD_TC(tp, mountfuzz2); 269 ATF_TP_ADD_TC(tp, mountfuzz3); 270 ATF_TP_ADD_TC(tp, mountfuzz4); 271 ATF_TP_ADD_TC(tp, mountfuzz5); 272 ATF_TP_ADD_TC(tp, mountfuzz6); 273 ATF_TP_ADD_TC(tp, mountfuzz7); 274 ATF_TP_ADD_TC(tp, mountfuzz8); 275 276 return atf_no_error(); 277 } 278