This patch adds test cases for LOCK_MAND: - LOCK_MAND with/without LOCK_READ/LOCK_WRITE - read/write - same fd - different fd - same PID - different PID Signed-off-by: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> --- tools/testing/selftests/sysctl/.gitignore | 2 + tools/testing/selftests/sysctl/Makefile | 9 +- tools/testing/selftests/sysctl/sysctl_flock.c | 157 ++++++++++++++++++ 3 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 tools/testing/selftests/sysctl/.gitignore create mode 100644 tools/testing/selftests/sysctl/sysctl_flock.c diff --git a/tools/testing/selftests/sysctl/.gitignore b/tools/testing/selftests/sysctl/.gitignore new file mode 100644 index 000000000000..a3382ba798a6 --- /dev/null +++ b/tools/testing/selftests/sysctl/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +/sysctl_flock diff --git a/tools/testing/selftests/sysctl/Makefile b/tools/testing/selftests/sysctl/Makefile index 110301f9f5be..eb565b6c8340 100644 --- a/tools/testing/selftests/sysctl/Makefile +++ b/tools/testing/selftests/sysctl/Makefile @@ -2,12 +2,11 @@ # Makefile for sysctl selftests. # Expects kernel.sysctl_writes_strict=1. -# No binaries, but make sure arg-less "make" doesn't trigger "run_tests". -all: +CFLAGS = -Wall -Wl,--no-as-needed -O2 -g +CFLAGS += -D_GNU_SOURCE TEST_PROGS := sysctl.sh -include ../lib.mk +TEST_GEN_PROGS += sysctl_flock -# Nothing to clean up. -clean: +include ../lib.mk diff --git a/tools/testing/selftests/sysctl/sysctl_flock.c b/tools/testing/selftests/sysctl/sysctl_flock.c new file mode 100644 index 000000000000..4c4be10ae0d3 --- /dev/null +++ b/tools/testing/selftests/sysctl/sysctl_flock.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright Amazon.com Inc. or its affiliates. */ + +#include <unistd.h> +#include <sys/file.h> +#include <sys/types.h> + +#include "../kselftest_harness.h" + +#define SYSCTL_PATH "/proc/sys/net/ipv4/tcp_migrate_req" +#define SYSCTL_BUFLEN 8 + +FIXTURE(proc_sysctl_flock) +{ + int fd; + char buf[SYSCTL_BUFLEN]; + int len; +}; + +FIXTURE_VARIANT(proc_sysctl_flock) +{ + int cmd; +}; + +FIXTURE_VARIANT_ADD(proc_sysctl_flock, lock_mand) +{ + .cmd = LOCK_MAND, +}; + +FIXTURE_VARIANT_ADD(proc_sysctl_flock, lock_mand_read) +{ + .cmd = LOCK_MAND | LOCK_READ, +}; + +FIXTURE_VARIANT_ADD(proc_sysctl_flock, lock_mand_write) +{ + .cmd = LOCK_MAND | LOCK_WRITE, +}; + +FIXTURE_VARIANT_ADD(proc_sysctl_flock, lock_mand_read_write) +{ + .cmd = LOCK_MAND | LOCK_READ | LOCK_WRITE, +}; + +int proc_sysctl_open(struct __test_metadata *_metadata) +{ + int fd; + + fd = open(SYSCTL_PATH, O_RDWR); + ASSERT_NE(-1, fd); + + return fd; +} + +FIXTURE_SETUP(proc_sysctl_flock) +{ + self->fd = proc_sysctl_open(_metadata); + ASSERT_EQ(0, flock(self->fd, variant->cmd)); + + self->len = read(self->fd, self->buf, sizeof(self->buf)); + ASSERT_NE(-1, self->len); + + ASSERT_EQ(self->len, write(self->fd, self->buf, self->len)); +} + +FIXTURE_TEARDOWN(proc_sysctl_flock) +{ + flock(self->fd, LOCK_UN); + close(self->fd); +} + +int is_readable(int cmd) +{ + return cmd & LOCK_READ; +} + +int is_writable(int cmd) +{ + return cmd & LOCK_WRITE; +} + +void proc_sysctl_newfd_read(struct __test_metadata *_metadata, + FIXTURE_DATA(proc_sysctl_flock) *self, + const FIXTURE_VARIANT(proc_sysctl_flock) *variant) +{ + char buf[SYSCTL_BUFLEN]; + int err, fd; + + fd = proc_sysctl_open(_metadata); + + err = read(fd, buf, SYSCTL_BUFLEN); + if (is_readable(variant->cmd)) { + ASSERT_EQ(self->len, err); + } else { + ASSERT_EQ(-1, err); + } + + close(fd); +} + +void proc_sysctl_newfd_write(struct __test_metadata *_metadata, + FIXTURE_DATA(proc_sysctl_flock) *self, + const FIXTURE_VARIANT(proc_sysctl_flock) *variant) +{ + int err, fd; + + fd = proc_sysctl_open(_metadata); + + err = write(fd, self->buf, self->len); + if (is_writable(variant->cmd)) { + ASSERT_EQ(self->len, err); + } else { + ASSERT_EQ(-1, err); + } + + close(fd); +} + +void proc_sysctl_fork(struct __test_metadata *_metadata, + FIXTURE_DATA(proc_sysctl_flock) *self, + const FIXTURE_VARIANT(proc_sysctl_flock) *variant, + int read) +{ + int pid, status; + + pid = fork(); + if (pid == 0) { + if (read) + return proc_sysctl_newfd_read(_metadata, self, variant); + else + return proc_sysctl_newfd_write(_metadata, self, variant); + } + + waitpid(pid, &status, 0); +} + +TEST_F(proc_sysctl_flock, test_newfd_read) +{ + proc_sysctl_newfd_read(_metadata, self, variant); +} + +TEST_F(proc_sysctl_flock, test_newfd_write) +{ + proc_sysctl_newfd_write(_metadata, self, variant); +} + +TEST_F(proc_sysctl_flock, test_fork_newfd_read) +{ + proc_sysctl_fork(_metadata, self, variant, 1); +} + +TEST_F(proc_sysctl_flock, test_fork_newfd_write) +{ + proc_sysctl_fork(_metadata, self, variant, 0); +} + +TEST_HARNESS_MAIN -- 2.30.2