1 /* $OpenBSD: syscall_mi.h,v 1.25 2020/01/21 16:16:23 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 32 */ 33 34 #include <sys/param.h> 35 #include <sys/pledge.h> 36 #include <sys/tracepoint.h> 37 #include <uvm/uvm_extern.h> 38 39 #ifdef KTRACE 40 #include <sys/ktrace.h> 41 #endif 42 43 #include "dt.h" 44 #if NDT > 0 45 #include <dev/dt/dtvar.h> 46 #endif 47 48 49 /* 50 * The MD setup for a system call has been done; here's the MI part. 51 */ 52 static inline int 53 mi_syscall(struct proc *p, register_t code, const struct sysent *callp, 54 register_t *argp, register_t retval[2]) 55 { 56 uint64_t tval; 57 int lock = !(callp->sy_flags & SY_NOLOCK); 58 int error, pledged; 59 60 /* refresh the thread's cache of the process's creds */ 61 refreshcreds(p); 62 63 #ifdef SYSCALL_DEBUG 64 KERNEL_LOCK(); 65 scdebug_call(p, code, argp); 66 KERNEL_UNLOCK(); 67 #endif 68 TRACEPOINT(raw_syscalls, sys_enter, code, NULL); 69 #if NDT > 0 70 DT_ENTER(syscall, code, callp->sy_argsize, argp); 71 #endif 72 #ifdef KTRACE 73 if (KTRPOINT(p, KTR_SYSCALL)) { 74 KERNEL_LOCK(); 75 ktrsyscall(p, code, callp->sy_argsize, argp); 76 KERNEL_UNLOCK(); 77 } 78 #endif 79 80 /* SP must be within MAP_STACK space */ 81 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), 82 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", 83 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial)) 84 return (EPERM); 85 86 /* PC must be in un-writeable permitted text (sigtramp, libc, ld.so) */ 87 if (!uvm_map_inentry(p, &p->p_pcinentry, PROC_PC(p), 88 "[%s]%d/%d pc=%lx inside %lx-%lx: bogus syscall\n", 89 uvm_map_inentry_pc, p->p_vmspace->vm_map.wserial)) 90 return (EPERM); 91 92 if (lock) 93 KERNEL_LOCK(); 94 pledged = (p->p_p->ps_flags & PS_PLEDGE); 95 if (pledged && (error = pledge_syscall(p, code, &tval))) { 96 if (!lock) 97 KERNEL_LOCK(); 98 error = pledge_fail(p, error, tval); 99 KERNEL_UNLOCK(); 100 return (error); 101 } 102 error = (*callp->sy_call)(p, argp, retval); 103 if (lock) 104 KERNEL_UNLOCK(); 105 106 return (error); 107 } 108 109 /* 110 * Finish MI stuff on return, after the registers have been set 111 */ 112 static inline void 113 mi_syscall_return(struct proc *p, register_t code, int error, 114 const register_t retval[2]) 115 { 116 #ifdef SYSCALL_DEBUG 117 KERNEL_LOCK(); 118 scdebug_ret(p, code, error, retval); 119 KERNEL_UNLOCK(); 120 #endif 121 #if NDT > 0 122 DT_LEAVE(syscall, code, error, retval[0], retval[1]); 123 #endif 124 TRACEPOINT(raw_syscalls, sys_exit, code, NULL); 125 126 userret(p); 127 128 #ifdef KTRACE 129 if (KTRPOINT(p, KTR_SYSRET)) { 130 KERNEL_LOCK(); 131 ktrsysret(p, code, error, retval); 132 KERNEL_UNLOCK(); 133 } 134 #endif 135 } 136 137 /* 138 * Finish MI stuff for a new process/thread to return 139 */ 140 static inline void 141 mi_child_return(struct proc *p) 142 { 143 #if defined(SYSCALL_DEBUG) || defined(KTRACE) || NDT > 0 144 int code = (p->p_flag & P_THREAD) ? SYS___tfork : 145 (p->p_p->ps_flags & PS_PPWAIT) ? SYS_vfork : SYS_fork; 146 const register_t child_retval[2] = { 0, 1 }; 147 #endif 148 149 TRACEPOINT(sched, on__cpu, NULL); 150 151 #ifdef SYSCALL_DEBUG 152 KERNEL_LOCK(); 153 scdebug_ret(p, code, 0, child_retval); 154 KERNEL_UNLOCK(); 155 #endif 156 #if NDT > 0 157 DT_LEAVE(syscall, code, 0, child_retval[0], child_retval[1]); 158 #endif 159 TRACEPOINT(raw_syscalls, sys_exit, code, NULL); 160 161 userret(p); 162 163 #ifdef KTRACE 164 if (KTRPOINT(p, KTR_SYSRET)) { 165 KERNEL_LOCK(); 166 ktrsysret(p, code, 0, child_retval); 167 KERNEL_UNLOCK(); 168 } 169 #endif 170 } 171 172 /* 173 * Do the specific processing necessary for an AST 174 */ 175 static inline void 176 mi_ast(struct proc *p, int resched) 177 { 178 if (p->p_flag & P_OWEUPC) { 179 KERNEL_LOCK(); 180 ADDUPROF(p); 181 KERNEL_UNLOCK(); 182 } 183 if (resched) 184 preempt(); 185 186 /* 187 * XXX could move call to userret() here, but 188 * hppa calls ast() in syscall return and sh calls 189 * it after userret() 190 */ 191 } 192