diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -4203,6 +4203,13 @@ /* ARGSUSED */ int nosys(struct thread *td, struct nosys_args *args) +{ + + return (kern_nosys(td)); +} + +int +kern_nosys(struct thread *td) { struct proc *p; diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -51,14 +51,14 @@ lkmnosys(struct thread *td, struct nosys_args *args) { - return (nosys(td, args)); + return (kern_nosys(td)); } int lkmressys(struct thread *td, struct nosys_args *args) { - return (nosys(td, args)); + return (kern_nosys(td)); } static void diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -58,7 +58,7 @@ struct syscall_args *sa; struct sysent *se; int error, traced; - bool sy_thr_static; + bool sy_thr_fast; VM_CNT_INC(v_syscall); p = td->td_proc; @@ -138,15 +138,17 @@ KASSERT((td->td_pflags & TDP_NERRNO) == 0, ("%s: TDP_NERRNO set", __func__)); - sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0; + sy_thr_fast = (se->sy_thrcnt & (SY_THR_STATIC|SY_THR_ABSENT)) != 0; if (__predict_false(SYSTRACE_ENABLED() || AUDIT_SYSCALL_ENTER(sa->code, td) || - !sy_thr_static)) { - if (!sy_thr_static) { + !sy_thr_fast)) { + if (!sy_thr_fast) { error = syscall_thread_enter(td, se); if (error != 0) { td->td_errno = error; + if (error == ENOSYS) + (void)kern_nosys(td); goto retval; } } @@ -181,7 +183,7 @@ error ? -1 : td->td_retval[0]); #endif - if (!sy_thr_static) + if (!sy_thr_fast) syscall_thread_exit(td, se); } else { error = (se->sy_call)(td, sa->args); diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -197,6 +197,7 @@ }; int nosys(struct thread *, struct nosys_args *); +int kern_nosys(struct thread *); #define NO_SYSCALL (-1) @@ -222,7 +223,7 @@ .sy_return = 0, \ .sy_flags = 0, \ .sy_thrcnt = 0 \ -} +} #define MAKE_SYSENT(syscallname) \ static struct sysent syscallname##_sysent = SYSENT_INIT_VALS(syscallname); diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -27,6 +27,7 @@ ATF_TESTS_C+= reaper ATF_TESTS_C+= sched_affinity ATF_TESTS_C+= sigaltstack +ATF_TESTS_C+= sigsys ATF_TESTS_C+= sigwait ATF_TESTS_C+= socket_accf ATF_TESTS_C+= socket_msg_trunc diff --git a/tests/sys/kern/sigsys.c b/tests/sys/kern/sigsys.c new file mode 100644 --- /dev/null +++ b/tests/sys/kern/sigsys.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2023 Dmitry Chagin + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include +#include + +static volatile sig_atomic_t signals = 0; +static volatile sig_atomic_t signo = 0; + +static void +handler(int sig) +{ + + signo = sig; + signals++; +} + +ATF_TC(test_sigsys); +ATF_TC_HEAD(test_sigsys, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check SIGSYS"); +} + +ATF_TC_BODY(test_sigsys, tc) +{ + int error; + + ATF_REQUIRE(signal(SIGSYS, handler) != SIG_ERR); + + /* 11 - obsolete execv */ + error = syscall(11, 0, 1); + ATF_REQUIRE(error == -1); + ATF_REQUIRE(errno == ENOSYS); + ATF_REQUIRE(signals == 1); + ATF_REQUIRE(signo == SIGSYS); + + /* loadable syscall */ + signals = signo = 0; + error = syscall(SYS_nfssvc, 0, 1); + ATF_REQUIRE(error == -1); + ATF_REQUIRE(errno == ENOSYS || errno == EINVAL); + ATF_REQUIRE(signals == 0 || signals == 1); + ATF_REQUIRE(signo == SIGSYS || signo == 0); + + /* non-existent syscall */ + signals = signo = 0; + error = syscall(SYS_MAXSYSCALL + 1, 0, 1); + ATF_REQUIRE(error == -1); + ATF_REQUIRE(errno == ENOSYS); + ATF_REQUIRE(signals == 1); + ATF_REQUIRE(signo == SIGSYS); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, test_sigsys); + + return (atf_no_error()); +}