tests: add unregistered and no syscall tests
authorMichael Jeanson <mjeanson@efficios.com>
Fri, 23 Feb 2024 15:38:46 +0000 (10:38 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 23 Feb 2024 20:17:16 +0000 (15:17 -0500)
Add tests to validate the state of the public symbols when no
registration has occured and when the rseq syscall is unavailable.

The no syscall test uses seccomp to deny access to rseq, libseccomp is
added as an optionnal build dependency.

Change-Id: I0bf6249fa13bd39af80c21a9d2892cd132644e69
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
12 files changed:
.gitignore
configure.ac
tests/Makefile.am
tests/disable-rseq-syscall.c [new file with mode: 0644]
tests/no_syscall_test.c [new file with mode: 0644]
tests/no_syscall_test_cxx.cpp [new file with mode: 0644]
tests/run_no_syscall_test.tap [new file with mode: 0755]
tests/run_no_syscall_test_cxx.tap [new file with mode: 0755]
tests/run_unregistered_test.tap [new file with mode: 0755]
tests/run_unregistered_test_cxx.tap [new file with mode: 0755]
tests/unregistered_test.c [new file with mode: 0644]
tests/unregistered_test_cxx.cpp [new file with mode: 0644]

index 6863b6e32f34b357921cbfaff0d1279625ed7914..dd925c3b6cf0e1406310311d27f484894162cca1 100644 (file)
@@ -74,6 +74,10 @@ dkms.conf
 /tests/param_test_mm_cid_benchmark_cxx
 /tests/param_test_mm_cid_compare_twice
 /tests/param_test_mm_cid_compare_twice_cxx
+/tests/no_syscall_test_cxx.tap
+/tests/no_syscall_test.tap
+/tests/unregistered_test_cxx.tap
+/tests/unregistered_test.tap
 
 #automake
 /include/config.h
index 7f712ad7f2745b79499b0503737f7c07d49f3cf5..9b8a33c893de40aae47339fcaeed3609bbec3ea4 100644 (file)
@@ -182,6 +182,15 @@ AC_CHECK_LIB([dl], [dlopen], [
 ])
 AC_SUBST(DL_LIBS)
 
+PKG_CHECK_MODULES([SECCOMP], [libseccomp],
+  [
+    dnl PKG_CHECK_MODULES defines SECCOMP_LIBS
+    have_seccomp=yes
+  ],
+  [
+    have_seccomp=no
+  ])
+
 
 ##                             ##
 ## Optional features selection ##
@@ -193,6 +202,13 @@ AE_FEATURE_DEFAULT_DISABLE
 AE_FEATURE([Werror], [Treat compiler warnings as errors.])
 
 
+##                                                                          ##
+## Set automake variables for optional feature conditionnals in Makefile.am ##
+##                                                                          ##
+
+AM_CONDITIONAL([ENABLE_SECCOMP], test "x${have_seccomp}" = "xyes")
+
+
 ##                                             ##
 ## Substitute variables for use in Makefile.am ##
 ##                                             ##
index 8ee8c1b879f1db56ae543af0a4556523697e1987..85e546bda6901a7bb2d6b0c3519f0ae3e456a0ae 100644 (file)
@@ -30,11 +30,27 @@ noinst_PROGRAMS = \
        param_test_compare_twice \
        param_test_compare_twice_cxx \
        param_test_mm_cid_compare_twice \
-       param_test_mm_cid_compare_twice_cxx
+       param_test_mm_cid_compare_twice_cxx \
+       no_syscall_test_cxx.tap \
+       no_syscall_test.tap \
+       unregistered_test_cxx.tap \
+       unregistered_test.tap
 
 dist_noinst_SCRIPTS = \
+       run_no_syscall_test_cxx.tap \
+       run_no_syscall_test.tap \
+       run_param_test_cxx.tap \
        run_param_test.tap \
-       run_param_test_cxx.tap
+       run_unregistered_test_cxx.tap \
+       run_unregistered_test.tap
+
+if ENABLE_SECCOMP
+noinst_LTLIBRARIES = libdisable-rseq-syscall.la
+
+libdisable_rseq_syscall_la_SOURCES = disable-rseq-syscall.c
+libdisable_rseq_syscall_la_LDFLAGS = -module -shared -avoid-version -rpath $(abs_builddir)/.libs/
+libdisable_rseq_syscall_la_LIBADD = $(SECCOMP_LIBS)
+endif
 
 basic_percpu_ops_test_tap_SOURCES = basic_percpu_ops_test.c
 basic_percpu_ops_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
@@ -50,6 +66,18 @@ 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)
 
