diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index ef38c078963..8114105655f 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -1033,7 +1033,7 @@ cpu_fetch_syscall_args_fallback(struct thread *td, struct syscall_args *sa) } 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/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c index 3fb905ab9e0..c61587a93d1 100644 --- a/sys/amd64/ia32/ia32_syscall.c +++ b/sys/amd64/ia32/ia32_syscall.c @@ -183,7 +183,7 @@ ia32_fetch_syscall_args(struct thread *td) 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/arm/arm/syscall.c b/sys/arm/arm/syscall.c index 57644c02364..c440f501e83 100644 --- a/sys/arm/arm/syscall.c +++ b/sys/arm/arm/syscall.c @@ -118,7 +118,7 @@ cpu_fetch_syscall_args(struct thread *td) } 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 index e1fcb533a8c..9cf1b2e11f8 100644 --- a/sys/arm64/arm64/elf32_machdep.c +++ b/sys/arm64/arm64/elf32_machdep.c @@ -191,7 +191,7 @@ freebsd32_fetch_syscall_args(struct thread *td) } 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/trap.c b/sys/arm64/arm64/trap.c index c3221e9faf9..2dda8cfc4c2 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -151,7 +151,7 @@ cpu_fetch_syscall_args(struct thread *td) } 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/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c index 5f9252accb5..19dd5866ba5 100644 --- a/sys/arm64/linux/linux_sysvec.c +++ b/sys/arm64/linux/linux_sysvec.c @@ -123,7 +123,7 @@ linux_fetch_syscall_args(struct thread *td) sa->original_code = sa->code; /* LINUXTODO: generic syscall? */ 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/i386/i386/trap.c b/sys/i386/i386/trap.c index 172317aead2..d0ee2b30a3c 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -1113,7 +1113,7 @@ cpu_fetch_syscall_args(struct thread *td) } 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/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index fe3e3f74362..a3d445951cc 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -522,7 +522,7 @@ linux_fetch_syscall_args(struct thread *td) 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/kern/kern_sig.c b/sys/kern/kern_sig.c index 964ad2398bd..8d0d2903bac 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2686,7 +2686,8 @@ ptrace_syscallreq(struct thread *td, struct proc *p, 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; diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index 78014a36b34..f923211cb6c 100644 --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -61,6 +61,17 @@ lkmressys(struct thread *td, struct nosys_args *args) 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 @@ syscall_thread_drain(struct sysent *se) } 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 index c0262a1b101..ff13672501b 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -144,7 +144,8 @@ syscallenter(struct thread *td) 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/trap.c b/sys/powerpc/powerpc/trap.c index 1527e813647..7f1a267f5cf 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -694,7 +694,7 @@ cpu_fetch_syscall_args(struct thread *td) } 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/trap.c b/sys/riscv/riscv/trap.c index b855fcc4163..ea48b02ba29 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -115,7 +115,7 @@ cpu_fetch_syscall_args(struct thread *td) } 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 index 3f52848af98..3ef6b06c554 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -191,6 +191,7 @@ struct sysentvec { 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 @@ struct nosys_args; 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);