Add a test to validate the syscall errors
authorMichael Jeanson <mjeanson@efficios.com>
Fri, 26 Jul 2024 15:15:44 +0000 (15:15 +0000)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 30 Jul 2024 18:21:25 +0000 (14:21 -0400)
Change-Id: Ia589597d23df3fe317a009d409272f4664f0a7e0
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
.gitignore
tests/Makefile.am
tests/run_syscall_errors_test.tap [new file with mode: 0755]
tests/run_syscall_errors_test_cxx.tap [new file with mode: 0755]
tests/syscall_errors_test.c [new file with mode: 0644]
tests/syscall_errors_test_cxx.cpp [new file with mode: 0644]

index 3bcfbf4cdc6b50ee0c2e4ddcbfd68c2bb25ec13d..47ca9cc6fcc4d69ea3d08c0e203653f792e7930b 100644 (file)
@@ -80,6 +80,8 @@ dkms.conf
 /tests/param_test_mm_cid_compare_twice_cxx
 /tests/no_syscall_test_cxx.tap
 /tests/no_syscall_test.tap
+/tests/syscall_errors_test_cxx.tap
+/tests/syscall_errors_test.tap
 /tests/unregistered_test_cxx.tap
 /tests/unregistered_test.tap
 
index 2cc71e82d6d8eeaedb98d09a4ad8b2cab55ef27a..d7f8ea56dd7236d32c6bf1f0d2de3daf21ebaef4 100644 (file)
@@ -37,6 +37,8 @@ noinst_PROGRAMS = \
        param_test_mm_cid_compare_twice_cxx \
        no_syscall_test_cxx.tap \
        no_syscall_test.tap \
+       syscall_errors_test.tap \
+       syscall_errors_test_cxx.tap \
        unregistered_test_cxx.tap \
        unregistered_test.tap
 
@@ -45,6 +47,8 @@ dist_noinst_SCRIPTS = \
        run_no_syscall_test.tap \
        run_param_test_cxx.tap \
        run_param_test.tap \
+       run_syscall_errors_test_cxx.tap \
+       run_syscall_errors_test.tap \
        run_unregistered_test_cxx.tap \
        run_unregistered_test.tap
 
@@ -72,6 +76,12 @@ basic_percpu_ops_mm_cid_test_cxx_tap_SOURCES = basic_percpu_ops_test_cxx.cpp
 basic_percpu_ops_mm_cid_test_cxx_tap_CPPFLAGS = $(AM_CPPFLAGS) -DBUILDOPT_RSEQ_PERCPU_MM_CID
 basic_percpu_ops_mm_cid_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
 
+syscall_errors_test_tap_SOURCES = syscall_errors_test.c
+syscall_errors_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
+syscall_errors_test_cxx_tap_SOURCES = syscall_errors_test_cxx.cpp
+syscall_errors_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
 unregistered_test_tap_SOURCES = unregistered_test.c
 unregistered_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
 
@@ -154,6 +164,8 @@ TESTS = \
        basic_test_cxx.tap \
        run_unregistered_test.tap \
        run_unregistered_test_cxx.tap \
+       run_syscall_errors_test.tap \
+       run_syscall_errors_test_cxx.tap \
        mempool_cow_race_test.tap \
        mempool_cow_race_test_cxx.tap \
        mempool_test.tap \