+unregistered_test_tap_SOURCES = unregistered_test.c
+unregistered_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
+unregistered_test_cxx_tap_SOURCES = unregistered_test_cxx.cpp
+unregistered_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
+no_syscall_test_tap_SOURCES = no_syscall_test.c
+no_syscall_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
+no_syscall_test_cxx_tap_SOURCES = no_syscall_test_cxx.cpp
+no_syscall_test_cxx_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
+
 basic_test_tap_SOURCES = basic_test.c
 basic_test_tap_LDADD = $(top_builddir)/src/librseq.la $(top_builddir)/tests/utils/libtap.la $(DL_LIBS)
 
@@ -102,12 +130,24 @@ param_test_mm_cid_compare_twice_cxx_SOURCES = param_test_cxx.cpp
 param_test_mm_cid_compare_twice_cxx_CPPFLAGS = $(AM_CPPFLAGS) -DRSEQ_COMPARE_TWICE -DBUILDOPT_RSEQ_PERCPU_MM_CID
 param_test_mm_cid_compare_twice_cxx_LDADD = $(top_builddir)/src/librseq.la $(DL_LIBS)
 
+# Run shorter tests first
 TESTS = \
+       basic_test.tap \
+       basic_test_cxx.tap \
+       run_unregistered_test.tap \
+       run_unregistered_test_cxx.tap
+
+if ENABLE_SECCOMP
+TESTS += \
+       run_no_syscall_test.tap \
+       run_no_syscall_test_cxx.tap
+endif
+
+# Run longer tests last
+TESTS += \
        basic_percpu_ops_test.tap \
        basic_percpu_ops_test_cxx.tap \
        basic_percpu_ops_mm_cid_test.tap \
        basic_percpu_ops_mm_cid_test_cxx.tap \
-       basic_test.tap \
-       basic_test_cxx.tap \
        run_param_test.tap \
        run_param_test_cxx.tap
