1/* $NetBSD: t_fuzz.c,v 1.7 2021/09/16 22:19:11 andvar 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 63static void 64fixversion(struct puffs_kargs *kargs) 65{ 66 67 kargs->pa_vers = PUFFSVERSION; 68} 69 70static void 71fixkflag(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 83static void 84fixfhflag(struct puffs_kargs *kargs) 85{ 86 87 kargs->pa_fhflags &= PUFFS_FHFLAG_MASK; 88} 89 90static void 91fixspare(struct puffs_kargs *kargs) 92{ 93 94 memset(&kargs->pa_spare, 0, sizeof(kargs->pa_spare)); 95} 96 97static void 98fixhandsize(struct puffs_kargs *kargs) 99{ 100 101 kargs->pa_fhsize %= PUFFS_FHSIZE_MAX+4; 102} 103 104static void 105fixhandsize2(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 115static void 116fixputter(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 124static void 125fixroot(struct puffs_kargs *kargs) 126{ 127 128 kargs->pa_root_vtype %= VBAD; 129} 130 131static void 132unfixputter(struct puffs_kargs *kargs) 133{ 134 135 rump_sys_close(kargs->pa_fd); 136} 137 138typedef void (*fixfn)(struct puffs_kargs *); 139static fixfn fixstack[] = { 140 fixversion, 141 fixkflag, 142 fixfhflag, 143 fixspare, 144 fixhandsize, 145 fixhandsize2, 146 fixputter, 147 fixroot, 148}; 149 150static void 151fixup(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 160static void 161unfixup(int nfix, struct puffs_kargs *kargs) 162{ 163 164 if (nfix >= 7) 165 unfixputter(kargs); 166} 167 168static pthread_mutex_t damtx; 169static pthread_cond_t dacv; 170static int dafd = -1; 171 172static void * 173respondthread(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 successful */ 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 210static void 211testbody(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_) \ 254ATF_TC(mountfuzz##_n_); \ 255ATF_TC_HEAD(mountfuzz##_n_, tc) \ 256{atf_tc_set_md_var(tc, "descr", "garbage kargs, " # _n_ " fix(es)");} \ 257ATF_TC_BODY(mountfuzz##_n_, tc) {testbody(_n_);} 258 259MAKETEST(0); 260MAKETEST(1); 261MAKETEST(2); 262MAKETEST(3); 263MAKETEST(4); 264MAKETEST(5); 265MAKETEST(6); 266MAKETEST(7); 267MAKETEST(8); 268 269ATF_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