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