summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2022-06-01 14:21:51 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2022-06-01 14:21:51 +0000
commitf31c028f896d19340a0b2bce2d646ef716c17fca (patch)
treebce3c29c70baed2abb6d45dae45910416a39b0e4 /regress
parented10d4eba3c704290036f1b616b50b3895aa0b0d (diff)
Add a regress test for the end of lock range ambiguity bug.
Diffstat (limited to 'regress')
-rw-r--r--regress/sys/kern/flock/Makefile4
-rw-r--r--regress/sys/kern/flock/flock.c97
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]);