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