xref: /netbsd-src/tests/fs/puffs/t_fuzz.c (revision b58602814f44cdb10d1ce70b9ef75bf29672fcc0)
1*b5860281Sandvar /*	$NetBSD: t_fuzz.c,v 1.7 2021/09/16 22:19:11 andvar Exp $	*/
29cf29ab3Spooka 
39cf29ab3Spooka /*-
49cf29ab3Spooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
59cf29ab3Spooka  * All rights reserved.
69cf29ab3Spooka  *
79cf29ab3Spooka  * Redistribution and use in source and binary forms, with or without
89cf29ab3Spooka  * modification, are permitted provided that the following conditions
99cf29ab3Spooka  * are met:
109cf29ab3Spooka  * 1. Redistributions of source code must retain the above copyright
119cf29ab3Spooka  *    notice, this list of conditions and the following disclaimer.
129cf29ab3Spooka  * 2. Redistributions in binary form must reproduce the above copyright
139cf29ab3Spooka  *    notice, this list of conditions and the following disclaimer in the
149cf29ab3Spooka  *    documentation and/or other materials provided with the distribution.
159cf29ab3Spooka  *
169cf29ab3Spooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
179cf29ab3Spooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
189cf29ab3Spooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
199cf29ab3Spooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
209cf29ab3Spooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219cf29ab3Spooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
229cf29ab3Spooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
239cf29ab3Spooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249cf29ab3Spooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
259cf29ab3Spooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
269cf29ab3Spooka  * POSSIBILITY OF SUCH DAMAGE.
279cf29ab3Spooka  */
289cf29ab3Spooka 
299cf29ab3Spooka /*
309cf29ab3Spooka  * Fuzztest puffs mount.  There are n different levels of testing:
319cf29ab3Spooka  * each one pours more and more sane garbage into the args to that
329cf29ab3Spooka  * the mount progresses further and further.  Level 8 (at least when
339cf29ab3Spooka  * writing this comment) should be the one where mounting actually
349cf29ab3Spooka  * succeeds.
359cf29ab3Spooka  *
369cf29ab3Spooka  * Our metric of success is crash / no crash.
379cf29ab3Spooka  */
389cf29ab3Spooka 
399cf29ab3Spooka #include <sys/types.h>
409cf29ab3Spooka #include <sys/mount.h>
4127e29707Spooka #include <sys/poll.h>
429cf29ab3Spooka 
439cf29ab3Spooka #include <assert.h>
449cf29ab3Spooka #include <atf-c.h>
459cf29ab3Spooka #include <err.h>
469cf29ab3Spooka #include <errno.h>
479cf29ab3Spooka #include <fcntl.h>
489cf29ab3Spooka #include <pthread.h>
499cf29ab3Spooka #include <stdio.h>
509cf29ab3Spooka #include <unistd.h>
519cf29ab3Spooka #include <string.h>
529cf29ab3Spooka #include <stdlib.h>
539cf29ab3Spooka 
549cf29ab3Spooka #include <fs/puffs/puffs_msgif.h>
559cf29ab3Spooka 
569cf29ab3Spooka #include <rump/rump.h>
579cf29ab3Spooka #include <rump/rump_syscalls.h>
589cf29ab3Spooka 
59c54cb811Schristos #include "h_macros.h"
609cf29ab3Spooka 
619cf29ab3Spooka #define ITERATIONS 100
629cf29ab3Spooka 
639cf29ab3Spooka static void
fixversion(struct puffs_kargs * kargs)649cf29ab3Spooka fixversion(struct puffs_kargs *kargs)
659cf29ab3Spooka {
669cf29ab3Spooka 
679cf29ab3Spooka 	kargs->pa_vers = PUFFSVERSION;
689cf29ab3Spooka }
699cf29ab3Spooka 
709cf29ab3Spooka static void
fixkflag(struct puffs_kargs * kargs)719cf29ab3Spooka fixkflag(struct puffs_kargs *kargs)
729cf29ab3Spooka {
739cf29ab3Spooka 
749cf29ab3Spooka 	kargs->pa_flags &= PUFFS_KFLAG_MASK;
75ae04a0baSmanu 
76ae04a0baSmanu 	/*
77ae04a0baSmanu 	 * PUFFS_KFLAG_CACHE_FS_TTL require extended behavior
78ae04a0baSmanu 	 * from the filesystem for which we have no test right now.
79ae04a0baSmanu 	 */
80ae04a0baSmanu 	kargs->pa_flags &= ~PUFFS_KFLAG_CACHE_FS_TTL;
819cf29ab3Spooka }
829cf29ab3Spooka 
839cf29ab3Spooka static void
fixfhflag(struct puffs_kargs * kargs)849cf29ab3Spooka fixfhflag(struct puffs_kargs *kargs)
859cf29ab3Spooka {
869cf29ab3Spooka 
879cf29ab3Spooka 	kargs->pa_fhflags &= PUFFS_FHFLAG_MASK;
889cf29ab3Spooka }
899cf29ab3Spooka 
909cf29ab3Spooka static void
fixspare(struct puffs_kargs * kargs)919cf29ab3Spooka fixspare(struct puffs_kargs *kargs)
929cf29ab3Spooka {
939cf29ab3Spooka 
949cf29ab3Spooka 	memset(&kargs->pa_spare, 0, sizeof(kargs->pa_spare));
959cf29ab3Spooka }
969cf29ab3Spooka 
979cf29ab3Spooka static void
fixhandsize(struct puffs_kargs * kargs)989cf29ab3Spooka fixhandsize(struct puffs_kargs *kargs)
999cf29ab3Spooka {
1009cf29ab3Spooka 
1019cf29ab3Spooka 	kargs->pa_fhsize %= PUFFS_FHSIZE_MAX+4;
1029cf29ab3Spooka }
1039cf29ab3Spooka 
1049cf29ab3Spooka static void
fixhandsize2(struct puffs_kargs * kargs)1059cf29ab3Spooka fixhandsize2(struct puffs_kargs *kargs)
1069cf29ab3Spooka {
1079cf29ab3Spooka 
1089cf29ab3Spooka 	/* XXX: values */
1099cf29ab3Spooka 	if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV3)
1109cf29ab3Spooka 		kargs->pa_fhsize %= 60;
1119cf29ab3Spooka 	if (kargs->pa_fhflags & PUFFS_FHFLAG_NFSV2)
1129cf29ab3Spooka 		kargs->pa_fhsize %= 28;
1139cf29ab3Spooka }
1149cf29ab3Spooka 
1159cf29ab3Spooka static void
fixputter(struct puffs_kargs * kargs)1169cf29ab3Spooka fixputter(struct puffs_kargs *kargs)
1179cf29ab3Spooka {
1189cf29ab3Spooka 
1199cf29ab3Spooka 	kargs->pa_fd = rump_sys_open("/dev/putter", O_RDWR);
1209cf29ab3Spooka 	if (kargs->pa_fd == -1)
1219cf29ab3Spooka 		atf_tc_fail_errno("open putter");
1229cf29ab3Spooka }
1239cf29ab3Spooka 
1249cf29ab3Spooka static void
fixroot(struct puffs_kargs * kargs)1259cf29ab3Spooka fixroot(struct puffs_kargs *kargs)
1269cf29ab3Spooka {
1279cf29ab3Spooka 
1289cf29ab3Spooka 	kargs->pa_root_vtype %= VBAD;
1299cf29ab3Spooka }
1309cf29ab3Spooka 
1319cf29ab3Spooka static void
unfixputter(struct puffs_kargs * kargs)1329cf29ab3Spooka unfixputter(struct puffs_kargs *kargs)
1339cf29ab3Spooka {
1349cf29ab3Spooka 
1359cf29ab3Spooka 	rump_sys_close(kargs->pa_fd);
1369cf29ab3Spooka }
1379cf29ab3Spooka 
1389cf29ab3Spooka typedef void (*fixfn)(struct puffs_kargs *);
1399cf29ab3Spooka static fixfn fixstack[] = {
1409cf29ab3Spooka 	fixversion,
1419cf29ab3Spooka 	fixkflag,
1429cf29ab3Spooka 	fixfhflag,
1439cf29ab3Spooka 	fixspare,
1449cf29ab3Spooka 	fixhandsize,
1459cf29ab3Spooka 	fixhandsize2,
1469cf29ab3Spooka 	fixputter,
1479cf29ab3Spooka 	fixroot,
1489cf29ab3Spooka };
1499cf29ab3Spooka 
1509cf29ab3Spooka static void
fixup(int nfix,struct puffs_kargs * kargs)1519cf29ab3Spooka fixup(int nfix, struct puffs_kargs *kargs)
1529cf29ab3Spooka {
1539cf29ab3Spooka 	int i;
1549cf29ab3Spooka 
1559cf29ab3Spooka 	assert(nfix <= __arraycount(fixstack));
1569cf29ab3Spooka 	for (i = 0; i < nfix; i++)
1579cf29ab3Spooka 		fixstack[i](kargs);
1589cf29ab3Spooka }
1599cf29ab3Spooka 
1609cf29ab3Spooka static void
unfixup(int nfix,struct puffs_kargs * kargs)1619cf29ab3Spooka unfixup(int nfix, struct puffs_kargs *kargs)
1629cf29ab3Spooka {
1639cf29ab3Spooka 
1649cf29ab3Spooka 	if (nfix >= 7)
1659cf29ab3Spooka 		unfixputter(kargs);
1669cf29ab3Spooka }
1679cf29ab3Spooka 
1689cf29ab3Spooka static pthread_mutex_t damtx;
1699cf29ab3Spooka static pthread_cond_t dacv;
1709cf29ab3Spooka static int dafd = -1;
1719cf29ab3Spooka 
1729cf29ab3Spooka static void *
respondthread(void * arg)1739cf29ab3Spooka respondthread(void *arg)
1749cf29ab3Spooka {
1759cf29ab3Spooka 	char buf[PUFFS_MSG_MAXSIZE];
1769cf29ab3Spooka 	struct puffs_req *preq = (void *)buf;
17727e29707Spooka 	struct pollfd pfd;
1789cf29ab3Spooka 	ssize_t n;
1799cf29ab3Spooka 
1809cf29ab3Spooka 	pthread_mutex_lock(&damtx);
1819cf29ab3Spooka 	for (;;) {
1829cf29ab3Spooka 		while (dafd == -1)
1839cf29ab3Spooka 			pthread_cond_wait(&dacv, &damtx);
1849cf29ab3Spooka 
1859cf29ab3Spooka 		while (dafd != -1) {
1869cf29ab3Spooka 			pthread_mutex_unlock(&damtx);
18727e29707Spooka 			pfd.fd = dafd;
18827e29707Spooka 			pfd.events = POLLIN;
18927e29707Spooka 			pfd.revents = 0;
19027e29707Spooka 			if (rump_sys_poll(&pfd, 1, 10) == 0) {
19127e29707Spooka 				pthread_mutex_lock(&damtx);
19227e29707Spooka 				continue;
19327e29707Spooka 			}
1949cf29ab3Spooka 			n = rump_sys_read(dafd, buf, sizeof(buf));
1959cf29ab3Spooka 			if (n <= 0) {
1969cf29ab3Spooka 				pthread_mutex_lock(&damtx);
1979cf29ab3Spooka 				break;
1989cf29ab3Spooka 			}
1999cf29ab3Spooka 
200*b5860281Sandvar 			/* just say it was successful */
2019cf29ab3Spooka 			preq->preq_rv = 0;
2029cf29ab3Spooka 			rump_sys_write(dafd, buf, n);
2039cf29ab3Spooka 			pthread_mutex_lock(&damtx);
2049cf29ab3Spooka 		}
2059cf29ab3Spooka 	}
2061a22a69cSpooka 
2071a22a69cSpooka 	return NULL;
2089cf29ab3Spooka }
2099cf29ab3Spooka 
2109cf29ab3Spooka static void
testbody(int nfix)2119cf29ab3Spooka testbody(int nfix)
2129cf29ab3Spooka {
2139cf29ab3Spooka 	pthread_t pt;
2149cf29ab3Spooka 	struct puffs_kargs kargs;
2159cf29ab3Spooka 	unsigned long seed;
2169cf29ab3Spooka 	int i;
2179cf29ab3Spooka 
2189cf29ab3Spooka 	seed = time(NULL);
2199cf29ab3Spooka 	srandom(seed);
2209cf29ab3Spooka 	printf("test seeded RNG with %lu\n", seed);
2219cf29ab3Spooka 
22227e29707Spooka 	rump_init();
22327e29707Spooka 
2249cf29ab3Spooka 	pthread_mutex_init(&damtx, NULL);
2259cf29ab3Spooka 	pthread_cond_init(&dacv, NULL);
2269cf29ab3Spooka 	pthread_create(&pt, NULL, respondthread, NULL);
2279cf29ab3Spooka 
2289cf29ab3Spooka 	ATF_REQUIRE(rump_sys_mkdir("/mnt", 0777) == 0);
2299cf29ab3Spooka 
2309cf29ab3Spooka 	for (i = 0; i < ITERATIONS; i++) {
23119a6309aSpooka 		tests_makegarbage(&kargs, sizeof(kargs));
2329cf29ab3Spooka 		fixup(nfix, &kargs);
2339cf29ab3Spooka 		if (rump_sys_mount(MOUNT_PUFFS, "/mnt", 0,
2349cf29ab3Spooka 		    &kargs, sizeof(kargs)) == 0) {
2359cf29ab3Spooka 			struct stat sb;
2369cf29ab3Spooka 
2379cf29ab3Spooka 			pthread_mutex_lock(&damtx);
2389cf29ab3Spooka 			dafd = kargs.pa_fd;
2399cf29ab3Spooka 			pthread_cond_signal(&dacv);
2409cf29ab3Spooka 			pthread_mutex_unlock(&damtx);
2419cf29ab3Spooka 
2429cf29ab3Spooka 			rump_sys_stat("/mnt", &sb);
2439cf29ab3Spooka 			rump_sys_unmount("/mnt", MNT_FORCE);
2449cf29ab3Spooka 		}
2459cf29ab3Spooka 		unfixup(nfix, &kargs);
2469cf29ab3Spooka 
2479cf29ab3Spooka 		pthread_mutex_lock(&damtx);
2489cf29ab3Spooka 		dafd = -1;
2499cf29ab3Spooka 		pthread_mutex_unlock(&damtx);
2509cf29ab3Spooka 	}
2519cf29ab3Spooka }
2529cf29ab3Spooka 
2539cf29ab3Spooka #define MAKETEST(_n_)							\
2549cf29ab3Spooka ATF_TC(mountfuzz##_n_);							\
2559cf29ab3Spooka ATF_TC_HEAD(mountfuzz##_n_, tc)						\
25619a6309aSpooka {atf_tc_set_md_var(tc, "descr", "garbage kargs, " # _n_ " fix(es)");}	\
2579cf29ab3Spooka ATF_TC_BODY(mountfuzz##_n_, tc) {testbody(_n_);}
2589cf29ab3Spooka 
2599cf29ab3Spooka MAKETEST(0);
2609cf29ab3Spooka MAKETEST(1);
2619cf29ab3Spooka MAKETEST(2);
2629cf29ab3Spooka MAKETEST(3);
2639cf29ab3Spooka MAKETEST(4);
2649cf29ab3Spooka MAKETEST(5);
2659cf29ab3Spooka MAKETEST(6);
2669cf29ab3Spooka MAKETEST(7);
2679cf29ab3Spooka MAKETEST(8);
2689cf29ab3Spooka 
ATF_TP_ADD_TCS(tp)2699cf29ab3Spooka ATF_TP_ADD_TCS(tp)
2709cf29ab3Spooka {
2719cf29ab3Spooka 
2729cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz0);
2739cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz1);
2749cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz2);
2759cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz3);
2769cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz4);
2779cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz5);
2789cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz6);
2799cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz7);
2809cf29ab3Spooka 	ATF_TP_ADD_TC(tp, mountfuzz8);
2819cf29ab3Spooka 
2829cf29ab3Spooka 	return atf_no_error();
2839cf29ab3Spooka }
284