xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision 4e99f45480598189d49d45a825533a6c9e12f02c)
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  * $FreeBSD$
26  */
27 
28 #include <sys/param.h>
29 #include <sys/module.h>
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 
34 #include <net/if.h>
35 #include <net/pfvar.h>
36 
37 #include <fcntl.h>
38 #include <stdio.h>
39 
40 #include <atf-c.h>
41 
42 static int dev;
43 
44 #define COMMON_HEAD() \
45 	if (modfind("pf") == -1) \
46 		atf_tc_skip("pf not loaded"); \
47 	dev = open("/dev/pf", O_RDWR); \
48 	if (dev == -1) \
49 		atf_tc_skip("Failed to open /dev/pf");
50 
51 #define COMMON_CLEANUP() \
52 	close(dev);
53 
54 static void
55 common_init_tbl(struct pfr_table *tbl)
56 {
57 	bzero(tbl, sizeof(struct pfr_table));
58 	strcpy(tbl->pfrt_anchor, "anchor");
59 	strcpy(tbl->pfrt_name, "name");
60 	tbl->pfrt_flags = 0;
61 	tbl->pfrt_fback = 0;
62 }
63 
64 ATF_TC_WITH_CLEANUP(addtables);
65 ATF_TC_HEAD(addtables, tc)
66 {
67 	atf_tc_set_md_var(tc, "require.user", "root");
68 }
69 
70 ATF_TC_BODY(addtables, tc)
71 {
72 	struct pfioc_table io;
73 	struct pfr_table tbl;
74 	struct pfr_table tbls[4];
75 	int flags;
76 
77 	COMMON_HEAD();
78 
79 	flags = 0;
80 
81 	bzero(&io, sizeof(io));
82 	io.pfrio_flags = flags;
83 	io.pfrio_buffer = &tbl;
84 	io.pfrio_esize = sizeof(tbl);
85 
86 	/* Negative size */
87 	io.pfrio_size = -1;
88 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
89 		atf_tc_fail("Request with size -1 succeeded");
90 
91 	/* Overly large size */
92 	io.pfrio_size = 1 << 24;
93 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
94 		atf_tc_fail("Request with size 1 << 24 succeeded");
95 
96 	/* NULL buffer */
97 	io.pfrio_size = 1;
98 	io.pfrio_buffer = NULL;
99 	if (ioctl(dev, DIOCRADDTABLES, &io) == 0)
100 		atf_tc_fail("Request with NULL buffer succeeded");
101 
102 	/* This can provoke a memory leak, see r331225. */
103 	io.pfrio_size = 4;
104 	for (int i = 0; i < io.pfrio_size; i++)
105 		common_init_tbl(&tbls[i]);
106 
107 	io.pfrio_buffer = &tbls;
108 	ioctl(dev, DIOCRADDTABLES, &io);
109 }
110 
111 ATF_TC_CLEANUP(addtables, tc)
112 {
113 	COMMON_CLEANUP();
114 }
115 
116 ATF_TC_WITH_CLEANUP(deltables);
117 ATF_TC_HEAD(deltables, tc)
118 {
119 	atf_tc_set_md_var(tc, "require.user", "root");
120 }
121 
122 ATF_TC_BODY(deltables, tc)
123 {
124 	struct pfioc_table io;
125 	struct pfr_table tbl;
126 	int flags;
127 
128 	COMMON_HEAD();
129 
130 	flags = 0;
131 
132 	bzero(&io, sizeof(io));
133 	io.pfrio_flags = flags;
134 	io.pfrio_buffer = &tbl;
135 	io.pfrio_esize = sizeof(tbl);
136 
137 	/* Negative size */
138 	io.pfrio_size = -1;
139 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
140 		atf_tc_fail("Request with size -1 succeeded");
141 
142 	/* Overly large size */
143 	io.pfrio_size = 1 << 24;
144 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
145 		atf_tc_fail("Request with size 1 << 24 succeeded");
146 
147 	/* NULL buffer */
148 	io.pfrio_size = 1;
149 	io.pfrio_buffer = NULL;
150 	if (ioctl(dev, DIOCRDELTABLES, &io) == 0)
151 		atf_tc_fail("Request with NULL buffer succeeded");
152 }
153 
154 ATF_TC_CLEANUP(deltables, tc)
155 {
156 	COMMON_CLEANUP();
157 }
158 
159 ATF_TC_WITH_CLEANUP(gettables);
160 ATF_TC_HEAD(gettables, tc)
161 {
162 	atf_tc_set_md_var(tc, "require.user", "root");
163 }
164 
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 
192 ATF_TC_CLEANUP(gettables, tc)
193 {
194 	COMMON_CLEANUP();
195 }
196 
197 ATF_TC_WITH_CLEANUP(gettstats);
198 ATF_TC_HEAD(gettstats, tc)
199 {
200 	atf_tc_set_md_var(tc, "require.user", "root");
201 }
202 
203 ATF_TC_BODY(gettstats, tc)
204 {
205 	struct pfioc_table io;
206 	struct pfr_tstats stats;
207 	int flags;
208 
209 	COMMON_HEAD();
210 
211 	flags = 0;
212 
213 	bzero(&io, sizeof(io));
214 	io.pfrio_flags = flags;
215 	io.pfrio_buffer = &stats;
216 	io.pfrio_esize = sizeof(stats);
217 
218 	/* Negative size. This will succeed, because the kernel will not copy
219 	 * tables than it has. */
220 	io.pfrio_size = -1;
221 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
222 		atf_tc_fail("Request with size -1 failed");
223 
224 	/* Overly large size. See above. */
225 	io.pfrio_size = 1 << 24;
226 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
227 		atf_tc_fail("Request with size 1 << 24 failed");
228 }
229 
230 ATF_TC_CLEANUP(gettstats, tc)
231 {
232 	COMMON_CLEANUP();
233 }
234 
235 ATF_TC_WITH_CLEANUP(clrtstats);
236 ATF_TC_HEAD(clrtstats, tc)
237 {
238 	atf_tc_set_md_var(tc, "require.user", "root");
239 }
240 
241 ATF_TC_BODY(clrtstats, tc)
242 {
243 	struct pfioc_table io;
244 	struct pfr_table tbl;
245 	int flags;
246 
247 	COMMON_HEAD();
248 
249 	flags = 0;
250 
251 	common_init_tbl(&tbl);
252 
253 	bzero(&io, sizeof(io));
254 	io.pfrio_flags = flags;
255 	io.pfrio_buffer = &tbl;
256 	io.pfrio_esize = sizeof(tbl);
257 
258 	/* Negative size. This will succeed, because the kernel will not copy
259 	 * tables than it has. */
260 	io.pfrio_size = -1;
261 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
262 		atf_tc_fail("Request with size -1 failed ");
263 
264 	/* Overly large size. See above. */
265 	io.pfrio_size = 1 << 24;
266 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
267 		atf_tc_fail("Request with size 1 << 24 failed");
268 }
269 
270 ATF_TC_CLEANUP(clrtstats, tc)
271 {
272 	COMMON_CLEANUP();
273 }
274 
275 ATF_TC_WITH_CLEANUP(settflags);
276 ATF_TC_HEAD(settflags, tc)
277 {
278 	atf_tc_set_md_var(tc, "require.user", "root");
279 }
280 
281 ATF_TC_BODY(settflags, tc)
282 {
283 	struct pfioc_table io;
284 	struct pfr_table tbl;
285 	int flags;
286 
287 	COMMON_HEAD();
288 
289 	flags = 0;
290 
291 	common_init_tbl(&tbl);
292 
293 	bzero(&io, sizeof(io));
294 	io.pfrio_flags = flags;
295 	io.pfrio_buffer = &tbl;
296 	io.pfrio_esize = sizeof(tbl);
297 
298 	/* Negative size. This will succeed, because the kernel will not copy
299 	 * tables than it has. */
300 	io.pfrio_size = -1;
301 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
302 		atf_tc_fail("Request with size -1 failed");
303 
304 	/* Overly large size. See above. */
305 	io.pfrio_size = 1 << 28;
306 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
307 		atf_tc_fail("Request with size 1 << 24 failed");
308 
309 	/* NULL buffer */
310 	io.pfrio_buffer = NULL;
311 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != -1)
312 		atf_tc_fail("Request with NULL buffer succeeded");
313 }
314 
315 ATF_TC_CLEANUP(settflags, tc)
316 {
317 	COMMON_CLEANUP();
318 }
319 
320 ATF_TC_WITH_CLEANUP(addaddrs);
321 ATF_TC_HEAD(addaddrs, tc)
322 {
323 	atf_tc_set_md_var(tc, "require.user", "root");
324 }
325 
326 ATF_TC_BODY(addaddrs, tc)
327 {
328 	struct pfioc_table io;
329 	struct pfr_addr addr;
330 
331 	COMMON_HEAD();
332 
333 	bzero(&addr, sizeof(addr));
334 	bzero(&io, sizeof(io));
335 	io.pfrio_flags = 0;
336 	io.pfrio_buffer = &addr;
337 	io.pfrio_esize = sizeof(addr);
338 
339 	/* Negative size. */
340 	io.pfrio_size = -1;
341 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
342 		atf_tc_fail("Request with size -1 succeeded");
343 
344 	/* Overly large size. */
345 	io.pfrio_size = 1 << 28;
346 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
347 		atf_tc_fail("Reuqest with size 1 << 28 failed");
348 }
349 
350 ATF_TC_CLEANUP(addaddrs, tc)
351 {
352 	COMMON_CLEANUP();
353 }
354 
355 ATF_TC_WITH_CLEANUP(deladdrs);
356 ATF_TC_HEAD(deladdrs, tc)
357 {
358 	atf_tc_set_md_var(tc, "require.user", "root");
359 }
360 
361 ATF_TC_BODY(deladdrs, tc)
362 {
363 	struct pfioc_table io;
364 	struct pfr_addr addr;
365 
366 	COMMON_HEAD();
367 
368 	bzero(&addr, sizeof(addr));
369 	bzero(&io, sizeof(io));
370 	io.pfrio_flags = 0;
371 	io.pfrio_buffer = &addr;
372 	io.pfrio_esize = sizeof(addr);
373 
374 	/* Negative size. */
375 	io.pfrio_size = -1;
376 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
377 		atf_tc_fail("Request with size -1 succeeded");
378 
379 	/* Overly large size. */
380 	io.pfrio_size = 1 << 28;
381 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
382 		atf_tc_fail("Reuqest with size 1 << 28 failed");
383 }
384 
385 ATF_TC_CLEANUP(deladdrs, tc)
386 {
387 	COMMON_CLEANUP();
388 }
389 
390 ATF_TC_WITH_CLEANUP(setaddrs);
391 ATF_TC_HEAD(setaddrs, tc)
392 {
393 	atf_tc_set_md_var(tc, "require.user", "root");
394 }
395 
396 ATF_TC_BODY(setaddrs, tc)
397 {
398 	struct pfioc_table io;
399 	struct pfr_addr addr;
400 
401 	COMMON_HEAD();
402 
403 	bzero(&addr, sizeof(addr));
404 	bzero(&io, sizeof(io));
405 	io.pfrio_flags = 0;
406 	io.pfrio_buffer = &addr;
407 	io.pfrio_esize = sizeof(addr);
408 
409 	/* Negative size. */
410 	io.pfrio_size = -1;
411 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
412 		atf_tc_fail("Request with size -1 succeeded");
413 
414 	/* Overly large size. */
415 	io.pfrio_size = 1 << 28;
416 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
417 		atf_tc_fail("Reuqest with size 1 << 28 failed");
418 }
419 
420 ATF_TC_CLEANUP(setaddrs, tc)
421 {
422 	COMMON_CLEANUP();
423 }
424 
425 ATF_TC_WITH_CLEANUP(getaddrs);
426 ATF_TC_HEAD(getaddrs, tc)
427 {
428 	atf_tc_set_md_var(tc, "require.user", "root");
429 }
430 
431 ATF_TC_BODY(getaddrs, tc)
432 {
433 	struct pfioc_table io;
434 	struct pfr_addr addr;
435 
436 	COMMON_HEAD();
437 
438 	bzero(&addr, sizeof(addr));
439 	bzero(&io, sizeof(io));
440 	io.pfrio_flags = 0;
441 	io.pfrio_buffer = &addr;
442 	io.pfrio_esize = sizeof(addr);
443 
444 	common_init_tbl(&io.pfrio_table);
445 
446 	/* Negative size. */
447 	io.pfrio_size = -1;
448 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
449 		atf_tc_fail("Request with size -1 succeeded");
450 
451 	/* Overly large size. */
452 	io.pfrio_size = 1 << 24;
453 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
454 		atf_tc_fail("Request with size 1 << 24 failed");
455 }
456 
457 ATF_TC_CLEANUP(getaddrs, tc)
458 {
459 	COMMON_CLEANUP();
460 }
461 
462 ATF_TC_WITH_CLEANUP(getastats);
463 ATF_TC_HEAD(getastats, tc)
464 {
465 	atf_tc_set_md_var(tc, "require.user", "root");
466 }
467 
468 ATF_TC_BODY(getastats, tc)
469 {
470 	struct pfioc_table io;
471 	struct pfr_astats astats;
472 
473 	COMMON_HEAD();
474 
475 	bzero(&astats, sizeof(astats));
476 	bzero(&io, sizeof(io));
477 	io.pfrio_flags = 0;
478 	io.pfrio_buffer = &astats;
479 	io.pfrio_esize = sizeof(astats);
480 
481 	common_init_tbl(&io.pfrio_table);
482 
483 	/* Negative size. */
484 	io.pfrio_size = -1;
485 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
486 		atf_tc_fail("Request with size -1 succeeded");
487 
488 	/* Overly large size. */
489 	io.pfrio_size = 1 << 24;
490 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
491 		atf_tc_fail("Request with size 1 << 24 failed");
492 }
493 
494 ATF_TC_CLEANUP(getastats, tc)
495 {
496 	COMMON_CLEANUP();
497 }
498 
499 ATF_TC_WITH_CLEANUP(clrastats);
500 ATF_TC_HEAD(clrastats, tc)
501 {
502 	atf_tc_set_md_var(tc, "require.user", "root");
503 }
504 
505 ATF_TC_BODY(clrastats, tc)
506 {
507 	struct pfioc_table io;
508 	struct pfr_addr addr;
509 
510 	COMMON_HEAD();
511 
512 	bzero(&addr, sizeof(addr));
513 	bzero(&io, sizeof(io));
514 	io.pfrio_flags = 0;
515 	io.pfrio_buffer = &addr;
516 	io.pfrio_esize = sizeof(addr);
517 
518 	common_init_tbl(&io.pfrio_table);
519 
520 	/* Negative size. */
521 	io.pfrio_size = -1;
522 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
523 		atf_tc_fail("Request with size -1 succeeded");
524 
525 	/* Overly large size. */
526 	io.pfrio_size = 1 << 24;
527 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
528 		atf_tc_fail("Request with size 1 << 24 failed");
529 }
530 
531 ATF_TC_CLEANUP(clrastats, tc)
532 {
533 	COMMON_CLEANUP();
534 }
535 
536 ATF_TC_WITH_CLEANUP(tstaddrs);
537 ATF_TC_HEAD(tstaddrs, tc)
538 {
539 	atf_tc_set_md_var(tc, "require.user", "root");
540 }
541 
542 ATF_TC_BODY(tstaddrs, tc)
543 {
544 	struct pfioc_table io;
545 	struct pfr_addr addr;
546 
547 	COMMON_HEAD();
548 
549 	bzero(&addr, sizeof(addr));
550 	bzero(&io, sizeof(io));
551 	io.pfrio_flags = 0;
552 	io.pfrio_buffer = &addr;
553 	io.pfrio_esize = sizeof(addr);
554 
555 	common_init_tbl(&io.pfrio_table);
556 
557 	/* Negative size. */
558 	io.pfrio_size = -1;
559 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
560 		atf_tc_fail("Request with size -1 succeeded");
561 
562 	/* Overly large size. */
563 	io.pfrio_size = 1 << 24;
564 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
565 		atf_tc_fail("Request with size 1 << 24 failed");
566 }
567 
568 ATF_TC_CLEANUP(tstaddrs, tc)
569 {
570 	COMMON_CLEANUP();
571 }
572 
573 ATF_TC_WITH_CLEANUP(inadefine);
574 ATF_TC_HEAD(inadefine, tc)
575 {
576 	atf_tc_set_md_var(tc, "require.user", "root");
577 }
578 
579 ATF_TC_BODY(inadefine, tc)
580 {
581 	struct pfioc_table io;
582 	struct pfr_addr addr;
583 
584 	COMMON_HEAD();
585 
586 	bzero(&addr, sizeof(addr));
587 	bzero(&io, sizeof(io));
588 	io.pfrio_flags = 0;
589 	io.pfrio_buffer = &addr;
590 	io.pfrio_esize = sizeof(addr);
591 
592 	common_init_tbl(&io.pfrio_table);
593 
594 	/* Negative size. */
595 	io.pfrio_size = -1;
596 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
597 		atf_tc_fail("Request with size -1 succeeded");
598 
599 	/* Overly large size. */
600 	io.pfrio_size = 1 << 24;
601 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
602 		atf_tc_fail("Request with size 1 << 24 failed");
603 }
604 
605 ATF_TC_CLEANUP(inadefine, tc)
606 {
607 	COMMON_CLEANUP();
608 }
609 
610 ATF_TC_WITH_CLEANUP(igetifaces);
611 ATF_TC_HEAD(igetifaces, tc)
612 {
613 	atf_tc_set_md_var(tc, "require.user", "root");
614 }
615 
616 ATF_TC_BODY(igetifaces, tc)
617 {
618 	struct pfioc_iface io;
619 	struct pfi_kif kif;
620 
621 	COMMON_HEAD();
622 
623 	bzero(&io, sizeof(io));
624 	io.pfiio_flags = 0;
625 	io.pfiio_buffer = &kif;
626 	io.pfiio_esize = sizeof(kif);
627 
628 	/* Negative size */
629 	io.pfiio_size = -1;
630 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
631 		atf_tc_fail("request with size -1 succeeded");
632 
633 	/* Overflow size */
634 	io.pfiio_size = 1 << 31;
635 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
636 		atf_tc_fail("request with size 1 << 31 succeeded");
637 }
638 
639 ATF_TC_CLEANUP(igetifaces, tc)
640 {
641 	COMMON_CLEANUP();
642 }
643 
644 ATF_TC_WITH_CLEANUP(cxbegin);
645 ATF_TC_HEAD(cxbegin, tc)
646 {
647 	atf_tc_set_md_var(tc, "require.user", "root");
648 }
649 
650 ATF_TC_BODY(cxbegin, tc)
651 {
652 	struct pfioc_trans io;
653 	struct pfioc_trans_e ioe;
654 
655 	COMMON_HEAD();
656 
657 	bzero(&io, sizeof(io));
658 	io.esize = sizeof(ioe);
659 	io.array = &ioe;
660 
661 	/* Negative size */
662 	io.size = -1;
663 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
664 		atf_tc_fail("request with size -1 succeeded");
665 
666 	/* Overflow size */
667 	io.size = 1 << 30;
668 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
669 		atf_tc_fail("request with size 1 << 30 succeeded");
670 
671 	/* NULL buffer */
672 	io.size = 1;
673 	io.array = NULL;
674 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
675 		atf_tc_fail("request with size -1 succeeded");
676 }
677 
678 ATF_TC_CLEANUP(cxbegin, tc)
679 {
680 	COMMON_CLEANUP();
681 }
682 
683 ATF_TC_WITH_CLEANUP(cxrollback);
684 ATF_TC_HEAD(cxrollback, tc)
685 {
686 	atf_tc_set_md_var(tc, "require.user", "root");
687 }
688 
689 ATF_TC_BODY(cxrollback, tc)
690 {
691 	struct pfioc_trans io;
692 	struct pfioc_trans_e ioe;
693 
694 	COMMON_HEAD();
695 
696 	bzero(&io, sizeof(io));
697 	io.esize = sizeof(ioe);
698 	io.array = &ioe;
699 
700 	/* Negative size */
701 	io.size = -1;
702 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
703 		atf_tc_fail("request with size -1 succeeded");
704 
705 	/* Overflow size */
706 	io.size = 1 << 30;
707 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
708 		atf_tc_fail("request with size 1 << 30 succeeded");
709 
710 	/* NULL buffer */
711 	io.size = 1;
712 	io.array = NULL;
713 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
714 		atf_tc_fail("request with size -1 succeeded");
715 }
716 
717 ATF_TC_CLEANUP(cxrollback, tc)
718 {
719 	COMMON_CLEANUP();
720 }
721 
722 ATF_TC_WITH_CLEANUP(commit);
723 ATF_TC_HEAD(commit, tc)
724 {
725 	atf_tc_set_md_var(tc, "require.user", "root");
726 }
727 
728 ATF_TC_BODY(commit, tc)
729 {
730 	struct pfioc_trans io;
731 	struct pfioc_trans_e ioe;
732 
733 	COMMON_HEAD();
734 
735 	bzero(&io, sizeof(io));
736 	io.esize = sizeof(ioe);
737 	io.array = &ioe;
738 
739 	/* Negative size */
740 	io.size = -1;
741 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
742 		atf_tc_fail("request with size -1 succeeded");
743 
744 	/* Overflow size */
745 	io.size = 1 << 30;
746 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
747 		atf_tc_fail("request with size 1 << 30 succeeded");
748 
749 	/* NULL buffer */
750 	io.size = 1;
751 	io.array = NULL;
752 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
753 		atf_tc_fail("request with size -1 succeeded");
754 }
755 
756 ATF_TC_CLEANUP(commit, tc)
757 {
758 	COMMON_CLEANUP();
759 }
760 
761 ATF_TC_WITH_CLEANUP(getsrcnodes);
762 ATF_TC_HEAD(getsrcnodes, tc)
763 {
764 	atf_tc_set_md_var(tc, "require.user", "root");
765 }
766 
767 ATF_TC_BODY(getsrcnodes, tc)
768 {
769 	struct pfioc_src_nodes psn;
770 
771 	COMMON_HEAD();
772 
773 	bzero(&psn, sizeof(psn));
774 
775 	psn.psn_len = -1;
776 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
777 		atf_tc_fail("request with size -1 failed");
778 
779 	psn.psn_len = 1 << 30;
780 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
781 		atf_tc_fail("request with size << 30 failed");
782 
783 	psn.psn_len = 1 << 31;
784 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
785 		atf_tc_fail("request with size << 30 failed");
786 }
787 
788 ATF_TC_CLEANUP(getsrcnodes, tc)
789 {
790 	COMMON_CLEANUP();
791 }
792 
793 ATF_TP_ADD_TCS(tp)
794 {
795 	ATF_TP_ADD_TC(tp, addtables);
796 	ATF_TP_ADD_TC(tp, deltables);
797 	ATF_TP_ADD_TC(tp, gettables);
798 	ATF_TP_ADD_TC(tp, getastats);
799 	ATF_TP_ADD_TC(tp, gettstats);
800 	ATF_TP_ADD_TC(tp, clrtstats);
801 	ATF_TP_ADD_TC(tp, settflags);
802 	ATF_TP_ADD_TC(tp, addaddrs);
803 	ATF_TP_ADD_TC(tp, deladdrs);
804 	ATF_TP_ADD_TC(tp, setaddrs);
805 	ATF_TP_ADD_TC(tp, getaddrs);
806 	ATF_TP_ADD_TC(tp, clrastats);
807 	ATF_TP_ADD_TC(tp, tstaddrs);
808 	ATF_TP_ADD_TC(tp, inadefine);
809 	ATF_TP_ADD_TC(tp, igetifaces);
810 	ATF_TP_ADD_TC(tp, cxbegin);
811 	ATF_TP_ADD_TC(tp, cxrollback);
812 	ATF_TP_ADD_TC(tp, commit);
813 	ATF_TP_ADD_TC(tp, getsrcnodes);
814 
815 	return (atf_no_error());
816 }
817