The branch stable/13 has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=f9d36fa86cdd458c00c74b8a211d049a560af322
commit f9d36fa86cdd458c00c74b8a211d049a560af322 Author: Dmitry Chagin <dcha...@freebsd.org> AuthorDate: 2023-10-03 07:38:02 +0000 Commit: Dmitry Chagin <dcha...@freebsd.org> CommitDate: 2023-10-10 05:15:57 +0000 tests: Test that SIGSYS is not delivered if kern.signosys knob is off Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D41979 MFC after: 1 week (cherry picked from commit b67c0ba4613861f8245ce835081311aef1c19bae) --- tests/sys/kern/Makefile | 1 + tests/sys/kern/sigsys.c | 101 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index ec2bbd742956..16faeeb40421 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -41,6 +41,7 @@ ATF_TESTS_C+= unix_socketpair_test ATF_TESTS_C+= waitpid_nohang ATF_TESTS_C+= pdeathsig ATF_TESTS_C+= sigsys +TEST_METADATA.sigsys+= is_exclusive="true" ATF_TESTS_SH+= coredump_phnum_test ATF_TESTS_SH+= sonewconn_overflow diff --git a/tests/sys/kern/sigsys.c b/tests/sys/kern/sigsys.c index 75e3816fc158..8554a646ebc6 100644 --- a/tests/sys/kern/sigsys.c +++ b/tests/sys/kern/sigsys.c @@ -7,31 +7,29 @@ * under sponsorship from the FreeBSD Foundation. */ +#include <sys/param.h> #include <sys/syscall.h> +#include <sys/sysctl.h> #include <atf-c.h> #include <errno.h> #include <signal.h> #include <stdatomic.h> #include <stdbool.h> +#include <stdio.h> static sig_atomic_t sigsys_cnt; +#define SAVEDVALUE "savedsignosys" + static void sigsys_handler(int signo, siginfo_t *si, void *ucp) { sigsys_cnt++; } -ATF_TC(sigsys_test); - -ATF_TC_HEAD(sigsys_test, tc) -{ - atf_tc_set_md_var(tc, "descr", - "Testing delivery of SIGSYS on invalid syscalls"); -} - -ATF_TC_BODY(sigsys_test, tc) +static void +sigsys_test(int knob) { struct sigaction sa; @@ -43,27 +41,102 @@ ATF_TC_BODY(sigsys_test, tc) ATF_REQUIRE(syscall(273) == -1); /* reserved */ ATF_CHECK_ERRNO(ENOSYS, true); atomic_signal_fence(memory_order_seq_cst); - ATF_CHECK_EQ(1, sigsys_cnt); + ATF_CHECK_EQ(1 * knob, sigsys_cnt * knob); ATF_REQUIRE(syscall(440) == -1); /* SYS_kse_switchin */ ATF_CHECK_ERRNO(ENOSYS, true); atomic_signal_fence(memory_order_seq_cst); - ATF_CHECK_EQ(2, sigsys_cnt); + ATF_CHECK_EQ(2 * knob, sigsys_cnt * knob); /* Hope this is enough for say next two months */ ATF_REQUIRE(syscall(3000000) == -1); ATF_CHECK_ERRNO(ENOSYS, true); atomic_signal_fence(memory_order_seq_cst); - ATF_CHECK_EQ(3, sigsys_cnt); + ATF_CHECK_EQ(3 * knob, sigsys_cnt * knob); ATF_REQUIRE(syscall(SYS_afs3_syscall) == -1); ATF_CHECK_ERRNO(ENOSYS, true); atomic_signal_fence(memory_order_seq_cst); - ATF_CHECK_EQ(4, sigsys_cnt); + ATF_CHECK_EQ(4 * knob, sigsys_cnt * knob); +} + +static void +sysctlset(const char *name, int val) +{ + size_t oldlen; + int oldval; + char buf[80]; + + ATF_REQUIRE(sysctlbyname(name, &oldval, &oldlen, NULL, 0) == 0); + + /* Store old %name in a symlink for cleanup */ + snprintf(buf, sizeof(buf), "%d", oldval); + ATF_REQUIRE(symlink(buf, SAVEDVALUE) == 0); + + ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0); +} + +static void +sysctlcleanup(const char *name) +{ + size_t oldlen; + int n, oldval; + char buf[80]; + + if ((n = readlink(SAVEDVALUE, buf, sizeof(buf))) > 0) { + buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0'; + if (sscanf(buf, "%d", &oldval) == 1) { + oldlen = sizeof(oldval); + (void)sysctlbyname(name, NULL, 0, + &oldval, oldlen); + } + } + (void)unlink(SAVEDVALUE); +} + +ATF_TC_WITH_CLEANUP(sigsys_test_on); +ATF_TC_HEAD(sigsys_test_on, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); + atf_tc_set_md_var(tc, "descr", + "Testing delivery of SIGSYS on invalid syscalls"); +} + +ATF_TC_BODY(sigsys_test_on, tc) +{ + sysctlset("kern.signosys", 1); + sigsys_test(1); +} + +ATF_TC_CLEANUP(sigsys_test_on, tc) +{ + sysctlcleanup("kern.signosys"); +} + +ATF_TC_WITH_CLEANUP(sigsys_test_off); +ATF_TC_HEAD(sigsys_test_off, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); + atf_tc_set_md_var(tc, "descr", + "Testing SIGSYS silence on invalid syscalls"); +} + +ATF_TC_BODY(sigsys_test_off, tc) +{ + sysctlset("kern.signosys", 0); + sigsys_test(0); +} + +ATF_TC_CLEANUP(sigsys_test_off, tc) +{ + sysctlcleanup("kern.signosys"); } ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, sigsys_test); + ATF_TP_ADD_TC(tp, sigsys_test_on); + ATF_TP_ADD_TC(tp, sigsys_test_off); return (atf_no_error()); }