xref: /freebsd/tests/sys/netpfil/pf/ioctl/validation.c (revision c444bfca0063d0820f3fc72cb429809f5f52a970)
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(gettstats);
ATF_TC_HEAD(gettstats,tc)198 ATF_TC_HEAD(gettstats, 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(gettstats,tc)204 ATF_TC_BODY(gettstats, tc)
205 {
206 	struct pfioc_table io;
207 	struct pfr_tstats stats;
208 	int flags;
209 
210 	COMMON_HEAD();
211 
212 	flags = 0;
213 
214 	bzero(&io, sizeof(io));
215 	io.pfrio_flags = flags;
216 	io.pfrio_buffer = &stats;
217 	io.pfrio_esize = sizeof(stats);
218 
219 	/* Negative size. This will succeed, because the kernel will not copy
220 	 * tables than it has. */
221 	io.pfrio_size = -1;
222 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
223 		atf_tc_fail("Request with size -1 failed");
224 
225 	/* Overly large size. See above. */
226 	io.pfrio_size = 1 << 24;
227 	if (ioctl(dev, DIOCRGETTSTATS, &io) != 0)
228 		atf_tc_fail("Request with size 1 << 24 failed");
229 }
230 
ATF_TC_CLEANUP(gettstats,tc)231 ATF_TC_CLEANUP(gettstats, tc)
232 {
233 	COMMON_CLEANUP();
234 }
235 
236 ATF_TC_WITH_CLEANUP(clrtstats);
ATF_TC_HEAD(clrtstats,tc)237 ATF_TC_HEAD(clrtstats, tc)
238 {
239 	atf_tc_set_md_var(tc, "require.user", "root");
240 	atf_tc_set_md_var(tc, "require.kmods", "pf");
241 }
242 
ATF_TC_BODY(clrtstats,tc)243 ATF_TC_BODY(clrtstats, tc)
244 {
245 	struct pfioc_table io;
246 	struct pfr_table tbl;
247 	int flags;
248 
249 	COMMON_HEAD();
250 
251 	flags = 0;
252 
253 	common_init_tbl(&tbl);
254 
255 	bzero(&io, sizeof(io));
256 	io.pfrio_flags = flags;
257 	io.pfrio_buffer = &tbl;
258 	io.pfrio_esize = sizeof(tbl);
259 
260 	/* Negative size. This will succeed, because the kernel will not copy
261 	 * tables than it has. */
262 	io.pfrio_size = -1;
263 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
264 		atf_tc_fail("Request with size -1 failed ");
265 
266 	/* Overly large size. See above. */
267 	io.pfrio_size = 1 << 24;
268 	if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0)
269 		atf_tc_fail("Request with size 1 << 24 failed");
270 
271 	io.pfrio_size = sizeof(tbl);
272 	io.pfrio_buffer = NULL;
273 	if (ioctl(dev, DIOCRCLRTSTATS, &io) == 0)
274 		atf_tc_fail("Request with NULL buffer succeeded");
275 }
276 
ATF_TC_CLEANUP(clrtstats,tc)277 ATF_TC_CLEANUP(clrtstats, tc)
278 {
279 	COMMON_CLEANUP();
280 }
281 
282 ATF_TC_WITH_CLEANUP(settflags);
ATF_TC_HEAD(settflags,tc)283 ATF_TC_HEAD(settflags, tc)
284 {
285 	atf_tc_set_md_var(tc, "require.user", "root");
286 	atf_tc_set_md_var(tc, "require.kmods", "pf");
287 }
288 
ATF_TC_BODY(settflags,tc)289 ATF_TC_BODY(settflags, tc)
290 {
291 	struct pfioc_table io;
292 	struct pfr_table tbl;
293 	int flags;
294 
295 	COMMON_HEAD();
296 
297 	flags = 0;
298 
299 	common_init_tbl(&tbl);
300 
301 	bzero(&io, sizeof(io));
302 	io.pfrio_flags = flags;
303 	io.pfrio_buffer = &tbl;
304 	io.pfrio_esize = sizeof(tbl);
305 
306 	/* Negative size. This will succeed, because the kernel will not copy
307 	 * tables than it has. */
308 	io.pfrio_size = -1;
309 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
310 		atf_tc_fail("Request with size -1 failed");
311 
312 	/* Overly large size. See above. */
313 	io.pfrio_size = 1 << 28;
314 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0)
315 		atf_tc_fail("Request with size 1 << 24 failed");
316 
317 	/* NULL buffer */
318 	io.pfrio_buffer = NULL;
319 	if (ioctl(dev, DIOCRSETTFLAGS, &io) != -1)
320 		atf_tc_fail("Request with NULL buffer succeeded");
321 }
322 
ATF_TC_CLEANUP(settflags,tc)323 ATF_TC_CLEANUP(settflags, tc)
324 {
325 	COMMON_CLEANUP();
326 }
327 
328 ATF_TC_WITH_CLEANUP(addaddrs);
ATF_TC_HEAD(addaddrs,tc)329 ATF_TC_HEAD(addaddrs, tc)
330 {
331 	atf_tc_set_md_var(tc, "require.user", "root");
332 	atf_tc_set_md_var(tc, "require.kmods", "pf");
333 }
334 
ATF_TC_BODY(addaddrs,tc)335 ATF_TC_BODY(addaddrs, tc)
336 {
337 	struct pfioc_table io;
338 	struct pfr_addr addr;
339 
340 	COMMON_HEAD();
341 
342 	bzero(&addr, sizeof(addr));
343 	bzero(&io, sizeof(io));
344 	io.pfrio_flags = 0;
345 	io.pfrio_buffer = &addr;
346 	io.pfrio_esize = sizeof(addr);
347 
348 	/* Negative size. */
349 	io.pfrio_size = -1;
350 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
351 		atf_tc_fail("Request with size -1 succeeded");
352 
353 	/* Overly large size. */
354 	io.pfrio_size = 1 << 28;
355 	if (ioctl(dev, DIOCRADDADDRS, &io) == 0)
356 		atf_tc_fail("Reuqest with size 1 << 28 failed");
357 }
358 
ATF_TC_CLEANUP(addaddrs,tc)359 ATF_TC_CLEANUP(addaddrs, tc)
360 {
361 	COMMON_CLEANUP();
362 }
363 
364 ATF_TC_WITH_CLEANUP(deladdrs);
ATF_TC_HEAD(deladdrs,tc)365 ATF_TC_HEAD(deladdrs, tc)
366 {
367 	atf_tc_set_md_var(tc, "require.user", "root");
368 	atf_tc_set_md_var(tc, "require.kmods", "pf");
369 }
370 
ATF_TC_BODY(deladdrs,tc)371 ATF_TC_BODY(deladdrs, tc)
372 {
373 	struct pfioc_table io;
374 	struct pfr_addr addr;
375 
376 	COMMON_HEAD();
377 
378 	bzero(&addr, sizeof(addr));
379 	bzero(&io, sizeof(io));
380 	io.pfrio_flags = 0;
381 	io.pfrio_buffer = &addr;
382 	io.pfrio_esize = sizeof(addr);
383 
384 	/* Negative size. */
385 	io.pfrio_size = -1;
386 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
387 		atf_tc_fail("Request with size -1 succeeded");
388 
389 	/* Overly large size. */
390 	io.pfrio_size = 1 << 28;
391 	if (ioctl(dev, DIOCRDELADDRS, &io) == 0)
392 		atf_tc_fail("Reuqest with size 1 << 28 failed");
393 }
394 
ATF_TC_CLEANUP(deladdrs,tc)395 ATF_TC_CLEANUP(deladdrs, tc)
396 {
397 	COMMON_CLEANUP();
398 }
399 
400 ATF_TC_WITH_CLEANUP(setaddrs);
ATF_TC_HEAD(setaddrs,tc)401 ATF_TC_HEAD(setaddrs, tc)
402 {
403 	atf_tc_set_md_var(tc, "require.user", "root");
404 	atf_tc_set_md_var(tc, "require.kmods", "pf");
405 }
406 
ATF_TC_BODY(setaddrs,tc)407 ATF_TC_BODY(setaddrs, tc)
408 {
409 	struct pfioc_table io;
410 	struct pfr_addr addr;
411 
412 	COMMON_HEAD();
413 
414 	bzero(&addr, sizeof(addr));
415 	bzero(&io, sizeof(io));
416 	io.pfrio_flags = 0;
417 	io.pfrio_buffer = &addr;
418 	io.pfrio_esize = sizeof(addr);
419 
420 	/* Negative size. */
421 	io.pfrio_size = -1;
422 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
423 		atf_tc_fail("Request with size -1 succeeded");
424 
425 	/* Overly large size. */
426 	io.pfrio_size = 1 << 28;
427 	if (ioctl(dev, DIOCRSETADDRS, &io) == 0)
428 		atf_tc_fail("Reuqest with size 1 << 28 failed");
429 }
430 
ATF_TC_CLEANUP(setaddrs,tc)431 ATF_TC_CLEANUP(setaddrs, tc)
432 {
433 	COMMON_CLEANUP();
434 }
435 
436 ATF_TC_WITH_CLEANUP(getaddrs);
ATF_TC_HEAD(getaddrs,tc)437 ATF_TC_HEAD(getaddrs, tc)
438 {
439 	atf_tc_set_md_var(tc, "require.user", "root");
440 	atf_tc_set_md_var(tc, "require.kmods", "pf");
441 }
442 
ATF_TC_BODY(getaddrs,tc)443 ATF_TC_BODY(getaddrs, tc)
444 {
445 	struct pfioc_table io;
446 	struct pfr_addr addr;
447 
448 	COMMON_HEAD();
449 
450 	bzero(&addr, sizeof(addr));
451 	bzero(&io, sizeof(io));
452 	io.pfrio_flags = 0;
453 	io.pfrio_buffer = &addr;
454 	io.pfrio_esize = sizeof(addr);
455 
456 	common_init_tbl(&io.pfrio_table);
457 
458 	/* Negative size. */
459 	io.pfrio_size = -1;
460 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
461 		atf_tc_fail("Request with size -1 succeeded");
462 
463 	/* Overly large size. */
464 	io.pfrio_size = 1 << 24;
465 	if (ioctl(dev, DIOCRGETADDRS, &io) == 0)
466 		atf_tc_fail("Request with size 1 << 24 failed");
467 }
468 
ATF_TC_CLEANUP(getaddrs,tc)469 ATF_TC_CLEANUP(getaddrs, tc)
470 {
471 	COMMON_CLEANUP();
472 }
473 
474 ATF_TC_WITH_CLEANUP(getastats);
ATF_TC_HEAD(getastats,tc)475 ATF_TC_HEAD(getastats, tc)
476 {
477 	atf_tc_set_md_var(tc, "require.user", "root");
478 	atf_tc_set_md_var(tc, "require.kmods", "pf");
479 }
480 
ATF_TC_BODY(getastats,tc)481 ATF_TC_BODY(getastats, tc)
482 {
483 	struct pfioc_table io;
484 	struct pfr_astats astats;
485 
486 	COMMON_HEAD();
487 
488 	bzero(&astats, sizeof(astats));
489 	bzero(&io, sizeof(io));
490 	io.pfrio_flags = 0;
491 	io.pfrio_buffer = &astats;
492 	io.pfrio_esize = sizeof(astats);
493 
494 	common_init_tbl(&io.pfrio_table);
495 
496 	/* Negative size. */
497 	io.pfrio_size = -1;
498 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
499 		atf_tc_fail("Request with size -1 succeeded");
500 
501 	/* Overly large size. */
502 	io.pfrio_size = 1 << 24;
503 	if (ioctl(dev, DIOCRGETASTATS, &io) == 0)
504 		atf_tc_fail("Request with size 1 << 24 failed");
505 }
506 
ATF_TC_CLEANUP(getastats,tc)507 ATF_TC_CLEANUP(getastats, tc)
508 {
509 	COMMON_CLEANUP();
510 }
511 
512 ATF_TC_WITH_CLEANUP(clrastats);
ATF_TC_HEAD(clrastats,tc)513 ATF_TC_HEAD(clrastats, tc)
514 {
515 	atf_tc_set_md_var(tc, "require.user", "root");
516 	atf_tc_set_md_var(tc, "require.kmods", "pf");
517 }
518 
ATF_TC_BODY(clrastats,tc)519 ATF_TC_BODY(clrastats, tc)
520 {
521 	struct pfioc_table io;
522 	struct pfr_addr addr;
523 
524 	COMMON_HEAD();
525 
526 	bzero(&addr, sizeof(addr));
527 	bzero(&io, sizeof(io));
528 	io.pfrio_flags = 0;
529 	io.pfrio_buffer = &addr;
530 	io.pfrio_esize = sizeof(addr);
531 
532 	common_init_tbl(&io.pfrio_table);
533 
534 	/* Negative size. */
535 	io.pfrio_size = -1;
536 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
537 		atf_tc_fail("Request with size -1 succeeded");
538 
539 	/* Overly large size. */
540 	io.pfrio_size = 1 << 24;
541 	if (ioctl(dev, DIOCRCLRASTATS, &io) == 0)
542 		atf_tc_fail("Request with size 1 << 24 failed");
543 }
544 
ATF_TC_CLEANUP(clrastats,tc)545 ATF_TC_CLEANUP(clrastats, tc)
546 {
547 	COMMON_CLEANUP();
548 }
549 
550 ATF_TC_WITH_CLEANUP(tstaddrs);
ATF_TC_HEAD(tstaddrs,tc)551 ATF_TC_HEAD(tstaddrs, tc)
552 {
553 	atf_tc_set_md_var(tc, "require.user", "root");
554 	atf_tc_set_md_var(tc, "require.kmods", "pf");
555 }
556 
ATF_TC_BODY(tstaddrs,tc)557 ATF_TC_BODY(tstaddrs, tc)
558 {
559 	struct pfioc_table io;
560 	struct pfr_addr addr;
561 
562 	COMMON_HEAD();
563 
564 	bzero(&addr, sizeof(addr));
565 	bzero(&io, sizeof(io));
566 	io.pfrio_flags = 0;
567 	io.pfrio_buffer = &addr;
568 	io.pfrio_esize = sizeof(addr);
569 
570 	common_init_tbl(&io.pfrio_table);
571 
572 	/* Negative size. */
573 	io.pfrio_size = -1;
574 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
575 		atf_tc_fail("Request with size -1 succeeded");
576 
577 	/* Overly large size. */
578 	io.pfrio_size = 1 << 24;
579 	if (ioctl(dev, DIOCRTSTADDRS, &io) == 0)
580 		atf_tc_fail("Request with size 1 << 24 failed");
581 }
582 
ATF_TC_CLEANUP(tstaddrs,tc)583 ATF_TC_CLEANUP(tstaddrs, tc)
584 {
585 	COMMON_CLEANUP();
586 }
587 
588 ATF_TC_WITH_CLEANUP(inadefine);
ATF_TC_HEAD(inadefine,tc)589 ATF_TC_HEAD(inadefine, tc)
590 {
591 	atf_tc_set_md_var(tc, "require.user", "root");
592 	atf_tc_set_md_var(tc, "require.kmods", "pf");
593 }
594 
ATF_TC_BODY(inadefine,tc)595 ATF_TC_BODY(inadefine, tc)
596 {
597 	struct pfioc_table io;
598 	struct pfr_addr addr;
599 
600 	COMMON_HEAD();
601 
602 	bzero(&addr, sizeof(addr));
603 	bzero(&io, sizeof(io));
604 	io.pfrio_flags = 0;
605 	io.pfrio_buffer = &addr;
606 	io.pfrio_esize = sizeof(addr);
607 
608 	common_init_tbl(&io.pfrio_table);
609 
610 	/* Negative size. */
611 	io.pfrio_size = -1;
612 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
613 		atf_tc_fail("Request with size -1 succeeded");
614 
615 	/* Overly large size. */
616 	io.pfrio_size = 1 << 24;
617 	if (ioctl(dev, DIOCRINADEFINE, &io) == 0)
618 		atf_tc_fail("Request with size 1 << 24 failed");
619 }
620 
ATF_TC_CLEANUP(inadefine,tc)621 ATF_TC_CLEANUP(inadefine, tc)
622 {
623 	COMMON_CLEANUP();
624 }
625 
626 ATF_TC_WITH_CLEANUP(igetifaces);
ATF_TC_HEAD(igetifaces,tc)627 ATF_TC_HEAD(igetifaces, tc)
628 {
629 	atf_tc_set_md_var(tc, "require.user", "root");
630 	atf_tc_set_md_var(tc, "require.kmods", "pf");
631 }
632 
ATF_TC_BODY(igetifaces,tc)633 ATF_TC_BODY(igetifaces, tc)
634 {
635 	struct pfioc_iface io;
636 	struct pfi_kif kif;
637 
638 	COMMON_HEAD();
639 
640 	bzero(&io, sizeof(io));
641 	io.pfiio_flags = 0;
642 	io.pfiio_buffer = &kif;
643 	io.pfiio_esize = sizeof(kif);
644 
645 	/* Negative size */
646 	io.pfiio_size = -1;
647 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
648 		atf_tc_fail("request with size -1 succeeded");
649 
650 	/* Overflow size */
651 	io.pfiio_size = 1 << 31;
652 	if (ioctl(dev, DIOCIGETIFACES, &io) == 0)
653 		atf_tc_fail("request with size 1 << 31 succeeded");
654 }
655 
ATF_TC_CLEANUP(igetifaces,tc)656 ATF_TC_CLEANUP(igetifaces, tc)
657 {
658 	COMMON_CLEANUP();
659 }
660 
661 ATF_TC_WITH_CLEANUP(cxbegin);
ATF_TC_HEAD(cxbegin,tc)662 ATF_TC_HEAD(cxbegin, tc)
663 {
664 	atf_tc_set_md_var(tc, "require.user", "root");
665 	atf_tc_set_md_var(tc, "require.kmods", "pf");
666 }
667 
ATF_TC_BODY(cxbegin,tc)668 ATF_TC_BODY(cxbegin, tc)
669 {
670 	struct pfioc_trans io;
671 	struct pfioc_trans_e ioe;
672 
673 	COMMON_HEAD();
674 
675 	bzero(&io, sizeof(io));
676 	io.esize = sizeof(ioe);
677 	io.array = &ioe;
678 
679 	/* Negative size */
680 	io.size = -1;
681 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
682 		atf_tc_fail("request with size -1 succeeded");
683 
684 	/* Overflow size */
685 	io.size = 1 << 30;
686 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
687 		atf_tc_fail("request with size 1 << 30 succeeded");
688 
689 	/* NULL buffer */
690 	io.size = 1;
691 	io.array = NULL;
692 	if (ioctl(dev, DIOCXBEGIN, &io) == 0)
693 		atf_tc_fail("request with size -1 succeeded");
694 }
695 
ATF_TC_CLEANUP(cxbegin,tc)696 ATF_TC_CLEANUP(cxbegin, tc)
697 {
698 	COMMON_CLEANUP();
699 }
700 
701 ATF_TC_WITH_CLEANUP(cxrollback);
ATF_TC_HEAD(cxrollback,tc)702 ATF_TC_HEAD(cxrollback, tc)
703 {
704 	atf_tc_set_md_var(tc, "require.user", "root");
705 	atf_tc_set_md_var(tc, "require.kmods", "pf");
706 }
707 
ATF_TC_BODY(cxrollback,tc)708 ATF_TC_BODY(cxrollback, tc)
709 {
710 	struct pfioc_trans io;
711 	struct pfioc_trans_e ioe;
712 
713 	COMMON_HEAD();
714 
715 	bzero(&io, sizeof(io));
716 	io.esize = sizeof(ioe);
717 	io.array = &ioe;
718 
719 	/* Negative size */
720 	io.size = -1;
721 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
722 		atf_tc_fail("request with size -1 succeeded");
723 
724 	/* Overflow size */
725 	io.size = 1 << 30;
726 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
727 		atf_tc_fail("request with size 1 << 30 succeeded");
728 
729 	/* NULL buffer */
730 	io.size = 1;
731 	io.array = NULL;
732 	if (ioctl(dev, DIOCXROLLBACK, &io) == 0)
733 		atf_tc_fail("request with size -1 succeeded");
734 }
735 
ATF_TC_CLEANUP(cxrollback,tc)736 ATF_TC_CLEANUP(cxrollback, tc)
737 {
738 	COMMON_CLEANUP();
739 }
740 
741 ATF_TC_WITH_CLEANUP(commit);
ATF_TC_HEAD(commit,tc)742 ATF_TC_HEAD(commit, tc)
743 {
744 	atf_tc_set_md_var(tc, "require.user", "root");
745 	atf_tc_set_md_var(tc, "require.kmods", "pf");
746 }
747 
ATF_TC_BODY(commit,tc)748 ATF_TC_BODY(commit, tc)
749 {
750 	struct pfioc_trans io;
751 	struct pfioc_trans_e ioe;
752 
753 	COMMON_HEAD();
754 
755 	bzero(&io, sizeof(io));
756 	io.esize = sizeof(ioe);
757 	io.array = &ioe;
758 
759 	/* Negative size */
760 	io.size = -1;
761 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
762 		atf_tc_fail("request with size -1 succeeded");
763 
764 	/* Overflow size */
765 	io.size = 1 << 30;
766 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
767 		atf_tc_fail("request with size 1 << 30 succeeded");
768 
769 	/* NULL buffer */
770 	io.size = 1;
771 	io.array = NULL;
772 	if (ioctl(dev, DIOCXCOMMIT, &io) == 0)
773 		atf_tc_fail("request with size -1 succeeded");
774 }
775 
ATF_TC_CLEANUP(commit,tc)776 ATF_TC_CLEANUP(commit, tc)
777 {
778 	COMMON_CLEANUP();
779 }
780 
781 ATF_TC_WITH_CLEANUP(getsrcnodes);
ATF_TC_HEAD(getsrcnodes,tc)782 ATF_TC_HEAD(getsrcnodes, tc)
783 {
784 	atf_tc_set_md_var(tc, "require.user", "root");
785 	atf_tc_set_md_var(tc, "require.kmods", "pf");
786 }
787 
ATF_TC_BODY(getsrcnodes,tc)788 ATF_TC_BODY(getsrcnodes, tc)
789 {
790 	struct pfioc_src_nodes psn;
791 
792 	COMMON_HEAD();
793 
794 	bzero(&psn, sizeof(psn));
795 
796 	psn.psn_len = -1;
797 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
798 		atf_tc_fail("request with size -1 failed");
799 
800 	psn.psn_len = 1 << 30;
801 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
802 		atf_tc_fail("request with size << 30 failed");
803 
804 	psn.psn_len = 1 << 31;
805 	if (ioctl(dev, DIOCGETSRCNODES, &psn) != 0)
806 		atf_tc_fail("request with size << 30 failed");
807 }
808 
ATF_TC_CLEANUP(getsrcnodes,tc)809 ATF_TC_CLEANUP(getsrcnodes, tc)
810 {
811 	COMMON_CLEANUP();
812 }
813 
814 ATF_TC_WITH_CLEANUP(tag);
ATF_TC_HEAD(tag,tc)815 ATF_TC_HEAD(tag, tc)
816 {
817 	atf_tc_set_md_var(tc, "require.user", "root");
818 	atf_tc_set_md_var(tc, "require.kmods", "pf");
819 }
820 
ATF_TC_BODY(tag,tc)821 ATF_TC_BODY(tag, tc)
822 {
823 	struct pfioc_rule rule;
824 
825 	COMMON_HEAD();
826 
827 	memset(&rule, 0x42, sizeof(rule));
828 
829 	rule.ticket = 0;
830 	rule.pool_ticket = 0;
831 	rule.anchor[0] = 0;
832 
833 	rule.rule.return_icmp = 0;
834 	bzero(&rule.rule.src, sizeof(rule.rule.src));
835 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
836 
837 	rule.rule.ifname[0] = 0;
838 	rule.rule.action = 0;
839 	rule.rule.rtableid = 0;
840 
841 	rule.rule.tagname[0] = 0;
842 
843 	for (int i = 0; i < 10; i++)
844 		ioctl(dev, DIOCADDRULE, &rule);
845 }
846 
ATF_TC_CLEANUP(tag,tc)847 ATF_TC_CLEANUP(tag, tc)
848 {
849 	COMMON_CLEANUP();
850 }
851 
852 ATF_TC_WITH_CLEANUP(rpool_mtx);
ATF_TC_HEAD(rpool_mtx,tc)853 ATF_TC_HEAD(rpool_mtx, tc)
854 {
855 	atf_tc_set_md_var(tc, "require.user", "root");
856 	atf_tc_set_md_var(tc, "require.kmods", "pf");
857 }
858 
ATF_TC_BODY(rpool_mtx,tc)859 ATF_TC_BODY(rpool_mtx, tc)
860 {
861 	struct pfioc_rule rule;
862 
863 	COMMON_HEAD();
864 
865 	memset(&rule, 0, sizeof(rule));
866 
867 	rule.ticket = 0;
868 	rule.pool_ticket = 0;
869 	rule.anchor[0] = 0;
870 
871 	rule.rule.return_icmp = 0;
872 	bzero(&rule.rule.src, sizeof(rule.rule.src));
873 	bzero(&rule.rule.dst, sizeof(rule.rule.dst));
874 
875 	rule.rule.ifname[0] = 0;
876 	rule.rule.action = 0;
877 	rule.rule.rtableid = 0;
878 
879 	rule.rule.tagname[0] = 0;
880 	rule.rule.action = 42;
881 
882 	ioctl(dev, DIOCADDRULE, &rule);
883 }
884 
ATF_TC_CLEANUP(rpool_mtx,tc)885 ATF_TC_CLEANUP(rpool_mtx, tc)
886 {
887 	COMMON_CLEANUP();
888 }
889 
890 ATF_TC_WITH_CLEANUP(rpool_mtx2);
ATF_TC_HEAD(rpool_mtx2,tc)891 ATF_TC_HEAD(rpool_mtx2, tc)
892 {
893 	atf_tc_set_md_var(tc, "require.user", "root");
894 	atf_tc_set_md_var(tc, "require.kmods", "pf");
895 }
896 
ATF_TC_BODY(rpool_mtx2,tc)897 ATF_TC_BODY(rpool_mtx2, tc)
898 {
899 	struct pfioc_rule rule;
900 
901 	COMMON_HEAD();
902 
903 	memset(&rule, 0, sizeof(rule));
904 
905 	rule.pool_ticket = 1000000;
906 	rule.action = PF_CHANGE_ADD_HEAD;
907 	rule.rule.af = AF_INET;
908 
909 	ioctl(dev, DIOCCHANGERULE, &rule);
910 }
911 
ATF_TC_CLEANUP(rpool_mtx2,tc)912 ATF_TC_CLEANUP(rpool_mtx2, tc)
913 {
914 	COMMON_CLEANUP();
915 }
916 
917 ATF_TC_WITH_CLEANUP(natlook);
ATF_TC_HEAD(natlook,tc)918 ATF_TC_HEAD(natlook, tc)
919 {
920 	atf_tc_set_md_var(tc, "require.user", "root");
921 	atf_tc_set_md_var(tc, "require.kmods", "pf");
922 }
923 
ATF_TC_BODY(natlook,tc)924 ATF_TC_BODY(natlook, tc)
925 {
926 	struct pfioc_natlook nl = { 0 };
927 
928 	COMMON_HEAD();
929 
930 	nl.af = AF_INET;
931 	nl.proto = IPPROTO_ICMP;
932 	nl.saddr.v4.s_addr = 0x01020304;
933 	nl.daddr.v4.s_addr = 0x05060708;
934 
935 	/* Invalid direction */
936 	nl.direction = 42;
937 
938 	ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCNATLOOK, &nl) == -1);
939 
940 	/* Invalid af */
941 	nl.direction = PF_IN;
942 	nl.af = 99;
943 
944 	ATF_CHECK_ERRNO(EAFNOSUPPORT, ioctl(dev, DIOCNATLOOK, &nl) == -1);
945 }
946 
ATF_TC_CLEANUP(natlook,tc)947 ATF_TC_CLEANUP(natlook, tc)
948 {
949 	COMMON_CLEANUP();
950 }
951 
ATF_TP_ADD_TCS(tp)952 ATF_TP_ADD_TCS(tp)
953 {
954 	ATF_TP_ADD_TC(tp, addtables);
955 	ATF_TP_ADD_TC(tp, deltables);
956 	ATF_TP_ADD_TC(tp, gettables);
957 	ATF_TP_ADD_TC(tp, getastats);
958 	ATF_TP_ADD_TC(tp, gettstats);
959 	ATF_TP_ADD_TC(tp, clrtstats);
960 	ATF_TP_ADD_TC(tp, settflags);
961 	ATF_TP_ADD_TC(tp, addaddrs);
962 	ATF_TP_ADD_TC(tp, deladdrs);
963 	ATF_TP_ADD_TC(tp, setaddrs);
964 	ATF_TP_ADD_TC(tp, getaddrs);
965 	ATF_TP_ADD_TC(tp, clrastats);
966 	ATF_TP_ADD_TC(tp, tstaddrs);
967 	ATF_TP_ADD_TC(tp, inadefine);
968 	ATF_TP_ADD_TC(tp, igetifaces);
969 	ATF_TP_ADD_TC(tp, cxbegin);
970 	ATF_TP_ADD_TC(tp, cxrollback);
971 	ATF_TP_ADD_TC(tp, commit);
972 	ATF_TP_ADD_TC(tp, getsrcnodes);
973 	ATF_TP_ADD_TC(tp, tag);
974 	ATF_TP_ADD_TC(tp, rpool_mtx);
975 	ATF_TP_ADD_TC(tp, rpool_mtx2);
976 	ATF_TP_ADD_TC(tp, natlook);
977 
978 	return (atf_no_error());
979 }
980