xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision 315ee00f)
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 <fcntl.h>
36 #include <stdio.h>
37 
38 #include <atf-c.h>
39 
40 static int dev;
41 
42 #define COMMON_HEAD() \
43 	if (modfind("pf") == -1) \
44 		atf_tc_skip("pf not loaded"); \
45 	dev = open("/dev/pf", O_RDWR); \
46 	if (dev == -1) \
47 		atf_tc_skip("Failed to open /dev/pf");
48 
49 #define COMMON_CLEANUP() \
50 	close(dev);
51 
52 static void
53 common_init_tbl(struct pfr_table *tbl)
54 {
55 	bzero(tbl, sizeof(struct pfr_table));
56 	strcpy(tbl->pfrt_anchor, "anchor");
57 	strcpy(tbl->pfrt_name, "name");
58 	tbl->pfrt_flags = 0;
59 	tbl->pfrt_fback = 0;
60 }
61 
62 ATF_TC_WITH_CLEANUP(addtables);
63 ATF_TC_HEAD(addtables, tc)
64 {
65 	atf_tc_set_md_var(tc, "require.user", "root");
66 }
67 
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 
109 ATF_TC_CLEANUP(addtables, tc)
110 {
111 	COMMON_CLEANUP();
112 }
113 
114 ATF_TC_WITH_CLEANUP(deltables);
115 ATF_TC_HEAD(deltables, tc)
116 {
117 	atf_tc_set_md_var(tc, "require.user", "root");
118 }
119 
120 ATF_TC_BODY(deltables, tc)
121 {
122 	struct pfioc_table io;
123 	struct pfr_table tbl;
124 	int flags;
125 
126 	COMMON_HEAD();
127 
128 	flags = 0;
129 
130 	bzero(&io, sizeof(io));
131 	io.pfrio_flags = flags;
132 	io.pfrio_buffer = &tbl;
133 	io.pfrio_esize = sizeof(tbl);
134 
135 	/* Negative size */
136 	io.pfrio_size = -1;
137 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
138 		atf_tc_fail("Request with size -1 succeeded");
139 
140 	/* Overly large size */
141 	io.pfrio_size = 1 << 24;
142 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
143 		atf_tc_fail("Request with size 1 << 24 succeeded");
144 
145 	/* NULL buffer */
146 	io.pfrio_size = 1;
147 	io.pfrio_buffer = NULL;
148 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
149 		atf_tc_fail("Request with NULL buffer succeeded");
150 }
151 
152 ATF_TC_CLEANUP(deltables, tc)
153 {
154 	COMMON_CLEANUP();
155 }
156 
157 ATF_TC_WITH_CLEANUP(gettables);
158 ATF_TC_HEAD(gettables, tc)
159 {
160 	atf_tc_set_md_var(tc, "require.user", "root");
161 }
162 
163 ATF_TC_BODY(gettables, tc)
164 {
165 	struct pfioc_table io;
166 	struct pfr_table tbl;
167 	int flags;
168 
169 	COMMON_HEAD();
170 
171 	flags = 0;
172 
173 	bzero(&io, sizeof(io));
174 	io.pfrio_flags = flags;
175 	io.pfrio_buffer = &tbl;
176 	io.pfrio_esize = sizeof(tbl);
177 
178 	/* Negative size. This will succeed, because the kernel will not copy
179 	 * tables than it has. */
180 	io.pfrio_size = -1;
181 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
182 		atf_tc_fail("Request with size -1 failed");
183 
184 	/* Overly large size. See above. */
185 	io.pfrio_size = 1 << 24;
186 	if (ioctl(dev, DIOCRGETTABLES, &io) != 0)
187 		atf_tc_fail("Request with size 1 << 24 failed");
188 }
189 
190 ATF_TC_CLEANUP(gettables, tc)
191 {
192 	COMMON_CLEANUP();
193 }
194 
195 ATF_TC_WITH_CLEANUP(gettstats);
196 ATF_TC_HEAD(gettstats, tc)
197 {
198 	atf_tc_set_md_var(tc, "require.user", "root");
199 }
200 
201 ATF_TC_BODY(gettstats, tc)
202 {
203 	struct pfioc_table io;
204 	struct pfr_tstats stats;
205 	int flags;
206 
207 	COMMON_HEAD();
208 
209 	flags = 0;
210 
211 	bzero(&io, sizeof(io));
212 	io.pfrio_flags = flags;
213 	io.pfrio_buffer = &stats;
214 	io.pfrio_esize = sizeof(stats);
215 
216 	/* Negative size. This will succeed, because the kernel will not copy
217 	 * tables than it has. */
218 	io.pfrio_size = -1;
219 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
220 		atf_tc_fail("Request with size -1 failed");
221 
222 	/* Overly large size. See above. */
223 	io.pfrio_size = 1 << 24;
224 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
225 		atf_tc_fail("Request with size 1 << 24 failed");
226 }
227 
228 ATF_TC_CLEANUP(gettstats, tc)
229 {
230 	COMMON_CLEANUP();
231 }
232 
233 ATF_TC_WITH_CLEANUP(clrtstats);
234 ATF_TC_HEAD(clrtstats, tc)
235 {
236 	atf_tc_set_md_var(tc, "require.user", "root");
237 }
238 
239 ATF_TC_BODY(clrtstats, tc)
240 {
241 	struct pfioc_table io;
242 	struct pfr_table tbl;
243 	int flags;
244 
245 	COMMON_HEAD();
246 
247 	flags = 0;
248 
249 	common_init_tbl(&tbl);
250 
251 	bzero(&io, sizeof(io));
252 	io.pfrio_flags = flags;
253 	io.pfrio_buffer = &tbl;
254 	io.pfrio_esize = sizeof(tbl);
255 
256 	/* Negative size. This will succeed, because the kernel will not copy
257 	 * tables than it has. */
258 	io.pfrio_size = -1;
259 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
260 		atf_tc_fail("Request with size -1 failed ");
261 
262 	/* Overly large size. See above. */
263 	io.pfrio_size = 1 << 24;
264 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
265 		atf_tc_fail("Request with size 1 << 24 failed");
266 
267 	io.pfrio_size = sizeof(tbl);
268 	io.pfrio_buffer = NULL;
269 	if (ioctl(dev, DIOCRCLRTSTATS, &io) == 0)
270 		atf_tc_fail("Request with NULL buffer succeeded");
271 }
272 
273 ATF_TC_CLEANUP(clrtstats, tc)
274 {
275 	COMMON_CLEANUP();
276 }
277 
278 ATF_TC_WITH_CLEANUP(settflags);
279 ATF_TC_HEAD(settflags, tc)
280 {
281 	atf_tc_set_md_var(tc, "require.user", "root");
282 }
283 
284 ATF_TC_BODY(settflags, tc)
285 {
286 	struct pfioc_table io;
287 	struct pfr_table tbl;
288 	int flags;
289 
290 	COMMON_HEAD();
291 
292 	flags = 0;
293 
294 	common_init_tbl(&tbl);
295 
296 	bzero(&io, sizeof(io));
297 	io.pfrio_flags = flags;
298 	io.pfrio_buffer = &tbl;
299 	io.pfrio_esize = sizeof(tbl);
300 
301 	/* Negative size. This will succeed, because the kernel will not copy
302 	 * tables than it has. */
303 	io.pfrio_size = -1;
304 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
305 		atf_tc_fail("Request with size -1 failed");
306 
307 	/* Overly large size. See above. */
308 	io.pfrio_size = 1 << 28;
309 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
310 		atf_tc_fail("Request with size 1 << 24 failed");
311 
312 	/* NULL buffer */
313 	io.pfrio_buffer = NULL;
314 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != -1)
315 		atf_tc_fail("Request with NULL buffer succeeded");
316 }
317 
318 ATF_TC_CLEANUP(settflags, tc)
319 {
320 	COMMON_CLEANUP();
321 }
322 
323 ATF_TC_WITH_CLEANUP(addaddrs);
324 ATF_TC_HEAD(addaddrs, tc)
325 {
326 	atf_tc_set_md_var(tc, "require.user", "root");
327 }
328 
329 ATF_TC_BODY(addaddrs, tc)
330 {
331 	struct pfioc_table io;
332 	struct pfr_addr addr;
333 
334 	COMMON_HEAD();
335 
336 	bzero(&addr, sizeof(addr));
337 	bzero(&io, sizeof(io));
338 	io.pfrio_flags = 0;
339 	io.pfrio_buffer = &addr;
340 	io.pfrio_esize = sizeof(addr);
341 
342 	/* Negative size. */
343 	io.pfrio_size = -1;
344 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
345 		atf_tc_fail("Request with size -1 succeeded");
346 
347 	/* Overly large size. */
348 	io.pfrio_size = 1 << 28;
349 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
350 		atf_tc_fail("Reuqest with size 1 << 28 failed");
351 }
352 
353 ATF_TC_CLEANUP(addaddrs, tc)
354 {
355 	COMMON_CLEANUP();
356 }
357 
358 ATF_TC_WITH_CLEANUP(deladdrs);
359 ATF_TC_HEAD(deladdrs, tc)
360 {
361 	atf_tc_set_md_var(tc, "require.user", "root");
362 }
363 
364 ATF_TC_BODY(deladdrs, tc)
365 {
366 	struct pfioc_table io;
367 	struct pfr_addr addr;
368 
369 	COMMON_HEAD();
370 
371 	bzero(&addr, sizeof(addr));
372 	bzero(&io, sizeof(io));
373 	io.pfrio_flags = 0;
374 	io.pfrio_buffer = &addr;
375 	io.pfrio_esize = sizeof(addr);
376 
377 	/* Negative size. */
378 	io.pfrio_size = -1;
379 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
380 		atf_tc_fail("Request with size -1 succeeded");
381 
382 	/* Overly large size. */
383 	io.pfrio_size = 1 << 28;
384 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
385 		atf_tc_fail("Reuqest with size 1 << 28 failed");
386 }
387 
388 ATF_TC_CLEANUP(deladdrs, tc)
389 {
390 	COMMON_CLEANUP();
391 }
392 
393 ATF_TC_WITH_CLEANUP(setaddrs);
394 ATF_TC_HEAD(setaddrs, tc)
395 {
396 	atf_tc_set_md_var(tc, "require.user", "root");
397 }
398 
399 ATF_TC_BODY(setaddrs, tc)
400 {
401 	struct pfioc_table io;
402 	struct pfr_addr addr;
403 
404 	COMMON_HEAD();
405 
406 	bzero(&addr, sizeof(addr));
407 	bzero(&io, sizeof(io));
408 	io.pfrio_flags = 0;
409 	io.pfrio_buffer = &addr;
410 	io.pfrio_esize = sizeof(addr);
411 
412 	/* Negative size. */
413 	io.pfrio_size = -1;
414 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
415 		atf_tc_fail("Request with size -1 succeeded");
416 
417 	/* Overly large size. */
418 	io.pfrio_size = 1 << 28;
419 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
420 		atf_tc_fail("Reuqest with size 1 << 28 failed");
421 }
422 
423 ATF_TC_CLEANUP(setaddrs, tc)
424 {
425 	COMMON_CLEANUP();
426 }
427 
428 ATF_TC_WITH_CLEANUP(getaddrs);
429 ATF_TC_HEAD(getaddrs, tc)
430 {
431 	atf_tc_set_md_var(tc, "require.user", "root");
432 }
433 
434 ATF_TC_BODY(getaddrs, tc)
435 {
436 	struct pfioc_table io;
437 	struct pfr_addr addr;
438 
439 	COMMON_HEAD();
440 
441 	bzero(&addr, sizeof(addr));
442 	bzero(&io, sizeof(io));
443 	io.pfrio_flags = 0;
444 	io.pfrio_buffer = &addr;
445 	io.pfrio_esize = sizeof(addr);
446 
447 	common_init_tbl(&io.pfrio_table);
448 
449 	/* Negative size. */
450 	io.pfrio_size = -1;
451 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
452 		atf_tc_fail("Request with size -1 succeeded");
453 
454 	/* Overly large size. */
455 	io.pfrio_size = 1 << 24;
456 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
457 		atf_tc_fail("Request with size 1 << 24 failed");
458 }
459 
460 ATF_TC_CLEANUP(getaddrs, tc)
461 {
462 	COMMON_CLEANUP();
463 }
464 
465 ATF_TC_WITH_CLEANUP(getastats);
466 ATF_TC_HEAD(getastats, tc)
467 {
468 	atf_tc_set_md_var(tc, "require.user", "root");
469 }
470 
471 ATF_TC_BODY(getastats, tc)
472 {
473 	struct pfioc_table io;
474 	struct pfr_astats astats;
475 
476 	COMMON_HEAD();
477 
478 	bzero(&astats, sizeof(astats));
479 	bzero(&io, sizeof(io));
480 	io.pfrio_flags = 0;
481 	io.pfrio_buffer = &astats;
482 	io.pfrio_esize = sizeof(astats);
483 
484 	common_init_tbl(&io.pfrio_table);
485 
486 	/* Negative size. */
487 	io.pfrio_size = -1;
488 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
489 		atf_tc_fail("Request with size -1 succeeded");
490 
491 	/* Overly large size. */
492 	io.pfrio_size = 1 << 24;
493 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
494 		atf_tc_fail("Request with size 1 << 24 failed");
495 }
496 
497 ATF_TC_CLEANUP(getastats, tc)
498 {
499 	COMMON_CLEANUP();
500 }
501 
502 ATF_TC_WITH_CLEANUP(clrastats);
503 ATF_TC_HEAD(clrastats, tc)
504 {
505 	atf_tc_set_md_var(tc, "require.user", "root");
506 }
507 
508 ATF_TC_BODY(clrastats, tc)
509 {
510 	struct pfioc_table io;
511 	struct pfr_addr addr;
512 
513 	COMMON_HEAD();
514 
515 	bzero(&addr, sizeof(addr));
516 	bzero(&io, sizeof(io));
517 	io.pfrio_flags = 0;
518 	io.pfrio_buffer = &addr;
519 	io.pfrio_esize = sizeof(addr);
520 
521 	common_init_tbl(&io.pfrio_table);
522 
523 	/* Negative size. */
524 	io.pfrio_size = -1;
525 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
526 		atf_tc_fail("Request with size -1 succeeded");
527 
528 	/* Overly large size. */
529 	io.pfrio_size = 1 << 24;
530 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
531 		atf_tc_fail("Request with size 1 << 24 failed");
532 }
533 
534 ATF_TC_CLEANUP(clrastats, tc)
535 {
536 	COMMON_CLEANUP();
537 }
538 
539 ATF_TC_WITH_CLEANUP(tstaddrs);
540 ATF_TC_HEAD(tstaddrs, tc)
541 {
542 	atf_tc_set_md_var(tc, "require.user", "root");
543 }
544 
545 ATF_TC_BODY(tstaddrs, tc)
546 {
547 	struct pfioc_table io;
548 	struct pfr_addr addr;
549 
550 	COMMON_HEAD();
551 
552 	bzero(&addr, sizeof(addr));
553 	bzero(&io, sizeof(io));
554 	io.pfrio_flags = 0;
555 	io.pfrio_buffer = &addr;
556 	io.pfrio_esize = sizeof(addr);
557 
558 	common_init_tbl(&io.pfrio_table);
559 
560 	/* Negative size. */
561 	io.pfrio_size = -1;
562 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
563 		atf_tc_fail("Request with size -1 succeeded");
564 
565 	/* Overly large size. */
566 	io.pfrio_size = 1 << 24;
567 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
568 		atf_tc_fail("Request with size 1 << 24 failed");
569 }
570 
571 ATF_TC_CLEANUP(tstaddrs, tc)
572 {
573 	COMMON_CLEANUP();
574 }
575 
576 ATF_TC_WITH_CLEANUP(inadefine);
577 ATF_TC_HEAD(inadefine, tc)
578 {
579 	atf_tc_set_md_var(tc, "require.user", "root");
580 }
581 
582 ATF_TC_BODY(inadefine, tc)
583 {
584 	struct pfioc_table io;
585 	struct pfr_addr addr;
586 
587 	COMMON_HEAD();
588 
589 	bzero(&addr, sizeof(addr));
590 	bzero(&io, sizeof(io));
591 	io.pfrio_flags = 0;
592 	io.pfrio_buffer = &addr;
593 	io.pfrio_esize = sizeof(addr);
594 
595 	common_init_tbl(&io.pfrio_table);
596 
597 	/* Negative size. */
598 	io.pfrio_size = -1;
599 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
600 		atf_tc_fail("Request with size -1 succeeded");
601 
602 	/* Overly large size. */
603 	io.pfrio_size = 1 << 24;
604 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
605 		atf_tc_fail("Request with size 1 << 24 failed");
606 }
607 
608 ATF_TC_CLEANUP(inadefine, tc)
609 {
610 	COMMON_CLEANUP();
611 }
612 
613 ATF_TC_WITH_CLEANUP(igetifaces);
614 ATF_TC_HEAD(igetifaces, tc)
615 {
616 	atf_tc_set_md_var(tc, "require.user", "root");
617 }
618 
619 ATF_TC_BODY(igetifaces, tc)
620 {
621 	struct pfioc_iface io;
622 	struct pfi_kif kif;
623 
624 	COMMON_HEAD();
625 
626 	bzero(&io, sizeof(io));
627 	io.pfiio_flags = 0;
628 	io.pfiio_buffer = &kif;
629 	io.pfiio_esize = sizeof(kif);
630 
631 	/* Negative size */
632 	io.pfiio_size = -1;
633 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
634 		atf_tc_fail("request with size -1 succeeded");
635 
636 	/* Overflow size */
637 	io.pfiio_size = 1 << 31;
638 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
639 		atf_tc_fail("request with size 1 << 31 succeeded");
640 }
641 
642 ATF_TC_CLEANUP(igetifaces, tc)
643 {
644 	COMMON_CLEANUP();
645 }
646 
647 ATF_TC_WITH_CLEANUP(cxbegin);
648 ATF_TC_HEAD(cxbegin, tc)
649 {
650 	atf_tc_set_md_var(tc, "require.user", "root");
651 }
652 
653 ATF_TC_BODY(cxbegin, tc)
654 {
655 	struct pfioc_trans io;
656 	struct pfioc_trans_e ioe;
657 
658 	COMMON_HEAD();
659 
660 	bzero(&io, sizeof(io));
661 	io.esize = sizeof(ioe);
662 	io.array = &ioe;
663 
664 	/* Negative size */
665 	io.size = -1;
666 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
667 		atf_tc_fail("request with size -1 succeeded");
668 
669 	/* Overflow size */
670 	io.size = 1 << 30;
671 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
672 		atf_tc_fail("request with size 1 << 30 succeeded");
673 
674 	/* NULL buffer */
675 	io.size = 1;
676 	io.array = NULL;
677 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
678 		atf_tc_fail("request with size -1 succeeded");
679 }
680 
681 ATF_TC_CLEANUP(cxbegin, tc)
682 {
683 	COMMON_CLEANUP();
684 }
685 
686 ATF_TC_WITH_CLEANUP(cxrollback);
687 ATF_TC_HEAD(cxrollback, tc)
688 {
689 	atf_tc_set_md_var(tc, "require.user", "root");
690 }
691 
692 ATF_TC_BODY(cxrollback, tc)
693 {
694 	struct pfioc_trans io;
695 	struct pfioc_trans_e ioe;
696 
697 	COMMON_HEAD();
698 
699 	bzero(&io, sizeof(io));
700 	io.esize = sizeof(ioe);
701 	io.array = &ioe;
702 
703 	/* Negative size */
704 	io.size = -1;
705 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
706 		atf_tc_fail("request with size -1 succeeded");
707 
708 	/* Overflow size */
709 	io.size = 1 << 30;
710 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
711 		atf_tc_fail("request with size 1 << 30 succeeded");
712 
713 	/* NULL buffer */
714 	io.size = 1;
715 	io.array = NULL;
716 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
717 		atf_tc_fail("request with size -1 succeeded");
718 }
719 
720 ATF_TC_CLEANUP(cxrollback, tc)
721 {
722 	COMMON_CLEANUP();
723 }
724 
725 ATF_TC_WITH_CLEANUP(commit);
726 ATF_TC_HEAD(commit, tc)
727 {
728 	atf_tc_set_md_var(tc, "require.user", "root");
729 }
730 
731 ATF_TC_BODY(commit, tc)
732 {
733 	struct pfioc_trans io;
734 	struct pfioc_trans_e ioe;
735 
736 	COMMON_HEAD();
737 
738 	bzero(&io, sizeof(io));
739 	io.esize = sizeof(ioe);
740 	io.array = &ioe;
741 
742 	/* Negative size */
743 	io.size = -1;
744 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
745 		atf_tc_fail("request with size -1 succeeded");
746 
747 	/* Overflow size */
748 	io.size = 1 << 30;
749 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
750 		atf_tc_fail("request with size 1 << 30 succeeded");
751 
752 	/* NULL buffer */
753 	io.size = 1;
754 	io.array = NULL;
755 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
756 		atf_tc_fail("request with size -1 succeeded");
757 }
758 
759 ATF_TC_CLEANUP(commit, tc)
760 {
761 	COMMON_CLEANUP();
762 }
763 
764 ATF_TC_WITH_CLEANUP(getsrcnodes);
765 ATF_TC_HEAD(getsrcnodes, tc)
766 {
767 	atf_tc_set_md_var(tc, "require.user", "root");
768 }
769 
770 ATF_TC_BODY(getsrcnodes, tc)
771 {
772 	struct pfioc_src_nodes psn;
773 
774 	COMMON_HEAD();
775 
776 	bzero(&psn, sizeof(psn));
777 
778 	psn.psn_len = -1;
779 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
780 		atf_tc_fail("request with size -1 failed");
781 
782 	psn.psn_len = 1 << 30;
783 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
784 		atf_tc_fail("request with size << 30 failed");
785 
786 	psn.psn_len = 1 << 31;
787 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
788 		atf_tc_fail("request with size << 30 failed");
789 }
790 
791 ATF_TC_CLEANUP(getsrcnodes, tc)
792 {
793 	COMMON_CLEANUP();
794 }
795 
796 ATF_TC_WITH_CLEANUP(tag);
797 ATF_TC_HEAD(tag, tc)
798 {
799 	atf_tc_set_md_var(tc, "require.user", "root");
800 }
801 
802 ATF_TC_BODY(tag, tc)
803 {
804 	struct pfioc_rule rule;
805 
806 	COMMON_HEAD();
807 
808 	memset(&rule, 0x42, sizeof(rule));
809 
810 	rule.ticket = 0;
811 	rule.pool_ticket = 0;
812 	rule.anchor[0] = 0;
813 
814 	rule.rule.return_icmp = 0;
815 	bzero(&rule.rule.src, sizeof(rule.rule.src));
816 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
817 
818 	rule.rule.ifname[0] = 0;
819 	rule.rule.action = 0;
820 	rule.rule.rtableid = 0;
821 
822 	rule.rule.tagname[0] = 0;
823 
824 	for (int i = 0; i < 10; i++)
825 		ioctl(dev, DIOCADDRULE, &rule);
826 }
827 
828 ATF_TC_CLEANUP(tag, tc)
829 {
830 	COMMON_CLEANUP();
831 }
832 
833 ATF_TC_WITH_CLEANUP(rpool_mtx);
834 ATF_TC_HEAD(rpool_mtx, tc)
835 {
836 	atf_tc_set_md_var(tc, "require.user", "root");
837 }
838 
839 ATF_TC_BODY(rpool_mtx, tc)
840 {
841 	struct pfioc_rule rule;
842 
843 	COMMON_HEAD();
844 
845 	memset(&rule, 0, sizeof(rule));
846 
847 	rule.ticket = 0;
848 	rule.pool_ticket = 0;
849 	rule.anchor[0] = 0;
850 
851 	rule.rule.return_icmp = 0;
852 	bzero(&rule.rule.src, sizeof(rule.rule.src));
853 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
854 
855 	rule.rule.ifname[0] = 0;
856 	rule.rule.action = 0;
857 	rule.rule.rtableid = 0;
858 
859 	rule.rule.tagname[0] = 0;
860 	rule.rule.action = 42;
861 
862 	ioctl(dev, DIOCADDRULE, &rule);
863 }
864 
865 ATF_TC_CLEANUP(rpool_mtx, tc)
866 {
867 	COMMON_CLEANUP();
868 }
869 
870 ATF_TC_WITH_CLEANUP(rpool_mtx2);
871 ATF_TC_HEAD(rpool_mtx2, tc)
872 {
873 	atf_tc_set_md_var(tc, "require.user", "root");
874 }
875 
876 ATF_TC_BODY(rpool_mtx2, tc)
877 {
878 	struct pfioc_rule rule;
879 
880 	COMMON_HEAD();
881 
882 	memset(&rule, 0, sizeof(rule));
883 
884 	rule.pool_ticket = 1000000;
885 	rule.action = PF_CHANGE_ADD_HEAD;
886 	rule.rule.af = AF_INET;
887 
888 	ioctl(dev, DIOCCHANGERULE, &rule);
889 }
890 
891 ATF_TC_CLEANUP(rpool_mtx2, tc)
892 {
893 	COMMON_CLEANUP();
894 }
895 
896 
897 ATF_TP_ADD_TCS(tp)
898 {
899 	ATF_TP_ADD_TC(tp, addtables);
900 	ATF_TP_ADD_TC(tp, deltables);
901 	ATF_TP_ADD_TC(tp, gettables);
902 	ATF_TP_ADD_TC(tp, getastats);
903 	ATF_TP_ADD_TC(tp, gettstats);
904 	ATF_TP_ADD_TC(tp, clrtstats);
905 	ATF_TP_ADD_TC(tp, settflags);
906 	ATF_TP_ADD_TC(tp, addaddrs);
907 	ATF_TP_ADD_TC(tp, deladdrs);
908 	ATF_TP_ADD_TC(tp, setaddrs);
909 	ATF_TP_ADD_TC(tp, getaddrs);
910 	ATF_TP_ADD_TC(tp, clrastats);
911 	ATF_TP_ADD_TC(tp, tstaddrs);
912 	ATF_TP_ADD_TC(tp, inadefine);
913 	ATF_TP_ADD_TC(tp, igetifaces);
914 	ATF_TP_ADD_TC(tp, cxbegin);
915 	ATF_TP_ADD_TC(tp, cxrollback);
916 	ATF_TP_ADD_TC(tp, commit);
917 	ATF_TP_ADD_TC(tp, getsrcnodes);
918 	ATF_TP_ADD_TC(tp, tag);
919 	ATF_TP_ADD_TC(tp, rpool_mtx);
920 	ATF_TP_ADD_TC(tp, rpool_mtx2);
921 
922 	return (atf_no_error());
923 }
924