10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53768Ssl108498 * Common Development and Distribution License (the "License").
63768Ssl108498 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21390Sraf
220Sstevel@tonic-gate /*
23*11940SRoger.Faulkner@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/uio.h>
290Sstevel@tonic-gate #include <sys/param.h>
300Sstevel@tonic-gate #include <sys/cmn_err.h>
310Sstevel@tonic-gate #include <sys/cred.h>
320Sstevel@tonic-gate #include <sys/policy.h>
330Sstevel@tonic-gate #include <sys/debug.h>
340Sstevel@tonic-gate #include <sys/errno.h>
350Sstevel@tonic-gate #include <sys/file.h>
360Sstevel@tonic-gate #include <sys/inline.h>
370Sstevel@tonic-gate #include <sys/kmem.h>
380Sstevel@tonic-gate #include <sys/proc.h>
39*11940SRoger.Faulkner@Sun.COM #include <sys/brand.h>
400Sstevel@tonic-gate #include <sys/regset.h>
410Sstevel@tonic-gate #include <sys/sysmacros.h>
420Sstevel@tonic-gate #include <sys/systm.h>
430Sstevel@tonic-gate #include <sys/vfs.h>
440Sstevel@tonic-gate #include <sys/vnode.h>
450Sstevel@tonic-gate #include <sys/signal.h>
460Sstevel@tonic-gate #include <sys/auxv.h>
470Sstevel@tonic-gate #include <sys/user.h>
480Sstevel@tonic-gate #include <sys/class.h>
490Sstevel@tonic-gate #include <sys/fault.h>
500Sstevel@tonic-gate #include <sys/syscall.h>
510Sstevel@tonic-gate #include <sys/procfs.h>
520Sstevel@tonic-gate #include <sys/zone.h>
530Sstevel@tonic-gate #include <sys/copyops.h>
540Sstevel@tonic-gate #include <sys/schedctl.h>
550Sstevel@tonic-gate #include <vm/as.h>
560Sstevel@tonic-gate #include <vm/seg.h>
570Sstevel@tonic-gate #include <fs/proc/prdata.h>
580Sstevel@tonic-gate #include <sys/contract/process_impl.h>
590Sstevel@tonic-gate
600Sstevel@tonic-gate static void pr_settrace(proc_t *, sigset_t *);
610Sstevel@tonic-gate static int pr_setfpregs(prnode_t *, prfpregset_t *);
620Sstevel@tonic-gate #if defined(__sparc)
630Sstevel@tonic-gate static int pr_setxregs(prnode_t *, prxregset_t *);
640Sstevel@tonic-gate static int pr_setasrs(prnode_t *, asrset_t);
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate static int pr_setvaddr(prnode_t *, caddr_t);
670Sstevel@tonic-gate static int pr_clearsig(prnode_t *);
680Sstevel@tonic-gate static int pr_clearflt(prnode_t *);
690Sstevel@tonic-gate static int pr_watch(prnode_t *, prwatch_t *, int *);
700Sstevel@tonic-gate static int pr_agent(prnode_t *, prgregset_t, int *);
710Sstevel@tonic-gate static int pr_rdwr(proc_t *, enum uio_rw, priovec_t *);
720Sstevel@tonic-gate static int pr_scred(proc_t *, prcred_t *, cred_t *, boolean_t);
730Sstevel@tonic-gate static int pr_spriv(proc_t *, prpriv_t *, cred_t *);
740Sstevel@tonic-gate static int pr_szoneid(proc_t *, zoneid_t, cred_t *);
750Sstevel@tonic-gate static void pauselwps(proc_t *);
760Sstevel@tonic-gate static void unpauselwps(proc_t *);
770Sstevel@tonic-gate
780Sstevel@tonic-gate typedef union {
790Sstevel@tonic-gate long sig; /* PCKILL, PCUNKILL */
800Sstevel@tonic-gate long nice; /* PCNICE */
810Sstevel@tonic-gate long timeo; /* PCTWSTOP */
820Sstevel@tonic-gate ulong_t flags; /* PCRUN, PCSET, PCUNSET */
830Sstevel@tonic-gate caddr_t vaddr; /* PCSVADDR */
840Sstevel@tonic-gate siginfo_t siginfo; /* PCSSIG */
850Sstevel@tonic-gate sigset_t sigset; /* PCSTRACE, PCSHOLD */
860Sstevel@tonic-gate fltset_t fltset; /* PCSFAULT */
870Sstevel@tonic-gate sysset_t sysset; /* PCSENTRY, PCSEXIT */
880Sstevel@tonic-gate prgregset_t prgregset; /* PCSREG, PCAGENT */
890Sstevel@tonic-gate prfpregset_t prfpregset; /* PCSFPREG */
900Sstevel@tonic-gate #if defined(__sparc)
910Sstevel@tonic-gate prxregset_t prxregset; /* PCSXREG */
920Sstevel@tonic-gate asrset_t asrset; /* PCSASRS */
930Sstevel@tonic-gate #endif
940Sstevel@tonic-gate prwatch_t prwatch; /* PCWATCH */
950Sstevel@tonic-gate priovec_t priovec; /* PCREAD, PCWRITE */
960Sstevel@tonic-gate prcred_t prcred; /* PCSCRED */
970Sstevel@tonic-gate prpriv_t prpriv; /* PCSPRIV */
980Sstevel@tonic-gate long przoneid; /* PCSZONE */
990Sstevel@tonic-gate } arg_t;
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate static int pr_control(long, arg_t *, prnode_t *, cred_t *);
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate static size_t
ctlsize(long cmd,size_t resid,arg_t * argp)1040Sstevel@tonic-gate ctlsize(long cmd, size_t resid, arg_t *argp)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate size_t size = sizeof (long);
1070Sstevel@tonic-gate size_t rnd;
1080Sstevel@tonic-gate int ngrp;
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate switch (cmd) {
1110Sstevel@tonic-gate case PCNULL:
1120Sstevel@tonic-gate case PCSTOP:
1130Sstevel@tonic-gate case PCDSTOP:
1140Sstevel@tonic-gate case PCWSTOP:
1150Sstevel@tonic-gate case PCCSIG:
1160Sstevel@tonic-gate case PCCFAULT:
1170Sstevel@tonic-gate break;
1180Sstevel@tonic-gate case PCSSIG:
1190Sstevel@tonic-gate size += sizeof (siginfo_t);
1200Sstevel@tonic-gate break;
1210Sstevel@tonic-gate case PCTWSTOP:
1220Sstevel@tonic-gate size += sizeof (long);
1230Sstevel@tonic-gate break;
1240Sstevel@tonic-gate case PCKILL:
1250Sstevel@tonic-gate case PCUNKILL:
1260Sstevel@tonic-gate case PCNICE:
1270Sstevel@tonic-gate size += sizeof (long);
1280Sstevel@tonic-gate break;
1290Sstevel@tonic-gate case PCRUN:
1300Sstevel@tonic-gate case PCSET:
1310Sstevel@tonic-gate case PCUNSET:
1320Sstevel@tonic-gate size += sizeof (ulong_t);
1330Sstevel@tonic-gate break;
1340Sstevel@tonic-gate case PCSVADDR:
1350Sstevel@tonic-gate size += sizeof (caddr_t);
1360Sstevel@tonic-gate break;
1370Sstevel@tonic-gate case PCSTRACE:
1380Sstevel@tonic-gate case PCSHOLD:
1390Sstevel@tonic-gate size += sizeof (sigset_t);
1400Sstevel@tonic-gate break;
1410Sstevel@tonic-gate case PCSFAULT:
1420Sstevel@tonic-gate size += sizeof (fltset_t);
1430Sstevel@tonic-gate break;
1440Sstevel@tonic-gate case PCSENTRY:
1450Sstevel@tonic-gate case PCSEXIT:
1460Sstevel@tonic-gate size += sizeof (sysset_t);
1470Sstevel@tonic-gate break;
1480Sstevel@tonic-gate case PCSREG:
1490Sstevel@tonic-gate case PCAGENT:
1500Sstevel@tonic-gate size += sizeof (prgregset_t);
1510Sstevel@tonic-gate break;
1520Sstevel@tonic-gate case PCSFPREG:
1530Sstevel@tonic-gate size += sizeof (prfpregset_t);
1540Sstevel@tonic-gate break;
1550Sstevel@tonic-gate #if defined(__sparc)
1560Sstevel@tonic-gate case PCSXREG:
1570Sstevel@tonic-gate size += sizeof (prxregset_t);
1580Sstevel@tonic-gate break;
1590Sstevel@tonic-gate case PCSASRS:
1600Sstevel@tonic-gate size += sizeof (asrset_t);
1610Sstevel@tonic-gate break;
1620Sstevel@tonic-gate #endif
1630Sstevel@tonic-gate case PCWATCH:
1640Sstevel@tonic-gate size += sizeof (prwatch_t);
1650Sstevel@tonic-gate break;
1660Sstevel@tonic-gate case PCREAD:
1670Sstevel@tonic-gate case PCWRITE:
1680Sstevel@tonic-gate size += sizeof (priovec_t);
1690Sstevel@tonic-gate break;
1700Sstevel@tonic-gate case PCSCRED:
1710Sstevel@tonic-gate size += sizeof (prcred_t);
1720Sstevel@tonic-gate break;
1730Sstevel@tonic-gate case PCSCREDX:
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * We cannot derefence the pr_ngroups fields if it
1760Sstevel@tonic-gate * we don't have enough data.
1770Sstevel@tonic-gate */
1780Sstevel@tonic-gate if (resid < size + sizeof (prcred_t) - sizeof (gid_t))
1790Sstevel@tonic-gate return (0);
1800Sstevel@tonic-gate ngrp = argp->prcred.pr_ngroups;
1810Sstevel@tonic-gate if (ngrp < 0 || ngrp > ngroups_max)
1820Sstevel@tonic-gate return (0);
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /* The result can be smaller than sizeof (prcred_t) */
1850Sstevel@tonic-gate size += sizeof (prcred_t) - sizeof (gid_t);
1860Sstevel@tonic-gate size += ngrp * sizeof (gid_t);
1870Sstevel@tonic-gate break;
1880Sstevel@tonic-gate case PCSPRIV:
1890Sstevel@tonic-gate if (resid >= size + sizeof (prpriv_t))
1900Sstevel@tonic-gate size += priv_prgetprivsize(&argp->prpriv);
1910Sstevel@tonic-gate else
1920Sstevel@tonic-gate return (0);
1930Sstevel@tonic-gate break;
1940Sstevel@tonic-gate case PCSZONE:
1950Sstevel@tonic-gate size += sizeof (long);
1960Sstevel@tonic-gate break;
1970Sstevel@tonic-gate default:
1989319SSuhasini.Peddada@Sun.COM return (0);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /* Round up to a multiple of long, unless exact amount written */
2020Sstevel@tonic-gate if (size < resid) {
2030Sstevel@tonic-gate rnd = size & (sizeof (long) - 1);
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate if (rnd != 0)
2060Sstevel@tonic-gate size += sizeof (long) - rnd;
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate if (size > resid)
2100Sstevel@tonic-gate return (0);
2110Sstevel@tonic-gate return (size);
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate * Control operations (lots).
2160Sstevel@tonic-gate */
2170Sstevel@tonic-gate int
prwritectl(vnode_t * vp,uio_t * uiop,cred_t * cr)2180Sstevel@tonic-gate prwritectl(vnode_t *vp, uio_t *uiop, cred_t *cr)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate #define MY_BUFFER_SIZE \
2210Sstevel@tonic-gate 100 > 1 + sizeof (arg_t) / sizeof (long) ? \
2220Sstevel@tonic-gate 100 : 1 + sizeof (arg_t) / sizeof (long)
2230Sstevel@tonic-gate long buf[MY_BUFFER_SIZE];
2240Sstevel@tonic-gate long *bufp;
2250Sstevel@tonic-gate size_t resid = 0;
2260Sstevel@tonic-gate size_t size;
2270Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
2280Sstevel@tonic-gate int error;
2290Sstevel@tonic-gate int locked = 0;
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate while (uiop->uio_resid) {
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate * Read several commands in one gulp.
2340Sstevel@tonic-gate */
2350Sstevel@tonic-gate bufp = buf;
2360Sstevel@tonic-gate if (resid) { /* move incomplete command to front of buffer */
2370Sstevel@tonic-gate long *tail;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (resid >= sizeof (buf))
2400Sstevel@tonic-gate break;
2410Sstevel@tonic-gate tail = (long *)((char *)buf + sizeof (buf) - resid);
2420Sstevel@tonic-gate do {
2430Sstevel@tonic-gate *bufp++ = *tail++;
2440Sstevel@tonic-gate } while ((resid -= sizeof (long)) != 0);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate resid = sizeof (buf) - ((char *)bufp - (char *)buf);
2470Sstevel@tonic-gate if (resid > uiop->uio_resid)
2480Sstevel@tonic-gate resid = uiop->uio_resid;
2490Sstevel@tonic-gate if (error = uiomove((caddr_t)bufp, resid, UIO_WRITE, uiop))
2500Sstevel@tonic-gate return (error);
2510Sstevel@tonic-gate resid += (char *)bufp - (char *)buf;
2520Sstevel@tonic-gate bufp = buf;
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate do { /* loop over commands in buffer */
2550Sstevel@tonic-gate long cmd = bufp[0];
2560Sstevel@tonic-gate arg_t *argp = (arg_t *)&bufp[1];
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate size = ctlsize(cmd, resid, argp);
2599319SSuhasini.Peddada@Sun.COM if (size == 0) /* incomplete or invalid command */
2609275SSuhasini.Peddada@Sun.COM break;
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * Perform the specified control operation.
2630Sstevel@tonic-gate */
2640Sstevel@tonic-gate if (!locked) {
2650Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
2660Sstevel@tonic-gate return (error);
2670Sstevel@tonic-gate locked = 1;
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate if (error = pr_control(cmd, argp, pnp, cr)) {
2700Sstevel@tonic-gate if (error == -1) /* -1 is timeout */
2710Sstevel@tonic-gate locked = 0;
2720Sstevel@tonic-gate else
2730Sstevel@tonic-gate return (error);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate bufp = (long *)((char *)bufp + size);
2760Sstevel@tonic-gate } while ((resid -= size) != 0);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if (locked) {
2790Sstevel@tonic-gate prunlock(pnp);
2800Sstevel@tonic-gate locked = 0;
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate return (resid? EINVAL : 0);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate static int
pr_control(long cmd,arg_t * argp,prnode_t * pnp,cred_t * cr)2870Sstevel@tonic-gate pr_control(long cmd, arg_t *argp, prnode_t *pnp, cred_t *cr)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate prcommon_t *pcp;
2900Sstevel@tonic-gate proc_t *p;
2910Sstevel@tonic-gate int unlocked;
2920Sstevel@tonic-gate int error = 0;
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate if (cmd == PCNULL)
2950Sstevel@tonic-gate return (0);
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate pcp = pnp->pr_common;
2980Sstevel@tonic-gate p = pcp->prc_proc;
2990Sstevel@tonic-gate ASSERT(p != NULL);
3000Sstevel@tonic-gate
30111173SJonathan.Adams@Sun.COM /* System processes defy control. */
30211173SJonathan.Adams@Sun.COM if (p->p_flag & SSYS) {
30311173SJonathan.Adams@Sun.COM prunlock(pnp);
30411173SJonathan.Adams@Sun.COM return (EBUSY);
30511173SJonathan.Adams@Sun.COM }
30611173SJonathan.Adams@Sun.COM
3070Sstevel@tonic-gate switch (cmd) {
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate default:
3100Sstevel@tonic-gate error = EINVAL;
3110Sstevel@tonic-gate break;
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate case PCSTOP: /* direct process or lwp to stop and wait for stop */
3140Sstevel@tonic-gate case PCDSTOP: /* direct process or lwp to stop, don't wait */
3150Sstevel@tonic-gate case PCWSTOP: /* wait for process or lwp to stop */
3160Sstevel@tonic-gate case PCTWSTOP: /* wait for process or lwp to stop, with timeout */
3175771Sjp151216 {
3185771Sjp151216 time_t timeo;
3190Sstevel@tonic-gate
3205771Sjp151216 /*
3215771Sjp151216 * Can't apply to a system process.
3225771Sjp151216 */
32311173SJonathan.Adams@Sun.COM if (p->p_as == &kas) {
3245771Sjp151216 error = EBUSY;
3255771Sjp151216 break;
3265771Sjp151216 }
3270Sstevel@tonic-gate
3285771Sjp151216 if (cmd == PCSTOP || cmd == PCDSTOP)
3295771Sjp151216 pr_stop(pnp);
3300Sstevel@tonic-gate
3315771Sjp151216 if (cmd == PCDSTOP)
3325771Sjp151216 break;
3330Sstevel@tonic-gate
3345771Sjp151216 /*
3355771Sjp151216 * If an lwp is waiting for itself or its process,
3365771Sjp151216 * don't wait. The stopped lwp would never see the
3375771Sjp151216 * fact that it is stopped.
3385771Sjp151216 */
3395771Sjp151216 if ((pcp->prc_flags & PRC_LWP)?
3405771Sjp151216 (pcp->prc_thread == curthread) : (p == curproc)) {
3415771Sjp151216 if (cmd == PCWSTOP || cmd == PCTWSTOP)
3425771Sjp151216 error = EBUSY;
3435771Sjp151216 break;
3445771Sjp151216 }
3450Sstevel@tonic-gate
3466247Sraf timeo = (cmd == PCTWSTOP)? (time_t)argp->timeo : 0;
3476247Sraf if ((error = pr_wait_stop(pnp, timeo)) != 0)
3486247Sraf return (error);
3490Sstevel@tonic-gate
3506247Sraf break;
3515771Sjp151216 }
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate case PCRUN: /* make lwp or process runnable */
3540Sstevel@tonic-gate error = pr_setrun(pnp, argp->flags);
3550Sstevel@tonic-gate break;
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate case PCSTRACE: /* set signal trace mask */
3580Sstevel@tonic-gate pr_settrace(p, &argp->sigset);
3590Sstevel@tonic-gate break;
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate case PCSSIG: /* set current signal */
3620Sstevel@tonic-gate error = pr_setsig(pnp, &argp->siginfo);
3630Sstevel@tonic-gate if (argp->siginfo.si_signo == SIGKILL && error == 0) {
3640Sstevel@tonic-gate prunlock(pnp);
3650Sstevel@tonic-gate pr_wait_die(pnp);
3660Sstevel@tonic-gate return (-1);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate break;
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate case PCKILL: /* send signal */
3710Sstevel@tonic-gate error = pr_kill(pnp, (int)argp->sig, cr);
3720Sstevel@tonic-gate if (error == 0 && argp->sig == SIGKILL) {
3730Sstevel@tonic-gate prunlock(pnp);
3740Sstevel@tonic-gate pr_wait_die(pnp);
3750Sstevel@tonic-gate return (-1);
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate break;
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate case PCUNKILL: /* delete a pending signal */
3800Sstevel@tonic-gate error = pr_unkill(pnp, (int)argp->sig);
3810Sstevel@tonic-gate break;
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate case PCNICE: /* set nice priority */
3840Sstevel@tonic-gate error = pr_nice(p, (int)argp->nice, cr);
3850Sstevel@tonic-gate break;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate case PCSENTRY: /* set syscall entry bit mask */
3880Sstevel@tonic-gate case PCSEXIT: /* set syscall exit bit mask */
3890Sstevel@tonic-gate pr_setentryexit(p, &argp->sysset, cmd == PCSENTRY);
3900Sstevel@tonic-gate break;
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate case PCSET: /* set process flags */
3930Sstevel@tonic-gate error = pr_set(p, argp->flags);
3940Sstevel@tonic-gate break;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate case PCUNSET: /* unset process flags */
3970Sstevel@tonic-gate error = pr_unset(p, argp->flags);
3980Sstevel@tonic-gate break;
3990Sstevel@tonic-gate
4000Sstevel@tonic-gate case PCSREG: /* set general registers */
4015771Sjp151216 {
4025771Sjp151216 kthread_t *t = pr_thread(pnp);
4030Sstevel@tonic-gate
4045771Sjp151216 if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
4055771Sjp151216 thread_unlock(t);
4065771Sjp151216 error = EBUSY;
4075771Sjp151216 } else {
4085771Sjp151216 thread_unlock(t);
4095771Sjp151216 mutex_exit(&p->p_lock);
4105771Sjp151216 prsetprregs(ttolwp(t), argp->prgregset, 0);
4115771Sjp151216 mutex_enter(&p->p_lock);
4125771Sjp151216 }
4135771Sjp151216 break;
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate case PCSFPREG: /* set floating-point registers */
4170Sstevel@tonic-gate error = pr_setfpregs(pnp, &argp->prfpregset);
4180Sstevel@tonic-gate break;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate case PCSXREG: /* set extra registers */
4210Sstevel@tonic-gate #if defined(__sparc)
4220Sstevel@tonic-gate error = pr_setxregs(pnp, &argp->prxregset);
4230Sstevel@tonic-gate #else
4240Sstevel@tonic-gate error = EINVAL;
4250Sstevel@tonic-gate #endif
4260Sstevel@tonic-gate break;
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate #if defined(__sparc)
4290Sstevel@tonic-gate case PCSASRS: /* set ancillary state registers */
4300Sstevel@tonic-gate error = pr_setasrs(pnp, argp->asrset);
4310Sstevel@tonic-gate break;
4320Sstevel@tonic-gate #endif
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate case PCSVADDR: /* set virtual address at which to resume */
4350Sstevel@tonic-gate error = pr_setvaddr(pnp, argp->vaddr);
4360Sstevel@tonic-gate break;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate case PCSHOLD: /* set signal-hold mask */
4390Sstevel@tonic-gate pr_sethold(pnp, &argp->sigset);
4400Sstevel@tonic-gate break;
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate case PCSFAULT: /* set mask of traced faults */
4430Sstevel@tonic-gate pr_setfault(p, &argp->fltset);
4440Sstevel@tonic-gate break;
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate case PCCSIG: /* clear current signal */
4470Sstevel@tonic-gate error = pr_clearsig(pnp);
4480Sstevel@tonic-gate break;
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate case PCCFAULT: /* clear current fault */
4510Sstevel@tonic-gate error = pr_clearflt(pnp);
4520Sstevel@tonic-gate break;
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate case PCWATCH: /* set or clear watched areas */
4550Sstevel@tonic-gate error = pr_watch(pnp, &argp->prwatch, &unlocked);
4560Sstevel@tonic-gate if (error && unlocked)
4570Sstevel@tonic-gate return (error);
4580Sstevel@tonic-gate break;
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate case PCAGENT: /* create the /proc agent lwp in the target process */
4610Sstevel@tonic-gate error = pr_agent(pnp, argp->prgregset, &unlocked);
4620Sstevel@tonic-gate if (error && unlocked)
4630Sstevel@tonic-gate return (error);
4640Sstevel@tonic-gate break;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate case PCREAD: /* read from the address space */
4670Sstevel@tonic-gate error = pr_rdwr(p, UIO_READ, &argp->priovec);
4680Sstevel@tonic-gate break;
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate case PCWRITE: /* write to the address space */
4710Sstevel@tonic-gate error = pr_rdwr(p, UIO_WRITE, &argp->priovec);
4720Sstevel@tonic-gate break;
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate case PCSCRED: /* set the process credentials */
4750Sstevel@tonic-gate case PCSCREDX:
4760Sstevel@tonic-gate error = pr_scred(p, &argp->prcred, cr, cmd == PCSCREDX);
4770Sstevel@tonic-gate break;
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate case PCSPRIV: /* set the process privileges */
4800Sstevel@tonic-gate error = pr_spriv(p, &argp->prpriv, cr);
4810Sstevel@tonic-gate break;
4820Sstevel@tonic-gate case PCSZONE: /* set the process's zoneid credentials */
4830Sstevel@tonic-gate error = pr_szoneid(p, (zoneid_t)argp->przoneid, cr);
4840Sstevel@tonic-gate break;
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate if (error)
4880Sstevel@tonic-gate prunlock(pnp);
4890Sstevel@tonic-gate return (error);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate typedef union {
4950Sstevel@tonic-gate int32_t sig; /* PCKILL, PCUNKILL */
4960Sstevel@tonic-gate int32_t nice; /* PCNICE */
4970Sstevel@tonic-gate int32_t timeo; /* PCTWSTOP */
4980Sstevel@tonic-gate uint32_t flags; /* PCRUN, PCSET, PCUNSET */
4990Sstevel@tonic-gate caddr32_t vaddr; /* PCSVADDR */
5000Sstevel@tonic-gate siginfo32_t siginfo; /* PCSSIG */
5010Sstevel@tonic-gate sigset_t sigset; /* PCSTRACE, PCSHOLD */
5020Sstevel@tonic-gate fltset_t fltset; /* PCSFAULT */
5030Sstevel@tonic-gate sysset_t sysset; /* PCSENTRY, PCSEXIT */
5040Sstevel@tonic-gate prgregset32_t prgregset; /* PCSREG, PCAGENT */
5050Sstevel@tonic-gate prfpregset32_t prfpregset; /* PCSFPREG */
5060Sstevel@tonic-gate #if defined(__sparc)
5070Sstevel@tonic-gate prxregset_t prxregset; /* PCSXREG */
5080Sstevel@tonic-gate #endif
5090Sstevel@tonic-gate prwatch32_t prwatch; /* PCWATCH */
5100Sstevel@tonic-gate priovec32_t priovec; /* PCREAD, PCWRITE */
5110Sstevel@tonic-gate prcred32_t prcred; /* PCSCRED */
5120Sstevel@tonic-gate prpriv_t prpriv; /* PCSPRIV */
5130Sstevel@tonic-gate int32_t przoneid; /* PCSZONE */
5140Sstevel@tonic-gate } arg32_t;
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate static int pr_control32(int32_t, arg32_t *, prnode_t *, cred_t *);
5170Sstevel@tonic-gate static int pr_setfpregs32(prnode_t *, prfpregset32_t *);
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate /*
5200Sstevel@tonic-gate * Note that while ctlsize32() can use argp, it must do so only in a way
5210Sstevel@tonic-gate * that assumes 32-bit rather than 64-bit alignment as argp is a pointer
5220Sstevel@tonic-gate * to an array of 32-bit values and only 32-bit alignment is ensured.
5230Sstevel@tonic-gate */
5240Sstevel@tonic-gate static size_t
ctlsize32(int32_t cmd,size_t resid,arg32_t * argp)5250Sstevel@tonic-gate ctlsize32(int32_t cmd, size_t resid, arg32_t *argp)
5260Sstevel@tonic-gate {
5270Sstevel@tonic-gate size_t size = sizeof (int32_t);
5280Sstevel@tonic-gate size_t rnd;
5290Sstevel@tonic-gate int ngrp;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate switch (cmd) {
5320Sstevel@tonic-gate case PCNULL:
5330Sstevel@tonic-gate case PCSTOP:
5340Sstevel@tonic-gate case PCDSTOP:
5350Sstevel@tonic-gate case PCWSTOP:
5360Sstevel@tonic-gate case PCCSIG:
5370Sstevel@tonic-gate case PCCFAULT:
5380Sstevel@tonic-gate break;
5390Sstevel@tonic-gate case PCSSIG:
5400Sstevel@tonic-gate size += sizeof (siginfo32_t);
5410Sstevel@tonic-gate break;
5420Sstevel@tonic-gate case PCTWSTOP:
5430Sstevel@tonic-gate size += sizeof (int32_t);
5440Sstevel@tonic-gate break;
5450Sstevel@tonic-gate case PCKILL:
5460Sstevel@tonic-gate case PCUNKILL:
5470Sstevel@tonic-gate case PCNICE:
5480Sstevel@tonic-gate size += sizeof (int32_t);
5490Sstevel@tonic-gate break;
5500Sstevel@tonic-gate case PCRUN:
5510Sstevel@tonic-gate case PCSET:
5520Sstevel@tonic-gate case PCUNSET:
5530Sstevel@tonic-gate size += sizeof (uint32_t);
5540Sstevel@tonic-gate break;
5550Sstevel@tonic-gate case PCSVADDR:
5560Sstevel@tonic-gate size += sizeof (caddr32_t);
5570Sstevel@tonic-gate break;
5580Sstevel@tonic-gate case PCSTRACE:
5590Sstevel@tonic-gate case PCSHOLD:
5600Sstevel@tonic-gate size += sizeof (sigset_t);
5610Sstevel@tonic-gate break;
5620Sstevel@tonic-gate case PCSFAULT:
5630Sstevel@tonic-gate size += sizeof (fltset_t);
5640Sstevel@tonic-gate break;
5650Sstevel@tonic-gate case PCSENTRY:
5660Sstevel@tonic-gate case PCSEXIT:
5670Sstevel@tonic-gate size += sizeof (sysset_t);
5680Sstevel@tonic-gate break;
5690Sstevel@tonic-gate case PCSREG:
5700Sstevel@tonic-gate case PCAGENT:
5710Sstevel@tonic-gate size += sizeof (prgregset32_t);
5720Sstevel@tonic-gate break;
5730Sstevel@tonic-gate case PCSFPREG:
5740Sstevel@tonic-gate size += sizeof (prfpregset32_t);
5750Sstevel@tonic-gate break;
5760Sstevel@tonic-gate #if defined(__sparc)
5770Sstevel@tonic-gate case PCSXREG:
5780Sstevel@tonic-gate size += sizeof (prxregset_t);
5790Sstevel@tonic-gate break;
5800Sstevel@tonic-gate #endif
5810Sstevel@tonic-gate case PCWATCH:
5820Sstevel@tonic-gate size += sizeof (prwatch32_t);
5830Sstevel@tonic-gate break;
5840Sstevel@tonic-gate case PCREAD:
5850Sstevel@tonic-gate case PCWRITE:
5860Sstevel@tonic-gate size += sizeof (priovec32_t);
5870Sstevel@tonic-gate break;
5880Sstevel@tonic-gate case PCSCRED:
5890Sstevel@tonic-gate size += sizeof (prcred32_t);
5900Sstevel@tonic-gate break;
5910Sstevel@tonic-gate case PCSCREDX:
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate * We cannot derefence the pr_ngroups fields if it
5940Sstevel@tonic-gate * we don't have enough data.
5950Sstevel@tonic-gate */
5960Sstevel@tonic-gate if (resid < size + sizeof (prcred32_t) - sizeof (gid32_t))
5970Sstevel@tonic-gate return (0);
5980Sstevel@tonic-gate ngrp = argp->prcred.pr_ngroups;
5990Sstevel@tonic-gate if (ngrp < 0 || ngrp > ngroups_max)
6000Sstevel@tonic-gate return (0);
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate /* The result can be smaller than sizeof (prcred32_t) */
6030Sstevel@tonic-gate size += sizeof (prcred32_t) - sizeof (gid32_t);
6040Sstevel@tonic-gate size += ngrp * sizeof (gid32_t);
6050Sstevel@tonic-gate break;
6060Sstevel@tonic-gate case PCSPRIV:
6070Sstevel@tonic-gate if (resid >= size + sizeof (prpriv_t))
6080Sstevel@tonic-gate size += priv_prgetprivsize(&argp->prpriv);
6090Sstevel@tonic-gate else
6100Sstevel@tonic-gate return (0);
6110Sstevel@tonic-gate break;
6120Sstevel@tonic-gate case PCSZONE:
6130Sstevel@tonic-gate size += sizeof (int32_t);
6140Sstevel@tonic-gate break;
6150Sstevel@tonic-gate default:
6160Sstevel@tonic-gate return (0);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate /* Round up to a multiple of int32_t */
6200Sstevel@tonic-gate rnd = size & (sizeof (int32_t) - 1);
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate if (rnd != 0)
6230Sstevel@tonic-gate size += sizeof (int32_t) - rnd;
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate if (size > resid)
6260Sstevel@tonic-gate return (0);
6270Sstevel@tonic-gate return (size);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate * Control operations (lots).
6320Sstevel@tonic-gate */
6330Sstevel@tonic-gate int
prwritectl32(struct vnode * vp,struct uio * uiop,cred_t * cr)6340Sstevel@tonic-gate prwritectl32(struct vnode *vp, struct uio *uiop, cred_t *cr)
6350Sstevel@tonic-gate {
6360Sstevel@tonic-gate #define MY_BUFFER_SIZE32 \
6370Sstevel@tonic-gate 100 > 1 + sizeof (arg32_t) / sizeof (int32_t) ? \
6380Sstevel@tonic-gate 100 : 1 + sizeof (arg32_t) / sizeof (int32_t)
6390Sstevel@tonic-gate int32_t buf[MY_BUFFER_SIZE32];
6400Sstevel@tonic-gate int32_t *bufp;
6410Sstevel@tonic-gate arg32_t arg;
6420Sstevel@tonic-gate size_t resid = 0;
6430Sstevel@tonic-gate size_t size;
6440Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
6450Sstevel@tonic-gate int error;
6460Sstevel@tonic-gate int locked = 0;
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate while (uiop->uio_resid) {
6490Sstevel@tonic-gate /*
6500Sstevel@tonic-gate * Read several commands in one gulp.
6510Sstevel@tonic-gate */
6520Sstevel@tonic-gate bufp = buf;
6530Sstevel@tonic-gate if (resid) { /* move incomplete command to front of buffer */
6540Sstevel@tonic-gate int32_t *tail;
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate if (resid >= sizeof (buf))
6570Sstevel@tonic-gate break;
6580Sstevel@tonic-gate tail = (int32_t *)((char *)buf + sizeof (buf) - resid);
6590Sstevel@tonic-gate do {
6600Sstevel@tonic-gate *bufp++ = *tail++;
6610Sstevel@tonic-gate } while ((resid -= sizeof (int32_t)) != 0);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate resid = sizeof (buf) - ((char *)bufp - (char *)buf);
6640Sstevel@tonic-gate if (resid > uiop->uio_resid)
6650Sstevel@tonic-gate resid = uiop->uio_resid;
6660Sstevel@tonic-gate if (error = uiomove((caddr_t)bufp, resid, UIO_WRITE, uiop))
6670Sstevel@tonic-gate return (error);
6680Sstevel@tonic-gate resid += (char *)bufp - (char *)buf;
6690Sstevel@tonic-gate bufp = buf;
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate do { /* loop over commands in buffer */
6720Sstevel@tonic-gate int32_t cmd = bufp[0];
6730Sstevel@tonic-gate arg32_t *argp = (arg32_t *)&bufp[1];
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate size = ctlsize32(cmd, resid, argp);
6769319SSuhasini.Peddada@Sun.COM if (size == 0) /* incomplete or invalid command */
6779275SSuhasini.Peddada@Sun.COM break;
6780Sstevel@tonic-gate /*
6790Sstevel@tonic-gate * Perform the specified control operation.
6800Sstevel@tonic-gate */
6810Sstevel@tonic-gate if (!locked) {
6820Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
6830Sstevel@tonic-gate return (error);
6840Sstevel@tonic-gate locked = 1;
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /*
6880Sstevel@tonic-gate * Since some members of the arg32_t union contain
6890Sstevel@tonic-gate * 64-bit values (which must be 64-bit aligned), we
6900Sstevel@tonic-gate * can't simply pass a pointer to the structure as
6910Sstevel@tonic-gate * it may be unaligned. Note that we do pass the
6920Sstevel@tonic-gate * potentially unaligned structure to ctlsize32()
6930Sstevel@tonic-gate * above, but that uses it a way that makes no
6940Sstevel@tonic-gate * assumptions about alignment.
6950Sstevel@tonic-gate */
6960Sstevel@tonic-gate ASSERT(size - sizeof (cmd) <= sizeof (arg));
6970Sstevel@tonic-gate bcopy(argp, &arg, size - sizeof (cmd));
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate if (error = pr_control32(cmd, &arg, pnp, cr)) {
7000Sstevel@tonic-gate if (error == -1) /* -1 is timeout */
7010Sstevel@tonic-gate locked = 0;
7020Sstevel@tonic-gate else
7030Sstevel@tonic-gate return (error);
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate bufp = (int32_t *)((char *)bufp + size);
7060Sstevel@tonic-gate } while ((resid -= size) != 0);
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate if (locked) {
7090Sstevel@tonic-gate prunlock(pnp);
7100Sstevel@tonic-gate locked = 0;
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate return (resid? EINVAL : 0);
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate static int
pr_control32(int32_t cmd,arg32_t * argp,prnode_t * pnp,cred_t * cr)7170Sstevel@tonic-gate pr_control32(int32_t cmd, arg32_t *argp, prnode_t *pnp, cred_t *cr)
7180Sstevel@tonic-gate {
7190Sstevel@tonic-gate prcommon_t *pcp;
7200Sstevel@tonic-gate proc_t *p;
7210Sstevel@tonic-gate int unlocked;
7220Sstevel@tonic-gate int error = 0;
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate if (cmd == PCNULL)
7250Sstevel@tonic-gate return (0);
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate pcp = pnp->pr_common;
7280Sstevel@tonic-gate p = pcp->prc_proc;
7290Sstevel@tonic-gate ASSERT(p != NULL);
7300Sstevel@tonic-gate
73111173SJonathan.Adams@Sun.COM if (p->p_flag & SSYS) {
73211173SJonathan.Adams@Sun.COM prunlock(pnp);
73311173SJonathan.Adams@Sun.COM return (EBUSY);
73411173SJonathan.Adams@Sun.COM }
73511173SJonathan.Adams@Sun.COM
7360Sstevel@tonic-gate switch (cmd) {
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate default:
7390Sstevel@tonic-gate error = EINVAL;
7400Sstevel@tonic-gate break;
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate case PCSTOP: /* direct process or lwp to stop and wait for stop */
7430Sstevel@tonic-gate case PCDSTOP: /* direct process or lwp to stop, don't wait */
7440Sstevel@tonic-gate case PCWSTOP: /* wait for process or lwp to stop */
7450Sstevel@tonic-gate case PCTWSTOP: /* wait for process or lwp to stop, with timeout */
7465771Sjp151216 {
7475771Sjp151216 time_t timeo;
7485771Sjp151216
7495771Sjp151216 /*
7505771Sjp151216 * Can't apply to a system process.
7515771Sjp151216 */
75211173SJonathan.Adams@Sun.COM if (p->p_as == &kas) {
7535771Sjp151216 error = EBUSY;
7545771Sjp151216 break;
7555771Sjp151216 }
7565771Sjp151216
7575771Sjp151216 if (cmd == PCSTOP || cmd == PCDSTOP)
7585771Sjp151216 pr_stop(pnp);
7595771Sjp151216
7605771Sjp151216 if (cmd == PCDSTOP)
7615771Sjp151216 break;
7620Sstevel@tonic-gate
7635771Sjp151216 /*
7645771Sjp151216 * If an lwp is waiting for itself or its process,
7655771Sjp151216 * don't wait. The lwp will never see the fact that
7665771Sjp151216 * itself is stopped.
7675771Sjp151216 */
7685771Sjp151216 if ((pcp->prc_flags & PRC_LWP)?
7695771Sjp151216 (pcp->prc_thread == curthread) : (p == curproc)) {
7705771Sjp151216 if (cmd == PCWSTOP || cmd == PCTWSTOP)
7715771Sjp151216 error = EBUSY;
7725771Sjp151216 break;
7735771Sjp151216 }
7745771Sjp151216
7755771Sjp151216 timeo = (cmd == PCTWSTOP)? (time_t)argp->timeo : 0;
7765771Sjp151216 if ((error = pr_wait_stop(pnp, timeo)) != 0)
7775771Sjp151216 return (error);
7785771Sjp151216
7790Sstevel@tonic-gate break;
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate case PCRUN: /* make lwp or process runnable */
7830Sstevel@tonic-gate error = pr_setrun(pnp, (ulong_t)argp->flags);
7840Sstevel@tonic-gate break;
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate case PCSTRACE: /* set signal trace mask */
7870Sstevel@tonic-gate pr_settrace(p, &argp->sigset);
7880Sstevel@tonic-gate break;
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate case PCSSIG: /* set current signal */
7910Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
7920Sstevel@tonic-gate error = EOVERFLOW;
7930Sstevel@tonic-gate else {
7940Sstevel@tonic-gate int sig = (int)argp->siginfo.si_signo;
7950Sstevel@tonic-gate siginfo_t siginfo;
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate bzero(&siginfo, sizeof (siginfo));
7980Sstevel@tonic-gate siginfo_32tok(&argp->siginfo, (k_siginfo_t *)&siginfo);
7990Sstevel@tonic-gate error = pr_setsig(pnp, &siginfo);
8000Sstevel@tonic-gate if (sig == SIGKILL && error == 0) {
8010Sstevel@tonic-gate prunlock(pnp);
8020Sstevel@tonic-gate pr_wait_die(pnp);
8030Sstevel@tonic-gate return (-1);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate break;
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate case PCKILL: /* send signal */
8090Sstevel@tonic-gate error = pr_kill(pnp, (int)argp->sig, cr);
8100Sstevel@tonic-gate if (error == 0 && argp->sig == SIGKILL) {
8110Sstevel@tonic-gate prunlock(pnp);
8120Sstevel@tonic-gate pr_wait_die(pnp);
8130Sstevel@tonic-gate return (-1);
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate break;
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate case PCUNKILL: /* delete a pending signal */
8180Sstevel@tonic-gate error = pr_unkill(pnp, (int)argp->sig);
8190Sstevel@tonic-gate break;
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate case PCNICE: /* set nice priority */
8220Sstevel@tonic-gate error = pr_nice(p, (int)argp->nice, cr);
8230Sstevel@tonic-gate break;
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate case PCSENTRY: /* set syscall entry bit mask */
8260Sstevel@tonic-gate case PCSEXIT: /* set syscall exit bit mask */
8270Sstevel@tonic-gate pr_setentryexit(p, &argp->sysset, cmd == PCSENTRY);
8280Sstevel@tonic-gate break;
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate case PCSET: /* set process flags */
8310Sstevel@tonic-gate error = pr_set(p, (long)argp->flags);
8320Sstevel@tonic-gate break;
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate case PCUNSET: /* unset process flags */
8350Sstevel@tonic-gate error = pr_unset(p, (long)argp->flags);
8360Sstevel@tonic-gate break;
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate case PCSREG: /* set general registers */
8390Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
8400Sstevel@tonic-gate error = EOVERFLOW;
8410Sstevel@tonic-gate else {
8420Sstevel@tonic-gate kthread_t *t = pr_thread(pnp);
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
8450Sstevel@tonic-gate thread_unlock(t);
8460Sstevel@tonic-gate error = EBUSY;
8470Sstevel@tonic-gate } else {
8480Sstevel@tonic-gate prgregset_t prgregset;
8490Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate thread_unlock(t);
8520Sstevel@tonic-gate mutex_exit(&p->p_lock);
8530Sstevel@tonic-gate prgregset_32ton(lwp, argp->prgregset,
8545771Sjp151216 prgregset);
8550Sstevel@tonic-gate prsetprregs(lwp, prgregset, 0);
8560Sstevel@tonic-gate mutex_enter(&p->p_lock);
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate }
8590Sstevel@tonic-gate break;
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate case PCSFPREG: /* set floating-point registers */
8620Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
8630Sstevel@tonic-gate error = EOVERFLOW;
8640Sstevel@tonic-gate else
8650Sstevel@tonic-gate error = pr_setfpregs32(pnp, &argp->prfpregset);
8660Sstevel@tonic-gate break;
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate case PCSXREG: /* set extra registers */
8690Sstevel@tonic-gate #if defined(__sparc)
8700Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
8710Sstevel@tonic-gate error = EOVERFLOW;
8720Sstevel@tonic-gate else
8730Sstevel@tonic-gate error = pr_setxregs(pnp, &argp->prxregset);
8740Sstevel@tonic-gate #else
8750Sstevel@tonic-gate error = EINVAL;
8760Sstevel@tonic-gate #endif
8770Sstevel@tonic-gate break;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate case PCSVADDR: /* set virtual address at which to resume */
8800Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
8810Sstevel@tonic-gate error = EOVERFLOW;
8820Sstevel@tonic-gate else
8830Sstevel@tonic-gate error = pr_setvaddr(pnp,
8840Sstevel@tonic-gate (caddr_t)(uintptr_t)argp->vaddr);
8850Sstevel@tonic-gate break;
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate case PCSHOLD: /* set signal-hold mask */
8880Sstevel@tonic-gate pr_sethold(pnp, &argp->sigset);
8890Sstevel@tonic-gate break;
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate case PCSFAULT: /* set mask of traced faults */
8920Sstevel@tonic-gate pr_setfault(p, &argp->fltset);
8930Sstevel@tonic-gate break;
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate case PCCSIG: /* clear current signal */
8960Sstevel@tonic-gate error = pr_clearsig(pnp);
8970Sstevel@tonic-gate break;
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate case PCCFAULT: /* clear current fault */
9000Sstevel@tonic-gate error = pr_clearflt(pnp);
9010Sstevel@tonic-gate break;
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate case PCWATCH: /* set or clear watched areas */
9040Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
9050Sstevel@tonic-gate error = EOVERFLOW;
9060Sstevel@tonic-gate else {
9070Sstevel@tonic-gate prwatch_t prwatch;
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate prwatch.pr_vaddr = argp->prwatch.pr_vaddr;
9100Sstevel@tonic-gate prwatch.pr_size = argp->prwatch.pr_size;
9110Sstevel@tonic-gate prwatch.pr_wflags = argp->prwatch.pr_wflags;
9120Sstevel@tonic-gate prwatch.pr_pad = argp->prwatch.pr_pad;
9130Sstevel@tonic-gate error = pr_watch(pnp, &prwatch, &unlocked);
9140Sstevel@tonic-gate if (error && unlocked)
9150Sstevel@tonic-gate return (error);
9160Sstevel@tonic-gate }
9170Sstevel@tonic-gate break;
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate case PCAGENT: /* create the /proc agent lwp in the target process */
9200Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
9210Sstevel@tonic-gate error = EOVERFLOW;
9220Sstevel@tonic-gate else {
9230Sstevel@tonic-gate prgregset_t prgregset;
9240Sstevel@tonic-gate kthread_t *t = pr_thread(pnp);
9250Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
9260Sstevel@tonic-gate thread_unlock(t);
9270Sstevel@tonic-gate mutex_exit(&p->p_lock);
9280Sstevel@tonic-gate prgregset_32ton(lwp, argp->prgregset, prgregset);
9290Sstevel@tonic-gate mutex_enter(&p->p_lock);
9300Sstevel@tonic-gate error = pr_agent(pnp, prgregset, &unlocked);
9310Sstevel@tonic-gate if (error && unlocked)
9320Sstevel@tonic-gate return (error);
9330Sstevel@tonic-gate }
9340Sstevel@tonic-gate break;
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate case PCREAD: /* read from the address space */
9370Sstevel@tonic-gate case PCWRITE: /* write to the address space */
9380Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p))
9390Sstevel@tonic-gate error = EOVERFLOW;
9400Sstevel@tonic-gate else {
9410Sstevel@tonic-gate enum uio_rw rw = (cmd == PCREAD)? UIO_READ : UIO_WRITE;
9420Sstevel@tonic-gate priovec_t priovec;
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate priovec.pio_base =
9450Sstevel@tonic-gate (void *)(uintptr_t)argp->priovec.pio_base;
9460Sstevel@tonic-gate priovec.pio_len = (size_t)argp->priovec.pio_len;
9470Sstevel@tonic-gate priovec.pio_offset = (off_t)
9485771Sjp151216 (uint32_t)argp->priovec.pio_offset;
9490Sstevel@tonic-gate error = pr_rdwr(p, rw, &priovec);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate break;
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate case PCSCRED: /* set the process credentials */
9540Sstevel@tonic-gate case PCSCREDX:
9555771Sjp151216 {
9565771Sjp151216 /*
9575771Sjp151216 * All the fields in these structures are exactly the
9585771Sjp151216 * same and so the structures are compatible. In case
9595771Sjp151216 * this ever changes, we catch this with the ASSERT
9605771Sjp151216 * below.
9615771Sjp151216 */
9625771Sjp151216 prcred_t *prcred = (prcred_t *)&argp->prcred;
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate #ifndef __lint
9655771Sjp151216 ASSERT(sizeof (prcred_t) == sizeof (prcred32_t));
9660Sstevel@tonic-gate #endif
9670Sstevel@tonic-gate
9685771Sjp151216 error = pr_scred(p, prcred, cr, cmd == PCSCREDX);
9695771Sjp151216 break;
9705771Sjp151216 }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate case PCSPRIV: /* set the process privileges */
9736247Sraf error = pr_spriv(p, &argp->prpriv, cr);
9746247Sraf break;
9750Sstevel@tonic-gate
9760Sstevel@tonic-gate case PCSZONE: /* set the process's zoneid */
9775771Sjp151216 error = pr_szoneid(p, (zoneid_t)argp->przoneid, cr);
9785771Sjp151216 break;
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate if (error)
9820Sstevel@tonic-gate prunlock(pnp);
9830Sstevel@tonic-gate return (error);
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * Return the specific or chosen thread/lwp for a control operation.
9900Sstevel@tonic-gate * Returns with the thread locked via thread_lock(t).
9910Sstevel@tonic-gate */
9920Sstevel@tonic-gate kthread_t *
pr_thread(prnode_t * pnp)9930Sstevel@tonic-gate pr_thread(prnode_t *pnp)
9940Sstevel@tonic-gate {
9950Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
9960Sstevel@tonic-gate kthread_t *t;
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP) {
9990Sstevel@tonic-gate t = pcp->prc_thread;
10000Sstevel@tonic-gate ASSERT(t != NULL);
10010Sstevel@tonic-gate thread_lock(t);
10020Sstevel@tonic-gate } else {
10030Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
10040Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
10050Sstevel@tonic-gate ASSERT(t != NULL);
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate return (t);
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate /*
10120Sstevel@tonic-gate * Direct the process or lwp to stop.
10130Sstevel@tonic-gate */
10140Sstevel@tonic-gate void
pr_stop(prnode_t * pnp)10150Sstevel@tonic-gate pr_stop(prnode_t *pnp)
10160Sstevel@tonic-gate {
10170Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
10180Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
10190Sstevel@tonic-gate kthread_t *t;
10200Sstevel@tonic-gate vnode_t *vp;
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate /*
10230Sstevel@tonic-gate * If already stopped, do nothing; otherwise flag
10240Sstevel@tonic-gate * it to be stopped the next time it tries to run.
10250Sstevel@tonic-gate * If sleeping at interruptible priority, set it
10260Sstevel@tonic-gate * running so it will stop within cv_wait_sig().
10270Sstevel@tonic-gate *
10280Sstevel@tonic-gate * Take care to cooperate with jobcontrol: if an lwp
10290Sstevel@tonic-gate * is stopped due to the default action of a jobcontrol
10300Sstevel@tonic-gate * stop signal, flag it to be stopped the next time it
10310Sstevel@tonic-gate * starts due to a SIGCONT signal.
10320Sstevel@tonic-gate */
10330Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP)
10340Sstevel@tonic-gate t = pcp->prc_thread;
10350Sstevel@tonic-gate else
10360Sstevel@tonic-gate t = p->p_tlist;
10370Sstevel@tonic-gate ASSERT(t != NULL);
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate do {
10400Sstevel@tonic-gate int notify;
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate notify = 0;
10430Sstevel@tonic-gate thread_lock(t);
10440Sstevel@tonic-gate if (!ISTOPPED(t)) {
10450Sstevel@tonic-gate t->t_proc_flag |= TP_PRSTOP;
10460Sstevel@tonic-gate t->t_sig_check = 1; /* do ISSIG */
10470Sstevel@tonic-gate }
10483792Sakolb
10493792Sakolb /* Move the thread from wait queue to run queue */
10503792Sakolb if (ISWAITING(t))
10513792Sakolb setrun_locked(t);
10523792Sakolb
10533792Sakolb if (ISWAKEABLE(t)) {
10540Sstevel@tonic-gate if (t->t_wchan0 == NULL)
10550Sstevel@tonic-gate setrun_locked(t);
10560Sstevel@tonic-gate else if (!VSTOPPED(t)) {
10570Sstevel@tonic-gate /*
10580Sstevel@tonic-gate * Mark it virtually stopped.
10590Sstevel@tonic-gate */
10600Sstevel@tonic-gate t->t_proc_flag |= TP_PRVSTOP;
10610Sstevel@tonic-gate notify = 1;
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate * force the thread into the kernel
10660Sstevel@tonic-gate * if it is not already there.
10670Sstevel@tonic-gate */
10680Sstevel@tonic-gate prpokethread(t);
10690Sstevel@tonic-gate thread_unlock(t);
10700Sstevel@tonic-gate if (notify &&
10710Sstevel@tonic-gate (vp = p->p_lwpdir[t->t_dslot].ld_entry->le_trace) != NULL)
10720Sstevel@tonic-gate prnotify(vp);
10730Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP)
10740Sstevel@tonic-gate break;
10750Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /*
10780Sstevel@tonic-gate * We do this just in case the thread we asked
10790Sstevel@tonic-gate * to stop is in holdlwps() (called from cfork()).
10800Sstevel@tonic-gate */
10810Sstevel@tonic-gate cv_broadcast(&p->p_holdlwps);
10820Sstevel@tonic-gate }
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate /*
10850Sstevel@tonic-gate * Sleep until the lwp stops, but cooperate with
10860Sstevel@tonic-gate * jobcontrol: Don't wake up if the lwp is stopped
10870Sstevel@tonic-gate * due to the default action of a jobcontrol stop signal.
10880Sstevel@tonic-gate * If this is the process file descriptor, sleep
10890Sstevel@tonic-gate * until all of the process's lwps stop.
10900Sstevel@tonic-gate */
10910Sstevel@tonic-gate int
pr_wait_stop(prnode_t * pnp,time_t timeo)10920Sstevel@tonic-gate pr_wait_stop(prnode_t *pnp, time_t timeo)
10930Sstevel@tonic-gate {
10940Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
10950Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
10960Sstevel@tonic-gate timestruc_t rqtime;
10970Sstevel@tonic-gate timestruc_t *rqtp = NULL;
10984123Sdm120769 int timecheck = 0;
10990Sstevel@tonic-gate kthread_t *t;
11000Sstevel@tonic-gate int error;
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate if (timeo > 0) { /* millisecond timeout */
11030Sstevel@tonic-gate /*
11040Sstevel@tonic-gate * Determine the precise future time of the requested timeout.
11050Sstevel@tonic-gate */
11060Sstevel@tonic-gate timestruc_t now;
11070Sstevel@tonic-gate
11084123Sdm120769 timecheck = timechanged;
11090Sstevel@tonic-gate gethrestime(&now);
11100Sstevel@tonic-gate rqtp = &rqtime;
11110Sstevel@tonic-gate rqtp->tv_sec = timeo / MILLISEC;
11120Sstevel@tonic-gate rqtp->tv_nsec = (timeo % MILLISEC) * MICROSEC;
11130Sstevel@tonic-gate timespecadd(rqtp, &now);
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP) { /* lwp file descriptor */
11170Sstevel@tonic-gate t = pcp->prc_thread;
11180Sstevel@tonic-gate ASSERT(t != NULL);
11190Sstevel@tonic-gate thread_lock(t);
11200Sstevel@tonic-gate while (!ISTOPPED(t) && !VSTOPPED(t)) {
11210Sstevel@tonic-gate thread_unlock(t);
11220Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
11230Sstevel@tonic-gate prunlock(pnp);
11244123Sdm120769 error = pr_wait(pcp, rqtp, timecheck);
11250Sstevel@tonic-gate if (error) /* -1 is timeout */
11260Sstevel@tonic-gate return (error);
11270Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
11280Sstevel@tonic-gate return (error);
11290Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
11300Sstevel@tonic-gate ASSERT(t == pcp->prc_thread);
11310Sstevel@tonic-gate thread_lock(t);
11320Sstevel@tonic-gate }
11330Sstevel@tonic-gate thread_unlock(t);
11340Sstevel@tonic-gate } else { /* process file descriptor */
11350Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
11360Sstevel@tonic-gate ASSERT(t != NULL);
11370Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
11380Sstevel@tonic-gate while ((!ISTOPPED(t) && !VSTOPPED(t) && !SUSPENDED(t)) ||
11390Sstevel@tonic-gate (p->p_flag & SEXITLWPS)) {
11400Sstevel@tonic-gate thread_unlock(t);
11410Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
11420Sstevel@tonic-gate prunlock(pnp);
11434123Sdm120769 error = pr_wait(pcp, rqtp, timecheck);
11440Sstevel@tonic-gate if (error) /* -1 is timeout */
11450Sstevel@tonic-gate return (error);
11460Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
11470Sstevel@tonic-gate return (error);
11480Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
11490Sstevel@tonic-gate t = prchoose(p); /* returns locked t */
11500Sstevel@tonic-gate ASSERT(t != NULL);
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate thread_unlock(t);
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate ASSERT(!(pcp->prc_flags & PRC_DESTROY) && p->p_stat != SZOMB &&
11560Sstevel@tonic-gate t != NULL && t->t_state != TS_ZOMB);
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate return (0);
11590Sstevel@tonic-gate }
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate int
pr_setrun(prnode_t * pnp,ulong_t flags)11620Sstevel@tonic-gate pr_setrun(prnode_t *pnp, ulong_t flags)
11630Sstevel@tonic-gate {
11640Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
11650Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
11660Sstevel@tonic-gate kthread_t *t;
11670Sstevel@tonic-gate klwp_t *lwp;
11680Sstevel@tonic-gate
11690Sstevel@tonic-gate /*
11700Sstevel@tonic-gate * Cannot set an lwp running if it is not stopped.
11710Sstevel@tonic-gate * Also, no lwp other than the /proc agent lwp can
11720Sstevel@tonic-gate * be set running so long as the /proc agent lwp exists.
11730Sstevel@tonic-gate */
11740Sstevel@tonic-gate t = pr_thread(pnp); /* returns locked thread */
11750Sstevel@tonic-gate if ((!ISTOPPED(t) && !VSTOPPED(t) &&
11760Sstevel@tonic-gate !(t->t_proc_flag & TP_PRSTOP)) ||
11770Sstevel@tonic-gate (p->p_agenttp != NULL &&
11780Sstevel@tonic-gate (t != p->p_agenttp || !(pcp->prc_flags & PRC_LWP)))) {
11790Sstevel@tonic-gate thread_unlock(t);
11800Sstevel@tonic-gate return (EBUSY);
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate thread_unlock(t);
11830Sstevel@tonic-gate if (flags & ~(PRCSIG|PRCFAULT|PRSTEP|PRSTOP|PRSABORT))
11840Sstevel@tonic-gate return (EINVAL);
11850Sstevel@tonic-gate lwp = ttolwp(t);
11860Sstevel@tonic-gate if ((flags & PRCSIG) && lwp->lwp_cursig != SIGKILL) {
11870Sstevel@tonic-gate /*
11880Sstevel@tonic-gate * Discard current siginfo_t, if any.
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate lwp->lwp_cursig = 0;
11910Sstevel@tonic-gate lwp->lwp_extsig = 0;
11920Sstevel@tonic-gate if (lwp->lwp_curinfo) {
11930Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo);
11940Sstevel@tonic-gate lwp->lwp_curinfo = NULL;
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate if (flags & PRCFAULT)
11980Sstevel@tonic-gate lwp->lwp_curflt = 0;
11990Sstevel@tonic-gate /*
12000Sstevel@tonic-gate * We can't hold p->p_lock when we touch the lwp's registers.
12010Sstevel@tonic-gate * It may be swapped out and we will get a page fault.
12020Sstevel@tonic-gate */
12030Sstevel@tonic-gate if (flags & PRSTEP) {
12040Sstevel@tonic-gate mutex_exit(&p->p_lock);
12050Sstevel@tonic-gate prstep(lwp, 0);
12060Sstevel@tonic-gate mutex_enter(&p->p_lock);
12070Sstevel@tonic-gate }
12080Sstevel@tonic-gate if (flags & PRSTOP) {
12090Sstevel@tonic-gate t->t_proc_flag |= TP_PRSTOP;
12100Sstevel@tonic-gate t->t_sig_check = 1; /* do ISSIG */
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate if (flags & PRSABORT)
12130Sstevel@tonic-gate lwp->lwp_sysabort = 1;
12140Sstevel@tonic-gate thread_lock(t);
12150Sstevel@tonic-gate if ((pcp->prc_flags & PRC_LWP) || (flags & (PRSTEP|PRSTOP))) {
12160Sstevel@tonic-gate /*
12170Sstevel@tonic-gate * Here, we are dealing with a single lwp.
12180Sstevel@tonic-gate */
12190Sstevel@tonic-gate if (ISTOPPED(t)) {
12200Sstevel@tonic-gate t->t_schedflag |= TS_PSTART;
12210Sstevel@tonic-gate t->t_dtrace_stop = 0;
12220Sstevel@tonic-gate setrun_locked(t);
12230Sstevel@tonic-gate } else if (flags & PRSABORT) {
12240Sstevel@tonic-gate t->t_proc_flag &=
12250Sstevel@tonic-gate ~(TP_PRSTOP|TP_PRVSTOP|TP_STOPPING);
12260Sstevel@tonic-gate setrun_locked(t);
12270Sstevel@tonic-gate } else if (!(flags & PRSTOP)) {
12280Sstevel@tonic-gate t->t_proc_flag &=
12290Sstevel@tonic-gate ~(TP_PRSTOP|TP_PRVSTOP|TP_STOPPING);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate thread_unlock(t);
12320Sstevel@tonic-gate } else {
12330Sstevel@tonic-gate /*
12340Sstevel@tonic-gate * Here, we are dealing with the whole process.
12350Sstevel@tonic-gate */
12360Sstevel@tonic-gate if (ISTOPPED(t)) {
12370Sstevel@tonic-gate /*
12380Sstevel@tonic-gate * The representative lwp is stopped on an event
12390Sstevel@tonic-gate * of interest. We demote it to PR_REQUESTED and
12400Sstevel@tonic-gate * choose another representative lwp. If the new
12410Sstevel@tonic-gate * representative lwp is not stopped on an event of
12420Sstevel@tonic-gate * interest (other than PR_REQUESTED), we set the
12430Sstevel@tonic-gate * whole process running, else we leave the process
12440Sstevel@tonic-gate * stopped showing the next event of interest.
12450Sstevel@tonic-gate */
12460Sstevel@tonic-gate kthread_t *tx = NULL;
12470Sstevel@tonic-gate
12480Sstevel@tonic-gate if (!(flags & PRSABORT) &&
12490Sstevel@tonic-gate t->t_whystop == PR_SYSENTRY &&
12500Sstevel@tonic-gate t->t_whatstop == SYS_lwp_exit)
12510Sstevel@tonic-gate tx = t; /* remember the exiting lwp */
12520Sstevel@tonic-gate t->t_whystop = PR_REQUESTED;
12530Sstevel@tonic-gate t->t_whatstop = 0;
12540Sstevel@tonic-gate thread_unlock(t);
12550Sstevel@tonic-gate t = prchoose(p); /* returns locked t */
12560Sstevel@tonic-gate ASSERT(ISTOPPED(t) || VSTOPPED(t));
12570Sstevel@tonic-gate if (VSTOPPED(t) ||
12580Sstevel@tonic-gate t->t_whystop == PR_REQUESTED) {
12590Sstevel@tonic-gate thread_unlock(t);
12600Sstevel@tonic-gate allsetrun(p);
12610Sstevel@tonic-gate } else {
12620Sstevel@tonic-gate thread_unlock(t);
12630Sstevel@tonic-gate /*
12640Sstevel@tonic-gate * As a special case, if the old representative
12650Sstevel@tonic-gate * lwp was stopped on entry to _lwp_exit()
12660Sstevel@tonic-gate * (and we are not aborting the system call),
12670Sstevel@tonic-gate * we set the old representative lwp running.
12680Sstevel@tonic-gate * We do this so that the next process stop
12690Sstevel@tonic-gate * will find the exiting lwp gone.
12700Sstevel@tonic-gate */
12710Sstevel@tonic-gate if (tx != NULL) {
12720Sstevel@tonic-gate thread_lock(tx);
12730Sstevel@tonic-gate tx->t_schedflag |= TS_PSTART;
12740Sstevel@tonic-gate t->t_dtrace_stop = 0;
12750Sstevel@tonic-gate setrun_locked(tx);
12760Sstevel@tonic-gate thread_unlock(tx);
12770Sstevel@tonic-gate }
12780Sstevel@tonic-gate }
12790Sstevel@tonic-gate } else {
12800Sstevel@tonic-gate /*
12810Sstevel@tonic-gate * No event of interest; set all of the lwps running.
12820Sstevel@tonic-gate */
12830Sstevel@tonic-gate if (flags & PRSABORT) {
12840Sstevel@tonic-gate t->t_proc_flag &=
12850Sstevel@tonic-gate ~(TP_PRSTOP|TP_PRVSTOP|TP_STOPPING);
12860Sstevel@tonic-gate setrun_locked(t);
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate thread_unlock(t);
12890Sstevel@tonic-gate allsetrun(p);
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate }
12920Sstevel@tonic-gate return (0);
12930Sstevel@tonic-gate }
12940Sstevel@tonic-gate
12950Sstevel@tonic-gate /*
12960Sstevel@tonic-gate * Wait until process/lwp stops or until timer expires.
12970Sstevel@tonic-gate * Return EINTR for an interruption, -1 for timeout, else 0.
12980Sstevel@tonic-gate */
12990Sstevel@tonic-gate int
pr_wait(prcommon_t * pcp,timestruc_t * ts,int timecheck)13000Sstevel@tonic-gate pr_wait(prcommon_t *pcp, /* prcommon referring to process/lwp */
13014123Sdm120769 timestruc_t *ts, /* absolute time of timeout, if any */
13024123Sdm120769 int timecheck)
13030Sstevel@tonic-gate {
13040Sstevel@tonic-gate int rval;
13050Sstevel@tonic-gate
13060Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pcp->prc_mutex));
13074123Sdm120769 rval = cv_waituntil_sig(&pcp->prc_wait, &pcp->prc_mutex, ts, timecheck);
13080Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
13090Sstevel@tonic-gate switch (rval) {
13100Sstevel@tonic-gate case 0:
13110Sstevel@tonic-gate return (EINTR);
13120Sstevel@tonic-gate case -1:
13130Sstevel@tonic-gate return (-1);
13140Sstevel@tonic-gate default:
13150Sstevel@tonic-gate return (0);
13160Sstevel@tonic-gate }
13170Sstevel@tonic-gate }
13180Sstevel@tonic-gate
13190Sstevel@tonic-gate /*
13200Sstevel@tonic-gate * Make all threads in the process runnable.
13210Sstevel@tonic-gate */
13220Sstevel@tonic-gate void
allsetrun(proc_t * p)13230Sstevel@tonic-gate allsetrun(proc_t *p)
13240Sstevel@tonic-gate {
13250Sstevel@tonic-gate kthread_t *t;
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
13300Sstevel@tonic-gate do {
13310Sstevel@tonic-gate thread_lock(t);
13320Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
13330Sstevel@tonic-gate t->t_proc_flag &= ~(TP_PRSTOP|TP_PRVSTOP|TP_STOPPING);
13340Sstevel@tonic-gate if (ISTOPPED(t)) {
13350Sstevel@tonic-gate t->t_schedflag |= TS_PSTART;
13360Sstevel@tonic-gate t->t_dtrace_stop = 0;
13370Sstevel@tonic-gate setrun_locked(t);
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate thread_unlock(t);
13400Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate }
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate /*
13450Sstevel@tonic-gate * Wait for the process to die.
13460Sstevel@tonic-gate * We do this after sending SIGKILL because we know it will
13470Sstevel@tonic-gate * die soon and we want subsequent operations to return ENOENT.
13480Sstevel@tonic-gate */
13490Sstevel@tonic-gate void
pr_wait_die(prnode_t * pnp)13500Sstevel@tonic-gate pr_wait_die(prnode_t *pnp)
13510Sstevel@tonic-gate {
13520Sstevel@tonic-gate proc_t *p;
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate mutex_enter(&pidlock);
13550Sstevel@tonic-gate while ((p = pnp->pr_common->prc_proc) != NULL && p->p_stat != SZOMB) {
13560Sstevel@tonic-gate if (!cv_wait_sig(&p->p_srwchan_cv, &pidlock))
13570Sstevel@tonic-gate break;
13580Sstevel@tonic-gate }
13590Sstevel@tonic-gate mutex_exit(&pidlock);
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate
13620Sstevel@tonic-gate static void
pr_settrace(proc_t * p,sigset_t * sp)13630Sstevel@tonic-gate pr_settrace(proc_t *p, sigset_t *sp)
13640Sstevel@tonic-gate {
13650Sstevel@tonic-gate prdelset(sp, SIGKILL);
13660Sstevel@tonic-gate prassignset(&p->p_sigmask, sp);
13670Sstevel@tonic-gate if (!sigisempty(&p->p_sigmask))
13680Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
13690Sstevel@tonic-gate else if (prisempty(&p->p_fltmask)) {
13700Sstevel@tonic-gate user_t *up = PTOU(p);
13710Sstevel@tonic-gate if (up->u_systrap == 0)
13720Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
13730Sstevel@tonic-gate }
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate
13760Sstevel@tonic-gate int
pr_setsig(prnode_t * pnp,siginfo_t * sip)13770Sstevel@tonic-gate pr_setsig(prnode_t *pnp, siginfo_t *sip)
13780Sstevel@tonic-gate {
1379*11940SRoger.Faulkner@Sun.COM int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
13800Sstevel@tonic-gate int sig = sip->si_signo;
13810Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
13820Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
13830Sstevel@tonic-gate kthread_t *t;
13840Sstevel@tonic-gate klwp_t *lwp;
13850Sstevel@tonic-gate int error = 0;
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate t = pr_thread(pnp); /* returns locked thread */
13880Sstevel@tonic-gate thread_unlock(t);
13890Sstevel@tonic-gate lwp = ttolwp(t);
1390*11940SRoger.Faulkner@Sun.COM if (sig < 0 || sig >= nsig)
13910Sstevel@tonic-gate /* Zero allowed here */
13920Sstevel@tonic-gate error = EINVAL;
13930Sstevel@tonic-gate else if (lwp->lwp_cursig == SIGKILL)
13940Sstevel@tonic-gate /* "can't happen", but just in case */
13950Sstevel@tonic-gate error = EBUSY;
13960Sstevel@tonic-gate else if ((lwp->lwp_cursig = (uchar_t)sig) == 0) {
13970Sstevel@tonic-gate lwp->lwp_extsig = 0;
13980Sstevel@tonic-gate /*
13990Sstevel@tonic-gate * Discard current siginfo_t, if any.
14000Sstevel@tonic-gate */
14010Sstevel@tonic-gate if (lwp->lwp_curinfo) {
14020Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo);
14030Sstevel@tonic-gate lwp->lwp_curinfo = NULL;
14040Sstevel@tonic-gate }
14050Sstevel@tonic-gate } else {
14060Sstevel@tonic-gate kthread_t *tx;
14070Sstevel@tonic-gate sigqueue_t *sqp;
14080Sstevel@tonic-gate
14090Sstevel@tonic-gate /* drop p_lock to do kmem_alloc(KM_SLEEP) */
14100Sstevel@tonic-gate mutex_exit(&p->p_lock);
14110Sstevel@tonic-gate sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
14120Sstevel@tonic-gate mutex_enter(&p->p_lock);
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate if (lwp->lwp_curinfo == NULL)
14150Sstevel@tonic-gate lwp->lwp_curinfo = sqp;
14160Sstevel@tonic-gate else
14170Sstevel@tonic-gate kmem_free(sqp, sizeof (sigqueue_t));
14180Sstevel@tonic-gate /*
14190Sstevel@tonic-gate * Copy contents of info to current siginfo_t.
14200Sstevel@tonic-gate */
14210Sstevel@tonic-gate bcopy(sip, &lwp->lwp_curinfo->sq_info,
14220Sstevel@tonic-gate sizeof (lwp->lwp_curinfo->sq_info));
14230Sstevel@tonic-gate /*
14240Sstevel@tonic-gate * Prevent contents published by si_zoneid-unaware /proc
14250Sstevel@tonic-gate * consumers from being incorrectly filtered. Because
14260Sstevel@tonic-gate * an uninitialized si_zoneid is the same as
14270Sstevel@tonic-gate * GLOBAL_ZONEID, this means that you can't pr_setsig a
14280Sstevel@tonic-gate * process in a non-global zone with a siginfo which
14290Sstevel@tonic-gate * appears to come from the global zone.
14300Sstevel@tonic-gate */
14310Sstevel@tonic-gate if (SI_FROMUSER(sip) && sip->si_zoneid == 0)
14320Sstevel@tonic-gate lwp->lwp_curinfo->sq_info.si_zoneid =
14330Sstevel@tonic-gate p->p_zone->zone_id;
14340Sstevel@tonic-gate /*
14350Sstevel@tonic-gate * Side-effects for SIGKILL and jobcontrol signals.
14360Sstevel@tonic-gate */
14370Sstevel@tonic-gate if (sig == SIGKILL) {
14380Sstevel@tonic-gate p->p_flag |= SKILLED;
14390Sstevel@tonic-gate p->p_flag &= ~SEXTKILLED;
14400Sstevel@tonic-gate } else if (sig == SIGCONT) {
14410Sstevel@tonic-gate p->p_flag |= SSCONT;
14420Sstevel@tonic-gate sigdelq(p, NULL, SIGSTOP);
14430Sstevel@tonic-gate sigdelq(p, NULL, SIGTSTP);
14440Sstevel@tonic-gate sigdelq(p, NULL, SIGTTOU);
14450Sstevel@tonic-gate sigdelq(p, NULL, SIGTTIN);
14460Sstevel@tonic-gate sigdiffset(&p->p_sig, &stopdefault);
14470Sstevel@tonic-gate sigdiffset(&p->p_extsig, &stopdefault);
14480Sstevel@tonic-gate if ((tx = p->p_tlist) != NULL) {
14490Sstevel@tonic-gate do {
14500Sstevel@tonic-gate sigdelq(p, tx, SIGSTOP);
14510Sstevel@tonic-gate sigdelq(p, tx, SIGTSTP);
14520Sstevel@tonic-gate sigdelq(p, tx, SIGTTOU);
14530Sstevel@tonic-gate sigdelq(p, tx, SIGTTIN);
14540Sstevel@tonic-gate sigdiffset(&tx->t_sig, &stopdefault);
14550Sstevel@tonic-gate sigdiffset(&tx->t_extsig, &stopdefault);
14560Sstevel@tonic-gate } while ((tx = tx->t_forw) != p->p_tlist);
14570Sstevel@tonic-gate }
14580Sstevel@tonic-gate } else if (sigismember(&stopdefault, sig)) {
14590Sstevel@tonic-gate if (PTOU(p)->u_signal[sig-1] == SIG_DFL &&
14600Sstevel@tonic-gate (sig == SIGSTOP || !p->p_pgidp->pid_pgorphaned))
14610Sstevel@tonic-gate p->p_flag &= ~SSCONT;
14620Sstevel@tonic-gate sigdelq(p, NULL, SIGCONT);
14630Sstevel@tonic-gate sigdelset(&p->p_sig, SIGCONT);
14640Sstevel@tonic-gate sigdelset(&p->p_extsig, SIGCONT);
14650Sstevel@tonic-gate if ((tx = p->p_tlist) != NULL) {
14660Sstevel@tonic-gate do {
14670Sstevel@tonic-gate sigdelq(p, tx, SIGCONT);
14680Sstevel@tonic-gate sigdelset(&tx->t_sig, SIGCONT);
14690Sstevel@tonic-gate sigdelset(&tx->t_extsig, SIGCONT);
14700Sstevel@tonic-gate } while ((tx = tx->t_forw) != p->p_tlist);
14710Sstevel@tonic-gate }
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate thread_lock(t);
14743792Sakolb if (ISWAKEABLE(t) || ISWAITING(t)) {
14755331Samw /* Set signaled sleeping/waiting lwp running */
14760Sstevel@tonic-gate setrun_locked(t);
14770Sstevel@tonic-gate } else if (t->t_state == TS_STOPPED && sig == SIGKILL) {
14780Sstevel@tonic-gate /* If SIGKILL, set stopped lwp running */
14790Sstevel@tonic-gate p->p_stopsig = 0;
14800Sstevel@tonic-gate t->t_schedflag |= TS_XSTART | TS_PSTART;
14810Sstevel@tonic-gate t->t_dtrace_stop = 0;
14820Sstevel@tonic-gate setrun_locked(t);
14830Sstevel@tonic-gate }
14840Sstevel@tonic-gate t->t_sig_check = 1; /* so ISSIG will be done */
14850Sstevel@tonic-gate thread_unlock(t);
14860Sstevel@tonic-gate /*
14870Sstevel@tonic-gate * More jobcontrol side-effects.
14880Sstevel@tonic-gate */
14890Sstevel@tonic-gate if (sig == SIGCONT && (tx = p->p_tlist) != NULL) {
14900Sstevel@tonic-gate p->p_stopsig = 0;
14910Sstevel@tonic-gate do {
14920Sstevel@tonic-gate thread_lock(tx);
14930Sstevel@tonic-gate if (tx->t_state == TS_STOPPED &&
14940Sstevel@tonic-gate tx->t_whystop == PR_JOBCONTROL) {
14950Sstevel@tonic-gate tx->t_schedflag |= TS_XSTART;
14960Sstevel@tonic-gate setrun_locked(tx);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate thread_unlock(tx);
14990Sstevel@tonic-gate } while ((tx = tx->t_forw) != p->p_tlist);
15000Sstevel@tonic-gate }
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate return (error);
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate int
pr_kill(prnode_t * pnp,int sig,cred_t * cr)15060Sstevel@tonic-gate pr_kill(prnode_t *pnp, int sig, cred_t *cr)
15070Sstevel@tonic-gate {
1508*11940SRoger.Faulkner@Sun.COM int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
15090Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
15100Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
15110Sstevel@tonic-gate k_siginfo_t info;
15120Sstevel@tonic-gate
1513*11940SRoger.Faulkner@Sun.COM if (sig <= 0 || sig >= nsig)
15140Sstevel@tonic-gate return (EINVAL);
15150Sstevel@tonic-gate
15160Sstevel@tonic-gate bzero(&info, sizeof (info));
15170Sstevel@tonic-gate info.si_signo = sig;
15180Sstevel@tonic-gate info.si_code = SI_USER;
15190Sstevel@tonic-gate info.si_pid = curproc->p_pid;
15200Sstevel@tonic-gate info.si_ctid = PRCTID(curproc);
15210Sstevel@tonic-gate info.si_zoneid = getzoneid();
15220Sstevel@tonic-gate info.si_uid = crgetruid(cr);
15230Sstevel@tonic-gate sigaddq(p, (pcp->prc_flags & PRC_LWP)?
15240Sstevel@tonic-gate pcp->prc_thread : NULL, &info, KM_NOSLEEP);
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate return (0);
15270Sstevel@tonic-gate }
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate int
pr_unkill(prnode_t * pnp,int sig)15300Sstevel@tonic-gate pr_unkill(prnode_t *pnp, int sig)
15310Sstevel@tonic-gate {
1532*11940SRoger.Faulkner@Sun.COM int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
15330Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
15340Sstevel@tonic-gate proc_t *p = pcp->prc_proc;
15350Sstevel@tonic-gate sigqueue_t *infop = NULL;
15360Sstevel@tonic-gate
1537*11940SRoger.Faulkner@Sun.COM if (sig <= 0 || sig >= nsig || sig == SIGKILL)
15380Sstevel@tonic-gate return (EINVAL);
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP)
15410Sstevel@tonic-gate sigdeq(p, pcp->prc_thread, sig, &infop);
15420Sstevel@tonic-gate else
15430Sstevel@tonic-gate sigdeq(p, NULL, sig, &infop);
15440Sstevel@tonic-gate
15450Sstevel@tonic-gate if (infop)
15460Sstevel@tonic-gate siginfofree(infop);
15470Sstevel@tonic-gate
15480Sstevel@tonic-gate return (0);
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate int
pr_nice(proc_t * p,int nice,cred_t * cr)15520Sstevel@tonic-gate pr_nice(proc_t *p, int nice, cred_t *cr)
15530Sstevel@tonic-gate {
15540Sstevel@tonic-gate kthread_t *t;
15550Sstevel@tonic-gate int err;
15560Sstevel@tonic-gate int error = 0;
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate t = p->p_tlist;
15590Sstevel@tonic-gate do {
15600Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
15610Sstevel@tonic-gate err = CL_DONICE(t, cr, nice, (int *)NULL);
15626247Sraf schedctl_set_cidpri(t);
15630Sstevel@tonic-gate if (error == 0)
15640Sstevel@tonic-gate error = err;
15650Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate return (error);
15680Sstevel@tonic-gate }
15690Sstevel@tonic-gate
15700Sstevel@tonic-gate void
pr_setentryexit(proc_t * p,sysset_t * sysset,int entry)15710Sstevel@tonic-gate pr_setentryexit(proc_t *p, sysset_t *sysset, int entry)
15720Sstevel@tonic-gate {
15730Sstevel@tonic-gate user_t *up = PTOU(p);
15740Sstevel@tonic-gate
15750Sstevel@tonic-gate if (entry) {
15760Sstevel@tonic-gate prassignset(&up->u_entrymask, sysset);
15770Sstevel@tonic-gate } else {
15780Sstevel@tonic-gate prassignset(&up->u_exitmask, sysset);
15790Sstevel@tonic-gate }
15800Sstevel@tonic-gate if (!prisempty(&up->u_entrymask) ||
15810Sstevel@tonic-gate !prisempty(&up->u_exitmask)) {
15820Sstevel@tonic-gate up->u_systrap = 1;
15830Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
15840Sstevel@tonic-gate set_proc_sys(p); /* set pre and post-sys flags */
15850Sstevel@tonic-gate } else {
15860Sstevel@tonic-gate up->u_systrap = 0;
15870Sstevel@tonic-gate if (sigisempty(&p->p_sigmask) &&
15880Sstevel@tonic-gate prisempty(&p->p_fltmask))
15890Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
15900Sstevel@tonic-gate }
15910Sstevel@tonic-gate }
15920Sstevel@tonic-gate
15930Sstevel@tonic-gate #define ALLFLAGS \
15940Sstevel@tonic-gate (PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_MSFORK|PR_PTRACE)
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate int
pr_set(proc_t * p,long flags)15970Sstevel@tonic-gate pr_set(proc_t *p, long flags)
15980Sstevel@tonic-gate {
15990Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
16000Sstevel@tonic-gate return (EBUSY);
16010Sstevel@tonic-gate
16020Sstevel@tonic-gate if (flags & ~ALLFLAGS)
16030Sstevel@tonic-gate return (EINVAL);
16040Sstevel@tonic-gate
16050Sstevel@tonic-gate if (flags & PR_FORK)
16060Sstevel@tonic-gate p->p_proc_flag |= P_PR_FORK;
16070Sstevel@tonic-gate if (flags & PR_RLC)
16080Sstevel@tonic-gate p->p_proc_flag |= P_PR_RUNLCL;
16090Sstevel@tonic-gate if (flags & PR_KLC)
16100Sstevel@tonic-gate p->p_proc_flag |= P_PR_KILLCL;
16110Sstevel@tonic-gate if (flags & PR_ASYNC)
16120Sstevel@tonic-gate p->p_proc_flag |= P_PR_ASYNC;
16130Sstevel@tonic-gate if (flags & PR_BPTADJ)
16140Sstevel@tonic-gate p->p_proc_flag |= P_PR_BPTADJ;
16150Sstevel@tonic-gate if (flags & PR_MSACCT)
16160Sstevel@tonic-gate if ((p->p_flag & SMSACCT) == 0)
16170Sstevel@tonic-gate estimate_msacct(p->p_tlist, gethrtime());
16180Sstevel@tonic-gate if (flags & PR_MSFORK)
16190Sstevel@tonic-gate p->p_flag |= SMSFORK;
16200Sstevel@tonic-gate if (flags & PR_PTRACE) {
16210Sstevel@tonic-gate p->p_proc_flag |= P_PR_PTRACE;
16220Sstevel@tonic-gate /* ptraced process must die if parent dead */
16230Sstevel@tonic-gate if (p->p_ppid == 1)
16240Sstevel@tonic-gate sigtoproc(p, NULL, SIGKILL);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate return (0);
16280Sstevel@tonic-gate }
16290Sstevel@tonic-gate
16300Sstevel@tonic-gate int
pr_unset(proc_t * p,long flags)16310Sstevel@tonic-gate pr_unset(proc_t *p, long flags)
16320Sstevel@tonic-gate {
16330Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
16340Sstevel@tonic-gate return (EBUSY);
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate if (flags & ~ALLFLAGS)
16370Sstevel@tonic-gate return (EINVAL);
16380Sstevel@tonic-gate
16390Sstevel@tonic-gate if (flags & PR_FORK)
16400Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_FORK;
16410Sstevel@tonic-gate if (flags & PR_RLC)
16420Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_RUNLCL;
16430Sstevel@tonic-gate if (flags & PR_KLC)
16440Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_KILLCL;
16450Sstevel@tonic-gate if (flags & PR_ASYNC)
16460Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_ASYNC;
16470Sstevel@tonic-gate if (flags & PR_BPTADJ)
16480Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_BPTADJ;
16490Sstevel@tonic-gate if (flags & PR_MSACCT)
16500Sstevel@tonic-gate disable_msacct(p);
16510Sstevel@tonic-gate if (flags & PR_MSFORK)
16520Sstevel@tonic-gate p->p_flag &= ~SMSFORK;
16530Sstevel@tonic-gate if (flags & PR_PTRACE)
16540Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_PTRACE;
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate return (0);
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate
16590Sstevel@tonic-gate static int
pr_setfpregs(prnode_t * pnp,prfpregset_t * prfpregset)16600Sstevel@tonic-gate pr_setfpregs(prnode_t *pnp, prfpregset_t *prfpregset)
16610Sstevel@tonic-gate {
16620Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
16630Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
16640Sstevel@tonic-gate
16650Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
16660Sstevel@tonic-gate thread_unlock(t);
16670Sstevel@tonic-gate return (EBUSY);
16680Sstevel@tonic-gate }
16690Sstevel@tonic-gate if (!prhasfp()) {
16700Sstevel@tonic-gate thread_unlock(t);
16710Sstevel@tonic-gate return (EINVAL); /* No FP support */
16720Sstevel@tonic-gate }
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
16750Sstevel@tonic-gate thread_unlock(t);
16760Sstevel@tonic-gate mutex_exit(&p->p_lock);
16770Sstevel@tonic-gate prsetprfpregs(ttolwp(t), prfpregset);
16780Sstevel@tonic-gate mutex_enter(&p->p_lock);
16790Sstevel@tonic-gate
16800Sstevel@tonic-gate return (0);
16810Sstevel@tonic-gate }
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
16840Sstevel@tonic-gate static int
pr_setfpregs32(prnode_t * pnp,prfpregset32_t * prfpregset)16850Sstevel@tonic-gate pr_setfpregs32(prnode_t *pnp, prfpregset32_t *prfpregset)
16860Sstevel@tonic-gate {
16870Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
16880Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
16890Sstevel@tonic-gate
16900Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
16910Sstevel@tonic-gate thread_unlock(t);
16920Sstevel@tonic-gate return (EBUSY);
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate if (!prhasfp()) {
16950Sstevel@tonic-gate thread_unlock(t);
16960Sstevel@tonic-gate return (EINVAL); /* No FP support */
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate
16990Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
17000Sstevel@tonic-gate thread_unlock(t);
17010Sstevel@tonic-gate mutex_exit(&p->p_lock);
17020Sstevel@tonic-gate prsetprfpregs32(ttolwp(t), prfpregset);
17030Sstevel@tonic-gate mutex_enter(&p->p_lock);
17040Sstevel@tonic-gate
17050Sstevel@tonic-gate return (0);
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
17080Sstevel@tonic-gate
17090Sstevel@tonic-gate #if defined(__sparc)
17100Sstevel@tonic-gate /* ARGSUSED */
17110Sstevel@tonic-gate static int
pr_setxregs(prnode_t * pnp,prxregset_t * prxregset)17120Sstevel@tonic-gate pr_setxregs(prnode_t *pnp, prxregset_t *prxregset)
17130Sstevel@tonic-gate {
17140Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
17150Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
17180Sstevel@tonic-gate thread_unlock(t);
17190Sstevel@tonic-gate return (EBUSY);
17200Sstevel@tonic-gate }
17210Sstevel@tonic-gate thread_unlock(t);
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate if (!prhasx(p))
17240Sstevel@tonic-gate return (EINVAL); /* No extra register support */
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
17270Sstevel@tonic-gate mutex_exit(&p->p_lock);
17280Sstevel@tonic-gate prsetprxregs(ttolwp(t), (caddr_t)prxregset);
17290Sstevel@tonic-gate mutex_enter(&p->p_lock);
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate return (0);
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate static int
pr_setasrs(prnode_t * pnp,asrset_t asrset)17350Sstevel@tonic-gate pr_setasrs(prnode_t *pnp, asrset_t asrset)
17360Sstevel@tonic-gate {
17370Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
17380Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
17390Sstevel@tonic-gate
17400Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
17410Sstevel@tonic-gate thread_unlock(t);
17420Sstevel@tonic-gate return (EBUSY);
17430Sstevel@tonic-gate }
17440Sstevel@tonic-gate thread_unlock(t);
17450Sstevel@tonic-gate
17460Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
17470Sstevel@tonic-gate mutex_exit(&p->p_lock);
17480Sstevel@tonic-gate prsetasregs(ttolwp(t), asrset);
17490Sstevel@tonic-gate mutex_enter(&p->p_lock);
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate return (0);
17520Sstevel@tonic-gate }
17530Sstevel@tonic-gate #endif
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate static int
pr_setvaddr(prnode_t * pnp,caddr_t vaddr)17560Sstevel@tonic-gate pr_setvaddr(prnode_t *pnp, caddr_t vaddr)
17570Sstevel@tonic-gate {
17580Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
17590Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
17600Sstevel@tonic-gate
17610Sstevel@tonic-gate if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
17620Sstevel@tonic-gate thread_unlock(t);
17630Sstevel@tonic-gate return (EBUSY);
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate
17660Sstevel@tonic-gate /* drop p_lock while touching the lwp's stack */
17670Sstevel@tonic-gate thread_unlock(t);
17680Sstevel@tonic-gate mutex_exit(&p->p_lock);
17690Sstevel@tonic-gate prsvaddr(ttolwp(t), vaddr);
17700Sstevel@tonic-gate mutex_enter(&p->p_lock);
17710Sstevel@tonic-gate
17720Sstevel@tonic-gate return (0);
17730Sstevel@tonic-gate }
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate void
pr_sethold(prnode_t * pnp,sigset_t * sp)17760Sstevel@tonic-gate pr_sethold(prnode_t *pnp, sigset_t *sp)
17770Sstevel@tonic-gate {
17780Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
17790Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
17800Sstevel@tonic-gate
17810Sstevel@tonic-gate schedctl_finish_sigblock(t);
17820Sstevel@tonic-gate sigutok(sp, &t->t_hold);
17833792Sakolb if (ISWAKEABLE(t) &&
17840Sstevel@tonic-gate (fsig(&p->p_sig, t) || fsig(&t->t_sig, t)))
17850Sstevel@tonic-gate setrun_locked(t);
17860Sstevel@tonic-gate t->t_sig_check = 1; /* so thread will see new holdmask */
17870Sstevel@tonic-gate thread_unlock(t);
17880Sstevel@tonic-gate }
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate void
pr_setfault(proc_t * p,fltset_t * fltp)17910Sstevel@tonic-gate pr_setfault(proc_t *p, fltset_t *fltp)
17920Sstevel@tonic-gate {
17930Sstevel@tonic-gate prassignset(&p->p_fltmask, fltp);
17940Sstevel@tonic-gate if (!prisempty(&p->p_fltmask))
17950Sstevel@tonic-gate p->p_proc_flag |= P_PR_TRACE;
17960Sstevel@tonic-gate else if (sigisempty(&p->p_sigmask)) {
17970Sstevel@tonic-gate user_t *up = PTOU(p);
17980Sstevel@tonic-gate if (up->u_systrap == 0)
17990Sstevel@tonic-gate p->p_proc_flag &= ~P_PR_TRACE;
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate }
18020Sstevel@tonic-gate
18030Sstevel@tonic-gate static int
pr_clearsig(prnode_t * pnp)18040Sstevel@tonic-gate pr_clearsig(prnode_t *pnp)
18050Sstevel@tonic-gate {
18060Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
18070Sstevel@tonic-gate klwp_t *lwp = ttolwp(t);
18080Sstevel@tonic-gate
18090Sstevel@tonic-gate thread_unlock(t);
18100Sstevel@tonic-gate if (lwp->lwp_cursig == SIGKILL)
18110Sstevel@tonic-gate return (EBUSY);
18120Sstevel@tonic-gate
18130Sstevel@tonic-gate /*
18140Sstevel@tonic-gate * Discard current siginfo_t, if any.
18150Sstevel@tonic-gate */
18160Sstevel@tonic-gate lwp->lwp_cursig = 0;
18170Sstevel@tonic-gate lwp->lwp_extsig = 0;
18180Sstevel@tonic-gate if (lwp->lwp_curinfo) {
18190Sstevel@tonic-gate siginfofree(lwp->lwp_curinfo);
18200Sstevel@tonic-gate lwp->lwp_curinfo = NULL;
18210Sstevel@tonic-gate }
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate return (0);
18240Sstevel@tonic-gate }
18250Sstevel@tonic-gate
18260Sstevel@tonic-gate static int
pr_clearflt(prnode_t * pnp)18270Sstevel@tonic-gate pr_clearflt(prnode_t *pnp)
18280Sstevel@tonic-gate {
18290Sstevel@tonic-gate kthread_t *t = pr_thread(pnp); /* returns locked thread */
18300Sstevel@tonic-gate
18310Sstevel@tonic-gate thread_unlock(t);
18320Sstevel@tonic-gate ttolwp(t)->lwp_curflt = 0;
18330Sstevel@tonic-gate
18340Sstevel@tonic-gate return (0);
18350Sstevel@tonic-gate }
18360Sstevel@tonic-gate
18370Sstevel@tonic-gate static int
pr_watch(prnode_t * pnp,prwatch_t * pwp,int * unlocked)18380Sstevel@tonic-gate pr_watch(prnode_t *pnp, prwatch_t *pwp, int *unlocked)
18390Sstevel@tonic-gate {
18400Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
18410Sstevel@tonic-gate struct as *as = p->p_as;
18420Sstevel@tonic-gate uintptr_t vaddr = pwp->pr_vaddr;
18430Sstevel@tonic-gate size_t size = pwp->pr_size;
18440Sstevel@tonic-gate int wflags = pwp->pr_wflags;
18450Sstevel@tonic-gate ulong_t newpage = 0;
18460Sstevel@tonic-gate struct watched_area *pwa;
18470Sstevel@tonic-gate int error;
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate *unlocked = 0;
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate /*
18520Sstevel@tonic-gate * Can't apply to a system process.
18530Sstevel@tonic-gate */
18540Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
18550Sstevel@tonic-gate return (EBUSY);
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate /*
18580Sstevel@tonic-gate * Verify that the address range does not wrap
18590Sstevel@tonic-gate * and that only the proper flags were specified.
18600Sstevel@tonic-gate */
18610Sstevel@tonic-gate if ((wflags & ~WA_TRAPAFTER) == 0)
18620Sstevel@tonic-gate size = 0;
18630Sstevel@tonic-gate if (vaddr + size < vaddr ||
18640Sstevel@tonic-gate (wflags & ~(WA_READ|WA_WRITE|WA_EXEC|WA_TRAPAFTER)) != 0 ||
18650Sstevel@tonic-gate ((wflags & ~WA_TRAPAFTER) != 0 && size == 0))
18660Sstevel@tonic-gate return (EINVAL);
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate /*
18690Sstevel@tonic-gate * Don't let the address range go above as->a_userlimit.
18700Sstevel@tonic-gate * There is no error here, just a limitation.
18710Sstevel@tonic-gate */
18720Sstevel@tonic-gate if (vaddr >= (uintptr_t)as->a_userlimit)
18730Sstevel@tonic-gate return (0);
18740Sstevel@tonic-gate if (vaddr + size > (uintptr_t)as->a_userlimit)
18750Sstevel@tonic-gate size = (uintptr_t)as->a_userlimit - vaddr;
18760Sstevel@tonic-gate
18770Sstevel@tonic-gate /*
18780Sstevel@tonic-gate * Compute maximum number of pages this will add.
18790Sstevel@tonic-gate */
18800Sstevel@tonic-gate if ((wflags & ~WA_TRAPAFTER) != 0) {
18810Sstevel@tonic-gate ulong_t pagespan = (vaddr + size) - (vaddr & PAGEMASK);
18820Sstevel@tonic-gate newpage = btopr(pagespan);
18830Sstevel@tonic-gate if (newpage > 2 * prnwatch)
18840Sstevel@tonic-gate return (E2BIG);
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate /*
18880Sstevel@tonic-gate * Force the process to be fully stopped.
18890Sstevel@tonic-gate */
18900Sstevel@tonic-gate if (p == curproc) {
18910Sstevel@tonic-gate prunlock(pnp);
18920Sstevel@tonic-gate while (holdwatch() != 0)
18930Sstevel@tonic-gate continue;
18940Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0) {
18950Sstevel@tonic-gate continuelwps(p);
18960Sstevel@tonic-gate *unlocked = 1;
18970Sstevel@tonic-gate return (error);
18980Sstevel@tonic-gate }
18990Sstevel@tonic-gate } else {
19000Sstevel@tonic-gate pauselwps(p);
19010Sstevel@tonic-gate while (pr_allstopped(p, 0) > 0) {
19020Sstevel@tonic-gate /*
19030Sstevel@tonic-gate * This cv/mutex pair is persistent even
19040Sstevel@tonic-gate * if the process disappears after we
19050Sstevel@tonic-gate * unmark it and drop p->p_lock.
19060Sstevel@tonic-gate */
19070Sstevel@tonic-gate kcondvar_t *cv = &pr_pid_cv[p->p_slot];
19080Sstevel@tonic-gate kmutex_t *mp = &p->p_lock;
19090Sstevel@tonic-gate
19100Sstevel@tonic-gate prunmark(p);
19110Sstevel@tonic-gate (void) cv_wait(cv, mp);
19120Sstevel@tonic-gate mutex_exit(mp);
19130Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0) {
19140Sstevel@tonic-gate /*
19150Sstevel@tonic-gate * Unpause the process if it exists.
19160Sstevel@tonic-gate */
19170Sstevel@tonic-gate p = pr_p_lock(pnp);
19180Sstevel@tonic-gate mutex_exit(&pr_pidlock);
19190Sstevel@tonic-gate if (p != NULL) {
19200Sstevel@tonic-gate unpauselwps(p);
19210Sstevel@tonic-gate prunlock(pnp);
19220Sstevel@tonic-gate }
19230Sstevel@tonic-gate *unlocked = 1;
19240Sstevel@tonic-gate return (error);
19250Sstevel@tonic-gate }
19260Sstevel@tonic-gate }
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate
19290Sstevel@tonic-gate /*
19300Sstevel@tonic-gate * Drop p->p_lock in order to perform the rest of this.
19310Sstevel@tonic-gate * The process is still locked with the P_PR_LOCK flag.
19320Sstevel@tonic-gate */
19330Sstevel@tonic-gate mutex_exit(&p->p_lock);
19340Sstevel@tonic-gate
19350Sstevel@tonic-gate pwa = kmem_alloc(sizeof (struct watched_area), KM_SLEEP);
19360Sstevel@tonic-gate pwa->wa_vaddr = (caddr_t)vaddr;
19370Sstevel@tonic-gate pwa->wa_eaddr = (caddr_t)vaddr + size;
19380Sstevel@tonic-gate pwa->wa_flags = (ulong_t)wflags;
19390Sstevel@tonic-gate
19406247Sraf error = ((pwa->wa_flags & ~WA_TRAPAFTER) == 0)?
19415771Sjp151216 clear_watched_area(p, pwa) : set_watched_area(p, pwa);
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate if (p == curproc) {
19440Sstevel@tonic-gate setallwatch();
19450Sstevel@tonic-gate mutex_enter(&p->p_lock);
19460Sstevel@tonic-gate continuelwps(p);
19470Sstevel@tonic-gate } else {
19480Sstevel@tonic-gate mutex_enter(&p->p_lock);
19490Sstevel@tonic-gate unpauselwps(p);
19500Sstevel@tonic-gate }
19510Sstevel@tonic-gate
19520Sstevel@tonic-gate return (error);
19530Sstevel@tonic-gate }
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate /* jobcontrol stopped, but with a /proc directed stop in effect */
19560Sstevel@tonic-gate #define JDSTOPPED(t) \
19570Sstevel@tonic-gate ((t)->t_state == TS_STOPPED && \
19580Sstevel@tonic-gate (t)->t_whystop == PR_JOBCONTROL && \
19590Sstevel@tonic-gate ((t)->t_proc_flag & TP_PRSTOP))
19600Sstevel@tonic-gate
19610Sstevel@tonic-gate /*
19620Sstevel@tonic-gate * pr_agent() creates the agent lwp. If the process is exiting while
19630Sstevel@tonic-gate * we are creating an agent lwp, then exitlwps() waits until the
19640Sstevel@tonic-gate * agent has been created using prbarrier().
19650Sstevel@tonic-gate */
19660Sstevel@tonic-gate static int
pr_agent(prnode_t * pnp,prgregset_t prgregset,int * unlocked)19670Sstevel@tonic-gate pr_agent(prnode_t *pnp, prgregset_t prgregset, int *unlocked)
19680Sstevel@tonic-gate {
19690Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
19700Sstevel@tonic-gate prcommon_t *pcp;
19710Sstevel@tonic-gate kthread_t *t;
19720Sstevel@tonic-gate kthread_t *ct;
19730Sstevel@tonic-gate klwp_t *clwp;
19740Sstevel@tonic-gate k_sigset_t smask;
19750Sstevel@tonic-gate int cid;
19760Sstevel@tonic-gate void *bufp = NULL;
19770Sstevel@tonic-gate int error;
19780Sstevel@tonic-gate
19790Sstevel@tonic-gate *unlocked = 0;
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate /*
19820Sstevel@tonic-gate * Cannot create the /proc agent lwp if :-
19830Sstevel@tonic-gate * - the process is not fully stopped or directed to stop.
19840Sstevel@tonic-gate * - there is an agent lwp already.
1985390Sraf * - the process has been killed.
1986390Sraf * - the process is exiting.
19870Sstevel@tonic-gate * - it's a vfork(2) parent.
19880Sstevel@tonic-gate */
19890Sstevel@tonic-gate t = prchoose(p); /* returns locked thread */
19900Sstevel@tonic-gate ASSERT(t != NULL);
19910Sstevel@tonic-gate
1992390Sraf if ((!ISTOPPED(t) && !VSTOPPED(t) && !SUSPENDED(t) && !JDSTOPPED(t)) ||
1993390Sraf p->p_agenttp != NULL ||
1994390Sraf (p->p_flag & (SKILLED | SEXITING | SVFWAIT))) {
19950Sstevel@tonic-gate thread_unlock(t);
19960Sstevel@tonic-gate return (EBUSY);
19970Sstevel@tonic-gate }
19980Sstevel@tonic-gate
19990Sstevel@tonic-gate thread_unlock(t);
20000Sstevel@tonic-gate mutex_exit(&p->p_lock);
20010Sstevel@tonic-gate
20020Sstevel@tonic-gate sigfillset(&smask);
20030Sstevel@tonic-gate sigdiffset(&smask, &cantmask);
20040Sstevel@tonic-gate clwp = lwp_create(lwp_rtt, NULL, 0, p, TS_STOPPED,
20050Sstevel@tonic-gate t->t_pri, &smask, NOCLASS, 0);
20060Sstevel@tonic-gate if (clwp == NULL) {
20070Sstevel@tonic-gate mutex_enter(&p->p_lock);
20080Sstevel@tonic-gate return (ENOMEM);
20090Sstevel@tonic-gate }
20100Sstevel@tonic-gate prsetprregs(clwp, prgregset, 1);
20110Sstevel@tonic-gate retry:
20120Sstevel@tonic-gate cid = t->t_cid;
20130Sstevel@tonic-gate (void) CL_ALLOC(&bufp, cid, KM_SLEEP);
20140Sstevel@tonic-gate mutex_enter(&p->p_lock);
20150Sstevel@tonic-gate if (cid != t->t_cid) {
20160Sstevel@tonic-gate /*
20170Sstevel@tonic-gate * Someone just changed this thread's scheduling class,
20180Sstevel@tonic-gate * so try pre-allocating the buffer again. Hopefully we
20190Sstevel@tonic-gate * don't hit this often.
20200Sstevel@tonic-gate */
20210Sstevel@tonic-gate mutex_exit(&p->p_lock);
20220Sstevel@tonic-gate CL_FREE(cid, bufp);
20230Sstevel@tonic-gate goto retry;
20240Sstevel@tonic-gate }
20250Sstevel@tonic-gate
20260Sstevel@tonic-gate clwp->lwp_ap = clwp->lwp_arg;
20270Sstevel@tonic-gate clwp->lwp_eosys = NORMALRETURN;
20280Sstevel@tonic-gate ct = lwptot(clwp);
20290Sstevel@tonic-gate ct->t_clfuncs = t->t_clfuncs;
20300Sstevel@tonic-gate CL_FORK(t, ct, bufp);
20310Sstevel@tonic-gate ct->t_cid = t->t_cid;
20320Sstevel@tonic-gate ct->t_proc_flag |= TP_PRSTOP;
20330Sstevel@tonic-gate /*
20340Sstevel@tonic-gate * Setting t_sysnum to zero causes post_syscall()
20350Sstevel@tonic-gate * to bypass all syscall checks and go directly to
20360Sstevel@tonic-gate * if (issig()) psig();
20370Sstevel@tonic-gate * so that the agent lwp will stop in issig_forreal()
20380Sstevel@tonic-gate * showing PR_REQUESTED.
20390Sstevel@tonic-gate */
20400Sstevel@tonic-gate ct->t_sysnum = 0;
20410Sstevel@tonic-gate ct->t_post_sys = 1;
20420Sstevel@tonic-gate ct->t_sig_check = 1;
20430Sstevel@tonic-gate p->p_agenttp = ct;
20440Sstevel@tonic-gate ct->t_proc_flag &= ~TP_HOLDLWP;
20450Sstevel@tonic-gate
20460Sstevel@tonic-gate pcp = pnp->pr_pcommon;
20470Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
20480Sstevel@tonic-gate
20490Sstevel@tonic-gate lwp_create_done(ct);
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate /*
20520Sstevel@tonic-gate * Don't return until the agent is stopped on PR_REQUESTED.
20530Sstevel@tonic-gate */
20540Sstevel@tonic-gate
20550Sstevel@tonic-gate for (;;) {
20560Sstevel@tonic-gate prunlock(pnp);
20570Sstevel@tonic-gate *unlocked = 1;
20580Sstevel@tonic-gate
20590Sstevel@tonic-gate /*
20600Sstevel@tonic-gate * Wait for the agent to stop and notify us.
20610Sstevel@tonic-gate * If we've been interrupted, return that information.
20620Sstevel@tonic-gate */
20634123Sdm120769 error = pr_wait(pcp, NULL, 0);
20640Sstevel@tonic-gate if (error == EINTR) {
20650Sstevel@tonic-gate error = 0;
20660Sstevel@tonic-gate break;
20670Sstevel@tonic-gate }
20680Sstevel@tonic-gate
20690Sstevel@tonic-gate /*
20700Sstevel@tonic-gate * Confirm that the agent LWP has stopped.
20710Sstevel@tonic-gate */
20720Sstevel@tonic-gate
20730Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
20740Sstevel@tonic-gate break;
20750Sstevel@tonic-gate *unlocked = 0;
20760Sstevel@tonic-gate
20770Sstevel@tonic-gate /*
20780Sstevel@tonic-gate * Since we dropped the lock on the process, the agent
20790Sstevel@tonic-gate * may have disappeared or changed. Grab the current
20800Sstevel@tonic-gate * agent and check fail if it has disappeared.
20810Sstevel@tonic-gate */
20820Sstevel@tonic-gate if ((ct = p->p_agenttp) == NULL) {
20830Sstevel@tonic-gate error = ENOENT;
20840Sstevel@tonic-gate break;
20850Sstevel@tonic-gate }
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
20880Sstevel@tonic-gate thread_lock(ct);
20890Sstevel@tonic-gate
20900Sstevel@tonic-gate if (ISTOPPED(ct)) {
20910Sstevel@tonic-gate thread_unlock(ct);
20920Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
20930Sstevel@tonic-gate break;
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate thread_unlock(ct);
20970Sstevel@tonic-gate }
20980Sstevel@tonic-gate
20990Sstevel@tonic-gate return (error ? error : -1);
21000Sstevel@tonic-gate }
21010Sstevel@tonic-gate
21020Sstevel@tonic-gate static int
pr_rdwr(proc_t * p,enum uio_rw rw,priovec_t * pio)21030Sstevel@tonic-gate pr_rdwr(proc_t *p, enum uio_rw rw, priovec_t *pio)
21040Sstevel@tonic-gate {
21050Sstevel@tonic-gate caddr_t base = (caddr_t)pio->pio_base;
21060Sstevel@tonic-gate size_t cnt = pio->pio_len;
21070Sstevel@tonic-gate uintptr_t offset = (uintptr_t)pio->pio_offset;
21080Sstevel@tonic-gate struct uio auio;
21090Sstevel@tonic-gate struct iovec aiov;
21100Sstevel@tonic-gate int error = 0;
21110Sstevel@tonic-gate
21120Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
21130Sstevel@tonic-gate error = EIO;
21140Sstevel@tonic-gate else if ((base + cnt) < base || (offset + cnt) < offset)
21150Sstevel@tonic-gate error = EINVAL;
21160Sstevel@tonic-gate else if (cnt != 0) {
21170Sstevel@tonic-gate aiov.iov_base = base;
21180Sstevel@tonic-gate aiov.iov_len = cnt;
21190Sstevel@tonic-gate
21200Sstevel@tonic-gate auio.uio_loffset = offset;
21210Sstevel@tonic-gate auio.uio_iov = &aiov;
21220Sstevel@tonic-gate auio.uio_iovcnt = 1;
21230Sstevel@tonic-gate auio.uio_resid = cnt;
21240Sstevel@tonic-gate auio.uio_segflg = UIO_USERSPACE;
21250Sstevel@tonic-gate auio.uio_llimit = (longlong_t)MAXOFFSET_T;
21260Sstevel@tonic-gate auio.uio_fmode = FREAD|FWRITE;
21270Sstevel@tonic-gate auio.uio_extflg = UIO_COPY_DEFAULT;
21280Sstevel@tonic-gate
21290Sstevel@tonic-gate mutex_exit(&p->p_lock);
21300Sstevel@tonic-gate error = prusrio(p, rw, &auio, 0);
21310Sstevel@tonic-gate mutex_enter(&p->p_lock);
21320Sstevel@tonic-gate
21330Sstevel@tonic-gate /*
21340Sstevel@tonic-gate * We have no way to return the i/o count,
21350Sstevel@tonic-gate * like read() or write() would do, so we
21360Sstevel@tonic-gate * return an error if the i/o was truncated.
21370Sstevel@tonic-gate */
21380Sstevel@tonic-gate if (auio.uio_resid != 0 && error == 0)
21390Sstevel@tonic-gate error = EIO;
21400Sstevel@tonic-gate }
21410Sstevel@tonic-gate
21420Sstevel@tonic-gate return (error);
21430Sstevel@tonic-gate }
21440Sstevel@tonic-gate
21450Sstevel@tonic-gate static int
pr_scred(proc_t * p,prcred_t * prcred,cred_t * cr,boolean_t dogrps)21460Sstevel@tonic-gate pr_scred(proc_t *p, prcred_t *prcred, cred_t *cr, boolean_t dogrps)
21470Sstevel@tonic-gate {
21480Sstevel@tonic-gate kthread_t *t;
21490Sstevel@tonic-gate cred_t *oldcred;
21500Sstevel@tonic-gate cred_t *newcred;
21510Sstevel@tonic-gate uid_t oldruid;
21520Sstevel@tonic-gate int error;
21535771Sjp151216 zone_t *zone = crgetzone(cr);
21540Sstevel@tonic-gate
21555771Sjp151216 if (!VALID_UID(prcred->pr_euid, zone) ||
21565771Sjp151216 !VALID_UID(prcred->pr_ruid, zone) ||
21575771Sjp151216 !VALID_UID(prcred->pr_suid, zone) ||
21585771Sjp151216 !VALID_GID(prcred->pr_egid, zone) ||
21595771Sjp151216 !VALID_GID(prcred->pr_rgid, zone) ||
21605771Sjp151216 !VALID_GID(prcred->pr_sgid, zone))
21610Sstevel@tonic-gate return (EINVAL);
21620Sstevel@tonic-gate
21630Sstevel@tonic-gate if (dogrps) {
21640Sstevel@tonic-gate int ngrp = prcred->pr_ngroups;
21650Sstevel@tonic-gate int i;
21660Sstevel@tonic-gate
21670Sstevel@tonic-gate if (ngrp < 0 || ngrp > ngroups_max)
21680Sstevel@tonic-gate return (EINVAL);
21690Sstevel@tonic-gate
21700Sstevel@tonic-gate for (i = 0; i < ngrp; i++) {
21715771Sjp151216 if (!VALID_GID(prcred->pr_groups[i], zone))
21720Sstevel@tonic-gate return (EINVAL);
21730Sstevel@tonic-gate }
21740Sstevel@tonic-gate }
21750Sstevel@tonic-gate
21760Sstevel@tonic-gate error = secpolicy_allow_setid(cr, prcred->pr_euid, B_FALSE);
21770Sstevel@tonic-gate
21780Sstevel@tonic-gate if (error == 0 && prcred->pr_ruid != prcred->pr_euid)
21790Sstevel@tonic-gate error = secpolicy_allow_setid(cr, prcred->pr_ruid, B_FALSE);
21800Sstevel@tonic-gate
21810Sstevel@tonic-gate if (error == 0 && prcred->pr_suid != prcred->pr_euid &&
21820Sstevel@tonic-gate prcred->pr_suid != prcred->pr_ruid)
21830Sstevel@tonic-gate error = secpolicy_allow_setid(cr, prcred->pr_suid, B_FALSE);
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate if (error)
21860Sstevel@tonic-gate return (error);
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate mutex_exit(&p->p_lock);
21890Sstevel@tonic-gate
21900Sstevel@tonic-gate /* hold old cred so it doesn't disappear while we dup it */
21910Sstevel@tonic-gate mutex_enter(&p->p_crlock);
21920Sstevel@tonic-gate crhold(oldcred = p->p_cred);
21930Sstevel@tonic-gate mutex_exit(&p->p_crlock);
21940Sstevel@tonic-gate newcred = crdup(oldcred);
21950Sstevel@tonic-gate oldruid = crgetruid(oldcred);
21960Sstevel@tonic-gate crfree(oldcred);
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate /* Error checking done above */
21990Sstevel@tonic-gate (void) crsetresuid(newcred, prcred->pr_ruid, prcred->pr_euid,
22005771Sjp151216 prcred->pr_suid);
22010Sstevel@tonic-gate (void) crsetresgid(newcred, prcred->pr_rgid, prcred->pr_egid,
22025771Sjp151216 prcred->pr_sgid);
22030Sstevel@tonic-gate
22040Sstevel@tonic-gate if (dogrps) {
22050Sstevel@tonic-gate (void) crsetgroups(newcred, prcred->pr_ngroups,
22060Sstevel@tonic-gate prcred->pr_groups);
22070Sstevel@tonic-gate
22080Sstevel@tonic-gate }
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate mutex_enter(&p->p_crlock);
22110Sstevel@tonic-gate oldcred = p->p_cred;
22120Sstevel@tonic-gate p->p_cred = newcred;
22130Sstevel@tonic-gate mutex_exit(&p->p_crlock);
22140Sstevel@tonic-gate crfree(oldcred);
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate /*
22170Sstevel@tonic-gate * Keep count of processes per uid consistent.
22180Sstevel@tonic-gate */
22190Sstevel@tonic-gate if (oldruid != prcred->pr_ruid) {
22200Sstevel@tonic-gate zoneid_t zoneid = crgetzoneid(newcred);
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate mutex_enter(&pidlock);
22230Sstevel@tonic-gate upcount_dec(oldruid, zoneid);
22240Sstevel@tonic-gate upcount_inc(prcred->pr_ruid, zoneid);
22250Sstevel@tonic-gate mutex_exit(&pidlock);
22260Sstevel@tonic-gate }
22270Sstevel@tonic-gate
22280Sstevel@tonic-gate /*
22290Sstevel@tonic-gate * Broadcast the cred change to the threads.
22300Sstevel@tonic-gate */
22310Sstevel@tonic-gate mutex_enter(&p->p_lock);
22320Sstevel@tonic-gate t = p->p_tlist;
22330Sstevel@tonic-gate do {
22340Sstevel@tonic-gate t->t_pre_sys = 1; /* so syscall will get new cred */
22350Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
22360Sstevel@tonic-gate
22370Sstevel@tonic-gate return (0);
22380Sstevel@tonic-gate }
22390Sstevel@tonic-gate
22400Sstevel@tonic-gate /*
22410Sstevel@tonic-gate * Change process credentials to specified zone. Used to temporarily
22420Sstevel@tonic-gate * set a process to run in the global zone; only transitions between
22430Sstevel@tonic-gate * the process's actual zone and the global zone are allowed.
22440Sstevel@tonic-gate */
22450Sstevel@tonic-gate static int
pr_szoneid(proc_t * p,zoneid_t zoneid,cred_t * cr)22460Sstevel@tonic-gate pr_szoneid(proc_t *p, zoneid_t zoneid, cred_t *cr)
22470Sstevel@tonic-gate {
22480Sstevel@tonic-gate kthread_t *t;
22490Sstevel@tonic-gate cred_t *oldcred;
22500Sstevel@tonic-gate cred_t *newcred;
22510Sstevel@tonic-gate zone_t *zptr;
22523768Ssl108498 zoneid_t oldzoneid;
22530Sstevel@tonic-gate
22540Sstevel@tonic-gate if (secpolicy_zone_config(cr) != 0)
22550Sstevel@tonic-gate return (EPERM);
22560Sstevel@tonic-gate if (zoneid != GLOBAL_ZONEID && zoneid != p->p_zone->zone_id)
22570Sstevel@tonic-gate return (EINVAL);
22580Sstevel@tonic-gate if ((zptr = zone_find_by_id(zoneid)) == NULL)
22590Sstevel@tonic-gate return (EINVAL);
22600Sstevel@tonic-gate mutex_exit(&p->p_lock);
22610Sstevel@tonic-gate mutex_enter(&p->p_crlock);
22623768Ssl108498 oldcred = p->p_cred;
22633768Ssl108498 crhold(oldcred);
22640Sstevel@tonic-gate mutex_exit(&p->p_crlock);
22650Sstevel@tonic-gate newcred = crdup(oldcred);
22663768Ssl108498 oldzoneid = crgetzoneid(oldcred);
22670Sstevel@tonic-gate crfree(oldcred);
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate crsetzone(newcred, zptr);
22700Sstevel@tonic-gate zone_rele(zptr);
22710Sstevel@tonic-gate
22720Sstevel@tonic-gate mutex_enter(&p->p_crlock);
22730Sstevel@tonic-gate oldcred = p->p_cred;
22740Sstevel@tonic-gate p->p_cred = newcred;
22750Sstevel@tonic-gate mutex_exit(&p->p_crlock);
22760Sstevel@tonic-gate crfree(oldcred);
22770Sstevel@tonic-gate
22780Sstevel@tonic-gate /*
22793768Ssl108498 * The target process is changing zones (according to its cred), so
22803768Ssl108498 * update the per-zone upcounts, which are based on process creds.
22813768Ssl108498 */
22823768Ssl108498 if (oldzoneid != zoneid) {
22833768Ssl108498 uid_t ruid = crgetruid(newcred);
22843768Ssl108498
22853768Ssl108498 mutex_enter(&pidlock);
22863768Ssl108498 upcount_dec(ruid, oldzoneid);
22873768Ssl108498 upcount_inc(ruid, zoneid);
22883768Ssl108498 mutex_exit(&pidlock);
22893768Ssl108498 }
22903768Ssl108498 /*
22910Sstevel@tonic-gate * Broadcast the cred change to the threads.
22920Sstevel@tonic-gate */
22930Sstevel@tonic-gate mutex_enter(&p->p_lock);
22940Sstevel@tonic-gate t = p->p_tlist;
22950Sstevel@tonic-gate do {
22960Sstevel@tonic-gate t->t_pre_sys = 1; /* so syscall will get new cred */
22970Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
22980Sstevel@tonic-gate
22990Sstevel@tonic-gate return (0);
23000Sstevel@tonic-gate }
23010Sstevel@tonic-gate
23020Sstevel@tonic-gate static int
pr_spriv(proc_t * p,prpriv_t * prpriv,cred_t * cr)23030Sstevel@tonic-gate pr_spriv(proc_t *p, prpriv_t *prpriv, cred_t *cr)
23040Sstevel@tonic-gate {
23050Sstevel@tonic-gate kthread_t *t;
23060Sstevel@tonic-gate int err;
23070Sstevel@tonic-gate
23080Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
23090Sstevel@tonic-gate
23100Sstevel@tonic-gate if ((err = priv_pr_spriv(p, prpriv, cr)) == 0) {
23110Sstevel@tonic-gate /*
23120Sstevel@tonic-gate * Broadcast the cred change to the threads.
23130Sstevel@tonic-gate */
23140Sstevel@tonic-gate t = p->p_tlist;
23150Sstevel@tonic-gate do {
23160Sstevel@tonic-gate t->t_pre_sys = 1; /* so syscall will get new cred */
23170Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
23180Sstevel@tonic-gate }
23190Sstevel@tonic-gate
23200Sstevel@tonic-gate return (err);
23210Sstevel@tonic-gate }
23220Sstevel@tonic-gate
23230Sstevel@tonic-gate /*
23240Sstevel@tonic-gate * Return -1 if the process is the parent of a vfork(1) whose child has yet to
23250Sstevel@tonic-gate * terminate or perform an exec(2).
23260Sstevel@tonic-gate *
23270Sstevel@tonic-gate * Returns 0 if the process is fully stopped except for the current thread (if
23280Sstevel@tonic-gate * we are operating on our own process), 1 otherwise.
23290Sstevel@tonic-gate *
23300Sstevel@tonic-gate * If the watchstop flag is set, then we ignore threads with TP_WATCHSTOP set.
23310Sstevel@tonic-gate * See holdwatch() for details.
23320Sstevel@tonic-gate */
23330Sstevel@tonic-gate int
pr_allstopped(proc_t * p,int watchstop)23340Sstevel@tonic-gate pr_allstopped(proc_t *p, int watchstop)
23350Sstevel@tonic-gate {
23360Sstevel@tonic-gate kthread_t *t;
23370Sstevel@tonic-gate int rv = 0;
23380Sstevel@tonic-gate
23390Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
23400Sstevel@tonic-gate
23410Sstevel@tonic-gate if (p->p_flag & SVFWAIT) /* waiting for vfork'd child to exec */
23420Sstevel@tonic-gate return (-1);
23430Sstevel@tonic-gate
23440Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
23450Sstevel@tonic-gate do {
23460Sstevel@tonic-gate if (t == curthread || VSTOPPED(t) ||
23470Sstevel@tonic-gate (watchstop && (t->t_proc_flag & TP_WATCHSTOP)))
23480Sstevel@tonic-gate continue;
23490Sstevel@tonic-gate thread_lock(t);
23500Sstevel@tonic-gate switch (t->t_state) {
23510Sstevel@tonic-gate case TS_ZOMB:
23520Sstevel@tonic-gate case TS_STOPPED:
23530Sstevel@tonic-gate break;
23540Sstevel@tonic-gate case TS_SLEEP:
23550Sstevel@tonic-gate if (!(t->t_flag & T_WAKEABLE) ||
23560Sstevel@tonic-gate t->t_wchan0 == NULL)
23570Sstevel@tonic-gate rv = 1;
23580Sstevel@tonic-gate break;
23590Sstevel@tonic-gate default:
23600Sstevel@tonic-gate rv = 1;
23610Sstevel@tonic-gate break;
23620Sstevel@tonic-gate }
23630Sstevel@tonic-gate thread_unlock(t);
23640Sstevel@tonic-gate } while (rv == 0 && (t = t->t_forw) != p->p_tlist);
23650Sstevel@tonic-gate }
23660Sstevel@tonic-gate
23670Sstevel@tonic-gate return (rv);
23680Sstevel@tonic-gate }
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate /*
23710Sstevel@tonic-gate * Cause all lwps in the process to pause (for watchpoint operations).
23720Sstevel@tonic-gate */
23730Sstevel@tonic-gate static void
pauselwps(proc_t * p)23740Sstevel@tonic-gate pauselwps(proc_t *p)
23750Sstevel@tonic-gate {
23760Sstevel@tonic-gate kthread_t *t;
23770Sstevel@tonic-gate
23780Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
23790Sstevel@tonic-gate ASSERT(p != curproc);
23800Sstevel@tonic-gate
23810Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
23820Sstevel@tonic-gate do {
23830Sstevel@tonic-gate thread_lock(t);
23840Sstevel@tonic-gate t->t_proc_flag |= TP_PAUSE;
23850Sstevel@tonic-gate aston(t);
23863792Sakolb if ((ISWAKEABLE(t) && (t->t_wchan0 == NULL)) ||
23873792Sakolb ISWAITING(t)) {
23883792Sakolb setrun_locked(t);
23890Sstevel@tonic-gate }
23900Sstevel@tonic-gate prpokethread(t);
23910Sstevel@tonic-gate thread_unlock(t);
23920Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
23930Sstevel@tonic-gate }
23940Sstevel@tonic-gate }
23950Sstevel@tonic-gate
23960Sstevel@tonic-gate /*
23970Sstevel@tonic-gate * undo the effects of pauselwps()
23980Sstevel@tonic-gate */
23990Sstevel@tonic-gate static void
unpauselwps(proc_t * p)24000Sstevel@tonic-gate unpauselwps(proc_t *p)
24010Sstevel@tonic-gate {
24020Sstevel@tonic-gate kthread_t *t;
24030Sstevel@tonic-gate
24040Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock));
24050Sstevel@tonic-gate ASSERT(p != curproc);
24060Sstevel@tonic-gate
24070Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
24080Sstevel@tonic-gate do {
24090Sstevel@tonic-gate thread_lock(t);
24100Sstevel@tonic-gate t->t_proc_flag &= ~TP_PAUSE;
24110Sstevel@tonic-gate if (t->t_state == TS_STOPPED) {
24120Sstevel@tonic-gate t->t_schedflag |= TS_UNPAUSE;
24130Sstevel@tonic-gate t->t_dtrace_stop = 0;
24140Sstevel@tonic-gate setrun_locked(t);
24150Sstevel@tonic-gate }
24160Sstevel@tonic-gate thread_unlock(t);
24170Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
24180Sstevel@tonic-gate }
24190Sstevel@tonic-gate }
24200Sstevel@tonic-gate
24210Sstevel@tonic-gate /*
24220Sstevel@tonic-gate * Cancel all watched areas. Called from prclose().
24230Sstevel@tonic-gate */
24240Sstevel@tonic-gate proc_t *
pr_cancel_watch(prnode_t * pnp)24250Sstevel@tonic-gate pr_cancel_watch(prnode_t *pnp)
24260Sstevel@tonic-gate {
24270Sstevel@tonic-gate proc_t *p = pnp->pr_pcommon->prc_proc;
24280Sstevel@tonic-gate struct as *as;
24290Sstevel@tonic-gate kthread_t *t;
24300Sstevel@tonic-gate
24310Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
24320Sstevel@tonic-gate
24330Sstevel@tonic-gate if (!pr_watch_active(p))
24340Sstevel@tonic-gate return (p);
24350Sstevel@tonic-gate
24360Sstevel@tonic-gate /*
24370Sstevel@tonic-gate * Pause the process before dealing with the watchpoints.
24380Sstevel@tonic-gate */
24390Sstevel@tonic-gate if (p == curproc) {
24400Sstevel@tonic-gate prunlock(pnp);
24410Sstevel@tonic-gate while (holdwatch() != 0)
24420Sstevel@tonic-gate continue;
24430Sstevel@tonic-gate p = pr_p_lock(pnp);
24440Sstevel@tonic-gate mutex_exit(&pr_pidlock);
24450Sstevel@tonic-gate ASSERT(p == curproc);
24460Sstevel@tonic-gate } else {
24470Sstevel@tonic-gate pauselwps(p);
24480Sstevel@tonic-gate while (p != NULL && pr_allstopped(p, 0) > 0) {
24490Sstevel@tonic-gate /*
24500Sstevel@tonic-gate * This cv/mutex pair is persistent even
24510Sstevel@tonic-gate * if the process disappears after we
24520Sstevel@tonic-gate * unmark it and drop p->p_lock.
24530Sstevel@tonic-gate */
24540Sstevel@tonic-gate kcondvar_t *cv = &pr_pid_cv[p->p_slot];
24550Sstevel@tonic-gate kmutex_t *mp = &p->p_lock;
24560Sstevel@tonic-gate
24570Sstevel@tonic-gate prunmark(p);
24580Sstevel@tonic-gate (void) cv_wait(cv, mp);
24590Sstevel@tonic-gate mutex_exit(mp);
24600Sstevel@tonic-gate p = pr_p_lock(pnp); /* NULL if process disappeared */
24610Sstevel@tonic-gate mutex_exit(&pr_pidlock);
24620Sstevel@tonic-gate }
24630Sstevel@tonic-gate }
24640Sstevel@tonic-gate
24650Sstevel@tonic-gate if (p == NULL) /* the process disappeared */
24660Sstevel@tonic-gate return (NULL);
24670Sstevel@tonic-gate
24680Sstevel@tonic-gate ASSERT(p == pnp->pr_pcommon->prc_proc);
24690Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate if (pr_watch_active(p)) {
24720Sstevel@tonic-gate pr_free_watchpoints(p);
24730Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
24740Sstevel@tonic-gate do {
24750Sstevel@tonic-gate watch_disable(t);
24760Sstevel@tonic-gate
24770Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
24780Sstevel@tonic-gate }
24790Sstevel@tonic-gate }
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate if ((as = p->p_as) != NULL) {
24820Sstevel@tonic-gate avl_tree_t *tree;
24830Sstevel@tonic-gate struct watched_page *pwp;
24840Sstevel@tonic-gate
24850Sstevel@tonic-gate /*
24860Sstevel@tonic-gate * If this is the parent of a vfork, the watched page
24870Sstevel@tonic-gate * list has been moved temporarily to p->p_wpage.
24880Sstevel@tonic-gate */
24890Sstevel@tonic-gate if (avl_numnodes(&p->p_wpage) != 0)
24900Sstevel@tonic-gate tree = &p->p_wpage;
24910Sstevel@tonic-gate else
24920Sstevel@tonic-gate tree = &as->a_wpage;
24930Sstevel@tonic-gate
24940Sstevel@tonic-gate mutex_exit(&p->p_lock);
24950Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_WRITER);
24960Sstevel@tonic-gate
24970Sstevel@tonic-gate for (pwp = avl_first(tree); pwp != NULL;
24980Sstevel@tonic-gate pwp = AVL_NEXT(tree, pwp)) {
24990Sstevel@tonic-gate pwp->wp_read = 0;
25000Sstevel@tonic-gate pwp->wp_write = 0;
25010Sstevel@tonic-gate pwp->wp_exec = 0;
25020Sstevel@tonic-gate if ((pwp->wp_flags & WP_SETPROT) == 0) {
25030Sstevel@tonic-gate pwp->wp_flags |= WP_SETPROT;
25040Sstevel@tonic-gate pwp->wp_prot = pwp->wp_oprot;
25050Sstevel@tonic-gate pwp->wp_list = p->p_wprot;
25060Sstevel@tonic-gate p->p_wprot = pwp;
25070Sstevel@tonic-gate }
25080Sstevel@tonic-gate }
25090Sstevel@tonic-gate
25100Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock);
25110Sstevel@tonic-gate mutex_enter(&p->p_lock);
25120Sstevel@tonic-gate }
25130Sstevel@tonic-gate
25140Sstevel@tonic-gate /*
25150Sstevel@tonic-gate * Unpause the process now.
25160Sstevel@tonic-gate */
25170Sstevel@tonic-gate if (p == curproc)
25180Sstevel@tonic-gate continuelwps(p);
25190Sstevel@tonic-gate else
25200Sstevel@tonic-gate unpauselwps(p);
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate return (p);
25230Sstevel@tonic-gate }
2524