Home | History | Annotate | Line # | Download | only in puffs
      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 
     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 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 
    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