1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/param.h> 30*0Sstevel@tonic-gate #include <sys/vmparam.h> 31*0Sstevel@tonic-gate #include <sys/types.h> 32*0Sstevel@tonic-gate #include <sys/sysmacros.h> 33*0Sstevel@tonic-gate #include <sys/systm.h> 34*0Sstevel@tonic-gate #include <sys/signal.h> 35*0Sstevel@tonic-gate #include <sys/stack.h> 36*0Sstevel@tonic-gate #include <sys/cred.h> 37*0Sstevel@tonic-gate #include <sys/cmn_err.h> 38*0Sstevel@tonic-gate #include <sys/user.h> 39*0Sstevel@tonic-gate #include <sys/privregs.h> 40*0Sstevel@tonic-gate #include <sys/psw.h> 41*0Sstevel@tonic-gate #include <sys/debug.h> 42*0Sstevel@tonic-gate #include <sys/errno.h> 43*0Sstevel@tonic-gate #include <sys/proc.h> 44*0Sstevel@tonic-gate #include <sys/modctl.h> 45*0Sstevel@tonic-gate #include <sys/var.h> 46*0Sstevel@tonic-gate #include <sys/inline.h> 47*0Sstevel@tonic-gate #include <sys/syscall.h> 48*0Sstevel@tonic-gate #include <sys/ucontext.h> 49*0Sstevel@tonic-gate #include <sys/cpuvar.h> 50*0Sstevel@tonic-gate #include <sys/siginfo.h> 51*0Sstevel@tonic-gate #include <sys/trap.h> 52*0Sstevel@tonic-gate #include <sys/vtrace.h> 53*0Sstevel@tonic-gate #include <sys/sysinfo.h> 54*0Sstevel@tonic-gate #include <sys/procfs.h> 55*0Sstevel@tonic-gate #include <c2/audit.h> 56*0Sstevel@tonic-gate #include <sys/modctl.h> 57*0Sstevel@tonic-gate #include <sys/aio_impl.h> 58*0Sstevel@tonic-gate #include <sys/tnf.h> 59*0Sstevel@tonic-gate #include <sys/tnf_probe.h> 60*0Sstevel@tonic-gate #include <sys/copyops.h> 61*0Sstevel@tonic-gate #include <sys/priv.h> 62*0Sstevel@tonic-gate #include <sys/msacct.h> 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate int syscalltrace = 0; 65*0Sstevel@tonic-gate #ifdef SYSCALLTRACE 66*0Sstevel@tonic-gate static kmutex_t systrace_lock; /* syscall tracing lock */ 67*0Sstevel@tonic-gate #else 68*0Sstevel@tonic-gate #define syscalltrace 0 69*0Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate typedef int64_t (*llfcn_t)(); /* function returning long long */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate int pre_syscall(void); 74*0Sstevel@tonic-gate void post_syscall(long rval1, long rval2); 75*0Sstevel@tonic-gate static krwlock_t *lock_syscall(struct sysent *, uint_t); 76*0Sstevel@tonic-gate static void deferred_singlestep_trap(caddr_t); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 79*0Sstevel@tonic-gate #define LWP_GETSYSENT(lwp) \ 80*0Sstevel@tonic-gate (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE ? sysent : sysent32) 81*0Sstevel@tonic-gate #else 82*0Sstevel@tonic-gate #define LWP_GETSYSENT(lwp) (sysent) 83*0Sstevel@tonic-gate #endif 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * Arrange for the real time profiling signal to be dispatched. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate void 89*0Sstevel@tonic-gate realsigprof(int sysnum, int error) 90*0Sstevel@tonic-gate { 91*0Sstevel@tonic-gate proc_t *p; 92*0Sstevel@tonic-gate klwp_t *lwp; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate if (curthread->t_rprof->rp_anystate == 0) 95*0Sstevel@tonic-gate return; 96*0Sstevel@tonic-gate p = ttoproc(curthread); 97*0Sstevel@tonic-gate lwp = ttolwp(curthread); 98*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 99*0Sstevel@tonic-gate if (sigismember(&p->p_ignore, SIGPROF) || 100*0Sstevel@tonic-gate signal_is_blocked(curthread, SIGPROF)) { 101*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 102*0Sstevel@tonic-gate return; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate lwp->lwp_siginfo.si_signo = SIGPROF; 105*0Sstevel@tonic-gate lwp->lwp_siginfo.si_code = PROF_SIG; 106*0Sstevel@tonic-gate lwp->lwp_siginfo.si_errno = error; 107*0Sstevel@tonic-gate hrt2ts(gethrtime(), &lwp->lwp_siginfo.si_tstamp); 108*0Sstevel@tonic-gate lwp->lwp_siginfo.si_syscall = sysnum; 109*0Sstevel@tonic-gate lwp->lwp_siginfo.si_nsysarg = (sysnum > 0 && sysnum < NSYSCALL) ? 110*0Sstevel@tonic-gate LWP_GETSYSENT(lwp)[sysnum].sy_narg : 0; 111*0Sstevel@tonic-gate lwp->lwp_siginfo.si_fault = lwp->lwp_lastfault; 112*0Sstevel@tonic-gate lwp->lwp_siginfo.si_faddr = lwp->lwp_lastfaddr; 113*0Sstevel@tonic-gate lwp->lwp_lastfault = 0; 114*0Sstevel@tonic-gate lwp->lwp_lastfaddr = NULL; 115*0Sstevel@tonic-gate sigtoproc(p, curthread, SIGPROF); 116*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 117*0Sstevel@tonic-gate ASSERT(lwp->lwp_cursig == 0); 118*0Sstevel@tonic-gate if (issig(FORREAL)) 119*0Sstevel@tonic-gate psig(); 120*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 121*0Sstevel@tonic-gate lwp->lwp_siginfo.si_signo = 0; 122*0Sstevel@tonic-gate bzero(curthread->t_rprof, sizeof (*curthread->t_rprof)); 123*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * If watchpoints are active, don't make copying in of 128*0Sstevel@tonic-gate * system call arguments take a read watchpoint trap. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate static int 131*0Sstevel@tonic-gate copyin_args(struct regs *rp, long *ap, uint_t nargs) 132*0Sstevel@tonic-gate { 133*0Sstevel@tonic-gate greg_t *sp = 1 + (greg_t *)rp->r_sp; /* skip ret addr */ 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate return (copyin_nowatch(sp, ap, nargs * sizeof (*sp))); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 141*0Sstevel@tonic-gate static int 142*0Sstevel@tonic-gate copyin_args32(struct regs *rp, long *ap, uint_t nargs) 143*0Sstevel@tonic-gate { 144*0Sstevel@tonic-gate greg32_t *sp = 1 + (greg32_t *)rp->r_sp; /* skip ret addr */ 145*0Sstevel@tonic-gate uint32_t a32[MAXSYSARGS]; 146*0Sstevel@tonic-gate int rc; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate if ((rc = copyin_nowatch(sp, a32, nargs * sizeof (*sp))) == 0) { 151*0Sstevel@tonic-gate uint32_t *a32p = &a32[0]; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate while (nargs--) 154*0Sstevel@tonic-gate *ap++ = (ulong_t)*a32p++; 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate return (rc); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate #define COPYIN_ARGS32 copyin_args32 159*0Sstevel@tonic-gate #else 160*0Sstevel@tonic-gate #define COPYIN_ARGS32 copyin_args 161*0Sstevel@tonic-gate #endif 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate /* 164*0Sstevel@tonic-gate * Error handler for system calls where arg copy gets fault. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate static longlong_t 167*0Sstevel@tonic-gate syscall_err() 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate return (0); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* 173*0Sstevel@tonic-gate * Corresponding sysent entry to allow syscall_entry caller 174*0Sstevel@tonic-gate * to invoke syscall_err. 175*0Sstevel@tonic-gate */ 176*0Sstevel@tonic-gate static struct sysent sysent_err = { 177*0Sstevel@tonic-gate 0, SE_32RVAL1, NULL, NULL, (llfcn_t)syscall_err 178*0Sstevel@tonic-gate }; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Called from syscall() when a non-trivial 32-bit system call occurs. 182*0Sstevel@tonic-gate * Sets up the args and returns a pointer to the handler. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate struct sysent * 185*0Sstevel@tonic-gate syscall_entry(kthread_t *t, long *argp) 186*0Sstevel@tonic-gate { 187*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 188*0Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 189*0Sstevel@tonic-gate unsigned int code; 190*0Sstevel@tonic-gate struct sysent *callp; 191*0Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 192*0Sstevel@tonic-gate int error = 0; 193*0Sstevel@tonic-gate uint_t nargs; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate ASSERT(t == curthread && curthread->t_schedflag & TS_DONT_SWAP); 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate lwp->lwp_ru.sysc++; 198*0Sstevel@tonic-gate lwp->lwp_eosys = NORMALRETURN; /* assume this will be normal */ 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate /* 201*0Sstevel@tonic-gate * Set lwp_ap to point to the args, even if none are needed for this 202*0Sstevel@tonic-gate * system call. This is for the loadable-syscall case where the 203*0Sstevel@tonic-gate * number of args won't be known until the system call is loaded, and 204*0Sstevel@tonic-gate * also maintains a non-NULL lwp_ap setup for get_syscall_args(). Note 205*0Sstevel@tonic-gate * that lwp_ap MUST be set to a non-NULL value _BEFORE_ t_sysnum is 206*0Sstevel@tonic-gate * set to non-zero; otherwise get_syscall_args(), seeing a non-zero 207*0Sstevel@tonic-gate * t_sysnum for this thread, will charge ahead and dereference lwp_ap. 208*0Sstevel@tonic-gate */ 209*0Sstevel@tonic-gate lwp->lwp_ap = argp; /* for get_syscall_args */ 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate code = rp->r_r0; 212*0Sstevel@tonic-gate t->t_sysnum = (short)code; 213*0Sstevel@tonic-gate callp = code >= NSYSCALL ? &nosys_ent : se + code; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate if ((t->t_pre_sys | syscalltrace) != 0) { 216*0Sstevel@tonic-gate error = pre_syscall(); 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * Reset lwp_ap so that the args will be refetched if 219*0Sstevel@tonic-gate * the lwp stopped for /proc purposes in pre_syscall(). 220*0Sstevel@tonic-gate */ 221*0Sstevel@tonic-gate lwp->lwp_argsaved = 0; 222*0Sstevel@tonic-gate lwp->lwp_ap = argp; 223*0Sstevel@tonic-gate if (error) 224*0Sstevel@tonic-gate return (&sysent_err); /* use dummy handler */ 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* 228*0Sstevel@tonic-gate * Fetch the system call arguments. 229*0Sstevel@tonic-gate * Note: for loadable system calls the number of arguments required 230*0Sstevel@tonic-gate * may not be known at this point, and will be zero if the system call 231*0Sstevel@tonic-gate * was never loaded. Once the system call has been loaded, the number 232*0Sstevel@tonic-gate * of args is not allowed to be changed. 233*0Sstevel@tonic-gate */ 234*0Sstevel@tonic-gate if ((nargs = (uint_t)callp->sy_narg) != 0 && 235*0Sstevel@tonic-gate COPYIN_ARGS32(rp, argp, nargs)) { 236*0Sstevel@tonic-gate (void) set_errno(EFAULT); 237*0Sstevel@tonic-gate return (&sysent_err); /* use dummy handler */ 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate return (callp); /* return sysent entry for caller */ 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate void 244*0Sstevel@tonic-gate syscall_exit(kthread_t *t, long rval1, long rval2) 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate /* 247*0Sstevel@tonic-gate * Handle signals and other post-call events if necessary. 248*0Sstevel@tonic-gate */ 249*0Sstevel@tonic-gate if ((t->t_post_sys_ast | syscalltrace) == 0) { 250*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 251*0Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Normal return. 255*0Sstevel@tonic-gate * Clear error indication and set return values. 256*0Sstevel@tonic-gate */ 257*0Sstevel@tonic-gate rp->r_ps &= ~PS_C; /* reset carry bit */ 258*0Sstevel@tonic-gate rp->r_r0 = rval1; 259*0Sstevel@tonic-gate rp->r_r1 = rval2; 260*0Sstevel@tonic-gate lwp->lwp_state = LWP_USER; 261*0Sstevel@tonic-gate } else 262*0Sstevel@tonic-gate post_syscall(rval1, rval2); 263*0Sstevel@tonic-gate t->t_sysnum = 0; /* invalidate args */ 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate /* 267*0Sstevel@tonic-gate * Perform pre-system-call processing, including stopping for tracing, 268*0Sstevel@tonic-gate * auditing, etc. 269*0Sstevel@tonic-gate * 270*0Sstevel@tonic-gate * This routine is called only if the t_pre_sys flag is set. Any condition 271*0Sstevel@tonic-gate * requiring pre-syscall handling must set the t_pre_sys flag. If the 272*0Sstevel@tonic-gate * condition is persistent, this routine will repost t_pre_sys. 273*0Sstevel@tonic-gate */ 274*0Sstevel@tonic-gate int 275*0Sstevel@tonic-gate pre_syscall() 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate kthread_t *t = curthread; 278*0Sstevel@tonic-gate unsigned code = t->t_sysnum; 279*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 280*0Sstevel@tonic-gate proc_t *p = ttoproc(t); 281*0Sstevel@tonic-gate int repost; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate t->t_pre_sys = repost = 0; /* clear pre-syscall processing flag */ 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate ASSERT(t->t_schedflag & TS_DONT_SWAP); 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate #if defined(DEBUG) 288*0Sstevel@tonic-gate /* 289*0Sstevel@tonic-gate * On the i386 kernel, lwp_ap points at the piece of the thread 290*0Sstevel@tonic-gate * stack that we copy the users arguments into. 291*0Sstevel@tonic-gate * 292*0Sstevel@tonic-gate * On the amd64 kernel, the syscall arguments in the rdi..r9 293*0Sstevel@tonic-gate * registers should be pointed at by lwp_ap. If the args need to 294*0Sstevel@tonic-gate * be copied so that those registers can be changed without losing 295*0Sstevel@tonic-gate * the ability to get the args for /proc, they can be saved by 296*0Sstevel@tonic-gate * save_syscall_args(), and lwp_ap will be restored by post_syscall(). 297*0Sstevel@tonic-gate */ 298*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 299*0Sstevel@tonic-gate #if defined(_LP64) 300*0Sstevel@tonic-gate ASSERT(lwp->lwp_ap == (long *)&lwptoregs(lwp)->r_rdi); 301*0Sstevel@tonic-gate } else { 302*0Sstevel@tonic-gate #endif 303*0Sstevel@tonic-gate ASSERT((caddr_t)lwp->lwp_ap > t->t_stkbase && 304*0Sstevel@tonic-gate (caddr_t)lwp->lwp_ap < t->t_stk); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate #endif /* DEBUG */ 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate /* 309*0Sstevel@tonic-gate * Make sure the thread is holding the latest credentials for the 310*0Sstevel@tonic-gate * process. The credentials in the process right now apply to this 311*0Sstevel@tonic-gate * thread for the entire system call. 312*0Sstevel@tonic-gate */ 313*0Sstevel@tonic-gate if (t->t_cred != p->p_cred) { 314*0Sstevel@tonic-gate cred_t *oldcred = t->t_cred; 315*0Sstevel@tonic-gate /* 316*0Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred must 317*0Sstevel@tonic-gate * always be either NULL, or point to a valid, allocated cred 318*0Sstevel@tonic-gate * structure. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate t->t_cred = crgetcred(); 321*0Sstevel@tonic-gate crfree(oldcred); 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * From the proc(4) manual page: 326*0Sstevel@tonic-gate * When entry to a system call is being traced, the traced process 327*0Sstevel@tonic-gate * stops after having begun the call to the system but before the 328*0Sstevel@tonic-gate * system call arguments have been fetched from the process. 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate if (PTOU(p)->u_systrap) { 331*0Sstevel@tonic-gate if (prismember(&PTOU(p)->u_entrymask, code)) { 332*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 333*0Sstevel@tonic-gate /* 334*0Sstevel@tonic-gate * Recheck stop condition, now that lock is held. 335*0Sstevel@tonic-gate */ 336*0Sstevel@tonic-gate if (PTOU(p)->u_systrap && 337*0Sstevel@tonic-gate prismember(&PTOU(p)->u_entrymask, code)) { 338*0Sstevel@tonic-gate stop(PR_SYSENTRY, code); 339*0Sstevel@tonic-gate #if defined(_LP64) 340*0Sstevel@tonic-gate /* 341*0Sstevel@tonic-gate * Must refetch args since they were 342*0Sstevel@tonic-gate * possibly modified by /proc. 343*0Sstevel@tonic-gate * Indicate that a valid copy is in registers. 344*0Sstevel@tonic-gate */ 345*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 346*0Sstevel@tonic-gate lwp->lwp_argsaved = 0; 347*0Sstevel@tonic-gate lwp->lwp_ap = 348*0Sstevel@tonic-gate (long *)&lwptoregs(lwp)->r_rdi; 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate #endif 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate repost = 1; 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate if (lwp->lwp_sysabort) { 358*0Sstevel@tonic-gate /* 359*0Sstevel@tonic-gate * lwp_sysabort may have been set via /proc while the process 360*0Sstevel@tonic-gate * was stopped on PR_SYSENTRY. If so, abort the system call. 361*0Sstevel@tonic-gate * Override any error from the copyin() of the arguments. 362*0Sstevel@tonic-gate */ 363*0Sstevel@tonic-gate lwp->lwp_sysabort = 0; 364*0Sstevel@tonic-gate (void) set_errno(EINTR); /* forces post_sys */ 365*0Sstevel@tonic-gate t->t_pre_sys = 1; /* repost anyway */ 366*0Sstevel@tonic-gate return (1); /* don't do system call, return EINTR */ 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate #ifdef C2_AUDIT 370*0Sstevel@tonic-gate if (audit_active) { /* begin auditing for this syscall */ 371*0Sstevel@tonic-gate int error; 372*0Sstevel@tonic-gate if (error = audit_start(T_SYSCALL, code, 0, lwp)) { 373*0Sstevel@tonic-gate t->t_pre_sys = 1; /* repost anyway */ 374*0Sstevel@tonic-gate (void) set_errno(error); 375*0Sstevel@tonic-gate return (1); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate repost = 1; 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate #endif /* C2_AUDIT */ 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate #ifndef NPROBE 382*0Sstevel@tonic-gate /* Kernel probe */ 383*0Sstevel@tonic-gate if (tnf_tracing_active) { 384*0Sstevel@tonic-gate TNF_PROBE_1(syscall_start, "syscall thread", /* CSTYLED */, 385*0Sstevel@tonic-gate tnf_sysnum, sysnum, t->t_sysnum); 386*0Sstevel@tonic-gate t->t_post_sys = 1; /* make sure post_syscall runs */ 387*0Sstevel@tonic-gate repost = 1; 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate #endif /* NPROBE */ 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate #ifdef SYSCALLTRACE 392*0Sstevel@tonic-gate if (syscalltrace) { 393*0Sstevel@tonic-gate int i; 394*0Sstevel@tonic-gate long *ap; 395*0Sstevel@tonic-gate char *cp; 396*0Sstevel@tonic-gate char *sysname; 397*0Sstevel@tonic-gate struct sysent *callp; 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate if (code >= NSYSCALL) 400*0Sstevel@tonic-gate callp = &nosys_ent; /* nosys has no args */ 401*0Sstevel@tonic-gate else 402*0Sstevel@tonic-gate callp = LWP_GETSYSENT(lwp) + code; 403*0Sstevel@tonic-gate (void) save_syscall_args(); 404*0Sstevel@tonic-gate mutex_enter(&systrace_lock); 405*0Sstevel@tonic-gate printf("%d: ", p->p_pid); 406*0Sstevel@tonic-gate if (code >= NSYSCALL) 407*0Sstevel@tonic-gate printf("0x%x", code); 408*0Sstevel@tonic-gate else { 409*0Sstevel@tonic-gate sysname = mod_getsysname(code); 410*0Sstevel@tonic-gate printf("%s[0x%x/0x%p]", sysname == NULL ? "NULL" : 411*0Sstevel@tonic-gate sysname, code, callp->sy_callc); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate cp = "("; 414*0Sstevel@tonic-gate for (i = 0, ap = lwp->lwp_ap; i < callp->sy_narg; i++, ap++) { 415*0Sstevel@tonic-gate printf("%s%lx", cp, *ap); 416*0Sstevel@tonic-gate cp = ", "; 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate if (i) 419*0Sstevel@tonic-gate printf(")"); 420*0Sstevel@tonic-gate printf(" %s id=0x%p\n", PTOU(p)->u_comm, curthread); 421*0Sstevel@tonic-gate mutex_exit(&systrace_lock); 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate /* 426*0Sstevel@tonic-gate * If there was a continuing reason for pre-syscall processing, 427*0Sstevel@tonic-gate * set the t_pre_sys flag for the next system call. 428*0Sstevel@tonic-gate */ 429*0Sstevel@tonic-gate if (repost) 430*0Sstevel@tonic-gate t->t_pre_sys = 1; 431*0Sstevel@tonic-gate lwp->lwp_error = 0; /* for old drivers */ 432*0Sstevel@tonic-gate lwp->lwp_badpriv = PRIV_NONE; 433*0Sstevel@tonic-gate return (0); 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate /* 438*0Sstevel@tonic-gate * Post-syscall processing. Perform abnormal system call completion 439*0Sstevel@tonic-gate * actions such as /proc tracing, profiling, signals, preemption, etc. 440*0Sstevel@tonic-gate * 441*0Sstevel@tonic-gate * This routine is called only if t_post_sys, t_sig_check, or t_astflag is set. 442*0Sstevel@tonic-gate * Any condition requiring pre-syscall handling must set one of these. 443*0Sstevel@tonic-gate * If the condition is persistent, this routine will repost t_post_sys. 444*0Sstevel@tonic-gate */ 445*0Sstevel@tonic-gate void 446*0Sstevel@tonic-gate post_syscall(long rval1, long rval2) 447*0Sstevel@tonic-gate { 448*0Sstevel@tonic-gate kthread_t *t = curthread; 449*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 450*0Sstevel@tonic-gate proc_t *p = ttoproc(t); 451*0Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 452*0Sstevel@tonic-gate uint_t error; 453*0Sstevel@tonic-gate uint_t code = t->t_sysnum; 454*0Sstevel@tonic-gate int repost = 0; 455*0Sstevel@tonic-gate int proc_stop = 0; /* non-zero if stopping */ 456*0Sstevel@tonic-gate int sigprof = 0; /* non-zero if sending SIGPROF */ 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate t->t_post_sys = 0; 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate error = lwp->lwp_errno; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* 463*0Sstevel@tonic-gate * Code can be zero if this is a new LWP returning after a forkall(), 464*0Sstevel@tonic-gate * other than the one which matches the one in the parent which called 465*0Sstevel@tonic-gate * forkall(). In these LWPs, skip most of post-syscall activity. 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate if (code == 0) 468*0Sstevel@tonic-gate goto sig_check; 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate #ifdef C2_AUDIT 471*0Sstevel@tonic-gate if (audit_active) { /* put out audit record for this syscall */ 472*0Sstevel@tonic-gate rval_t rval; 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* XX64 -- truncation of 64-bit return values? */ 475*0Sstevel@tonic-gate rval.r_val1 = (int)rval1; 476*0Sstevel@tonic-gate rval.r_val2 = (int)rval2; 477*0Sstevel@tonic-gate audit_finish(T_SYSCALL, code, error, &rval); 478*0Sstevel@tonic-gate repost = 1; 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate #endif /* C2_AUDIT */ 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate if (curthread->t_pdmsg != NULL) { 483*0Sstevel@tonic-gate char *m = curthread->t_pdmsg; 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate uprintf("%s", m); 486*0Sstevel@tonic-gate kmem_free(m, strlen(m) + 1); 487*0Sstevel@tonic-gate curthread->t_pdmsg = NULL; 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate /* 491*0Sstevel@tonic-gate * If we're going to stop for /proc tracing, set the flag and 492*0Sstevel@tonic-gate * save the arguments so that the return values don't smash them. 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate if (PTOU(p)->u_systrap) { 495*0Sstevel@tonic-gate if (prismember(&PTOU(p)->u_exitmask, code)) { 496*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 497*0Sstevel@tonic-gate (void) save_syscall_args(); 498*0Sstevel@tonic-gate proc_stop = 1; 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate repost = 1; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate /* 504*0Sstevel@tonic-gate * Similarly check to see if SIGPROF might be sent. 505*0Sstevel@tonic-gate */ 506*0Sstevel@tonic-gate if (curthread->t_rprof != NULL && 507*0Sstevel@tonic-gate curthread->t_rprof->rp_anystate != 0) { 508*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 509*0Sstevel@tonic-gate (void) save_syscall_args(); 510*0Sstevel@tonic-gate sigprof = 1; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate if (lwp->lwp_eosys == NORMALRETURN) { 514*0Sstevel@tonic-gate if (error == 0) { 515*0Sstevel@tonic-gate #ifdef SYSCALLTRACE 516*0Sstevel@tonic-gate if (syscalltrace) { 517*0Sstevel@tonic-gate mutex_enter(&systrace_lock); 518*0Sstevel@tonic-gate printf( 519*0Sstevel@tonic-gate "%d: r_val1=0x%lx, r_val2=0x%lx, id 0x%p\n", 520*0Sstevel@tonic-gate p->p_pid, rval1, rval2, curthread); 521*0Sstevel@tonic-gate mutex_exit(&systrace_lock); 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 524*0Sstevel@tonic-gate rp->r_ps &= ~PS_C; 525*0Sstevel@tonic-gate rp->r_r0 = rval1; 526*0Sstevel@tonic-gate rp->r_r1 = rval2; 527*0Sstevel@tonic-gate } else { 528*0Sstevel@tonic-gate int sig; 529*0Sstevel@tonic-gate #ifdef SYSCALLTRACE 530*0Sstevel@tonic-gate if (syscalltrace) { 531*0Sstevel@tonic-gate mutex_enter(&systrace_lock); 532*0Sstevel@tonic-gate printf("%d: error=%d, id 0x%p\n", 533*0Sstevel@tonic-gate p->p_pid, error, curthread); 534*0Sstevel@tonic-gate mutex_exit(&systrace_lock); 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate #endif /* SYSCALLTRACE */ 537*0Sstevel@tonic-gate if (error == EINTR && t->t_activefd.a_stale) 538*0Sstevel@tonic-gate error = EBADF; 539*0Sstevel@tonic-gate if (error == EINTR && 540*0Sstevel@tonic-gate (sig = lwp->lwp_cursig) != 0 && 541*0Sstevel@tonic-gate sigismember(&PTOU(p)->u_sigrestart, sig) && 542*0Sstevel@tonic-gate PTOU(p)->u_signal[sig - 1] != SIG_DFL && 543*0Sstevel@tonic-gate PTOU(p)->u_signal[sig - 1] != SIG_IGN) 544*0Sstevel@tonic-gate error = ERESTART; 545*0Sstevel@tonic-gate rp->r_r0 = error; 546*0Sstevel@tonic-gate rp->r_ps |= PS_C; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate /* 551*0Sstevel@tonic-gate * From the proc(4) manual page: 552*0Sstevel@tonic-gate * When exit from a system call is being traced, the traced process 553*0Sstevel@tonic-gate * stops on completion of the system call just prior to checking for 554*0Sstevel@tonic-gate * signals and returning to user level. At this point all return 555*0Sstevel@tonic-gate * values have been stored into the traced process's saved registers. 556*0Sstevel@tonic-gate */ 557*0Sstevel@tonic-gate if (proc_stop) { 558*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 559*0Sstevel@tonic-gate if (PTOU(p)->u_systrap && 560*0Sstevel@tonic-gate prismember(&PTOU(p)->u_exitmask, code)) 561*0Sstevel@tonic-gate stop(PR_SYSEXIT, code); 562*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* 566*0Sstevel@tonic-gate * If we are the parent returning from a successful 567*0Sstevel@tonic-gate * vfork, wait for the child to exec or exit. 568*0Sstevel@tonic-gate * This code must be here and not in the bowels of the system 569*0Sstevel@tonic-gate * so that /proc can intercept exit from vfork in a timely way. 570*0Sstevel@tonic-gate */ 571*0Sstevel@tonic-gate if (code == SYS_vfork && rp->r_r1 == 0 && error == 0) 572*0Sstevel@tonic-gate vfwait((pid_t)rval1); 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * If profiling is active, bill the current PC in user-land 576*0Sstevel@tonic-gate * and keep reposting until profiling is disabled. 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate if (p->p_prof.pr_scale) { 579*0Sstevel@tonic-gate if (lwp->lwp_oweupc) 580*0Sstevel@tonic-gate profil_tick(rp->r_pc); 581*0Sstevel@tonic-gate repost = 1; 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate sig_check: 585*0Sstevel@tonic-gate /* 586*0Sstevel@tonic-gate * Reset flag for next time. 587*0Sstevel@tonic-gate * We must do this after stopping on PR_SYSEXIT 588*0Sstevel@tonic-gate * because /proc uses the information in lwp_eosys. 589*0Sstevel@tonic-gate */ 590*0Sstevel@tonic-gate lwp->lwp_eosys = NORMALRETURN; 591*0Sstevel@tonic-gate clear_stale_fd(); 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate /* 594*0Sstevel@tonic-gate * If a single-step trap occurred on a syscall (see trap()) 595*0Sstevel@tonic-gate * recognize it now. Do this before checking for signals 596*0Sstevel@tonic-gate * because deferred_singlestep_trap() may generate a SIGTRAP to 597*0Sstevel@tonic-gate * the LWP or may otherwise mark the LWP to call issig(FORREAL). 598*0Sstevel@tonic-gate */ 599*0Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & DEBUG_PENDING) 600*0Sstevel@tonic-gate deferred_singlestep_trap((caddr_t)rp->r_pc); 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate if (t->t_astflag | t->t_sig_check) { 603*0Sstevel@tonic-gate /* 604*0Sstevel@tonic-gate * Turn off the AST flag before checking all the conditions that 605*0Sstevel@tonic-gate * may have caused an AST. This flag is on whenever a signal or 606*0Sstevel@tonic-gate * unusual condition should be handled after the next trap or 607*0Sstevel@tonic-gate * syscall. 608*0Sstevel@tonic-gate */ 609*0Sstevel@tonic-gate astoff(t); 610*0Sstevel@tonic-gate t->t_sig_check = 0; 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 613*0Sstevel@tonic-gate if (curthread->t_proc_flag & TP_CHANGEBIND) { 614*0Sstevel@tonic-gate timer_lwpbind(); 615*0Sstevel@tonic-gate curthread->t_proc_flag &= ~TP_CHANGEBIND; 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate /* 620*0Sstevel@tonic-gate * for kaio requests on the special kaio poll queue, 621*0Sstevel@tonic-gate * copyout their results to user memory. 622*0Sstevel@tonic-gate */ 623*0Sstevel@tonic-gate if (p->p_aio) 624*0Sstevel@tonic-gate aio_cleanup(0); 625*0Sstevel@tonic-gate /* 626*0Sstevel@tonic-gate * If this LWP was asked to hold, call holdlwp(), which will 627*0Sstevel@tonic-gate * stop. holdlwps() sets this up and calls pokelwps() which 628*0Sstevel@tonic-gate * sets the AST flag. 629*0Sstevel@tonic-gate * 630*0Sstevel@tonic-gate * Also check TP_EXITLWP, since this is used by fresh new LWPs 631*0Sstevel@tonic-gate * through lwp_rtt(). That flag is set if the lwp_create(2) 632*0Sstevel@tonic-gate * syscall failed after creating the LWP. 633*0Sstevel@tonic-gate */ 634*0Sstevel@tonic-gate if (ISHOLD(p) || (t->t_proc_flag & TP_EXITLWP)) 635*0Sstevel@tonic-gate holdlwp(); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* 638*0Sstevel@tonic-gate * All code that sets signals and makes ISSIG_PENDING 639*0Sstevel@tonic-gate * evaluate true must set t_sig_check afterwards. 640*0Sstevel@tonic-gate */ 641*0Sstevel@tonic-gate if (ISSIG_PENDING(t, lwp, p)) { 642*0Sstevel@tonic-gate if (issig(FORREAL)) 643*0Sstevel@tonic-gate psig(); 644*0Sstevel@tonic-gate t->t_sig_check = 1; /* recheck next time */ 645*0Sstevel@tonic-gate } 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate if (sigprof) { 648*0Sstevel@tonic-gate realsigprof(code, error); 649*0Sstevel@tonic-gate t->t_sig_check = 1; /* recheck next time */ 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate /* 653*0Sstevel@tonic-gate * If a performance counter overflow interrupt was 654*0Sstevel@tonic-gate * delivered *during* the syscall, then re-enable the 655*0Sstevel@tonic-gate * AST so that we take a trip through trap() to cause 656*0Sstevel@tonic-gate * the SIGEMT to be delivered. 657*0Sstevel@tonic-gate */ 658*0Sstevel@tonic-gate if (lwp->lwp_pcb.pcb_flags & CPC_OVERFLOW) 659*0Sstevel@tonic-gate aston(t); 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate lwp->lwp_errno = 0; /* clear error for next time */ 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate #ifndef NPROBE 665*0Sstevel@tonic-gate /* Kernel probe */ 666*0Sstevel@tonic-gate if (tnf_tracing_active) { 667*0Sstevel@tonic-gate TNF_PROBE_3(syscall_end, "syscall thread", /* CSTYLED */, 668*0Sstevel@tonic-gate tnf_long, rval1, rval1, 669*0Sstevel@tonic-gate tnf_long, rval2, rval2, 670*0Sstevel@tonic-gate tnf_long, errno, (long)error); 671*0Sstevel@tonic-gate repost = 1; 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate #endif /* NPROBE */ 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * Set state to LWP_USER here so preempt won't give us a kernel 677*0Sstevel@tonic-gate * priority if it occurs after this point. Call CL_TRAPRET() to 678*0Sstevel@tonic-gate * restore the user-level priority. 679*0Sstevel@tonic-gate * 680*0Sstevel@tonic-gate * It is important that no locks (other than spinlocks) be entered 681*0Sstevel@tonic-gate * after this point before returning to user mode (unless lwp_state 682*0Sstevel@tonic-gate * is set back to LWP_SYS). 683*0Sstevel@tonic-gate * 684*0Sstevel@tonic-gate * XXX Sampled times past this point are charged to the user. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate lwp->lwp_state = LWP_USER; 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate if (t->t_trapret) { 689*0Sstevel@tonic-gate t->t_trapret = 0; 690*0Sstevel@tonic-gate thread_lock(t); 691*0Sstevel@tonic-gate CL_TRAPRET(t); 692*0Sstevel@tonic-gate thread_unlock(t); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate if (CPU->cpu_runrun) 695*0Sstevel@tonic-gate preempt(); 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate lwp->lwp_errno = 0; /* clear error for next time */ 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate /* 700*0Sstevel@tonic-gate * The thread lock must be held in order to clear sysnum and reset 701*0Sstevel@tonic-gate * lwp_ap atomically with respect to other threads in the system that 702*0Sstevel@tonic-gate * may be looking at the args via lwp_ap from get_syscall_args(). 703*0Sstevel@tonic-gate */ 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate thread_lock(t); 706*0Sstevel@tonic-gate t->t_sysnum = 0; /* no longer in a system call */ 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 709*0Sstevel@tonic-gate #if defined(_LP64) 710*0Sstevel@tonic-gate /* 711*0Sstevel@tonic-gate * In case the args were copied to the lwp, reset the 712*0Sstevel@tonic-gate * pointer so the next syscall will have the right 713*0Sstevel@tonic-gate * lwp_ap pointer. 714*0Sstevel@tonic-gate */ 715*0Sstevel@tonic-gate lwp->lwp_ap = (long *)&rp->r_rdi; 716*0Sstevel@tonic-gate } else { 717*0Sstevel@tonic-gate #endif 718*0Sstevel@tonic-gate lwp->lwp_ap = NULL; /* reset on every syscall entry */ 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate thread_unlock(t); 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate lwp->lwp_argsaved = 0; 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* 725*0Sstevel@tonic-gate * If there was a continuing reason for post-syscall processing, 726*0Sstevel@tonic-gate * set the t_post_sys flag for the next system call. 727*0Sstevel@tonic-gate */ 728*0Sstevel@tonic-gate if (repost) 729*0Sstevel@tonic-gate t->t_post_sys = 1; 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate /* 732*0Sstevel@tonic-gate * If there is a ustack registered for this lwp, and the stack rlimit 733*0Sstevel@tonic-gate * has been altered, read in the ustack. If the saved stack rlimit 734*0Sstevel@tonic-gate * matches the bounds of the ustack, update the ustack to reflect 735*0Sstevel@tonic-gate * the new rlimit. If the new stack rlimit is RLIM_INFINITY, disable 736*0Sstevel@tonic-gate * stack checking by setting the size to 0. 737*0Sstevel@tonic-gate */ 738*0Sstevel@tonic-gate if (lwp->lwp_ustack != 0 && lwp->lwp_old_stk_ctl != 0) { 739*0Sstevel@tonic-gate rlim64_t new_size; 740*0Sstevel@tonic-gate caddr_t top; 741*0Sstevel@tonic-gate stack_t stk; 742*0Sstevel@tonic-gate struct rlimit64 rl; 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate mutex_enter(&p->p_lock); 745*0Sstevel@tonic-gate new_size = p->p_stk_ctl; 746*0Sstevel@tonic-gate top = p->p_usrstack; 747*0Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[RLIMIT_STACK], p, &rl); 748*0Sstevel@tonic-gate mutex_exit(&p->p_lock); 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate if (rl.rlim_cur == RLIM64_INFINITY) 751*0Sstevel@tonic-gate new_size = 0; 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate if (copyin((stack_t *)lwp->lwp_ustack, &stk, 754*0Sstevel@tonic-gate sizeof (stack_t)) == 0 && 755*0Sstevel@tonic-gate (stk.ss_size == lwp->lwp_old_stk_ctl || 756*0Sstevel@tonic-gate stk.ss_size == 0) && 757*0Sstevel@tonic-gate stk.ss_sp == top - stk.ss_size) { 758*0Sstevel@tonic-gate stk.ss_sp = (void *)((uintptr_t)stk.ss_sp + 759*0Sstevel@tonic-gate stk.ss_size - (uintptr_t)new_size); 760*0Sstevel@tonic-gate stk.ss_size = new_size; 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate (void) copyout(&stk, (stack_t *)lwp->lwp_ustack, 763*0Sstevel@tonic-gate sizeof (stack_t)); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate lwp->lwp_old_stk_ctl = 0; 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate /* 771*0Sstevel@tonic-gate * Called from post_syscall() when a deferred singlestep is to be taken. 772*0Sstevel@tonic-gate */ 773*0Sstevel@tonic-gate static void 774*0Sstevel@tonic-gate deferred_singlestep_trap(caddr_t pc) 775*0Sstevel@tonic-gate { 776*0Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 777*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 778*0Sstevel@tonic-gate pcb_t *pcb = &lwp->lwp_pcb; 779*0Sstevel@tonic-gate uint_t fault = 0; 780*0Sstevel@tonic-gate k_siginfo_t siginfo; 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo)); 783*0Sstevel@tonic-gate 784*0Sstevel@tonic-gate /* 785*0Sstevel@tonic-gate * If both NORMAL_STEP and WATCH_STEP are in 786*0Sstevel@tonic-gate * effect, give precedence to NORMAL_STEP. 787*0Sstevel@tonic-gate * If neither is set, user must have set the 788*0Sstevel@tonic-gate * PS_T bit in %efl; treat this as NORMAL_STEP. 789*0Sstevel@tonic-gate */ 790*0Sstevel@tonic-gate if ((pcb->pcb_flags & NORMAL_STEP) || 791*0Sstevel@tonic-gate !(pcb->pcb_flags & WATCH_STEP)) { 792*0Sstevel@tonic-gate siginfo.si_signo = SIGTRAP; 793*0Sstevel@tonic-gate siginfo.si_code = TRAP_TRACE; 794*0Sstevel@tonic-gate siginfo.si_addr = pc; 795*0Sstevel@tonic-gate fault = FLTTRACE; 796*0Sstevel@tonic-gate if (pcb->pcb_flags & WATCH_STEP) 797*0Sstevel@tonic-gate (void) undo_watch_step(NULL); 798*0Sstevel@tonic-gate } else { 799*0Sstevel@tonic-gate fault = undo_watch_step(&siginfo); 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate pcb->pcb_flags &= ~(DEBUG_PENDING|NORMAL_STEP|WATCH_STEP); 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate if (fault) { 804*0Sstevel@tonic-gate /* 805*0Sstevel@tonic-gate * Remember the fault and fault adddress 806*0Sstevel@tonic-gate * for real-time (SIGPROF) profiling. 807*0Sstevel@tonic-gate */ 808*0Sstevel@tonic-gate lwp->lwp_lastfault = fault; 809*0Sstevel@tonic-gate lwp->lwp_lastfaddr = siginfo.si_addr; 810*0Sstevel@tonic-gate /* 811*0Sstevel@tonic-gate * If a debugger has declared this fault to be an 812*0Sstevel@tonic-gate * event of interest, stop the lwp. Otherwise just 813*0Sstevel@tonic-gate * deliver the associated signal. 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate if (prismember(&p->p_fltmask, fault) && 816*0Sstevel@tonic-gate stop_on_fault(fault, &siginfo) == 0) 817*0Sstevel@tonic-gate siginfo.si_signo = 0; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate if (siginfo.si_signo) 821*0Sstevel@tonic-gate trapsig(&siginfo, 1); 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* 825*0Sstevel@tonic-gate * nonexistent system call-- signal lwp (may want to handle it) 826*0Sstevel@tonic-gate * flag error if lwp won't see signal immediately 827*0Sstevel@tonic-gate */ 828*0Sstevel@tonic-gate int64_t 829*0Sstevel@tonic-gate nosys() 830*0Sstevel@tonic-gate { 831*0Sstevel@tonic-gate tsignal(curthread, SIGSYS); 832*0Sstevel@tonic-gate return (set_errno(ENOSYS)); 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 836*0Sstevel@tonic-gate /* 837*0Sstevel@tonic-gate * Execute a 32-bit system call on behalf of the current thread. 838*0Sstevel@tonic-gate */ 839*0Sstevel@tonic-gate void 840*0Sstevel@tonic-gate dosyscall(void) 841*0Sstevel@tonic-gate { 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * Need space on the stack to store syscall arguments. 844*0Sstevel@tonic-gate */ 845*0Sstevel@tonic-gate long syscall_args[MAXSYSARGS]; 846*0Sstevel@tonic-gate struct sysent *se; 847*0Sstevel@tonic-gate int64_t ret; 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate syscall_mstate(LMS_TRAP, LMS_SYSTEM); 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate ASSERT(curproc->p_model == DATAMODEL_ILP32); 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate CPU_STATS_ENTER_K(); 854*0Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, syscall, 1); 855*0Sstevel@tonic-gate CPU_STATS_EXIT_K(); 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate se = syscall_entry(curthread, syscall_args); 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate /* 860*0Sstevel@tonic-gate * syscall_entry() copied all 8 arguments into syscall_args. 861*0Sstevel@tonic-gate */ 862*0Sstevel@tonic-gate ret = se->sy_callc(syscall_args[0], syscall_args[1], syscall_args[2], 863*0Sstevel@tonic-gate syscall_args[3], syscall_args[4], syscall_args[5], syscall_args[6], 864*0Sstevel@tonic-gate syscall_args[7]); 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate syscall_exit(curthread, (int)ret & 0xffffffffu, (int)(ret >> 32)); 867*0Sstevel@tonic-gate syscall_mstate(LMS_SYSTEM, LMS_TRAP); 868*0Sstevel@tonic-gate } 869*0Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* 872*0Sstevel@tonic-gate * Get the arguments to the current system call. See comment atop 873*0Sstevel@tonic-gate * save_syscall_args() regarding lwp_ap usage. 874*0Sstevel@tonic-gate */ 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate uint_t 877*0Sstevel@tonic-gate get_syscall_args(klwp_t *lwp, long *argp, int *nargsp) 878*0Sstevel@tonic-gate { 879*0Sstevel@tonic-gate kthread_t *t = lwptot(lwp); 880*0Sstevel@tonic-gate ulong_t mask = 0xfffffffful; 881*0Sstevel@tonic-gate uint_t code; 882*0Sstevel@tonic-gate long *ap; 883*0Sstevel@tonic-gate int nargs; 884*0Sstevel@tonic-gate 885*0Sstevel@tonic-gate #if defined(_LP64) 886*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) 887*0Sstevel@tonic-gate mask = 0xfffffffffffffffful; 888*0Sstevel@tonic-gate #endif 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate /* 891*0Sstevel@tonic-gate * The thread lock must be held while looking at the arguments to ensure 892*0Sstevel@tonic-gate * they don't go away via post_syscall(). 893*0Sstevel@tonic-gate * get_syscall_args() is the only routine to read them which is callable 894*0Sstevel@tonic-gate * outside the LWP in question and hence the only one that must be 895*0Sstevel@tonic-gate * synchronized in this manner. 896*0Sstevel@tonic-gate */ 897*0Sstevel@tonic-gate thread_lock(t); 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate code = t->t_sysnum; 900*0Sstevel@tonic-gate ap = lwp->lwp_ap; 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate thread_unlock(t); 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate if (code != 0 && code < NSYSCALL) { 905*0Sstevel@tonic-gate nargs = LWP_GETSYSENT(lwp)[code].sy_narg; 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate *nargsp = nargs; 910*0Sstevel@tonic-gate while (nargs-- > 0) 911*0Sstevel@tonic-gate *argp++ = *ap++ & mask; 912*0Sstevel@tonic-gate } else { 913*0Sstevel@tonic-gate *nargsp = 0; 914*0Sstevel@tonic-gate } 915*0Sstevel@tonic-gate 916*0Sstevel@tonic-gate return (code); 917*0Sstevel@tonic-gate } 918*0Sstevel@tonic-gate 919*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 920*0Sstevel@tonic-gate /* 921*0Sstevel@tonic-gate * Get the arguments to the current 32-bit system call. 922*0Sstevel@tonic-gate */ 923*0Sstevel@tonic-gate uint_t 924*0Sstevel@tonic-gate get_syscall32_args(klwp_t *lwp, int *argp, int *nargsp) 925*0Sstevel@tonic-gate { 926*0Sstevel@tonic-gate long args[MAXSYSARGS]; 927*0Sstevel@tonic-gate uint_t i, code; 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate code = get_syscall_args(lwp, args, nargsp); 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate for (i = 0; i != *nargsp; i++) 932*0Sstevel@tonic-gate *argp++ = (int)args[i]; 933*0Sstevel@tonic-gate return (code); 934*0Sstevel@tonic-gate } 935*0Sstevel@tonic-gate #endif 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* 938*0Sstevel@tonic-gate * Save the system call arguments in a safe place. 939*0Sstevel@tonic-gate * 940*0Sstevel@tonic-gate * On the i386 kernel: 941*0Sstevel@tonic-gate * 942*0Sstevel@tonic-gate * Copy the users args prior to changing the stack or stack pointer. 943*0Sstevel@tonic-gate * This is so /proc will be able to get a valid copy of the 944*0Sstevel@tonic-gate * args from the user stack even after the user stack has been changed. 945*0Sstevel@tonic-gate * Note that the kernel stack copy of the args may also have been 946*0Sstevel@tonic-gate * changed by a system call handler which takes C-style arguments. 947*0Sstevel@tonic-gate * 948*0Sstevel@tonic-gate * Note that this may be called by stop() from trap(). In that case 949*0Sstevel@tonic-gate * t_sysnum will be zero (syscall_exit clears it), so no args will be 950*0Sstevel@tonic-gate * copied. 951*0Sstevel@tonic-gate * 952*0Sstevel@tonic-gate * On the amd64 kernel: 953*0Sstevel@tonic-gate * 954*0Sstevel@tonic-gate * For 64-bit applications, lwp->lwp_ap normally points to %rdi..%r9 955*0Sstevel@tonic-gate * in the reg structure. If the user is going to change the argument 956*0Sstevel@tonic-gate * registers, rax, or the stack and might want to get the args (for 957*0Sstevel@tonic-gate * /proc tracing), it must copy the args elsewhere via save_syscall_args(). 958*0Sstevel@tonic-gate * 959*0Sstevel@tonic-gate * For 32-bit applications, lwp->lwp_ap normally points to a copy of 960*0Sstevel@tonic-gate * the system call arguments on the kernel stack made from the user 961*0Sstevel@tonic-gate * stack. Copy the args prior to change the stack or stack pointer. 962*0Sstevel@tonic-gate * This is so /proc will be able to get a valid copy of the args 963*0Sstevel@tonic-gate * from the user stack even after that stack has been changed. 964*0Sstevel@tonic-gate * 965*0Sstevel@tonic-gate * This may be called from stop() even when we're not in a system call. 966*0Sstevel@tonic-gate * Since there's no easy way to tell, this must be safe (not panic). 967*0Sstevel@tonic-gate * If the copyins get data faults, return non-zero. 968*0Sstevel@tonic-gate */ 969*0Sstevel@tonic-gate int 970*0Sstevel@tonic-gate save_syscall_args() 971*0Sstevel@tonic-gate { 972*0Sstevel@tonic-gate kthread_t *t = curthread; 973*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 974*0Sstevel@tonic-gate uint_t code = t->t_sysnum; 975*0Sstevel@tonic-gate uint_t nargs; 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate if (lwp->lwp_argsaved || code == 0) 978*0Sstevel@tonic-gate return (0); /* args already saved or not needed */ 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate if (code >= NSYSCALL) { 981*0Sstevel@tonic-gate nargs = 0; /* illegal syscall */ 982*0Sstevel@tonic-gate } else { 983*0Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 984*0Sstevel@tonic-gate struct sysent *callp = se + code; 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate nargs = callp->sy_narg; 987*0Sstevel@tonic-gate if (LOADABLE_SYSCALL(callp) && nargs == 0) { 988*0Sstevel@tonic-gate krwlock_t *module_lock; 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate /* 991*0Sstevel@tonic-gate * Find out how many arguments the system 992*0Sstevel@tonic-gate * call uses. 993*0Sstevel@tonic-gate * 994*0Sstevel@tonic-gate * We have the property that loaded syscalls 995*0Sstevel@tonic-gate * never change the number of arguments they 996*0Sstevel@tonic-gate * use after they've been loaded once. This 997*0Sstevel@tonic-gate * allows us to stop for /proc tracing without 998*0Sstevel@tonic-gate * holding the module lock. 999*0Sstevel@tonic-gate * /proc is assured that sy_narg is valid. 1000*0Sstevel@tonic-gate */ 1001*0Sstevel@tonic-gate module_lock = lock_syscall(se, code); 1002*0Sstevel@tonic-gate nargs = callp->sy_narg; 1003*0Sstevel@tonic-gate rw_exit(module_lock); 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate /* 1008*0Sstevel@tonic-gate * Fetch the system call arguments. 1009*0Sstevel@tonic-gate */ 1010*0Sstevel@tonic-gate if (nargs == 0) 1011*0Sstevel@tonic-gate goto out; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate ASSERT(nargs <= MAXSYSARGS); 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 1016*0Sstevel@tonic-gate #if defined(_LP64) 1017*0Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate lwp->lwp_arg[0] = rp->r_rdi; 1020*0Sstevel@tonic-gate lwp->lwp_arg[1] = rp->r_rsi; 1021*0Sstevel@tonic-gate lwp->lwp_arg[2] = rp->r_rdx; 1022*0Sstevel@tonic-gate lwp->lwp_arg[3] = rp->r_rcx; 1023*0Sstevel@tonic-gate lwp->lwp_arg[4] = rp->r_r8; 1024*0Sstevel@tonic-gate lwp->lwp_arg[5] = rp->r_r9; 1025*0Sstevel@tonic-gate if (nargs > 6 && copyin_args(rp, &lwp->lwp_arg[6], nargs - 6)) 1026*0Sstevel@tonic-gate return (-1); 1027*0Sstevel@tonic-gate } else { 1028*0Sstevel@tonic-gate #endif 1029*0Sstevel@tonic-gate if (COPYIN_ARGS32(lwptoregs(lwp), lwp->lwp_arg, nargs)) 1030*0Sstevel@tonic-gate return (-1); 1031*0Sstevel@tonic-gate } 1032*0Sstevel@tonic-gate out: 1033*0Sstevel@tonic-gate lwp->lwp_ap = lwp->lwp_arg; 1034*0Sstevel@tonic-gate lwp->lwp_argsaved = 1; 1035*0Sstevel@tonic-gate t->t_post_sys = 1; /* so lwp_ap will be reset */ 1036*0Sstevel@tonic-gate return (0); 1037*0Sstevel@tonic-gate } 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate void 1040*0Sstevel@tonic-gate reset_syscall_args(void) 1041*0Sstevel@tonic-gate { 1042*0Sstevel@tonic-gate ttolwp(curthread)->lwp_argsaved = 0; 1043*0Sstevel@tonic-gate } 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate /* 1046*0Sstevel@tonic-gate * Call a system call which takes a pointer to the user args struct and 1047*0Sstevel@tonic-gate * a pointer to the return values. This is a bit slower than the standard 1048*0Sstevel@tonic-gate * C arg-passing method in some cases. 1049*0Sstevel@tonic-gate */ 1050*0Sstevel@tonic-gate int64_t 1051*0Sstevel@tonic-gate syscall_ap(void) 1052*0Sstevel@tonic-gate { 1053*0Sstevel@tonic-gate uint_t error; 1054*0Sstevel@tonic-gate struct sysent *callp; 1055*0Sstevel@tonic-gate rval_t rval; 1056*0Sstevel@tonic-gate kthread_t *t = curthread; 1057*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(t); 1058*0Sstevel@tonic-gate struct regs *rp = lwptoregs(lwp); 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate callp = LWP_GETSYSENT(lwp) + t->t_sysnum; 1061*0Sstevel@tonic-gate 1062*0Sstevel@tonic-gate #if defined(__amd64) 1063*0Sstevel@tonic-gate /* 1064*0Sstevel@tonic-gate * If the arguments don't fit in registers %rdi-%r9, make sure they 1065*0Sstevel@tonic-gate * have been copied to the lwp_arg array. 1066*0Sstevel@tonic-gate */ 1067*0Sstevel@tonic-gate if (callp->sy_narg > 6 && save_syscall_args()) 1068*0Sstevel@tonic-gate return ((int64_t)set_errno(EFAULT)); 1069*0Sstevel@tonic-gate #endif 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate rval.r_val1 = 0; 1072*0Sstevel@tonic-gate rval.r_val2 = rp->r_r1; 1073*0Sstevel@tonic-gate lwp->lwp_error = 0; /* for old drivers */ 1074*0Sstevel@tonic-gate error = (*(callp->sy_call))(lwp->lwp_ap, &rval); 1075*0Sstevel@tonic-gate if (error) 1076*0Sstevel@tonic-gate return ((longlong_t)set_errno(error)); 1077*0Sstevel@tonic-gate return (rval.r_vals); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate /* 1081*0Sstevel@tonic-gate * Load system call module. 1082*0Sstevel@tonic-gate * Returns with pointer to held read lock for module. 1083*0Sstevel@tonic-gate */ 1084*0Sstevel@tonic-gate static krwlock_t * 1085*0Sstevel@tonic-gate lock_syscall(struct sysent *table, uint_t code) 1086*0Sstevel@tonic-gate { 1087*0Sstevel@tonic-gate krwlock_t *module_lock; 1088*0Sstevel@tonic-gate struct modctl *modp; 1089*0Sstevel@tonic-gate int id; 1090*0Sstevel@tonic-gate struct sysent *callp; 1091*0Sstevel@tonic-gate 1092*0Sstevel@tonic-gate callp = table + code; 1093*0Sstevel@tonic-gate module_lock = callp->sy_lock; 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate /* 1096*0Sstevel@tonic-gate * Optimization to only call modload if we don't have a loaded 1097*0Sstevel@tonic-gate * syscall. 1098*0Sstevel@tonic-gate */ 1099*0Sstevel@tonic-gate rw_enter(module_lock, RW_READER); 1100*0Sstevel@tonic-gate if (LOADED_SYSCALL(callp)) 1101*0Sstevel@tonic-gate return (module_lock); 1102*0Sstevel@tonic-gate rw_exit(module_lock); 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate for (;;) { 1105*0Sstevel@tonic-gate if ((id = modload("sys", syscallnames[code])) == -1) 1106*0Sstevel@tonic-gate break; 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate /* 1109*0Sstevel@tonic-gate * If we loaded successfully at least once, the modctl 1110*0Sstevel@tonic-gate * will still be valid, so we try to grab it by filename. 1111*0Sstevel@tonic-gate * If this call fails, it's because the mod_filename 1112*0Sstevel@tonic-gate * was changed after the call to modload() (mod_hold_by_name() 1113*0Sstevel@tonic-gate * is the likely culprit). We can safely just take 1114*0Sstevel@tonic-gate * another lap if this is the case; the modload() will 1115*0Sstevel@tonic-gate * change the mod_filename back to one by which we can 1116*0Sstevel@tonic-gate * find the modctl. 1117*0Sstevel@tonic-gate */ 1118*0Sstevel@tonic-gate modp = mod_find_by_filename("sys", syscallnames[code]); 1119*0Sstevel@tonic-gate 1120*0Sstevel@tonic-gate if (modp == NULL) 1121*0Sstevel@tonic-gate continue; 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate mutex_enter(&mod_lock); 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate if (!modp->mod_installed) { 1126*0Sstevel@tonic-gate mutex_exit(&mod_lock); 1127*0Sstevel@tonic-gate continue; 1128*0Sstevel@tonic-gate } 1129*0Sstevel@tonic-gate break; 1130*0Sstevel@tonic-gate } 1131*0Sstevel@tonic-gate rw_enter(module_lock, RW_READER); 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate if (id != -1) 1134*0Sstevel@tonic-gate mutex_exit(&mod_lock); 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate return (module_lock); 1137*0Sstevel@tonic-gate } 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate /* 1140*0Sstevel@tonic-gate * Loadable syscall support. 1141*0Sstevel@tonic-gate * If needed, load the module, then reserve it by holding a read 1142*0Sstevel@tonic-gate * lock for the duration of the call. 1143*0Sstevel@tonic-gate * Later, if the syscall is not unloadable, it could patch the vector. 1144*0Sstevel@tonic-gate */ 1145*0Sstevel@tonic-gate /*ARGSUSED*/ 1146*0Sstevel@tonic-gate int64_t 1147*0Sstevel@tonic-gate loadable_syscall( 1148*0Sstevel@tonic-gate long a0, long a1, long a2, long a3, 1149*0Sstevel@tonic-gate long a4, long a5, long a6, long a7) 1150*0Sstevel@tonic-gate { 1151*0Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 1152*0Sstevel@tonic-gate int64_t rval; 1153*0Sstevel@tonic-gate struct sysent *callp; 1154*0Sstevel@tonic-gate struct sysent *se = LWP_GETSYSENT(lwp); 1155*0Sstevel@tonic-gate krwlock_t *module_lock; 1156*0Sstevel@tonic-gate int code, error = 0; 1157*0Sstevel@tonic-gate int64_t (*sy_call)(); 1158*0Sstevel@tonic-gate 1159*0Sstevel@tonic-gate code = curthread->t_sysnum; 1160*0Sstevel@tonic-gate callp = se + code; 1161*0Sstevel@tonic-gate 1162*0Sstevel@tonic-gate /* 1163*0Sstevel@tonic-gate * Try to autoload the system call if necessary 1164*0Sstevel@tonic-gate */ 1165*0Sstevel@tonic-gate module_lock = lock_syscall(se, code); 1166*0Sstevel@tonic-gate THREAD_KPRI_RELEASE(); /* drop priority given by rw_enter */ 1167*0Sstevel@tonic-gate 1168*0Sstevel@tonic-gate /* 1169*0Sstevel@tonic-gate * we've locked either the loaded syscall or nosys 1170*0Sstevel@tonic-gate */ 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE) { 1173*0Sstevel@tonic-gate #if defined(_LP64) 1174*0Sstevel@tonic-gate if (callp->sy_flags & SE_ARGC) { 1175*0Sstevel@tonic-gate sy_call = (int64_t (*)())callp->sy_call; 1176*0Sstevel@tonic-gate rval = (*sy_call)(a0, a1, a2, a3, a4, a5); 1177*0Sstevel@tonic-gate } else 1178*0Sstevel@tonic-gate rval = syscall_ap(); 1179*0Sstevel@tonic-gate } else { 1180*0Sstevel@tonic-gate #endif 1181*0Sstevel@tonic-gate /* 1182*0Sstevel@tonic-gate * Now that it's loaded, make sure enough args were copied. 1183*0Sstevel@tonic-gate */ 1184*0Sstevel@tonic-gate if (COPYIN_ARGS32(lwptoregs(lwp), lwp->lwp_ap, callp->sy_narg)) 1185*0Sstevel@tonic-gate error = EFAULT; 1186*0Sstevel@tonic-gate if (error) { 1187*0Sstevel@tonic-gate rval = set_errno(error); 1188*0Sstevel@tonic-gate } else if (callp->sy_flags & SE_ARGC) { 1189*0Sstevel@tonic-gate sy_call = (int64_t (*)())callp->sy_call; 1190*0Sstevel@tonic-gate rval = (*sy_call)(lwp->lwp_ap[0], lwp->lwp_ap[1], 1191*0Sstevel@tonic-gate lwp->lwp_ap[2], lwp->lwp_ap[3], lwp->lwp_ap[4], 1192*0Sstevel@tonic-gate lwp->lwp_ap[5]); 1193*0Sstevel@tonic-gate } else 1194*0Sstevel@tonic-gate rval = syscall_ap(); 1195*0Sstevel@tonic-gate } 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate THREAD_KPRI_REQUEST(); /* regain priority from read lock */ 1198*0Sstevel@tonic-gate rw_exit(module_lock); 1199*0Sstevel@tonic-gate return (rval); 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate /* 1203*0Sstevel@tonic-gate * Indirect syscall handled in libc on x86 architectures 1204*0Sstevel@tonic-gate */ 1205*0Sstevel@tonic-gate int64_t 1206*0Sstevel@tonic-gate indir() 1207*0Sstevel@tonic-gate { 1208*0Sstevel@tonic-gate return (nosys()); 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate /* 1212*0Sstevel@tonic-gate * set_errno - set an error return from the current system call. 1213*0Sstevel@tonic-gate * This could be a macro. 1214*0Sstevel@tonic-gate * This returns the value it is passed, so that the caller can 1215*0Sstevel@tonic-gate * use tail-recursion-elimination and do return (set_errno(ERRNO)); 1216*0Sstevel@tonic-gate */ 1217*0Sstevel@tonic-gate uint_t 1218*0Sstevel@tonic-gate set_errno(uint_t error) 1219*0Sstevel@tonic-gate { 1220*0Sstevel@tonic-gate ASSERT(error != 0); /* must not be used to clear errno */ 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate curthread->t_post_sys = 1; /* have post_syscall do error return */ 1223*0Sstevel@tonic-gate return (ttolwp(curthread)->lwp_errno = error); 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate 1226*0Sstevel@tonic-gate /* 1227*0Sstevel@tonic-gate * set_proc_pre_sys - Set pre-syscall processing for entire process. 1228*0Sstevel@tonic-gate */ 1229*0Sstevel@tonic-gate void 1230*0Sstevel@tonic-gate set_proc_pre_sys(proc_t *p) 1231*0Sstevel@tonic-gate { 1232*0Sstevel@tonic-gate kthread_t *t; 1233*0Sstevel@tonic-gate kthread_t *first; 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate t = first = p->p_tlist; 1238*0Sstevel@tonic-gate do { 1239*0Sstevel@tonic-gate t->t_pre_sys = 1; 1240*0Sstevel@tonic-gate } while ((t = t->t_forw) != first); 1241*0Sstevel@tonic-gate } 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate /* 1244*0Sstevel@tonic-gate * set_proc_post_sys - Set post-syscall processing for entire process. 1245*0Sstevel@tonic-gate */ 1246*0Sstevel@tonic-gate void 1247*0Sstevel@tonic-gate set_proc_post_sys(proc_t *p) 1248*0Sstevel@tonic-gate { 1249*0Sstevel@tonic-gate kthread_t *t; 1250*0Sstevel@tonic-gate kthread_t *first; 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate t = first = p->p_tlist; 1255*0Sstevel@tonic-gate do { 1256*0Sstevel@tonic-gate t->t_post_sys = 1; 1257*0Sstevel@tonic-gate } while ((t = t->t_forw) != first); 1258*0Sstevel@tonic-gate } 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate /* 1261*0Sstevel@tonic-gate * set_proc_sys - Set pre- and post-syscall processing for entire process. 1262*0Sstevel@tonic-gate */ 1263*0Sstevel@tonic-gate void 1264*0Sstevel@tonic-gate set_proc_sys(proc_t *p) 1265*0Sstevel@tonic-gate { 1266*0Sstevel@tonic-gate kthread_t *t; 1267*0Sstevel@tonic-gate kthread_t *first; 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate t = first = p->p_tlist; 1272*0Sstevel@tonic-gate do { 1273*0Sstevel@tonic-gate t->t_pre_sys = 1; 1274*0Sstevel@tonic-gate t->t_post_sys = 1; 1275*0Sstevel@tonic-gate } while ((t = t->t_forw) != first); 1276*0Sstevel@tonic-gate } 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate /* 1279*0Sstevel@tonic-gate * set_all_proc_sys - set pre- and post-syscall processing flags for all 1280*0Sstevel@tonic-gate * user processes. 1281*0Sstevel@tonic-gate * 1282*0Sstevel@tonic-gate * This is needed when auditing, tracing, or other facilities which affect 1283*0Sstevel@tonic-gate * all processes are turned on. 1284*0Sstevel@tonic-gate */ 1285*0Sstevel@tonic-gate void 1286*0Sstevel@tonic-gate set_all_proc_sys() 1287*0Sstevel@tonic-gate { 1288*0Sstevel@tonic-gate kthread_t *t; 1289*0Sstevel@tonic-gate kthread_t *first; 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gate mutex_enter(&pidlock); 1292*0Sstevel@tonic-gate t = first = curthread; 1293*0Sstevel@tonic-gate do { 1294*0Sstevel@tonic-gate t->t_pre_sys = 1; 1295*0Sstevel@tonic-gate t->t_post_sys = 1; 1296*0Sstevel@tonic-gate } while ((t = t->t_next) != first); 1297*0Sstevel@tonic-gate mutex_exit(&pidlock); 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate /* 1301*0Sstevel@tonic-gate * set_proc_ast - Set asynchronous service trap (AST) flag for all 1302*0Sstevel@tonic-gate * threads in process. 1303*0Sstevel@tonic-gate */ 1304*0Sstevel@tonic-gate void 1305*0Sstevel@tonic-gate set_proc_ast(proc_t *p) 1306*0Sstevel@tonic-gate { 1307*0Sstevel@tonic-gate kthread_t *t; 1308*0Sstevel@tonic-gate kthread_t *first; 1309*0Sstevel@tonic-gate 1310*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 1311*0Sstevel@tonic-gate 1312*0Sstevel@tonic-gate t = first = p->p_tlist; 1313*0Sstevel@tonic-gate do { 1314*0Sstevel@tonic-gate aston(t); 1315*0Sstevel@tonic-gate } while ((t = t->t_forw) != first); 1316*0Sstevel@tonic-gate } 1317