diff --git a/tests/run_syscall_errors_test.tap b/tests/run_syscall_errors_test.tap
new file mode 100755 (executable)
index 0000000..c9682cf
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+SH_TAP=0
+
+if [ "x${RSEQ_TESTS_SRCDIR:-}" != "x" ]; then
+       UTILSSH="$RSEQ_TESTS_SRCDIR/utils/utils.sh"
+else
+       UTILSSH="$(dirname "$0")/utils/utils.sh"
+fi
+
+# shellcheck source=./utils/utils.sh
+source "$UTILSSH"
+
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0" "${RSEQ_TESTS_BUILDDIR}/syscall_errors_test.tap"
diff --git a/tests/run_syscall_errors_test_cxx.tap b/tests/run_syscall_errors_test_cxx.tap
new file mode 100755 (executable)
index 0000000..6193501
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+SH_TAP=0
+
+if [ "x${RSEQ_TESTS_SRCDIR:-}" != "x" ]; then
+       UTILSSH="$RSEQ_TESTS_SRCDIR/utils/utils.sh"
+else
+       UTILSSH="$(dirname "$0")/utils/utils.sh"
+fi
+
+# shellcheck source=./utils/utils.sh
+source "$UTILSSH"
+
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0" "${RSEQ_TESTS_BUILDDIR}/syscall_errors_test_cxx.tap"
diff --git a/tests/syscall_errors_test.c b/tests/syscall_errors_test.c
new file mode 100644 (file)
index 0000000..a319717
--- /dev/null
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdint.h>
+#include <syscall.h>
+#include <unistd.h>
+
+#include <rseq/rseq.h>
+
+#include "tap.h"
+
+#if RSEQ_BITS_PER_LONG == 64
+#define NR_TESTS 8
+#else
+#define NR_TESTS 7
+#endif
+
+static int sys_rseq(void *rseq_abi, uint32_t rseq_len,
+                   int flags, uint32_t sig)
+{
+       return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
+}
+
+/*
+ * Check the value of errno on some expected failures of the rseq syscall.
+ */
+
+int main(void)
+{
+       struct rseq_abi *global_rseq = rseq_get_abi();
+       int ret;
+       int errno_copy;
+
+       plan_tests(NR_TESTS);
+
+       if (!rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
+               skip(NR_TESTS, "rseq syscall unavailable");
+               goto end;
+       }
+
+       /* The current thread is NOT registered. */
+
+       /* EINVAL */
+       errno = 0;
+       ret = sys_rseq(global_rseq, 32, -1, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EINVAL, "Invalid flag set errno to EINVAL (ret = %d, errno = %d)", ret, errno_copy);
+
+       errno = 0;
+       ret = sys_rseq((char *) global_rseq + 1, 32, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EINVAL, "Unaligned rseq_abi set errno to EINVAL (ret = %d, errno = %d)", ret, errno_copy);
+
+       errno = 0;
+       ret = sys_rseq(global_rseq, 31, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EINVAL, "Invalid size set errno to EINVAL (ret = %d, errno = %d)", ret, errno_copy);
+
+
+#if RSEQ_BITS_PER_LONG == 64
+       /*
+        * We haven't found a reliable way to find an invalid address when
+        * running a 32bit userspace on a 64bit kernel, so only run this test
+        * on 64bit builds for the moment.
+        */
+
+       /* EFAULT */
+       errno = 0;
+       ret = sys_rseq((void *) -4096UL, 32, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EFAULT, "Invalid address set errno to EFAULT (ret = %d, errno = %d)", ret, errno_copy);
+#endif
+
+       errno = 0;
+       ret = sys_rseq(global_rseq, 32, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret == 0, "Register rseq for the current thread (ret = %d, errno = %d)", ret, errno_copy);
+
+       /* The current thread is registered. */
+
+       /* EBUSY */
+       errno = 0;
+       ret = sys_rseq(global_rseq, 32, 0, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EBUSY, "Same registration set errno to EBUSY (ret = %d, errno = %d)", ret, errno_copy);
+
+       /* EPERM */
+       errno = 0;
+       ret = sys_rseq(global_rseq, 32, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG + 1);
+       errno_copy = errno;
+       ok(ret != 0 && errno_copy == EPERM, "Unregistration with wrong RSEQ_SIG set errno to EPERM (ret = %d, errno = %d)", ret, errno_copy);
+
+       errno = 0;
+       ret = sys_rseq(global_rseq, 32, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
+       errno_copy = errno;
+       ok(ret == 0, "Unregister rseq for the current thread (ret = %d, errno = %d)", ret, errno_copy);
+
+end:
+       exit(exit_status());
+}
diff --git a/tests/syscall_errors_test_cxx.cpp b/tests/syscall_errors_test_cxx.cpp
new file mode 100644 (file)
index 0000000..8badeef
--- /dev/null
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 EfficiOS Inc.
+
+#include "syscall_errors_test.c"
This page took 0.026228 seconds and 4 git commands to generate.