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 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_WITHOUT_HEAD(addtables); 65 ATF_TC_BODY(addtables, tc) 66 { 67 struct pfioc_table io; 68 struct pfr_table tbl; 69 struct pfr_table tbls[4]; 70 int flags; 71 72 COMMON_HEAD(); 73 74 flags = 0; 75 76 bzero(&io, sizeof(io)); 77 io.pfrio_flags = flags; 78 io.pfrio_buffer = &tbl; 79 io.pfrio_esize = sizeof(tbl); 80 81 /* Negative size */ 82 io.pfrio_size = -1; 83 if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 84 atf_tc_fail("Request with size -1 succeeded"); 85 86 /* Overly large size */ 87 io.pfrio_size = 1 << 24; 88 if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 89 atf_tc_fail("Request with size 1 << 24 succeeded"); 90 91 /* NULL buffer */ 92 io.pfrio_size = 1; 93 io.pfrio_buffer = NULL; 94 if (ioctl(dev, DIOCRADDTABLES, &io) == 0) 95 atf_tc_fail("Request with NULL buffer succeeded"); 96 97 /* This can provoke a memory leak, see r331225. */ 98 io.pfrio_size = 4; 99 for (int i = 0; i < io.pfrio_size; i++) 100 common_init_tbl(&tbls[i]); 101 102 io.pfrio_buffer = &tbls; 103 ioctl(dev, DIOCRADDTABLES, &io); 104 105 COMMON_CLEANUP(); 106 } 107 108 ATF_TC_WITHOUT_HEAD(deltables); 109 ATF_TC_BODY(deltables, tc) 110 { 111 struct pfioc_table io; 112 struct pfr_table tbl; 113 int flags; 114 115 COMMON_HEAD(); 116 117 flags = 0; 118 119 bzero(&io, sizeof(io)); 120 io.pfrio_flags = flags; 121 io.pfrio_buffer = &tbl; 122 io.pfrio_esize = sizeof(tbl); 123 124 /* Negative size */ 125 io.pfrio_size = -1; 126 if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 127 atf_tc_fail("Request with size -1 succeeded"); 128 129 /* Overly large size */ 130 io.pfrio_size = 1 << 24; 131 if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 132 atf_tc_fail("Request with size 1 << 24 succeeded"); 133 134 /* NULL buffer */ 135 io.pfrio_size = 1; 136 io.pfrio_buffer = NULL; 137 if (ioctl(dev, DIOCRDELTABLES, &io) == 0) 138 atf_tc_fail("Request with NULL buffer succeeded"); 139 140 COMMON_CLEANUP(); 141 } 142 143 ATF_TC_WITHOUT_HEAD(gettables); 144 ATF_TC_BODY(gettables, tc) 145 { 146 struct pfioc_table io; 147 struct pfr_table tbl; 148 int flags; 149 150 COMMON_HEAD(); 151 152 flags = 0; 153 154 bzero(&io, sizeof(io)); 155 io.pfrio_flags = flags; 156 io.pfrio_buffer = &tbl; 157 io.pfrio_esize = sizeof(tbl); 158 159 /* Negative size. This will succeed, because the kernel will not copy 160 * tables than it has. */ 161 io.pfrio_size = -1; 162 if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 163 atf_tc_fail("Request with size -1 failed"); 164 165 /* Overly large size. See above. */ 166 io.pfrio_size = 1 << 24; 167 if (ioctl(dev, DIOCRGETTABLES, &io) != 0) 168 atf_tc_fail("Request with size 1 << 24 failed"); 169 170 COMMON_CLEANUP(); 171 } 172 173 ATF_TC_WITHOUT_HEAD(gettstats); 174 ATF_TC_BODY(gettstats, tc) 175 { 176 struct pfioc_table io; 177 struct pfr_tstats stats; 178 int flags; 179 180 COMMON_HEAD(); 181 182 flags = 0; 183 184 bzero(&io, sizeof(io)); 185 io.pfrio_flags = flags; 186 io.pfrio_buffer = &stats; 187 io.pfrio_esize = sizeof(stats); 188 189 /* Negative size. This will succeed, because the kernel will not copy 190 * tables than it has. */ 191 io.pfrio_size = -1; 192 if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 193 atf_tc_fail("Request with size -1 failed"); 194 195 /* Overly large size. See above. */ 196 io.pfrio_size = 1 << 24; 197 if (ioctl(dev, DIOCRGETTSTATS, &io) != 0) 198 atf_tc_fail("Request with size 1 << 24 failed"); 199 200 COMMON_CLEANUP(); 201 } 202 203 ATF_TC_WITHOUT_HEAD(clrtstats); 204 ATF_TC_BODY(clrtstats, 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 common_init_tbl(&tbl); 215 216 bzero(&io, sizeof(io)); 217 io.pfrio_flags = flags; 218 io.pfrio_buffer = &tbl; 219 io.pfrio_esize = sizeof(tbl); 220 221 /* Negative size. This will succeed, because the kernel will not copy 222 * tables than it has. */ 223 io.pfrio_size = -1; 224 if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 225 atf_tc_fail("Request with size -1 failed "); 226 227 /* Overly large size. See above. */ 228 io.pfrio_size = 1 << 24; 229 if (ioctl(dev, DIOCRCLRTSTATS, &io) != 0) 230 atf_tc_fail("Request with size 1 << 24 failed"); 231 232 COMMON_CLEANUP(); 233 } 234 235 ATF_TC_WITHOUT_HEAD(settflags); 236 ATF_TC_BODY(settflags, tc) 237 { 238 struct pfioc_table io; 239 struct pfr_table tbl; 240 int flags; 241 242 COMMON_HEAD(); 243 244 flags = 0; 245 246 common_init_tbl(&tbl); 247 248 bzero(&io, sizeof(io)); 249 io.pfrio_flags = flags; 250 io.pfrio_buffer = &tbl; 251 io.pfrio_esize = sizeof(tbl); 252 253 /* Negative size. This will succeed, because the kernel will not copy 254 * tables than it has. */ 255 io.pfrio_size = -1; 256 if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 257 atf_tc_fail("Request with size -1 failed"); 258 259 /* Overly large size. See above. */ 260 io.pfrio_size = 1 << 28; 261 if (ioctl(dev, DIOCRSETTFLAGS, &io) != 0) 262 atf_tc_fail("Request with size 1 << 24 failed"); 263 264 COMMON_CLEANUP(); 265 } 266 267 ATF_TC_WITHOUT_HEAD(addaddrs); 268 ATF_TC_BODY(addaddrs, tc) 269 { 270 struct pfioc_table io; 271 struct pfr_addr addr; 272 273 COMMON_HEAD(); 274 275 bzero(&addr, sizeof(addr)); 276 bzero(&io, sizeof(io)); 277 io.pfrio_flags = 0; 278 io.pfrio_buffer = &addr; 279 io.pfrio_esize = sizeof(addr); 280 281 /* Negative size. */ 282 io.pfrio_size = -1; 283 if (ioctl(dev, DIOCRADDADDRS, &io) == 0) 284 atf_tc_fail("Request with size -1 succeeded"); 285 286 /* Overly large size. */ 287 io.pfrio_size = 1 << 28; 288 if (ioctl(dev, DIOCRADDADDRS, &io) == 0) 289 atf_tc_fail("Reuqest with size 1 << 28 failed"); 290 291 COMMON_CLEANUP(); 292 } 293 294 ATF_TC_WITHOUT_HEAD(deladdrs); 295 ATF_TC_BODY(deladdrs, tc) 296 { 297 struct pfioc_table io; 298 struct pfr_addr addr; 299 300 COMMON_HEAD(); 301 302 bzero(&addr, sizeof(addr)); 303 bzero(&io, sizeof(io)); 304 io.pfrio_flags = 0; 305 io.pfrio_buffer = &addr; 306 io.pfrio_esize = sizeof(addr); 307 308 /* Negative size. */ 309 io.pfrio_size = -1; 310 if (ioctl(dev, DIOCRDELADDRS, &io) == 0) 311 atf_tc_fail("Request with size -1 succeeded"); 312 313 /* Overly large size. */ 314 io.pfrio_size = 1 << 28; 315 if (ioctl(dev, DIOCRDELADDRS, &io) == 0) 316 atf_tc_fail("Reuqest with size 1 << 28 failed"); 317 318 COMMON_CLEANUP(); 319 } 320 321 ATF_TC_WITHOUT_HEAD(setaddrs); 322 ATF_TC_BODY(setaddrs, tc) 323 { 324 struct pfioc_table io; 325 struct pfr_addr addr; 326 327 COMMON_HEAD(); 328 329 bzero(&addr, sizeof(addr)); 330 bzero(&io, sizeof(io)); 331 io.pfrio_flags = 0; 332 io.pfrio_buffer = &addr; 333 io.pfrio_esize = sizeof(addr); 334 335 /* Negative size. */ 336 io.pfrio_size = -1; 337 if (ioctl(dev, DIOCRSETADDRS, &io) == 0) 338 atf_tc_fail("Request with size -1 succeeded"); 339 340 /* Overly large size. */ 341 io.pfrio_size = 1 << 28; 342 if (ioctl(dev, DIOCRSETADDRS, &io) == 0) 343 atf_tc_fail("Reuqest with size 1 << 28 failed"); 344 345 COMMON_CLEANUP(); 346 } 347 348 ATF_TC_WITHOUT_HEAD(getaddrs); 349 ATF_TC_BODY(getaddrs, tc) 350 { 351 struct pfioc_table io; 352 struct pfr_addr addr; 353 354 COMMON_HEAD(); 355 356 bzero(&addr, sizeof(addr)); 357 bzero(&io, sizeof(io)); 358 io.pfrio_flags = 0; 359 io.pfrio_buffer = &addr; 360 io.pfrio_esize = sizeof(addr); 361 362 common_init_tbl(&io.pfrio_table); 363 364 /* Negative size. */ 365 io.pfrio_size = -1; 366 if (ioctl(dev, DIOCRGETADDRS, &io) == 0) 367 atf_tc_fail("Request with size -1 succeeded"); 368 369 /* Overly large size. */ 370 io.pfrio_size = 1 << 24; 371 if (ioctl(dev, DIOCRGETADDRS, &io) == 0) 372 atf_tc_fail("Request with size 1 << 24 failed"); 373 374 COMMON_CLEANUP(); 375 } 376 377 ATF_TC_WITHOUT_HEAD(getastats); 378 ATF_TC_BODY(getastats, tc) 379 { 380 struct pfioc_table io; 381 struct pfr_astats astats; 382 383 COMMON_HEAD(); 384 385 bzero(&astats, sizeof(astats)); 386 bzero(&io, sizeof(io)); 387 io.pfrio_flags = 0; 388 io.pfrio_buffer = &astats; 389 io.pfrio_esize = sizeof(astats); 390 391 common_init_tbl(&io.pfrio_table); 392 393 /* Negative size. */ 394 io.pfrio_size = -1; 395 if (ioctl(dev, DIOCRGETASTATS, &io) == 0) 396 atf_tc_fail("Request with size -1 succeeded"); 397 398 /* Overly large size. */ 399 io.pfrio_size = 1 << 24; 400 if (ioctl(dev, DIOCRGETASTATS, &io) == 0) 401 atf_tc_fail("Request with size 1 << 24 failed"); 402 403 COMMON_CLEANUP(); 404 } 405 406 ATF_TC_WITHOUT_HEAD(clrastats); 407 ATF_TC_BODY(clrastats, 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 common_init_tbl(&io.pfrio_table); 421 422 /* Negative size. */ 423 io.pfrio_size = -1; 424 if (ioctl(dev, DIOCRCLRASTATS, &io) == 0) 425 atf_tc_fail("Request with size -1 succeeded"); 426 427 /* Overly large size. */ 428 io.pfrio_size = 1 << 24; 429 if (ioctl(dev, DIOCRCLRASTATS, &io) == 0) 430 atf_tc_fail("Request with size 1 << 24 failed"); 431 432 COMMON_CLEANUP(); 433 } 434 435 ATF_TC_WITHOUT_HEAD(tstaddrs); 436 ATF_TC_BODY(tstaddrs, tc) 437 { 438 struct pfioc_table io; 439 struct pfr_addr addr; 440 441 COMMON_HEAD(); 442 443 bzero(&addr, sizeof(addr)); 444 bzero(&io, sizeof(io)); 445 io.pfrio_flags = 0; 446 io.pfrio_buffer = &addr; 447 io.pfrio_esize = sizeof(addr); 448 449 common_init_tbl(&io.pfrio_table); 450 451 /* Negative size. */ 452 io.pfrio_size = -1; 453 if (ioctl(dev, DIOCRTSTADDRS, &io) == 0) 454 atf_tc_fail("Request with size -1 succeeded"); 455 456 /* Overly large size. */ 457 io.pfrio_size = 1 << 24; 458 if (ioctl(dev, DIOCRTSTADDRS, &io) == 0) 459 atf_tc_fail("Request with size 1 << 24 failed"); 460 461 COMMON_CLEANUP(); 462 } 463 464 ATF_TC_WITHOUT_HEAD(inadefine); 465 ATF_TC_BODY(inadefine, tc) 466 { 467 struct pfioc_table io; 468 struct pfr_addr addr; 469 470 COMMON_HEAD(); 471 472 bzero(&addr, sizeof(addr)); 473 bzero(&io, sizeof(io)); 474 io.pfrio_flags = 0; 475 io.pfrio_buffer = &addr; 476 io.pfrio_esize = sizeof(addr); 477 478 common_init_tbl(&io.pfrio_table); 479 480 /* Negative size. */ 481 io.pfrio_size = -1; 482 if (ioctl(dev, DIOCRINADEFINE, &io) == 0) 483 atf_tc_fail("Request with size -1 succeeded"); 484 485 /* Overly large size. */ 486 io.pfrio_size = 1 << 24; 487 if (ioctl(dev, DIOCRINADEFINE, &io) == 0) 488 atf_tc_fail("Request with size 1 << 24 failed"); 489 490 COMMON_CLEANUP(); 491 } 492 493 ATF_TC_WITHOUT_HEAD(igetifaces); 494 ATF_TC_BODY(igetifaces, tc) 495 { 496 struct pfioc_iface io; 497 struct pfi_kif kif; 498 499 COMMON_HEAD(); 500 501 bzero(&io, sizeof(io)); 502 io.pfiio_flags = 0; 503 io.pfiio_buffer = &kif; 504 io.pfiio_esize = sizeof(kif); 505 506 /* Negative size */ 507 io.pfiio_size = -1; 508 if (ioctl(dev, DIOCIGETIFACES, &io) == 0) 509 atf_tc_fail("request with size -1 succeeded"); 510 511 /* Overflow size */ 512 io.pfiio_size = 1 << 31; 513 if (ioctl(dev, DIOCIGETIFACES, &io) == 0) 514 atf_tc_fail("request with size 1 << 31 succeeded"); 515 516 COMMON_CLEANUP(); 517 } 518 519 ATF_TC_WITHOUT_HEAD(cxbegin); 520 ATF_TC_BODY(cxbegin, tc) 521 { 522 struct pfioc_trans io; 523 struct pfioc_trans_e ioe; 524 525 COMMON_HEAD(); 526 527 bzero(&io, sizeof(io)); 528 io.esize = sizeof(ioe); 529 io.array = &ioe; 530 531 /* Negative size */ 532 io.size = -1; 533 if (ioctl(dev, DIOCXBEGIN, &io) == 0) 534 atf_tc_fail("request with size -1 succeeded"); 535 536 /* Overflow size */ 537 io.size = 1 << 30; 538 if (ioctl(dev, DIOCXBEGIN, &io) == 0) 539 atf_tc_fail("request with size 1 << 30 succeeded"); 540 541 /* NULL buffer */ 542 io.size = 1; 543 io.array = NULL; 544 if (ioctl(dev, DIOCXBEGIN, &io) == 0) 545 atf_tc_fail("request with size -1 succeeded"); 546 547 COMMON_CLEANUP(); 548 } 549 550 ATF_TC_WITHOUT_HEAD(cxrollback); 551 ATF_TC_BODY(cxrollback, tc) 552 { 553 struct pfioc_trans io; 554 struct pfioc_trans_e ioe; 555 556 COMMON_HEAD(); 557 558 bzero(&io, sizeof(io)); 559 io.esize = sizeof(ioe); 560 io.array = &ioe; 561 562 /* Negative size */ 563 io.size = -1; 564 if (ioctl(dev, DIOCXROLLBACK, &io) == 0) 565 atf_tc_fail("request with size -1 succeeded"); 566 567 /* Overflow size */ 568 io.size = 1 << 30; 569 if (ioctl(dev, DIOCXROLLBACK, &io) == 0) 570 atf_tc_fail("request with size 1 << 30 succeeded"); 571 572 /* NULL buffer */ 573 io.size = 1; 574 io.array = NULL; 575 if (ioctl(dev, DIOCXROLLBACK, &io) == 0) 576 atf_tc_fail("request with size -1 succeeded"); 577 578 COMMON_CLEANUP(); 579 } 580 581 ATF_TC_WITHOUT_HEAD(commit); 582 ATF_TC_BODY(commit, tc) 583 { 584 struct pfioc_trans io; 585 struct pfioc_trans_e ioe; 586 587 COMMON_HEAD(); 588 589 bzero(&io, sizeof(io)); 590 io.esize = sizeof(ioe); 591 io.array = &ioe; 592 593 /* Negative size */ 594 io.size = -1; 595 if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 596 atf_tc_fail("request with size -1 succeeded"); 597 598 /* Overflow size */ 599 io.size = 1 << 30; 600 if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 601 atf_tc_fail("request with size 1 << 30 succeeded"); 602 603 /* NULL buffer */ 604 io.size = 1; 605 io.array = NULL; 606 if (ioctl(dev, DIOCXCOMMIT, &io) == 0) 607 atf_tc_fail("request with size -1 succeeded"); 608 609 COMMON_CLEANUP(); 610 } 611 612 ATF_TP_ADD_TCS(tp) 613 { 614 ATF_TP_ADD_TC(tp, addtables); 615 ATF_TP_ADD_TC(tp, deltables); 616 ATF_TP_ADD_TC(tp, gettables); 617 ATF_TP_ADD_TC(tp, gettstats); 618 ATF_TP_ADD_TC(tp, clrtstats); 619 ATF_TP_ADD_TC(tp, settflags); 620 ATF_TP_ADD_TC(tp, addaddrs); 621 ATF_TP_ADD_TC(tp, deladdrs); 622 ATF_TP_ADD_TC(tp, setaddrs); 623 ATF_TP_ADD_TC(tp, getaddrs); 624 ATF_TP_ADD_TC(tp, clrastats); 625 ATF_TP_ADD_TC(tp, tstaddrs); 626 ATF_TP_ADD_TC(tp, inadefine); 627 ATF_TP_ADD_TC(tp, igetifaces); 628 ATF_TP_ADD_TC(tp, cxbegin); 629 ATF_TP_ADD_TC(tp, cxrollback); 630 ATF_TP_ADD_TC(tp, commit); 631 632 return (atf_no_error()); 633 } 634