From: Michael Jeanson Date: Fri, 26 Jul 2024 15:15:44 +0000 (+0000) Subject: Add a test to validate the syscall errors X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=342f99be42b02d29cea1fb185ef2012f29947203;p=librseq.git Add a test to validate the syscall errors Change-Id: Ia589597d23df3fe317a009d409272f4664f0a7e0 Signed-off-by: Michael Jeanson Signed-off-by: Mathieu Desnoyers --- diff --git a/.gitignore b/.gitignore index 3bcfbf4..47ca9cc 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/tests/Makefile.am b/tests/Makefile.am index 2cc71e8..d7f8ea5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 0000000..c9682cf --- /dev/null +++ b/tests/run_syscall_errors_test.tap @@ -0,0 +1,16 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2024 Michael Jeanson + +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 index 0000000..6193501 --- /dev/null +++ b/tests/run_syscall_errors_test_cxx.tap @@ -0,0 +1,16 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2024 Michael Jeanson + +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 index 0000000..a319717 --- /dev/null +++ b/tests/syscall_errors_test.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2024 Michael Jeanson + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include + +#include + +#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 index 0000000..8badeef --- /dev/null +++ b/tests/syscall_errors_test_cxx.cpp @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2024 EfficiOS Inc. + +#include "syscall_errors_test.c"