subr_syscall.c revision 232240
1139749Simp/*- 2126177Srik * Copyright (C) 1994, David Greenman 3126177Srik * Copyright (c) 1990, 1993 4126177Srik * The Regents of the University of California. All rights reserved. 5126177Srik * Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org> 6126177Srik * 7126177Srik * This code is derived from software contributed to Berkeley by 8126177Srik * the University of Utah, and William Jolitz. 9126177Srik * 10126177Srik * Redistribution and use in source and binary forms, with or without 11126177Srik * modification, are permitted provided that the following conditions 12126177Srik * are met: 13126177Srik * 1. Redistributions of source code must retain the above copyright 14126177Srik * notice, this list of conditions and the following disclaimer. 15126177Srik * 2. Redistributions in binary form must reproduce the above copyright 16126177Srik * notice, this list of conditions and the following disclaimer in the 17126177Srik * documentation and/or other materials provided with the distribution. 18126177Srik * 3. All advertising materials mentioning features or use of this software 19126177Srik * must display the following acknowledgement: 20126177Srik * This product includes software developed by the University of 21126177Srik * California, Berkeley and its contributors. 22126177Srik * 4. Neither the name of the University nor the names of its contributors 23126177Srik * may be used to endorse or promote products derived from this software 24126177Srik * without specific prior written permission. 25126177Srik * 26126177Srik * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27126177Srik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28126177Srik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29126177Srik * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30126177Srik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31126177Srik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32126177Srik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33126177Srik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34126177Srik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35126177Srik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36126177Srik * SUCH DAMAGE. 37126177Srik * 38126177Srik * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 39126177Srik */ 40126177Srik 41126177Srik#include "opt_capsicum.h" 42126177Srik#include "opt_ktrace.h" 43126177Srik#include "opt_kdtrace.h" 44126177Srik 45126177Srik__FBSDID("$FreeBSD: head/sys/kern/subr_syscall.c 232240 2012-02-27 21:10:10Z kib $"); 46126177Srik 47126177Srik#include <sys/capability.h> 48126177Srik#include <sys/ktr.h> 49126177Srik#ifdef KTRACE 50126177Srik#include <sys/uio.h> 51126177Srik#include <sys/ktrace.h> 52126177Srik#endif 53126177Srik#include <security/audit/audit.h> 54126177Srik 55126177Srikstatic inline int 56126177Sriksyscallenter(struct thread *td, struct syscall_args *sa) 57126177Srik{ 58126177Srik struct proc *p; 59126177Srik int error, traced; 60126177Srik 61126177Srik PCPU_INC(cnt.v_syscall); 62126177Srik p = td->td_proc; 63126177Srik 64126177Srik td->td_pticks = 0; 65126177Srik if (td->td_ucred != p->p_ucred) 66126177Srik cred_update_thread(td); 67126177Srik if (p->p_flag & P_TRACED) { 68126177Srik traced = 1; 69126177Srik PROC_LOCK(p); 70126177Srik td->td_dbgflags &= ~TDB_USERWR; 71126177Srik td->td_dbgflags |= TDB_SCE; 72126177Srik PROC_UNLOCK(p); 73126177Srik } else 74126177Srik traced = 0; 75126177Srik error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); 76126177Srik#ifdef KTRACE 77126177Srik if (KTRPOINT(td, KTR_SYSCALL)) 78126177Srik ktrsyscall(sa->code, sa->narg, sa->args); 79126177Srik#endif 80126177Srik 81126177Srik CTR6(KTR_SYSC, 82126177Srik"syscall: td=%p pid %d %s (%#lx, %#lx, %#lx)", 83126177Srik td, td->td_proc->p_pid, syscallname(p, sa->code), 84126177Srik sa->args[0], sa->args[1], sa->args[2]); 85126177Srik 86126177Srik if (error == 0) { 87126177Srik STOPEVENT(p, S_SCE, sa->narg); 88126177Srik if (p->p_flag & P_TRACED && p->p_stops & S_PT_SCE) { 89126177Srik PROC_LOCK(p); 90126177Srik ptracestop((td), SIGTRAP); 91126177Srik PROC_UNLOCK(p); 92126177Srik } 93126177Srik if (td->td_dbgflags & TDB_USERWR) { 94126177Srik /* 95126177Srik * Reread syscall number and arguments if 96126177Srik * debugger modified registers or memory. 97126177Srik */ 98126177Srik error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); 99126177Srik#ifdef KTRACE 100126177Srik if (KTRPOINT(td, KTR_SYSCALL)) 101126177Srik ktrsyscall(sa->code, sa->narg, sa->args); 102126177Srik#endif 103126177Srik if (error != 0) 104126177Srik goto retval; 105126177Srik } 106126177Srik 107126177Srik#ifdef CAPABILITY_MODE 108126177Srik /* 109126177Srik * In capability mode, we only allow access to system calls 110126177Srik * flagged with SYF_CAPENABLED. 111126177Srik */ 112126177Srik if (IN_CAPABILITY_MODE(td) && 113126177Srik !(sa->callp->sy_flags & SYF_CAPENABLED)) { 114126177Srik error = ECAPMODE; 115126177Srik goto retval; 116126177Srik } 117126177Srik#endif 118126177Srik 119126177Srik error = syscall_thread_enter(td, sa->callp); 120126177Srik if (error != 0) 121126177Srik goto retval; 122126177Srik 123126177Srik#ifdef KDTRACE_HOOKS 124126177Srik /* 125126177Srik * If the systrace module has registered it's probe 126126177Srik * callback and if there is a probe active for the 127126177Srik * syscall 'entry', process the probe. 128126177Srik */ 129126177Srik if (systrace_probe_func != NULL && sa->callp->sy_entry != 0) 130126177Srik (*systrace_probe_func)(sa->callp->sy_entry, sa->code, 131126177Srik sa->callp, sa->args, 0); 132126177Srik#endif 133126177Srik 134126177Srik AUDIT_SYSCALL_ENTER(sa->code, td); 135126177Srik error = (sa->callp->sy_call)(td, sa->args); 136126177Srik AUDIT_SYSCALL_EXIT(error, td); 137126177Srik 138126177Srik /* Save the latest error return value. */ 139126177Srik td->td_errno = error; 140126177Srik 141126177Srik#ifdef KDTRACE_HOOKS 142126177Srik /* 143126177Srik * If the systrace module has registered it's probe 144126177Srik * callback and if there is a probe active for the 145126177Srik * syscall 'return', process the probe. 146126177Srik */ 147126177Srik if (systrace_probe_func != NULL && sa->callp->sy_return != 0) 148126177Srik (*systrace_probe_func)(sa->callp->sy_return, sa->code, 149126177Srik sa->callp, NULL, (error) ? -1 : td->td_retval[0]); 150126177Srik#endif 151126177Srik syscall_thread_exit(td, sa->callp); 152126177Srik CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx", 153126177Srik p, error, td->td_retval[0], td->td_retval[1]); 154126177Srik } 155126177Srik retval: 156126177Srik if (traced) { 157126177Srik PROC_LOCK(p); 158126177Srik td->td_dbgflags &= ~TDB_SCE; 159126177Srik PROC_UNLOCK(p); 160126177Srik } 161126177Srik (p->p_sysent->sv_set_syscall_retval)(td, error); 162126177Srik return (error); 163126177Srik} 164126177Srik 165126177Srikstatic inline void 166126177Sriksyscallret(struct thread *td, int error, struct syscall_args *sa __unused) 167126177Srik{ 168126177Srik struct proc *p, *p2; 169126177Srik int traced; 170126177Srik 171126177Srik p = td->td_proc; 172126177Srik 173126177Srik /* 174126177Srik * Check for misbehavior. 175126177Srik */ 176126177Srik WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", 177126177Srik syscallname(p, sa->code)); 178126177Srik KASSERT(td->td_critnest == 0, 179126177Srik ("System call %s returning in a critical section", 180126177Srik syscallname(p, sa->code))); 181126177Srik KASSERT(td->td_locks == 0, 182126177Srik ("System call %s returning with %d locks held", 183126177Srik syscallname(p, sa->code), td->td_locks)); 184126177Srik 185126177Srik /* 186126177Srik * Handle reschedule and other end-of-syscall issues 187126177Srik */ 188126177Srik userret(td, td->td_frame); 189126177Srik 190126177Srik CTR4(KTR_SYSC, "syscall %s exit thread %p pid %d proc %s", 191126177Srik syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name); 192126177Srik 193126177Srik#ifdef KTRACE 194126177Srik if (KTRPOINT(td, KTR_SYSRET)) 195126177Srik ktrsysret(sa->code, error, td->td_retval[0]); 196126177Srik#endif 197126177Srik 198126177Srik if (p->p_flag & P_TRACED) { 199126177Srik traced = 1; 200126177Srik PROC_LOCK(p); 201126177Srik td->td_dbgflags |= TDB_SCX; 202126177Srik PROC_UNLOCK(p); 203126177Srik } else 204126177Srik traced = 0; 205126177Srik /* 206126177Srik * This works because errno is findable through the 207126177Srik * register set. If we ever support an emulation where this 208126177Srik * is not the case, this code will need to be revisited. 209126177Srik */ 210126177Srik STOPEVENT(p, S_SCX, sa->code); 211126177Srik if (traced || (td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0) { 212126177Srik PROC_LOCK(p); 213126177Srik /* 214126177Srik * If tracing the execed process, trap to the debugger 215126177Srik * so that breakpoints can be set before the program 216126177Srik * executes. If debugger requested tracing of syscall 217126177Srik * returns, do it now too. 218126177Srik */ 219126177Srik if (traced && 220126177Srik ((td->td_dbgflags & (TDB_FORK | TDB_EXEC)) != 0 || 221126177Srik (p->p_stops & S_PT_SCX) != 0)) 222126177Srik ptracestop(td, SIGTRAP); 223126177Srik td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK); 224126177Srik PROC_UNLOCK(p); 225126177Srik } 226126177Srik 227126177Srik if (td->td_pflags & TDP_RFPPWAIT) { 228126177Srik /* 229126177Srik * Preserve synchronization semantics of vfork. If 230126177Srik * waiting for child to exec or exit, fork set 231126177Srik * P_PPWAIT on child, and there we sleep on our proc 232126177Srik * (in case of exit). 233126177Srik * 234126177Srik * Do it after the ptracestop() above is finished, to 235126177Srik * not block our debugger until child execs or exits 236126177Srik * to finish vfork wait. 237126177Srik */ 238126177Srik td->td_pflags &= ~TDP_RFPPWAIT; 239126177Srik p2 = td->td_rfppwait_p; 240126177Srik PROC_LOCK(p2); 241126177Srik while (p2->p_flag & P_PPWAIT) 242126177Srik cv_wait(&p2->p_pwait, &p2->p_mtx); 243126177Srik PROC_UNLOCK(p2); 244126177Srik } 245126177Srik} 246126177Srik