10afcac3eSKonstantin Belousov /*-
20afcac3eSKonstantin Belousov * Copyright (c) 2023 The FreeBSD Foundation
30afcac3eSKonstantin Belousov *
40afcac3eSKonstantin Belousov * SPDX-License-Identifier: BSD-2-Clause
50afcac3eSKonstantin Belousov *
60afcac3eSKonstantin Belousov * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
70afcac3eSKonstantin Belousov * under sponsorship from the FreeBSD Foundation.
80afcac3eSKonstantin Belousov */
90afcac3eSKonstantin Belousov
10b67c0ba4SDmitry Chagin #include <sys/param.h>
110afcac3eSKonstantin Belousov #include <sys/syscall.h>
12b67c0ba4SDmitry Chagin #include <sys/sysctl.h>
130afcac3eSKonstantin Belousov
140afcac3eSKonstantin Belousov #include <atf-c.h>
150afcac3eSKonstantin Belousov #include <errno.h>
160afcac3eSKonstantin Belousov #include <signal.h>
170afcac3eSKonstantin Belousov #include <stdatomic.h>
180afcac3eSKonstantin Belousov #include <stdbool.h>
19b67c0ba4SDmitry Chagin #include <stdio.h>
200afcac3eSKonstantin Belousov
210afcac3eSKonstantin Belousov static sig_atomic_t sigsys_cnt;
220afcac3eSKonstantin Belousov
23b67c0ba4SDmitry Chagin #define SAVEDVALUE "savedsignosys"
24b67c0ba4SDmitry Chagin
250afcac3eSKonstantin Belousov static void
sigsys_handler(int signo,siginfo_t * si,void * ucp)260afcac3eSKonstantin Belousov sigsys_handler(int signo, siginfo_t *si, void *ucp)
270afcac3eSKonstantin Belousov {
280afcac3eSKonstantin Belousov sigsys_cnt++;
290afcac3eSKonstantin Belousov }
300afcac3eSKonstantin Belousov
31b67c0ba4SDmitry Chagin static void
sigsys_test(int knob)32b67c0ba4SDmitry Chagin sigsys_test(int knob)
330afcac3eSKonstantin Belousov {
340afcac3eSKonstantin Belousov struct sigaction sa;
350afcac3eSKonstantin Belousov
360afcac3eSKonstantin Belousov memset(&sa, 0, sizeof(sa));
370afcac3eSKonstantin Belousov sa.sa_sigaction = sigsys_handler;
380afcac3eSKonstantin Belousov sa.sa_flags = SA_SIGINFO;
390afcac3eSKonstantin Belousov ATF_REQUIRE(sigaction(SIGSYS, &sa, NULL) == 0);
400afcac3eSKonstantin Belousov
410afcac3eSKonstantin Belousov ATF_REQUIRE(syscall(273) == -1); /* reserved */
420afcac3eSKonstantin Belousov ATF_CHECK_ERRNO(ENOSYS, true);
430afcac3eSKonstantin Belousov atomic_signal_fence(memory_order_seq_cst);
44*09dd7240SKonstantin Belousov ATF_CHECK_EQ(1 * knob, sigsys_cnt);
450afcac3eSKonstantin Belousov
460afcac3eSKonstantin Belousov ATF_REQUIRE(syscall(440) == -1); /* SYS_kse_switchin */
470afcac3eSKonstantin Belousov ATF_CHECK_ERRNO(ENOSYS, true);
480afcac3eSKonstantin Belousov atomic_signal_fence(memory_order_seq_cst);
49*09dd7240SKonstantin Belousov ATF_CHECK_EQ(2 * knob, sigsys_cnt);
500afcac3eSKonstantin Belousov
510afcac3eSKonstantin Belousov /* Hope this is enough for say next two months */
520afcac3eSKonstantin Belousov ATF_REQUIRE(syscall(3000000) == -1);
530afcac3eSKonstantin Belousov ATF_CHECK_ERRNO(ENOSYS, true);
540afcac3eSKonstantin Belousov atomic_signal_fence(memory_order_seq_cst);
55*09dd7240SKonstantin Belousov ATF_CHECK_EQ(3 * knob, sigsys_cnt);
560afcac3eSKonstantin Belousov
570afcac3eSKonstantin Belousov ATF_REQUIRE(syscall(SYS_afs3_syscall) == -1);
580afcac3eSKonstantin Belousov ATF_CHECK_ERRNO(ENOSYS, true);
590afcac3eSKonstantin Belousov atomic_signal_fence(memory_order_seq_cst);
60*09dd7240SKonstantin Belousov ATF_CHECK_EQ(4 * knob, sigsys_cnt);
61b67c0ba4SDmitry Chagin }
62b67c0ba4SDmitry Chagin
63b67c0ba4SDmitry Chagin static void
sysctlset(const char * name,int val)64b67c0ba4SDmitry Chagin sysctlset(const char *name, int val)
65b67c0ba4SDmitry Chagin {
66e53b83a8SGleb Smirnoff size_t oldlen = sizeof(int);
67b67c0ba4SDmitry Chagin int oldval;
68b67c0ba4SDmitry Chagin char buf[80];
69b67c0ba4SDmitry Chagin
70b67c0ba4SDmitry Chagin ATF_REQUIRE(sysctlbyname(name, &oldval, &oldlen, NULL, 0) == 0);
71b67c0ba4SDmitry Chagin
72b67c0ba4SDmitry Chagin /* Store old %name in a symlink for cleanup */
73b67c0ba4SDmitry Chagin snprintf(buf, sizeof(buf), "%d", oldval);
74b67c0ba4SDmitry Chagin ATF_REQUIRE(symlink(buf, SAVEDVALUE) == 0);
75b67c0ba4SDmitry Chagin
76b67c0ba4SDmitry Chagin ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0);
77b67c0ba4SDmitry Chagin }
78b67c0ba4SDmitry Chagin
79b67c0ba4SDmitry Chagin static void
sysctlcleanup(const char * name)80b67c0ba4SDmitry Chagin sysctlcleanup(const char *name)
81b67c0ba4SDmitry Chagin {
82b67c0ba4SDmitry Chagin size_t oldlen;
83b67c0ba4SDmitry Chagin int n, oldval;
84b67c0ba4SDmitry Chagin char buf[80];
85b67c0ba4SDmitry Chagin
86b67c0ba4SDmitry Chagin if ((n = readlink(SAVEDVALUE, buf, sizeof(buf))) > 0) {
87b67c0ba4SDmitry Chagin buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0';
88b67c0ba4SDmitry Chagin if (sscanf(buf, "%d", &oldval) == 1) {
89b67c0ba4SDmitry Chagin oldlen = sizeof(oldval);
90b67c0ba4SDmitry Chagin (void)sysctlbyname(name, NULL, 0,
91b67c0ba4SDmitry Chagin &oldval, oldlen);
92b67c0ba4SDmitry Chagin }
93b67c0ba4SDmitry Chagin }
94b67c0ba4SDmitry Chagin (void)unlink(SAVEDVALUE);
95b67c0ba4SDmitry Chagin }
96b67c0ba4SDmitry Chagin
97b67c0ba4SDmitry Chagin ATF_TC_WITH_CLEANUP(sigsys_test_on);
ATF_TC_HEAD(sigsys_test_on,tc)98b67c0ba4SDmitry Chagin ATF_TC_HEAD(sigsys_test_on, tc)
99b67c0ba4SDmitry Chagin {
100b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
101b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
102b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "descr",
103b67c0ba4SDmitry Chagin "Testing delivery of SIGSYS on invalid syscalls");
104b67c0ba4SDmitry Chagin }
105b67c0ba4SDmitry Chagin
ATF_TC_BODY(sigsys_test_on,tc)106b67c0ba4SDmitry Chagin ATF_TC_BODY(sigsys_test_on, tc)
107b67c0ba4SDmitry Chagin {
108b67c0ba4SDmitry Chagin sysctlset("kern.signosys", 1);
109b67c0ba4SDmitry Chagin sigsys_test(1);
110b67c0ba4SDmitry Chagin }
111b67c0ba4SDmitry Chagin
ATF_TC_CLEANUP(sigsys_test_on,tc)112b67c0ba4SDmitry Chagin ATF_TC_CLEANUP(sigsys_test_on, tc)
113b67c0ba4SDmitry Chagin {
114b67c0ba4SDmitry Chagin sysctlcleanup("kern.signosys");
115b67c0ba4SDmitry Chagin }
116b67c0ba4SDmitry Chagin
117b67c0ba4SDmitry Chagin ATF_TC_WITH_CLEANUP(sigsys_test_off);
ATF_TC_HEAD(sigsys_test_off,tc)118b67c0ba4SDmitry Chagin ATF_TC_HEAD(sigsys_test_off, tc)
119b67c0ba4SDmitry Chagin {
120b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
121b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
122b67c0ba4SDmitry Chagin atf_tc_set_md_var(tc, "descr",
123b67c0ba4SDmitry Chagin "Testing SIGSYS silence on invalid syscalls");
124b67c0ba4SDmitry Chagin }
125b67c0ba4SDmitry Chagin
ATF_TC_BODY(sigsys_test_off,tc)126b67c0ba4SDmitry Chagin ATF_TC_BODY(sigsys_test_off, tc)
127b67c0ba4SDmitry Chagin {
128b67c0ba4SDmitry Chagin sysctlset("kern.signosys", 0);
129b67c0ba4SDmitry Chagin sigsys_test(0);
130b67c0ba4SDmitry Chagin }
131b67c0ba4SDmitry Chagin
ATF_TC_CLEANUP(sigsys_test_off,tc)132b67c0ba4SDmitry Chagin ATF_TC_CLEANUP(sigsys_test_off, tc)
133b67c0ba4SDmitry Chagin {
134b67c0ba4SDmitry Chagin sysctlcleanup("kern.signosys");
1350afcac3eSKonstantin Belousov }
1360afcac3eSKonstantin Belousov
ATF_TP_ADD_TCS(tp)1370afcac3eSKonstantin Belousov ATF_TP_ADD_TCS(tp)
1380afcac3eSKonstantin Belousov {
139b67c0ba4SDmitry Chagin ATF_TP_ADD_TC(tp, sigsys_test_on);
140b67c0ba4SDmitry Chagin ATF_TP_ADD_TC(tp, sigsys_test_off);
1410afcac3eSKonstantin Belousov return (atf_no_error());
1420afcac3eSKonstantin Belousov }
143