diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2022-06-01 14:21:51 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2022-06-01 14:21:51 +0000 |
commit | f31c028f896d19340a0b2bce2d646ef716c17fca (patch) | |
tree | bce3c29c70baed2abb6d45dae45910416a39b0e4 /regress | |
parent | ed10d4eba3c704290036f1b616b50b3895aa0b0d (diff) |
Add a regress test for the end of lock range ambiguity bug.
Diffstat (limited to 'regress')
-rw-r--r-- | regress/sys/kern/flock/Makefile | 4 | ||||
-rw-r--r-- | regress/sys/kern/flock/flock.c | 97 |
2 files changed, 99 insertions, 2 deletions
diff --git a/regress/sys/kern/flock/Makefile b/regress/sys/kern/flock/Makefile index 2bf4167e0b1..46556e05f91 100644 --- a/regress/sys/kern/flock/Makefile +++ b/regress/sys/kern/flock/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2022/04/27 18:02:05 anton Exp $ +# $OpenBSD: Makefile,v 1.13 2022/06/01 14:21:50 visa Exp $ PROGS+= flock SRCS_flock= flock.c util.c @@ -9,7 +9,7 @@ SRCS_lockf= lockf.c util.c WARNINGS= yes -TESTS_FLOCK!= jot 25 1 +TESTS_FLOCK!= jot 26 1 .for t in ${TESTS_FLOCK} run-flock-$t: flock ./flock ${LOCKFLAGS} $t diff --git a/regress/sys/kern/flock/flock.c b/regress/sys/kern/flock/flock.c index f4fa317600e..f8ec8a0c5d1 100644 --- a/regress/sys/kern/flock/flock.c +++ b/regress/sys/kern/flock/flock.c @@ -1760,6 +1760,102 @@ test25(int fd) SUCCEED; } +/* + * Test 26 - range end point ambiguity regression + * + * When a new lock range [start, LLONG_MAX] overlapped with an existing range, + * kernel's lock data structure could become inconsistent. + */ +static int +test26(int fd) +{ + struct flock fl; + pid_t pid; + int res, status; + + /* Lock the whole range. */ + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = 0; + fl.l_type = F_RDLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_SETLK, &fl); + FAIL(res != 0); + + /* + * Split the range at the end. + * This should be handled as if l_len == 0. + */ + fl.l_start = LLONG_MAX; + fl.l_len = 1; + fl.l_pid = 0; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_SETLK, &fl); + FAIL(res != 0); + + /* Check the resulting ranges. */ + pid = fork(); + if (pid == -1) + err(1, "fork"); + if (pid == 0) { + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_GETLK, &fl); + FAIL(res != 0); + FAIL(fl.l_type != F_RDLCK); + FAIL(fl.l_start != 0); + FAIL(fl.l_len != LLONG_MAX); + + fl.l_start = LLONG_MAX; + fl.l_len = 0; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_GETLK, &fl); + FAIL(res != 0); + FAIL(fl.l_type != F_WRLCK); + FAIL(fl.l_start != LLONG_MAX); + FAIL(fl.l_len != 0); + + _exit(0); + } + status = safe_waitpid(pid); + FAIL(status != 0); + + /* Release all locks. */ + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = 0; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_SETLK, &fl); + FAIL(res != 0); + + /* Check the resulting ranges. */ + pid = fork(); + if (pid == -1) + err(1, "fork"); + if (pid == 0) { + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + res = fcntl(fd, F_GETLK, &fl); + FAIL(res != 0); + FAIL(fl.l_type != F_UNLCK); + FAIL(fl.l_start != 0); + FAIL(fl.l_len != 0); + + _exit(0); + } + status = safe_waitpid(pid); + FAIL(status != 0); + + SUCCEED; +} + static struct test tests[] = { { test1, 0 }, { test2, 0 }, @@ -1786,6 +1882,7 @@ static struct test tests[] = { { test23, 0 }, { test24, 0 }, { test25, 0 }, + { test26, 0 }, }; static int test_count = sizeof(tests) / sizeof(tests[0]); |