1*26ccf4f1SKonstantin Belousov /*- 2*26ccf4f1SKonstantin Belousov * Copyright (C) 1994, David Greenman 3*26ccf4f1SKonstantin Belousov * Copyright (c) 1990, 1993 4*26ccf4f1SKonstantin Belousov * The Regents of the University of California. All rights reserved. 5*26ccf4f1SKonstantin Belousov * Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org> 6*26ccf4f1SKonstantin Belousov * 7*26ccf4f1SKonstantin Belousov * This code is derived from software contributed to Berkeley by 8*26ccf4f1SKonstantin Belousov * the University of Utah, and William Jolitz. 9*26ccf4f1SKonstantin Belousov * 10*26ccf4f1SKonstantin Belousov * Redistribution and use in source and binary forms, with or without 11*26ccf4f1SKonstantin Belousov * modification, are permitted provided that the following conditions 12*26ccf4f1SKonstantin Belousov * are met: 13*26ccf4f1SKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 14*26ccf4f1SKonstantin Belousov * notice, this list of conditions and the following disclaimer. 15*26ccf4f1SKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 16*26ccf4f1SKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 17*26ccf4f1SKonstantin Belousov * documentation and/or other materials provided with the distribution. 18*26ccf4f1SKonstantin Belousov * 3. All advertising materials mentioning features or use of this software 19*26ccf4f1SKonstantin Belousov * must display the following acknowledgement: 20*26ccf4f1SKonstantin Belousov * This product includes software developed by the University of 21*26ccf4f1SKonstantin Belousov * California, Berkeley and its contributors. 22*26ccf4f1SKonstantin Belousov * 4. Neither the name of the University nor the names of its contributors 23*26ccf4f1SKonstantin Belousov * may be used to endorse or promote products derived from this software 24*26ccf4f1SKonstantin Belousov * without specific prior written permission. 25*26ccf4f1SKonstantin Belousov * 26*26ccf4f1SKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27*26ccf4f1SKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28*26ccf4f1SKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29*26ccf4f1SKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30*26ccf4f1SKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31*26ccf4f1SKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32*26ccf4f1SKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33*26ccf4f1SKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34*26ccf4f1SKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35*26ccf4f1SKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36*26ccf4f1SKonstantin Belousov * SUCH DAMAGE. 37*26ccf4f1SKonstantin Belousov * 38*26ccf4f1SKonstantin Belousov * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 39*26ccf4f1SKonstantin Belousov */ 40*26ccf4f1SKonstantin Belousov 41*26ccf4f1SKonstantin Belousov #include "opt_capsicum.h" 42*26ccf4f1SKonstantin Belousov #include "opt_ktrace.h" 43*26ccf4f1SKonstantin Belousov #include "opt_kdtrace.h" 44*26ccf4f1SKonstantin Belousov 45*26ccf4f1SKonstantin Belousov __FBSDID("$FreeBSD$"); 46*26ccf4f1SKonstantin Belousov 47*26ccf4f1SKonstantin Belousov #include <sys/capability.h> 48*26ccf4f1SKonstantin Belousov #include <sys/ktr.h> 49*26ccf4f1SKonstantin Belousov #ifdef KTRACE 50*26ccf4f1SKonstantin Belousov #include <sys/uio.h> 51*26ccf4f1SKonstantin Belousov #include <sys/ktrace.h> 52*26ccf4f1SKonstantin Belousov #endif 53*26ccf4f1SKonstantin Belousov #include <security/audit/audit.h> 54*26ccf4f1SKonstantin Belousov 55*26ccf4f1SKonstantin Belousov static inline int 56*26ccf4f1SKonstantin Belousov syscallenter(struct thread *td, struct syscall_args *sa) 57*26ccf4f1SKonstantin Belousov { 58*26ccf4f1SKonstantin Belousov struct proc *p; 59*26ccf4f1SKonstantin Belousov int error, traced; 60*26ccf4f1SKonstantin Belousov 61*26ccf4f1SKonstantin Belousov PCPU_INC(cnt.v_syscall); 62*26ccf4f1SKonstantin Belousov p = td->td_proc; 63*26ccf4f1SKonstantin Belousov 64*26ccf4f1SKonstantin Belousov td->td_pticks = 0; 65*26ccf4f1SKonstantin Belousov if (td->td_ucred != p->p_ucred) 66*26ccf4f1SKonstantin Belousov cred_update_thread(td); 67*26ccf4f1SKonstantin Belousov if (p->p_flag & P_TRACED) { 68*26ccf4f1SKonstantin Belousov traced = 1; 69*26ccf4f1SKonstantin Belousov PROC_LOCK(p); 70*26ccf4f1SKonstantin Belousov td->td_dbgflags &= ~TDB_USERWR; 71*26ccf4f1SKonstantin Belousov td->td_dbgflags |= TDB_SCE; 72*26ccf4f1SKonstantin Belousov PROC_UNLOCK(p); 73*26ccf4f1SKonstantin Belousov } else 74*26ccf4f1SKonstantin Belousov traced = 0; 75*26ccf4f1SKonstantin Belousov error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); 76*26ccf4f1SKonstantin Belousov #ifdef KTRACE 77*26ccf4f1SKonstantin Belousov if (KTRPOINT(td, KTR_SYSCALL)) 78*26ccf4f1SKonstantin Belousov ktrsyscall(sa->code, sa->narg, sa->args); 79*26ccf4f1SKonstantin Belousov #endif 80*26ccf4f1SKonstantin Belousov 81*26ccf4f1SKonstantin Belousov CTR6(KTR_SYSC, 82*26ccf4f1SKonstantin Belousov "syscall: td=%p pid %d %s (%#lx, %#lx, %#lx)", 83*26ccf4f1SKonstantin Belousov td, td->td_proc->p_pid, syscallname(p, sa->code), 84*26ccf4f1SKonstantin Belousov sa->args[0], sa->args[1], sa->args[2]); 85*26ccf4f1SKonstantin Belousov 86*26ccf4f1SKonstantin Belousov if (error == 0) { 87*26ccf4f1SKonstantin Belousov STOPEVENT(p, S_SCE, sa->narg); 88*26ccf4f1SKonstantin Belousov PTRACESTOP_SC(p, td, S_PT_SCE); 89*26ccf4f1SKonstantin Belousov if (td->td_dbgflags & TDB_USERWR) { 90*26ccf4f1SKonstantin Belousov /* 91*26ccf4f1SKonstantin Belousov * Reread syscall number and arguments if 92*26ccf4f1SKonstantin Belousov * debugger modified registers or memory. 93*26ccf4f1SKonstantin Belousov */ 94*26ccf4f1SKonstantin Belousov error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); 95*26ccf4f1SKonstantin Belousov #ifdef KTRACE 96*26ccf4f1SKonstantin Belousov if (KTRPOINT(td, KTR_SYSCALL)) 97*26ccf4f1SKonstantin Belousov ktrsyscall(sa->code, sa->narg, sa->args); 98*26ccf4f1SKonstantin Belousov #endif 99*26ccf4f1SKonstantin Belousov if (error != 0) 100*26ccf4f1SKonstantin Belousov goto retval; 101*26ccf4f1SKonstantin Belousov } 102*26ccf4f1SKonstantin Belousov 103*26ccf4f1SKonstantin Belousov #ifdef CAPABILITY_MODE 104*26ccf4f1SKonstantin Belousov /* 105*26ccf4f1SKonstantin Belousov * In capability mode, we only allow access to system calls 106*26ccf4f1SKonstantin Belousov * flagged with SYF_CAPENABLED. 107*26ccf4f1SKonstantin Belousov */ 108*26ccf4f1SKonstantin Belousov if (IN_CAPABILITY_MODE(td) && 109*26ccf4f1SKonstantin Belousov !(sa->callp->sy_flags & SYF_CAPENABLED)) { 110*26ccf4f1SKonstantin Belousov error = ECAPMODE; 111*26ccf4f1SKonstantin Belousov goto retval; 112*26ccf4f1SKonstantin Belousov } 113*26ccf4f1SKonstantin Belousov #endif 114*26ccf4f1SKonstantin Belousov 115*26ccf4f1SKonstantin Belousov error = syscall_thread_enter(td, sa->callp); 116*26ccf4f1SKonstantin Belousov if (error != 0) 117*26ccf4f1SKonstantin Belousov goto retval; 118*26ccf4f1SKonstantin Belousov 119*26ccf4f1SKonstantin Belousov #ifdef KDTRACE_HOOKS 120*26ccf4f1SKonstantin Belousov /* 121*26ccf4f1SKonstantin Belousov * If the systrace module has registered it's probe 122*26ccf4f1SKonstantin Belousov * callback and if there is a probe active for the 123*26ccf4f1SKonstantin Belousov * syscall 'entry', process the probe. 124*26ccf4f1SKonstantin Belousov */ 125*26ccf4f1SKonstantin Belousov if (systrace_probe_func != NULL && sa->callp->sy_entry != 0) 126*26ccf4f1SKonstantin Belousov (*systrace_probe_func)(sa->callp->sy_entry, sa->code, 127*26ccf4f1SKonstantin Belousov sa->callp, sa->args, 0); 128*26ccf4f1SKonstantin Belousov #endif 129*26ccf4f1SKonstantin Belousov 130*26ccf4f1SKonstantin Belousov AUDIT_SYSCALL_ENTER(sa->code, td); 131*26ccf4f1SKonstantin Belousov error = (sa->callp->sy_call)(td, sa->args); 132*26ccf4f1SKonstantin Belousov AUDIT_SYSCALL_EXIT(error, td); 133*26ccf4f1SKonstantin Belousov 134*26ccf4f1SKonstantin Belousov /* Save the latest error return value. */ 135*26ccf4f1SKonstantin Belousov td->td_errno = error; 136*26ccf4f1SKonstantin Belousov 137*26ccf4f1SKonstantin Belousov #ifdef KDTRACE_HOOKS 138*26ccf4f1SKonstantin Belousov /* 139*26ccf4f1SKonstantin Belousov * If the systrace module has registered it's probe 140*26ccf4f1SKonstantin Belousov * callback and if there is a probe active for the 141*26ccf4f1SKonstantin Belousov * syscall 'return', process the probe. 142*26ccf4f1SKonstantin Belousov */ 143*26ccf4f1SKonstantin Belousov if (systrace_probe_func != NULL && sa->callp->sy_return != 0) 144*26ccf4f1SKonstantin Belousov (*systrace_probe_func)(sa->callp->sy_return, sa->code, 145*26ccf4f1SKonstantin Belousov sa->callp, NULL, (error) ? -1 : td->td_retval[0]); 146*26ccf4f1SKonstantin Belousov #endif 147*26ccf4f1SKonstantin Belousov syscall_thread_exit(td, sa->callp); 148*26ccf4f1SKonstantin Belousov CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx", 149*26ccf4f1SKonstantin Belousov p, error, td->td_retval[0], td->td_retval[1]); 150*26ccf4f1SKonstantin Belousov } 151*26ccf4f1SKonstantin Belousov retval: 152*26ccf4f1SKonstantin Belousov if (traced) { 153*26ccf4f1SKonstantin Belousov PROC_LOCK(p); 154*26ccf4f1SKonstantin Belousov td->td_dbgflags &= ~TDB_SCE; 155*26ccf4f1SKonstantin Belousov PROC_UNLOCK(p); 156*26ccf4f1SKonstantin Belousov } 157*26ccf4f1SKonstantin Belousov (p->p_sysent->sv_set_syscall_retval)(td, error); 158*26ccf4f1SKonstantin Belousov return (error); 159*26ccf4f1SKonstantin Belousov } 160*26ccf4f1SKonstantin Belousov 161*26ccf4f1SKonstantin Belousov static inline void 162*26ccf4f1SKonstantin Belousov syscallret(struct thread *td, int error, struct syscall_args *sa __unused) 163*26ccf4f1SKonstantin Belousov { 164*26ccf4f1SKonstantin Belousov struct proc *p; 165*26ccf4f1SKonstantin Belousov int traced; 166*26ccf4f1SKonstantin Belousov 167*26ccf4f1SKonstantin Belousov p = td->td_proc; 168*26ccf4f1SKonstantin Belousov 169*26ccf4f1SKonstantin Belousov /* 170*26ccf4f1SKonstantin Belousov * Check for misbehavior. 171*26ccf4f1SKonstantin Belousov */ 172*26ccf4f1SKonstantin Belousov WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", 173*26ccf4f1SKonstantin Belousov syscallname(p, sa->code)); 174*26ccf4f1SKonstantin Belousov KASSERT(td->td_critnest == 0, 175*26ccf4f1SKonstantin Belousov ("System call %s returning in a critical section", 176*26ccf4f1SKonstantin Belousov syscallname(p, sa->code))); 177*26ccf4f1SKonstantin Belousov KASSERT(td->td_locks == 0, 178*26ccf4f1SKonstantin Belousov ("System call %s returning with %d locks held", 179*26ccf4f1SKonstantin Belousov syscallname(p, sa->code), td->td_locks)); 180*26ccf4f1SKonstantin Belousov 181*26ccf4f1SKonstantin Belousov /* 182*26ccf4f1SKonstantin Belousov * Handle reschedule and other end-of-syscall issues 183*26ccf4f1SKonstantin Belousov */ 184*26ccf4f1SKonstantin Belousov userret(td, td->td_frame); 185*26ccf4f1SKonstantin Belousov 186*26ccf4f1SKonstantin Belousov CTR4(KTR_SYSC, "syscall %s exit thread %p pid %d proc %s", 187*26ccf4f1SKonstantin Belousov syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name); 188*26ccf4f1SKonstantin Belousov 189*26ccf4f1SKonstantin Belousov #ifdef KTRACE 190*26ccf4f1SKonstantin Belousov if (KTRPOINT(td, KTR_SYSRET)) 191*26ccf4f1SKonstantin Belousov ktrsysret(sa->code, error, td->td_retval[0]); 192*26ccf4f1SKonstantin Belousov #endif 193*26ccf4f1SKonstantin Belousov 194*26ccf4f1SKonstantin Belousov if (p->p_flag & P_TRACED) { 195*26ccf4f1SKonstantin Belousov traced = 1; 196*26ccf4f1SKonstantin Belousov PROC_LOCK(p); 197*26ccf4f1SKonstantin Belousov td->td_dbgflags |= TDB_SCX; 198*26ccf4f1SKonstantin Belousov PROC_UNLOCK(p); 199*26ccf4f1SKonstantin Belousov } else 200*26ccf4f1SKonstantin Belousov traced = 0; 201*26ccf4f1SKonstantin Belousov /* 202*26ccf4f1SKonstantin Belousov * This works because errno is findable through the 203*26ccf4f1SKonstantin Belousov * register set. If we ever support an emulation where this 204*26ccf4f1SKonstantin Belousov * is not the case, this code will need to be revisited. 205*26ccf4f1SKonstantin Belousov */ 206*26ccf4f1SKonstantin Belousov STOPEVENT(p, S_SCX, sa->code); 207*26ccf4f1SKonstantin Belousov PTRACESTOP_SC(p, td, S_PT_SCX); 208*26ccf4f1SKonstantin Belousov if (traced || (td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0) { 209*26ccf4f1SKonstantin Belousov PROC_LOCK(p); 210*26ccf4f1SKonstantin Belousov td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK); 211*26ccf4f1SKonstantin Belousov PROC_UNLOCK(p); 212*26ccf4f1SKonstantin Belousov } 213*26ccf4f1SKonstantin Belousov } 214