xref: /freebsd-src/tests/sys/kern/sigsys.c (revision 09dd7240acf1fc50061246013ce318404d70c4e0)
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