Index: sys/cddl/dev/systrace/systrace.c =================================================================== --- sys/cddl/dev/systrace/systrace.c +++ sys/cddl/dev/systrace/systrace.c @@ -318,7 +318,7 @@ SYSENT[sysnum].sy_return = id; systrace_enabled_count++; if (systrace_enabled_count == 1) - systrace_enabled = true; + syscall_slow_down(SYSCALL_SLOW_SYSTRACE); } static void @@ -331,7 +331,7 @@ SYSENT[sysnum].sy_return = DTRACE_IDNONE; systrace_enabled_count--; if (systrace_enabled_count == 0) - systrace_enabled = false; + syscall_speed_up(SYSCALL_SLOW_SYSTRACE); } static void Index: sys/kern/kern_dtrace.c =================================================================== --- sys/kern/kern_dtrace.c +++ sys/kern/kern_dtrace.c @@ -56,7 +56,6 @@ dtrace_pid_probe_ptr_t dtrace_pid_probe_ptr; dtrace_return_probe_ptr_t dtrace_return_probe_ptr; -bool __read_frequently systrace_enabled; systrace_probe_func_t systrace_probe_func; /* Return the DTrace process data size compiled in the kernel hooks. */ Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -116,6 +116,7 @@ static int filt_signal(struct knote *kn, long hint); static struct thread *sigtd(struct proc *p, int sig, bool fast_sigblock); static void sigqueue_start(void); +static int sysctl_sigfastblock_check_always(SYSCTL_HANDLER_ARGS); static uma_zone_t ksiginfo_zone = NULL; struct filterops sig_filtops = { @@ -157,9 +158,10 @@ SYSCTL_INT(_kern, OID_AUTO, lognosys, CTLFLAG_RWTUN, &kern_lognosys, 0, "Log invalid syscalls"); -__read_frequently bool sigfastblock_fetch_always = false; -SYSCTL_BOOL(_kern, OID_AUTO, sigfastblock_fetch_always, CTLFLAG_RWTUN, - &sigfastblock_fetch_always, 0, +bool sigfastblock_fetch_always = false; +SYSCTL_PROC(_kern, OID_AUTO, sigfastblock_fetch_always, + CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RW, NULL, 0, + sysctl_sigfastblock_check_always, "U", "Fetch sigfastblock word on each syscall entry for proper " "blocking semantic"); @@ -4247,4 +4249,21 @@ reschedule_signals(p, fastblock_mask, SIGPROCMASK_FASTBLK); PROC_UNLOCK(p); } +} + +static int +sysctl_sigfastblock_check_always(SYSCTL_HANDLER_ARGS) +{ + int error; + + error = sysctl_handle_int(oidp, &sigfastblock_fetch_always, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + if (sigfastblock_fetch_always) + syscall_slow_down(SYSCALL_SLOW_SIGFASTBLOCK); + else + syscall_speed_up(SYSCALL_SLOW_SIGFASTBLOCK); + + return (0); } Index: sys/kern/kern_syscalls.c =================================================================== --- sys/kern/kern_syscalls.c +++ sys/kern/kern_syscalls.c @@ -43,6 +43,8 @@ #include #include +int __read_frequently syscall_slow_path_required = 0; + /* * Acts like "nosys" but can be identified in sysent for dynamic call * number assignment for a limited number of calls. @@ -262,4 +264,18 @@ sd1->registered = 0; } return (0); +} + +void +syscall_slow_down(int id) +{ + + atomic_set_int(&syscall_slow_path_required, id); +} + +void +syscall_speed_up(int id) +{ + + atomic_clear_int(&syscall_slow_path_required, id); } Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -129,22 +129,20 @@ } #endif - /* - * Fetch fast sigblock value at the time of syscall entry to - * handle sleepqueue primitives which might call cursig(). - */ - if (__predict_false(sigfastblock_fetch_always)) - (void)sigfastblock_fetch(td); - /* Let system calls set td_errno directly. */ KASSERT((td->td_pflags & TDP_NERRNO) == 0, ("%s: TDP_NERRNO set", __func__)); sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0; - if (__predict_false(SYSTRACE_ENABLED() || - AUDIT_SYSCALL_ENTER(sa->code, td) || - !sy_thr_static)) { + if (__predict_false(syscall_slow_path_required || !sy_thr_static)) { + /* + * Fetch fast sigblock value at the time of syscall entry to + * handle sleepqueue primitives which might call cursig(). + */ + if (__predict_false(sigfastblock_fetch_always)) + (void)sigfastblock_fetch(td); + if (!sy_thr_static) { error = syscall_thread_enter(td, se); if (error != 0) { Index: sys/security/audit/audit.c =================================================================== --- sys/security/audit/audit.c +++ sys/security/audit/audit.c @@ -227,6 +227,10 @@ #ifdef KDTRACE_HOOKS } #endif + if (audit_syscalls_enabled) + syscall_slow_down(SYSCALL_SLOW_AUDIT); + else + syscall_speed_up(SYSCALL_SLOW_AUDIT); mtx_unlock(&audit_mtx); } Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -55,13 +55,6 @@ #ifdef _KERNEL extern systrace_probe_func_t systrace_probe_func; -extern bool systrace_enabled; - -#ifdef KDTRACE_HOOKS -#define SYSTRACE_ENABLED() (systrace_enabled) -#else -#define SYSTRACE_ENABLED() (0) -#endif #endif /* _KERNEL */ struct sysent { /* system call table */ @@ -310,6 +303,15 @@ #define INIT_SYSENTVEC(name, sv) \ SYSINIT(name, SI_SUB_EXEC, SI_ORDER_ANY, \ (sysinit_cfunc_t)exec_sysvec_init, sv); + +extern int syscall_slow_path_required; + +#define SYSCALL_SLOW_AUDIT 0x01 +#define SYSCALL_SLOW_SYSTRACE 0x02 +#define SYSCALL_SLOW_SIGFASTBLOCK 0x04 + +void syscall_slow_down(int id); +void syscall_speed_up(int id); #endif /* _KERNEL */