xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision faacc0d968816cf8714c974b6d8df6191cfb0e0d)
1 /*-
2  * Copyright (c) 2018	Kristof Provost <kp@FreeBSD.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/param.h>
27 #include <sys/module.h>
28 #include <sys/types.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
31 
32 #include <net/if.h>
33 #include <net/pfvar.h>
34 
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 
39 #include <atf-c.h>
40 
41 static int dev;
42 
43 #define COMMON_HEAD() \
44 	dev = open("/dev/pf", O_RDWR); \
45 	if (dev == -1) \
46 		atf_tc_skip("Failed to open /dev/pf");
47 
48 #define COMMON_CLEANUP() \
49 	close(dev);
50 
51 static void
common_init_tbl(struct pfr_table * tbl)52 common_init_tbl(struct pfr_table *tbl)
53 {
54 	bzero(tbl, sizeof(struct pfr_table));
55 	strcpy(tbl->pfrt_anchor, "anchor");
56 	strcpy(tbl->pfrt_name, "name");
57 	tbl->pfrt_flags = 0;
58 	tbl->pfrt_fback = 0;
59 }
60 
61 ATF_TC_WITH_CLEANUP(addtables);
ATF_TC_HEAD(addtables,tc)62 ATF_TC_HEAD(addtables, tc)
63 {
64 	atf_tc_set_md_var(tc, "require.user", "root");
65 	atf_tc_set_md_var(tc, "require.kmods", "pf");
66 }
67 
ATF_TC_BODY(addtables,tc)68 ATF_TC_BODY(addtables, tc)
69 {
70 	struct pfioc_table io;
71 	struct pfr_table tbl;
72 	struct pfr_table tbls[4];
73 	int flags;
74 
75 	COMMON_HEAD();
76 
77 	flags = 0;
78 
79 	bzero(&io, sizeof(io));
80 	io.pfrio_flags = flags;
81 	io.pfrio_buffer = &tbl;
82 	io.pfrio_esize = sizeof(tbl);
83 
84 	/* Negative size */
85 	io.pfrio_size = -1;
86 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
87 		atf_tc_fail("Request with size -1 succeeded");
88 
89 	/* Overly large size */
90 	io.pfrio_size = 1 << 24;
91 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
92 		atf_tc_fail("Request with size 1 << 24 succeeded");
93 
94 	/* NULL buffer */
95 	io.pfrio_size = 1;
96 	io.pfrio_buffer = NULL;
97 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
98 		atf_tc_fail("Request with NULL buffer succeeded");
99 
100 	/* This can provoke a memory leak, see r331225. */
101 	io.pfrio_size = 4;
102 	for (int i = 0; i < io.pfrio_size; i++)
103 		common_init_tbl(&tbls[i]);
104 
105 	io.pfrio_buffer = &tbls;
106 	ioctl(dev, DIOCRADDTABLES, &io);
107 }
108 
ATF_TC_CLEANUP(addtables,tc)109 ATF_TC_CLEANUP(addtables, tc)
110 {
111 	COMMON_CLEANUP();
112 }
113 
114 ATF_TC_WITH_CLEANUP(deltables);
ATF_TC_HEAD(deltables,tc)115 ATF_TC_HEAD(deltables, tc)
116 {
117 	atf_tc_set_md_var(tc, "require.user", "root");
118 	atf_tc_set_md_var(tc, "require.kmods", "pf");
119 }
120 
ATF_TC_BODY(deltables,tc)121 ATF_TC_BODY(deltables, tc)
122 {
123 	struct pfioc_table io;
124 	struct pfr_table tbl;
125 	int flags;
126 
127 	COMMON_HEAD();
128 
129 	flags = 0;
130 
131 	bzero(&io, sizeof(io));
132 	io.pfrio_flags = flags;
133 	io.pfrio_buffer = &tbl;
134 	io.pfrio_esize = sizeof(tbl);
135 
136 	/* Negative size */
137 	io.pfrio_size = -1;
138 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
139 		atf_tc_fail("Request with size -1 succeeded");
140 
141 	/* Overly large size */
142 	io.pfrio_size = 1 << 24;
143 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
144 		atf_tc_fail("Request with size 1 << 24 succeeded");
145 
146 	/* NULL buffer */
147 	io.pfrio_size = 1;
148 	io.pfrio_buffer = NULL;
149 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
150 		atf_tc_fail("Request with NULL buffer succeeded");
151 }
152 
ATF_TC_CLEANUP(deltables,tc)153 ATF_TC_CLEANUP(deltables, tc)
154 {
155 	COMMON_CLEANUP();
156 }
157 
158 ATF_TC_WITH_CLEANUP(gettables);
ATF_TC_HEAD(gettables,tc)159 ATF_TC_HEAD(gettables, tc)
160 {
161 	atf_tc_set_md_var(tc, "require.user", "root");
162 	atf_tc_set_md_var(tc, "require.kmods", "pf");
163 }
164 
ATF_TC_BODY(gettables,tc)165 ATF_TC_BODY(gettables, tc)
166 {
167 	struct pfioc_table io;
168 	struct pfr_table tbl;
169 	int flags;
170 
171 	COMMON_HEAD();
172 
173 	flags = 0;
174 
175 	bzero(&io, sizeof(io));
176 	io.pfrio_flags = flags;
177 	io.pfrio_buffer = &tbl;
178 	io.pfrio_esize = sizeof(tbl);
179 
180 	/* Negative size. This will succeed, because the kernel will not copy
181 	 * tables than it has. */
182 	io.pfrio_size = -1;
183 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
184 		atf_tc_fail("Request with size -1 failed");
185 
186 	/* Overly large size. See above. */
187 	io.pfrio_size = 1 << 24;
188 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
189 		atf_tc_fail("Request with size 1 << 24 failed");
190 }
191 
ATF_TC_CLEANUP(gettables,tc)192 ATF_TC_CLEANUP(gettables, tc)
193 {
194 	COMMON_CLEANUP();
195 }
196 
197 ATF_TC_WITH_CLEANUP(clrtables);
ATF_TC_HEAD(clrtables,tc)198 ATF_TC_HEAD(clrtables, tc)
199 {
200 	atf_tc_set_md_var(tc, "require.user", "root");
201 	atf_tc_set_md_var(tc, "require.kmods", "pf");
202 }
203 
ATF_TC_BODY(clrtables,tc)204 ATF_TC_BODY(clrtables, tc)
205 {
206 	struct pfioc_table io;
207 	struct pfr_table tbl;
208 	int flags;
209 
210 	COMMON_HEAD();
211 
212 	flags = 0;
213 
214 	memset(&io, '/', sizeof(io));
215 	io.pfrio_flags = flags;
216 	io.pfrio_buffer = &tbl;
217 	io.pfrio_esize = 0;
218 	io.pfrio_size = 1;
219 
220 	if (ioctl(dev, DIOCRCLRTABLES, &io) == 0)
221 		atf_tc_fail("Request with unterminated anchor name succeeded");
222 }
223 
ATF_TC_CLEANUP(clrtables,tc)224 ATF_TC_CLEANUP(clrtables, tc)
225 {
226 	COMMON_CLEANUP();
227 }
228 
229 ATF_TC_WITH_CLEANUP(gettstats);
ATF_TC_HEAD(gettstats,tc)230 ATF_TC_HEAD(gettstats, tc)
231 {
232 	atf_tc_set_md_var(tc, "require.user", "root");
233 	atf_tc_set_md_var(tc, "require.kmods", "pf");
234 }
235 
ATF_TC_BODY(gettstats,tc)236 ATF_TC_BODY(gettstats, tc)
237 {
238 	struct pfioc_table io;
239 	struct pfr_tstats stats;
240 	int flags;
241 
242 	COMMON_HEAD();
243 
244 	flags = 0;
245 
246 	bzero(&io, sizeof(io));
247 	io.pfrio_flags = flags;
248 	io.pfrio_buffer = &stats;
249 	io.pfrio_esize = sizeof(stats);
250 
251 	/* Negative size. This will succeed, because the kernel will not copy
252 	 * tables than it has. */
253 	io.pfrio_size = -1;
254 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
255 		atf_tc_fail("Request with size -1 failed");
256 
257 	/* Overly large size. See above. */
258 	io.pfrio_size = 1 << 24;
259 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
260 		atf_tc_fail("Request with size 1 << 24 failed");
261 }
262 
ATF_TC_CLEANUP(gettstats,tc)263 ATF_TC_CLEANUP(gettstats, tc)
264 {
265 	COMMON_CLEANUP();
266 }
267 
268 ATF_TC_WITH_CLEANUP(clrtstats);
ATF_TC_HEAD(clrtstats,tc)269 ATF_TC_HEAD(clrtstats, tc)
270 {
271 	atf_tc_set_md_var(tc, "require.user", "root");
272 	atf_tc_set_md_var(tc, "require.kmods", "pf");
273 }
274 
ATF_TC_BODY(clrtstats,tc)275 ATF_TC_BODY(clrtstats, tc)
276 {
277 	struct pfioc_table io;
278 	struct pfr_table tbl;
279 	int flags;
280 
281 	COMMON_HEAD();
282 
283 	flags = 0;
284 
285 	common_init_tbl(&tbl);
286 
287 	bzero(&io, sizeof(io));
288 	io.pfrio_flags = flags;
289 	io.pfrio_buffer = &tbl;
290 	io.pfrio_esize = sizeof(tbl);
291 
292 	/* Negative size. This will succeed, because the kernel will not copy
293 	 * tables than it has. */
294 	io.pfrio_size = -1;
295 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
296 		atf_tc_fail("Request with size -1 failed ");
297 
298 	/* Overly large size. See above. */
299 	io.pfrio_size = 1 << 24;
300 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
301 		atf_tc_fail("Request with size 1 << 24 failed");
302 
303 	io.pfrio_size = sizeof(tbl);
304 	io.pfrio_buffer = NULL;
305 	if (ioctl(dev, DIOCRCLRTSTATS, &io) == 0)
306 		atf_tc_fail("Request with NULL buffer succeeded");
307 }
308 
ATF_TC_CLEANUP(clrtstats,tc)309 ATF_TC_CLEANUP(clrtstats, tc)
310 {
311 	COMMON_CLEANUP();
312 }
313 
314 ATF_TC_WITH_CLEANUP(settflags);
ATF_TC_HEAD(settflags,tc)315 ATF_TC_HEAD(settflags, tc)
316 {
317 	atf_tc_set_md_var(tc, "require.user", "root");
318 	atf_tc_set_md_var(tc, "require.kmods", "pf");
319 }
320 
ATF_TC_BODY(settflags,tc)321 ATF_TC_BODY(settflags, tc)
322 {
323 	struct pfioc_table io;
324 	struct pfr_table tbl;
325 	int flags;
326 
327 	COMMON_HEAD();
328 
329 	flags = 0;
330 
331 	common_init_tbl(&tbl);
332 
333 	bzero(&io, sizeof(io));
334 	io.pfrio_flags = flags;
335 	io.pfrio_buffer = &tbl;
336 	io.pfrio_esize = sizeof(tbl);
337 
338 	/* Negative size. This will succeed, because the kernel will not copy
339 	 * tables than it has. */
340 	io.pfrio_size = -1;
341 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
342 		atf_tc_fail("Request with size -1 failed");
343 
344 	/* Overly large size. See above. */
345 	io.pfrio_size = 1 << 28;
346 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
347 		atf_tc_fail("Request with size 1 << 24 failed");
348 
349 	/* NULL buffer */
350 	io.pfrio_buffer = NULL;
351 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != -1)
352 		atf_tc_fail("Request with NULL buffer succeeded");
353 }
354 
ATF_TC_CLEANUP(settflags,tc)355 ATF_TC_CLEANUP(settflags, tc)
356 {
357 	COMMON_CLEANUP();
358 }
359 
360 ATF_TC_WITH_CLEANUP(addaddrs);
ATF_TC_HEAD(addaddrs,tc)361 ATF_TC_HEAD(addaddrs, tc)
362 {
363 	atf_tc_set_md_var(tc, "require.user", "root");
364 	atf_tc_set_md_var(tc, "require.kmods", "pf");
365 }
366 
ATF_TC_BODY(addaddrs,tc)367 ATF_TC_BODY(addaddrs, tc)
368 {
369 	struct pfioc_table io;
370 	struct pfr_addr addr;
371 
372 	COMMON_HEAD();
373 
374 	bzero(&addr, sizeof(addr));
375 	bzero(&io, sizeof(io));
376 	io.pfrio_flags = 0;
377 	io.pfrio_buffer = &addr;
378 	io.pfrio_esize = sizeof(addr);
379 
380 	/* Negative size. */
381 	io.pfrio_size = -1;
382 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
383 		atf_tc_fail("Request with size -1 succeeded");
384 
385 	/* Overly large size. */
386 	io.pfrio_size = 1 << 28;
387 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
388 		atf_tc_fail("Reuqest with size 1 << 28 failed");
389 }
390 
ATF_TC_CLEANUP(addaddrs,tc)391 ATF_TC_CLEANUP(addaddrs, tc)
392 {
393 	COMMON_CLEANUP();
394 }
395 
396 ATF_TC_WITH_CLEANUP(deladdrs);
ATF_TC_HEAD(deladdrs,tc)397 ATF_TC_HEAD(deladdrs, tc)
398 {
399 	atf_tc_set_md_var(tc, "require.user", "root");
400 	atf_tc_set_md_var(tc, "require.kmods", "pf");
401 }
402 
ATF_TC_BODY(deladdrs,tc)403 ATF_TC_BODY(deladdrs, tc)
404 {
405 	struct pfioc_table io;
406 	struct pfr_addr addr;
407 
408 	COMMON_HEAD();
409 
410 	bzero(&addr, sizeof(addr));
411 	bzero(&io, sizeof(io));
412 	io.pfrio_flags = 0;
413 	io.pfrio_buffer = &addr;
414 	io.pfrio_esize = sizeof(addr);
415 
416 	/* Negative size. */
417 	io.pfrio_size = -1;
418 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
419 		atf_tc_fail("Request with size -1 succeeded");
420 
421 	/* Overly large size. */
422 	io.pfrio_size = 1 << 28;
423 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
424 		atf_tc_fail("Reuqest with size 1 << 28 failed");
425 }
426 
ATF_TC_CLEANUP(deladdrs,tc)427 ATF_TC_CLEANUP(deladdrs, tc)
428 {
429 	COMMON_CLEANUP();
430 }
431 
432 ATF_TC_WITH_CLEANUP(setaddrs);
ATF_TC_HEAD(setaddrs,tc)433 ATF_TC_HEAD(setaddrs, tc)
434 {
435 	atf_tc_set_md_var(tc, "require.user", "root");
436 	atf_tc_set_md_var(tc, "require.kmods", "pf");
437 }
438 
ATF_TC_BODY(setaddrs,tc)439 ATF_TC_BODY(setaddrs, tc)
440 {
441 	struct pfioc_table io;
442 	struct pfr_addr addr;
443 
444 	COMMON_HEAD();
445 
446 	bzero(&addr, sizeof(addr));
447 	bzero(&io, sizeof(io));
448 	io.pfrio_flags = 0;
449 	io.pfrio_buffer = &addr;
450 	io.pfrio_esize = sizeof(addr);
451 
452 	/* Negative size. */
453 	io.pfrio_size = -1;
454 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
455 		atf_tc_fail("Request with size -1 succeeded");
456 
457 	/* Overly large size. */
458 	io.pfrio_size = 1 << 28;
459 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
460 		atf_tc_fail("Reuqest with size 1 << 28 failed");
461 }
462 
ATF_TC_CLEANUP(setaddrs,tc)463 ATF_TC_CLEANUP(setaddrs, tc)
464 {
465 	COMMON_CLEANUP();
466 }
467 
468 ATF_TC_WITH_CLEANUP(getaddrs);
ATF_TC_HEAD(getaddrs,tc)469 ATF_TC_HEAD(getaddrs, tc)
470 {
471 	atf_tc_set_md_var(tc, "require.user", "root");
472 	atf_tc_set_md_var(tc, "require.kmods", "pf");
473 }
474 
ATF_TC_BODY(getaddrs,tc)475 ATF_TC_BODY(getaddrs, tc)
476 {
477 	struct pfioc_table io;
478 	struct pfr_addr addr;
479 
480 	COMMON_HEAD();
481 
482 	bzero(&addr, sizeof(addr));
483 	bzero(&io, sizeof(io));
484 	io.pfrio_flags = 0;
485 	io.pfrio_buffer = &addr;
486 	io.pfrio_esize = sizeof(addr);
487 
488 	common_init_tbl(&io.pfrio_table);
489 
490 	/* Negative size. */
491 	io.pfrio_size = -1;
492 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
493 		atf_tc_fail("Request with size -1 succeeded");
494 
495 	/* Overly large size. */
496 	io.pfrio_size = 1 << 24;
497 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
498 		atf_tc_fail("Request with size 1 << 24 failed");
499 }
500 
ATF_TC_CLEANUP(getaddrs,tc)501 ATF_TC_CLEANUP(getaddrs, tc)
502 {
503 	COMMON_CLEANUP();
504 }
505 
506 ATF_TC_WITH_CLEANUP(getastats);
ATF_TC_HEAD(getastats,tc)507 ATF_TC_HEAD(getastats, tc)
508 {
509 	atf_tc_set_md_var(tc, "require.user", "root");
510 	atf_tc_set_md_var(tc, "require.kmods", "pf");
511 }
512 
ATF_TC_BODY(getastats,tc)513 ATF_TC_BODY(getastats, tc)
514 {
515 	struct pfioc_table io;
516 	struct pfr_astats astats;
517 
518 	COMMON_HEAD();
519 
520 	bzero(&astats, sizeof(astats));
521 	bzero(&io, sizeof(io));
522 	io.pfrio_flags = 0;
523 	io.pfrio_buffer = &astats;
524 	io.pfrio_esize = sizeof(astats);
525 
526 	common_init_tbl(&io.pfrio_table);
527 
528 	/* Negative size. */
529 	io.pfrio_size = -1;
530 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
531 		atf_tc_fail("Request with size -1 succeeded");
532 
533 	/* Overly large size. */
534 	io.pfrio_size = 1 << 24;
535 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
536 		atf_tc_fail("Request with size 1 << 24 failed");
537 }
538 
ATF_TC_CLEANUP(getastats,tc)539 ATF_TC_CLEANUP(getastats, tc)
540 {
541 	COMMON_CLEANUP();
542 }
543 
544 ATF_TC_WITH_CLEANUP(clrastats);
ATF_TC_HEAD(clrastats,tc)545 ATF_TC_HEAD(clrastats, tc)
546 {
547 	atf_tc_set_md_var(tc, "require.user", "root");
548 	atf_tc_set_md_var(tc, "require.kmods", "pf");
549 }
550 
ATF_TC_BODY(clrastats,tc)551 ATF_TC_BODY(clrastats, tc)
552 {
553 	struct pfioc_table io;
554 	struct pfr_addr addr;
555 
556 	COMMON_HEAD();
557 
558 	bzero(&addr, sizeof(addr));
559 	bzero(&io, sizeof(io));
560 	io.pfrio_flags = 0;
561 	io.pfrio_buffer = &addr;
562 	io.pfrio_esize = sizeof(addr);
563 
564 	common_init_tbl(&io.pfrio_table);
565 
566 	/* Negative size. */
567 	io.pfrio_size = -1;
568 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
569 		atf_tc_fail("Request with size -1 succeeded");
570 
571 	/* Overly large size. */
572 	io.pfrio_size = 1 << 24;
573 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
574 		atf_tc_fail("Request with size 1 << 24 failed");
575 }
576 
ATF_TC_CLEANUP(clrastats,tc)577 ATF_TC_CLEANUP(clrastats, tc)
578 {
579 	COMMON_CLEANUP();
580 }
581 
582 ATF_TC_WITH_CLEANUP(tstaddrs);
ATF_TC_HEAD(tstaddrs,tc)583 ATF_TC_HEAD(tstaddrs, tc)
584 {
585 	atf_tc_set_md_var(tc, "require.user", "root");
586 	atf_tc_set_md_var(tc, "require.kmods", "pf");
587 }
588 
ATF_TC_BODY(tstaddrs,tc)589 ATF_TC_BODY(tstaddrs, tc)
590 {
591 	struct pfioc_table io;
592 	struct pfr_addr addr;
593 
594 	COMMON_HEAD();
595 
596 	bzero(&addr, sizeof(addr));
597 	bzero(&io, sizeof(io));
598 	io.pfrio_flags = 0;
599 	io.pfrio_buffer = &addr;
600 	io.pfrio_esize = sizeof(addr);
601 
602 	common_init_tbl(&io.pfrio_table);
603 
604 	/* Negative size. */
605 	io.pfrio_size = -1;
606 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
607 		atf_tc_fail("Request with size -1 succeeded");
608 
609 	/* Overly large size. */
610 	io.pfrio_size = 1 << 24;
611 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
612 		atf_tc_fail("Request with size 1 << 24 failed");
613 }
614 
ATF_TC_CLEANUP(tstaddrs,tc)615 ATF_TC_CLEANUP(tstaddrs, tc)
616 {
617 	COMMON_CLEANUP();
618 }
619 
620 ATF_TC_WITH_CLEANUP(inadefine);
ATF_TC_HEAD(inadefine,tc)621 ATF_TC_HEAD(inadefine, tc)
622 {
623 	atf_tc_set_md_var(tc, "require.user", "root");
624 	atf_tc_set_md_var(tc, "require.kmods", "pf");
625 }
626 
ATF_TC_BODY(inadefine,tc)627 ATF_TC_BODY(inadefine, tc)
628 {
629 	struct pfioc_table io;
630 	struct pfr_addr addr;
631 
632 	COMMON_HEAD();
633 
634 	bzero(&addr, sizeof(addr));
635 	bzero(&io, sizeof(io));
636 	io.pfrio_flags = 0;
637 	io.pfrio_buffer = &addr;
638 	io.pfrio_esize = sizeof(addr);
639 
640 	common_init_tbl(&io.pfrio_table);
641 
642 	/* Negative size. */
643 	io.pfrio_size = -1;
644 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
645 		atf_tc_fail("Request with size -1 succeeded");
646 
647 	/* Overly large size. */
648 	io.pfrio_size = 1 << 24;
649 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
650 		atf_tc_fail("Request with size 1 << 24 failed");
651 }
652 
ATF_TC_CLEANUP(inadefine,tc)653 ATF_TC_CLEANUP(inadefine, tc)
654 {
655 	COMMON_CLEANUP();
656 }
657 
658 ATF_TC_WITH_CLEANUP(igetifaces);
ATF_TC_HEAD(igetifaces,tc)659 ATF_TC_HEAD(igetifaces, tc)
660 {
661 	atf_tc_set_md_var(tc, "require.user", "root");
662 	atf_tc_set_md_var(tc, "require.kmods", "pf");
663 }
664 
ATF_TC_BODY(igetifaces,tc)665 ATF_TC_BODY(igetifaces, tc)
666 {
667 	struct pfioc_iface io;
668 	struct pfi_kif kif;
669 
670 	COMMON_HEAD();
671 
672 	bzero(&io, sizeof(io));
673 	io.pfiio_flags = 0;
674 	io.pfiio_buffer = &kif;
675 	io.pfiio_esize = sizeof(kif);
676 
677 	/* Negative size */
678 	io.pfiio_size = -1;
679 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
680 		atf_tc_fail("request with size -1 succeeded");
681 
682 	/* Overflow size */
683 	io.pfiio_size = 1 << 31;
684 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
685 		atf_tc_fail("request with size 1 << 31 succeeded");
686 }
687 
ATF_TC_CLEANUP(igetifaces,tc)688 ATF_TC_CLEANUP(igetifaces, tc)
689 {
690 	COMMON_CLEANUP();
691 }
692 
693 ATF_TC_WITH_CLEANUP(cxbegin);
ATF_TC_HEAD(cxbegin,tc)694 ATF_TC_HEAD(cxbegin, tc)
695 {
696 	atf_tc_set_md_var(tc, "require.user", "root");
697 	atf_tc_set_md_var(tc, "require.kmods", "pf");
698 }
699 
ATF_TC_BODY(cxbegin,tc)700 ATF_TC_BODY(cxbegin, tc)
701 {
702 	struct pfioc_trans io;
703 	struct pfioc_trans_e ioe;
704 
705 	COMMON_HEAD();
706 
707 	bzero(&io, sizeof(io));
708 	io.esize = sizeof(ioe);
709 	io.array = &ioe;
710 
711 	/* Negative size */
712 	io.size = -1;
713 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
714 		atf_tc_fail("request with size -1 succeeded");
715 
716 	/* Overflow size */
717 	io.size = 1 << 30;
718 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
719 		atf_tc_fail("request with size 1 << 30 succeeded");
720 
721 	/* NULL buffer */
722 	io.size = 1;
723 	io.array = NULL;
724 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
725 		atf_tc_fail("request with size -1 succeeded");
726 }
727 
ATF_TC_CLEANUP(cxbegin,tc)728 ATF_TC_CLEANUP(cxbegin, tc)
729 {
730 	COMMON_CLEANUP();
731 }
732 
733 ATF_TC_WITH_CLEANUP(cxrollback);
ATF_TC_HEAD(cxrollback,tc)734 ATF_TC_HEAD(cxrollback, tc)
735 {
736 	atf_tc_set_md_var(tc, "require.user", "root");
737 	atf_tc_set_md_var(tc, "require.kmods", "pf");
738 }
739 
ATF_TC_BODY(cxrollback,tc)740 ATF_TC_BODY(cxrollback, tc)
741 {
742 	struct pfioc_trans io;
743 	struct pfioc_trans_e ioe;
744 
745 	COMMON_HEAD();
746 
747 	bzero(&io, sizeof(io));
748 	io.esize = sizeof(ioe);
749 	io.array = &ioe;
750 
751 	/* Negative size */
752 	io.size = -1;
753 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
754 		atf_tc_fail("request with size -1 succeeded");
755 
756 	/* Overflow size */
757 	io.size = 1 << 30;
758 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
759 		atf_tc_fail("request with size 1 << 30 succeeded");
760 
761 	/* NULL buffer */
762 	io.size = 1;
763 	io.array = NULL;
764 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
765 		atf_tc_fail("request with size -1 succeeded");
766 }
767 
ATF_TC_CLEANUP(cxrollback,tc)768 ATF_TC_CLEANUP(cxrollback, tc)
769 {
770 	COMMON_CLEANUP();
771 }
772 
773 ATF_TC_WITH_CLEANUP(commit);
ATF_TC_HEAD(commit,tc)774 ATF_TC_HEAD(commit, tc)
775 {
776 	atf_tc_set_md_var(tc, "require.user", "root");
777 	atf_tc_set_md_var(tc, "require.kmods", "pf");
778 }
779 
ATF_TC_BODY(commit,tc)780 ATF_TC_BODY(commit, tc)
781 {
782 	struct pfioc_trans io;
783 	struct pfioc_trans_e ioe;
784 
785 	COMMON_HEAD();
786 
787 	bzero(&io, sizeof(io));
788 	io.esize = sizeof(ioe);
789 	io.array = &ioe;
790 
791 	/* Negative size */
792 	io.size = -1;
793 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
794 		atf_tc_fail("request with size -1 succeeded");
795 
796 	/* Overflow size */
797 	io.size = 1 << 30;
798 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
799 		atf_tc_fail("request with size 1 << 30 succeeded");
800 
801 	/* NULL buffer */
802 	io.size = 1;
803 	io.array = NULL;
804 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
805 		atf_tc_fail("request with size -1 succeeded");
806 }
807 
ATF_TC_CLEANUP(commit,tc)808 ATF_TC_CLEANUP(commit, tc)
809 {
810 	COMMON_CLEANUP();
811 }
812 
813 ATF_TC_WITH_CLEANUP(getsrcnodes);
ATF_TC_HEAD(getsrcnodes,tc)814 ATF_TC_HEAD(getsrcnodes, tc)
815 {
816 	atf_tc_set_md_var(tc, "require.user", "root");
817 	atf_tc_set_md_var(tc, "require.kmods", "pf");
818 }
819 
ATF_TC_BODY(getsrcnodes,tc)820 ATF_TC_BODY(getsrcnodes, tc)
821 {
822 	struct pfioc_src_nodes psn;
823 
824 	COMMON_HEAD();
825 
826 	bzero(&psn, sizeof(psn));
827 
828 	psn.psn_len = -1;
829 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
830 		atf_tc_fail("request with size -1 failed");
831 
832 	psn.psn_len = 1 << 30;
833 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
834 		atf_tc_fail("request with size << 30 failed");
835 
836 	psn.psn_len = 1 << 31;
837 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
838 		atf_tc_fail("request with size << 30 failed");
839 }
840 
ATF_TC_CLEANUP(getsrcnodes,tc)841 ATF_TC_CLEANUP(getsrcnodes, tc)
842 {
843 	COMMON_CLEANUP();
844 }
845 
846 ATF_TC_WITH_CLEANUP(tag);
ATF_TC_HEAD(tag,tc)847 ATF_TC_HEAD(tag, tc)
848 {
849 	atf_tc_set_md_var(tc, "require.user", "root");
850 	atf_tc_set_md_var(tc, "require.kmods", "pf");
851 }
852 
ATF_TC_BODY(tag,tc)853 ATF_TC_BODY(tag, tc)
854 {
855 	struct pfioc_rule rule;
856 
857 	COMMON_HEAD();
858 
859 	memset(&rule, 0x42, sizeof(rule));
860 
861 	rule.ticket = 0;
862 	rule.pool_ticket = 0;
863 	rule.anchor[0] = 0;
864 
865 	rule.rule.return_icmp = 0;
866 	bzero(&rule.rule.src, sizeof(rule.rule.src));
867 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
868 
869 	rule.rule.ifname[0] = 0;
870 	rule.rule.action = 0;
871 	rule.rule.rtableid = 0;
872 
873 	rule.rule.tagname[0] = 0;
874 
875 	for (int i = 0; i < 10; i++)
876 		ioctl(dev, DIOCADDRULE, &rule);
877 }
878 
ATF_TC_CLEANUP(tag,tc)879 ATF_TC_CLEANUP(tag, tc)
880 {
881 	COMMON_CLEANUP();
882 }
883 
884 ATF_TC_WITH_CLEANUP(rpool_mtx);
ATF_TC_HEAD(rpool_mtx,tc)885 ATF_TC_HEAD(rpool_mtx, tc)
886 {
887 	atf_tc_set_md_var(tc, "require.user", "root");
888 	atf_tc_set_md_var(tc, "require.kmods", "pf");
889 }
890 
ATF_TC_BODY(rpool_mtx,tc)891 ATF_TC_BODY(rpool_mtx, tc)
892 {
893 	struct pfioc_rule rule;
894 
895 	COMMON_HEAD();
896 
897 	memset(&rule, 0, sizeof(rule));
898 
899 	rule.ticket = 0;
900 	rule.pool_ticket = 0;
901 	rule.anchor[0] = 0;
902 
903 	rule.rule.return_icmp = 0;
904 	bzero(&rule.rule.src, sizeof(rule.rule.src));
905 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
906 
907 	rule.rule.ifname[0] = 0;
908 	rule.rule.action = 0;
909 	rule.rule.rtableid = 0;
910 
911 	rule.rule.tagname[0] = 0;
912 	rule.rule.action = 42;
913 
914 	ioctl(dev, DIOCADDRULE, &rule);
915 }
916 
ATF_TC_CLEANUP(rpool_mtx,tc)917 ATF_TC_CLEANUP(rpool_mtx, tc)
918 {
919 	COMMON_CLEANUP();
920 }
921 
922 ATF_TC_WITH_CLEANUP(rpool_mtx2);
ATF_TC_HEAD(rpool_mtx2,tc)923 ATF_TC_HEAD(rpool_mtx2, tc)
924 {
925 	atf_tc_set_md_var(tc, "require.user", "root");
926 	atf_tc_set_md_var(tc, "require.kmods", "pf");
927 }
928 
ATF_TC_BODY(rpool_mtx2,tc)929 ATF_TC_BODY(rpool_mtx2, tc)
930 {
931 	struct pfioc_rule rule;
932 
933 	COMMON_HEAD();
934 
935 	memset(&rule, 0, sizeof(rule));
936 
937 	rule.pool_ticket = 1000000;
938 	rule.action = PF_CHANGE_ADD_HEAD;
939 	rule.rule.af = AF_INET;
940 
941 	ioctl(dev, DIOCCHANGERULE, &rule);
942 }
943 
ATF_TC_CLEANUP(rpool_mtx2,tc)944 ATF_TC_CLEANUP(rpool_mtx2, tc)
945 {
946 	COMMON_CLEANUP();
947 }
948 
949 ATF_TC_WITH_CLEANUP(natlook);
ATF_TC_HEAD(natlook,tc)950 ATF_TC_HEAD(natlook, tc)
951 {
952 	atf_tc_set_md_var(tc, "require.user", "root");
953 	atf_tc_set_md_var(tc, "require.kmods", "pf");
954 }
955 
ATF_TC_BODY(natlook,tc)956 ATF_TC_BODY(natlook, tc)
957 {
958 	struct pfioc_natlook nl = { 0 };
959 
960 	COMMON_HEAD();
961 
962 	nl.af = AF_INET;
963 	nl.proto = IPPROTO_ICMP;
964 	nl.saddr.v4.s_addr = 0x01020304;
965 	nl.daddr.v4.s_addr = 0x05060708;
966 
967 	/* Invalid direction */
968 	nl.direction = 42;
969 
970 	ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCNATLOOK, &nl) == -1);
971 
972 	/* Invalid af */
973 	nl.direction = PF_IN;
974 	nl.af = 99;
975 
976 	ATF_CHECK_ERRNO(EAFNOSUPPORT, ioctl(dev, DIOCNATLOOK, &nl) == -1);
977 }
978 
ATF_TC_CLEANUP(natlook,tc)979 ATF_TC_CLEANUP(natlook, tc)
980 {
981 	COMMON_CLEANUP();
982 }
983 
984 ATF_TC_WITH_CLEANUP(addstate);
ATF_TC_HEAD(addstate,tc)985 ATF_TC_HEAD(addstate, tc)
986 {
987 	atf_tc_set_md_var(tc, "require.user", "root");
988 	atf_tc_set_md_var(tc, "require.kmods", "pfsync");
989 }
990 
ATF_TC_BODY(addstate,tc)991 ATF_TC_BODY(addstate, tc)
992 {
993 	struct pfioc_state st;
994 
995 	COMMON_HEAD();
996 
997 	memset(&st, 'a', sizeof(st));
998 	st.state.timeout = PFTM_TCP_FIRST_PACKET;
999 
1000 	ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCADDSTATE, &st) == -1);
1001 }
1002 
ATF_TC_CLEANUP(addstate,tc)1003 ATF_TC_CLEANUP(addstate, tc)
1004 {
1005 	COMMON_CLEANUP();
1006 }
1007 
ATF_TP_ADD_TCS(tp)1008 ATF_TP_ADD_TCS(tp)
1009 {
1010 	ATF_TP_ADD_TC(tp, addtables);
1011 	ATF_TP_ADD_TC(tp, deltables);
1012 	ATF_TP_ADD_TC(tp, gettables);
1013 	ATF_TP_ADD_TC(tp, clrtables);
1014 	ATF_TP_ADD_TC(tp, getastats);
1015 	ATF_TP_ADD_TC(tp, gettstats);
1016 	ATF_TP_ADD_TC(tp, clrtstats);
1017 	ATF_TP_ADD_TC(tp, settflags);
1018 	ATF_TP_ADD_TC(tp, addaddrs);
1019 	ATF_TP_ADD_TC(tp, deladdrs);
1020 	ATF_TP_ADD_TC(tp, setaddrs);
1021 	ATF_TP_ADD_TC(tp, getaddrs);
1022 	ATF_TP_ADD_TC(tp, clrastats);
1023 	ATF_TP_ADD_TC(tp, tstaddrs);
1024 	ATF_TP_ADD_TC(tp, inadefine);
1025 	ATF_TP_ADD_TC(tp, igetifaces);
1026 	ATF_TP_ADD_TC(tp, cxbegin);
1027 	ATF_TP_ADD_TC(tp, cxrollback);
1028 	ATF_TP_ADD_TC(tp, commit);
1029 	ATF_TP_ADD_TC(tp, getsrcnodes);
1030 	ATF_TP_ADD_TC(tp, tag);
1031 	ATF_TP_ADD_TC(tp, rpool_mtx);
1032 	ATF_TP_ADD_TC(tp, rpool_mtx2);
1033 	ATF_TP_ADD_TC(tp, natlook);
1034 	ATF_TP_ADD_TC(tp, addstate);
1035 
1036 	return (atf_no_error());
1037 }
1038