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