t_fuzz.c revision 1.7 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