1 /*- 2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3 * Authors: Doug Rabson <dfr@rabson.org> 4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: src/tools/regression/file/flock/flock.c,v 1.3 2008/06/26 10:21:54 dfr Exp $ 28 */ 29 30 #include <sys/time.h> 31 #include <sys/stat.h> 32 33 #include <err.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <limits.h> 37 #include <signal.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "util.h" 44 45 int verbose = 0; 46 47 static void 48 ignore_alarm(int __unused sig) 49 { 50 } 51 52 static int 53 safe_kill(pid_t pid, int sig) 54 { 55 int save_errno; 56 int status; 57 58 save_errno = errno; 59 errno = 0; 60 status = kill(pid, sig); 61 errno = save_errno; 62 63 return (status); 64 } 65 66 /* 67 * Test 1 - F_GETLK on unlocked region 68 * 69 * If no lock is found that would prevent this lock from being 70 * created, the structure is left unchanged by this function call 71 * except for the lock type which is set to F_UNLCK. 72 */ 73 static int 74 test1(int fd) 75 { 76 struct flock fl1, fl2; 77 78 memset(&fl1, 1, sizeof(fl1)); 79 fl1.l_type = F_WRLCK; 80 fl1.l_whence = SEEK_SET; 81 fl2 = fl1; 82 83 if (fcntl(fd, F_GETLK, &fl1) < 0) 84 err(1, "F_GETLK"); 85 86 if (verbose) printf("1 - F_GETLK on unlocked region: "); 87 FAIL(fl1.l_start != fl2.l_start); 88 FAIL(fl1.l_len != fl2.l_len); 89 FAIL(fl1.l_pid != fl2.l_pid); 90 FAIL(fl1.l_type != F_UNLCK); 91 FAIL(fl1.l_whence != fl2.l_whence); 92 93 SUCCEED; 94 } 95 96 /* 97 * Test 2 - F_SETLK on locked region 98 * 99 * If a shared or exclusive lock cannot be set, fcntl returns 100 * immediately with EACCES or EAGAIN. 101 */ 102 static int 103 test2(int fd) 104 { 105 /* 106 * We create a child process to hold the lock which we will 107 * test. We use a pipe to communicate with the child. 108 */ 109 int pid; 110 int pfd[2]; 111 struct flock fl; 112 char ch; 113 int res; 114 115 if (pipe(pfd) < 0) 116 err(1, "pipe"); 117 118 fl.l_start = 0; 119 fl.l_len = 0; 120 fl.l_type = F_WRLCK; 121 fl.l_whence = SEEK_SET; 122 123 pid = fork(); 124 if (pid < 0) 125 err(1, "fork"); 126 127 if (pid == 0) { 128 /* 129 * We are the child. We set a write lock and then 130 * write one byte back to the parent to tell it. The 131 * parent will kill us when its done. 132 */ 133 if (fcntl(fd, F_SETLK, &fl) < 0) 134 err(1, "F_SETLK (child)"); 135 if (write(pfd[1], "a", 1) < 0) 136 err(1, "writing to pipe (child)"); 137 pause(); 138 exit(0); 139 } 140 141 /* 142 * Wait until the child has set its lock and then perform the 143 * test. 144 */ 145 if (read(pfd[0], &ch, 1) != 1) 146 err(1, "reading from pipe (child)"); 147 148 /* 149 * fcntl should return -1 with errno set to either EACCES or 150 * EAGAIN. 151 */ 152 if (verbose) printf("2 - F_SETLK on locked region: "); 153 res = fcntl(fd, F_SETLK, &fl); 154 safe_kill(pid, SIGTERM); 155 safe_waitpid(pid); 156 close(pfd[0]); 157 close(pfd[1]); 158 FAIL(res == 0); 159 FAIL(errno != EACCES && errno != EAGAIN); 160 161 SUCCEED; 162 } 163 164 /* 165 * Test 3 - F_SETLKW on locked region 166 * 167 * If a shared or exclusive lock is blocked by other locks, the 168 * process waits until the request can be satisfied. 169 * 170 * XXX this test hangs on FreeBSD NFS filesystems due to limitations 171 * in FreeBSD's client (and server) lockd implementation. 172 */ 173 static int 174 test3(int fd) 175 { 176 /* 177 * We create a child process to hold the lock which we will 178 * test. We use a pipe to communicate with the child. 179 */ 180 int pid; 181 int pfd[2]; 182 struct flock fl; 183 char ch; 184 int res; 185 186 if (pipe(pfd) < 0) 187 err(1, "pipe"); 188 189 fl.l_start = 0; 190 fl.l_len = 0; 191 fl.l_type = F_WRLCK; 192 fl.l_whence = SEEK_SET; 193 194 pid = fork(); 195 if (pid < 0) 196 err(1, "fork"); 197 198 if (pid == 0) { 199 /* 200 * We are the child. We set a write lock and then 201 * write one byte back to the parent to tell it. The 202 * parent will kill us when its done. 203 */ 204 if (fcntl(fd, F_SETLK, &fl) < 0) 205 err(1, "F_SETLK (child)"); 206 if (write(pfd[1], "a", 1) < 0) 207 err(1, "writing to pipe (child)"); 208 pause(); 209 exit(0); 210 } 211 212 /* 213 * Wait until the child has set its lock and then perform the 214 * test. 215 */ 216 if (read(pfd[0], &ch, 1) != 1) 217 err(1, "reading from pipe (child)"); 218 219 /* 220 * fcntl should wait until the alarm and then return -1 with 221 * errno set to EINTR. 222 */ 223 if (verbose) printf("3 - F_SETLKW on locked region: "); 224 225 alarm(1); 226 227 res = fcntl(fd, F_SETLKW, &fl); 228 safe_kill(pid, SIGTERM); 229 safe_waitpid(pid); 230 close(pfd[0]); 231 close(pfd[1]); 232 FAIL(res == 0); 233 FAIL(errno != EINTR); 234 235 SUCCEED; 236 } 237 238 /* 239 * Test 4 - F_GETLK on locked region 240 * 241 * Get the first lock that blocks the lock. 242 */ 243 static int 244 test4(int fd) 245 { 246 /* 247 * We create a child process to hold the lock which we will 248 * test. We use a pipe to communicate with the child. 249 */ 250 int pid; 251 int pfd[2]; 252 struct flock fl; 253 char ch; 254 255 if (pipe(pfd) < 0) 256 err(1, "pipe"); 257 258 fl.l_start = 0; 259 fl.l_len = 99; 260 fl.l_type = F_WRLCK; 261 fl.l_whence = SEEK_SET; 262 263 pid = fork(); 264 if (pid < 0) 265 err(1, "fork"); 266 267 if (pid == 0) { 268 /* 269 * We are the child. We set a write lock and then 270 * write one byte back to the parent to tell it. The 271 * parent will kill us when its done. 272 */ 273 if (fcntl(fd, F_SETLK, &fl) < 0) 274 err(1, "F_SETLK (child)"); 275 if (write(pfd[1], "a", 1) < 0) 276 err(1, "writing to pipe (child)"); 277 pause(); 278 exit(0); 279 } 280 281 /* 282 * Wait until the child has set its lock and then perform the 283 * test. 284 */ 285 if (read(pfd[0], &ch, 1) != 1) 286 err(1, "reading from pipe (child)"); 287 288 /* 289 * fcntl should return a lock structure reflecting the lock we 290 * made in the child process. 291 */ 292 if (fcntl(fd, F_GETLK, &fl) < 0) 293 err(1, "F_GETLK"); 294 295 if (verbose) printf("4 - F_GETLK on locked region: "); 296 FAIL(fl.l_start != 0); 297 FAIL(fl.l_len != 99); 298 FAIL(fl.l_type != F_WRLCK); 299 FAIL(fl.l_pid != pid); 300 301 safe_kill(pid, SIGTERM); 302 safe_waitpid(pid); 303 close(pfd[0]); 304 close(pfd[1]); 305 306 SUCCEED; 307 } 308 309 /* 310 * Test 5 - F_SETLKW simple deadlock 311 * 312 * If a blocking shared lock request would cause a deadlock (i.e. the 313 * lock request is blocked by a process which is itself blocked on a 314 * lock currently owned by the process making the new request), 315 * EDEADLK is returned. 316 */ 317 static int 318 test5(int fd) 319 { 320 /* 321 * We create a child process to hold the lock which we will 322 * test. Because our test relies on the child process being 323 * blocked on the parent's lock, we can't easily use a pipe to 324 * synchronize so we just sleep in the parent to given the 325 * child a chance to setup. 326 * 327 * To create the deadlock condition, we arrange for the parent 328 * to lock the first byte of the file and the child to lock 329 * the second byte. After locking the second byte, the child 330 * will attempt to lock the first byte of the file, and 331 * block. The parent will then attempt to lock the second byte 332 * (owned by the child) which should cause deadlock. 333 */ 334 int pid; 335 struct flock fl; 336 int res; 337 338 /* 339 * Lock the first byte in the parent. 340 */ 341 fl.l_start = 0; 342 fl.l_len = 1; 343 fl.l_type = F_WRLCK; 344 fl.l_whence = SEEK_SET; 345 if (fcntl(fd, F_SETLK, &fl) < 0) 346 err(1, "F_SETLK 1 (parent)"); 347 348 pid = fork(); 349 if (pid < 0) 350 err(1, "fork"); 351 352 if (pid == 0) { 353 /* 354 * Lock the second byte in the child and then block on 355 * the parent's lock. 356 */ 357 fl.l_start = 1; 358 if (fcntl(fd, F_SETLK, &fl) < 0) 359 err(1, "F_SETLK (child)"); 360 fl.l_start = 0; 361 if (fcntl(fd, F_SETLKW, &fl) < 0) 362 err(1, "F_SETLKW (child)"); 363 exit(0); 364 } 365 366 /* 367 * Wait until the child has set its lock and then perform the 368 * test. 369 */ 370 sleep(1); 371 372 /* 373 * fcntl should immediately return -1 with errno set to 374 * EDEADLK. If the alarm fires, we failed to detect the 375 * deadlock. 376 */ 377 alarm(1); 378 if (verbose) printf("5 - F_SETLKW simple deadlock: "); 379 380 fl.l_start = 1; 381 res = fcntl(fd, F_SETLKW, &fl); 382 safe_kill(pid, SIGTERM); 383 safe_waitpid(pid); 384 385 FAIL(res == 0); 386 FAIL(errno != EDEADLK); 387 388 fl.l_start = 0; 389 fl.l_len = 0; 390 fl.l_type = F_UNLCK; 391 if (fcntl(fd, F_SETLK, &fl) < 0) 392 err(1, "F_UNLCK"); 393 394 /* 395 * Cancel the alarm to avoid confusing later tests. 396 */ 397 alarm(0); 398 399 SUCCEED; 400 } 401 402 /* 403 * Test 6 - F_SETLKW complex deadlock. 404 * 405 * This test involves three process, P, C1 and C2. We set things up so 406 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We 407 * also block C2 by attempting to lock byte zero. Lastly, P attempts 408 * to lock a range including byte 1 and 2. This represents a deadlock 409 * (due to C2's blocking attempt to lock byte zero). 410 */ 411 static int 412 test6(int fd) 413 { 414 /* 415 * Because our test relies on the child process being blocked 416 * on the parent's lock, we can't easily use a pipe to 417 * synchronize so we just sleep in the parent to given the 418 * children a chance to setup. 419 */ 420 int pid1, pid2; 421 struct flock fl; 422 int res; 423 424 /* 425 * Lock the first byte in the parent. 426 */ 427 fl.l_start = 0; 428 fl.l_len = 1; 429 fl.l_type = F_WRLCK; 430 fl.l_whence = SEEK_SET; 431 if (fcntl(fd, F_SETLK, &fl) < 0) 432 err(1, "F_SETLK 1 (parent)"); 433 434 pid1 = fork(); 435 if (pid1 < 0) 436 err(1, "fork"); 437 438 if (pid1 == 0) { 439 /* 440 * C1 441 * Lock the second byte in the child and then sleep 442 */ 443 fl.l_start = 1; 444 if (fcntl(fd, F_SETLK, &fl) < 0) 445 err(1, "F_SETLK (child1)"); 446 pause(); 447 exit(0); 448 } 449 450 pid2 = fork(); 451 if (pid2 < 0) 452 err(1, "fork"); 453 454 if (pid2 == 0) { 455 /* 456 * C2 457 * Lock the third byte in the child and then block on 458 * the parent's lock. 459 */ 460 fl.l_start = 2; 461 if (fcntl(fd, F_SETLK, &fl) < 0) 462 err(1, "F_SETLK (child2)"); 463 fl.l_start = 0; 464 if (fcntl(fd, F_SETLKW, &fl) < 0) 465 err(1, "F_SETLKW (child2)"); 466 exit(0); 467 } 468 469 /* 470 * Wait until the children have set their locks and then 471 * perform the test. 472 */ 473 sleep(1); 474 475 /* 476 * fcntl should immediately return -1 with errno set to 477 * EDEADLK. If the alarm fires, we failed to detect the 478 * deadlock. 479 */ 480 alarm(1); 481 if (verbose) printf("6 - F_SETLKW complex deadlock: "); 482 483 fl.l_start = 1; 484 fl.l_len = 2; 485 res = fcntl(fd, F_SETLKW, &fl); 486 safe_kill(pid1, SIGTERM); 487 safe_waitpid(pid1); 488 safe_kill(pid2, SIGTERM); 489 safe_waitpid(pid2); 490 491 fl.l_start = 0; 492 fl.l_len = 0; 493 fl.l_type = F_UNLCK; 494 if (fcntl(fd, F_SETLK, &fl) < 0) 495 err(1, "F_UNLCK"); 496 497 FAIL(res == 0); 498 FAIL(errno != EDEADLK); 499 500 /* 501 * Cancel the alarm to avoid confusing later tests. 502 */ 503 alarm(0); 504 505 SUCCEED; 506 } 507 508 /* 509 * Test 7 - F_SETLK shared lock on exclusive locked region 510 * 511 * If a shared or exclusive lock cannot be set, fcntl returns 512 * immediately with EACCES or EAGAIN. 513 */ 514 static int 515 test7(int fd) 516 { 517 /* 518 * We create a child process to hold the lock which we will 519 * test. We use a pipe to communicate with the child. 520 */ 521 int pid; 522 int pfd[2]; 523 struct flock fl; 524 char ch; 525 int res; 526 527 if (pipe(pfd) < 0) 528 err(1, "pipe"); 529 530 fl.l_start = 0; 531 fl.l_len = 0; 532 fl.l_type = F_WRLCK; 533 fl.l_whence = SEEK_SET; 534 535 pid = fork(); 536 if (pid < 0) 537 err(1, "fork"); 538 539 if (pid == 0) { 540 /* 541 * We are the child. We set a write lock and then 542 * write one byte back to the parent to tell it. The 543 * parent will kill us when its done. 544 */ 545 if (fcntl(fd, F_SETLK, &fl) < 0) 546 err(1, "F_SETLK (child)"); 547 if (write(pfd[1], "a", 1) < 0) 548 err(1, "writing to pipe (child)"); 549 pause(); 550 exit(0); 551 } 552 553 /* 554 * Wait until the child has set its lock and then perform the 555 * test. 556 */ 557 if (read(pfd[0], &ch, 1) != 1) 558 err(1, "reading from pipe (child)"); 559 560 /* 561 * fcntl should wait until the alarm and then return -1 with 562 * errno set to EINTR. 563 */ 564 if (verbose) printf("7 - F_SETLK shared lock on exclusive locked region: "); 565 566 fl.l_type = F_RDLCK; 567 res = fcntl(fd, F_SETLK, &fl); 568 safe_kill(pid, SIGTERM); 569 safe_waitpid(pid); 570 close(pfd[0]); 571 close(pfd[1]); 572 573 FAIL(res == 0); 574 FAIL(errno != EACCES && errno != EAGAIN); 575 576 SUCCEED; 577 } 578 579 /* 580 * Test 8 - F_SETLK shared lock on share locked region 581 * 582 * When a shared lock is set on a segment of a file, other processes 583 * shall be able to set shared locks on that segment or a portion of 584 * it. 585 */ 586 static int 587 test8(int fd) 588 { 589 /* 590 * We create a child process to hold the lock which we will 591 * test. We use a pipe to communicate with the child. 592 */ 593 int pid; 594 int pfd[2]; 595 struct flock fl; 596 char ch; 597 int res; 598 599 if (pipe(pfd) < 0) 600 err(1, "pipe"); 601 602 fl.l_start = 0; 603 fl.l_len = 0; 604 fl.l_type = F_RDLCK; 605 fl.l_whence = SEEK_SET; 606 607 pid = fork(); 608 if (pid < 0) 609 err(1, "fork"); 610 611 if (pid == 0) { 612 /* 613 * We are the child. We set a write lock and then 614 * write one byte back to the parent to tell it. The 615 * parent will kill us when its done. 616 */ 617 if (fcntl(fd, F_SETLK, &fl) < 0) 618 err(1, "F_SETLK (child)"); 619 if (write(pfd[1], "a", 1) < 0) 620 err(1, "writing to pipe (child)"); 621 pause(); 622 exit(0); 623 } 624 625 /* 626 * Wait until the child has set its lock and then perform the 627 * test. 628 */ 629 if (read(pfd[0], &ch, 1) != 1) 630 err(1, "reading from pipe (child)"); 631 632 /* 633 * fcntl should wait until the alarm and then return -1 with 634 * errno set to EINTR. 635 */ 636 if (verbose) printf("8 - F_SETLK shared lock on share locked region: "); 637 638 fl.l_type = F_RDLCK; 639 res = fcntl(fd, F_SETLK, &fl); 640 641 safe_kill(pid, SIGTERM); 642 safe_waitpid(pid); 643 close(pfd[0]); 644 close(pfd[1]); 645 646 fl.l_start = 0; 647 fl.l_len = 0; 648 fl.l_type = F_UNLCK; 649 if (fcntl(fd, F_SETLK, &fl) < 0) 650 err(1, "F_UNLCK"); 651 652 FAIL(res != 0); 653 654 SUCCEED; 655 } 656 657 /* 658 * Test 9 - F_SETLK exclusive lock on share locked region 659 * 660 * If a shared or exclusive lock cannot be set, fcntl returns 661 * immediately with EACCES or EAGAIN. 662 */ 663 static int 664 test9(int fd) 665 { 666 /* 667 * We create a child process to hold the lock which we will 668 * test. We use a pipe to communicate with the child. 669 */ 670 int pid; 671 int pfd[2]; 672 struct flock fl; 673 char ch; 674 int res; 675 676 if (pipe(pfd) < 0) 677 err(1, "pipe"); 678 679 fl.l_start = 0; 680 fl.l_len = 0; 681 fl.l_type = F_RDLCK; 682 fl.l_whence = SEEK_SET; 683 684 pid = fork(); 685 if (pid < 0) 686 err(1, "fork"); 687 688 if (pid == 0) { 689 /* 690 * We are the child. We set a write lock and then 691 * write one byte back to the parent to tell it. The 692 * parent will kill us when its done. 693 */ 694 if (fcntl(fd, F_SETLK, &fl) < 0) 695 err(1, "F_SETLK (child)"); 696 if (write(pfd[1], "a", 1) < 0) 697 err(1, "writing to pipe (child)"); 698 pause(); 699 exit(0); 700 } 701 702 /* 703 * Wait until the child has set its lock and then perform the 704 * test. 705 */ 706 if (read(pfd[0], &ch, 1) != 1) 707 err(1, "reading from pipe (child)"); 708 709 /* 710 * fcntl should wait until the alarm and then return -1 with 711 * errno set to EINTR. 712 */ 713 if (verbose) printf("9 - F_SETLK exclusive lock on share locked region: "); 714 715 fl.l_type = F_WRLCK; 716 res = fcntl(fd, F_SETLK, &fl); 717 safe_kill(pid, SIGTERM); 718 safe_waitpid(pid); 719 close(pfd[0]); 720 close(pfd[1]); 721 722 FAIL(res == 0); 723 FAIL(errno != EACCES && errno != EAGAIN); 724 725 SUCCEED; 726 } 727 728 /* 729 * Test 10 - trying to set bogus pid or sysid values 730 * 731 * The l_pid and l_sysid fields are only used with F_GETLK to return 732 * the process ID of the process holding a blocking lock and the 733 * system ID of the system that owns that process 734 */ 735 static int 736 test10(int fd) 737 { 738 /* 739 * We create a child process to hold the lock which we will 740 * test. We use a pipe to communicate with the child. 741 */ 742 int pid; 743 int pfd[2]; 744 struct flock fl; 745 char ch; 746 747 if (pipe(pfd) < 0) 748 err(1, "pipe"); 749 750 fl.l_start = 0; 751 fl.l_len = 0; 752 fl.l_type = F_WRLCK; 753 fl.l_whence = SEEK_SET; 754 fl.l_pid = 9999; 755 756 pid = fork(); 757 if (pid < 0) 758 err(1, "fork"); 759 760 if (pid == 0) { 761 /* 762 * We are the child. We set a write lock and then 763 * write one byte back to the parent to tell it. The 764 * parent will kill us when its done. 765 */ 766 if (fcntl(fd, F_SETLK, &fl) < 0) 767 err(1, "F_SETLK (child)"); 768 if (write(pfd[1], "a", 1) < 0) 769 err(1, "writing to pipe (child)"); 770 pause(); 771 exit(0); 772 } 773 774 /* 775 * Wait until the child has set its lock and then perform the 776 * test. 777 */ 778 if (read(pfd[0], &ch, 1) != 1) 779 err(1, "reading from pipe (child)"); 780 781 if (verbose) printf("10 - trying to set bogus pid or sysid values: "); 782 783 if (fcntl(fd, F_GETLK, &fl) < 0) 784 err(1, "F_GETLK"); 785 786 safe_kill(pid, SIGTERM); 787 safe_waitpid(pid); 788 close(pfd[0]); 789 close(pfd[1]); 790 791 FAIL(fl.l_pid != pid); 792 793 SUCCEED; 794 } 795 796 /* 797 * Test 11 - remote locks 798 * 799 * XXX temporary interface which will be removed when the kernel lockd 800 * is added. 801 */ 802 static int 803 test11(int fd) 804 { 805 #ifdef F_SETLK_REMOTE 806 struct flock fl; 807 int res; 808 809 if (geteuid() != 0) 810 return 0; 811 812 fl.l_start = 0; 813 fl.l_len = 0; 814 fl.l_type = F_WRLCK; 815 fl.l_whence = SEEK_SET; 816 fl.l_pid = 9999; 817 fl.l_sysid = 1001; 818 819 if (verbose) printf("11 - remote locks: "); 820 821 res = fcntl(fd, F_SETLK_REMOTE, &fl); 822 FAIL(res != 0); 823 824 fl.l_sysid = 1002; 825 res = fcntl(fd, F_SETLK_REMOTE, &fl); 826 FAIL(res == 0); 827 FAIL(errno != EACCES && errno != EAGAIN); 828 829 res = fcntl(fd, F_GETLK, &fl); 830 FAIL(res != 0); 831 FAIL(fl.l_pid != 9999); 832 FAIL(fl.l_sysid != 1001); 833 834 fl.l_type = F_UNLCK; 835 fl.l_sysid = 1001; 836 fl.l_start = 0; 837 fl.l_len = 0; 838 res = fcntl(fd, F_SETLK_REMOTE, &fl); 839 FAIL(res != 0); 840 841 fl.l_pid = 1234; 842 fl.l_sysid = 1001; 843 fl.l_start = 0; 844 fl.l_len = 1; 845 fl.l_whence = SEEK_SET; 846 fl.l_type = F_RDLCK; 847 res = fcntl(fd, F_SETLK_REMOTE, &fl); 848 FAIL(res != 0); 849 850 fl.l_sysid = 1002; 851 res = fcntl(fd, F_SETLK_REMOTE, &fl); 852 FAIL(res != 0); 853 854 fl.l_type = F_UNLCKSYS; 855 fl.l_sysid = 1001; 856 res = fcntl(fd, F_SETLK_REMOTE, &fl); 857 FAIL(res != 0); 858 859 fl.l_type = F_WRLCK; 860 res = fcntl(fd, F_GETLK, &fl); 861 FAIL(res != 0); 862 FAIL(fl.l_pid != 1234); 863 FAIL(fl.l_sysid != 1002); 864 865 fl.l_type = F_UNLCKSYS; 866 fl.l_sysid = 1002; 867 res = fcntl(fd, F_SETLK_REMOTE, &fl); 868 FAIL(res != 0); 869 870 SUCCEED; 871 #else 872 return 0; 873 #endif 874 } 875 876 /* 877 * Test 12 - F_SETLKW on locked region which is then unlocked 878 * 879 * If a shared or exclusive lock is blocked by other locks, the 880 * process waits until the request can be satisfied. 881 */ 882 static int 883 test12(int fd) 884 { 885 /* 886 * We create a child process to hold the lock which we will 887 * test. We use a pipe to communicate with the child. 888 */ 889 int pid; 890 int pfd[2]; 891 struct flock fl; 892 char ch; 893 int res; 894 895 if (pipe(pfd) < 0) 896 err(1, "pipe"); 897 898 fl.l_start = 0; 899 fl.l_len = 0; 900 fl.l_type = F_WRLCK; 901 fl.l_whence = SEEK_SET; 902 903 pid = fork(); 904 if (pid < 0) 905 err(1, "fork"); 906 907 if (pid == 0) { 908 /* 909 * We are the child. We set a write lock and then 910 * write one byte back to the parent to tell it. The 911 * parent will kill us when its done. 912 */ 913 if (fcntl(fd, F_SETLK, &fl) < 0) 914 err(1, "F_SETLK (child)"); 915 if (write(pfd[1], "a", 1) < 0) 916 err(1, "writing to pipe (child)"); 917 918 sleep(1); 919 exit(0); 920 } 921 922 /* 923 * Wait until the child has set its lock and then perform the 924 * test. 925 */ 926 if (read(pfd[0], &ch, 1) != 1) 927 err(1, "reading from pipe (child)"); 928 929 /* 930 * fcntl should wait until the alarm and then return -1 with 931 * errno set to EINTR. 932 */ 933 if (verbose) printf("12 - F_SETLKW on locked region which is then unlocked: "); 934 935 //alarm(1); 936 937 res = fcntl(fd, F_SETLKW, &fl); 938 safe_kill(pid, SIGTERM); 939 safe_waitpid(pid); 940 close(pfd[0]); 941 close(pfd[1]); 942 FAIL(res != 0); 943 944 fl.l_start = 0; 945 fl.l_len = 0; 946 fl.l_type = F_UNLCK; 947 if (fcntl(fd, F_SETLK, &fl) < 0) 948 err(1, "F_UNLCK"); 949 950 SUCCEED; 951 } 952 953 /* 954 * Test 13 - F_SETLKW on locked region, race with owner 955 * 956 * If a shared or exclusive lock is blocked by other locks, the 957 * process waits until the request can be satisfied. 958 */ 959 static int 960 test13(int fd) 961 { 962 /* 963 * We create a child process to hold the lock which we will 964 * test. We use a pipe to communicate with the child. 965 */ 966 int i; 967 int pid; 968 int pfd[2]; 969 struct flock fl; 970 char ch; 971 int res; 972 struct itimerval itv; 973 974 if (verbose) printf("13 - F_SETLKW on locked region, race with owner: "); 975 fflush(stdout); 976 977 for (i = 0; i < 100; i++) { 978 if (pipe(pfd) < 0) 979 err(1, "pipe"); 980 981 fl.l_start = 0; 982 fl.l_len = 0; 983 fl.l_type = F_WRLCK; 984 fl.l_whence = SEEK_SET; 985 986 pid = fork(); 987 if (pid < 0) 988 err(1, "fork"); 989 990 if (pid == 0) { 991 /* 992 * We are the child. We set a write lock and then 993 * write one byte back to the parent to tell it. The 994 * parent will kill us when its done. 995 */ 996 if (fcntl(fd, F_SETLK, &fl) < 0) 997 err(1, "F_SETLK (child)"); 998 if (write(pfd[1], "a", 1) < 0) 999 err(1, "writing to pipe (child)"); 1000 1001 sleep(1); 1002 exit(0); 1003 } 1004 1005 /* 1006 * Wait until the child has set its lock and then perform the 1007 * test. 1008 */ 1009 while (read(pfd[0], &ch, 1) != 1) { 1010 if (errno == EINTR) 1011 continue; 1012 err(1, "reading from pipe (child)"); 1013 } 1014 1015 /* 1016 * fcntl should wait until the alarm and then return -1 with 1017 * errno set to EINTR. 1018 */ 1019 itv.it_interval.tv_sec = 0; 1020 itv.it_interval.tv_usec = 0; 1021 itv.it_value.tv_sec = 0; 1022 itv.it_value.tv_usec = 2; 1023 setitimer(ITIMER_REAL, &itv, NULL); 1024 1025 res = fcntl(fd, F_SETLKW, &fl); 1026 safe_kill(pid, SIGTERM); 1027 safe_waitpid(pid); 1028 close(pfd[0]); 1029 close(pfd[1]); 1030 FAIL(!(res == 0 || (res == -1 && errno == EINTR))); 1031 1032 fl.l_start = 0; 1033 fl.l_len = 0; 1034 fl.l_type = F_UNLCK; 1035 if (fcntl(fd, F_SETLK, &fl) < 0) 1036 err(1, "F_UNLCK"); 1037 } 1038 SUCCEED; 1039 } 1040 1041 /* 1042 * Test 14 - soak test 1043 */ 1044 static int 1045 test14(int fd) 1046 { 1047 #define CHILD_COUNT 20 1048 /* 1049 * We create a set of child processes and let each one run 1050 * through a random sequence of locks and unlocks. 1051 */ 1052 int i, j, id; 1053 int pids[CHILD_COUNT], pid; 1054 char buf[128]; 1055 char tbuf[128]; 1056 int map[128]; 1057 char outbuf[512]; 1058 struct flock fl; 1059 struct itimerval itv; 1060 int status; 1061 int id_base = 0; 1062 1063 if (verbose) printf("14 - soak test: "); 1064 fflush(stdout); 1065 1066 for (i = 0; i < 128; i++) 1067 map[i] = F_UNLCK; 1068 1069 for (i = 0; i < CHILD_COUNT; i++) { 1070 1071 pid = fork(); 1072 if (pid < 0) 1073 err(1, "fork"); 1074 if (pid) { 1075 /* 1076 * Parent - record the pid and continue. 1077 */ 1078 pids[i] = pid; 1079 continue; 1080 } 1081 1082 /* 1083 * Child - do some work and exit. 1084 */ 1085 id = id_base + i; 1086 for (j = 0; j < 50; j++) { 1087 int start, end, len; 1088 int set, wrlock; 1089 1090 do { 1091 start = arc4random_uniform(128); 1092 end = arc4random_uniform(128); 1093 } while (end <= start); 1094 1095 set = arc4random_uniform(2); 1096 wrlock = arc4random_uniform(2); 1097 1098 len = end - start; 1099 fl.l_start = start; 1100 fl.l_len = len; 1101 fl.l_whence = SEEK_SET; 1102 if (set) 1103 fl.l_type = wrlock ? F_WRLCK : F_RDLCK; 1104 else 1105 fl.l_type = F_UNLCK; 1106 1107 itv.it_interval.tv_sec = 0; 1108 itv.it_interval.tv_usec = 0; 1109 itv.it_value.tv_sec = 0; 1110 itv.it_value.tv_usec = 3000; 1111 setitimer(ITIMER_REAL, &itv, NULL); 1112 1113 if (fcntl(fd, F_SETLKW, &fl) < 0) { 1114 if (errno == EDEADLK || errno == EINTR) { 1115 if (verbose) { 1116 snprintf(outbuf, sizeof(outbuf), 1117 "%d[%d]: %s [%d .. %d] %s\n", 1118 id, j, 1119 set ? (wrlock ? "write lock" 1120 : "read lock") 1121 : "unlock", start, end, 1122 errno == EDEADLK 1123 ? "deadlock" 1124 : "interrupted"); 1125 write(1, outbuf, 1126 strlen(outbuf)); 1127 } 1128 continue; 1129 } else { 1130 perror("fcntl"); 1131 } 1132 } 1133 1134 itv.it_interval.tv_sec = 0; 1135 itv.it_interval.tv_usec = 0; 1136 itv.it_value.tv_sec = 0; 1137 itv.it_value.tv_usec = 0; 1138 setitimer(ITIMER_REAL, &itv, NULL); 1139 1140 if (verbose) { 1141 snprintf(outbuf, sizeof(outbuf), 1142 "%d[%d]: %s [%d .. %d] succeeded\n", 1143 id, j, 1144 set ? (wrlock ? "write lock" : "read lock") 1145 : "unlock", start, end); 1146 write(1, outbuf, strlen(outbuf)); 1147 } 1148 1149 if (set) { 1150 if (wrlock) { 1151 /* 1152 * We got a write lock - write 1153 * our ID to each byte that we 1154 * managed to claim. 1155 */ 1156 for (i = start; i < end; i++) 1157 map[i] = F_WRLCK; 1158 memset(&buf[start], id, len); 1159 if (pwrite(fd, &buf[start], len, 1160 start) != len) { 1161 printf("%d: short write\n", id); 1162 exit(1); 1163 } 1164 } else { 1165 /* 1166 * We got a read lock - read 1167 * the bytes which we claimed 1168 * so that we can check that 1169 * they don't change 1170 * unexpectedly. 1171 */ 1172 for (i = start; i < end; i++) 1173 map[i] = F_RDLCK; 1174 if (pread(fd, &buf[start], len, 1175 start) != len) { 1176 printf("%d: short read\n", id); 1177 exit(1); 1178 } 1179 } 1180 } else { 1181 for (i = start; i < end; i++) 1182 map[i] = F_UNLCK; 1183 } 1184 1185 usleep(1000); 1186 1187 /* 1188 * Read back the whole region so that we can 1189 * check that all the bytes we have some kind 1190 * of claim to have the correct value. 1191 */ 1192 if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) { 1193 printf("%d: short read\n", id); 1194 exit(1); 1195 } 1196 1197 for (i = 0; i < 128; i++) { 1198 if (map[i] != F_UNLCK && buf[i] != tbuf[i]) { 1199 snprintf(outbuf, sizeof(outbuf), 1200 "%d: byte %d expected %d, " 1201 "got %d\n", id, i, buf[i], tbuf[i]); 1202 write(1, outbuf, strlen(outbuf)); 1203 exit(1); 1204 } 1205 } 1206 } 1207 if (verbose) 1208 printf("%d[%d]: done\n", id, j); 1209 1210 exit(0); 1211 } 1212 1213 status = 0; 1214 for (i = 0; i < CHILD_COUNT; i++) { 1215 status += safe_waitpid(pids[i]); 1216 } 1217 if (status) 1218 FAIL(status != 0); 1219 1220 SUCCEED; 1221 } 1222 1223 /* 1224 * Test 15 - flock(2) semantcs 1225 * 1226 * When a lock holder has a shared lock and attempts to upgrade that 1227 * shared lock to exclusive, it must drop the shared lock before 1228 * blocking on the exclusive lock. 1229 * 1230 * To test this, we first arrange for two shared locks on the file, 1231 * and then attempt to upgrade one of them to exclusive. This should 1232 * drop one of the shared locks and block. We interrupt the blocking 1233 * lock request and examine the lock state of the file after dropping 1234 * the other shared lock - there should be no active locks at this 1235 * point. 1236 */ 1237 static int 1238 test15(int fd) 1239 { 1240 #ifdef LOCK_EX 1241 /* 1242 * We create a child process to hold the lock which we will 1243 * test. We use a pipe to communicate with the child. 1244 * 1245 * Since we only have one file descriptors and lock ownership 1246 * for flock(2) goes with the file descriptor, we use fcntl to 1247 * set the child's shared lock. 1248 */ 1249 int pid; 1250 int pfd[2]; 1251 int fd2; 1252 struct flock fl; 1253 char ch; 1254 int res; 1255 1256 if (pipe(pfd) < 0) 1257 err(1, "pipe"); 1258 1259 pid = fork(); 1260 if (pid < 0) 1261 err(1, "fork"); 1262 1263 if (pid == 0) { 1264 /* 1265 * We are the child. We set a shared lock and then 1266 * write one byte back to the parent to tell it. The 1267 * parent will kill us when its done. 1268 */ 1269 fl.l_start = 0; 1270 fl.l_len = 0; 1271 fl.l_type = F_RDLCK; 1272 fl.l_whence = SEEK_SET; 1273 if (fcntl(fd, F_SETLK, &fl) < 0) 1274 err(1, "fcntl(F_SETLK) (child)"); 1275 if (write(pfd[1], "a", 1) < 0) 1276 err(1, "writing to pipe (child)"); 1277 pause(); 1278 exit(0); 1279 } 1280 1281 /* 1282 * Wait until the child has set its lock and then perform the 1283 * test. 1284 */ 1285 if (read(pfd[0], &ch, 1) != 1) 1286 err(1, "reading from pipe (child)"); 1287 1288 fd2 = dup(fd); 1289 if (flock(fd, LOCK_SH) < 0) 1290 err(1, "flock shared"); 1291 1292 /* 1293 * flock should wait until the alarm and then return -1 with 1294 * errno set to EINTR. 1295 */ 1296 if (verbose) printf("15 - flock(2) semantics: "); 1297 1298 alarm(1); 1299 flock(fd, LOCK_EX); 1300 1301 /* 1302 * Kill the child to force it to drop its locks. 1303 */ 1304 safe_kill(pid, SIGTERM); 1305 safe_waitpid(pid); 1306 1307 fl.l_start = 0; 1308 fl.l_len = 0; 1309 fl.l_type = F_WRLCK; 1310 fl.l_whence = SEEK_SET; 1311 res = fcntl(fd, F_GETLK, &fl); 1312 1313 close(pfd[0]); 1314 close(pfd[1]); 1315 FAIL(res != 0); 1316 FAIL(fl.l_type != F_UNLCK); 1317 1318 SUCCEED; 1319 #else 1320 return 0; 1321 #endif 1322 } 1323 1324 /* 1325 * Test 16 - double free regression 1326 * 1327 * Not applicable anymore due to stricter bounds validation. 1328 */ 1329 static int 1330 test16(int fd) 1331 { 1332 #if 0 1333 struct flock fl; 1334 int res; 1335 1336 fl.l_pid = 0; 1337 fl.l_type = 1; 1338 fl.l_whence = 0; 1339 1340 fl.l_start = 0; 1341 fl.l_len = 0x8000000000000000; 1342 res = fcntl(fd, F_SETLK, &fl); 1343 FAIL(res != 0); 1344 1345 fl.l_start = 0x10000; 1346 fl.l_len = 0; 1347 res = fcntl(fd, F_SETLK, &fl); 1348 FAIL(res != 0); 1349 1350 fl.l_start = 0; 1351 fl.l_len = 0x8000000000000000; 1352 res = fcntl(fd, F_SETLK, &fl); 1353 FAIL(res != 0); 1354 1355 fl.l_start = 0x10000; 1356 fl.l_len = 0; 1357 res = fcntl(fd, F_SETLK, &fl); 1358 FAIL(res != 0); 1359 #endif 1360 1361 SUCCEED; 1362 } 1363 1364 /* 1365 * Test 17 - lf_findoverlap() case 0 1366 * 1367 * No overlap. 1368 */ 1369 static int 1370 test17(int fd) 1371 { 1372 struct flock fl; 1373 int nfd, res; 1374 1375 /* First lock. */ 1376 { 1377 nfd = dup(fd); 1378 FAIL(nfd == -1); 1379 1380 fl.l_start = 0; 1381 fl.l_len = 100; 1382 fl.l_pid = 0; 1383 fl.l_type = F_RDLCK; 1384 fl.l_whence = 0; 1385 res = fcntl(fd, F_SETLK, &fl); 1386 FAIL(res != 0); 1387 1388 close(nfd); 1389 } 1390 1391 /* Insert at end. */ 1392 { 1393 nfd = dup(fd); 1394 FAIL(nfd == -1); 1395 1396 fl.l_start = 100; 1397 fl.l_len = 100; 1398 fl.l_pid = 0; 1399 fl.l_type = F_RDLCK; 1400 fl.l_whence = 0; 1401 res = fcntl(fd, F_SETLK, &fl); 1402 FAIL(res != 0); 1403 1404 fl.l_start = 200; 1405 fl.l_len = 100; 1406 fl.l_pid = 0; 1407 fl.l_type = F_RDLCK; 1408 fl.l_whence = 0; 1409 res = fcntl(fd, F_SETLK, &fl); 1410 FAIL(res != 0); 1411 1412 close(nfd); 1413 } 1414 1415 /* Insert before overlap. */ 1416 { 1417 nfd = dup(fd); 1418 FAIL(nfd == -1); 1419 1420 fl.l_start = 300; 1421 fl.l_len = 100; 1422 fl.l_pid = 0; 1423 fl.l_type = F_RDLCK; 1424 fl.l_whence = 0; 1425 res = fcntl(fd, F_SETLK, &fl); 1426 FAIL(res != 0); 1427 1428 fl.l_start = 500; 1429 fl.l_len = 100; 1430 fl.l_pid = 0; 1431 fl.l_type = F_RDLCK; 1432 fl.l_whence = 0; 1433 res = fcntl(fd, F_SETLK, &fl); 1434 FAIL(res != 0); 1435 1436 fl.l_start = 400; 1437 fl.l_len = 100; 1438 fl.l_pid = 0; 1439 fl.l_type = F_RDLCK; 1440 fl.l_whence = 0; 1441 res = fcntl(fd, F_SETLK, &fl); 1442 FAIL(res != 0); 1443 1444 close(nfd); 1445 } 1446 1447 SUCCEED; 1448 } 1449 1450 /* 1451 * Test 18 - lf_findoverlap() case 1 1452 * 1453 * Overlap and lock are equal. 1454 */ 1455 static int 1456 test18(int fd) 1457 { 1458 struct flock fl; 1459 int res; 1460 1461 fl.l_start = 0; 1462 fl.l_len = 100; 1463 fl.l_pid = 0; 1464 fl.l_type = F_RDLCK; 1465 fl.l_whence = 0; 1466 res = fcntl(fd, F_SETLK, &fl); 1467 FAIL(res != 0); 1468 res = fcntl(fd, F_SETLK, &fl); 1469 FAIL(res != 0); 1470 1471 SUCCEED; 1472 } 1473 1474 /* 1475 * Test 19 - lf_findoverlap() case 2 1476 * 1477 * Overlap contains lock. 1478 */ 1479 static int 1480 test19(int fd) 1481 { 1482 struct flock fl; 1483 int nfd, res; 1484 1485 /* Same type. */ 1486 { 1487 nfd = dup(fd); 1488 FAIL(nfd == -1); 1489 1490 fl.l_start = 0; 1491 fl.l_len = 100; 1492 fl.l_pid = 0; 1493 fl.l_type = F_RDLCK; 1494 fl.l_whence = 0; 1495 res = fcntl(fd, F_SETLK, &fl); 1496 FAIL(res != 0); 1497 1498 fl.l_start = 0; 1499 fl.l_len = 50; 1500 fl.l_pid = 0; 1501 fl.l_type = F_RDLCK; 1502 fl.l_whence = 0; 1503 res = fcntl(fd, F_SETLK, &fl); 1504 FAIL(res != 0); 1505 1506 close(nfd); 1507 } 1508 1509 /* Different type, same start offset. */ 1510 { 1511 nfd = dup(fd); 1512 FAIL(nfd == -1); 1513 1514 fl.l_start = 100; 1515 fl.l_len = 100; 1516 fl.l_pid = 0; 1517 fl.l_type = F_RDLCK; 1518 fl.l_whence = 0; 1519 res = fcntl(fd, F_SETLK, &fl); 1520 FAIL(res != 0); 1521 1522 fl.l_start = 100; 1523 fl.l_len = 50; 1524 fl.l_pid = 0; 1525 fl.l_type = F_WRLCK; 1526 fl.l_whence = 0; 1527 res = fcntl(fd, F_SETLK, &fl); 1528 FAIL(res != 0); 1529 1530 close(nfd); 1531 } 1532 1533 /* Split fallback. */ 1534 { 1535 nfd = dup(fd); 1536 FAIL(nfd == -1); 1537 1538 fl.l_start = 100; 1539 fl.l_len = 100; 1540 fl.l_pid = 0; 1541 fl.l_type = F_RDLCK; 1542 fl.l_whence = 0; 1543 res = fcntl(fd, F_SETLK, &fl); 1544 FAIL(res != 0); 1545 1546 fl.l_start = 110; 1547 fl.l_len = 50; 1548 fl.l_pid = 0; 1549 fl.l_type = F_WRLCK; 1550 fl.l_whence = 0; 1551 res = fcntl(fd, F_SETLK, &fl); 1552 FAIL(res != 0); 1553 1554 close(nfd); 1555 } 1556 1557 SUCCEED; 1558 } 1559 1560 /* 1561 * Test 20 - lf_findoverlap() case 3 1562 * 1563 * Lock contains overlap. 1564 */ 1565 static int 1566 test20(int fd) 1567 { 1568 struct flock fl; 1569 int res; 1570 1571 fl.l_start = 0; 1572 fl.l_len = 100; 1573 fl.l_pid = 0; 1574 fl.l_type = F_WRLCK; 1575 fl.l_whence = 0; 1576 res = fcntl(fd, F_SETLK, &fl); 1577 FAIL(res != 0); 1578 1579 fl.l_start = 0; 1580 fl.l_len = 200; 1581 fl.l_pid = 0; 1582 fl.l_type = F_WRLCK; 1583 fl.l_whence = 0; 1584 res = fcntl(fd, F_SETLK, &fl); 1585 FAIL(res != 0); 1586 1587 SUCCEED; 1588 } 1589 1590 /* 1591 * Test 21 - lf_findoverlap() case 4 1592 * 1593 * Overlap starts before lock. 1594 */ 1595 static int 1596 test21(int fd) 1597 { 1598 struct flock fl; 1599 int res; 1600 1601 fl.l_start = 0; 1602 fl.l_len = 100; 1603 fl.l_pid = 0; 1604 fl.l_type = F_WRLCK; 1605 fl.l_whence = 0; 1606 res = fcntl(fd, F_SETLK, &fl); 1607 FAIL(res != 0); 1608 1609 fl.l_start = 50; 1610 fl.l_len = 100; 1611 fl.l_pid = 0; 1612 fl.l_type = F_WRLCK; 1613 fl.l_whence = 0; 1614 res = fcntl(fd, F_SETLK, &fl); 1615 FAIL(res != 0); 1616 1617 SUCCEED; 1618 } 1619 1620 /* 1621 * Test 22 - lf_findoverlap() case 5 1622 * 1623 * Overlap ends after lock. 1624 */ 1625 static int 1626 test22(int fd) 1627 { 1628 struct flock fl; 1629 int res; 1630 1631 fl.l_start = 10; 1632 fl.l_len = 100; 1633 fl.l_pid = 0; 1634 fl.l_type = F_WRLCK; 1635 fl.l_whence = 0; 1636 res = fcntl(fd, F_SETLK, &fl); 1637 FAIL(res != 0); 1638 1639 fl.l_start = 0; 1640 fl.l_len = 50; 1641 fl.l_pid = 0; 1642 fl.l_type = F_WRLCK; 1643 fl.l_whence = 0; 1644 res = fcntl(fd, F_SETLK, &fl); 1645 FAIL(res != 0); 1646 1647 SUCCEED; 1648 } 1649 1650 /* 1651 * Test 23 - positive length overflow 1652 */ 1653 static int 1654 test23(int fd) 1655 { 1656 struct flock fl; 1657 int res; 1658 1659 fl.l_pid = 0; 1660 fl.l_type = F_WRLCK; 1661 fl.l_whence = SEEK_SET; 1662 fl.l_start = 2; 1663 fl.l_len = LLONG_MAX; 1664 res = fcntl(fd, F_SETLK, &fl); 1665 FAIL(res != -1); 1666 FAIL(errno != EOVERFLOW); 1667 1668 SUCCEED; 1669 } 1670 1671 /* 1672 * Test 24 - negative length 1673 */ 1674 static int 1675 test24(int fd) 1676 { 1677 struct flock fl; 1678 pid_t pid; 1679 int res, status; 1680 1681 fl.l_pid = 0; 1682 fl.l_type = F_WRLCK; 1683 fl.l_whence = SEEK_SET; 1684 1685 /* Start offset plus length must be positive. */ 1686 fl.l_start = 0; 1687 fl.l_len = LLONG_MIN; 1688 res = fcntl(fd, F_SETLK, &fl); 1689 FAIL(res != -1); 1690 FAIL(errno != EINVAL); 1691 1692 /* Set exclusive lock on range [2,3] */ 1693 fl.l_start = 4; 1694 fl.l_len = -2; 1695 res = fcntl(fd, F_SETLK, &fl); 1696 FAIL(res != 0); 1697 1698 /* Another process must not be able to lock the same range. */ 1699 pid = fork(); 1700 if (pid == -1) 1701 err(1, "fork"); 1702 if (pid == 0) { 1703 fl.l_start = 2; 1704 fl.l_len = 2; 1705 res = fcntl(fd, F_GETLK, &fl); 1706 FAIL(res != 0); 1707 FAIL(fl.l_type == F_UNLCK); 1708 _exit(0); 1709 } 1710 status = safe_waitpid(pid); 1711 FAIL(status != 0); 1712 1713 SUCCEED; 1714 } 1715 1716 static struct test tests[] = { 1717 { test1, 0 }, 1718 { test2, 0 }, 1719 { test3, 1 }, 1720 { test4, 0 }, 1721 { test5, 1 }, 1722 { test6, 1 }, 1723 { test7, 0 }, 1724 { test8, 0 }, 1725 { test9, 0 }, 1726 { test10, 0 }, 1727 { test11, 1 }, 1728 { test12, 0 }, 1729 { test13, 1 }, 1730 { test14, 0 }, 1731 { test15, 1 }, 1732 { test16, 0 }, 1733 { test17, 0 }, 1734 { test18, 0 }, 1735 { test19, 0 }, 1736 { test20, 0 }, 1737 { test21, 0 }, 1738 { test22, 0 }, 1739 { test23, 0 }, 1740 { test24, 0 }, 1741 }; 1742 1743 static int test_count = sizeof(tests) / sizeof(tests[0]); 1744 1745 int 1746 main(int argc, char *argv[]) 1747 { 1748 struct sigaction sa; 1749 const char *errstr; 1750 int c, fd, i; 1751 int error = 0; 1752 int testnum = 0; 1753 1754 while ((c = getopt(argc, argv, "v")) != -1) 1755 switch (c) { 1756 case 'v': 1757 verbose = 1; 1758 break; 1759 default: 1760 usage(); 1761 } 1762 argc -= optind; 1763 argv += optind; 1764 if (argc > 1) 1765 usage(); 1766 if (argc == 1) { 1767 testnum = strtonum(argv[0], 1, test_count, &errstr); 1768 if (testnum == 0) 1769 errx(1, "test number %s", errstr); 1770 } 1771 1772 fd = make_file(1024); 1773 1774 sa.sa_handler = ignore_alarm; 1775 sigemptyset(&sa.sa_mask); 1776 sa.sa_flags = 0; 1777 sigaction(SIGALRM, &sa, 0); 1778 1779 for (i = 0; i < test_count; i++) { 1780 if (testnum == 0 || testnum == i + 1) 1781 error |= tests[i].testfn(fd); 1782 } 1783 1784 return (error ? 1 : 0); 1785 } 1786