Page MenuHomeFreeBSD

D41976.id127813.diff
No OneTemporary

D41976.id127813.diff

diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -80,7 +80,8 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
- SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG |
+ SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
@@ -122,7 +123,8 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
- SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG |
+ SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -1032,10 +1032,10 @@
regcnt--;
}
- if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
- else
- sa->callp = &p->p_sysent->sv_table[sa->code];
+ if (sa->code >= p->p_sysent->sv_size)
+ sa->callp = &nosys_sysent;
+ else
+ sa->callp = &p->p_sysent->sv_table[sa->code];
KASSERT(sa->callp->sy_narg <= nitems(sa->args),
("Too many syscall arguments!"));
@@ -1045,7 +1045,7 @@
if (sa->callp->sy_narg > regcnt) {
params = (caddr_t)frame->tf_rsp + sizeof(register_t);
error = copyin(params, &sa->args[regcnt],
- (sa->callp->sy_narg - regcnt) * sizeof(sa->args[0]));
+ (sa->callp->sy_narg - regcnt) * sizeof(sa->args[0]));
if (__predict_false(error != 0))
return (error);
}
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -183,7 +183,7 @@
params += sizeof(quad_t);
}
if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -159,7 +159,7 @@
if (sa->code >= p->p_sysent->sv_size)
/* nosys */
- sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -531,7 +531,7 @@
if (sa->code >= p->p_sysent->sv_size)
/* nosys */
- sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -87,7 +87,7 @@
.sv_maxssiz = NULL,
.sv_flags =
SV_ASLR | SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER |
- SV_ABI_FREEBSD | SV_ILP32,
+ SV_ABI_FREEBSD | SV_ILP32 | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/arm/arm/syscall.c b/sys/arm/arm/syscall.c
--- a/sys/arm/arm/syscall.c
+++ b/sys/arm/arm/syscall.c
@@ -118,7 +118,7 @@
}
p = td->td_proc;
if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
error = 0;
diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -105,7 +105,7 @@
.sv_fixlimit = NULL, // XXX
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ILP32 | SV_SHP | SV_TIMEKEEP |
- SV_RNG_SEED_VER,
+ SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = freebsd32_set_syscall_retval,
.sv_fetch_syscall_args = freebsd32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
@@ -191,7 +191,7 @@
}
if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c
--- a/sys/arm64/arm64/elf_machdep.c
+++ b/sys/arm64/arm64/elf_machdep.c
@@ -84,7 +84,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_SHP | SV_TIMEKEEP | SV_ABI_FREEBSD | SV_LP64 |
- SV_ASLR | SV_RNG_SEED_VER,
+ SV_ASLR | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -151,7 +151,7 @@
}
if (__predict_false(sa->code >= p->p_sysent->sv_size))
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -127,7 +127,8 @@
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
- SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
+ SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER |
+ SV_DSO_SIG | SV_SIGSYS,
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -75,7 +75,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
- SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -1113,7 +1113,7 @@
}
if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &sysent_nosys;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -91,7 +91,8 @@
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
- .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
+ .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32 |
+ SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
@@ -140,7 +141,8 @@
.sv_setregs = ia32_setregs,
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
- .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32,
+ .sv_flags = SV_ABI_FREEBSD | SV_AOUT | SV_IA32 | SV_ILP32 |
+ SV_SIGSYS,
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
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
@@ -159,6 +159,10 @@
SYSCTL_INT(_kern, OID_AUTO, lognosys, CTLFLAG_RWTUN, &kern_lognosys, 0,
"Log invalid syscalls");
+static int kern_signosys = 1;
+SYSCTL_INT(_kern, OID_AUTO, signosys, CTLFLAG_RWTUN, &kern_signosys, 0,
+ "Send SIGSYS on return from invalid syscall");
+
__read_frequently bool sigfastblock_fetch_always = false;
SYSCTL_BOOL(_kern, OID_AUTO, sigfastblock_fetch_always, CTLFLAG_RWTUN,
&sigfastblock_fetch_always, 0,
@@ -2686,7 +2690,8 @@
audited = AUDIT_SYSCALL_ENTER(sc, td) != 0;
if (!sy_thr_static) {
- error = syscall_thread_enter(td, se);
+ error = syscall_thread_enter(td, &se);
+ sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0;
if (error != 0) {
tsr->ts_ret.sr_error = error;
return;
@@ -4218,9 +4223,11 @@
p = td->td_proc;
- PROC_LOCK(p);
- tdsignal(td, SIGSYS);
- PROC_UNLOCK(p);
+ if (SV_PROC_FLAG(p, SV_SIGSYS) != 0 && kern_signosys) {
+ PROC_LOCK(p);
+ tdsignal(td, SIGSYS);
+ PROC_UNLOCK(p);
+ }
if (kern_lognosys == 1 || kern_lognosys == 3) {
uprintf("pid %d comm %s: nosys %d\n", p->p_pid, p->p_comm,
td->td_sa.code);
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
@@ -61,6 +61,17 @@
return (nosys(td, args));
}
+struct sysent nosys_sysent = {
+ .sy_call = (sy_call_t *)nosys,
+ .sy_systrace_args_func = NULL,
+ .sy_narg = 0,
+ .sy_flags = SYF_CAPENABLED,
+ .sy_auevent = AUE_NULL,
+ .sy_entry = 0, /* DTRACE_IDNONE */
+ .sy_return = 0,
+ .sy_thrcnt = SY_THR_STATIC,
+};
+
static void
syscall_thread_drain(struct sysent *se)
{
@@ -78,19 +89,21 @@
}
int
-syscall_thread_enter(struct thread *td, struct sysent *se)
+syscall_thread_enter(struct thread *td, struct sysent **se)
{
uint32_t cnt, oldcnt;
- KASSERT((se->sy_thrcnt & SY_THR_STATIC) == 0,
+ KASSERT(((*se)->sy_thrcnt & SY_THR_STATIC) == 0,
("%s: not a static syscall", __func__));
do {
- oldcnt = se->sy_thrcnt;
- if ((oldcnt & (SY_THR_DRAINING | SY_THR_ABSENT)) != 0)
- return (ENOSYS);
+ oldcnt = (*se)->sy_thrcnt;
+ if ((oldcnt & (SY_THR_DRAINING | SY_THR_ABSENT)) != 0) {
+ *se = &nosys_sysent;
+ return (0);
+ }
cnt = oldcnt + SY_THR_INCR;
- } while (atomic_cmpset_acq_32(&se->sy_thrcnt, oldcnt, cnt) == 0);
+ } while (atomic_cmpset_acq_32(&(*se)->sy_thrcnt, oldcnt, cnt) == 0);
return (0);
}
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
@@ -144,7 +144,8 @@
AUDIT_SYSCALL_ENTER(sa->code, td) ||
!sy_thr_static)) {
if (!sy_thr_static) {
- error = syscall_thread_enter(td, se);
+ error = syscall_thread_enter(td, &se);
+ sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0;
if (error != 0) {
td->td_errno = error;
goto retval;
diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c
--- a/sys/powerpc/powerpc/elf32_machdep.c
+++ b/sys/powerpc/powerpc/elf32_machdep.c
@@ -124,7 +124,7 @@
#endif
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ILP32 | SV_SHP | SV_ASLR |
- SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c
--- a/sys/powerpc/powerpc/elf64_machdep.c
+++ b/sys/powerpc/powerpc/elf64_machdep.c
@@ -86,7 +86,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_ASLR |
- SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
@@ -128,7 +128,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_LP64 | SV_SHP |
- SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c
--- a/sys/powerpc/powerpc/trap.c
+++ b/sys/powerpc/powerpc/trap.c
@@ -694,7 +694,7 @@
}
if (sa->code >= p->p_sysent->sv_size)
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/riscv/riscv/elf_machdep.c b/sys/riscv/riscv/elf_machdep.c
--- a/sys/riscv/riscv/elf_machdep.c
+++ b/sys/riscv/riscv/elf_machdep.c
@@ -84,7 +84,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_LP64 | SV_SHP | SV_TIMEKEEP |
- SV_ASLR | SV_RNG_SEED_VER,
+ SV_ASLR | SV_RNG_SEED_VER | SV_SIGSYS,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c
--- a/sys/riscv/riscv/trap.c
+++ b/sys/riscv/riscv/trap.c
@@ -115,7 +115,7 @@
}
if (__predict_false(sa->code >= p->p_sysent->sv_size))
- sa->callp = &p->p_sysent->sv_table[0];
+ sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -164,7 +164,7 @@
#define SV_IA32 0x004000 /* Intel 32-bit executable. */
#define SV_AOUT 0x008000 /* a.out executable. */
#define SV_SHP 0x010000 /* Shared page. */
-#define SV_AVAIL1 0x020000 /* Unused */
+#define SV_SIGSYS 0x020000 /* SIGSYS for non-existing syscall */
#define SV_TIMEKEEP 0x040000 /* Shared page timehands. */
#define SV_ASLR 0x080000 /* ASLR allowed. */
#define SV_RNG_SEED_VER 0x100000 /* random(4) reseed generation. */
@@ -191,6 +191,7 @@
extern struct sysentvec aout_sysvec;
extern struct sysent sysent[];
extern const char *syscallnames[];
+extern struct sysent nosys_sysent;
struct nosys_args {
register_t dummy;
@@ -319,7 +320,7 @@
int lkmnosys(struct thread *, struct nosys_args *);
int lkmressys(struct thread *, struct nosys_args *);
-int syscall_thread_enter(struct thread *td, struct sysent *se);
+int syscall_thread_enter(struct thread *td, struct sysent **se);
void syscall_thread_exit(struct thread *td, struct sysent *se);
int shared_page_alloc(int size, int align);
diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile
--- a/tests/sys/kern/Makefile
+++ b/tests/sys/kern/Makefile
@@ -48,6 +48,7 @@
ATF_TESTS_C+= unix_socketpair_test
ATF_TESTS_C+= waitpid_nohang
ATF_TESTS_C+= pdeathsig
+ATF_TESTS_C+= sigsys
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
new file mode 100644
--- /dev/null
+++ b/tests/sys/kern/sigsys.c
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2023 The FreeBSD Foundation
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <sys/syscall.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdatomic.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+static sig_atomic_t sigsys_cnt;
+
+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)
+{
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = sigsys_handler;
+ sa.sa_flags = SA_SIGINFO;
+ ATF_REQUIRE(sigaction(SIGSYS, &sa, NULL) == 0);
+
+ ATF_REQUIRE(syscall(273) == -1); /* reserved */
+ atomic_signal_fence(memory_order_seq_cst);
+ ATF_REQUIRE(sigsys_cnt == 1);
+
+ ATF_REQUIRE(syscall(440) == -1); /* SYS_kse_switchin */
+ atomic_signal_fence(memory_order_seq_cst);
+ ATF_REQUIRE(sigsys_cnt == 2);
+
+ /* Hope this is enough for say next two months */
+ ATF_REQUIRE(syscall(3000000) == -1);
+ atomic_signal_fence(memory_order_seq_cst);
+ ATF_REQUIRE(sigsys_cnt == 3);
+
+ ATF_REQUIRE(syscall(SYS_afs3_syscall) == -1);
+ atomic_signal_fence(memory_order_seq_cst);
+ ATF_REQUIRE(sigsys_cnt == 4);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, sigsys_test);
+ return (atf_no_error());
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 28, 11:52 PM (15 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17834958
Default Alt Text
D41976.id127813.diff (15 KB)

Event Timeline