diff --git a/tests/disable-rseq-syscall.c b/tests/disable-rseq-syscall.c
new file mode 100644 (file)
index 0000000..329c925
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+#include <errno.h>
+#include <seccomp.h>
+
+/*
+ * Library constructor.
+ *
+ * Apply a seccomp policy that blocks access to the rseq syscall and returns
+ * ENOSYS.
+ */
+static __attribute__((constructor))
+void disable_rseq_syscall(void)
+{
+       scmp_filter_ctx ctx;
+
+       ctx = seccomp_init(SCMP_ACT_ALLOW);
+       seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOSYS), SCMP_SYS(rseq), 0);
+       seccomp_load(ctx);
+}
diff --git a/tests/no_syscall_test.c b/tests/no_syscall_test.c
new file mode 100644 (file)
index 0000000..b116012
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdint.h>
+
+#include <rseq/rseq.h>
+
+#include "tap.h"
+
+#define NR_TESTS 5
+
+/*
+ * Check the state of the public symbols when the rseq syscall is unavailable.
+ *
+ * This test must be used with an LD_PRELOAD library to deny access to the
+ * syscall, or on a kernel that doesn't implement the syscall.
+ */
+
+int main(void)
+{
+       struct rseq_abi *rseq_abi;
+
+       plan_tests(NR_TESTS);
+
+       if (rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
+               fail("The rseq syscall should be unavailable");
+               goto end;
+       }
+
+       /* The rseq syscall is disabled, no registration is possible. */
+
+       ok(rseq_flags == 0, "rseq_flags prior to registration is 0 (%d)", rseq_flags);
+       ok(rseq_size == 0, "rseq_size prior to registration is 0 (%d)", rseq_size);
+       ok(rseq_feature_size == 0, "rseq_feature_size prior to registration is 0 (%d)", rseq_feature_size);
+       ok(rseq_offset != 0, "rseq_offset prior to registration is not 0 (%td)", rseq_offset);
+
+       rseq_abi = rseq_get_abi();
+       ok((int32_t) rseq_abi->cpu_id == RSEQ_ABI_CPU_ID_UNINITIALIZED,
+                       "rseq->cpu_id is set to RSEQ_ABI_CPU_ID_UNINITIALIZED (%d)",
+                       (int32_t) rseq_abi->cpu_id);
+
+end:
+       exit(exit_status());
+}
diff --git a/tests/no_syscall_test_cxx.cpp b/tests/no_syscall_test_cxx.cpp
new file mode 100644 (file)
index 0000000..3b846f1
--- /dev/null
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 EfficiOS Inc.
+
+#include "no_syscall_test.c"
diff --git a/tests/run_no_syscall_test.tap b/tests/run_no_syscall_test.tap
new file mode 100755 (executable)
index 0000000..a0347fc
--- /dev/null
@@ -0,0 +1,21 @@
+#!/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"
+
+CURDIR="${RSEQ_TESTS_BUILDDIR}/"
+
+LIBDISABLE_RSEQ_SYSCALL_PATH="${CURDIR}/.libs"
+LIBDISABLE_RSEQ_SYSCALL="${LIBDISABLE_RSEQ_SYSCALL_PATH}/libdisable-rseq-syscall.so"
+
+LD_PRELOAD="${LIBDISABLE_RSEQ_SYSCALL}" "${CURDIR}/no_syscall_test.tap"
diff --git a/tests/run_no_syscall_test_cxx.tap b/tests/run_no_syscall_test_cxx.tap
new file mode 100755 (executable)
index 0000000..63b7466
--- /dev/null
@@ -0,0 +1,21 @@
+#!/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"
+
+CURDIR="${RSEQ_TESTS_BUILDDIR}/"
+
+LIBDISABLE_RSEQ_SYSCALL_PATH="${CURDIR}/.libs"
+LIBDISABLE_RSEQ_SYSCALL="${LIBDISABLE_RSEQ_SYSCALL_PATH}/libdisable-rseq-syscall.so"
+
+LD_PRELOAD="${LIBDISABLE_RSEQ_SYSCALL}" "${CURDIR}/no_syscall_test_cxx.tap"
diff --git a/tests/run_unregistered_test.tap b/tests/run_unregistered_test.tap
new file mode 100755 (executable)
index 0000000..eef9063
--- /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}/unregistered_test.tap"
diff --git a/tests/run_unregistered_test_cxx.tap b/tests/run_unregistered_test_cxx.tap
new file mode 100755 (executable)
index 0000000..61718e1
--- /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}/unregistered_test_cxx.tap"
diff --git a/tests/unregistered_test.c b/tests/unregistered_test.c
new file mode 100644 (file)
index 0000000..fc45dab
--- /dev/null
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 Michael Jeanson <mjeanson@efficios.com>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdint.h>
+
+#include <rseq/rseq.h>
+
+#include "tap.h"
+
+#define NR_TESTS 5
+
+/*
+ * Check the state of the public symbols when the rseq syscall is available but
+ * no thread has registered.
+ */
+
+int main(void)
+{
+       struct rseq_abi *rseq_abi;
+
+       plan_tests(NR_TESTS);
+
+       if (!rseq_available(RSEQ_AVAILABLE_QUERY_KERNEL)) {
+               skip(NR_TESTS, "rseq syscall unavailable");
+               goto end;
+       }
+
+       /* The syscall is available but the current thread is not registered. */
+
+       ok(rseq_flags == 0, "rseq_flags prior to registration is 0 (%d)", rseq_flags);
+       ok(rseq_size >= 32, "rseq_size prior to registration is 32 or greater (%d)", rseq_size);
+       ok(rseq_feature_size >= 20, "rseq_feature_size prior to registration is 20 or greater (%d)", rseq_feature_size);
+       ok(rseq_offset != 0, "rseq_offset prior to registration is not 0 (%td)", rseq_offset);
+
+       rseq_abi = rseq_get_abi();
+       ok((int32_t) rseq_abi->cpu_id == RSEQ_ABI_CPU_ID_UNINITIALIZED,
+                       "rseq->cpu_id is set to RSEQ_ABI_CPU_ID_UNINITIALIZED (%d)",
+                       (int32_t) rseq_abi->cpu_id);
+
+end:
+       exit(exit_status());
+}
diff --git a/tests/unregistered_test_cxx.cpp b/tests/unregistered_test_cxx.cpp
new file mode 100644 (file)
index 0000000..3e401b8
--- /dev/null
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+// SPDX-FileCopyrightText: 2024 EfficiOS Inc.
+
+#include "unregistered_test.c"
This page took 0.030434 seconds and 4 git commands to generate.