17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5870619e9Sfrankho * Common Development and Distribution License (the "License").
6870619e9Sfrankho * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21eb9dbf0cSRoger A. Faulkner
227c478bd9Sstevel@tonic-gate /*
23e24ad047SChristopher Baumbauer - Oracle America - San Diego United States * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f971a346SBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/time.h>
337c478bd9Sstevel@tonic-gate #include <sys/cred.h>
347c478bd9Sstevel@tonic-gate #include <sys/policy.h>
357c478bd9Sstevel@tonic-gate #include <sys/debug.h>
367c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
377c478bd9Sstevel@tonic-gate #include <sys/errno.h>
387c478bd9Sstevel@tonic-gate #include <sys/file.h>
397c478bd9Sstevel@tonic-gate #include <sys/inline.h>
407c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
417c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
427c478bd9Sstevel@tonic-gate #include <sys/proc.h>
43eb9dbf0cSRoger A. Faulkner #include <sys/brand.h>
447c478bd9Sstevel@tonic-gate #include <sys/signal.h>
457c478bd9Sstevel@tonic-gate #include <sys/stat.h>
467c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
477c478bd9Sstevel@tonic-gate #include <sys/systm.h>
487c478bd9Sstevel@tonic-gate #include <sys/zone.h>
497c478bd9Sstevel@tonic-gate #include <sys/uio.h>
507c478bd9Sstevel@tonic-gate #include <sys/var.h>
517c478bd9Sstevel@tonic-gate #include <sys/mode.h>
527c478bd9Sstevel@tonic-gate #include <sys/poll.h>
537c478bd9Sstevel@tonic-gate #include <sys/user.h>
547c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
55aa59c4cbSrsb #include <sys/vfs_opreg.h>
567c478bd9Sstevel@tonic-gate #include <sys/gfs.h>
577c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
587c478bd9Sstevel@tonic-gate #include <sys/fault.h>
597c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
607c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
617c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
627c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
637c478bd9Sstevel@tonic-gate #include <sys/contract_impl.h>
647c478bd9Sstevel@tonic-gate #include <sys/ctfs.h>
657c478bd9Sstevel@tonic-gate #include <sys/avl.h>
667c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
677c478bd9Sstevel@tonic-gate #include <vm/rm.h>
687c478bd9Sstevel@tonic-gate #include <vm/as.h>
697c478bd9Sstevel@tonic-gate #include <vm/seg.h>
707c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
717c478bd9Sstevel@tonic-gate #include <vm/hat.h>
727c478bd9Sstevel@tonic-gate #include <fs/proc/prdata.h>
737c478bd9Sstevel@tonic-gate #if defined(__sparc)
747c478bd9Sstevel@tonic-gate #include <sys/regset.h>
757c478bd9Sstevel@tonic-gate #endif
767c478bd9Sstevel@tonic-gate #if defined(__x86)
777c478bd9Sstevel@tonic-gate #include <sys/sysi86.h>
787c478bd9Sstevel@tonic-gate #endif
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate * Created by prinit.
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate vnodeops_t *prvnodeops;
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate * Directory characteristics (patterned after the s5 file system).
877c478bd9Sstevel@tonic-gate */
887c478bd9Sstevel@tonic-gate #define PRROOTINO 2
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate #define PRDIRSIZE 14
917c478bd9Sstevel@tonic-gate struct prdirect {
927c478bd9Sstevel@tonic-gate ushort_t d_ino;
937c478bd9Sstevel@tonic-gate char d_name[PRDIRSIZE];
947c478bd9Sstevel@tonic-gate };
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate #define PRSDSIZE (sizeof (struct prdirect))
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate * Directory characteristics.
1007c478bd9Sstevel@tonic-gate */
1017c478bd9Sstevel@tonic-gate typedef struct prdirent {
1027c478bd9Sstevel@tonic-gate ino64_t d_ino; /* "inode number" of entry */
1037c478bd9Sstevel@tonic-gate off64_t d_off; /* offset of disk directory entry */
1047c478bd9Sstevel@tonic-gate unsigned short d_reclen; /* length of this record */
1057c478bd9Sstevel@tonic-gate char d_name[14]; /* name of file */
1067c478bd9Sstevel@tonic-gate } prdirent_t;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * Contents of a /proc/<pid> directory.
1107c478bd9Sstevel@tonic-gate * Reuse d_ino field for the /proc file type.
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate static prdirent_t piddir[] = {
1137c478bd9Sstevel@tonic-gate { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
1147c478bd9Sstevel@tonic-gate "." },
1157c478bd9Sstevel@tonic-gate { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
1167c478bd9Sstevel@tonic-gate ".." },
1177c478bd9Sstevel@tonic-gate { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
1187c478bd9Sstevel@tonic-gate "as" },
1197c478bd9Sstevel@tonic-gate { PR_CTL, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
1207c478bd9Sstevel@tonic-gate "ctl" },
1217c478bd9Sstevel@tonic-gate { PR_STATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
1227c478bd9Sstevel@tonic-gate "status" },
1237c478bd9Sstevel@tonic-gate { PR_LSTATUS, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
1247c478bd9Sstevel@tonic-gate "lstatus" },
1257c478bd9Sstevel@tonic-gate { PR_PSINFO, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
1267c478bd9Sstevel@tonic-gate "psinfo" },
1277c478bd9Sstevel@tonic-gate { PR_LPSINFO, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
1287c478bd9Sstevel@tonic-gate "lpsinfo" },
1297c478bd9Sstevel@tonic-gate { PR_MAP, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
1307c478bd9Sstevel@tonic-gate "map" },
1317c478bd9Sstevel@tonic-gate { PR_RMAP, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
1327c478bd9Sstevel@tonic-gate "rmap" },
1337c478bd9Sstevel@tonic-gate { PR_XMAP, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
1347c478bd9Sstevel@tonic-gate "xmap" },
1357c478bd9Sstevel@tonic-gate { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
1367c478bd9Sstevel@tonic-gate "cred" },
1377c478bd9Sstevel@tonic-gate { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
1387c478bd9Sstevel@tonic-gate "sigact" },
1397c478bd9Sstevel@tonic-gate { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
1407c478bd9Sstevel@tonic-gate "auxv" },
1417c478bd9Sstevel@tonic-gate { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
1427c478bd9Sstevel@tonic-gate "usage" },
1437c478bd9Sstevel@tonic-gate { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
1447c478bd9Sstevel@tonic-gate "lusage" },
1457c478bd9Sstevel@tonic-gate { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
1467c478bd9Sstevel@tonic-gate "pagedata" },
1477c478bd9Sstevel@tonic-gate { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
1487c478bd9Sstevel@tonic-gate "watch" },
1497c478bd9Sstevel@tonic-gate { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
1507c478bd9Sstevel@tonic-gate "cwd" },
1517c478bd9Sstevel@tonic-gate { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
1527c478bd9Sstevel@tonic-gate "root" },
1537c478bd9Sstevel@tonic-gate { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
1547c478bd9Sstevel@tonic-gate "fd" },
1557c478bd9Sstevel@tonic-gate { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
1567c478bd9Sstevel@tonic-gate "object" },
1577c478bd9Sstevel@tonic-gate { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
1587c478bd9Sstevel@tonic-gate "lwp" },
1597c478bd9Sstevel@tonic-gate { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
1607c478bd9Sstevel@tonic-gate "priv" },
1617c478bd9Sstevel@tonic-gate { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
1627c478bd9Sstevel@tonic-gate "path" },
1637c478bd9Sstevel@tonic-gate { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
1647c478bd9Sstevel@tonic-gate "contracts" },
1657c478bd9Sstevel@tonic-gate #if defined(__x86)
1667c478bd9Sstevel@tonic-gate { PR_LDT, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
1677c478bd9Sstevel@tonic-gate "ldt" },
1687c478bd9Sstevel@tonic-gate #endif
1697c478bd9Sstevel@tonic-gate };
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * Contents of a /proc/<pid>/lwp/<lwpid> directory.
1757c478bd9Sstevel@tonic-gate */
1767c478bd9Sstevel@tonic-gate static prdirent_t lwpiddir[] = {
1777c478bd9Sstevel@tonic-gate { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
1787c478bd9Sstevel@tonic-gate "." },
1797c478bd9Sstevel@tonic-gate { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
1807c478bd9Sstevel@tonic-gate ".." },
1817c478bd9Sstevel@tonic-gate { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
1827c478bd9Sstevel@tonic-gate "lwpctl" },
1837c478bd9Sstevel@tonic-gate { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
1847c478bd9Sstevel@tonic-gate "lwpstatus" },
1857c478bd9Sstevel@tonic-gate { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
1867c478bd9Sstevel@tonic-gate "lwpsinfo" },
1877c478bd9Sstevel@tonic-gate { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
1887c478bd9Sstevel@tonic-gate "lwpusage" },
1897c478bd9Sstevel@tonic-gate { PR_XREGS, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
1907c478bd9Sstevel@tonic-gate "xregs" },
1917c478bd9Sstevel@tonic-gate { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
1927c478bd9Sstevel@tonic-gate "templates" },
193f971a346SBryan Cantrill { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
194f971a346SBryan Cantrill "spymaster" },
1957c478bd9Sstevel@tonic-gate #if defined(__sparc)
196f971a346SBryan Cantrill { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
1977c478bd9Sstevel@tonic-gate "gwindows" },
198f971a346SBryan Cantrill { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
1997c478bd9Sstevel@tonic-gate "asrs" },
2007c478bd9Sstevel@tonic-gate #endif
2017c478bd9Sstevel@tonic-gate };
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate #define NLWPIDDIRFILES (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate * Span of entries in the array files (lstatus, lpsinfo, lusage).
2077c478bd9Sstevel@tonic-gate * We make the span larger than the size of the structure on purpose,
2087c478bd9Sstevel@tonic-gate * to make sure that programs cannot use the structure size by mistake.
2097c478bd9Sstevel@tonic-gate * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate #ifdef _LP64
2127c478bd9Sstevel@tonic-gate #define LSPAN(type) (round16(sizeof (type)) + 16)
2137c478bd9Sstevel@tonic-gate #define LSPAN32(type) (round8(sizeof (type)) + 8)
2147c478bd9Sstevel@tonic-gate #else
2157c478bd9Sstevel@tonic-gate #define LSPAN(type) (round8(sizeof (type)) + 8)
2167c478bd9Sstevel@tonic-gate #endif
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate static void rebuild_objdir(struct as *);
2197c478bd9Sstevel@tonic-gate static void prfreecommon(prcommon_t *);
220da6c28aaSamw static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate static int
propen(vnode_t ** vpp,int flag,cred_t * cr,caller_context_t * ct)223da6c28aaSamw propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate vnode_t *vp = *vpp;
2267c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
2277c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_pcommon;
2287c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
2297c478bd9Sstevel@tonic-gate vnode_t *rvp;
2307c478bd9Sstevel@tonic-gate vtype_t vtype;
2317c478bd9Sstevel@tonic-gate proc_t *p;
2327c478bd9Sstevel@tonic-gate int error = 0;
2337c478bd9Sstevel@tonic-gate prnode_t *npnp = NULL;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * Nothing to do for the /proc directory itself.
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR)
2397c478bd9Sstevel@tonic-gate return (0);
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * If we are opening an underlying mapped object, reject opens
2437c478bd9Sstevel@tonic-gate * for writing regardless of the objects's access modes.
2447c478bd9Sstevel@tonic-gate * If we are opening a file in the /proc/pid/fd directory,
2457c478bd9Sstevel@tonic-gate * reject the open for any but a regular file or directory.
2467c478bd9Sstevel@tonic-gate * Just do it if we are opening the current or root directory.
2477c478bd9Sstevel@tonic-gate */
2487c478bd9Sstevel@tonic-gate switch (type) {
2497c478bd9Sstevel@tonic-gate case PR_OBJECT:
2507c478bd9Sstevel@tonic-gate case PR_FD:
2517c478bd9Sstevel@tonic-gate case PR_CURDIR:
2527c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
2537c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
2547c478bd9Sstevel@tonic-gate vtype = rvp->v_type;
2557c478bd9Sstevel@tonic-gate if ((type == PR_OBJECT && (flag & FWRITE)) ||
2567c478bd9Sstevel@tonic-gate (type == PR_FD && vtype != VREG && vtype != VDIR))
2577c478bd9Sstevel@tonic-gate error = EACCES;
2587c478bd9Sstevel@tonic-gate else {
2597c478bd9Sstevel@tonic-gate /*
2607c478bd9Sstevel@tonic-gate * Need to hold rvp since VOP_OPEN() may release it.
2617c478bd9Sstevel@tonic-gate */
2627c478bd9Sstevel@tonic-gate VN_HOLD(rvp);
263da6c28aaSamw error = VOP_OPEN(&rvp, flag, cr, ct);
2647c478bd9Sstevel@tonic-gate if (error) {
2657c478bd9Sstevel@tonic-gate VN_RELE(rvp);
2667c478bd9Sstevel@tonic-gate } else {
2677c478bd9Sstevel@tonic-gate *vpp = rvp;
2687c478bd9Sstevel@tonic-gate VN_RELE(vp);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate return (error);
2727c478bd9Sstevel@tonic-gate default:
2737c478bd9Sstevel@tonic-gate break;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate /*
2777c478bd9Sstevel@tonic-gate * If we are opening the pagedata file, allocate a prnode now
2787c478bd9Sstevel@tonic-gate * to avoid calling kmem_alloc() while holding p->p_lock.
2797c478bd9Sstevel@tonic-gate */
2807c478bd9Sstevel@tonic-gate if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
2817c478bd9Sstevel@tonic-gate npnp = prgetnode(vp, type);
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate * If the process exists, lock it now.
2857c478bd9Sstevel@tonic-gate * Otherwise we have a race condition with prclose().
2867c478bd9Sstevel@tonic-gate */
2877c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
2887c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
2897c478bd9Sstevel@tonic-gate if (p == NULL) {
2907c478bd9Sstevel@tonic-gate if (npnp != NULL)
2917c478bd9Sstevel@tonic-gate prfreenode(npnp);
2927c478bd9Sstevel@tonic-gate return (ENOENT);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
2957c478bd9Sstevel@tonic-gate ASSERT(p->p_proc_flag & P_PR_LOCK);
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /*
2987c478bd9Sstevel@tonic-gate * Maintain a count of opens for write. Allow exactly one
2997c478bd9Sstevel@tonic-gate * O_WRITE|O_EXCL request and fail subsequent ones.
3007c478bd9Sstevel@tonic-gate * Don't fail opens of old (bletch!) /proc lwp files.
3017c478bd9Sstevel@tonic-gate * Special case for open by the process itself:
3027c478bd9Sstevel@tonic-gate * Always allow the open by self and discount this
3037c478bd9Sstevel@tonic-gate * open for other opens for writing.
3047c478bd9Sstevel@tonic-gate */
3057c478bd9Sstevel@tonic-gate if (flag & FWRITE) {
3067c478bd9Sstevel@tonic-gate if (p == curproc) {
3077c478bd9Sstevel@tonic-gate pcp->prc_selfopens++;
3087c478bd9Sstevel@tonic-gate pnp->pr_flags |= PR_ISSELF;
3097c478bd9Sstevel@tonic-gate } else if (type == PR_LWPIDFILE) {
3107c478bd9Sstevel@tonic-gate /* EMPTY */;
3117c478bd9Sstevel@tonic-gate } else if (flag & FEXCL) {
3127c478bd9Sstevel@tonic-gate if (pcp->prc_writers > pcp->prc_selfopens) {
3137c478bd9Sstevel@tonic-gate error = EBUSY;
3147c478bd9Sstevel@tonic-gate goto out;
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate /* semantic for old /proc interface */
3177c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR)
3187c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_EXCL;
3197c478bd9Sstevel@tonic-gate } else if (pcp->prc_flags & PRC_EXCL) {
3207c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers > pcp->prc_selfopens);
3217c478bd9Sstevel@tonic-gate error = secpolicy_proc_excl_open(cr);
3227c478bd9Sstevel@tonic-gate if (error)
3237c478bd9Sstevel@tonic-gate goto out;
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate pcp->prc_writers++;
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate * The vnode may have become invalid between the
3287c478bd9Sstevel@tonic-gate * VOP_LOOKUP() of the /proc vnode and the VOP_OPEN().
3297c478bd9Sstevel@tonic-gate * If so, do now what prinvalidate() should have done.
3307c478bd9Sstevel@tonic-gate */
3317c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & PR_INVAL) ||
3327c478bd9Sstevel@tonic-gate (type == PR_PIDDIR &&
3337c478bd9Sstevel@tonic-gate (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
3347c478bd9Sstevel@tonic-gate if (p != curproc)
3357c478bd9Sstevel@tonic-gate pcp->prc_selfopens++;
3367c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
3377c478bd9Sstevel@tonic-gate if (pcp->prc_selfopens == pcp->prc_writers)
3387c478bd9Sstevel@tonic-gate pcp->prc_flags &= ~PRC_EXCL;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
343d1b18d1aSBryan Cantrill * If this is a large file open, indicate that in our flags -- some
344d1b18d1aSBryan Cantrill * procfs structures are not off_t-neutral (e.g., priovec_t), and
345d1b18d1aSBryan Cantrill * the open will need to be differentiated where 32-bit processes
346d1b18d1aSBryan Cantrill * pass these structures across the user/kernel boundary.
347d1b18d1aSBryan Cantrill */
348d1b18d1aSBryan Cantrill if (flag & FOFFMAX)
349d1b18d1aSBryan Cantrill pnp->pr_flags |= PR_OFFMAX;
350d1b18d1aSBryan Cantrill
351d1b18d1aSBryan Cantrill /*
3527c478bd9Sstevel@tonic-gate * Do file-specific things.
3537c478bd9Sstevel@tonic-gate */
3547c478bd9Sstevel@tonic-gate switch (type) {
3557c478bd9Sstevel@tonic-gate default:
3567c478bd9Sstevel@tonic-gate break;
3577c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
3587c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * Enable data collection for page data file;
3617c478bd9Sstevel@tonic-gate * get unique id from the hat layer.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate int id;
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * Drop p->p_lock to call hat_startstat()
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3707c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas ||
3717c478bd9Sstevel@tonic-gate (id = hat_startstat(p->p_as)) == -1) {
3727c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3737c478bd9Sstevel@tonic-gate error = ENOMEM;
3747c478bd9Sstevel@tonic-gate } else if (pnp->pr_hatid == 0) {
3757c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3767c478bd9Sstevel@tonic-gate pnp->pr_hatid = (uint_t)id;
3777c478bd9Sstevel@tonic-gate } else {
3787c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3797c478bd9Sstevel@tonic-gate /*
3807c478bd9Sstevel@tonic-gate * Use our newly allocated prnode.
3817c478bd9Sstevel@tonic-gate */
3827c478bd9Sstevel@tonic-gate npnp->pr_hatid = (uint_t)id;
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
3857c478bd9Sstevel@tonic-gate * Duplicate the remainder.
3867c478bd9Sstevel@tonic-gate */
3877c478bd9Sstevel@tonic-gate npnp->pr_ino = pnp->pr_ino;
3887c478bd9Sstevel@tonic-gate npnp->pr_common = pnp->pr_common;
3897c478bd9Sstevel@tonic-gate npnp->pr_pcommon = pnp->pr_pcommon;
3907c478bd9Sstevel@tonic-gate npnp->pr_parent = pnp->pr_parent;
3917c478bd9Sstevel@tonic-gate VN_HOLD(npnp->pr_parent);
3927c478bd9Sstevel@tonic-gate npnp->pr_index = pnp->pr_index;
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate npnp->pr_next = p->p_plist;
3957c478bd9Sstevel@tonic-gate p->p_plist = PTOV(npnp);
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate VN_RELE(PTOV(pnp));
3987c478bd9Sstevel@tonic-gate pnp = npnp;
3997c478bd9Sstevel@tonic-gate npnp = NULL;
4007c478bd9Sstevel@tonic-gate *vpp = PTOV(pnp);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate break;
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate out:
4077c478bd9Sstevel@tonic-gate prunlock(pnp);
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate if (npnp != NULL)
4107c478bd9Sstevel@tonic-gate prfreenode(npnp);
4117c478bd9Sstevel@tonic-gate return (error);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /* ARGSUSED */
4157c478bd9Sstevel@tonic-gate static int
prclose(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)416da6c28aaSamw prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
417da6c28aaSamw caller_context_t *ct)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
4207c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_pcommon;
4217c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
4227c478bd9Sstevel@tonic-gate proc_t *p;
4237c478bd9Sstevel@tonic-gate kthread_t *t;
4247c478bd9Sstevel@tonic-gate user_t *up;
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate * Nothing to do for the /proc directory itself.
4287c478bd9Sstevel@tonic-gate */
4297c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR)
4307c478bd9Sstevel@tonic-gate return (0);
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate ASSERT(type != PR_OBJECT && type != PR_FD &&
4337c478bd9Sstevel@tonic-gate type != PR_CURDIR && type != PR_ROOTDIR);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate * If the process exists, lock it now.
4377c478bd9Sstevel@tonic-gate * Otherwise we have a race condition with propen().
4387c478bd9Sstevel@tonic-gate * Hold pr_pidlock across the reference to prc_selfopens,
4397c478bd9Sstevel@tonic-gate * and prc_writers in case there is no process anymore,
4407c478bd9Sstevel@tonic-gate * to cover the case of concurrent calls to prclose()
4417c478bd9Sstevel@tonic-gate * after the process has been reaped by freeproc().
4427c478bd9Sstevel@tonic-gate */
4437c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate * There is nothing more to do until the last close of
4477c478bd9Sstevel@tonic-gate * the file table entry except to clear the pr_owner
4487c478bd9Sstevel@tonic-gate * field of the prnode and notify any waiters
4497c478bd9Sstevel@tonic-gate * (their file descriptor may have just been closed).
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate if (count > 1) {
4527c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
4537c478bd9Sstevel@tonic-gate if (pnp->pr_owner == curproc && !fisopen(vp))
4547c478bd9Sstevel@tonic-gate pnp->pr_owner = NULL;
4557c478bd9Sstevel@tonic-gate if (p != NULL) {
4567c478bd9Sstevel@tonic-gate prnotify(vp);
4577c478bd9Sstevel@tonic-gate prunlock(pnp);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate return (0);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate * Decrement the count of self-opens for writing.
4647c478bd9Sstevel@tonic-gate * Decrement the total count of opens for writing.
4657c478bd9Sstevel@tonic-gate * Cancel exclusive opens when only self-opens remain.
4667c478bd9Sstevel@tonic-gate */
4677c478bd9Sstevel@tonic-gate if (flag & FWRITE) {
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate * prc_selfopens also contains the count of
4707c478bd9Sstevel@tonic-gate * invalid writers. See prinvalidate().
4717c478bd9Sstevel@tonic-gate */
4727c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
4737c478bd9Sstevel@tonic-gate (type == PR_PIDDIR &&
4747c478bd9Sstevel@tonic-gate (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
4757c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens != 0);
4767c478bd9Sstevel@tonic-gate --pcp->prc_selfopens;
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers != 0);
4797c478bd9Sstevel@tonic-gate if (--pcp->prc_writers == pcp->prc_selfopens)
4807c478bd9Sstevel@tonic-gate pcp->prc_flags &= ~PRC_EXCL;
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
4837c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
4847c478bd9Sstevel@tonic-gate if (pnp->pr_owner == curproc && !fisopen(vp))
4857c478bd9Sstevel@tonic-gate pnp->pr_owner = NULL;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate /*
4887c478bd9Sstevel@tonic-gate * If there is no process, there is nothing more to do.
4897c478bd9Sstevel@tonic-gate */
4907c478bd9Sstevel@tonic-gate if (p == NULL)
4917c478bd9Sstevel@tonic-gate return (0);
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
4947c478bd9Sstevel@tonic-gate prnotify(vp); /* notify waiters */
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate /*
4977c478bd9Sstevel@tonic-gate * Do file-specific things.
4987c478bd9Sstevel@tonic-gate */
4997c478bd9Sstevel@tonic-gate switch (type) {
5007c478bd9Sstevel@tonic-gate default:
5017c478bd9Sstevel@tonic-gate break;
5027c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
5037c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate * This is a page data file.
5067c478bd9Sstevel@tonic-gate * Free the hat level statistics.
5077c478bd9Sstevel@tonic-gate * Drop p->p_lock before calling hat_freestat().
5087c478bd9Sstevel@tonic-gate */
5097c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
5107c478bd9Sstevel@tonic-gate if (p->p_as != &kas && pnp->pr_hatid != 0)
5117c478bd9Sstevel@tonic-gate hat_freestat(p->p_as, pnp->pr_hatid);
5127c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
5137c478bd9Sstevel@tonic-gate pnp->pr_hatid = 0;
5147c478bd9Sstevel@tonic-gate break;
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate /*
5187c478bd9Sstevel@tonic-gate * On last close of all writable file descriptors,
5197c478bd9Sstevel@tonic-gate * perform run-on-last-close and/or kill-on-last-close logic.
5207c478bd9Sstevel@tonic-gate * Can't do this is the /proc agent lwp still exists.
5217c478bd9Sstevel@tonic-gate */
5227c478bd9Sstevel@tonic-gate if (pcp->prc_writers == 0 &&
5237c478bd9Sstevel@tonic-gate p->p_agenttp == NULL &&
5247c478bd9Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY) &&
5257c478bd9Sstevel@tonic-gate p->p_stat != SZOMB &&
5267c478bd9Sstevel@tonic-gate (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
5277c478bd9Sstevel@tonic-gate int killproc;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate * Cancel any watchpoints currently in effect.
5317c478bd9Sstevel@tonic-gate * The process might disappear during this operation.
5327c478bd9Sstevel@tonic-gate */
5337c478bd9Sstevel@tonic-gate if (pr_cancel_watch(pnp) == NULL)
5347c478bd9Sstevel@tonic-gate return (0);
5357c478bd9Sstevel@tonic-gate /*
5367c478bd9Sstevel@tonic-gate * If any tracing flags are set, clear them.
5377c478bd9Sstevel@tonic-gate */
5387c478bd9Sstevel@tonic-gate if (p->p_proc_flag & P_PR_TRACE) {
5397c478bd9Sstevel@tonic-gate up = PTOU(p);
5407c478bd9Sstevel@tonic-gate premptyset(&up->u_entrymask);
5417c478bd9Sstevel@tonic-gate premptyset(&up->u_exitmask);
5427c478bd9Sstevel@tonic-gate up->u_systrap = 0;
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate premptyset(&p->p_sigmask);
5457c478bd9Sstevel@tonic-gate premptyset(&p->p_fltmask);
5467c478bd9Sstevel@tonic-gate killproc = (p->p_proc_flag & P_PR_KILLCL);
5477c478bd9Sstevel@tonic-gate p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
5487c478bd9Sstevel@tonic-gate /*
5497c478bd9Sstevel@tonic-gate * Cancel any outstanding single-step requests.
5507c478bd9Sstevel@tonic-gate */
5517c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate * Drop p_lock because prnostep() touches the stack.
5547c478bd9Sstevel@tonic-gate * The loop is safe because the process is P_PR_LOCK'd.
5557c478bd9Sstevel@tonic-gate */
5567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
5577c478bd9Sstevel@tonic-gate do {
5587c478bd9Sstevel@tonic-gate prnostep(ttolwp(t));
5597c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
5607c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * Set runnable all lwps stopped by /proc.
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate if (killproc)
5667c478bd9Sstevel@tonic-gate sigtoproc(p, NULL, SIGKILL);
5677c478bd9Sstevel@tonic-gate else
5687c478bd9Sstevel@tonic-gate allsetrun(p);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate prunlock(pnp);
5727c478bd9Sstevel@tonic-gate return (0);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate * Array of read functions, indexed by /proc file type.
5777c478bd9Sstevel@tonic-gate */
5787c478bd9Sstevel@tonic-gate static int pr_read_inval(), pr_read_as(), pr_read_status(),
5797c478bd9Sstevel@tonic-gate pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
5807c478bd9Sstevel@tonic-gate pr_read_map(), pr_read_rmap(), pr_read_xmap(),
5817c478bd9Sstevel@tonic-gate pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
5827c478bd9Sstevel@tonic-gate #if defined(__x86)
5837c478bd9Sstevel@tonic-gate pr_read_ldt(),
5847c478bd9Sstevel@tonic-gate #endif
5857c478bd9Sstevel@tonic-gate pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
5867c478bd9Sstevel@tonic-gate pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
5877c478bd9Sstevel@tonic-gate pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
588f971a346SBryan Cantrill pr_read_spymaster(),
5897c478bd9Sstevel@tonic-gate #if defined(__sparc)
5907c478bd9Sstevel@tonic-gate pr_read_gwindows(), pr_read_asrs(),
5917c478bd9Sstevel@tonic-gate #endif
5927c478bd9Sstevel@tonic-gate pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate static int (*pr_read_function[PR_NFILES])() = {
5957c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc */
5967c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/self */
5977c478bd9Sstevel@tonic-gate pr_read_piddir, /* /proc/<pid> (old /proc read()) */
5987c478bd9Sstevel@tonic-gate pr_read_as, /* /proc/<pid>/as */
5997c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/ctl */
6007c478bd9Sstevel@tonic-gate pr_read_status, /* /proc/<pid>/status */
6017c478bd9Sstevel@tonic-gate pr_read_lstatus, /* /proc/<pid>/lstatus */
6027c478bd9Sstevel@tonic-gate pr_read_psinfo, /* /proc/<pid>/psinfo */
6037c478bd9Sstevel@tonic-gate pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
6047c478bd9Sstevel@tonic-gate pr_read_map, /* /proc/<pid>/map */
6057c478bd9Sstevel@tonic-gate pr_read_rmap, /* /proc/<pid>/rmap */
6067c478bd9Sstevel@tonic-gate pr_read_xmap, /* /proc/<pid>/xmap */
6077c478bd9Sstevel@tonic-gate pr_read_cred, /* /proc/<pid>/cred */
6087c478bd9Sstevel@tonic-gate pr_read_sigact, /* /proc/<pid>/sigact */
6097c478bd9Sstevel@tonic-gate pr_read_auxv, /* /proc/<pid>/auxv */
6107c478bd9Sstevel@tonic-gate #if defined(__x86)
6117c478bd9Sstevel@tonic-gate pr_read_ldt, /* /proc/<pid>/ldt */
6127c478bd9Sstevel@tonic-gate #endif
6137c478bd9Sstevel@tonic-gate pr_read_usage, /* /proc/<pid>/usage */
6147c478bd9Sstevel@tonic-gate pr_read_lusage, /* /proc/<pid>/lusage */
6157c478bd9Sstevel@tonic-gate pr_read_pagedata, /* /proc/<pid>/pagedata */
6167c478bd9Sstevel@tonic-gate pr_read_watch, /* /proc/<pid>/watch */
6177c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/cwd */
6187c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/root */
6197c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd */
6207c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd/nn */
6217c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object */
6227c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object/xxx */
6237c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp */
6247c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
6257c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
6267c478bd9Sstevel@tonic-gate pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
6277c478bd9Sstevel@tonic-gate pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
6287c478bd9Sstevel@tonic-gate pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
6297c478bd9Sstevel@tonic-gate pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
6307c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
6317c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
632f971a346SBryan Cantrill pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
6337c478bd9Sstevel@tonic-gate #if defined(__sparc)
6347c478bd9Sstevel@tonic-gate pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
6357c478bd9Sstevel@tonic-gate pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
6367c478bd9Sstevel@tonic-gate #endif
6377c478bd9Sstevel@tonic-gate pr_read_priv, /* /proc/<pid>/priv */
6387c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path */
6397c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path/xxx */
6407c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts */
6417c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
6427c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old process file */
6437c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old lwp file */
6447c478bd9Sstevel@tonic-gate pr_read_opagedata, /* old pagedata file */
6457c478bd9Sstevel@tonic-gate };
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate /* ARGSUSED */
6487c478bd9Sstevel@tonic-gate static int
pr_read_inval(prnode_t * pnp,uio_t * uiop)6497c478bd9Sstevel@tonic-gate pr_read_inval(prnode_t *pnp, uio_t *uiop)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * No read() on any /proc directory, use getdents(2) instead.
6537c478bd9Sstevel@tonic-gate * Cannot read a control file either.
6547c478bd9Sstevel@tonic-gate * An underlying mapped object file cannot get here.
6557c478bd9Sstevel@tonic-gate */
6567c478bd9Sstevel@tonic-gate return (EINVAL);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate static int
pr_uioread(void * base,long count,uio_t * uiop)6607c478bd9Sstevel@tonic-gate pr_uioread(void *base, long count, uio_t *uiop)
6617c478bd9Sstevel@tonic-gate {
6627c478bd9Sstevel@tonic-gate int error = 0;
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate ASSERT(count >= 0);
6657c478bd9Sstevel@tonic-gate count -= uiop->uio_offset;
6667c478bd9Sstevel@tonic-gate if (count > 0 && uiop->uio_offset >= 0) {
6677c478bd9Sstevel@tonic-gate error = uiomove((char *)base + uiop->uio_offset,
6687c478bd9Sstevel@tonic-gate count, UIO_READ, uiop);
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate return (error);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate static int
pr_read_as(prnode_t * pnp,uio_t * uiop)6757c478bd9Sstevel@tonic-gate pr_read_as(prnode_t *pnp, uio_t *uiop)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate int error;
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AS);
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
6827c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
6837c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
6877c478bd9Sstevel@tonic-gate * A 32-bit process cannot read a 64-bit process.
6887c478bd9Sstevel@tonic-gate */
6897c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
6907c478bd9Sstevel@tonic-gate error = 0;
6917c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
6927c478bd9Sstevel@tonic-gate } else if (curproc->p_model == DATAMODEL_ILP32 &&
6937c478bd9Sstevel@tonic-gate PROCESS_NOT_32BIT(p)) {
6947c478bd9Sstevel@tonic-gate error = EOVERFLOW;
6957c478bd9Sstevel@tonic-gate #endif
6967c478bd9Sstevel@tonic-gate } else {
6977c478bd9Sstevel@tonic-gate /*
6987c478bd9Sstevel@tonic-gate * We don't hold p_lock over an i/o operation because
6997c478bd9Sstevel@tonic-gate * that could lead to deadlock with the clock thread.
7007c478bd9Sstevel@tonic-gate */
7017c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
7027c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_READ, uiop, 0);
7037c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate prunlock(pnp);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate return (error);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate static int
pr_read_status(prnode_t * pnp,uio_t * uiop)7127c478bd9Sstevel@tonic-gate pr_read_status(prnode_t *pnp, uio_t *uiop)
7137c478bd9Sstevel@tonic-gate {
7147c478bd9Sstevel@tonic-gate pstatus_t *sp;
7157c478bd9Sstevel@tonic-gate int error;
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_STATUS);
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate /*
7207c478bd9Sstevel@tonic-gate * We kmem_alloc() the pstatus structure because
7217c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
7227c478bd9Sstevel@tonic-gate */
7237c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
7247c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
725fa9e4066Sahrens prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
7267c478bd9Sstevel@tonic-gate prunlock(pnp);
7277c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
7307c478bd9Sstevel@tonic-gate return (error);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate static int
pr_read_lstatus(prnode_t * pnp,uio_t * uiop)7347c478bd9Sstevel@tonic-gate pr_read_lstatus(prnode_t *pnp, uio_t *uiop)
7357c478bd9Sstevel@tonic-gate {
7367c478bd9Sstevel@tonic-gate proc_t *p;
7377c478bd9Sstevel@tonic-gate kthread_t *t;
7387c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
7397c478bd9Sstevel@tonic-gate size_t size;
7407c478bd9Sstevel@tonic-gate prheader_t *php;
7417c478bd9Sstevel@tonic-gate lwpstatus_t *sp;
7427c478bd9Sstevel@tonic-gate int error;
7437c478bd9Sstevel@tonic-gate int nlwp;
7447c478bd9Sstevel@tonic-gate int i;
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LSTATUS);
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
7497c478bd9Sstevel@tonic-gate return (error);
7507c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
7517c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt;
7527c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
7557c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
7567c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
7577c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
7587c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
7597c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
7627c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(lwpstatus_t);
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate sp = (lwpstatus_t *)(php + 1);
7657c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
7667c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
7677c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
7687c478bd9Sstevel@tonic-gate continue;
769fa9e4066Sahrens prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
7707c478bd9Sstevel@tonic-gate sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate prunlock(pnp);
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
7757c478bd9Sstevel@tonic-gate kmem_free(php, size);
7767c478bd9Sstevel@tonic-gate return (error);
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate static int
pr_read_psinfo(prnode_t * pnp,uio_t * uiop)7807c478bd9Sstevel@tonic-gate pr_read_psinfo(prnode_t *pnp, uio_t *uiop)
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate psinfo_t psinfo;
7837c478bd9Sstevel@tonic-gate proc_t *p;
7847c478bd9Sstevel@tonic-gate int error = 0;
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PSINFO);
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate /*
7897c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
7907c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
7917c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
7927c478bd9Sstevel@tonic-gate */
7937c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
7947c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
7957c478bd9Sstevel@tonic-gate if (p == NULL)
7967c478bd9Sstevel@tonic-gate error = ENOENT;
7977c478bd9Sstevel@tonic-gate else {
7987c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
7997c478bd9Sstevel@tonic-gate prgetpsinfo(p, &psinfo);
8007c478bd9Sstevel@tonic-gate prunlock(pnp);
8017c478bd9Sstevel@tonic-gate error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate return (error);
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate
8067c478bd9Sstevel@tonic-gate static int
pr_read_lpsinfo(prnode_t * pnp,uio_t * uiop)8077c478bd9Sstevel@tonic-gate pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate proc_t *p;
8107c478bd9Sstevel@tonic-gate kthread_t *t;
8117c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
8127c478bd9Sstevel@tonic-gate lwpent_t *lep;
8137c478bd9Sstevel@tonic-gate size_t size;
8147c478bd9Sstevel@tonic-gate prheader_t *php;
8157c478bd9Sstevel@tonic-gate lwpsinfo_t *sp;
8167c478bd9Sstevel@tonic-gate int error;
8177c478bd9Sstevel@tonic-gate int nlwp;
8187c478bd9Sstevel@tonic-gate int i;
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LPSINFO);
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate /*
8237c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
8247c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
8257c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
8267c478bd9Sstevel@tonic-gate */
8277c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
8287c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
8297c478bd9Sstevel@tonic-gate if (p == NULL)
8307c478bd9Sstevel@tonic-gate return (ENOENT);
8317c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
8327c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
8337c478bd9Sstevel@tonic-gate prunlock(pnp);
8347c478bd9Sstevel@tonic-gate return (ENOENT);
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
8397c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
8407c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
8417c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
8427c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
8437c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
8467c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(lwpsinfo_t);
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate sp = (lwpsinfo_t *)(php + 1);
8497c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
8507c478bd9Sstevel@tonic-gate if ((lep = ldp->ld_entry) == NULL)
8517c478bd9Sstevel@tonic-gate continue;
8527c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) != NULL)
8537c478bd9Sstevel@tonic-gate prgetlwpsinfo(t, sp);
8547c478bd9Sstevel@tonic-gate else {
8557c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp));
8567c478bd9Sstevel@tonic-gate sp->pr_lwpid = lep->le_lwpid;
8577c478bd9Sstevel@tonic-gate sp->pr_state = SZOMB;
8587c478bd9Sstevel@tonic-gate sp->pr_sname = 'Z';
8597c478bd9Sstevel@tonic-gate sp->pr_start.tv_sec = lep->le_start;
8607c478bd9Sstevel@tonic-gate sp->pr_bindpro = PBIND_NONE;
8617c478bd9Sstevel@tonic-gate sp->pr_bindpset = PS_NONE;
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate prunlock(pnp);
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
8687c478bd9Sstevel@tonic-gate kmem_free(php, size);
8697c478bd9Sstevel@tonic-gate return (error);
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate static int
pr_read_map_common(prnode_t * pnp,uio_t * uiop,prnodetype_t type)873870619e9Sfrankho pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
8747c478bd9Sstevel@tonic-gate {
8757c478bd9Sstevel@tonic-gate proc_t *p;
8767c478bd9Sstevel@tonic-gate struct as *as;
877870619e9Sfrankho list_t iolhead;
8787c478bd9Sstevel@tonic-gate int error;
8797c478bd9Sstevel@tonic-gate
880e24ad047SChristopher Baumbauer - Oracle America - San Diego United States readmap_common:
8817c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
8827c478bd9Sstevel@tonic-gate return (error);
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
8857c478bd9Sstevel@tonic-gate as = p->p_as;
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
8887c478bd9Sstevel@tonic-gate prunlock(pnp);
8897c478bd9Sstevel@tonic-gate return (0);
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate
892*fd435bccSJosef 'Jeff' Sipek if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
893e24ad047SChristopher Baumbauer - Oracle America - San Diego United States prunlock(pnp);
894e24ad047SChristopher Baumbauer - Oracle America - San Diego United States delay(1);
895e24ad047SChristopher Baumbauer - Oracle America - San Diego United States goto readmap_common;
896e24ad047SChristopher Baumbauer - Oracle America - San Diego United States }
8977c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
898e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
899870619e9Sfrankho switch (type) {
900870619e9Sfrankho case PR_XMAP:
901870619e9Sfrankho error = prgetxmap(p, &iolhead);
902870619e9Sfrankho break;
903870619e9Sfrankho case PR_RMAP:
904870619e9Sfrankho error = prgetmap(p, 1, &iolhead);
905870619e9Sfrankho break;
906870619e9Sfrankho case PR_MAP:
907870619e9Sfrankho error = prgetmap(p, 0, &iolhead);
908870619e9Sfrankho break;
909870619e9Sfrankho }
910e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
911*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
9127c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
9137c478bd9Sstevel@tonic-gate prunlock(pnp);
9147c478bd9Sstevel@tonic-gate
915870619e9Sfrankho error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
916870619e9Sfrankho
9177c478bd9Sstevel@tonic-gate return (error);
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate static int
pr_read_map(prnode_t * pnp,uio_t * uiop)9217c478bd9Sstevel@tonic-gate pr_read_map(prnode_t *pnp, uio_t *uiop)
9227c478bd9Sstevel@tonic-gate {
9237c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_MAP);
924870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate static int
pr_read_rmap(prnode_t * pnp,uio_t * uiop)9287c478bd9Sstevel@tonic-gate pr_read_rmap(prnode_t *pnp, uio_t *uiop)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_RMAP);
931870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate static int
pr_read_xmap(prnode_t * pnp,uio_t * uiop)9357c478bd9Sstevel@tonic-gate pr_read_xmap(prnode_t *pnp, uio_t *uiop)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XMAP);
938870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate static int
pr_read_cred(prnode_t * pnp,uio_t * uiop)9427c478bd9Sstevel@tonic-gate pr_read_cred(prnode_t *pnp, uio_t *uiop)
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate proc_t *p;
9457c478bd9Sstevel@tonic-gate prcred_t *pcrp;
9467c478bd9Sstevel@tonic-gate int error;
9477c478bd9Sstevel@tonic-gate size_t count;
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_CRED);
9507c478bd9Sstevel@tonic-gate
9517c478bd9Sstevel@tonic-gate /*
9527c478bd9Sstevel@tonic-gate * We kmem_alloc() the prcred_t structure because
9537c478bd9Sstevel@tonic-gate * the number of supplementary groups is variable.
9547c478bd9Sstevel@tonic-gate */
9557c478bd9Sstevel@tonic-gate pcrp =
9567c478bd9Sstevel@tonic-gate kmem_alloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
9577c478bd9Sstevel@tonic-gate KM_SLEEP);
9587c478bd9Sstevel@tonic-gate
9597c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
9607c478bd9Sstevel@tonic-gate goto out;
9617c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
9627c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
9637c478bd9Sstevel@tonic-gate
9647c478bd9Sstevel@tonic-gate prgetcred(p, pcrp);
9657c478bd9Sstevel@tonic-gate prunlock(pnp);
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate count = sizeof (prcred_t);
9687c478bd9Sstevel@tonic-gate if (pcrp->pr_ngroups > 1)
9697c478bd9Sstevel@tonic-gate count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
9707c478bd9Sstevel@tonic-gate error = pr_uioread(pcrp, count, uiop);
9717c478bd9Sstevel@tonic-gate out:
9727c478bd9Sstevel@tonic-gate kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
9737c478bd9Sstevel@tonic-gate return (error);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate
9767c478bd9Sstevel@tonic-gate static int
pr_read_priv(prnode_t * pnp,uio_t * uiop)9777c478bd9Sstevel@tonic-gate pr_read_priv(prnode_t *pnp, uio_t *uiop)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate proc_t *p;
9807c478bd9Sstevel@tonic-gate size_t psize = prgetprivsize();
9817c478bd9Sstevel@tonic-gate prpriv_t *ppriv = kmem_alloc(psize, KM_SLEEP);
9827c478bd9Sstevel@tonic-gate int error;
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PRIV);
9857c478bd9Sstevel@tonic-gate
9867c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
9877c478bd9Sstevel@tonic-gate goto out;
9887c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
9897c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate prgetpriv(p, ppriv);
9927c478bd9Sstevel@tonic-gate prunlock(pnp);
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate error = pr_uioread(ppriv, psize, uiop);
9957c478bd9Sstevel@tonic-gate out:
9967c478bd9Sstevel@tonic-gate kmem_free(ppriv, psize);
9977c478bd9Sstevel@tonic-gate return (error);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate
10007c478bd9Sstevel@tonic-gate static int
pr_read_sigact(prnode_t * pnp,uio_t * uiop)10017c478bd9Sstevel@tonic-gate pr_read_sigact(prnode_t *pnp, uio_t *uiop)
10027c478bd9Sstevel@tonic-gate {
1003eb9dbf0cSRoger A. Faulkner int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
10047c478bd9Sstevel@tonic-gate proc_t *p;
10057c478bd9Sstevel@tonic-gate struct sigaction *sap;
10067c478bd9Sstevel@tonic-gate int sig;
10077c478bd9Sstevel@tonic-gate int error;
10087c478bd9Sstevel@tonic-gate user_t *up;
10097c478bd9Sstevel@tonic-gate
10107c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_SIGACT);
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate /*
10137c478bd9Sstevel@tonic-gate * We kmem_alloc() the sigaction array because
10147c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
10157c478bd9Sstevel@tonic-gate */
1016eb9dbf0cSRoger A. Faulkner sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
10197c478bd9Sstevel@tonic-gate goto out;
10207c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
10217c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
10227c478bd9Sstevel@tonic-gate
1023eb9dbf0cSRoger A. Faulkner if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
10247c478bd9Sstevel@tonic-gate prunlock(pnp);
10257c478bd9Sstevel@tonic-gate goto out;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
10287c478bd9Sstevel@tonic-gate up = PTOU(p);
1029eb9dbf0cSRoger A. Faulkner for (sig = 1; sig < nsig; sig++)
10307c478bd9Sstevel@tonic-gate prgetaction(p, up, sig, &sap[sig-1]);
10317c478bd9Sstevel@tonic-gate prunlock(pnp);
10327c478bd9Sstevel@tonic-gate
1033eb9dbf0cSRoger A. Faulkner error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
10347c478bd9Sstevel@tonic-gate out:
1035eb9dbf0cSRoger A. Faulkner kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
10367c478bd9Sstevel@tonic-gate return (error);
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate static int
pr_read_auxv(prnode_t * pnp,uio_t * uiop)10407c478bd9Sstevel@tonic-gate pr_read_auxv(prnode_t *pnp, uio_t *uiop)
10417c478bd9Sstevel@tonic-gate {
10427c478bd9Sstevel@tonic-gate auxv_t auxv[__KERN_NAUXV_IMPL];
10437c478bd9Sstevel@tonic-gate proc_t *p;
10447c478bd9Sstevel@tonic-gate user_t *up;
10457c478bd9Sstevel@tonic-gate int error;
10467c478bd9Sstevel@tonic-gate
10477c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AUXV);
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
10507c478bd9Sstevel@tonic-gate return (error);
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (auxv)) {
10537c478bd9Sstevel@tonic-gate prunlock(pnp);
10547c478bd9Sstevel@tonic-gate return (0);
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
10587c478bd9Sstevel@tonic-gate up = PTOU(p);
10597c478bd9Sstevel@tonic-gate bcopy(up->u_auxv, auxv, sizeof (auxv));
10607c478bd9Sstevel@tonic-gate prunlock(pnp);
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate return (pr_uioread(auxv, sizeof (auxv), uiop));
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate #if defined(__x86)
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate * XX64
10687c478bd9Sstevel@tonic-gate * This is almost certainly broken for the amd64 kernel, because
10697c478bd9Sstevel@tonic-gate * we have two kinds of LDT structures to export -- one for compatibility
10707c478bd9Sstevel@tonic-gate * mode, and one for long mode, sigh.
10717c478bd9Sstevel@tonic-gate *
10727c478bd9Sstevel@tonic-gate * For now lets just have a ldt of size 0 for 64-bit processes.
10737c478bd9Sstevel@tonic-gate */
10747c478bd9Sstevel@tonic-gate static int
pr_read_ldt(prnode_t * pnp,uio_t * uiop)10757c478bd9Sstevel@tonic-gate pr_read_ldt(prnode_t *pnp, uio_t *uiop)
10767c478bd9Sstevel@tonic-gate {
10777c478bd9Sstevel@tonic-gate proc_t *p;
10787c478bd9Sstevel@tonic-gate struct ssd *ssd;
10797c478bd9Sstevel@tonic-gate size_t size;
10807c478bd9Sstevel@tonic-gate int error;
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LDT);
10837c478bd9Sstevel@tonic-gate
10847c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
10857c478bd9Sstevel@tonic-gate return (error);
10867c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
10897c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
10907c478bd9Sstevel@tonic-gate size = prnldt(p) * sizeof (struct ssd);
10917c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
10927c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
10937c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
10947c478bd9Sstevel@tonic-gate prunlock(pnp);
10957c478bd9Sstevel@tonic-gate return (0);
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate
10987c478bd9Sstevel@tonic-gate ssd = kmem_alloc(size, KM_SLEEP);
10997c478bd9Sstevel@tonic-gate prgetldt(p, ssd);
11007c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
11017c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
11027c478bd9Sstevel@tonic-gate prunlock(pnp);
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate error = pr_uioread(ssd, size, uiop);
11057c478bd9Sstevel@tonic-gate kmem_free(ssd, size);
11067c478bd9Sstevel@tonic-gate return (error);
11077c478bd9Sstevel@tonic-gate }
11087c478bd9Sstevel@tonic-gate #endif /* __x86 */
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate static int
pr_read_usage(prnode_t * pnp,uio_t * uiop)11117c478bd9Sstevel@tonic-gate pr_read_usage(prnode_t *pnp, uio_t *uiop)
11127c478bd9Sstevel@tonic-gate {
11137c478bd9Sstevel@tonic-gate prhusage_t *pup;
11147c478bd9Sstevel@tonic-gate prusage_t *upup;
11157c478bd9Sstevel@tonic-gate proc_t *p;
11167c478bd9Sstevel@tonic-gate kthread_t *t;
11177c478bd9Sstevel@tonic-gate int error;
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_USAGE);
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
11227c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
11237c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
11277c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
11287c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
11297c478bd9Sstevel@tonic-gate */
11307c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
11317c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
11327c478bd9Sstevel@tonic-gate if (p == NULL) {
11337c478bd9Sstevel@tonic-gate error = ENOENT;
11347c478bd9Sstevel@tonic-gate goto out;
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage_t)) {
11397c478bd9Sstevel@tonic-gate prunlock(pnp);
11407c478bd9Sstevel@tonic-gate error = 0;
11417c478bd9Sstevel@tonic-gate goto out;
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
11477c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
11487c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
11517c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
11527c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
11537c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
11547c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
11557c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
11567c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
11577c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
11587c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
11597c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
11607c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
11637c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
11647c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
11657c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
11667c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
11677c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
11687c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
11697c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
11707c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
11717c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
11727c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
11737c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate /*
11767c478bd9Sstevel@tonic-gate * Add the usage information for each active lwp.
11777c478bd9Sstevel@tonic-gate */
11787c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
11797c478bd9Sstevel@tonic-gate !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
11807c478bd9Sstevel@tonic-gate do {
11817c478bd9Sstevel@tonic-gate if (t->t_proc_flag & TP_LWPEXIT)
11827c478bd9Sstevel@tonic-gate continue;
11837c478bd9Sstevel@tonic-gate pup->pr_count++;
11847c478bd9Sstevel@tonic-gate praddusage(t, pup);
11857c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
11867c478bd9Sstevel@tonic-gate }
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate prunlock(pnp);
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage_t), uiop);
11937c478bd9Sstevel@tonic-gate out:
11947c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
11957c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
11967c478bd9Sstevel@tonic-gate return (error);
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate static int
pr_read_lusage(prnode_t * pnp,uio_t * uiop)12007c478bd9Sstevel@tonic-gate pr_read_lusage(prnode_t *pnp, uio_t *uiop)
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate int nlwp;
12037c478bd9Sstevel@tonic-gate prhusage_t *pup;
12047c478bd9Sstevel@tonic-gate prheader_t *php;
12057c478bd9Sstevel@tonic-gate prusage_t *upup;
12067c478bd9Sstevel@tonic-gate size_t size;
12077c478bd9Sstevel@tonic-gate hrtime_t curtime;
12087c478bd9Sstevel@tonic-gate proc_t *p;
12097c478bd9Sstevel@tonic-gate kthread_t *t;
12107c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
12117c478bd9Sstevel@tonic-gate int error;
12127c478bd9Sstevel@tonic-gate int i;
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LUSAGE);
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate /*
12177c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
12187c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
12197c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
12207c478bd9Sstevel@tonic-gate */
12217c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
12227c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
12237c478bd9Sstevel@tonic-gate if (p == NULL)
12247c478bd9Sstevel@tonic-gate return (ENOENT);
12257c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
12267c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt) == 0) {
12277c478bd9Sstevel@tonic-gate prunlock(pnp);
12287c478bd9Sstevel@tonic-gate return (ENOENT);
12297c478bd9Sstevel@tonic-gate }
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
12327c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
12337c478bd9Sstevel@tonic-gate prunlock(pnp);
12347c478bd9Sstevel@tonic-gate return (0);
12357c478bd9Sstevel@tonic-gate }
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
12387c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
12397c478bd9Sstevel@tonic-gate pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
12407c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
12417c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
12427c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate php = (prheader_t *)(pup + 1);
12457c478bd9Sstevel@tonic-gate upup = (prusage_t *)(php + 1);
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate php->pr_nent = nlwp + 1;
12487c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(prusage_t);
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate curtime = gethrtime();
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate /*
12537c478bd9Sstevel@tonic-gate * First the summation over defunct lwps.
12547c478bd9Sstevel@tonic-gate */
12557c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
12567c478bd9Sstevel@tonic-gate pup->pr_tstamp = curtime;
12577c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
12587c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
12617c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
12627c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
12637c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
12647c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
12657c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
12667c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
12677c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
12687c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
12697c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
12707c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
12717c478bd9Sstevel@tonic-gate
12727c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
12737c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
12747c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
12757c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
12767c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
12777c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
12787c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
12797c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
12807c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
12817c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
12827c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
12837c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
12847c478bd9Sstevel@tonic-gate
12857c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate /*
12887c478bd9Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
12897c478bd9Sstevel@tonic-gate */
12907c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
12917c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
12927c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
12937c478bd9Sstevel@tonic-gate continue;
12947c478bd9Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
12957c478bd9Sstevel@tonic-gate ASSERT(nlwp > 0);
12967c478bd9Sstevel@tonic-gate --nlwp;
12977c478bd9Sstevel@tonic-gate upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
12987c478bd9Sstevel@tonic-gate prgetusage(t, pup);
12997c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
13007c478bd9Sstevel@tonic-gate }
13017c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0);
13027c478bd9Sstevel@tonic-gate
13037c478bd9Sstevel@tonic-gate prunlock(pnp);
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
13067c478bd9Sstevel@tonic-gate kmem_free(pup, size + sizeof (prhusage_t));
13077c478bd9Sstevel@tonic-gate return (error);
13087c478bd9Sstevel@tonic-gate }
13097c478bd9Sstevel@tonic-gate
13107c478bd9Sstevel@tonic-gate static int
pr_read_pagedata(prnode_t * pnp,uio_t * uiop)13117c478bd9Sstevel@tonic-gate pr_read_pagedata(prnode_t *pnp, uio_t *uiop)
13127c478bd9Sstevel@tonic-gate {
13137c478bd9Sstevel@tonic-gate proc_t *p;
13147c478bd9Sstevel@tonic-gate int error;
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PAGEDATA);
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
13197c478bd9Sstevel@tonic-gate return (error);
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
13227c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
13237c478bd9Sstevel@tonic-gate prunlock(pnp);
13247c478bd9Sstevel@tonic-gate return (0);
13257c478bd9Sstevel@tonic-gate }
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
13287c478bd9Sstevel@tonic-gate error = prpdread(p, pnp->pr_hatid, uiop);
13297c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate prunlock(pnp);
13327c478bd9Sstevel@tonic-gate return (error);
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate static int
pr_read_opagedata(prnode_t * pnp,uio_t * uiop)13367c478bd9Sstevel@tonic-gate pr_read_opagedata(prnode_t *pnp, uio_t *uiop)
13377c478bd9Sstevel@tonic-gate {
13387c478bd9Sstevel@tonic-gate proc_t *p;
13397c478bd9Sstevel@tonic-gate struct as *as;
13407c478bd9Sstevel@tonic-gate int error;
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OPAGEDATA);
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
13457c478bd9Sstevel@tonic-gate return (error);
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
13487c478bd9Sstevel@tonic-gate as = p->p_as;
13497c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
13507c478bd9Sstevel@tonic-gate prunlock(pnp);
13517c478bd9Sstevel@tonic-gate return (0);
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate
13547c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
13557c478bd9Sstevel@tonic-gate error = oprpdread(as, pnp->pr_hatid, uiop);
13567c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate prunlock(pnp);
13597c478bd9Sstevel@tonic-gate return (error);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate static int
pr_read_watch(prnode_t * pnp,uio_t * uiop)13637c478bd9Sstevel@tonic-gate pr_read_watch(prnode_t *pnp, uio_t *uiop)
13647c478bd9Sstevel@tonic-gate {
13657c478bd9Sstevel@tonic-gate proc_t *p;
13667c478bd9Sstevel@tonic-gate int error;
13677c478bd9Sstevel@tonic-gate prwatch_t *Bpwp;
13687c478bd9Sstevel@tonic-gate size_t size;
13697c478bd9Sstevel@tonic-gate prwatch_t *pwp;
13707c478bd9Sstevel@tonic-gate int nwarea;
13717c478bd9Sstevel@tonic-gate struct watched_area *pwarea;
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_WATCH);
13747c478bd9Sstevel@tonic-gate
13757c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
13767c478bd9Sstevel@tonic-gate return (error);
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
13797c478bd9Sstevel@tonic-gate nwarea = avl_numnodes(&p->p_warea);
13807c478bd9Sstevel@tonic-gate size = nwarea * sizeof (prwatch_t);
13817c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
13827c478bd9Sstevel@tonic-gate prunlock(pnp);
13837c478bd9Sstevel@tonic-gate return (0);
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate
13867c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
13877c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
13887c478bd9Sstevel@tonic-gate Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
13897c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
13907c478bd9Sstevel@tonic-gate /* p->p_nwarea can't change while process is locked */
13917c478bd9Sstevel@tonic-gate ASSERT(nwarea == avl_numnodes(&p->p_warea));
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate /* gather the watched areas */
13947c478bd9Sstevel@tonic-gate for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
13957c478bd9Sstevel@tonic-gate pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
13967c478bd9Sstevel@tonic-gate pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
13977c478bd9Sstevel@tonic-gate pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
13987c478bd9Sstevel@tonic-gate pwp->pr_wflags = (int)pwarea->wa_flags;
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate prunlock(pnp);
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate error = pr_uioread(Bpwp, size, uiop);
14047c478bd9Sstevel@tonic-gate kmem_free(Bpwp, size);
14057c478bd9Sstevel@tonic-gate return (error);
14067c478bd9Sstevel@tonic-gate }
14077c478bd9Sstevel@tonic-gate
14087c478bd9Sstevel@tonic-gate static int
pr_read_lwpstatus(prnode_t * pnp,uio_t * uiop)14097c478bd9Sstevel@tonic-gate pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop)
14107c478bd9Sstevel@tonic-gate {
14117c478bd9Sstevel@tonic-gate lwpstatus_t *sp;
14127c478bd9Sstevel@tonic-gate int error;
14137c478bd9Sstevel@tonic-gate
14147c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSTATUS);
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate /*
14177c478bd9Sstevel@tonic-gate * We kmem_alloc() the lwpstatus structure because
14187c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
14197c478bd9Sstevel@tonic-gate */
14207c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
14237c478bd9Sstevel@tonic-gate goto out;
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (*sp)) {
14267c478bd9Sstevel@tonic-gate prunlock(pnp);
14277c478bd9Sstevel@tonic-gate goto out;
14287c478bd9Sstevel@tonic-gate }
14297c478bd9Sstevel@tonic-gate
1430fa9e4066Sahrens prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
14317c478bd9Sstevel@tonic-gate prunlock(pnp);
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
14347c478bd9Sstevel@tonic-gate out:
14357c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
14367c478bd9Sstevel@tonic-gate return (error);
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate static int
pr_read_lwpsinfo(prnode_t * pnp,uio_t * uiop)14407c478bd9Sstevel@tonic-gate pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop)
14417c478bd9Sstevel@tonic-gate {
14427c478bd9Sstevel@tonic-gate lwpsinfo_t lwpsinfo;
14437c478bd9Sstevel@tonic-gate proc_t *p;
14447c478bd9Sstevel@tonic-gate kthread_t *t;
14457c478bd9Sstevel@tonic-gate lwpent_t *lep;
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSINFO);
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate /*
14507c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
14517c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
14527c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
14537c478bd9Sstevel@tonic-gate */
14547c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
14557c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
14567c478bd9Sstevel@tonic-gate if (p == NULL)
14577c478bd9Sstevel@tonic-gate return (ENOENT);
14587c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
14597c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_tslot == -1) {
14607c478bd9Sstevel@tonic-gate prunlock(pnp);
14617c478bd9Sstevel@tonic-gate return (ENOENT);
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate
14647c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpsinfo)) {
14657c478bd9Sstevel@tonic-gate prunlock(pnp);
14667c478bd9Sstevel@tonic-gate return (0);
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate if ((t = pnp->pr_common->prc_thread) != NULL)
14707c478bd9Sstevel@tonic-gate prgetlwpsinfo(t, &lwpsinfo);
14717c478bd9Sstevel@tonic-gate else {
14727c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
14737c478bd9Sstevel@tonic-gate bzero(&lwpsinfo, sizeof (lwpsinfo));
14747c478bd9Sstevel@tonic-gate lwpsinfo.pr_lwpid = lep->le_lwpid;
14757c478bd9Sstevel@tonic-gate lwpsinfo.pr_state = SZOMB;
14767c478bd9Sstevel@tonic-gate lwpsinfo.pr_sname = 'Z';
14777c478bd9Sstevel@tonic-gate lwpsinfo.pr_start.tv_sec = lep->le_start;
14787c478bd9Sstevel@tonic-gate lwpsinfo.pr_bindpro = PBIND_NONE;
14797c478bd9Sstevel@tonic-gate lwpsinfo.pr_bindpset = PS_NONE;
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate prunlock(pnp);
14827c478bd9Sstevel@tonic-gate
14837c478bd9Sstevel@tonic-gate return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
14847c478bd9Sstevel@tonic-gate }
14857c478bd9Sstevel@tonic-gate
14867c478bd9Sstevel@tonic-gate static int
pr_read_lwpusage(prnode_t * pnp,uio_t * uiop)14877c478bd9Sstevel@tonic-gate pr_read_lwpusage(prnode_t *pnp, uio_t *uiop)
14887c478bd9Sstevel@tonic-gate {
14897c478bd9Sstevel@tonic-gate prhusage_t *pup;
14907c478bd9Sstevel@tonic-gate prusage_t *upup;
14917c478bd9Sstevel@tonic-gate proc_t *p;
14927c478bd9Sstevel@tonic-gate int error;
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPUSAGE);
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
14977c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
14987c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
14997c478bd9Sstevel@tonic-gate
15007c478bd9Sstevel@tonic-gate /*
15017c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
15027c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
15037c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
15047c478bd9Sstevel@tonic-gate */
15057c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
15067c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
15077c478bd9Sstevel@tonic-gate if (p == NULL) {
15087c478bd9Sstevel@tonic-gate error = ENOENT;
15097c478bd9Sstevel@tonic-gate goto out;
15107c478bd9Sstevel@tonic-gate }
15117c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
15127c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_thread == NULL) {
15137c478bd9Sstevel@tonic-gate prunlock(pnp);
15147c478bd9Sstevel@tonic-gate error = ENOENT;
15157c478bd9Sstevel@tonic-gate goto out;
15167c478bd9Sstevel@tonic-gate }
15177c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage_t)) {
15187c478bd9Sstevel@tonic-gate prunlock(pnp);
15197c478bd9Sstevel@tonic-gate error = 0;
15207c478bd9Sstevel@tonic-gate goto out;
15217c478bd9Sstevel@tonic-gate }
15227c478bd9Sstevel@tonic-gate
15237c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
15247c478bd9Sstevel@tonic-gate prgetusage(pnp->pr_common->prc_thread, pup);
15257c478bd9Sstevel@tonic-gate
15267c478bd9Sstevel@tonic-gate prunlock(pnp);
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage_t), uiop);
15317c478bd9Sstevel@tonic-gate out:
15327c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
15337c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
15347c478bd9Sstevel@tonic-gate return (error);
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate /* ARGSUSED */
15387c478bd9Sstevel@tonic-gate static int
pr_read_xregs(prnode_t * pnp,uio_t * uiop)15397c478bd9Sstevel@tonic-gate pr_read_xregs(prnode_t *pnp, uio_t *uiop)
15407c478bd9Sstevel@tonic-gate {
15417c478bd9Sstevel@tonic-gate #if defined(__sparc)
15427c478bd9Sstevel@tonic-gate proc_t *p;
15437c478bd9Sstevel@tonic-gate kthread_t *t;
15447c478bd9Sstevel@tonic-gate int error;
15457c478bd9Sstevel@tonic-gate char *xreg;
15467c478bd9Sstevel@tonic-gate size_t size;
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XREGS);
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate xreg = kmem_zalloc(sizeof (prxregset_t), KM_SLEEP);
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
15537c478bd9Sstevel@tonic-gate goto out;
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
15567c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate size = prhasx(p)? prgetprxregsize(p) : 0;
15597c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
15607c478bd9Sstevel@tonic-gate prunlock(pnp);
15617c478bd9Sstevel@tonic-gate goto out;
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate /* drop p->p_lock while (possibly) touching the stack */
15657c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
15667c478bd9Sstevel@tonic-gate prgetprxregs(ttolwp(t), xreg);
15677c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
15687c478bd9Sstevel@tonic-gate prunlock(pnp);
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate error = pr_uioread(xreg, size, uiop);
15717c478bd9Sstevel@tonic-gate out:
15727c478bd9Sstevel@tonic-gate kmem_free(xreg, sizeof (prxregset_t));
15737c478bd9Sstevel@tonic-gate return (error);
15747c478bd9Sstevel@tonic-gate #else
15757c478bd9Sstevel@tonic-gate return (0);
15767c478bd9Sstevel@tonic-gate #endif
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
1579f971a346SBryan Cantrill static int
pr_read_spymaster(prnode_t * pnp,uio_t * uiop)1580f971a346SBryan Cantrill pr_read_spymaster(prnode_t *pnp, uio_t *uiop)
1581f971a346SBryan Cantrill {
1582f971a346SBryan Cantrill psinfo_t psinfo;
1583f971a346SBryan Cantrill int error;
1584f971a346SBryan Cantrill klwp_t *lwp;
1585f971a346SBryan Cantrill
1586f971a346SBryan Cantrill ASSERT(pnp->pr_type == PR_SPYMASTER);
1587f971a346SBryan Cantrill
1588f971a346SBryan Cantrill if ((error = prlock(pnp, ZNO)) != 0)
1589f971a346SBryan Cantrill return (error);
1590f971a346SBryan Cantrill
1591f971a346SBryan Cantrill lwp = pnp->pr_common->prc_thread->t_lwp;
1592f971a346SBryan Cantrill
1593f971a346SBryan Cantrill if (lwp->lwp_spymaster == NULL) {
1594f971a346SBryan Cantrill prunlock(pnp);
1595f971a346SBryan Cantrill return (0);
1596f971a346SBryan Cantrill }
1597f971a346SBryan Cantrill
1598f971a346SBryan Cantrill bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1599f971a346SBryan Cantrill prunlock(pnp);
1600f971a346SBryan Cantrill
1601f971a346SBryan Cantrill return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1602f971a346SBryan Cantrill }
1603f971a346SBryan Cantrill
16047c478bd9Sstevel@tonic-gate #if defined(__sparc)
16057c478bd9Sstevel@tonic-gate
16067c478bd9Sstevel@tonic-gate static int
pr_read_gwindows(prnode_t * pnp,uio_t * uiop)16077c478bd9Sstevel@tonic-gate pr_read_gwindows(prnode_t *pnp, uio_t *uiop)
16087c478bd9Sstevel@tonic-gate {
16097c478bd9Sstevel@tonic-gate proc_t *p;
16107c478bd9Sstevel@tonic-gate kthread_t *t;
16117c478bd9Sstevel@tonic-gate gwindows_t *gwp;
16127c478bd9Sstevel@tonic-gate int error;
16137c478bd9Sstevel@tonic-gate size_t size;
16147c478bd9Sstevel@tonic-gate
16157c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_GWINDOWS);
16167c478bd9Sstevel@tonic-gate
16177c478bd9Sstevel@tonic-gate gwp = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP);
16187c478bd9Sstevel@tonic-gate
16197c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
16207c478bd9Sstevel@tonic-gate goto out;
16217c478bd9Sstevel@tonic-gate
16227c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
16237c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate /*
16267c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
16277c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
16287c478bd9Sstevel@tonic-gate * disappearing while we do this.
16297c478bd9Sstevel@tonic-gate */
16307c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
16317c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0)
16327c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) -
16337c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow);
16347c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
16357c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
16367c478bd9Sstevel@tonic-gate prunlock(pnp);
16377c478bd9Sstevel@tonic-gate goto out;
16387c478bd9Sstevel@tonic-gate }
16397c478bd9Sstevel@tonic-gate prgetwindows(ttolwp(t), gwp);
16407c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
16417c478bd9Sstevel@tonic-gate prunlock(pnp);
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate error = pr_uioread(gwp, size, uiop);
16447c478bd9Sstevel@tonic-gate out:
16457c478bd9Sstevel@tonic-gate kmem_free(gwp, sizeof (gwindows_t));
16467c478bd9Sstevel@tonic-gate return (error);
16477c478bd9Sstevel@tonic-gate }
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate /* ARGSUSED */
16507c478bd9Sstevel@tonic-gate static int
pr_read_asrs(prnode_t * pnp,uio_t * uiop)16517c478bd9Sstevel@tonic-gate pr_read_asrs(prnode_t *pnp, uio_t *uiop)
16527c478bd9Sstevel@tonic-gate {
16537c478bd9Sstevel@tonic-gate int error;
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_ASRS);
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
16587c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
16597c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
16607c478bd9Sstevel@tonic-gate kthread_t *t = pnp->pr_common->prc_thread;
16617c478bd9Sstevel@tonic-gate asrset_t asrset;
16627c478bd9Sstevel@tonic-gate
16637c478bd9Sstevel@tonic-gate if (p->p_model != DATAMODEL_LP64 ||
16647c478bd9Sstevel@tonic-gate uiop->uio_offset >= sizeof (asrset_t)) {
16657c478bd9Sstevel@tonic-gate prunlock(pnp);
16667c478bd9Sstevel@tonic-gate return (0);
16677c478bd9Sstevel@tonic-gate }
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate /*
16707c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
16717c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
16727c478bd9Sstevel@tonic-gate * disappearing while we do this.
16737c478bd9Sstevel@tonic-gate */
16747c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
16757c478bd9Sstevel@tonic-gate prgetasregs(ttolwp(t), asrset);
16767c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
16777c478bd9Sstevel@tonic-gate prunlock(pnp);
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate error = pr_uioread(&asrset[0], sizeof (asrset_t), uiop);
16807c478bd9Sstevel@tonic-gate }
16817c478bd9Sstevel@tonic-gate
16827c478bd9Sstevel@tonic-gate return (error);
16837c478bd9Sstevel@tonic-gate }
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate #endif /* __sparc */
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate static int
pr_read_piddir(prnode_t * pnp,uio_t * uiop)16887c478bd9Sstevel@tonic-gate pr_read_piddir(prnode_t *pnp, uio_t *uiop)
16897c478bd9Sstevel@tonic-gate {
16907c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
16917c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_pidfile != NULL);
16927c478bd9Sstevel@tonic-gate
16937c478bd9Sstevel@tonic-gate /* use the underlying PR_PIDFILE to read the process */
16947c478bd9Sstevel@tonic-gate pnp = VTOP(pnp->pr_pidfile);
16957c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate return (pr_read_pidfile(pnp, uiop));
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate
17007c478bd9Sstevel@tonic-gate static int
pr_read_pidfile(prnode_t * pnp,uio_t * uiop)17017c478bd9Sstevel@tonic-gate pr_read_pidfile(prnode_t *pnp, uio_t *uiop)
17027c478bd9Sstevel@tonic-gate {
17037c478bd9Sstevel@tonic-gate int error;
17047c478bd9Sstevel@tonic-gate
17057c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
17087c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
17097c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
17127c478bd9Sstevel@tonic-gate /*
17137c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
17147c478bd9Sstevel@tonic-gate */
17157c478bd9Sstevel@tonic-gate error = EIO; /* old /proc semantics */
17167c478bd9Sstevel@tonic-gate } else {
17177c478bd9Sstevel@tonic-gate /*
17187c478bd9Sstevel@tonic-gate * We drop p_lock because we don't want to hold
17197c478bd9Sstevel@tonic-gate * it over an I/O operation because that could
17207c478bd9Sstevel@tonic-gate * lead to deadlock with the clock thread.
17217c478bd9Sstevel@tonic-gate * The process will not disappear and its address
17227c478bd9Sstevel@tonic-gate * space will not change because it is marked P_PR_LOCK.
17237c478bd9Sstevel@tonic-gate */
17247c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
17257c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_READ, uiop, 1);
17267c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate prunlock(pnp);
17297c478bd9Sstevel@tonic-gate }
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate return (error);
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate
17347c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate /*
17377c478bd9Sstevel@tonic-gate * Array of ILP32 read functions, indexed by /proc file type.
17387c478bd9Sstevel@tonic-gate */
17397c478bd9Sstevel@tonic-gate static int pr_read_status_32(),
17407c478bd9Sstevel@tonic-gate pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
17417c478bd9Sstevel@tonic-gate pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
17427c478bd9Sstevel@tonic-gate pr_read_sigact_32(), pr_read_auxv_32(),
17437c478bd9Sstevel@tonic-gate pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
17447c478bd9Sstevel@tonic-gate pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1745f971a346SBryan Cantrill pr_read_lwpusage_32(), pr_read_spymaster_32(),
17467c478bd9Sstevel@tonic-gate #if defined(__sparc)
17477c478bd9Sstevel@tonic-gate pr_read_gwindows_32(),
17487c478bd9Sstevel@tonic-gate #endif
17497c478bd9Sstevel@tonic-gate pr_read_opagedata_32();
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate static int (*pr_read_function_32[PR_NFILES])() = {
17527c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc */
17537c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/self */
17547c478bd9Sstevel@tonic-gate pr_read_piddir, /* /proc/<pid> (old /proc read()) */
17557c478bd9Sstevel@tonic-gate pr_read_as, /* /proc/<pid>/as */
17567c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/ctl */
17577c478bd9Sstevel@tonic-gate pr_read_status_32, /* /proc/<pid>/status */
17587c478bd9Sstevel@tonic-gate pr_read_lstatus_32, /* /proc/<pid>/lstatus */
17597c478bd9Sstevel@tonic-gate pr_read_psinfo_32, /* /proc/<pid>/psinfo */
17607c478bd9Sstevel@tonic-gate pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
17617c478bd9Sstevel@tonic-gate pr_read_map_32, /* /proc/<pid>/map */
17627c478bd9Sstevel@tonic-gate pr_read_rmap_32, /* /proc/<pid>/rmap */
17637c478bd9Sstevel@tonic-gate pr_read_xmap_32, /* /proc/<pid>/xmap */
17647c478bd9Sstevel@tonic-gate pr_read_cred, /* /proc/<pid>/cred */
17657c478bd9Sstevel@tonic-gate pr_read_sigact_32, /* /proc/<pid>/sigact */
17667c478bd9Sstevel@tonic-gate pr_read_auxv_32, /* /proc/<pid>/auxv */
17677c478bd9Sstevel@tonic-gate #if defined(__x86)
17687c478bd9Sstevel@tonic-gate pr_read_ldt, /* /proc/<pid>/ldt */
17697c478bd9Sstevel@tonic-gate #endif
17707c478bd9Sstevel@tonic-gate pr_read_usage_32, /* /proc/<pid>/usage */
17717c478bd9Sstevel@tonic-gate pr_read_lusage_32, /* /proc/<pid>/lusage */
17727c478bd9Sstevel@tonic-gate pr_read_pagedata_32, /* /proc/<pid>/pagedata */
17737c478bd9Sstevel@tonic-gate pr_read_watch_32, /* /proc/<pid>/watch */
17747c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/cwd */
17757c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/root */
17767c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd */
17777c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd/nn */
17787c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object */
17797c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object/xxx */
17807c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp */
17817c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
17827c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
17837c478bd9Sstevel@tonic-gate pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
17847c478bd9Sstevel@tonic-gate pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
17857c478bd9Sstevel@tonic-gate pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
17867c478bd9Sstevel@tonic-gate pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
17877c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
17887c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1789f971a346SBryan Cantrill pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
17907c478bd9Sstevel@tonic-gate #if defined(__sparc)
17917c478bd9Sstevel@tonic-gate pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
17927c478bd9Sstevel@tonic-gate pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
17937c478bd9Sstevel@tonic-gate #endif
17947c478bd9Sstevel@tonic-gate pr_read_priv, /* /proc/<pid>/priv */
17957c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path */
17967c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path/xxx */
17977c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts */
17987c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
17997c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old process file */
18007c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old lwp file */
18017c478bd9Sstevel@tonic-gate pr_read_opagedata_32, /* old pagedata file */
18027c478bd9Sstevel@tonic-gate };
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate static int
pr_read_status_32(prnode_t * pnp,uio_t * uiop)18057c478bd9Sstevel@tonic-gate pr_read_status_32(prnode_t *pnp, uio_t *uiop)
18067c478bd9Sstevel@tonic-gate {
18077c478bd9Sstevel@tonic-gate pstatus32_t *sp;
18087c478bd9Sstevel@tonic-gate proc_t *p;
18097c478bd9Sstevel@tonic-gate int error;
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_STATUS);
18127c478bd9Sstevel@tonic-gate
18137c478bd9Sstevel@tonic-gate /*
18147c478bd9Sstevel@tonic-gate * We kmem_alloc() the pstatus structure because
18157c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
18167c478bd9Sstevel@tonic-gate */
18177c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
18187c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
18197c478bd9Sstevel@tonic-gate /*
18207c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
18217c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
18227c478bd9Sstevel@tonic-gate */
18237c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
18247c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
18257c478bd9Sstevel@tonic-gate prunlock(pnp);
18267c478bd9Sstevel@tonic-gate error = EOVERFLOW;
18277c478bd9Sstevel@tonic-gate } else {
18287c478bd9Sstevel@tonic-gate prgetstatus32(pnp->pr_common->prc_proc, sp,
1829fa9e4066Sahrens VTOZONE(PTOV(pnp)));
18307c478bd9Sstevel@tonic-gate prunlock(pnp);
18317c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate }
18347c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sp, sizeof (*sp));
18357c478bd9Sstevel@tonic-gate return (error);
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate
18387c478bd9Sstevel@tonic-gate static int
pr_read_lstatus_32(prnode_t * pnp,uio_t * uiop)18397c478bd9Sstevel@tonic-gate pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop)
18407c478bd9Sstevel@tonic-gate {
18417c478bd9Sstevel@tonic-gate proc_t *p;
18427c478bd9Sstevel@tonic-gate kthread_t *t;
18437c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
18447c478bd9Sstevel@tonic-gate size_t size;
18457c478bd9Sstevel@tonic-gate prheader32_t *php;
18467c478bd9Sstevel@tonic-gate lwpstatus32_t *sp;
18477c478bd9Sstevel@tonic-gate int error;
18487c478bd9Sstevel@tonic-gate int nlwp;
18497c478bd9Sstevel@tonic-gate int i;
18507c478bd9Sstevel@tonic-gate
18517c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LSTATUS);
18527c478bd9Sstevel@tonic-gate
18537c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
18547c478bd9Sstevel@tonic-gate return (error);
18557c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
18567c478bd9Sstevel@tonic-gate /*
18577c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
18587c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
18597c478bd9Sstevel@tonic-gate */
18607c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
18617c478bd9Sstevel@tonic-gate prunlock(pnp);
18627c478bd9Sstevel@tonic-gate return (EOVERFLOW);
18637c478bd9Sstevel@tonic-gate }
18647c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt;
18657c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
18667c478bd9Sstevel@tonic-gate
18677c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
18687c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
18697c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
18707c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
18717c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
18727c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
18757c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(lwpstatus32_t);
18767c478bd9Sstevel@tonic-gate
18777c478bd9Sstevel@tonic-gate sp = (lwpstatus32_t *)(php + 1);
18787c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
18797c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
18807c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
18817c478bd9Sstevel@tonic-gate continue;
1882fa9e4066Sahrens prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
18837c478bd9Sstevel@tonic-gate sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
18847c478bd9Sstevel@tonic-gate }
18857c478bd9Sstevel@tonic-gate prunlock(pnp);
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
18887c478bd9Sstevel@tonic-gate kmem_free(php, size);
18897c478bd9Sstevel@tonic-gate return (error);
18907c478bd9Sstevel@tonic-gate }
18917c478bd9Sstevel@tonic-gate
18927c478bd9Sstevel@tonic-gate static int
pr_read_psinfo_32(prnode_t * pnp,uio_t * uiop)18937c478bd9Sstevel@tonic-gate pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop)
18947c478bd9Sstevel@tonic-gate {
18957c478bd9Sstevel@tonic-gate psinfo32_t psinfo;
18967c478bd9Sstevel@tonic-gate proc_t *p;
18977c478bd9Sstevel@tonic-gate int error = 0;
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PSINFO);
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gate /*
19027c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
19037c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
19047c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
19057c478bd9Sstevel@tonic-gate */
19067c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
19077c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
19087c478bd9Sstevel@tonic-gate if (p == NULL)
19097c478bd9Sstevel@tonic-gate error = ENOENT;
19107c478bd9Sstevel@tonic-gate else {
19117c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
19127c478bd9Sstevel@tonic-gate prgetpsinfo32(p, &psinfo);
19137c478bd9Sstevel@tonic-gate prunlock(pnp);
19147c478bd9Sstevel@tonic-gate error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
19157c478bd9Sstevel@tonic-gate }
19167c478bd9Sstevel@tonic-gate return (error);
19177c478bd9Sstevel@tonic-gate }
19187c478bd9Sstevel@tonic-gate
19197c478bd9Sstevel@tonic-gate static int
pr_read_lpsinfo_32(prnode_t * pnp,uio_t * uiop)19207c478bd9Sstevel@tonic-gate pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop)
19217c478bd9Sstevel@tonic-gate {
19227c478bd9Sstevel@tonic-gate proc_t *p;
19237c478bd9Sstevel@tonic-gate kthread_t *t;
19247c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
19257c478bd9Sstevel@tonic-gate lwpent_t *lep;
19267c478bd9Sstevel@tonic-gate size_t size;
19277c478bd9Sstevel@tonic-gate prheader32_t *php;
19287c478bd9Sstevel@tonic-gate lwpsinfo32_t *sp;
19297c478bd9Sstevel@tonic-gate int error;
19307c478bd9Sstevel@tonic-gate int nlwp;
19317c478bd9Sstevel@tonic-gate int i;
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LPSINFO);
19347c478bd9Sstevel@tonic-gate
19357c478bd9Sstevel@tonic-gate /*
19367c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
19377c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
19387c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
19397c478bd9Sstevel@tonic-gate */
19407c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
19417c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
19427c478bd9Sstevel@tonic-gate if (p == NULL)
19437c478bd9Sstevel@tonic-gate return (ENOENT);
19447c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
19457c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
19467c478bd9Sstevel@tonic-gate prunlock(pnp);
19477c478bd9Sstevel@tonic-gate return (ENOENT);
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
19507c478bd9Sstevel@tonic-gate
19517c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
19527c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
19537c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
19547c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
19557c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
19567c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
19577c478bd9Sstevel@tonic-gate
19587c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
19597c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(lwpsinfo32_t);
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate sp = (lwpsinfo32_t *)(php + 1);
19627c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
19637c478bd9Sstevel@tonic-gate if ((lep = ldp->ld_entry) == NULL)
19647c478bd9Sstevel@tonic-gate continue;
19657c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) != NULL)
19667c478bd9Sstevel@tonic-gate prgetlwpsinfo32(t, sp);
19677c478bd9Sstevel@tonic-gate else {
19687c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp));
19697c478bd9Sstevel@tonic-gate sp->pr_lwpid = lep->le_lwpid;
19707c478bd9Sstevel@tonic-gate sp->pr_state = SZOMB;
19717c478bd9Sstevel@tonic-gate sp->pr_sname = 'Z';
19727c478bd9Sstevel@tonic-gate sp->pr_start.tv_sec = (time32_t)lep->le_start;
19737c478bd9Sstevel@tonic-gate }
19747c478bd9Sstevel@tonic-gate sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate prunlock(pnp);
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
19797c478bd9Sstevel@tonic-gate kmem_free(php, size);
19807c478bd9Sstevel@tonic-gate return (error);
19817c478bd9Sstevel@tonic-gate }
19827c478bd9Sstevel@tonic-gate
19837c478bd9Sstevel@tonic-gate static int
pr_read_map_common_32(prnode_t * pnp,uio_t * uiop,prnodetype_t type)1984870619e9Sfrankho pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
19857c478bd9Sstevel@tonic-gate {
19867c478bd9Sstevel@tonic-gate proc_t *p;
19877c478bd9Sstevel@tonic-gate struct as *as;
1988870619e9Sfrankho list_t iolhead;
19897c478bd9Sstevel@tonic-gate int error;
19907c478bd9Sstevel@tonic-gate
1991e24ad047SChristopher Baumbauer - Oracle America - San Diego United States readmap32_common:
19927c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
19937c478bd9Sstevel@tonic-gate return (error);
19947c478bd9Sstevel@tonic-gate
19957c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
19967c478bd9Sstevel@tonic-gate as = p->p_as;
19977c478bd9Sstevel@tonic-gate
19987c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
19997c478bd9Sstevel@tonic-gate prunlock(pnp);
20007c478bd9Sstevel@tonic-gate return (0);
20017c478bd9Sstevel@tonic-gate }
20027c478bd9Sstevel@tonic-gate
20037c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
20047c478bd9Sstevel@tonic-gate prunlock(pnp);
20057c478bd9Sstevel@tonic-gate return (EOVERFLOW);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate
2008*fd435bccSJosef 'Jeff' Sipek if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
2009e24ad047SChristopher Baumbauer - Oracle America - San Diego United States prunlock(pnp);
2010e24ad047SChristopher Baumbauer - Oracle America - San Diego United States delay(1);
2011e24ad047SChristopher Baumbauer - Oracle America - San Diego United States goto readmap32_common;
2012e24ad047SChristopher Baumbauer - Oracle America - San Diego United States }
20137c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
2014e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
2015870619e9Sfrankho switch (type) {
2016870619e9Sfrankho case PR_XMAP:
2017870619e9Sfrankho error = prgetxmap32(p, &iolhead);
2018870619e9Sfrankho break;
2019870619e9Sfrankho case PR_RMAP:
2020870619e9Sfrankho error = prgetmap32(p, 1, &iolhead);
2021870619e9Sfrankho break;
2022870619e9Sfrankho case PR_MAP:
2023870619e9Sfrankho error = prgetmap32(p, 0, &iolhead);
2024870619e9Sfrankho break;
2025870619e9Sfrankho }
2026*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
20277c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
20287c478bd9Sstevel@tonic-gate prunlock(pnp);
20297c478bd9Sstevel@tonic-gate
2030870619e9Sfrankho error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
2031870619e9Sfrankho
20327c478bd9Sstevel@tonic-gate return (error);
20337c478bd9Sstevel@tonic-gate }
20347c478bd9Sstevel@tonic-gate
20357c478bd9Sstevel@tonic-gate static int
pr_read_map_32(prnode_t * pnp,uio_t * uiop)20367c478bd9Sstevel@tonic-gate pr_read_map_32(prnode_t *pnp, uio_t *uiop)
20377c478bd9Sstevel@tonic-gate {
20387c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_MAP);
2039870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
20407c478bd9Sstevel@tonic-gate }
20417c478bd9Sstevel@tonic-gate
20427c478bd9Sstevel@tonic-gate static int
pr_read_rmap_32(prnode_t * pnp,uio_t * uiop)20437c478bd9Sstevel@tonic-gate pr_read_rmap_32(prnode_t *pnp, uio_t *uiop)
20447c478bd9Sstevel@tonic-gate {
20457c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_RMAP);
2046870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
20477c478bd9Sstevel@tonic-gate }
20487c478bd9Sstevel@tonic-gate
20497c478bd9Sstevel@tonic-gate static int
pr_read_xmap_32(prnode_t * pnp,uio_t * uiop)20507c478bd9Sstevel@tonic-gate pr_read_xmap_32(prnode_t *pnp, uio_t *uiop)
20517c478bd9Sstevel@tonic-gate {
20527c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XMAP);
2053870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
20547c478bd9Sstevel@tonic-gate }
20557c478bd9Sstevel@tonic-gate
20567c478bd9Sstevel@tonic-gate static int
pr_read_sigact_32(prnode_t * pnp,uio_t * uiop)20577c478bd9Sstevel@tonic-gate pr_read_sigact_32(prnode_t *pnp, uio_t *uiop)
20587c478bd9Sstevel@tonic-gate {
2059eb9dbf0cSRoger A. Faulkner int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
20607c478bd9Sstevel@tonic-gate proc_t *p;
20617c478bd9Sstevel@tonic-gate struct sigaction32 *sap;
20627c478bd9Sstevel@tonic-gate int sig;
20637c478bd9Sstevel@tonic-gate int error;
20647c478bd9Sstevel@tonic-gate user_t *up;
20657c478bd9Sstevel@tonic-gate
20667c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_SIGACT);
20677c478bd9Sstevel@tonic-gate
20687c478bd9Sstevel@tonic-gate /*
20697c478bd9Sstevel@tonic-gate * We kmem_alloc() the sigaction32 array because
20707c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
20717c478bd9Sstevel@tonic-gate */
2072eb9dbf0cSRoger A. Faulkner sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
20757c478bd9Sstevel@tonic-gate goto out;
20767c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
20777c478bd9Sstevel@tonic-gate
20787c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
20797c478bd9Sstevel@tonic-gate prunlock(pnp);
20807c478bd9Sstevel@tonic-gate error = EOVERFLOW;
20817c478bd9Sstevel@tonic-gate goto out;
20827c478bd9Sstevel@tonic-gate }
20837c478bd9Sstevel@tonic-gate
2084eb9dbf0cSRoger A. Faulkner if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
20857c478bd9Sstevel@tonic-gate prunlock(pnp);
20867c478bd9Sstevel@tonic-gate goto out;
20877c478bd9Sstevel@tonic-gate }
20887c478bd9Sstevel@tonic-gate
20897c478bd9Sstevel@tonic-gate up = PTOU(p);
2090eb9dbf0cSRoger A. Faulkner for (sig = 1; sig < nsig; sig++)
20917c478bd9Sstevel@tonic-gate prgetaction32(p, up, sig, &sap[sig-1]);
20927c478bd9Sstevel@tonic-gate prunlock(pnp);
20937c478bd9Sstevel@tonic-gate
2094eb9dbf0cSRoger A. Faulkner error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
20957c478bd9Sstevel@tonic-gate out:
2096eb9dbf0cSRoger A. Faulkner kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
20977c478bd9Sstevel@tonic-gate return (error);
20987c478bd9Sstevel@tonic-gate }
20997c478bd9Sstevel@tonic-gate
21007c478bd9Sstevel@tonic-gate static int
pr_read_auxv_32(prnode_t * pnp,uio_t * uiop)21017c478bd9Sstevel@tonic-gate pr_read_auxv_32(prnode_t *pnp, uio_t *uiop)
21027c478bd9Sstevel@tonic-gate {
21037c478bd9Sstevel@tonic-gate auxv32_t auxv[__KERN_NAUXV_IMPL];
21047c478bd9Sstevel@tonic-gate proc_t *p;
21057c478bd9Sstevel@tonic-gate user_t *up;
21067c478bd9Sstevel@tonic-gate int error;
21077c478bd9Sstevel@tonic-gate int i;
21087c478bd9Sstevel@tonic-gate
21097c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AUXV);
21107c478bd9Sstevel@tonic-gate
21117c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
21127c478bd9Sstevel@tonic-gate return (error);
21137c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
21167c478bd9Sstevel@tonic-gate prunlock(pnp);
21177c478bd9Sstevel@tonic-gate return (EOVERFLOW);
21187c478bd9Sstevel@tonic-gate }
21197c478bd9Sstevel@tonic-gate
21207c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (auxv)) {
21217c478bd9Sstevel@tonic-gate prunlock(pnp);
21227c478bd9Sstevel@tonic-gate return (0);
21237c478bd9Sstevel@tonic-gate }
21247c478bd9Sstevel@tonic-gate
21257c478bd9Sstevel@tonic-gate up = PTOU(p);
21267c478bd9Sstevel@tonic-gate for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
21277c478bd9Sstevel@tonic-gate auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
21287c478bd9Sstevel@tonic-gate auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
21297c478bd9Sstevel@tonic-gate }
21307c478bd9Sstevel@tonic-gate prunlock(pnp);
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate return (pr_uioread(auxv, sizeof (auxv), uiop));
21337c478bd9Sstevel@tonic-gate }
21347c478bd9Sstevel@tonic-gate
21357c478bd9Sstevel@tonic-gate static int
pr_read_usage_32(prnode_t * pnp,uio_t * uiop)21367c478bd9Sstevel@tonic-gate pr_read_usage_32(prnode_t *pnp, uio_t *uiop)
21377c478bd9Sstevel@tonic-gate {
21387c478bd9Sstevel@tonic-gate prhusage_t *pup;
21397c478bd9Sstevel@tonic-gate prusage32_t *upup;
21407c478bd9Sstevel@tonic-gate proc_t *p;
21417c478bd9Sstevel@tonic-gate kthread_t *t;
21427c478bd9Sstevel@tonic-gate int error;
21437c478bd9Sstevel@tonic-gate
21447c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_USAGE);
21457c478bd9Sstevel@tonic-gate
21467c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
21477c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
21487c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate /*
21517c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
21527c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
21537c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
21547c478bd9Sstevel@tonic-gate */
21557c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
21567c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
21577c478bd9Sstevel@tonic-gate if (p == NULL) {
21587c478bd9Sstevel@tonic-gate error = ENOENT;
21597c478bd9Sstevel@tonic-gate goto out;
21607c478bd9Sstevel@tonic-gate }
21617c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
21627c478bd9Sstevel@tonic-gate
21637c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage32_t)) {
21647c478bd9Sstevel@tonic-gate prunlock(pnp);
21657c478bd9Sstevel@tonic-gate error = 0;
21667c478bd9Sstevel@tonic-gate goto out;
21677c478bd9Sstevel@tonic-gate }
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
21727c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
21737c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
21747c478bd9Sstevel@tonic-gate
21757c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
21767c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
21777c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
21787c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
21797c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
21807c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
21817c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
21827c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
21837c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
21847c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
21857c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
21867c478bd9Sstevel@tonic-gate
21877c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
21887c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
21897c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
21907c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
21917c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
21927c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
21937c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
21947c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
21957c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
21967c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
21977c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
21987c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate /*
22017c478bd9Sstevel@tonic-gate * Add the usage information for each active lwp.
22027c478bd9Sstevel@tonic-gate */
22037c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
22047c478bd9Sstevel@tonic-gate !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
22057c478bd9Sstevel@tonic-gate do {
22067c478bd9Sstevel@tonic-gate if (t->t_proc_flag & TP_LWPEXIT)
22077c478bd9Sstevel@tonic-gate continue;
22087c478bd9Sstevel@tonic-gate pup->pr_count++;
22097c478bd9Sstevel@tonic-gate praddusage(t, pup);
22107c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
22117c478bd9Sstevel@tonic-gate }
22127c478bd9Sstevel@tonic-gate
22137c478bd9Sstevel@tonic-gate prunlock(pnp);
22147c478bd9Sstevel@tonic-gate
22157c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage32_t), uiop);
22187c478bd9Sstevel@tonic-gate out:
22197c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
22207c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
22217c478bd9Sstevel@tonic-gate return (error);
22227c478bd9Sstevel@tonic-gate }
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate static int
pr_read_lusage_32(prnode_t * pnp,uio_t * uiop)22257c478bd9Sstevel@tonic-gate pr_read_lusage_32(prnode_t *pnp, uio_t *uiop)
22267c478bd9Sstevel@tonic-gate {
22277c478bd9Sstevel@tonic-gate int nlwp;
22287c478bd9Sstevel@tonic-gate prhusage_t *pup;
22297c478bd9Sstevel@tonic-gate prheader32_t *php;
22307c478bd9Sstevel@tonic-gate prusage32_t *upup;
22317c478bd9Sstevel@tonic-gate size_t size;
22327c478bd9Sstevel@tonic-gate hrtime_t curtime;
22337c478bd9Sstevel@tonic-gate proc_t *p;
22347c478bd9Sstevel@tonic-gate kthread_t *t;
22357c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
22367c478bd9Sstevel@tonic-gate int error;
22377c478bd9Sstevel@tonic-gate int i;
22387c478bd9Sstevel@tonic-gate
22397c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LUSAGE);
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate /*
22427c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
22437c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
22447c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
22457c478bd9Sstevel@tonic-gate */
22467c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
22477c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
22487c478bd9Sstevel@tonic-gate if (p == NULL)
22497c478bd9Sstevel@tonic-gate return (ENOENT);
22507c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
22517c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt) == 0) {
22527c478bd9Sstevel@tonic-gate prunlock(pnp);
22537c478bd9Sstevel@tonic-gate return (ENOENT);
22547c478bd9Sstevel@tonic-gate }
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
22577c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
22587c478bd9Sstevel@tonic-gate prunlock(pnp);
22597c478bd9Sstevel@tonic-gate return (0);
22607c478bd9Sstevel@tonic-gate }
22617c478bd9Sstevel@tonic-gate
22627c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
22637c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
22647c478bd9Sstevel@tonic-gate pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
22657c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
22667c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
22677c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
22687c478bd9Sstevel@tonic-gate
22697c478bd9Sstevel@tonic-gate php = (prheader32_t *)(pup + 1);
22707c478bd9Sstevel@tonic-gate upup = (prusage32_t *)(php + 1);
22717c478bd9Sstevel@tonic-gate
22727c478bd9Sstevel@tonic-gate php->pr_nent = nlwp + 1;
22737c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(prusage32_t);
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate curtime = gethrtime();
22767c478bd9Sstevel@tonic-gate
22777c478bd9Sstevel@tonic-gate /*
22787c478bd9Sstevel@tonic-gate * First the summation over defunct lwps.
22797c478bd9Sstevel@tonic-gate */
22807c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
22817c478bd9Sstevel@tonic-gate pup->pr_tstamp = curtime;
22827c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
22837c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
22867c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
22877c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
22887c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
22897c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
22907c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
22917c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
22927c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
22937c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
22947c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
22957c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
22967c478bd9Sstevel@tonic-gate
22977c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
22987c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
22997c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
23007c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
23017c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
23027c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
23037c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
23047c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
23057c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
23067c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
23077c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
23087c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
23097c478bd9Sstevel@tonic-gate
23107c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
23117c478bd9Sstevel@tonic-gate
23127c478bd9Sstevel@tonic-gate /*
23137c478bd9Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
23147c478bd9Sstevel@tonic-gate */
23157c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
23167c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
23177c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
23187c478bd9Sstevel@tonic-gate continue;
23197c478bd9Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
23207c478bd9Sstevel@tonic-gate ASSERT(nlwp > 0);
23217c478bd9Sstevel@tonic-gate --nlwp;
23227c478bd9Sstevel@tonic-gate upup = (prusage32_t *)
23237c478bd9Sstevel@tonic-gate ((caddr_t)upup + LSPAN32(prusage32_t));
23247c478bd9Sstevel@tonic-gate prgetusage(t, pup);
23257c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
23267c478bd9Sstevel@tonic-gate }
23277c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0);
23287c478bd9Sstevel@tonic-gate
23297c478bd9Sstevel@tonic-gate prunlock(pnp);
23307c478bd9Sstevel@tonic-gate
23317c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
23327c478bd9Sstevel@tonic-gate kmem_free(pup, size + sizeof (prhusage_t));
23337c478bd9Sstevel@tonic-gate return (error);
23347c478bd9Sstevel@tonic-gate }
23357c478bd9Sstevel@tonic-gate
23367c478bd9Sstevel@tonic-gate static int
pr_read_pagedata_32(prnode_t * pnp,uio_t * uiop)23377c478bd9Sstevel@tonic-gate pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop)
23387c478bd9Sstevel@tonic-gate {
23397c478bd9Sstevel@tonic-gate proc_t *p;
23407c478bd9Sstevel@tonic-gate int error;
23417c478bd9Sstevel@tonic-gate
23427c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PAGEDATA);
23437c478bd9Sstevel@tonic-gate
23447c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
23457c478bd9Sstevel@tonic-gate return (error);
23467c478bd9Sstevel@tonic-gate
23477c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
23487c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
23497c478bd9Sstevel@tonic-gate prunlock(pnp);
23507c478bd9Sstevel@tonic-gate return (0);
23517c478bd9Sstevel@tonic-gate }
23527c478bd9Sstevel@tonic-gate
23537c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
23547c478bd9Sstevel@tonic-gate prunlock(pnp);
23557c478bd9Sstevel@tonic-gate return (EOVERFLOW);
23567c478bd9Sstevel@tonic-gate }
23577c478bd9Sstevel@tonic-gate
23587c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
23597c478bd9Sstevel@tonic-gate error = prpdread32(p, pnp->pr_hatid, uiop);
23607c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
23617c478bd9Sstevel@tonic-gate
23627c478bd9Sstevel@tonic-gate prunlock(pnp);
23637c478bd9Sstevel@tonic-gate return (error);
23647c478bd9Sstevel@tonic-gate }
23657c478bd9Sstevel@tonic-gate
23667c478bd9Sstevel@tonic-gate static int
pr_read_opagedata_32(prnode_t * pnp,uio_t * uiop)23677c478bd9Sstevel@tonic-gate pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop)
23687c478bd9Sstevel@tonic-gate {
23697c478bd9Sstevel@tonic-gate proc_t *p;
23707c478bd9Sstevel@tonic-gate struct as *as;
23717c478bd9Sstevel@tonic-gate int error;
23727c478bd9Sstevel@tonic-gate
23737c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OPAGEDATA);
23747c478bd9Sstevel@tonic-gate
23757c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
23767c478bd9Sstevel@tonic-gate return (error);
23777c478bd9Sstevel@tonic-gate
23787c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
23797c478bd9Sstevel@tonic-gate as = p->p_as;
23807c478bd9Sstevel@tonic-gate
23817c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
23827c478bd9Sstevel@tonic-gate prunlock(pnp);
23837c478bd9Sstevel@tonic-gate return (0);
23847c478bd9Sstevel@tonic-gate }
23857c478bd9Sstevel@tonic-gate
23867c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
23877c478bd9Sstevel@tonic-gate prunlock(pnp);
23887c478bd9Sstevel@tonic-gate return (EOVERFLOW);
23897c478bd9Sstevel@tonic-gate }
23907c478bd9Sstevel@tonic-gate
23917c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
23927c478bd9Sstevel@tonic-gate error = oprpdread32(as, pnp->pr_hatid, uiop);
23937c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate prunlock(pnp);
23967c478bd9Sstevel@tonic-gate return (error);
23977c478bd9Sstevel@tonic-gate }
23987c478bd9Sstevel@tonic-gate
23997c478bd9Sstevel@tonic-gate static int
pr_read_watch_32(prnode_t * pnp,uio_t * uiop)24007c478bd9Sstevel@tonic-gate pr_read_watch_32(prnode_t *pnp, uio_t *uiop)
24017c478bd9Sstevel@tonic-gate {
24027c478bd9Sstevel@tonic-gate proc_t *p;
24037c478bd9Sstevel@tonic-gate int error;
24047c478bd9Sstevel@tonic-gate prwatch32_t *Bpwp;
24057c478bd9Sstevel@tonic-gate size_t size;
24067c478bd9Sstevel@tonic-gate prwatch32_t *pwp;
24077c478bd9Sstevel@tonic-gate int nwarea;
24087c478bd9Sstevel@tonic-gate struct watched_area *pwarea;
24097c478bd9Sstevel@tonic-gate
24107c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_WATCH);
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
24137c478bd9Sstevel@tonic-gate return (error);
24147c478bd9Sstevel@tonic-gate
24157c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
24167c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
24177c478bd9Sstevel@tonic-gate prunlock(pnp);
24187c478bd9Sstevel@tonic-gate return (EOVERFLOW);
24197c478bd9Sstevel@tonic-gate }
24207c478bd9Sstevel@tonic-gate nwarea = avl_numnodes(&p->p_warea);
24217c478bd9Sstevel@tonic-gate size = nwarea * sizeof (prwatch32_t);
24227c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
24237c478bd9Sstevel@tonic-gate prunlock(pnp);
24247c478bd9Sstevel@tonic-gate return (0);
24257c478bd9Sstevel@tonic-gate }
24267c478bd9Sstevel@tonic-gate
24277c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
24287c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
24297c478bd9Sstevel@tonic-gate Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
24307c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
24317c478bd9Sstevel@tonic-gate /* p->p_nwarea can't change while process is locked */
24327c478bd9Sstevel@tonic-gate ASSERT(nwarea == avl_numnodes(&p->p_warea));
24337c478bd9Sstevel@tonic-gate
24347c478bd9Sstevel@tonic-gate /* gather the watched areas */
24357c478bd9Sstevel@tonic-gate for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
24367c478bd9Sstevel@tonic-gate pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
24377c478bd9Sstevel@tonic-gate pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
24387c478bd9Sstevel@tonic-gate pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
24397c478bd9Sstevel@tonic-gate pwp->pr_wflags = (int)pwarea->wa_flags;
24407c478bd9Sstevel@tonic-gate }
24417c478bd9Sstevel@tonic-gate
24427c478bd9Sstevel@tonic-gate prunlock(pnp);
24437c478bd9Sstevel@tonic-gate
24447c478bd9Sstevel@tonic-gate error = pr_uioread(Bpwp, size, uiop);
24457c478bd9Sstevel@tonic-gate kmem_free(Bpwp, size);
24467c478bd9Sstevel@tonic-gate return (error);
24477c478bd9Sstevel@tonic-gate }
24487c478bd9Sstevel@tonic-gate
24497c478bd9Sstevel@tonic-gate static int
pr_read_lwpstatus_32(prnode_t * pnp,uio_t * uiop)24507c478bd9Sstevel@tonic-gate pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop)
24517c478bd9Sstevel@tonic-gate {
24527c478bd9Sstevel@tonic-gate lwpstatus32_t *sp;
24537c478bd9Sstevel@tonic-gate proc_t *p;
24547c478bd9Sstevel@tonic-gate int error;
24557c478bd9Sstevel@tonic-gate
24567c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSTATUS);
24577c478bd9Sstevel@tonic-gate
24587c478bd9Sstevel@tonic-gate /*
24597c478bd9Sstevel@tonic-gate * We kmem_alloc() the lwpstatus structure because
24607c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
24617c478bd9Sstevel@tonic-gate */
24627c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
24657c478bd9Sstevel@tonic-gate goto out;
24667c478bd9Sstevel@tonic-gate
24677c478bd9Sstevel@tonic-gate /*
24687c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
24697c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
24707c478bd9Sstevel@tonic-gate */
24717c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
24727c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
24737c478bd9Sstevel@tonic-gate prunlock(pnp);
24747c478bd9Sstevel@tonic-gate error = EOVERFLOW;
24757c478bd9Sstevel@tonic-gate goto out;
24767c478bd9Sstevel@tonic-gate }
24777c478bd9Sstevel@tonic-gate
24787c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (*sp)) {
24797c478bd9Sstevel@tonic-gate prunlock(pnp);
24807c478bd9Sstevel@tonic-gate goto out;
24817c478bd9Sstevel@tonic-gate }
24827c478bd9Sstevel@tonic-gate
2483fa9e4066Sahrens prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
24847c478bd9Sstevel@tonic-gate prunlock(pnp);
24857c478bd9Sstevel@tonic-gate
24867c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
24877c478bd9Sstevel@tonic-gate out:
24887c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
24897c478bd9Sstevel@tonic-gate return (error);
24907c478bd9Sstevel@tonic-gate }
24917c478bd9Sstevel@tonic-gate
24927c478bd9Sstevel@tonic-gate static int
pr_read_lwpsinfo_32(prnode_t * pnp,uio_t * uiop)24937c478bd9Sstevel@tonic-gate pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop)
24947c478bd9Sstevel@tonic-gate {
24957c478bd9Sstevel@tonic-gate lwpsinfo32_t lwpsinfo;
24967c478bd9Sstevel@tonic-gate proc_t *p;
24977c478bd9Sstevel@tonic-gate kthread_t *t;
24987c478bd9Sstevel@tonic-gate lwpent_t *lep;
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSINFO);
25017c478bd9Sstevel@tonic-gate
25027c478bd9Sstevel@tonic-gate /*
25037c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
25047c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
25057c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
25067c478bd9Sstevel@tonic-gate */
25077c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
25087c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
25097c478bd9Sstevel@tonic-gate if (p == NULL)
25107c478bd9Sstevel@tonic-gate return (ENOENT);
25117c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
25127c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_tslot == -1) {
25137c478bd9Sstevel@tonic-gate prunlock(pnp);
25147c478bd9Sstevel@tonic-gate return (ENOENT);
25157c478bd9Sstevel@tonic-gate }
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpsinfo)) {
25187c478bd9Sstevel@tonic-gate prunlock(pnp);
25197c478bd9Sstevel@tonic-gate return (0);
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate
25227c478bd9Sstevel@tonic-gate if ((t = pnp->pr_common->prc_thread) != NULL)
25237c478bd9Sstevel@tonic-gate prgetlwpsinfo32(t, &lwpsinfo);
25247c478bd9Sstevel@tonic-gate else {
25257c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
25267c478bd9Sstevel@tonic-gate bzero(&lwpsinfo, sizeof (lwpsinfo));
25277c478bd9Sstevel@tonic-gate lwpsinfo.pr_lwpid = lep->le_lwpid;
25287c478bd9Sstevel@tonic-gate lwpsinfo.pr_state = SZOMB;
25297c478bd9Sstevel@tonic-gate lwpsinfo.pr_sname = 'Z';
25307c478bd9Sstevel@tonic-gate lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
25317c478bd9Sstevel@tonic-gate }
25327c478bd9Sstevel@tonic-gate prunlock(pnp);
25337c478bd9Sstevel@tonic-gate
25347c478bd9Sstevel@tonic-gate return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
25357c478bd9Sstevel@tonic-gate }
25367c478bd9Sstevel@tonic-gate
25377c478bd9Sstevel@tonic-gate static int
pr_read_lwpusage_32(prnode_t * pnp,uio_t * uiop)25387c478bd9Sstevel@tonic-gate pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop)
25397c478bd9Sstevel@tonic-gate {
25407c478bd9Sstevel@tonic-gate prhusage_t *pup;
25417c478bd9Sstevel@tonic-gate prusage32_t *upup;
25427c478bd9Sstevel@tonic-gate proc_t *p;
25437c478bd9Sstevel@tonic-gate int error;
25447c478bd9Sstevel@tonic-gate
25457c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPUSAGE);
25467c478bd9Sstevel@tonic-gate
25477c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
25487c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
25497c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
25507c478bd9Sstevel@tonic-gate
25517c478bd9Sstevel@tonic-gate /*
25527c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
25537c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
25547c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
25557c478bd9Sstevel@tonic-gate */
25567c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
25577c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
25587c478bd9Sstevel@tonic-gate if (p == NULL) {
25597c478bd9Sstevel@tonic-gate error = ENOENT;
25607c478bd9Sstevel@tonic-gate goto out;
25617c478bd9Sstevel@tonic-gate }
25627c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
25637c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_thread == NULL) {
25647c478bd9Sstevel@tonic-gate prunlock(pnp);
25657c478bd9Sstevel@tonic-gate error = ENOENT;
25667c478bd9Sstevel@tonic-gate goto out;
25677c478bd9Sstevel@tonic-gate }
25687c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage32_t)) {
25697c478bd9Sstevel@tonic-gate prunlock(pnp);
25707c478bd9Sstevel@tonic-gate error = 0;
25717c478bd9Sstevel@tonic-gate goto out;
25727c478bd9Sstevel@tonic-gate }
25737c478bd9Sstevel@tonic-gate
25747c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
25757c478bd9Sstevel@tonic-gate prgetusage(pnp->pr_common->prc_thread, pup);
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate prunlock(pnp);
25787c478bd9Sstevel@tonic-gate
25797c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
25807c478bd9Sstevel@tonic-gate
25817c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage32_t), uiop);
25827c478bd9Sstevel@tonic-gate out:
25837c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
25847c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
25857c478bd9Sstevel@tonic-gate return (error);
25867c478bd9Sstevel@tonic-gate }
25877c478bd9Sstevel@tonic-gate
2588f971a346SBryan Cantrill static int
pr_read_spymaster_32(prnode_t * pnp,uio_t * uiop)2589f971a346SBryan Cantrill pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop)
2590f971a346SBryan Cantrill {
2591f971a346SBryan Cantrill psinfo32_t psinfo;
2592f971a346SBryan Cantrill int error;
2593f971a346SBryan Cantrill klwp_t *lwp;
2594f971a346SBryan Cantrill
2595f971a346SBryan Cantrill ASSERT(pnp->pr_type == PR_SPYMASTER);
2596f971a346SBryan Cantrill
2597f971a346SBryan Cantrill if ((error = prlock(pnp, ZNO)) != 0)
2598f971a346SBryan Cantrill return (error);
2599f971a346SBryan Cantrill
2600f971a346SBryan Cantrill lwp = pnp->pr_common->prc_thread->t_lwp;
2601f971a346SBryan Cantrill
2602f971a346SBryan Cantrill if (lwp->lwp_spymaster == NULL) {
2603f971a346SBryan Cantrill prunlock(pnp);
2604f971a346SBryan Cantrill return (0);
2605f971a346SBryan Cantrill }
2606f971a346SBryan Cantrill
2607f971a346SBryan Cantrill psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2608f971a346SBryan Cantrill prunlock(pnp);
2609f971a346SBryan Cantrill
2610f971a346SBryan Cantrill return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2611f971a346SBryan Cantrill }
2612f971a346SBryan Cantrill
26137c478bd9Sstevel@tonic-gate #if defined(__sparc)
26147c478bd9Sstevel@tonic-gate static int
pr_read_gwindows_32(prnode_t * pnp,uio_t * uiop)26157c478bd9Sstevel@tonic-gate pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop)
26167c478bd9Sstevel@tonic-gate {
26177c478bd9Sstevel@tonic-gate proc_t *p;
26187c478bd9Sstevel@tonic-gate kthread_t *t;
26197c478bd9Sstevel@tonic-gate gwindows32_t *gwp;
26207c478bd9Sstevel@tonic-gate int error;
26217c478bd9Sstevel@tonic-gate size_t size;
26227c478bd9Sstevel@tonic-gate
26237c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_GWINDOWS);
26247c478bd9Sstevel@tonic-gate
26257c478bd9Sstevel@tonic-gate gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
26267c478bd9Sstevel@tonic-gate
26277c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
26287c478bd9Sstevel@tonic-gate goto out;
26297c478bd9Sstevel@tonic-gate
26307c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
26317c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
26327c478bd9Sstevel@tonic-gate
26337c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
26347c478bd9Sstevel@tonic-gate prunlock(pnp);
26357c478bd9Sstevel@tonic-gate error = EOVERFLOW;
26367c478bd9Sstevel@tonic-gate goto out;
26377c478bd9Sstevel@tonic-gate }
26387c478bd9Sstevel@tonic-gate
26397c478bd9Sstevel@tonic-gate /*
26407c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
26417c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
26427c478bd9Sstevel@tonic-gate * disappearing while we do this.
26437c478bd9Sstevel@tonic-gate */
26447c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
26457c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0)
26467c478bd9Sstevel@tonic-gate size = sizeof (gwindows32_t) -
26477c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
26487c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
26497c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
26507c478bd9Sstevel@tonic-gate prunlock(pnp);
26517c478bd9Sstevel@tonic-gate goto out;
26527c478bd9Sstevel@tonic-gate }
26537c478bd9Sstevel@tonic-gate prgetwindows32(ttolwp(t), gwp);
26547c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
26557c478bd9Sstevel@tonic-gate prunlock(pnp);
26567c478bd9Sstevel@tonic-gate
26577c478bd9Sstevel@tonic-gate error = pr_uioread(gwp, size, uiop);
26587c478bd9Sstevel@tonic-gate out:
26597c478bd9Sstevel@tonic-gate kmem_free(gwp, sizeof (gwindows32_t));
26607c478bd9Sstevel@tonic-gate return (error);
26617c478bd9Sstevel@tonic-gate }
26627c478bd9Sstevel@tonic-gate #endif /* __sparc */
26637c478bd9Sstevel@tonic-gate
26647c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
26657c478bd9Sstevel@tonic-gate
26667c478bd9Sstevel@tonic-gate /* ARGSUSED */
26677c478bd9Sstevel@tonic-gate static int
prread(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)26687c478bd9Sstevel@tonic-gate prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
26697c478bd9Sstevel@tonic-gate {
26707c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
26717c478bd9Sstevel@tonic-gate
26727c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
26737c478bd9Sstevel@tonic-gate
26747c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
26757c478bd9Sstevel@tonic-gate /*
26767c478bd9Sstevel@tonic-gate * What is read from the /proc files depends on the data
26777c478bd9Sstevel@tonic-gate * model of the caller. An LP64 process will see LP64
26787c478bd9Sstevel@tonic-gate * data. An ILP32 process will see ILP32 data.
26797c478bd9Sstevel@tonic-gate */
26807c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_LP64)
26817c478bd9Sstevel@tonic-gate return (pr_read_function[pnp->pr_type](pnp, uiop));
26827c478bd9Sstevel@tonic-gate else
26837c478bd9Sstevel@tonic-gate return (pr_read_function_32[pnp->pr_type](pnp, uiop));
26847c478bd9Sstevel@tonic-gate #else
26857c478bd9Sstevel@tonic-gate return (pr_read_function[pnp->pr_type](pnp, uiop));
26867c478bd9Sstevel@tonic-gate #endif
26877c478bd9Sstevel@tonic-gate }
26887c478bd9Sstevel@tonic-gate
26897c478bd9Sstevel@tonic-gate /* ARGSUSED */
26907c478bd9Sstevel@tonic-gate static int
prwrite(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)26917c478bd9Sstevel@tonic-gate prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
26927c478bd9Sstevel@tonic-gate {
26937c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
26947c478bd9Sstevel@tonic-gate int old = 0;
26957c478bd9Sstevel@tonic-gate int error;
26967c478bd9Sstevel@tonic-gate ssize_t resid;
26977c478bd9Sstevel@tonic-gate
26987c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
26997c478bd9Sstevel@tonic-gate
27007c478bd9Sstevel@tonic-gate /*
27017c478bd9Sstevel@tonic-gate * Only a handful of /proc files are writable, enumerate them here.
27027c478bd9Sstevel@tonic-gate */
27037c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
27047c478bd9Sstevel@tonic-gate case PR_PIDDIR: /* directory write()s: visceral revulsion. */
27057c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_pidfile != NULL);
27067c478bd9Sstevel@tonic-gate /* use the underlying PR_PIDFILE to write the process */
27077c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
27087c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
27097c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
27107c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
27117c478bd9Sstevel@tonic-gate case PR_PIDFILE:
27127c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
27137c478bd9Sstevel@tonic-gate old = 1;
27147c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
27157c478bd9Sstevel@tonic-gate case PR_AS:
27167c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
27177c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
27187c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
27197c478bd9Sstevel@tonic-gate
27207c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
27217c478bd9Sstevel@tonic-gate /*
27227c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
27237c478bd9Sstevel@tonic-gate */
27247c478bd9Sstevel@tonic-gate error = EIO;
27257c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
27267c478bd9Sstevel@tonic-gate } else if (curproc->p_model == DATAMODEL_ILP32 &&
27277c478bd9Sstevel@tonic-gate PROCESS_NOT_32BIT(p)) {
27287c478bd9Sstevel@tonic-gate error = EOVERFLOW;
27297c478bd9Sstevel@tonic-gate #endif
27307c478bd9Sstevel@tonic-gate } else {
27317c478bd9Sstevel@tonic-gate /*
27327c478bd9Sstevel@tonic-gate * See comments above (pr_read_pidfile)
27337c478bd9Sstevel@tonic-gate * about this locking dance.
27347c478bd9Sstevel@tonic-gate */
27357c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
27367c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_WRITE, uiop, old);
27377c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
27387c478bd9Sstevel@tonic-gate }
27397c478bd9Sstevel@tonic-gate prunlock(pnp);
27407c478bd9Sstevel@tonic-gate }
27417c478bd9Sstevel@tonic-gate return (error);
27427c478bd9Sstevel@tonic-gate
27437c478bd9Sstevel@tonic-gate case PR_CTL:
27447c478bd9Sstevel@tonic-gate case PR_LWPCTL:
27457c478bd9Sstevel@tonic-gate resid = uiop->uio_resid;
27467c478bd9Sstevel@tonic-gate /*
27477c478bd9Sstevel@tonic-gate * Perform the action on the control file
27487c478bd9Sstevel@tonic-gate * by passing curthreads credentials
27497c478bd9Sstevel@tonic-gate * and not target process's credentials.
27507c478bd9Sstevel@tonic-gate */
27517c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
27527c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_ILP32)
27537c478bd9Sstevel@tonic-gate error = prwritectl32(vp, uiop, CRED());
27547c478bd9Sstevel@tonic-gate else
27557c478bd9Sstevel@tonic-gate error = prwritectl(vp, uiop, CRED());
27567c478bd9Sstevel@tonic-gate #else
27577c478bd9Sstevel@tonic-gate error = prwritectl(vp, uiop, CRED());
27587c478bd9Sstevel@tonic-gate #endif
27597c478bd9Sstevel@tonic-gate /*
27607c478bd9Sstevel@tonic-gate * This hack makes sure that the EINTR is passed
27617c478bd9Sstevel@tonic-gate * all the way back to the caller's write() call.
27627c478bd9Sstevel@tonic-gate */
27637c478bd9Sstevel@tonic-gate if (error == EINTR)
27647c478bd9Sstevel@tonic-gate uiop->uio_resid = resid;
27657c478bd9Sstevel@tonic-gate return (error);
27667c478bd9Sstevel@tonic-gate
27677c478bd9Sstevel@tonic-gate default:
27687c478bd9Sstevel@tonic-gate return ((vp->v_type == VDIR)? EISDIR : EBADF);
27697c478bd9Sstevel@tonic-gate }
27707c478bd9Sstevel@tonic-gate /* NOTREACHED */
27717c478bd9Sstevel@tonic-gate }
27727c478bd9Sstevel@tonic-gate
27737c478bd9Sstevel@tonic-gate static int
prgetattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)2774da6c28aaSamw prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2775da6c28aaSamw caller_context_t *ct)
27767c478bd9Sstevel@tonic-gate {
27777c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
27787c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
27797c478bd9Sstevel@tonic-gate prcommon_t *pcp;
27807c478bd9Sstevel@tonic-gate proc_t *p;
27817c478bd9Sstevel@tonic-gate struct as *as;
27827c478bd9Sstevel@tonic-gate int error;
27837c478bd9Sstevel@tonic-gate vnode_t *rvp;
27847c478bd9Sstevel@tonic-gate timestruc_t now;
27857c478bd9Sstevel@tonic-gate extern uint_t nproc;
27867c478bd9Sstevel@tonic-gate int ngroups;
2787eb9dbf0cSRoger A. Faulkner int nsig;
27887c478bd9Sstevel@tonic-gate
27897c478bd9Sstevel@tonic-gate /*
27907c478bd9Sstevel@tonic-gate * This ugly bit of code allows us to keep both versions of this
27917c478bd9Sstevel@tonic-gate * function from the same source.
27927c478bd9Sstevel@tonic-gate */
27937c478bd9Sstevel@tonic-gate #ifdef _LP64
27947c478bd9Sstevel@tonic-gate int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
27957c478bd9Sstevel@tonic-gate #define PR_OBJSIZE(obj32, obj64) \
27967c478bd9Sstevel@tonic-gate (iam32bit ? sizeof (obj32) : sizeof (obj64))
27977c478bd9Sstevel@tonic-gate #define PR_OBJSPAN(obj32, obj64) \
27987c478bd9Sstevel@tonic-gate (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
27997c478bd9Sstevel@tonic-gate #else
28007c478bd9Sstevel@tonic-gate #define PR_OBJSIZE(obj32, obj64) \
28017c478bd9Sstevel@tonic-gate (sizeof (obj64))
28027c478bd9Sstevel@tonic-gate #define PR_OBJSPAN(obj32, obj64) \
28037c478bd9Sstevel@tonic-gate (LSPAN(obj64))
28047c478bd9Sstevel@tonic-gate #endif
28057c478bd9Sstevel@tonic-gate
28067c478bd9Sstevel@tonic-gate /*
28077c478bd9Sstevel@tonic-gate * Return all the attributes. Should be refined
28087c478bd9Sstevel@tonic-gate * so that it returns only those asked for.
28097c478bd9Sstevel@tonic-gate * Most of this is complete fakery anyway.
28107c478bd9Sstevel@tonic-gate */
28117c478bd9Sstevel@tonic-gate
28127c478bd9Sstevel@tonic-gate /*
28137c478bd9Sstevel@tonic-gate * For files in the /proc/<pid>/object directory,
28147c478bd9Sstevel@tonic-gate * return the attributes of the underlying object.
28157c478bd9Sstevel@tonic-gate * For files in the /proc/<pid>/fd directory,
28167c478bd9Sstevel@tonic-gate * return the attributes of the underlying file, but
28177c478bd9Sstevel@tonic-gate * make it look inaccessible if it is not a regular file.
28187c478bd9Sstevel@tonic-gate * Make directories look like symlinks.
28197c478bd9Sstevel@tonic-gate */
28207c478bd9Sstevel@tonic-gate switch (type) {
28217c478bd9Sstevel@tonic-gate case PR_CURDIR:
28227c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
28237c478bd9Sstevel@tonic-gate if (!(flags & ATTR_REAL))
28247c478bd9Sstevel@tonic-gate break;
28257c478bd9Sstevel@tonic-gate /* restrict full knowledge of the attributes to owner or root */
2826da6c28aaSamw if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
28277c478bd9Sstevel@tonic-gate return (error);
28287c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
28297c478bd9Sstevel@tonic-gate case PR_OBJECT:
28307c478bd9Sstevel@tonic-gate case PR_FD:
28317c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
2832da6c28aaSamw error = VOP_GETATTR(rvp, vap, flags, cr, ct);
28337c478bd9Sstevel@tonic-gate if (error)
28347c478bd9Sstevel@tonic-gate return (error);
28357c478bd9Sstevel@tonic-gate if (type == PR_FD) {
28367c478bd9Sstevel@tonic-gate if (rvp->v_type != VREG && rvp->v_type != VDIR)
28377c478bd9Sstevel@tonic-gate vap->va_mode = 0;
28387c478bd9Sstevel@tonic-gate else
28397c478bd9Sstevel@tonic-gate vap->va_mode &= pnp->pr_mode;
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate if (type == PR_OBJECT)
28427c478bd9Sstevel@tonic-gate vap->va_mode &= 07555;
28437c478bd9Sstevel@tonic-gate if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
28447c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
28457c478bd9Sstevel@tonic-gate vap->va_size = 0;
28467c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
28477c478bd9Sstevel@tonic-gate }
28487c478bd9Sstevel@tonic-gate return (0);
28497c478bd9Sstevel@tonic-gate default:
28507c478bd9Sstevel@tonic-gate break;
28517c478bd9Sstevel@tonic-gate }
28527c478bd9Sstevel@tonic-gate
28537c478bd9Sstevel@tonic-gate bzero(vap, sizeof (*vap));
28547c478bd9Sstevel@tonic-gate /*
28557c478bd9Sstevel@tonic-gate * Large Files: Internally proc now uses VPROC to indicate
28567c478bd9Sstevel@tonic-gate * a proc file. Since we have been returning VREG through
28577c478bd9Sstevel@tonic-gate * VOP_GETATTR() until now, we continue to do this so as
28587c478bd9Sstevel@tonic-gate * not to break apps depending on this return value.
28597c478bd9Sstevel@tonic-gate */
28607c478bd9Sstevel@tonic-gate vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
28617c478bd9Sstevel@tonic-gate vap->va_mode = pnp->pr_mode;
28627c478bd9Sstevel@tonic-gate vap->va_fsid = vp->v_vfsp->vfs_dev;
28637c478bd9Sstevel@tonic-gate vap->va_blksize = DEV_BSIZE;
28647c478bd9Sstevel@tonic-gate vap->va_rdev = 0;
28657c478bd9Sstevel@tonic-gate vap->va_seq = 0;
28667c478bd9Sstevel@tonic-gate
28677c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR) {
28687c478bd9Sstevel@tonic-gate vap->va_uid = 0;
28697c478bd9Sstevel@tonic-gate vap->va_gid = 0;
28707c478bd9Sstevel@tonic-gate vap->va_nlink = nproc + 2;
28717c478bd9Sstevel@tonic-gate vap->va_nodeid = (ino64_t)PRROOTINO;
28727c478bd9Sstevel@tonic-gate gethrestime(&now);
28737c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_mtime = vap->va_ctime = now;
28747c478bd9Sstevel@tonic-gate vap->va_size = (v.v_proc + 2) * PRSDSIZE;
28757c478bd9Sstevel@tonic-gate vap->va_nblocks = btod(vap->va_size);
28767c478bd9Sstevel@tonic-gate return (0);
28777c478bd9Sstevel@tonic-gate }
28787c478bd9Sstevel@tonic-gate
28797c478bd9Sstevel@tonic-gate /*
28807c478bd9Sstevel@tonic-gate * /proc/<pid>/self is a symbolic link, and has no prcommon member
28817c478bd9Sstevel@tonic-gate */
28827c478bd9Sstevel@tonic-gate if (type == PR_SELF) {
28837c478bd9Sstevel@tonic-gate vap->va_uid = crgetruid(CRED());
28847c478bd9Sstevel@tonic-gate vap->va_gid = crgetrgid(CRED());
28857c478bd9Sstevel@tonic-gate vap->va_nodeid = (ino64_t)PR_SELF;
28867c478bd9Sstevel@tonic-gate gethrestime(&now);
28877c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_mtime = vap->va_ctime = now;
28887c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
28897c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
28907c478bd9Sstevel@tonic-gate vap->va_size = 0;
28917c478bd9Sstevel@tonic-gate return (0);
28927c478bd9Sstevel@tonic-gate }
28937c478bd9Sstevel@tonic-gate
28947c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
28957c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
28967c478bd9Sstevel@tonic-gate if (p == NULL)
28977c478bd9Sstevel@tonic-gate return (ENOENT);
28987c478bd9Sstevel@tonic-gate pcp = pnp->pr_common;
28997c478bd9Sstevel@tonic-gate
29007c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
29017c478bd9Sstevel@tonic-gate vap->va_uid = crgetruid(p->p_cred);
29027c478bd9Sstevel@tonic-gate vap->va_gid = crgetrgid(p->p_cred);
29037c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
29047c478bd9Sstevel@tonic-gate
29057c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
29067c478bd9Sstevel@tonic-gate vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
29077c478bd9Sstevel@tonic-gate pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
29087c478bd9Sstevel@tonic-gate if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
29097c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
29107c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec =
29117c478bd9Sstevel@tonic-gate p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
29127c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
29137c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = 0;
29147c478bd9Sstevel@tonic-gate } else {
29157c478bd9Sstevel@tonic-gate user_t *up = PTOU(p);
29167c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
29177c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec = up->u_start.tv_sec;
29187c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
29197c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
29207c478bd9Sstevel@tonic-gate }
29217c478bd9Sstevel@tonic-gate
29227c478bd9Sstevel@tonic-gate switch (type) {
29237c478bd9Sstevel@tonic-gate case PR_PIDDIR:
29247c478bd9Sstevel@tonic-gate /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
29257c478bd9Sstevel@tonic-gate vap->va_nlink = 5;
29267c478bd9Sstevel@tonic-gate vap->va_size = sizeof (piddir);
29277c478bd9Sstevel@tonic-gate break;
29287c478bd9Sstevel@tonic-gate case PR_OBJECTDIR:
29297c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
29307c478bd9Sstevel@tonic-gate vap->va_size = 2 * PRSDSIZE;
29317c478bd9Sstevel@tonic-gate else {
29327c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
2933*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
29347c478bd9Sstevel@tonic-gate if (as->a_updatedir)
29357c478bd9Sstevel@tonic-gate rebuild_objdir(as);
29367c478bd9Sstevel@tonic-gate vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
2937*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
29387c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
29397c478bd9Sstevel@tonic-gate }
29407c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29417c478bd9Sstevel@tonic-gate break;
29427c478bd9Sstevel@tonic-gate case PR_PATHDIR:
29437c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
29447c478bd9Sstevel@tonic-gate vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
29457c478bd9Sstevel@tonic-gate else {
29467c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
2947*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
29487c478bd9Sstevel@tonic-gate if (as->a_updatedir)
29497c478bd9Sstevel@tonic-gate rebuild_objdir(as);
29507c478bd9Sstevel@tonic-gate vap->va_size = (as->a_sizedir + 4 +
29517c478bd9Sstevel@tonic-gate P_FINFO(p)->fi_nfiles) * PRSDSIZE;
2952*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
29537c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
29547c478bd9Sstevel@tonic-gate }
29557c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29567c478bd9Sstevel@tonic-gate break;
29577c478bd9Sstevel@tonic-gate case PR_PATH:
29587c478bd9Sstevel@tonic-gate case PR_CURDIR:
29597c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
29607c478bd9Sstevel@tonic-gate case PR_CT:
29617c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
29627c478bd9Sstevel@tonic-gate vap->va_size = 0;
29637c478bd9Sstevel@tonic-gate break;
29647c478bd9Sstevel@tonic-gate case PR_FDDIR:
29657c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29667c478bd9Sstevel@tonic-gate vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
29677c478bd9Sstevel@tonic-gate break;
29687c478bd9Sstevel@tonic-gate case PR_LWPDIR:
29697c478bd9Sstevel@tonic-gate /*
29707c478bd9Sstevel@tonic-gate * va_nlink: count each lwp as a directory link.
29717c478bd9Sstevel@tonic-gate * va_size: size of p_lwpdir + 2
29727c478bd9Sstevel@tonic-gate */
29737c478bd9Sstevel@tonic-gate vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
29747c478bd9Sstevel@tonic-gate vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
29757c478bd9Sstevel@tonic-gate break;
29767c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
29777c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29787c478bd9Sstevel@tonic-gate vap->va_size = sizeof (lwpiddir);
29797c478bd9Sstevel@tonic-gate break;
29807c478bd9Sstevel@tonic-gate case PR_CTDIR:
29817c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29827c478bd9Sstevel@tonic-gate vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
29837c478bd9Sstevel@tonic-gate break;
29847c478bd9Sstevel@tonic-gate case PR_TMPLDIR:
29857c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
29867c478bd9Sstevel@tonic-gate vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
29877c478bd9Sstevel@tonic-gate break;
29887c478bd9Sstevel@tonic-gate case PR_AS:
29897c478bd9Sstevel@tonic-gate case PR_PIDFILE:
29907c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
29917c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
29927c478bd9Sstevel@tonic-gate vap->va_size = 0;
299340688216SSudheer A else
299440688216SSudheer A vap->va_size = as->a_resvsize;
29957c478bd9Sstevel@tonic-gate break;
29967c478bd9Sstevel@tonic-gate case PR_STATUS:
29977c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
29987c478bd9Sstevel@tonic-gate break;
29997c478bd9Sstevel@tonic-gate case PR_LSTATUS:
30007c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
30017c478bd9Sstevel@tonic-gate p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
30027c478bd9Sstevel@tonic-gate break;
30037c478bd9Sstevel@tonic-gate case PR_PSINFO:
30047c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
30057c478bd9Sstevel@tonic-gate break;
30067c478bd9Sstevel@tonic-gate case PR_LPSINFO:
30077c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
30087c478bd9Sstevel@tonic-gate (p->p_lwpcnt + p->p_zombcnt) *
30097c478bd9Sstevel@tonic-gate PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
30107c478bd9Sstevel@tonic-gate break;
30117c478bd9Sstevel@tonic-gate case PR_MAP:
30127c478bd9Sstevel@tonic-gate case PR_RMAP:
30137c478bd9Sstevel@tonic-gate case PR_XMAP:
30147c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
30157c478bd9Sstevel@tonic-gate vap->va_size = 0;
30167c478bd9Sstevel@tonic-gate else {
30177c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3018*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
30197c478bd9Sstevel@tonic-gate if (type == PR_MAP)
30207c478bd9Sstevel@tonic-gate vap->va_mtime = as->a_updatetime;
30217c478bd9Sstevel@tonic-gate if (type == PR_XMAP)
30227c478bd9Sstevel@tonic-gate vap->va_size = prnsegs(as, 0) *
30237c478bd9Sstevel@tonic-gate PR_OBJSIZE(prxmap32_t, prxmap_t);
30247c478bd9Sstevel@tonic-gate else
30257c478bd9Sstevel@tonic-gate vap->va_size = prnsegs(as, type == PR_RMAP) *
30267c478bd9Sstevel@tonic-gate PR_OBJSIZE(prmap32_t, prmap_t);
3027*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
30287c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
30297c478bd9Sstevel@tonic-gate }
30307c478bd9Sstevel@tonic-gate break;
30317c478bd9Sstevel@tonic-gate case PR_CRED:
30327c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
30337c478bd9Sstevel@tonic-gate vap->va_size = sizeof (prcred_t);
30347c478bd9Sstevel@tonic-gate ngroups = crgetngroups(p->p_cred);
30357c478bd9Sstevel@tonic-gate if (ngroups > 1)
30367c478bd9Sstevel@tonic-gate vap->va_size += (ngroups - 1) * sizeof (gid_t);
30377c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
30387c478bd9Sstevel@tonic-gate break;
30397c478bd9Sstevel@tonic-gate case PR_PRIV:
30407c478bd9Sstevel@tonic-gate vap->va_size = prgetprivsize();
30417c478bd9Sstevel@tonic-gate break;
30427c478bd9Sstevel@tonic-gate case PR_SIGACT:
3043eb9dbf0cSRoger A. Faulkner nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3044eb9dbf0cSRoger A. Faulkner vap->va_size = (nsig-1) *
30457c478bd9Sstevel@tonic-gate PR_OBJSIZE(struct sigaction32, struct sigaction);
30467c478bd9Sstevel@tonic-gate break;
30477c478bd9Sstevel@tonic-gate case PR_AUXV:
30487c478bd9Sstevel@tonic-gate vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
30497c478bd9Sstevel@tonic-gate break;
30507c478bd9Sstevel@tonic-gate #if defined(__x86)
30517c478bd9Sstevel@tonic-gate case PR_LDT:
30526e092be7SVamsi Nagineni mutex_exit(&p->p_lock);
30537c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
30547c478bd9Sstevel@tonic-gate vap->va_size = prnldt(p) * sizeof (struct ssd);
30557c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
30566e092be7SVamsi Nagineni mutex_enter(&p->p_lock);
30577c478bd9Sstevel@tonic-gate break;
30587c478bd9Sstevel@tonic-gate #endif
30597c478bd9Sstevel@tonic-gate case PR_USAGE:
30607c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
30617c478bd9Sstevel@tonic-gate break;
30627c478bd9Sstevel@tonic-gate case PR_LUSAGE:
30637c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
30647c478bd9Sstevel@tonic-gate (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
30657c478bd9Sstevel@tonic-gate break;
30667c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
30677c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
30687c478bd9Sstevel@tonic-gate vap->va_size = 0;
30697c478bd9Sstevel@tonic-gate else {
30707c478bd9Sstevel@tonic-gate /*
30717c478bd9Sstevel@tonic-gate * We can drop p->p_lock before grabbing the
30727c478bd9Sstevel@tonic-gate * address space lock because p->p_as will not
30737c478bd9Sstevel@tonic-gate * change while the process is marked P_PR_LOCK.
30747c478bd9Sstevel@tonic-gate */
30757c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3076*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
30777c478bd9Sstevel@tonic-gate #ifdef _LP64
30787c478bd9Sstevel@tonic-gate vap->va_size = iam32bit?
30797c478bd9Sstevel@tonic-gate prpdsize32(as) : prpdsize(as);
30807c478bd9Sstevel@tonic-gate #else
30817c478bd9Sstevel@tonic-gate vap->va_size = prpdsize(as);
30827c478bd9Sstevel@tonic-gate #endif
3083*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
30847c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
30857c478bd9Sstevel@tonic-gate }
30867c478bd9Sstevel@tonic-gate break;
30877c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
30887c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
30897c478bd9Sstevel@tonic-gate vap->va_size = 0;
30907c478bd9Sstevel@tonic-gate else {
30917c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3092*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
30937c478bd9Sstevel@tonic-gate #ifdef _LP64
30947c478bd9Sstevel@tonic-gate vap->va_size = iam32bit?
30957c478bd9Sstevel@tonic-gate oprpdsize32(as) : oprpdsize(as);
30967c478bd9Sstevel@tonic-gate #else
30977c478bd9Sstevel@tonic-gate vap->va_size = oprpdsize(as);
30987c478bd9Sstevel@tonic-gate #endif
3099*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
31007c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
31017c478bd9Sstevel@tonic-gate }
31027c478bd9Sstevel@tonic-gate break;
31037c478bd9Sstevel@tonic-gate case PR_WATCH:
31047c478bd9Sstevel@tonic-gate vap->va_size = avl_numnodes(&p->p_warea) *
31057c478bd9Sstevel@tonic-gate PR_OBJSIZE(prwatch32_t, prwatch_t);
31067c478bd9Sstevel@tonic-gate break;
31077c478bd9Sstevel@tonic-gate case PR_LWPSTATUS:
31087c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
31097c478bd9Sstevel@tonic-gate break;
31107c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
31117c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
31127c478bd9Sstevel@tonic-gate break;
31137c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
31147c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
31157c478bd9Sstevel@tonic-gate break;
31167c478bd9Sstevel@tonic-gate case PR_XREGS:
31177c478bd9Sstevel@tonic-gate if (prhasx(p))
31187c478bd9Sstevel@tonic-gate vap->va_size = prgetprxregsize(p);
31197c478bd9Sstevel@tonic-gate else
31207c478bd9Sstevel@tonic-gate vap->va_size = 0;
31217c478bd9Sstevel@tonic-gate break;
3122f971a346SBryan Cantrill case PR_SPYMASTER:
3123f971a346SBryan Cantrill if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3124f971a346SBryan Cantrill vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3125f971a346SBryan Cantrill } else {
3126f971a346SBryan Cantrill vap->va_size = 0;
3127f971a346SBryan Cantrill }
3128f971a346SBryan Cantrill break;
31297c478bd9Sstevel@tonic-gate #if defined(__sparc)
31307c478bd9Sstevel@tonic-gate case PR_GWINDOWS:
31317c478bd9Sstevel@tonic-gate {
31327c478bd9Sstevel@tonic-gate kthread_t *t;
31337c478bd9Sstevel@tonic-gate int n;
31347c478bd9Sstevel@tonic-gate
31357c478bd9Sstevel@tonic-gate /*
31367c478bd9Sstevel@tonic-gate * If there is no lwp then just make the size zero.
31377c478bd9Sstevel@tonic-gate * This can happen if the lwp exits between the VOP_LOOKUP()
31387c478bd9Sstevel@tonic-gate * of the /proc/<pid>/lwp/<lwpid>/gwindows file and the
31397c478bd9Sstevel@tonic-gate * VOP_GETATTR() of the resulting vnode.
31407c478bd9Sstevel@tonic-gate */
31417c478bd9Sstevel@tonic-gate if ((t = pcp->prc_thread) == NULL) {
31427c478bd9Sstevel@tonic-gate vap->va_size = 0;
31437c478bd9Sstevel@tonic-gate break;
31447c478bd9Sstevel@tonic-gate }
31457c478bd9Sstevel@tonic-gate /*
31467c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
31477c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
31487c478bd9Sstevel@tonic-gate * disappearing while we do this.
31497c478bd9Sstevel@tonic-gate */
31507c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
31517c478bd9Sstevel@tonic-gate if ((n = prnwindows(ttolwp(t))) == 0)
31527c478bd9Sstevel@tonic-gate vap->va_size = 0;
31537c478bd9Sstevel@tonic-gate else
31547c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
31557c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - n) *
31567c478bd9Sstevel@tonic-gate PR_OBJSIZE(struct rwindow32, struct rwindow);
31577c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
31587c478bd9Sstevel@tonic-gate break;
31597c478bd9Sstevel@tonic-gate }
31607c478bd9Sstevel@tonic-gate case PR_ASRS:
31617c478bd9Sstevel@tonic-gate #ifdef _LP64
31627c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_LP64)
31637c478bd9Sstevel@tonic-gate vap->va_size = sizeof (asrset_t);
31647c478bd9Sstevel@tonic-gate else
31657c478bd9Sstevel@tonic-gate #endif
31667c478bd9Sstevel@tonic-gate vap->va_size = 0;
31677c478bd9Sstevel@tonic-gate break;
31687c478bd9Sstevel@tonic-gate #endif
31697c478bd9Sstevel@tonic-gate case PR_CTL:
31707c478bd9Sstevel@tonic-gate case PR_LWPCTL:
31717c478bd9Sstevel@tonic-gate default:
31727c478bd9Sstevel@tonic-gate vap->va_size = 0;
31737c478bd9Sstevel@tonic-gate break;
31747c478bd9Sstevel@tonic-gate }
31757c478bd9Sstevel@tonic-gate
31767c478bd9Sstevel@tonic-gate prunlock(pnp);
31777c478bd9Sstevel@tonic-gate vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
31787c478bd9Sstevel@tonic-gate return (0);
31797c478bd9Sstevel@tonic-gate }
31807c478bd9Sstevel@tonic-gate
31817c478bd9Sstevel@tonic-gate static int
praccess(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)3182da6c28aaSamw praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
31837c478bd9Sstevel@tonic-gate {
31847c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
31857c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
31867c478bd9Sstevel@tonic-gate int vmode;
31877c478bd9Sstevel@tonic-gate vtype_t vtype;
31887c478bd9Sstevel@tonic-gate proc_t *p;
31897c478bd9Sstevel@tonic-gate int error = 0;
31907c478bd9Sstevel@tonic-gate vnode_t *rvp;
31917c478bd9Sstevel@tonic-gate vnode_t *xvp;
31927c478bd9Sstevel@tonic-gate
31937c478bd9Sstevel@tonic-gate if ((mode & VWRITE) && vn_is_readonly(vp))
31947c478bd9Sstevel@tonic-gate return (EROFS);
31957c478bd9Sstevel@tonic-gate
31967c478bd9Sstevel@tonic-gate switch (type) {
31977c478bd9Sstevel@tonic-gate case PR_PROCDIR:
31987c478bd9Sstevel@tonic-gate break;
31997c478bd9Sstevel@tonic-gate
32007c478bd9Sstevel@tonic-gate case PR_OBJECT:
32017c478bd9Sstevel@tonic-gate case PR_FD:
32027c478bd9Sstevel@tonic-gate /*
32037c478bd9Sstevel@tonic-gate * Disallow write access to the underlying objects.
32047c478bd9Sstevel@tonic-gate * Disallow access to underlying non-regular-file fds.
32057c478bd9Sstevel@tonic-gate * Disallow access to fds with other than existing open modes.
32067c478bd9Sstevel@tonic-gate */
32077c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
32087c478bd9Sstevel@tonic-gate vtype = rvp->v_type;
32097c478bd9Sstevel@tonic-gate vmode = pnp->pr_mode;
32107c478bd9Sstevel@tonic-gate if ((type == PR_OBJECT && (mode & VWRITE)) ||
32117c478bd9Sstevel@tonic-gate (type == PR_FD && vtype != VREG && vtype != VDIR) ||
32127c478bd9Sstevel@tonic-gate (type == PR_FD && (vmode & mode) != mode &&
32137c478bd9Sstevel@tonic-gate secpolicy_proc_access(cr) != 0))
32147c478bd9Sstevel@tonic-gate return (EACCES);
3215da6c28aaSamw return (VOP_ACCESS(rvp, mode, flags, cr, ct));
32167c478bd9Sstevel@tonic-gate
32177c478bd9Sstevel@tonic-gate case PR_PSINFO: /* these files can be read by anyone */
32187c478bd9Sstevel@tonic-gate case PR_LPSINFO:
32197c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
32207c478bd9Sstevel@tonic-gate case PR_LWPDIR:
32217c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
32227c478bd9Sstevel@tonic-gate case PR_USAGE:
32237c478bd9Sstevel@tonic-gate case PR_LUSAGE:
32247c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
32257c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
32267c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
32277c478bd9Sstevel@tonic-gate if (p == NULL)
32287c478bd9Sstevel@tonic-gate return (ENOENT);
32297c478bd9Sstevel@tonic-gate prunlock(pnp);
32307c478bd9Sstevel@tonic-gate break;
32317c478bd9Sstevel@tonic-gate
32327c478bd9Sstevel@tonic-gate default:
32337c478bd9Sstevel@tonic-gate /*
32347c478bd9Sstevel@tonic-gate * Except for the world-readable files above,
32357c478bd9Sstevel@tonic-gate * only /proc/pid exists if the process is a zombie.
32367c478bd9Sstevel@tonic-gate */
32377c478bd9Sstevel@tonic-gate if ((error = prlock(pnp,
32387c478bd9Sstevel@tonic-gate (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
32397c478bd9Sstevel@tonic-gate return (error);
32407c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
32417c478bd9Sstevel@tonic-gate if (p != curproc)
32427c478bd9Sstevel@tonic-gate error = priv_proc_cred_perm(cr, p, NULL, mode);
32437c478bd9Sstevel@tonic-gate
32447c478bd9Sstevel@tonic-gate if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3245ddf7fe95Scasper p->p_as == &kas || (xvp = p->p_exec) == NULL) {
32467c478bd9Sstevel@tonic-gate prunlock(pnp);
32477c478bd9Sstevel@tonic-gate } else {
32487c478bd9Sstevel@tonic-gate /*
32497c478bd9Sstevel@tonic-gate * Determine if the process's executable is readable.
3250ddf7fe95Scasper * We have to drop p->p_lock before the secpolicy
3251ddf7fe95Scasper * and VOP operation.
32527c478bd9Sstevel@tonic-gate */
32537c478bd9Sstevel@tonic-gate VN_HOLD(xvp);
32547c478bd9Sstevel@tonic-gate prunlock(pnp);
3255ddf7fe95Scasper if (secpolicy_proc_access(cr) != 0)
3256da6c28aaSamw error = VOP_ACCESS(xvp, VREAD, 0, cr, ct);
32577c478bd9Sstevel@tonic-gate VN_RELE(xvp);
32587c478bd9Sstevel@tonic-gate }
32597c478bd9Sstevel@tonic-gate if (error)
32607c478bd9Sstevel@tonic-gate return (error);
32617c478bd9Sstevel@tonic-gate break;
32627c478bd9Sstevel@tonic-gate }
32637c478bd9Sstevel@tonic-gate
32647c478bd9Sstevel@tonic-gate if (type == PR_CURDIR || type == PR_ROOTDIR) {
32657c478bd9Sstevel@tonic-gate /*
32667c478bd9Sstevel@tonic-gate * Final access check on the underlying directory vnode.
32677c478bd9Sstevel@tonic-gate */
3268da6c28aaSamw return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
32697c478bd9Sstevel@tonic-gate }
32707c478bd9Sstevel@tonic-gate
32717c478bd9Sstevel@tonic-gate /*
32727c478bd9Sstevel@tonic-gate * Visceral revulsion: For compatibility with old /proc,
32737c478bd9Sstevel@tonic-gate * allow the /proc/<pid> directory to be opened for writing.
32747c478bd9Sstevel@tonic-gate */
32757c478bd9Sstevel@tonic-gate vmode = pnp->pr_mode;
32767c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR)
32777c478bd9Sstevel@tonic-gate vmode |= VWRITE;
32787c478bd9Sstevel@tonic-gate if ((vmode & mode) != mode)
32797c478bd9Sstevel@tonic-gate error = secpolicy_proc_access(cr);
32807c478bd9Sstevel@tonic-gate return (error);
32817c478bd9Sstevel@tonic-gate }
32827c478bd9Sstevel@tonic-gate
32837c478bd9Sstevel@tonic-gate /*
32847c478bd9Sstevel@tonic-gate * Array of lookup functions, indexed by /proc file type.
32857c478bd9Sstevel@tonic-gate */
32867c478bd9Sstevel@tonic-gate static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
32877c478bd9Sstevel@tonic-gate *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
32887c478bd9Sstevel@tonic-gate *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
32897c478bd9Sstevel@tonic-gate *pr_lookup_ctdir();
32907c478bd9Sstevel@tonic-gate
32917c478bd9Sstevel@tonic-gate static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
32927c478bd9Sstevel@tonic-gate pr_lookup_procdir, /* /proc */
32937c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/self */
32947c478bd9Sstevel@tonic-gate pr_lookup_piddir, /* /proc/<pid> */
32957c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/as */
32967c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/ctl */
32977c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/status */
32987c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lstatus */
32997c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/psinfo */
33007c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
33017c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/map */
33027c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/rmap */
33037c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/xmap */
33047c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/cred */
33057c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/sigact */
33067c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/auxv */
33077c478bd9Sstevel@tonic-gate #if defined(__x86)
33087c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/ldt */
33097c478bd9Sstevel@tonic-gate #endif
33107c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/usage */
33117c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lusage */
33127c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/pagedata */
33137c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/watch */
33147c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/cwd */
33157c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/root */
33167c478bd9Sstevel@tonic-gate pr_lookup_fddir, /* /proc/<pid>/fd */
33177c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/fd/nn */
33187c478bd9Sstevel@tonic-gate pr_lookup_objectdir, /* /proc/<pid>/object */
33197c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/object/xxx */
33207c478bd9Sstevel@tonic-gate pr_lookup_lwpdir, /* /proc/<pid>/lwp */
33217c478bd9Sstevel@tonic-gate pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
33227c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
33237c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
33247c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
33257c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
33267c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
33277c478bd9Sstevel@tonic-gate pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
33287c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3329f971a346SBryan Cantrill pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
33307c478bd9Sstevel@tonic-gate #if defined(__sparc)
33317c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
33327c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
33337c478bd9Sstevel@tonic-gate #endif
33347c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/priv */
33357c478bd9Sstevel@tonic-gate pr_lookup_pathdir, /* /proc/<pid>/path */
33367c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/path/xxx */
33377c478bd9Sstevel@tonic-gate pr_lookup_ctdir, /* /proc/<pid>/contracts */
33387c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/contracts/<ctid> */
33397c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old process file */
33407c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old lwp file */
33417c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old pagedata file */
33427c478bd9Sstevel@tonic-gate };
33437c478bd9Sstevel@tonic-gate
33447c478bd9Sstevel@tonic-gate static int
prlookup(vnode_t * dp,char * comp,vnode_t ** vpp,pathname_t * pathp,int flags,vnode_t * rdir,cred_t * cr,caller_context_t * ct,int * direntflags,pathname_t * realpnp)33457c478bd9Sstevel@tonic-gate prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3346da6c28aaSamw int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3347da6c28aaSamw int *direntflags, pathname_t *realpnp)
33487c478bd9Sstevel@tonic-gate {
33497c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(dp);
33507c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
33517c478bd9Sstevel@tonic-gate int error;
33527c478bd9Sstevel@tonic-gate
33537c478bd9Sstevel@tonic-gate ASSERT(dp->v_type == VDIR);
33547c478bd9Sstevel@tonic-gate ASSERT(type < PR_NFILES);
33557c478bd9Sstevel@tonic-gate
33567c478bd9Sstevel@tonic-gate if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
33577c478bd9Sstevel@tonic-gate VN_HOLD(pnp->pr_parent);
33587c478bd9Sstevel@tonic-gate *vpp = pnp->pr_parent;
33597c478bd9Sstevel@tonic-gate return (0);
33607c478bd9Sstevel@tonic-gate }
33617c478bd9Sstevel@tonic-gate
33627c478bd9Sstevel@tonic-gate if (*comp == '\0' ||
33637c478bd9Sstevel@tonic-gate strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
33647c478bd9Sstevel@tonic-gate VN_HOLD(dp);
33657c478bd9Sstevel@tonic-gate *vpp = dp;
33667c478bd9Sstevel@tonic-gate return (0);
33677c478bd9Sstevel@tonic-gate }
33687c478bd9Sstevel@tonic-gate
33697c478bd9Sstevel@tonic-gate switch (type) {
33707c478bd9Sstevel@tonic-gate case PR_CURDIR:
33717c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
33727c478bd9Sstevel@tonic-gate /* restrict lookup permission to owner or root */
3373da6c28aaSamw if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
33747c478bd9Sstevel@tonic-gate return (error);
33757c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
33767c478bd9Sstevel@tonic-gate case PR_FD:
33777c478bd9Sstevel@tonic-gate dp = pnp->pr_realvp;
3378da6c28aaSamw return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3379da6c28aaSamw direntflags, realpnp));
33807c478bd9Sstevel@tonic-gate default:
33817c478bd9Sstevel@tonic-gate break;
33827c478bd9Sstevel@tonic-gate }
33837c478bd9Sstevel@tonic-gate
33847c478bd9Sstevel@tonic-gate if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
3385da6c28aaSamw (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
33867c478bd9Sstevel@tonic-gate return (error);
33877c478bd9Sstevel@tonic-gate
3388da6c28aaSamw /* XXX - Do we need to pass ct, direntflags, or realpnp? */
33897c478bd9Sstevel@tonic-gate *vpp = (pr_lookup_function[type](dp, comp));
33907c478bd9Sstevel@tonic-gate
33917c478bd9Sstevel@tonic-gate return ((*vpp == NULL) ? ENOENT : 0);
33927c478bd9Sstevel@tonic-gate }
33937c478bd9Sstevel@tonic-gate
33947c478bd9Sstevel@tonic-gate /* ARGSUSED */
33957c478bd9Sstevel@tonic-gate static int
prcreate(vnode_t * dp,char * comp,vattr_t * vap,vcexcl_t excl,int mode,vnode_t ** vpp,cred_t * cr,int flag,caller_context_t * ct,vsecattr_t * vsecp)33967c478bd9Sstevel@tonic-gate prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3397da6c28aaSamw int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3398da6c28aaSamw vsecattr_t *vsecp)
33997c478bd9Sstevel@tonic-gate {
34007c478bd9Sstevel@tonic-gate int error;
34017c478bd9Sstevel@tonic-gate
3402da6c28aaSamw if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3403da6c28aaSamw ct, NULL, NULL)) != 0) {
34047c478bd9Sstevel@tonic-gate if (error == ENOENT) /* can't O_CREAT nonexistent files */
34057c478bd9Sstevel@tonic-gate error = EACCES; /* unwriteable directories */
34067c478bd9Sstevel@tonic-gate } else {
34077c478bd9Sstevel@tonic-gate if (excl == EXCL) /* O_EXCL */
34087c478bd9Sstevel@tonic-gate error = EEXIST;
34097c478bd9Sstevel@tonic-gate else if (vap->va_mask & AT_SIZE) { /* O_TRUNC */
34107c478bd9Sstevel@tonic-gate vnode_t *vp = *vpp;
34117c478bd9Sstevel@tonic-gate uint_t mask;
34127c478bd9Sstevel@tonic-gate
34137c478bd9Sstevel@tonic-gate if (vp->v_type == VDIR)
34147c478bd9Sstevel@tonic-gate error = EISDIR;
34157c478bd9Sstevel@tonic-gate else if (vp->v_type != VPROC ||
34167c478bd9Sstevel@tonic-gate VTOP(vp)->pr_type != PR_FD)
34177c478bd9Sstevel@tonic-gate error = EACCES;
34187c478bd9Sstevel@tonic-gate else { /* /proc/<pid>/fd/<n> */
34197c478bd9Sstevel@tonic-gate vp = VTOP(vp)->pr_realvp;
34207c478bd9Sstevel@tonic-gate mask = vap->va_mask;
34217c478bd9Sstevel@tonic-gate vap->va_mask = AT_SIZE;
3422da6c28aaSamw error = VOP_SETATTR(vp, vap, 0, cr, ct);
34237c478bd9Sstevel@tonic-gate vap->va_mask = mask;
34247c478bd9Sstevel@tonic-gate }
34257c478bd9Sstevel@tonic-gate }
34267c478bd9Sstevel@tonic-gate if (error) {
34277c478bd9Sstevel@tonic-gate VN_RELE(*vpp);
34287c478bd9Sstevel@tonic-gate *vpp = NULL;
34297c478bd9Sstevel@tonic-gate }
34307c478bd9Sstevel@tonic-gate }
34317c478bd9Sstevel@tonic-gate return (error);
34327c478bd9Sstevel@tonic-gate }
34337c478bd9Sstevel@tonic-gate
34347c478bd9Sstevel@tonic-gate /* ARGSUSED */
34357c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_notdir(vnode_t * dp,char * comp)34367c478bd9Sstevel@tonic-gate pr_lookup_notdir(vnode_t *dp, char *comp)
34377c478bd9Sstevel@tonic-gate {
34387c478bd9Sstevel@tonic-gate return (NULL);
34397c478bd9Sstevel@tonic-gate }
34407c478bd9Sstevel@tonic-gate
34417c478bd9Sstevel@tonic-gate /*
34427c478bd9Sstevel@tonic-gate * Find or construct a process vnode for the given pid.
34437c478bd9Sstevel@tonic-gate */
34447c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_procdir(vnode_t * dp,char * comp)34457c478bd9Sstevel@tonic-gate pr_lookup_procdir(vnode_t *dp, char *comp)
34467c478bd9Sstevel@tonic-gate {
34477c478bd9Sstevel@tonic-gate pid_t pid;
34487c478bd9Sstevel@tonic-gate prnode_t *pnp;
34497c478bd9Sstevel@tonic-gate prcommon_t *pcp;
34507c478bd9Sstevel@tonic-gate vnode_t *vp;
34517c478bd9Sstevel@tonic-gate proc_t *p;
34527c478bd9Sstevel@tonic-gate int c;
34537c478bd9Sstevel@tonic-gate
34547c478bd9Sstevel@tonic-gate ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
34557c478bd9Sstevel@tonic-gate
34567c478bd9Sstevel@tonic-gate if (strcmp(comp, "self") == 0) {
34577c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_SELF);
34587c478bd9Sstevel@tonic-gate return (PTOV(pnp));
34597c478bd9Sstevel@tonic-gate } else {
34607c478bd9Sstevel@tonic-gate pid = 0;
34617c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
34627c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
34637c478bd9Sstevel@tonic-gate return (NULL);
34647c478bd9Sstevel@tonic-gate pid = 10*pid + c - '0';
34657c478bd9Sstevel@tonic-gate if (pid > maxpid)
34667c478bd9Sstevel@tonic-gate return (NULL);
34677c478bd9Sstevel@tonic-gate }
34687c478bd9Sstevel@tonic-gate }
34697c478bd9Sstevel@tonic-gate
34707c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_PIDDIR);
34717c478bd9Sstevel@tonic-gate
34727c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
34737c478bd9Sstevel@tonic-gate if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
34747c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
34757c478bd9Sstevel@tonic-gate prfreenode(pnp);
34767c478bd9Sstevel@tonic-gate return (NULL);
34777c478bd9Sstevel@tonic-gate }
34787c478bd9Sstevel@tonic-gate ASSERT(p->p_stat != 0);
34797c478bd9Sstevel@tonic-gate
3480ddf7fe95Scasper /* NOTE: we're holding pidlock across the policy call. */
34817c478bd9Sstevel@tonic-gate if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3482ddf7fe95Scasper mutex_exit(&pidlock);
34837c478bd9Sstevel@tonic-gate prfreenode(pnp);
34847c478bd9Sstevel@tonic-gate return (NULL);
34857c478bd9Sstevel@tonic-gate }
34867c478bd9Sstevel@tonic-gate
3487ddf7fe95Scasper mutex_enter(&p->p_lock);
3488ddf7fe95Scasper mutex_exit(&pidlock);
3489ddf7fe95Scasper
34907c478bd9Sstevel@tonic-gate /*
34917c478bd9Sstevel@tonic-gate * If a process vnode already exists and it is not invalid
34927c478bd9Sstevel@tonic-gate * and it was created by the current process and it belongs
34937c478bd9Sstevel@tonic-gate * to the same /proc mount point as our parent vnode, then
34947c478bd9Sstevel@tonic-gate * just use it and discard the newly-allocated prnode.
34957c478bd9Sstevel@tonic-gate */
34967c478bd9Sstevel@tonic-gate for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
34977c478bd9Sstevel@tonic-gate if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
34987c478bd9Sstevel@tonic-gate VTOP(vp)->pr_owner == curproc &&
34997c478bd9Sstevel@tonic-gate vp->v_vfsp == dp->v_vfsp) {
35007c478bd9Sstevel@tonic-gate ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
35017c478bd9Sstevel@tonic-gate VN_HOLD(vp);
35027c478bd9Sstevel@tonic-gate prfreenode(pnp);
35037c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
35047c478bd9Sstevel@tonic-gate return (vp);
35057c478bd9Sstevel@tonic-gate }
35067c478bd9Sstevel@tonic-gate }
35077c478bd9Sstevel@tonic-gate pnp->pr_owner = curproc;
35087c478bd9Sstevel@tonic-gate
35097c478bd9Sstevel@tonic-gate /*
35107c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
35117c478bd9Sstevel@tonic-gate * Finish the job.
35127c478bd9Sstevel@tonic-gate */
35137c478bd9Sstevel@tonic-gate pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
35147c478bd9Sstevel@tonic-gate if ((vp = p->p_trace) != NULL) {
35157c478bd9Sstevel@tonic-gate /* discard the new prcommon and use the existing prcommon */
35167c478bd9Sstevel@tonic-gate prfreecommon(pcp);
35177c478bd9Sstevel@tonic-gate pcp = VTOP(vp)->pr_common;
35187c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
35197c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
35207c478bd9Sstevel@tonic-gate pcp->prc_refcnt++;
35217c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
35227c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
35237c478bd9Sstevel@tonic-gate } else {
35247c478bd9Sstevel@tonic-gate /* initialize the new prcommon struct */
35257c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
35267c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_SYS;
35277c478bd9Sstevel@tonic-gate if (p->p_stat == SZOMB)
35287c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_DESTROY;
35297c478bd9Sstevel@tonic-gate pcp->prc_proc = p;
35307c478bd9Sstevel@tonic-gate pcp->prc_datamodel = p->p_model;
35317c478bd9Sstevel@tonic-gate pcp->prc_pid = p->p_pid;
35327c478bd9Sstevel@tonic-gate pcp->prc_slot = p->p_slot;
35337c478bd9Sstevel@tonic-gate }
35347c478bd9Sstevel@tonic-gate pnp->pr_pcommon = pcp;
35357c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
35367c478bd9Sstevel@tonic-gate VN_HOLD(dp);
35377c478bd9Sstevel@tonic-gate /*
35387c478bd9Sstevel@tonic-gate * Link in the old, invalid directory vnode so we
35397c478bd9Sstevel@tonic-gate * can later determine the last close of the file.
35407c478bd9Sstevel@tonic-gate */
35417c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_trace;
35427c478bd9Sstevel@tonic-gate p->p_trace = dp = PTOV(pnp);
35437c478bd9Sstevel@tonic-gate
35447c478bd9Sstevel@tonic-gate /*
35457c478bd9Sstevel@tonic-gate * Kludge for old /proc: initialize the PR_PIDFILE as well.
35467c478bd9Sstevel@tonic-gate */
35477c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
35487c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
35497c478bd9Sstevel@tonic-gate pnp->pr_ino = ptoi(pcp->prc_pid);
35507c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
35517c478bd9Sstevel@tonic-gate pnp->pr_pcommon = pcp;
35527c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
35537c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
35547c478bd9Sstevel@tonic-gate p->p_plist = vp;
35557c478bd9Sstevel@tonic-gate
35567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
35577c478bd9Sstevel@tonic-gate return (dp);
35587c478bd9Sstevel@tonic-gate }
35597c478bd9Sstevel@tonic-gate
35607c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_piddir(vnode_t * dp,char * comp)35617c478bd9Sstevel@tonic-gate pr_lookup_piddir(vnode_t *dp, char *comp)
35627c478bd9Sstevel@tonic-gate {
35637c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
35647c478bd9Sstevel@tonic-gate vnode_t *vp;
35657c478bd9Sstevel@tonic-gate prnode_t *pnp;
35667c478bd9Sstevel@tonic-gate proc_t *p;
35677c478bd9Sstevel@tonic-gate user_t *up;
35687c478bd9Sstevel@tonic-gate prdirent_t *dirp;
35697c478bd9Sstevel@tonic-gate int i;
35707c478bd9Sstevel@tonic-gate enum prnodetype type;
35717c478bd9Sstevel@tonic-gate
35727c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_PIDDIR);
35737c478bd9Sstevel@tonic-gate
35747c478bd9Sstevel@tonic-gate for (i = 0; i < NPIDDIRFILES; i++) {
35757c478bd9Sstevel@tonic-gate /* Skip "." and ".." */
35767c478bd9Sstevel@tonic-gate dirp = &piddir[i+2];
35777c478bd9Sstevel@tonic-gate if (strcmp(comp, dirp->d_name) == 0)
35787c478bd9Sstevel@tonic-gate break;
35797c478bd9Sstevel@tonic-gate }
35807c478bd9Sstevel@tonic-gate
35817c478bd9Sstevel@tonic-gate if (i >= NPIDDIRFILES)
35827c478bd9Sstevel@tonic-gate return (NULL);
35837c478bd9Sstevel@tonic-gate
35847c478bd9Sstevel@tonic-gate type = (int)dirp->d_ino;
35857c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, type);
35867c478bd9Sstevel@tonic-gate
35877c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
35887c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
35897c478bd9Sstevel@tonic-gate if (p == NULL) {
35907c478bd9Sstevel@tonic-gate prfreenode(pnp);
35917c478bd9Sstevel@tonic-gate return (NULL);
35927c478bd9Sstevel@tonic-gate }
35937c478bd9Sstevel@tonic-gate if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
35947c478bd9Sstevel@tonic-gate switch (type) {
35957c478bd9Sstevel@tonic-gate case PR_PSINFO:
35967c478bd9Sstevel@tonic-gate case PR_USAGE:
35977c478bd9Sstevel@tonic-gate break;
35987c478bd9Sstevel@tonic-gate default:
35997c478bd9Sstevel@tonic-gate prunlock(dpnp);
36007c478bd9Sstevel@tonic-gate prfreenode(pnp);
36017c478bd9Sstevel@tonic-gate return (NULL);
36027c478bd9Sstevel@tonic-gate }
36037c478bd9Sstevel@tonic-gate }
36047c478bd9Sstevel@tonic-gate
36057c478bd9Sstevel@tonic-gate switch (type) {
36067c478bd9Sstevel@tonic-gate case PR_CURDIR:
36077c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
36087c478bd9Sstevel@tonic-gate up = PTOU(p);
36097c478bd9Sstevel@tonic-gate vp = (type == PR_CURDIR)? up->u_cdir :
36107c478bd9Sstevel@tonic-gate (up->u_rdir? up->u_rdir : rootdir);
36117c478bd9Sstevel@tonic-gate
36127c478bd9Sstevel@tonic-gate if (vp == NULL) { /* can't happen? */
36137c478bd9Sstevel@tonic-gate prunlock(dpnp);
36147c478bd9Sstevel@tonic-gate prfreenode(pnp);
36157c478bd9Sstevel@tonic-gate return (NULL);
36167c478bd9Sstevel@tonic-gate }
36177c478bd9Sstevel@tonic-gate /*
36187c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
36197c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
36207c478bd9Sstevel@tonic-gate */
36217c478bd9Sstevel@tonic-gate VN_HOLD(vp);
36227c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
36237c478bd9Sstevel@tonic-gate break;
36247c478bd9Sstevel@tonic-gate default:
36257c478bd9Sstevel@tonic-gate break;
36267c478bd9Sstevel@tonic-gate }
36277c478bd9Sstevel@tonic-gate
36287c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
36297c478bd9Sstevel@tonic-gate
36307c478bd9Sstevel@tonic-gate if ((vp = dpnp->pr_files[i]) != NULL &&
36317c478bd9Sstevel@tonic-gate !(VTOP(vp)->pr_flags & PR_INVAL)) {
36327c478bd9Sstevel@tonic-gate VN_HOLD(vp);
36337c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
36347c478bd9Sstevel@tonic-gate prunlock(dpnp);
36357c478bd9Sstevel@tonic-gate prfreenode(pnp);
36367c478bd9Sstevel@tonic-gate return (vp);
36377c478bd9Sstevel@tonic-gate }
36387c478bd9Sstevel@tonic-gate
36397c478bd9Sstevel@tonic-gate /*
36407c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
36417c478bd9Sstevel@tonic-gate * Finish the job.
36427c478bd9Sstevel@tonic-gate */
36437c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
36447c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
36457c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
36467c478bd9Sstevel@tonic-gate VN_HOLD(dp);
36477c478bd9Sstevel@tonic-gate pnp->pr_index = i;
36487c478bd9Sstevel@tonic-gate
36497c478bd9Sstevel@tonic-gate dpnp->pr_files[i] = vp = PTOV(pnp);
36507c478bd9Sstevel@tonic-gate
36517c478bd9Sstevel@tonic-gate /*
36527c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
36537c478bd9Sstevel@tonic-gate */
36547c478bd9Sstevel@tonic-gate if (vp->v_type == VPROC) {
36557c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
36567c478bd9Sstevel@tonic-gate p->p_plist = vp;
36577c478bd9Sstevel@tonic-gate }
36587c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
36597c478bd9Sstevel@tonic-gate prunlock(dpnp);
36607c478bd9Sstevel@tonic-gate return (vp);
36617c478bd9Sstevel@tonic-gate }
36627c478bd9Sstevel@tonic-gate
36637c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_objectdir(vnode_t * dp,char * comp)36647c478bd9Sstevel@tonic-gate pr_lookup_objectdir(vnode_t *dp, char *comp)
36657c478bd9Sstevel@tonic-gate {
36667c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
36677c478bd9Sstevel@tonic-gate prnode_t *pnp;
36687c478bd9Sstevel@tonic-gate proc_t *p;
36697c478bd9Sstevel@tonic-gate struct seg *seg;
36707c478bd9Sstevel@tonic-gate struct as *as;
36717c478bd9Sstevel@tonic-gate vnode_t *vp;
36727c478bd9Sstevel@tonic-gate vattr_t vattr;
36737c478bd9Sstevel@tonic-gate
36747c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_OBJECTDIR);
36757c478bd9Sstevel@tonic-gate
36767c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_OBJECT);
36777c478bd9Sstevel@tonic-gate
36787c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
36797c478bd9Sstevel@tonic-gate prfreenode(pnp);
36807c478bd9Sstevel@tonic-gate return (NULL);
36817c478bd9Sstevel@tonic-gate }
36827c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
36837c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
36847c478bd9Sstevel@tonic-gate prunlock(dpnp);
36857c478bd9Sstevel@tonic-gate prfreenode(pnp);
36867c478bd9Sstevel@tonic-gate return (NULL);
36877c478bd9Sstevel@tonic-gate }
36887c478bd9Sstevel@tonic-gate
36897c478bd9Sstevel@tonic-gate /*
36907c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
36917c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
36927c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
36937c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
36947c478bd9Sstevel@tonic-gate */
36957c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3696*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_READER);
36977c478bd9Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL) {
36987c478bd9Sstevel@tonic-gate vp = NULL;
36997c478bd9Sstevel@tonic-gate goto out;
37007c478bd9Sstevel@tonic-gate }
37017c478bd9Sstevel@tonic-gate if (strcmp(comp, "a.out") == 0) {
37027c478bd9Sstevel@tonic-gate vp = p->p_exec;
37037c478bd9Sstevel@tonic-gate goto out;
37047c478bd9Sstevel@tonic-gate }
37057c478bd9Sstevel@tonic-gate do {
37067c478bd9Sstevel@tonic-gate /*
37077c478bd9Sstevel@tonic-gate * Manufacture a filename for the "object" directory.
37087c478bd9Sstevel@tonic-gate */
37097c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
37107c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
37117c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
37127c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
3713da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
37147c478bd9Sstevel@tonic-gate char name[64];
37157c478bd9Sstevel@tonic-gate
37167c478bd9Sstevel@tonic-gate if (vp == p->p_exec) /* "a.out" */
37177c478bd9Sstevel@tonic-gate continue;
37187c478bd9Sstevel@tonic-gate pr_object_name(name, vp, &vattr);
37197c478bd9Sstevel@tonic-gate if (strcmp(name, comp) == 0)
37207c478bd9Sstevel@tonic-gate goto out;
37217c478bd9Sstevel@tonic-gate }
37227c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
37237c478bd9Sstevel@tonic-gate
37247c478bd9Sstevel@tonic-gate vp = NULL;
37257c478bd9Sstevel@tonic-gate out:
37267c478bd9Sstevel@tonic-gate if (vp != NULL) {
37277c478bd9Sstevel@tonic-gate VN_HOLD(vp);
37287c478bd9Sstevel@tonic-gate }
3729*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
37307c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
37317c478bd9Sstevel@tonic-gate prunlock(dpnp);
37327c478bd9Sstevel@tonic-gate
37337c478bd9Sstevel@tonic-gate if (vp == NULL)
37347c478bd9Sstevel@tonic-gate prfreenode(pnp);
37357c478bd9Sstevel@tonic-gate else {
37367c478bd9Sstevel@tonic-gate /*
37377c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
37387c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
37397c478bd9Sstevel@tonic-gate * Don't link this prnode into the list of all
37407c478bd9Sstevel@tonic-gate * prnodes for the process; this is a one-use node.
37417c478bd9Sstevel@tonic-gate * Its use is entirely to catch and fail opens for writing.
37427c478bd9Sstevel@tonic-gate */
37437c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
37447c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
37457c478bd9Sstevel@tonic-gate }
37467c478bd9Sstevel@tonic-gate
37477c478bd9Sstevel@tonic-gate return (vp);
37487c478bd9Sstevel@tonic-gate }
37497c478bd9Sstevel@tonic-gate
37507c478bd9Sstevel@tonic-gate /*
37517c478bd9Sstevel@tonic-gate * Find or construct an lwp vnode for the given lwpid.
37527c478bd9Sstevel@tonic-gate */
37537c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_lwpdir(vnode_t * dp,char * comp)37547c478bd9Sstevel@tonic-gate pr_lookup_lwpdir(vnode_t *dp, char *comp)
37557c478bd9Sstevel@tonic-gate {
37567c478bd9Sstevel@tonic-gate id_t tid; /* same type as t->t_tid */
37577c478bd9Sstevel@tonic-gate int want_agent;
37587c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
37597c478bd9Sstevel@tonic-gate prnode_t *pnp;
37607c478bd9Sstevel@tonic-gate prcommon_t *pcp;
37617c478bd9Sstevel@tonic-gate vnode_t *vp;
37627c478bd9Sstevel@tonic-gate proc_t *p;
37637c478bd9Sstevel@tonic-gate kthread_t *t;
37647c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
37657c478bd9Sstevel@tonic-gate lwpent_t *lep;
37667c478bd9Sstevel@tonic-gate int tslot;
37677c478bd9Sstevel@tonic-gate int c;
37687c478bd9Sstevel@tonic-gate
37697c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_LWPDIR);
37707c478bd9Sstevel@tonic-gate
37717c478bd9Sstevel@tonic-gate tid = 0;
37727c478bd9Sstevel@tonic-gate if (strcmp(comp, "agent") == 0)
37737c478bd9Sstevel@tonic-gate want_agent = 1;
37747c478bd9Sstevel@tonic-gate else {
37757c478bd9Sstevel@tonic-gate want_agent = 0;
37767c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
37777c478bd9Sstevel@tonic-gate id_t otid;
37787c478bd9Sstevel@tonic-gate
37797c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
37807c478bd9Sstevel@tonic-gate return (NULL);
37817c478bd9Sstevel@tonic-gate otid = tid;
37827c478bd9Sstevel@tonic-gate tid = 10*tid + c - '0';
37837c478bd9Sstevel@tonic-gate if (tid/10 != otid) /* integer overflow */
37847c478bd9Sstevel@tonic-gate return (NULL);
37857c478bd9Sstevel@tonic-gate }
37867c478bd9Sstevel@tonic-gate }
37877c478bd9Sstevel@tonic-gate
37887c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_LWPIDDIR);
37897c478bd9Sstevel@tonic-gate
37907c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
37917c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
37927c478bd9Sstevel@tonic-gate if (p == NULL) {
37937c478bd9Sstevel@tonic-gate prfreenode(pnp);
37947c478bd9Sstevel@tonic-gate return (NULL);
37957c478bd9Sstevel@tonic-gate }
37967c478bd9Sstevel@tonic-gate
37977c478bd9Sstevel@tonic-gate if (want_agent) {
37987c478bd9Sstevel@tonic-gate if ((t = p->p_agenttp) == NULL)
37997c478bd9Sstevel@tonic-gate lep = NULL;
38007c478bd9Sstevel@tonic-gate else {
38017c478bd9Sstevel@tonic-gate tid = t->t_tid;
38027c478bd9Sstevel@tonic-gate tslot = t->t_dslot;
38037c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[tslot].ld_entry;
38047c478bd9Sstevel@tonic-gate }
38057c478bd9Sstevel@tonic-gate } else {
38067c478bd9Sstevel@tonic-gate if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
38077c478bd9Sstevel@tonic-gate lep = NULL;
38087c478bd9Sstevel@tonic-gate else {
38097c478bd9Sstevel@tonic-gate tslot = (int)(ldp - p->p_lwpdir);
38107c478bd9Sstevel@tonic-gate lep = ldp->ld_entry;
38117c478bd9Sstevel@tonic-gate }
38127c478bd9Sstevel@tonic-gate }
38137c478bd9Sstevel@tonic-gate
38147c478bd9Sstevel@tonic-gate if (lep == NULL) {
38157c478bd9Sstevel@tonic-gate prunlock(dpnp);
38167c478bd9Sstevel@tonic-gate prfreenode(pnp);
38177c478bd9Sstevel@tonic-gate return (NULL);
38187c478bd9Sstevel@tonic-gate }
38197c478bd9Sstevel@tonic-gate
38207c478bd9Sstevel@tonic-gate /*
38217c478bd9Sstevel@tonic-gate * If an lwp vnode already exists and it is not invalid
38227c478bd9Sstevel@tonic-gate * and it was created by the current process and it belongs
38237c478bd9Sstevel@tonic-gate * to the same /proc mount point as our parent vnode, then
38247c478bd9Sstevel@tonic-gate * just use it and discard the newly-allocated prnode.
38257c478bd9Sstevel@tonic-gate */
38267c478bd9Sstevel@tonic-gate for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
38277c478bd9Sstevel@tonic-gate if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
38287c478bd9Sstevel@tonic-gate VTOP(vp)->pr_owner == curproc &&
38297c478bd9Sstevel@tonic-gate vp->v_vfsp == dp->v_vfsp) {
38307c478bd9Sstevel@tonic-gate VN_HOLD(vp);
38317c478bd9Sstevel@tonic-gate prunlock(dpnp);
38327c478bd9Sstevel@tonic-gate prfreenode(pnp);
38337c478bd9Sstevel@tonic-gate return (vp);
38347c478bd9Sstevel@tonic-gate }
38357c478bd9Sstevel@tonic-gate }
38367c478bd9Sstevel@tonic-gate pnp->pr_owner = curproc;
38377c478bd9Sstevel@tonic-gate
38387c478bd9Sstevel@tonic-gate /*
38397c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
38407c478bd9Sstevel@tonic-gate * Finish the job.
38417c478bd9Sstevel@tonic-gate */
38427c478bd9Sstevel@tonic-gate pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
38437c478bd9Sstevel@tonic-gate if ((vp = lep->le_trace) != NULL) {
38447c478bd9Sstevel@tonic-gate /* discard the new prcommon and use the existing prcommon */
38457c478bd9Sstevel@tonic-gate prfreecommon(pcp);
38467c478bd9Sstevel@tonic-gate pcp = VTOP(vp)->pr_common;
38477c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
38487c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
38497c478bd9Sstevel@tonic-gate pcp->prc_refcnt++;
38507c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
38517c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
38527c478bd9Sstevel@tonic-gate } else {
38537c478bd9Sstevel@tonic-gate /* initialize the new prcommon struct */
38547c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_LWP;
38557c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
38567c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_SYS;
38577c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) == NULL)
38587c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_DESTROY;
38597c478bd9Sstevel@tonic-gate pcp->prc_proc = p;
38607c478bd9Sstevel@tonic-gate pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
38617c478bd9Sstevel@tonic-gate pcp->prc_pid = p->p_pid;
38627c478bd9Sstevel@tonic-gate pcp->prc_slot = p->p_slot;
38637c478bd9Sstevel@tonic-gate pcp->prc_thread = t;
38647c478bd9Sstevel@tonic-gate pcp->prc_tid = tid;
38657c478bd9Sstevel@tonic-gate pcp->prc_tslot = tslot;
38667c478bd9Sstevel@tonic-gate }
38677c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
38687c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
38697c478bd9Sstevel@tonic-gate VN_HOLD(dp);
38707c478bd9Sstevel@tonic-gate /*
38717c478bd9Sstevel@tonic-gate * Link in the old, invalid directory vnode so we
38727c478bd9Sstevel@tonic-gate * can later determine the last close of the file.
38737c478bd9Sstevel@tonic-gate */
38747c478bd9Sstevel@tonic-gate pnp->pr_next = lep->le_trace;
38757c478bd9Sstevel@tonic-gate lep->le_trace = vp = PTOV(pnp);
38767c478bd9Sstevel@tonic-gate prunlock(dpnp);
38777c478bd9Sstevel@tonic-gate return (vp);
38787c478bd9Sstevel@tonic-gate }
38797c478bd9Sstevel@tonic-gate
38807c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_lwpiddir(vnode_t * dp,char * comp)38817c478bd9Sstevel@tonic-gate pr_lookup_lwpiddir(vnode_t *dp, char *comp)
38827c478bd9Sstevel@tonic-gate {
38837c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
38847c478bd9Sstevel@tonic-gate vnode_t *vp;
38857c478bd9Sstevel@tonic-gate prnode_t *pnp;
38867c478bd9Sstevel@tonic-gate proc_t *p;
38877c478bd9Sstevel@tonic-gate prdirent_t *dirp;
38887c478bd9Sstevel@tonic-gate int i;
38897c478bd9Sstevel@tonic-gate enum prnodetype type;
38907c478bd9Sstevel@tonic-gate
38917c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_LWPIDDIR);
38927c478bd9Sstevel@tonic-gate
38937c478bd9Sstevel@tonic-gate for (i = 0; i < NLWPIDDIRFILES; i++) {
38947c478bd9Sstevel@tonic-gate /* Skip "." and ".." */
38957c478bd9Sstevel@tonic-gate dirp = &lwpiddir[i+2];
38967c478bd9Sstevel@tonic-gate if (strcmp(comp, dirp->d_name) == 0)
38977c478bd9Sstevel@tonic-gate break;
38987c478bd9Sstevel@tonic-gate }
38997c478bd9Sstevel@tonic-gate
39007c478bd9Sstevel@tonic-gate if (i >= NLWPIDDIRFILES)
39017c478bd9Sstevel@tonic-gate return (NULL);
39027c478bd9Sstevel@tonic-gate
39037c478bd9Sstevel@tonic-gate type = (int)dirp->d_ino;
39047c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, type);
39057c478bd9Sstevel@tonic-gate
39067c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
39077c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
39087c478bd9Sstevel@tonic-gate if (p == NULL) {
39097c478bd9Sstevel@tonic-gate prfreenode(pnp);
39107c478bd9Sstevel@tonic-gate return (NULL);
39117c478bd9Sstevel@tonic-gate }
39127c478bd9Sstevel@tonic-gate if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
39137c478bd9Sstevel@tonic-gate /*
39147c478bd9Sstevel@tonic-gate * Only the lwpsinfo file is present for zombie lwps.
39157c478bd9Sstevel@tonic-gate * Nothing is present if the lwp has been reaped.
39167c478bd9Sstevel@tonic-gate */
39177c478bd9Sstevel@tonic-gate if (dpnp->pr_common->prc_tslot == -1 ||
39187c478bd9Sstevel@tonic-gate type != PR_LWPSINFO) {
39197c478bd9Sstevel@tonic-gate prunlock(dpnp);
39207c478bd9Sstevel@tonic-gate prfreenode(pnp);
39217c478bd9Sstevel@tonic-gate return (NULL);
39227c478bd9Sstevel@tonic-gate }
39237c478bd9Sstevel@tonic-gate }
39247c478bd9Sstevel@tonic-gate
39257c478bd9Sstevel@tonic-gate #if defined(__sparc)
39267c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
39277c478bd9Sstevel@tonic-gate if (type == PR_ASRS && p->p_model != DATAMODEL_LP64) {
39287c478bd9Sstevel@tonic-gate prunlock(dpnp);
39297c478bd9Sstevel@tonic-gate prfreenode(pnp);
39307c478bd9Sstevel@tonic-gate return (NULL);
39317c478bd9Sstevel@tonic-gate }
39327c478bd9Sstevel@tonic-gate #endif
39337c478bd9Sstevel@tonic-gate
39347c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
39357c478bd9Sstevel@tonic-gate
39367c478bd9Sstevel@tonic-gate if ((vp = dpnp->pr_files[i]) != NULL &&
39377c478bd9Sstevel@tonic-gate !(VTOP(vp)->pr_flags & PR_INVAL)) {
39387c478bd9Sstevel@tonic-gate VN_HOLD(vp);
39397c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
39407c478bd9Sstevel@tonic-gate prunlock(dpnp);
39417c478bd9Sstevel@tonic-gate prfreenode(pnp);
39427c478bd9Sstevel@tonic-gate return (vp);
39437c478bd9Sstevel@tonic-gate }
39447c478bd9Sstevel@tonic-gate
39457c478bd9Sstevel@tonic-gate /*
39467c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
39477c478bd9Sstevel@tonic-gate * Finish the job.
39487c478bd9Sstevel@tonic-gate */
39497c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
39507c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
39517c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
39527c478bd9Sstevel@tonic-gate VN_HOLD(dp);
39537c478bd9Sstevel@tonic-gate pnp->pr_index = i;
39547c478bd9Sstevel@tonic-gate
39557c478bd9Sstevel@tonic-gate dpnp->pr_files[i] = vp = PTOV(pnp);
39567c478bd9Sstevel@tonic-gate
39577c478bd9Sstevel@tonic-gate /*
39587c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
39597c478bd9Sstevel@tonic-gate */
39607c478bd9Sstevel@tonic-gate if (vp->v_type == VPROC) {
39617c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
39627c478bd9Sstevel@tonic-gate p->p_plist = vp;
39637c478bd9Sstevel@tonic-gate }
39647c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
39657c478bd9Sstevel@tonic-gate prunlock(dpnp);
39667c478bd9Sstevel@tonic-gate return (vp);
39677c478bd9Sstevel@tonic-gate }
39687c478bd9Sstevel@tonic-gate
39697c478bd9Sstevel@tonic-gate /*
39707c478bd9Sstevel@tonic-gate * Lookup one of the process's open files.
39717c478bd9Sstevel@tonic-gate */
39727c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_fddir(vnode_t * dp,char * comp)39737c478bd9Sstevel@tonic-gate pr_lookup_fddir(vnode_t *dp, char *comp)
39747c478bd9Sstevel@tonic-gate {
39757c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
39767c478bd9Sstevel@tonic-gate prnode_t *pnp;
39777c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
39787c478bd9Sstevel@tonic-gate proc_t *p;
39797c478bd9Sstevel@tonic-gate file_t *fp;
39807c478bd9Sstevel@tonic-gate uint_t fd;
39817c478bd9Sstevel@tonic-gate int c;
39827c478bd9Sstevel@tonic-gate uf_entry_t *ufp;
39837c478bd9Sstevel@tonic-gate uf_info_t *fip;
39847c478bd9Sstevel@tonic-gate
39857c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_FDDIR);
39867c478bd9Sstevel@tonic-gate
39877c478bd9Sstevel@tonic-gate fd = 0;
39887c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
39897c478bd9Sstevel@tonic-gate int ofd;
39907c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
39917c478bd9Sstevel@tonic-gate return (NULL);
39927c478bd9Sstevel@tonic-gate ofd = fd;
39937c478bd9Sstevel@tonic-gate fd = 10*fd + c - '0';
39947c478bd9Sstevel@tonic-gate if (fd/10 != ofd) /* integer overflow */
39957c478bd9Sstevel@tonic-gate return (NULL);
39967c478bd9Sstevel@tonic-gate }
39977c478bd9Sstevel@tonic-gate
39987c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_FD);
39997c478bd9Sstevel@tonic-gate
40007c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
40017c478bd9Sstevel@tonic-gate prfreenode(pnp);
40027c478bd9Sstevel@tonic-gate return (NULL);
40037c478bd9Sstevel@tonic-gate }
40047c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
40057c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
40067c478bd9Sstevel@tonic-gate prunlock(dpnp);
40077c478bd9Sstevel@tonic-gate prfreenode(pnp);
40087c478bd9Sstevel@tonic-gate return (NULL);
40097c478bd9Sstevel@tonic-gate }
40107c478bd9Sstevel@tonic-gate
40117c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
40127c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
40137c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
40147c478bd9Sstevel@tonic-gate if (fd < fip->fi_nfiles) {
40157c478bd9Sstevel@tonic-gate UF_ENTER(ufp, fip, fd);
40167c478bd9Sstevel@tonic-gate if ((fp = ufp->uf_file) != NULL) {
40177c478bd9Sstevel@tonic-gate pnp->pr_mode = 07111;
40187c478bd9Sstevel@tonic-gate if (fp->f_flag & FREAD)
40197c478bd9Sstevel@tonic-gate pnp->pr_mode |= 0444;
40207c478bd9Sstevel@tonic-gate if (fp->f_flag & FWRITE)
40217c478bd9Sstevel@tonic-gate pnp->pr_mode |= 0222;
40227c478bd9Sstevel@tonic-gate vp = fp->f_vnode;
40237c478bd9Sstevel@tonic-gate VN_HOLD(vp);
40247c478bd9Sstevel@tonic-gate }
40257c478bd9Sstevel@tonic-gate UF_EXIT(ufp);
40267c478bd9Sstevel@tonic-gate }
40277c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
40287c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
40297c478bd9Sstevel@tonic-gate prunlock(dpnp);
40307c478bd9Sstevel@tonic-gate
40317c478bd9Sstevel@tonic-gate if (vp == NULL)
40327c478bd9Sstevel@tonic-gate prfreenode(pnp);
40337c478bd9Sstevel@tonic-gate else {
40347c478bd9Sstevel@tonic-gate /*
40357c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
40367c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
40377c478bd9Sstevel@tonic-gate * Don't link this prnode into the list of all
40387c478bd9Sstevel@tonic-gate * prnodes for the process; this is a one-use node.
40397c478bd9Sstevel@tonic-gate */
40407c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
40417c478bd9Sstevel@tonic-gate pnp->pr_parent = dp; /* needed for prlookup */
40427c478bd9Sstevel@tonic-gate VN_HOLD(dp);
40437c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
40447c478bd9Sstevel@tonic-gate if (pnp->pr_realvp->v_type == VDIR)
40457c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
40467c478bd9Sstevel@tonic-gate }
40477c478bd9Sstevel@tonic-gate
40487c478bd9Sstevel@tonic-gate return (vp);
40497c478bd9Sstevel@tonic-gate }
40507c478bd9Sstevel@tonic-gate
40517c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_pathdir(vnode_t * dp,char * comp)40527c478bd9Sstevel@tonic-gate pr_lookup_pathdir(vnode_t *dp, char *comp)
40537c478bd9Sstevel@tonic-gate {
40547c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
40557c478bd9Sstevel@tonic-gate prnode_t *pnp;
40567c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
40577c478bd9Sstevel@tonic-gate proc_t *p;
40587c478bd9Sstevel@tonic-gate uint_t fd, flags = 0;
40597c478bd9Sstevel@tonic-gate int c;
40607c478bd9Sstevel@tonic-gate uf_entry_t *ufp;
40617c478bd9Sstevel@tonic-gate uf_info_t *fip;
40627c478bd9Sstevel@tonic-gate enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
40637c478bd9Sstevel@tonic-gate char *tmp;
40647c478bd9Sstevel@tonic-gate int idx;
40657c478bd9Sstevel@tonic-gate struct seg *seg;
40667c478bd9Sstevel@tonic-gate struct as *as = NULL;
40677c478bd9Sstevel@tonic-gate vattr_t vattr;
40687c478bd9Sstevel@tonic-gate
40697c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_PATHDIR);
40707c478bd9Sstevel@tonic-gate
40717c478bd9Sstevel@tonic-gate /*
40727c478bd9Sstevel@tonic-gate * First, check if this is a numeric entry, in which case we have a
40737c478bd9Sstevel@tonic-gate * file descriptor.
40747c478bd9Sstevel@tonic-gate */
40757c478bd9Sstevel@tonic-gate fd = 0;
40767c478bd9Sstevel@tonic-gate type = NAME_FD;
40777c478bd9Sstevel@tonic-gate tmp = comp;
40787c478bd9Sstevel@tonic-gate while ((c = *tmp++) != '\0') {
40797c478bd9Sstevel@tonic-gate int ofd;
40807c478bd9Sstevel@tonic-gate if (c < '0' || c > '9') {
40817c478bd9Sstevel@tonic-gate type = NAME_UNKNOWN;
40827c478bd9Sstevel@tonic-gate break;
40837c478bd9Sstevel@tonic-gate }
40847c478bd9Sstevel@tonic-gate ofd = fd;
40857c478bd9Sstevel@tonic-gate fd = 10*fd + c - '0';
40867c478bd9Sstevel@tonic-gate if (fd/10 != ofd) { /* integer overflow */
40877c478bd9Sstevel@tonic-gate type = NAME_UNKNOWN;
40887c478bd9Sstevel@tonic-gate break;
40897c478bd9Sstevel@tonic-gate }
40907c478bd9Sstevel@tonic-gate }
40917c478bd9Sstevel@tonic-gate
40927c478bd9Sstevel@tonic-gate /*
40937c478bd9Sstevel@tonic-gate * Next, see if it is one of the special values {root, cwd}.
40947c478bd9Sstevel@tonic-gate */
40957c478bd9Sstevel@tonic-gate if (type == NAME_UNKNOWN) {
40967c478bd9Sstevel@tonic-gate if (strcmp(comp, "root") == 0)
40977c478bd9Sstevel@tonic-gate type = NAME_ROOT;
40987c478bd9Sstevel@tonic-gate else if (strcmp(comp, "cwd") == 0)
40997c478bd9Sstevel@tonic-gate type = NAME_CWD;
41007c478bd9Sstevel@tonic-gate }
41017c478bd9Sstevel@tonic-gate
41027c478bd9Sstevel@tonic-gate /*
41037c478bd9Sstevel@tonic-gate * Grab the necessary data from the process
41047c478bd9Sstevel@tonic-gate */
41057c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0)
41067c478bd9Sstevel@tonic-gate return (NULL);
41077c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
41087c478bd9Sstevel@tonic-gate
41097c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
41107c478bd9Sstevel@tonic-gate
41117c478bd9Sstevel@tonic-gate switch (type) {
41127c478bd9Sstevel@tonic-gate case NAME_ROOT:
41137c478bd9Sstevel@tonic-gate if ((vp = PTOU(p)->u_rdir) == NULL)
41147c478bd9Sstevel@tonic-gate vp = p->p_zone->zone_rootvp;
41157c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41167c478bd9Sstevel@tonic-gate break;
41177c478bd9Sstevel@tonic-gate case NAME_CWD:
41187c478bd9Sstevel@tonic-gate vp = PTOU(p)->u_cdir;
41197c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41207c478bd9Sstevel@tonic-gate break;
41217c478bd9Sstevel@tonic-gate default:
41227c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
41237c478bd9Sstevel@tonic-gate prunlock(dpnp);
41247c478bd9Sstevel@tonic-gate return (NULL);
41257c478bd9Sstevel@tonic-gate }
41267c478bd9Sstevel@tonic-gate }
41277c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
41287c478bd9Sstevel@tonic-gate
41297c478bd9Sstevel@tonic-gate /*
41307c478bd9Sstevel@tonic-gate * Determine if this is an object entry
41317c478bd9Sstevel@tonic-gate */
41327c478bd9Sstevel@tonic-gate if (type == NAME_UNKNOWN) {
41337c478bd9Sstevel@tonic-gate /*
41347c478bd9Sstevel@tonic-gate * Start with the inode index immediately after the number of
41357c478bd9Sstevel@tonic-gate * files.
41367c478bd9Sstevel@tonic-gate */
41377c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
41387c478bd9Sstevel@tonic-gate idx = fip->fi_nfiles + 4;
41397c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
41407c478bd9Sstevel@tonic-gate
41417c478bd9Sstevel@tonic-gate if (strcmp(comp, "a.out") == 0) {
41427c478bd9Sstevel@tonic-gate if (p->p_execdir != NULL) {
41437c478bd9Sstevel@tonic-gate vp = p->p_execdir;
41447c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41457c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
41467c478bd9Sstevel@tonic-gate flags |= PR_AOUT;
41477c478bd9Sstevel@tonic-gate } else {
41487c478bd9Sstevel@tonic-gate vp = p->p_exec;
41497c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41507c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
41517c478bd9Sstevel@tonic-gate }
41527c478bd9Sstevel@tonic-gate } else {
4153*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_READER);
41547c478bd9Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) != NULL) {
41557c478bd9Sstevel@tonic-gate do {
41567c478bd9Sstevel@tonic-gate /*
41577c478bd9Sstevel@tonic-gate * Manufacture a filename for the
41587c478bd9Sstevel@tonic-gate * "object" directory.
41597c478bd9Sstevel@tonic-gate */
41607c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
41617c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
41627c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp)
41637c478bd9Sstevel@tonic-gate == 0 &&
41647c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
4165da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(),
4166da6c28aaSamw NULL) == 0) {
41677c478bd9Sstevel@tonic-gate char name[64];
41687c478bd9Sstevel@tonic-gate
41697c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
41707c478bd9Sstevel@tonic-gate continue;
41717c478bd9Sstevel@tonic-gate idx++;
41727c478bd9Sstevel@tonic-gate pr_object_name(name, vp,
41737c478bd9Sstevel@tonic-gate &vattr);
41747c478bd9Sstevel@tonic-gate if (strcmp(name, comp) == 0)
41757c478bd9Sstevel@tonic-gate break;
41767c478bd9Sstevel@tonic-gate }
41777c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
41787c478bd9Sstevel@tonic-gate }
41797c478bd9Sstevel@tonic-gate
41807c478bd9Sstevel@tonic-gate if (seg == NULL) {
41817c478bd9Sstevel@tonic-gate vp = NULL;
41827c478bd9Sstevel@tonic-gate } else {
41837c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41847c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
41857c478bd9Sstevel@tonic-gate }
41867c478bd9Sstevel@tonic-gate
4187*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
41887c478bd9Sstevel@tonic-gate }
41897c478bd9Sstevel@tonic-gate }
41907c478bd9Sstevel@tonic-gate
41917c478bd9Sstevel@tonic-gate
41927c478bd9Sstevel@tonic-gate switch (type) {
41937c478bd9Sstevel@tonic-gate case NAME_FD:
41947c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
41957c478bd9Sstevel@tonic-gate if (fd < fip->fi_nfiles) {
41967c478bd9Sstevel@tonic-gate UF_ENTER(ufp, fip, fd);
41977c478bd9Sstevel@tonic-gate if (ufp->uf_file != NULL) {
41987c478bd9Sstevel@tonic-gate vp = ufp->uf_file->f_vnode;
41997c478bd9Sstevel@tonic-gate VN_HOLD(vp);
42007c478bd9Sstevel@tonic-gate }
42017c478bd9Sstevel@tonic-gate UF_EXIT(ufp);
42027c478bd9Sstevel@tonic-gate }
42037c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
42047c478bd9Sstevel@tonic-gate idx = fd + 4;
42057c478bd9Sstevel@tonic-gate break;
42067c478bd9Sstevel@tonic-gate case NAME_ROOT:
42077c478bd9Sstevel@tonic-gate idx = 2;
42087c478bd9Sstevel@tonic-gate break;
42097c478bd9Sstevel@tonic-gate case NAME_CWD:
42107c478bd9Sstevel@tonic-gate idx = 3;
42117c478bd9Sstevel@tonic-gate break;
42127c478bd9Sstevel@tonic-gate case NAME_OBJECT:
42137c478bd9Sstevel@tonic-gate case NAME_UNKNOWN:
42147c478bd9Sstevel@tonic-gate /* Nothing to do */
42157c478bd9Sstevel@tonic-gate break;
42167c478bd9Sstevel@tonic-gate }
42177c478bd9Sstevel@tonic-gate
42187c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
42197c478bd9Sstevel@tonic-gate prunlock(dpnp);
42207c478bd9Sstevel@tonic-gate
42217c478bd9Sstevel@tonic-gate if (vp != NULL) {
42227c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_PATH);
42237c478bd9Sstevel@tonic-gate
42247c478bd9Sstevel@tonic-gate pnp->pr_flags |= flags;
42257c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
42267c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
42277c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
42287c478bd9Sstevel@tonic-gate pnp->pr_parent = dp; /* needed for prlookup */
42297c478bd9Sstevel@tonic-gate pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
42307c478bd9Sstevel@tonic-gate VN_HOLD(dp);
42317c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
42327c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
42337c478bd9Sstevel@tonic-gate }
42347c478bd9Sstevel@tonic-gate
42357c478bd9Sstevel@tonic-gate return (vp);
42367c478bd9Sstevel@tonic-gate }
42377c478bd9Sstevel@tonic-gate
42387c478bd9Sstevel@tonic-gate /*
42397c478bd9Sstevel@tonic-gate * Look up one of the process's active templates.
42407c478bd9Sstevel@tonic-gate */
42417c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_tmpldir(vnode_t * dp,char * comp)42427c478bd9Sstevel@tonic-gate pr_lookup_tmpldir(vnode_t *dp, char *comp)
42437c478bd9Sstevel@tonic-gate {
42447c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
42457c478bd9Sstevel@tonic-gate prnode_t *pnp;
42467c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
42477c478bd9Sstevel@tonic-gate proc_t *p;
42487c478bd9Sstevel@tonic-gate int i;
42497c478bd9Sstevel@tonic-gate
42507c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_TMPLDIR);
42517c478bd9Sstevel@tonic-gate
42527c478bd9Sstevel@tonic-gate for (i = 0; i < ct_ntypes; i++)
42537c478bd9Sstevel@tonic-gate if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
42547c478bd9Sstevel@tonic-gate break;
42557c478bd9Sstevel@tonic-gate if (i == ct_ntypes)
42567c478bd9Sstevel@tonic-gate return (NULL);
42577c478bd9Sstevel@tonic-gate
42587c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_TMPL);
42597c478bd9Sstevel@tonic-gate
42607c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
42617c478bd9Sstevel@tonic-gate prfreenode(pnp);
42627c478bd9Sstevel@tonic-gate return (NULL);
42637c478bd9Sstevel@tonic-gate }
42647c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
42657c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas ||
42667c478bd9Sstevel@tonic-gate (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
42677c478bd9Sstevel@tonic-gate prunlock(dpnp);
42687c478bd9Sstevel@tonic-gate prfreenode(pnp);
42697c478bd9Sstevel@tonic-gate return (NULL);
42707c478bd9Sstevel@tonic-gate }
42717c478bd9Sstevel@tonic-gate if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
42727c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
42737c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
42747c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
42757c478bd9Sstevel@tonic-gate pnp->pr_cttype = i;
42767c478bd9Sstevel@tonic-gate VN_HOLD(dp);
42777c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
42787c478bd9Sstevel@tonic-gate } else {
42797c478bd9Sstevel@tonic-gate prfreenode(pnp);
42807c478bd9Sstevel@tonic-gate }
42817c478bd9Sstevel@tonic-gate prunlock(dpnp);
42827c478bd9Sstevel@tonic-gate
42837c478bd9Sstevel@tonic-gate return (vp);
42847c478bd9Sstevel@tonic-gate }
42857c478bd9Sstevel@tonic-gate
42867c478bd9Sstevel@tonic-gate /*
42877c478bd9Sstevel@tonic-gate * Look up one of the contracts owned by the process.
42887c478bd9Sstevel@tonic-gate */
42897c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_ctdir(vnode_t * dp,char * comp)42907c478bd9Sstevel@tonic-gate pr_lookup_ctdir(vnode_t *dp, char *comp)
42917c478bd9Sstevel@tonic-gate {
42927c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
42937c478bd9Sstevel@tonic-gate prnode_t *pnp;
42947c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
42957c478bd9Sstevel@tonic-gate proc_t *p;
42967c478bd9Sstevel@tonic-gate id_t id = 0;
42977c478bd9Sstevel@tonic-gate contract_t *ct;
42987c478bd9Sstevel@tonic-gate int c;
42997c478bd9Sstevel@tonic-gate
43007c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_CTDIR);
43017c478bd9Sstevel@tonic-gate
43027c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
43037c478bd9Sstevel@tonic-gate id_t oid;
43047c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
43057c478bd9Sstevel@tonic-gate return (NULL);
43067c478bd9Sstevel@tonic-gate oid = id;
43077c478bd9Sstevel@tonic-gate id = 10 * id + c - '0';
43087c478bd9Sstevel@tonic-gate if (id / 10 != oid) /* integer overflow */
43097c478bd9Sstevel@tonic-gate return (NULL);
43107c478bd9Sstevel@tonic-gate }
43117c478bd9Sstevel@tonic-gate
43127c478bd9Sstevel@tonic-gate /*
43137c478bd9Sstevel@tonic-gate * Search all contracts; we'll filter below.
43147c478bd9Sstevel@tonic-gate */
43157c478bd9Sstevel@tonic-gate ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
43167c478bd9Sstevel@tonic-gate if (ct == NULL)
43177c478bd9Sstevel@tonic-gate return (NULL);
43187c478bd9Sstevel@tonic-gate
43197c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_CT);
43207c478bd9Sstevel@tonic-gate
43217c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
43227c478bd9Sstevel@tonic-gate prfreenode(pnp);
43237c478bd9Sstevel@tonic-gate contract_rele(ct);
43247c478bd9Sstevel@tonic-gate return (NULL);
43257c478bd9Sstevel@tonic-gate }
43267c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
43277c478bd9Sstevel@tonic-gate /*
43287c478bd9Sstevel@tonic-gate * We only allow lookups of contracts owned by this process, or,
43297c478bd9Sstevel@tonic-gate * if we are zsched and this is a zone's procfs, contracts on
43307c478bd9Sstevel@tonic-gate * stuff in the zone which are held by processes or contracts
43317c478bd9Sstevel@tonic-gate * outside the zone. (see logic in contract_status_common)
43327c478bd9Sstevel@tonic-gate */
43337c478bd9Sstevel@tonic-gate if ((ct->ct_owner != p) &&
4334fa9e4066Sahrens !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4335fa9e4066Sahrens VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4336fa9e4066Sahrens VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
43377c478bd9Sstevel@tonic-gate ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
43387c478bd9Sstevel@tonic-gate prunlock(dpnp);
43397c478bd9Sstevel@tonic-gate prfreenode(pnp);
43407c478bd9Sstevel@tonic-gate contract_rele(ct);
43417c478bd9Sstevel@tonic-gate return (NULL);
43427c478bd9Sstevel@tonic-gate }
43437c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
43447c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
43457c478bd9Sstevel@tonic-gate pnp->pr_contract = ct;
43467c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
43477c478bd9Sstevel@tonic-gate pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
43487c478bd9Sstevel@tonic-gate VN_HOLD(dp);
43497c478bd9Sstevel@tonic-gate prunlock(dpnp);
43507c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
43517c478bd9Sstevel@tonic-gate
43527c478bd9Sstevel@tonic-gate return (vp);
43537c478bd9Sstevel@tonic-gate }
43547c478bd9Sstevel@tonic-gate
43557c478bd9Sstevel@tonic-gate /*
43567c478bd9Sstevel@tonic-gate * Construct an lwp vnode for the old /proc interface.
43577c478bd9Sstevel@tonic-gate * We stand on our head to make the /proc plumbing correct.
43587c478bd9Sstevel@tonic-gate */
43597c478bd9Sstevel@tonic-gate vnode_t *
prlwpnode(prnode_t * pnp,uint_t tid)43607c478bd9Sstevel@tonic-gate prlwpnode(prnode_t *pnp, uint_t tid)
43617c478bd9Sstevel@tonic-gate {
43627c478bd9Sstevel@tonic-gate char comp[12];
43637c478bd9Sstevel@tonic-gate vnode_t *dp;
43647c478bd9Sstevel@tonic-gate vnode_t *vp;
43657c478bd9Sstevel@tonic-gate prcommon_t *pcp;
43667c478bd9Sstevel@tonic-gate proc_t *p;
43677c478bd9Sstevel@tonic-gate
43687c478bd9Sstevel@tonic-gate /*
43697c478bd9Sstevel@tonic-gate * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
43707c478bd9Sstevel@tonic-gate */
43717c478bd9Sstevel@tonic-gate if (pnp->pr_type == PR_PIDFILE) {
43727c478bd9Sstevel@tonic-gate dp = pnp->pr_parent; /* /proc/<pid> */
43737c478bd9Sstevel@tonic-gate VN_HOLD(dp);
43747c478bd9Sstevel@tonic-gate vp = pr_lookup_piddir(dp, "lwp");
43757c478bd9Sstevel@tonic-gate VN_RELE(dp);
43767c478bd9Sstevel@tonic-gate if ((dp = vp) == NULL) /* /proc/<pid>/lwp */
43777c478bd9Sstevel@tonic-gate return (NULL);
43787c478bd9Sstevel@tonic-gate } else if (pnp->pr_type == PR_LWPIDFILE) {
43797c478bd9Sstevel@tonic-gate dp = pnp->pr_parent; /* /proc/<pid>/lwp/<lwpid> */
43807c478bd9Sstevel@tonic-gate dp = VTOP(dp)->pr_parent; /* /proc/<pid>/lwp */
43817c478bd9Sstevel@tonic-gate VN_HOLD(dp);
43827c478bd9Sstevel@tonic-gate } else {
43837c478bd9Sstevel@tonic-gate return (NULL);
43847c478bd9Sstevel@tonic-gate }
43857c478bd9Sstevel@tonic-gate
43867c478bd9Sstevel@tonic-gate (void) pr_u32tos(tid, comp, sizeof (comp));
43877c478bd9Sstevel@tonic-gate vp = pr_lookup_lwpdir(dp, comp);
43887c478bd9Sstevel@tonic-gate VN_RELE(dp);
43897c478bd9Sstevel@tonic-gate if ((dp = vp) == NULL)
43907c478bd9Sstevel@tonic-gate return (NULL);
43917c478bd9Sstevel@tonic-gate
43927c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_LWPIDFILE);
43937c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
43947c478bd9Sstevel@tonic-gate
43957c478bd9Sstevel@tonic-gate /*
43967c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
43977c478bd9Sstevel@tonic-gate * Finish the job.
43987c478bd9Sstevel@tonic-gate */
43997c478bd9Sstevel@tonic-gate pcp = VTOP(dp)->pr_common;
44007c478bd9Sstevel@tonic-gate pnp->pr_ino = ptoi(pcp->prc_pid);
44017c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
44027c478bd9Sstevel@tonic-gate pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
44037c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
44047c478bd9Sstevel@tonic-gate /*
44057c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
44067c478bd9Sstevel@tonic-gate */
44077c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
44087c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
44097c478bd9Sstevel@tonic-gate if (p == NULL) {
44107c478bd9Sstevel@tonic-gate VN_RELE(dp);
44117c478bd9Sstevel@tonic-gate prfreenode(pnp);
44127c478bd9Sstevel@tonic-gate vp = NULL;
44137c478bd9Sstevel@tonic-gate } else if (pcp->prc_thread == NULL) {
44147c478bd9Sstevel@tonic-gate prunlock(pnp);
44157c478bd9Sstevel@tonic-gate VN_RELE(dp);
44167c478bd9Sstevel@tonic-gate prfreenode(pnp);
44177c478bd9Sstevel@tonic-gate vp = NULL;
44187c478bd9Sstevel@tonic-gate } else {
44197c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
44207c478bd9Sstevel@tonic-gate p->p_plist = vp;
44217c478bd9Sstevel@tonic-gate prunlock(pnp);
44227c478bd9Sstevel@tonic-gate }
44237c478bd9Sstevel@tonic-gate
44247c478bd9Sstevel@tonic-gate return (vp);
44257c478bd9Sstevel@tonic-gate }
44267c478bd9Sstevel@tonic-gate
44277c478bd9Sstevel@tonic-gate #if defined(DEBUG)
44287c478bd9Sstevel@tonic-gate
44297c478bd9Sstevel@tonic-gate static uint32_t nprnode;
44307c478bd9Sstevel@tonic-gate static uint32_t nprcommon;
44317c478bd9Sstevel@tonic-gate
44321a5e258fSJosef 'Jeff' Sipek #define INCREMENT(x) atomic_inc_32(&x);
44331a5e258fSJosef 'Jeff' Sipek #define DECREMENT(x) atomic_dec_32(&x);
44347c478bd9Sstevel@tonic-gate
44357c478bd9Sstevel@tonic-gate #else
44367c478bd9Sstevel@tonic-gate
44377c478bd9Sstevel@tonic-gate #define INCREMENT(x)
44387c478bd9Sstevel@tonic-gate #define DECREMENT(x)
44397c478bd9Sstevel@tonic-gate
44407c478bd9Sstevel@tonic-gate #endif /* DEBUG */
44417c478bd9Sstevel@tonic-gate
44427c478bd9Sstevel@tonic-gate /*
44437c478bd9Sstevel@tonic-gate * New /proc vnode required; allocate it and fill in most of the fields.
44447c478bd9Sstevel@tonic-gate */
44457c478bd9Sstevel@tonic-gate prnode_t *
prgetnode(vnode_t * dp,prnodetype_t type)44467c478bd9Sstevel@tonic-gate prgetnode(vnode_t *dp, prnodetype_t type)
44477c478bd9Sstevel@tonic-gate {
44487c478bd9Sstevel@tonic-gate prnode_t *pnp;
44497c478bd9Sstevel@tonic-gate prcommon_t *pcp;
44507c478bd9Sstevel@tonic-gate vnode_t *vp;
44517c478bd9Sstevel@tonic-gate ulong_t nfiles;
44527c478bd9Sstevel@tonic-gate
44537c478bd9Sstevel@tonic-gate INCREMENT(nprnode);
44547c478bd9Sstevel@tonic-gate pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
44557c478bd9Sstevel@tonic-gate
44567c478bd9Sstevel@tonic-gate mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
44577c478bd9Sstevel@tonic-gate pnp->pr_type = type;
44587c478bd9Sstevel@tonic-gate
44597c478bd9Sstevel@tonic-gate pnp->pr_vnode = vn_alloc(KM_SLEEP);
44607c478bd9Sstevel@tonic-gate
44617c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
44627c478bd9Sstevel@tonic-gate vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
44637c478bd9Sstevel@tonic-gate vn_setops(vp, prvnodeops);
44647c478bd9Sstevel@tonic-gate vp->v_vfsp = dp->v_vfsp;
44657c478bd9Sstevel@tonic-gate vp->v_type = VPROC;
44667c478bd9Sstevel@tonic-gate vp->v_data = (caddr_t)pnp;
44677c478bd9Sstevel@tonic-gate
44687c478bd9Sstevel@tonic-gate switch (type) {
44697c478bd9Sstevel@tonic-gate case PR_PIDDIR:
44707c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
44717c478bd9Sstevel@tonic-gate /*
44727c478bd9Sstevel@tonic-gate * We need a prcommon and a files array for each of these.
44737c478bd9Sstevel@tonic-gate */
44747c478bd9Sstevel@tonic-gate INCREMENT(nprcommon);
44757c478bd9Sstevel@tonic-gate
44767c478bd9Sstevel@tonic-gate pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
44777c478bd9Sstevel@tonic-gate pcp->prc_refcnt = 1;
44787c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
44797c478bd9Sstevel@tonic-gate mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
44807c478bd9Sstevel@tonic-gate cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
44817c478bd9Sstevel@tonic-gate
44827c478bd9Sstevel@tonic-gate nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
44837c478bd9Sstevel@tonic-gate pnp->pr_files =
44847c478bd9Sstevel@tonic-gate kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
44857c478bd9Sstevel@tonic-gate
44867c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
44877c478bd9Sstevel@tonic-gate /*
44887c478bd9Sstevel@tonic-gate * Mode should be read-search by all, but we cannot so long
44897c478bd9Sstevel@tonic-gate * as we must support compatibility mode with old /proc.
44907c478bd9Sstevel@tonic-gate * Make /proc/<pid> be read by owner only, search by all.
44917c478bd9Sstevel@tonic-gate * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
44927c478bd9Sstevel@tonic-gate * set VDIROPEN on /proc/<pid> so it can be opened for writing.
44937c478bd9Sstevel@tonic-gate */
44947c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR) {
44957c478bd9Sstevel@tonic-gate /* kludge for old /proc interface */
44967c478bd9Sstevel@tonic-gate prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
44977c478bd9Sstevel@tonic-gate pnp->pr_pidfile = PTOV(xpnp);
44987c478bd9Sstevel@tonic-gate pnp->pr_mode = 0511;
44997c478bd9Sstevel@tonic-gate vp->v_flag |= VDIROPEN;
45007c478bd9Sstevel@tonic-gate } else {
45017c478bd9Sstevel@tonic-gate pnp->pr_mode = 0555;
45027c478bd9Sstevel@tonic-gate }
45037c478bd9Sstevel@tonic-gate
45047c478bd9Sstevel@tonic-gate break;
45057c478bd9Sstevel@tonic-gate
45067c478bd9Sstevel@tonic-gate case PR_CURDIR:
45077c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
45087c478bd9Sstevel@tonic-gate case PR_FDDIR:
45097c478bd9Sstevel@tonic-gate case PR_OBJECTDIR:
45107c478bd9Sstevel@tonic-gate case PR_PATHDIR:
45117c478bd9Sstevel@tonic-gate case PR_CTDIR:
45127c478bd9Sstevel@tonic-gate case PR_TMPLDIR:
45137c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
45147c478bd9Sstevel@tonic-gate pnp->pr_mode = 0500; /* read-search by owner only */
45157c478bd9Sstevel@tonic-gate break;
45167c478bd9Sstevel@tonic-gate
45177c478bd9Sstevel@tonic-gate case PR_CT:
45187c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
45197c478bd9Sstevel@tonic-gate pnp->pr_mode = 0500; /* read-search by owner only */
45207c478bd9Sstevel@tonic-gate break;
45217c478bd9Sstevel@tonic-gate
45227c478bd9Sstevel@tonic-gate case PR_PATH:
45237c478bd9Sstevel@tonic-gate case PR_SELF:
45247c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
45257c478bd9Sstevel@tonic-gate pnp->pr_mode = 0777;
45267c478bd9Sstevel@tonic-gate break;
45277c478bd9Sstevel@tonic-gate
45287c478bd9Sstevel@tonic-gate case PR_LWPDIR:
45297c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
45307c478bd9Sstevel@tonic-gate pnp->pr_mode = 0555; /* read-search by all */
45317c478bd9Sstevel@tonic-gate break;
45327c478bd9Sstevel@tonic-gate
45337c478bd9Sstevel@tonic-gate case PR_AS:
45347c478bd9Sstevel@tonic-gate case PR_TMPL:
45357c478bd9Sstevel@tonic-gate pnp->pr_mode = 0600; /* read-write by owner only */
45367c478bd9Sstevel@tonic-gate break;
45377c478bd9Sstevel@tonic-gate
45387c478bd9Sstevel@tonic-gate case PR_CTL:
45397c478bd9Sstevel@tonic-gate case PR_LWPCTL:
45407c478bd9Sstevel@tonic-gate pnp->pr_mode = 0200; /* write-only by owner only */
45417c478bd9Sstevel@tonic-gate break;
45427c478bd9Sstevel@tonic-gate
45437c478bd9Sstevel@tonic-gate case PR_PIDFILE:
45447c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
45457c478bd9Sstevel@tonic-gate pnp->pr_mode = 0600; /* read-write by owner only */
45467c478bd9Sstevel@tonic-gate break;
45477c478bd9Sstevel@tonic-gate
45487c478bd9Sstevel@tonic-gate case PR_PSINFO:
45497c478bd9Sstevel@tonic-gate case PR_LPSINFO:
45507c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
45517c478bd9Sstevel@tonic-gate case PR_USAGE:
45527c478bd9Sstevel@tonic-gate case PR_LUSAGE:
45537c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
45547c478bd9Sstevel@tonic-gate pnp->pr_mode = 0444; /* read-only by all */
45557c478bd9Sstevel@tonic-gate break;
45567c478bd9Sstevel@tonic-gate
45577c478bd9Sstevel@tonic-gate default:
45587c478bd9Sstevel@tonic-gate pnp->pr_mode = 0400; /* read-only by owner only */
45597c478bd9Sstevel@tonic-gate break;
45607c478bd9Sstevel@tonic-gate }
45617c478bd9Sstevel@tonic-gate vn_exists(vp);
45627c478bd9Sstevel@tonic-gate return (pnp);
45637c478bd9Sstevel@tonic-gate }
45647c478bd9Sstevel@tonic-gate
45657c478bd9Sstevel@tonic-gate /*
45667c478bd9Sstevel@tonic-gate * Free the storage obtained from prgetnode().
45677c478bd9Sstevel@tonic-gate */
45687c478bd9Sstevel@tonic-gate void
prfreenode(prnode_t * pnp)45697c478bd9Sstevel@tonic-gate prfreenode(prnode_t *pnp)
45707c478bd9Sstevel@tonic-gate {
45717c478bd9Sstevel@tonic-gate vnode_t *vp;
45727c478bd9Sstevel@tonic-gate ulong_t nfiles;
45737c478bd9Sstevel@tonic-gate
45747c478bd9Sstevel@tonic-gate vn_invalid(PTOV(pnp));
45757c478bd9Sstevel@tonic-gate vn_free(PTOV(pnp));
45767c478bd9Sstevel@tonic-gate mutex_destroy(&pnp->pr_mutex);
45777c478bd9Sstevel@tonic-gate
45787c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
45797c478bd9Sstevel@tonic-gate case PR_PIDDIR:
45807c478bd9Sstevel@tonic-gate /* kludge for old /proc interface */
45817c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
45827c478bd9Sstevel@tonic-gate prfreenode(VTOP(pnp->pr_pidfile));
45837c478bd9Sstevel@tonic-gate pnp->pr_pidfile = NULL;
45847c478bd9Sstevel@tonic-gate }
45857c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
45867c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
45877c478bd9Sstevel@tonic-gate /*
45887c478bd9Sstevel@tonic-gate * We allocated a prcommon and a files array for each of these.
45897c478bd9Sstevel@tonic-gate */
45907c478bd9Sstevel@tonic-gate prfreecommon(pnp->pr_common);
45917c478bd9Sstevel@tonic-gate nfiles = (pnp->pr_type == PR_PIDDIR)?
45927c478bd9Sstevel@tonic-gate NPIDDIRFILES : NLWPIDDIRFILES;
45937c478bd9Sstevel@tonic-gate kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
45947c478bd9Sstevel@tonic-gate break;
45957c478bd9Sstevel@tonic-gate default:
45967c478bd9Sstevel@tonic-gate break;
45977c478bd9Sstevel@tonic-gate }
45987c478bd9Sstevel@tonic-gate /*
45997c478bd9Sstevel@tonic-gate * If there is an underlying vnode, be sure
46007c478bd9Sstevel@tonic-gate * to release it after freeing the prnode.
46017c478bd9Sstevel@tonic-gate */
46027c478bd9Sstevel@tonic-gate vp = pnp->pr_realvp;
46037c478bd9Sstevel@tonic-gate kmem_free(pnp, sizeof (*pnp));
46047c478bd9Sstevel@tonic-gate DECREMENT(nprnode);
46057c478bd9Sstevel@tonic-gate if (vp != NULL) {
46067c478bd9Sstevel@tonic-gate VN_RELE(vp);
46077c478bd9Sstevel@tonic-gate }
46087c478bd9Sstevel@tonic-gate }
46097c478bd9Sstevel@tonic-gate
46107c478bd9Sstevel@tonic-gate /*
4611da6c28aaSamw * Free a prcommon structure, if the reference count reaches zero.
46127c478bd9Sstevel@tonic-gate */
46137c478bd9Sstevel@tonic-gate static void
prfreecommon(prcommon_t * pcp)46147c478bd9Sstevel@tonic-gate prfreecommon(prcommon_t *pcp)
46157c478bd9Sstevel@tonic-gate {
46167c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
46177c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
46187c478bd9Sstevel@tonic-gate if (--pcp->prc_refcnt != 0)
46197c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
46207c478bd9Sstevel@tonic-gate else {
46217c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
46227c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_pollhead.ph_list == NULL);
46237c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt == 0);
46247c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
46257c478bd9Sstevel@tonic-gate mutex_destroy(&pcp->prc_mutex);
46267c478bd9Sstevel@tonic-gate cv_destroy(&pcp->prc_wait);
46277c478bd9Sstevel@tonic-gate kmem_free(pcp, sizeof (prcommon_t));
46287c478bd9Sstevel@tonic-gate DECREMENT(nprcommon);
46297c478bd9Sstevel@tonic-gate }
46307c478bd9Sstevel@tonic-gate }
46317c478bd9Sstevel@tonic-gate
46327c478bd9Sstevel@tonic-gate /*
46337c478bd9Sstevel@tonic-gate * Array of readdir functions, indexed by /proc file type.
46347c478bd9Sstevel@tonic-gate */
46357c478bd9Sstevel@tonic-gate static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
46367c478bd9Sstevel@tonic-gate pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
46377c478bd9Sstevel@tonic-gate pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
46387c478bd9Sstevel@tonic-gate pr_readdir_ctdir();
46397c478bd9Sstevel@tonic-gate
46407c478bd9Sstevel@tonic-gate static int (*pr_readdir_function[PR_NFILES])() = {
46417c478bd9Sstevel@tonic-gate pr_readdir_procdir, /* /proc */
46427c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/self */
46437c478bd9Sstevel@tonic-gate pr_readdir_piddir, /* /proc/<pid> */
46447c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/as */
46457c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/ctl */
46467c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/status */
46477c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lstatus */
46487c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/psinfo */
46497c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
46507c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/map */
46517c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/rmap */
46527c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/xmap */
46537c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/cred */
46547c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/sigact */
46557c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/auxv */
46567c478bd9Sstevel@tonic-gate #if defined(__x86)
46577c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/ldt */
46587c478bd9Sstevel@tonic-gate #endif
46597c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/usage */
46607c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lusage */
46617c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/pagedata */
46627c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/watch */
46637c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/cwd */
46647c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/root */
46657c478bd9Sstevel@tonic-gate pr_readdir_fddir, /* /proc/<pid>/fd */
46667c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/fd/nn */
46677c478bd9Sstevel@tonic-gate pr_readdir_objectdir, /* /proc/<pid>/object */
46687c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/object/xxx */
46697c478bd9Sstevel@tonic-gate pr_readdir_lwpdir, /* /proc/<pid>/lwp */
46707c478bd9Sstevel@tonic-gate pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
46717c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
46727c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
46737c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
46747c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
46757c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
46767c478bd9Sstevel@tonic-gate pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
46777c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4678f971a346SBryan Cantrill pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
46797c478bd9Sstevel@tonic-gate #if defined(__sparc)
46807c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
46817c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
46827c478bd9Sstevel@tonic-gate #endif
46837c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/priv */
46847c478bd9Sstevel@tonic-gate pr_readdir_pathdir, /* /proc/<pid>/path */
46857c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/path/xxx */
46867c478bd9Sstevel@tonic-gate pr_readdir_ctdir, /* /proc/<pid>/contracts */
46877c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/contracts/<ctid> */
46887c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old process file */
46897c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old lwp file */
46907c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old pagedata file */
46917c478bd9Sstevel@tonic-gate };
46927c478bd9Sstevel@tonic-gate
46937c478bd9Sstevel@tonic-gate /* ARGSUSED */
46947c478bd9Sstevel@tonic-gate static int
prreaddir(vnode_t * vp,uio_t * uiop,cred_t * cr,int * eofp,caller_context_t * ct,int flags)4695da6c28aaSamw prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
4696da6c28aaSamw caller_context_t *ct, int flags)
46977c478bd9Sstevel@tonic-gate {
46987c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
46997c478bd9Sstevel@tonic-gate
47007c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
47017c478bd9Sstevel@tonic-gate
4702da6c28aaSamw /* XXX - Do we need to pass ct and flags? */
47037c478bd9Sstevel@tonic-gate return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
47047c478bd9Sstevel@tonic-gate }
47057c478bd9Sstevel@tonic-gate
47067c478bd9Sstevel@tonic-gate /* ARGSUSED */
47077c478bd9Sstevel@tonic-gate static int
pr_readdir_notdir(prnode_t * pnp,uio_t * uiop,int * eofp)47087c478bd9Sstevel@tonic-gate pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
47097c478bd9Sstevel@tonic-gate {
47107c478bd9Sstevel@tonic-gate return (ENOTDIR);
47117c478bd9Sstevel@tonic-gate }
47127c478bd9Sstevel@tonic-gate
47137c478bd9Sstevel@tonic-gate /* ARGSUSED */
47147c478bd9Sstevel@tonic-gate static int
pr_readdir_procdir(prnode_t * pnp,uio_t * uiop,int * eofp)47157c478bd9Sstevel@tonic-gate pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
47167c478bd9Sstevel@tonic-gate {
47177c478bd9Sstevel@tonic-gate zoneid_t zoneid;
47187c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
47197c478bd9Sstevel@tonic-gate int error, eof = 0;
47207c478bd9Sstevel@tonic-gate offset_t n;
47217c478bd9Sstevel@tonic-gate
47227c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PROCDIR);
47237c478bd9Sstevel@tonic-gate
4724fa9e4066Sahrens zoneid = VTOZONE(PTOV(pnp))->zone_id;
47257c478bd9Sstevel@tonic-gate
47267c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
4727b38f0970Sck153898 PRROOTINO, PRROOTINO, 0)) != 0)
47287c478bd9Sstevel@tonic-gate return (error);
47297c478bd9Sstevel@tonic-gate
47307c478bd9Sstevel@tonic-gate /*
47317c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until all processes
47327c478bd9Sstevel@tonic-gate * have been examined.
47337c478bd9Sstevel@tonic-gate */
47347c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
47357c478bd9Sstevel@tonic-gate uint_t pid;
47367c478bd9Sstevel@tonic-gate int pslot;
47377c478bd9Sstevel@tonic-gate proc_t *p;
47387c478bd9Sstevel@tonic-gate
47397c478bd9Sstevel@tonic-gate /*
47407c478bd9Sstevel@tonic-gate * Find next entry. Skip processes not visible where
47417c478bd9Sstevel@tonic-gate * this /proc was mounted.
47427c478bd9Sstevel@tonic-gate */
47437c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
47447c478bd9Sstevel@tonic-gate while (n < v.v_proc &&
47457c478bd9Sstevel@tonic-gate ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
47467c478bd9Sstevel@tonic-gate (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
47477c478bd9Sstevel@tonic-gate secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
47487c478bd9Sstevel@tonic-gate n++;
47497c478bd9Sstevel@tonic-gate
47507c478bd9Sstevel@tonic-gate /*
47517c478bd9Sstevel@tonic-gate * Stop when entire proc table has been examined.
47527c478bd9Sstevel@tonic-gate */
47537c478bd9Sstevel@tonic-gate if (n >= v.v_proc) {
47547c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
47557c478bd9Sstevel@tonic-gate eof = 1;
47567c478bd9Sstevel@tonic-gate break;
47577c478bd9Sstevel@tonic-gate }
47587c478bd9Sstevel@tonic-gate
47597c478bd9Sstevel@tonic-gate ASSERT(p->p_stat != 0);
47607c478bd9Sstevel@tonic-gate pid = p->p_pid;
47617c478bd9Sstevel@tonic-gate pslot = p->p_slot;
47627c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
47637c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, n,
47647c478bd9Sstevel@tonic-gate pmkino(0, pslot, PR_PIDDIR), pid);
47657c478bd9Sstevel@tonic-gate if (error)
47667c478bd9Sstevel@tonic-gate break;
47677c478bd9Sstevel@tonic-gate }
47687c478bd9Sstevel@tonic-gate
47697c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
47707c478bd9Sstevel@tonic-gate }
47717c478bd9Sstevel@tonic-gate
47727c478bd9Sstevel@tonic-gate /* ARGSUSED */
47737c478bd9Sstevel@tonic-gate static int
pr_readdir_piddir(prnode_t * pnp,uio_t * uiop,int * eofp)47747c478bd9Sstevel@tonic-gate pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
47757c478bd9Sstevel@tonic-gate {
47767c478bd9Sstevel@tonic-gate int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
47777c478bd9Sstevel@tonic-gate prdirent_t dirent;
47787c478bd9Sstevel@tonic-gate prdirent_t *dirp;
47797c478bd9Sstevel@tonic-gate offset_t off;
47807c478bd9Sstevel@tonic-gate int error;
47817c478bd9Sstevel@tonic-gate
47827c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
47837c478bd9Sstevel@tonic-gate
47847c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
47857c478bd9Sstevel@tonic-gate uiop->uio_offset % sizeof (prdirent_t) != 0 ||
47867c478bd9Sstevel@tonic-gate uiop->uio_resid < sizeof (prdirent_t))
47877c478bd9Sstevel@tonic-gate return (EINVAL);
47887c478bd9Sstevel@tonic-gate if (pnp->pr_pcommon->prc_proc == NULL)
47897c478bd9Sstevel@tonic-gate return (ENOENT);
47907c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (piddir))
47917c478bd9Sstevel@tonic-gate goto out;
47927c478bd9Sstevel@tonic-gate
47937c478bd9Sstevel@tonic-gate /*
47947c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied, omitting some
47957c478bd9Sstevel@tonic-gate * files along the way if the process is a zombie.
47967c478bd9Sstevel@tonic-gate */
47977c478bd9Sstevel@tonic-gate for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
47987c478bd9Sstevel@tonic-gate uiop->uio_resid >= sizeof (prdirent_t) &&
47997c478bd9Sstevel@tonic-gate dirp < &piddir[NPIDDIRFILES+2];
48007c478bd9Sstevel@tonic-gate uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
48017c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
48027c478bd9Sstevel@tonic-gate if (zombie) {
48037c478bd9Sstevel@tonic-gate switch (dirp->d_ino) {
48047c478bd9Sstevel@tonic-gate case PR_PIDDIR:
48057c478bd9Sstevel@tonic-gate case PR_PROCDIR:
48067c478bd9Sstevel@tonic-gate case PR_PSINFO:
48077c478bd9Sstevel@tonic-gate case PR_USAGE:
48087c478bd9Sstevel@tonic-gate break;
48097c478bd9Sstevel@tonic-gate default:
48107c478bd9Sstevel@tonic-gate continue;
48117c478bd9Sstevel@tonic-gate }
48127c478bd9Sstevel@tonic-gate }
48137c478bd9Sstevel@tonic-gate bcopy(dirp, &dirent, sizeof (prdirent_t));
48147c478bd9Sstevel@tonic-gate if (dirent.d_ino == PR_PROCDIR)
48157c478bd9Sstevel@tonic-gate dirent.d_ino = PRROOTINO;
48167c478bd9Sstevel@tonic-gate else
48177c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
48187c478bd9Sstevel@tonic-gate dirent.d_ino);
48197c478bd9Sstevel@tonic-gate if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
48207c478bd9Sstevel@tonic-gate UIO_READ, uiop)) != 0)
48217c478bd9Sstevel@tonic-gate return (error);
48227c478bd9Sstevel@tonic-gate }
48237c478bd9Sstevel@tonic-gate out:
48247c478bd9Sstevel@tonic-gate if (eofp)
48257c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= sizeof (piddir));
48267c478bd9Sstevel@tonic-gate return (0);
48277c478bd9Sstevel@tonic-gate }
48287c478bd9Sstevel@tonic-gate
48297c478bd9Sstevel@tonic-gate static void
rebuild_objdir(struct as * as)48307c478bd9Sstevel@tonic-gate rebuild_objdir(struct as *as)
48317c478bd9Sstevel@tonic-gate {
48327c478bd9Sstevel@tonic-gate struct seg *seg;
48337c478bd9Sstevel@tonic-gate vnode_t *vp;
48347c478bd9Sstevel@tonic-gate vattr_t vattr;
48357c478bd9Sstevel@tonic-gate vnode_t **dir;
48367c478bd9Sstevel@tonic-gate ulong_t nalloc;
48377c478bd9Sstevel@tonic-gate ulong_t nentries;
48387c478bd9Sstevel@tonic-gate int i, j;
48397c478bd9Sstevel@tonic-gate ulong_t nold, nnew;
48407c478bd9Sstevel@tonic-gate
4841*fd435bccSJosef 'Jeff' Sipek ASSERT(AS_WRITE_HELD(as));
48427c478bd9Sstevel@tonic-gate
48437c478bd9Sstevel@tonic-gate if (as->a_updatedir == 0 && as->a_objectdir != NULL)
48447c478bd9Sstevel@tonic-gate return;
48457c478bd9Sstevel@tonic-gate as->a_updatedir = 0;
48467c478bd9Sstevel@tonic-gate
48477c478bd9Sstevel@tonic-gate if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
48487c478bd9Sstevel@tonic-gate (seg = AS_SEGFIRST(as)) == NULL) /* can't happen? */
48497c478bd9Sstevel@tonic-gate return;
48507c478bd9Sstevel@tonic-gate
48517c478bd9Sstevel@tonic-gate /*
48527c478bd9Sstevel@tonic-gate * Allocate space for the new object directory.
48537c478bd9Sstevel@tonic-gate * (This is usually about two times too many entries.)
48547c478bd9Sstevel@tonic-gate */
48557c478bd9Sstevel@tonic-gate nalloc = (nalloc + 0xf) & ~0xf; /* multiple of 16 */
48567c478bd9Sstevel@tonic-gate dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
48577c478bd9Sstevel@tonic-gate
48587c478bd9Sstevel@tonic-gate /* fill in the new directory with desired entries */
48597c478bd9Sstevel@tonic-gate nentries = 0;
48607c478bd9Sstevel@tonic-gate do {
48617c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
48627c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
48637c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
48647c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
4865da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
48667c478bd9Sstevel@tonic-gate for (i = 0; i < nentries; i++)
48677c478bd9Sstevel@tonic-gate if (vp == dir[i])
48687c478bd9Sstevel@tonic-gate break;
48697c478bd9Sstevel@tonic-gate if (i == nentries) {
48707c478bd9Sstevel@tonic-gate ASSERT(nentries < nalloc);
48717c478bd9Sstevel@tonic-gate dir[nentries++] = vp;
48727c478bd9Sstevel@tonic-gate }
48737c478bd9Sstevel@tonic-gate }
48747c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
48757c478bd9Sstevel@tonic-gate
48767c478bd9Sstevel@tonic-gate if (as->a_objectdir == NULL) { /* first time */
48777c478bd9Sstevel@tonic-gate as->a_objectdir = dir;
48787c478bd9Sstevel@tonic-gate as->a_sizedir = nalloc;
48797c478bd9Sstevel@tonic-gate return;
48807c478bd9Sstevel@tonic-gate }
48817c478bd9Sstevel@tonic-gate
48827c478bd9Sstevel@tonic-gate /*
48837c478bd9Sstevel@tonic-gate * Null out all of the defunct entries in the old directory.
48847c478bd9Sstevel@tonic-gate */
48857c478bd9Sstevel@tonic-gate nold = 0;
48867c478bd9Sstevel@tonic-gate nnew = nentries;
48877c478bd9Sstevel@tonic-gate for (i = 0; i < as->a_sizedir; i++) {
48887c478bd9Sstevel@tonic-gate if ((vp = as->a_objectdir[i]) != NULL) {
48897c478bd9Sstevel@tonic-gate for (j = 0; j < nentries; j++) {
48907c478bd9Sstevel@tonic-gate if (vp == dir[j]) {
48917c478bd9Sstevel@tonic-gate dir[j] = NULL;
48927c478bd9Sstevel@tonic-gate nnew--;
48937c478bd9Sstevel@tonic-gate break;
48947c478bd9Sstevel@tonic-gate }
48957c478bd9Sstevel@tonic-gate }
48967c478bd9Sstevel@tonic-gate if (j == nentries)
48977c478bd9Sstevel@tonic-gate as->a_objectdir[i] = NULL;
48987c478bd9Sstevel@tonic-gate else
48997c478bd9Sstevel@tonic-gate nold++;
49007c478bd9Sstevel@tonic-gate }
49017c478bd9Sstevel@tonic-gate }
49027c478bd9Sstevel@tonic-gate
49037c478bd9Sstevel@tonic-gate if (nold + nnew > as->a_sizedir) {
49047c478bd9Sstevel@tonic-gate /*
49057c478bd9Sstevel@tonic-gate * Reallocate the old directory to have enough
49067c478bd9Sstevel@tonic-gate * space for the old and new entries combined.
49077c478bd9Sstevel@tonic-gate * Round up to the next multiple of 16.
49087c478bd9Sstevel@tonic-gate */
49097c478bd9Sstevel@tonic-gate ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
49107c478bd9Sstevel@tonic-gate vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
49117c478bd9Sstevel@tonic-gate KM_SLEEP);
49127c478bd9Sstevel@tonic-gate bcopy(as->a_objectdir, newdir,
49137c478bd9Sstevel@tonic-gate as->a_sizedir * sizeof (vnode_t *));
49147c478bd9Sstevel@tonic-gate kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
49157c478bd9Sstevel@tonic-gate as->a_objectdir = newdir;
49167c478bd9Sstevel@tonic-gate as->a_sizedir = newsize;
49177c478bd9Sstevel@tonic-gate }
49187c478bd9Sstevel@tonic-gate
49197c478bd9Sstevel@tonic-gate /*
49207c478bd9Sstevel@tonic-gate * Move all new entries to the old directory and
49217c478bd9Sstevel@tonic-gate * deallocate the space used by the new directory.
49227c478bd9Sstevel@tonic-gate */
49237c478bd9Sstevel@tonic-gate if (nnew) {
49247c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < nentries; i++) {
49257c478bd9Sstevel@tonic-gate if ((vp = dir[i]) == NULL)
49267c478bd9Sstevel@tonic-gate continue;
49277c478bd9Sstevel@tonic-gate for (; j < as->a_sizedir; j++) {
49287c478bd9Sstevel@tonic-gate if (as->a_objectdir[j] != NULL)
49297c478bd9Sstevel@tonic-gate continue;
49307c478bd9Sstevel@tonic-gate as->a_objectdir[j++] = vp;
49317c478bd9Sstevel@tonic-gate break;
49327c478bd9Sstevel@tonic-gate }
49337c478bd9Sstevel@tonic-gate }
49347c478bd9Sstevel@tonic-gate }
49357c478bd9Sstevel@tonic-gate kmem_free(dir, nalloc * sizeof (vnode_t *));
49367c478bd9Sstevel@tonic-gate }
49377c478bd9Sstevel@tonic-gate
49387c478bd9Sstevel@tonic-gate /*
49397c478bd9Sstevel@tonic-gate * Return the vnode from a slot in the process's object directory.
49407c478bd9Sstevel@tonic-gate * The caller must have locked the process's address space.
49417c478bd9Sstevel@tonic-gate * The only caller is below, in pr_readdir_objectdir().
49427c478bd9Sstevel@tonic-gate */
49437c478bd9Sstevel@tonic-gate static vnode_t *
obj_entry(struct as * as,int slot)49447c478bd9Sstevel@tonic-gate obj_entry(struct as *as, int slot)
49457c478bd9Sstevel@tonic-gate {
4946*fd435bccSJosef 'Jeff' Sipek ASSERT(AS_LOCK_HELD(as));
49477c478bd9Sstevel@tonic-gate if (as->a_objectdir == NULL)
49487c478bd9Sstevel@tonic-gate return (NULL);
49497c478bd9Sstevel@tonic-gate ASSERT(slot < as->a_sizedir);
49507c478bd9Sstevel@tonic-gate return (as->a_objectdir[slot]);
49517c478bd9Sstevel@tonic-gate }
49527c478bd9Sstevel@tonic-gate
49537c478bd9Sstevel@tonic-gate /* ARGSUSED */
49547c478bd9Sstevel@tonic-gate static int
pr_readdir_objectdir(prnode_t * pnp,uio_t * uiop,int * eofp)49557c478bd9Sstevel@tonic-gate pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
49567c478bd9Sstevel@tonic-gate {
49577c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
49587c478bd9Sstevel@tonic-gate int error, eof = 0;
49597c478bd9Sstevel@tonic-gate offset_t n;
49607c478bd9Sstevel@tonic-gate int pslot;
49617c478bd9Sstevel@tonic-gate size_t objdirsize;
49627c478bd9Sstevel@tonic-gate proc_t *p;
49637c478bd9Sstevel@tonic-gate struct as *as;
49647c478bd9Sstevel@tonic-gate vnode_t *vp;
49657c478bd9Sstevel@tonic-gate
49667c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OBJECTDIR);
49677c478bd9Sstevel@tonic-gate
49687c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
49697c478bd9Sstevel@tonic-gate return (error);
49707c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
49717c478bd9Sstevel@tonic-gate pslot = p->p_slot;
49727c478bd9Sstevel@tonic-gate
49737c478bd9Sstevel@tonic-gate /*
49747c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
49757c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
49767c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
49777c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
49787c478bd9Sstevel@tonic-gate */
49797c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
49807c478bd9Sstevel@tonic-gate
49817c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
49827c478bd9Sstevel@tonic-gate pmkino(0, pslot, PR_PIDDIR),
4983b38f0970Sck153898 pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
49847c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
49857c478bd9Sstevel@tonic-gate prunlock(pnp);
49867c478bd9Sstevel@tonic-gate return (error);
49877c478bd9Sstevel@tonic-gate }
49887c478bd9Sstevel@tonic-gate
49897c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
49907c478bd9Sstevel@tonic-gate as = NULL;
49917c478bd9Sstevel@tonic-gate objdirsize = 0;
499243d09bd4Spetede }
499343d09bd4Spetede
499443d09bd4Spetede /*
499543d09bd4Spetede * Loop until user's request is satisfied or until
499643d09bd4Spetede * all mapped objects have been examined. Cannot hold
499743d09bd4Spetede * the address space lock for the following call as
499843d09bd4Spetede * gfs_readdir_pred() utimately causes a call to uiomove().
499943d09bd4Spetede */
500043d09bd4Spetede while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
500143d09bd4Spetede vattr_t vattr;
500243d09bd4Spetede char str[64];
500343d09bd4Spetede
500443d09bd4Spetede /*
500543d09bd4Spetede * Set the correct size of the directory just
500643d09bd4Spetede * in case the process has changed it's address
500743d09bd4Spetede * space via mmap/munmap calls.
500843d09bd4Spetede */
500943d09bd4Spetede if (as != NULL) {
5010*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
50117c478bd9Sstevel@tonic-gate if (as->a_updatedir)
50127c478bd9Sstevel@tonic-gate rebuild_objdir(as);
50137c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
50147c478bd9Sstevel@tonic-gate }
50157c478bd9Sstevel@tonic-gate
50167c478bd9Sstevel@tonic-gate /*
50177c478bd9Sstevel@tonic-gate * Find next object.
50187c478bd9Sstevel@tonic-gate */
50197c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID | AT_NODEID;
50207c478bd9Sstevel@tonic-gate while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
5021da6c28aaSamw (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)
5022da6c28aaSamw != 0))) {
50237c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID | AT_NODEID;
50247c478bd9Sstevel@tonic-gate n++;
50257c478bd9Sstevel@tonic-gate }
50267c478bd9Sstevel@tonic-gate
502743d09bd4Spetede if (as != NULL)
5028*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
502943d09bd4Spetede
50307c478bd9Sstevel@tonic-gate /*
50317c478bd9Sstevel@tonic-gate * Stop when all objects have been reported.
50327c478bd9Sstevel@tonic-gate */
50337c478bd9Sstevel@tonic-gate if (n >= objdirsize) {
50347c478bd9Sstevel@tonic-gate eof = 1;
50357c478bd9Sstevel@tonic-gate break;
50367c478bd9Sstevel@tonic-gate }
50377c478bd9Sstevel@tonic-gate
50387c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
50397c478bd9Sstevel@tonic-gate (void) strcpy(str, "a.out");
50407c478bd9Sstevel@tonic-gate else
50417c478bd9Sstevel@tonic-gate pr_object_name(str, vp, &vattr);
50427c478bd9Sstevel@tonic-gate
50437c478bd9Sstevel@tonic-gate error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
5044b38f0970Sck153898 str, 0);
504543d09bd4Spetede
50467c478bd9Sstevel@tonic-gate if (error)
50477c478bd9Sstevel@tonic-gate break;
50487c478bd9Sstevel@tonic-gate }
50497c478bd9Sstevel@tonic-gate
50507c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
50517c478bd9Sstevel@tonic-gate prunlock(pnp);
50527c478bd9Sstevel@tonic-gate
50537c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
50547c478bd9Sstevel@tonic-gate }
50557c478bd9Sstevel@tonic-gate
50567c478bd9Sstevel@tonic-gate /* ARGSUSED */
50577c478bd9Sstevel@tonic-gate static int
pr_readdir_lwpdir(prnode_t * pnp,uio_t * uiop,int * eofp)50587c478bd9Sstevel@tonic-gate pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
50597c478bd9Sstevel@tonic-gate {
50607c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
50617c478bd9Sstevel@tonic-gate int error, eof = 0;
50627c478bd9Sstevel@tonic-gate offset_t tslot;
50637c478bd9Sstevel@tonic-gate proc_t *p;
50647c478bd9Sstevel@tonic-gate int pslot;
50657c478bd9Sstevel@tonic-gate lwpdir_t *lwpdir;
50667c478bd9Sstevel@tonic-gate int lwpdirsize;
50677c478bd9Sstevel@tonic-gate
50687c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPDIR);
50697c478bd9Sstevel@tonic-gate
50707c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
50717c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
50727c478bd9Sstevel@tonic-gate if (p == NULL)
50737c478bd9Sstevel@tonic-gate return (ENOENT);
50747c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
50757c478bd9Sstevel@tonic-gate pslot = p->p_slot;
50767c478bd9Sstevel@tonic-gate lwpdir = p->p_lwpdir;
50777c478bd9Sstevel@tonic-gate lwpdirsize = p->p_lwpdir_sz;
50787c478bd9Sstevel@tonic-gate
50797c478bd9Sstevel@tonic-gate /*
50807c478bd9Sstevel@tonic-gate * Drop p->p_lock so we can safely do uiomove().
50817c478bd9Sstevel@tonic-gate * The lwp directory will not change because
50827c478bd9Sstevel@tonic-gate * we have the process locked with P_PR_LOCK.
50837c478bd9Sstevel@tonic-gate */
50847c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
50857c478bd9Sstevel@tonic-gate
50867c478bd9Sstevel@tonic-gate
50877c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5088b38f0970Sck153898 pmkino(0, pslot, PR_PIDDIR),
5089b38f0970Sck153898 pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
50907c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
50917c478bd9Sstevel@tonic-gate prunlock(pnp);
50927c478bd9Sstevel@tonic-gate return (error);
50937c478bd9Sstevel@tonic-gate }
50947c478bd9Sstevel@tonic-gate
50957c478bd9Sstevel@tonic-gate /*
50967c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until all lwps
50977c478bd9Sstevel@tonic-gate * have been examined.
50987c478bd9Sstevel@tonic-gate */
50997c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
51007c478bd9Sstevel@tonic-gate lwpent_t *lep;
51017c478bd9Sstevel@tonic-gate uint_t tid;
51027c478bd9Sstevel@tonic-gate
51037c478bd9Sstevel@tonic-gate /*
51047c478bd9Sstevel@tonic-gate * Find next LWP.
51057c478bd9Sstevel@tonic-gate */
51067c478bd9Sstevel@tonic-gate while (tslot < lwpdirsize &&
51077c478bd9Sstevel@tonic-gate ((lep = lwpdir[tslot].ld_entry) == NULL))
51087c478bd9Sstevel@tonic-gate tslot++;
51097c478bd9Sstevel@tonic-gate /*
51107c478bd9Sstevel@tonic-gate * Stop when all lwps have been reported.
51117c478bd9Sstevel@tonic-gate */
51127c478bd9Sstevel@tonic-gate if (tslot >= lwpdirsize) {
51137c478bd9Sstevel@tonic-gate eof = 1;
51147c478bd9Sstevel@tonic-gate break;
51157c478bd9Sstevel@tonic-gate }
51167c478bd9Sstevel@tonic-gate
51177c478bd9Sstevel@tonic-gate tid = lep->le_lwpid;
51187c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, tslot,
51197c478bd9Sstevel@tonic-gate pmkino(tslot, pslot, PR_LWPIDDIR), tid);
51207c478bd9Sstevel@tonic-gate if (error)
51217c478bd9Sstevel@tonic-gate break;
51227c478bd9Sstevel@tonic-gate }
51237c478bd9Sstevel@tonic-gate
51247c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
51257c478bd9Sstevel@tonic-gate prunlock(pnp);
51267c478bd9Sstevel@tonic-gate
51277c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
51287c478bd9Sstevel@tonic-gate }
51297c478bd9Sstevel@tonic-gate
51307c478bd9Sstevel@tonic-gate /* ARGSUSED */
51317c478bd9Sstevel@tonic-gate static int
pr_readdir_lwpiddir(prnode_t * pnp,uio_t * uiop,int * eofp)51327c478bd9Sstevel@tonic-gate pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
51337c478bd9Sstevel@tonic-gate {
51347c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
51357c478bd9Sstevel@tonic-gate int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
51367c478bd9Sstevel@tonic-gate prdirent_t dirent;
51377c478bd9Sstevel@tonic-gate prdirent_t *dirp;
51387c478bd9Sstevel@tonic-gate offset_t off;
51397c478bd9Sstevel@tonic-gate int error;
51407c478bd9Sstevel@tonic-gate int pslot;
51417c478bd9Sstevel@tonic-gate int tslot;
51427c478bd9Sstevel@tonic-gate
51437c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPIDDIR);
51447c478bd9Sstevel@tonic-gate
51457c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
51467c478bd9Sstevel@tonic-gate uiop->uio_offset % sizeof (prdirent_t) != 0 ||
51477c478bd9Sstevel@tonic-gate uiop->uio_resid < sizeof (prdirent_t))
51487c478bd9Sstevel@tonic-gate return (EINVAL);
51497c478bd9Sstevel@tonic-gate if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
51507c478bd9Sstevel@tonic-gate return (ENOENT);
51517c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpiddir))
51527c478bd9Sstevel@tonic-gate goto out;
51537c478bd9Sstevel@tonic-gate
51547c478bd9Sstevel@tonic-gate /*
51557c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied, omitting some files
51567c478bd9Sstevel@tonic-gate * along the way if the lwp is a zombie and also depending
51577c478bd9Sstevel@tonic-gate * on the data model of the process.
51587c478bd9Sstevel@tonic-gate */
51597c478bd9Sstevel@tonic-gate pslot = pcp->prc_slot;
51607c478bd9Sstevel@tonic-gate tslot = pcp->prc_tslot;
51617c478bd9Sstevel@tonic-gate for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
51627c478bd9Sstevel@tonic-gate uiop->uio_resid >= sizeof (prdirent_t) &&
51637c478bd9Sstevel@tonic-gate dirp < &lwpiddir[NLWPIDDIRFILES+2];
51647c478bd9Sstevel@tonic-gate uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
51657c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
51667c478bd9Sstevel@tonic-gate if (zombie) {
51677c478bd9Sstevel@tonic-gate switch (dirp->d_ino) {
51687c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
51697c478bd9Sstevel@tonic-gate case PR_LWPDIR:
51707c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
51717c478bd9Sstevel@tonic-gate break;
51727c478bd9Sstevel@tonic-gate default:
51737c478bd9Sstevel@tonic-gate continue;
51747c478bd9Sstevel@tonic-gate }
51757c478bd9Sstevel@tonic-gate }
51767c478bd9Sstevel@tonic-gate #if defined(__sparc)
51777c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
51787c478bd9Sstevel@tonic-gate if (dirp->d_ino == PR_ASRS &&
51797c478bd9Sstevel@tonic-gate pcp->prc_datamodel != DATAMODEL_LP64)
51807c478bd9Sstevel@tonic-gate continue;
51817c478bd9Sstevel@tonic-gate #endif
51827c478bd9Sstevel@tonic-gate bcopy(dirp, &dirent, sizeof (prdirent_t));
51837c478bd9Sstevel@tonic-gate if (dirent.d_ino == PR_LWPDIR)
51847c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
51857c478bd9Sstevel@tonic-gate else
51867c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
51877c478bd9Sstevel@tonic-gate if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
51887c478bd9Sstevel@tonic-gate UIO_READ, uiop)) != 0)
51897c478bd9Sstevel@tonic-gate return (error);
51907c478bd9Sstevel@tonic-gate }
51917c478bd9Sstevel@tonic-gate out:
51927c478bd9Sstevel@tonic-gate if (eofp)
51937c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
51947c478bd9Sstevel@tonic-gate return (0);
51957c478bd9Sstevel@tonic-gate }
51967c478bd9Sstevel@tonic-gate
51977c478bd9Sstevel@tonic-gate /* ARGSUSED */
51987c478bd9Sstevel@tonic-gate static int
pr_readdir_fddir(prnode_t * pnp,uio_t * uiop,int * eofp)51997c478bd9Sstevel@tonic-gate pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
52007c478bd9Sstevel@tonic-gate {
52017c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
52027c478bd9Sstevel@tonic-gate int error, eof = 0;
52037c478bd9Sstevel@tonic-gate offset_t n;
52047c478bd9Sstevel@tonic-gate proc_t *p;
52057c478bd9Sstevel@tonic-gate int pslot;
52067c478bd9Sstevel@tonic-gate int fddirsize;
52077c478bd9Sstevel@tonic-gate uf_info_t *fip;
52087c478bd9Sstevel@tonic-gate
52097c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_FDDIR);
52107c478bd9Sstevel@tonic-gate
52117c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
52127c478bd9Sstevel@tonic-gate return (error);
52137c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
52147c478bd9Sstevel@tonic-gate pslot = p->p_slot;
52157c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
52167c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
52177c478bd9Sstevel@tonic-gate
52187c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5219b38f0970Sck153898 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
52207c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
52217c478bd9Sstevel@tonic-gate prunlock(pnp);
52227c478bd9Sstevel@tonic-gate return (error);
52237c478bd9Sstevel@tonic-gate }
52247c478bd9Sstevel@tonic-gate
52257c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
52267c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
52277c478bd9Sstevel@tonic-gate fddirsize = 0;
52287c478bd9Sstevel@tonic-gate else
52297c478bd9Sstevel@tonic-gate fddirsize = fip->fi_nfiles;
52307c478bd9Sstevel@tonic-gate
52317c478bd9Sstevel@tonic-gate /*
52327c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until
52337c478bd9Sstevel@tonic-gate * all file descriptors have been examined.
52347c478bd9Sstevel@tonic-gate */
52357c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
52367c478bd9Sstevel@tonic-gate /*
52377c478bd9Sstevel@tonic-gate * Find next fd.
52387c478bd9Sstevel@tonic-gate */
52397c478bd9Sstevel@tonic-gate while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
52407c478bd9Sstevel@tonic-gate n++;
52417c478bd9Sstevel@tonic-gate /*
52427c478bd9Sstevel@tonic-gate * Stop when all fds have been reported.
52437c478bd9Sstevel@tonic-gate */
52447c478bd9Sstevel@tonic-gate if (n >= fddirsize) {
52457c478bd9Sstevel@tonic-gate eof = 1;
52467c478bd9Sstevel@tonic-gate break;
52477c478bd9Sstevel@tonic-gate }
52487c478bd9Sstevel@tonic-gate
52497c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, n,
52507c478bd9Sstevel@tonic-gate pmkino(n, pslot, PR_FD), n);
52517c478bd9Sstevel@tonic-gate if (error)
52527c478bd9Sstevel@tonic-gate break;
52537c478bd9Sstevel@tonic-gate }
52547c478bd9Sstevel@tonic-gate
52557c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
52567c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
52577c478bd9Sstevel@tonic-gate prunlock(pnp);
52587c478bd9Sstevel@tonic-gate
52597c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
52607c478bd9Sstevel@tonic-gate }
52617c478bd9Sstevel@tonic-gate
52627c478bd9Sstevel@tonic-gate /* ARGSUSED */
52637c478bd9Sstevel@tonic-gate static int
pr_readdir_pathdir(prnode_t * pnp,uio_t * uiop,int * eofp)52647c478bd9Sstevel@tonic-gate pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
52657c478bd9Sstevel@tonic-gate {
52667c478bd9Sstevel@tonic-gate longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
52677c478bd9Sstevel@tonic-gate dirent64_t *dirent = (dirent64_t *)bp;
52687c478bd9Sstevel@tonic-gate int reclen;
52697c478bd9Sstevel@tonic-gate ssize_t oresid;
52707c478bd9Sstevel@tonic-gate offset_t off, idx;
52717c478bd9Sstevel@tonic-gate int error = 0;
52727c478bd9Sstevel@tonic-gate proc_t *p;
52737c478bd9Sstevel@tonic-gate int fd, obj;
52747c478bd9Sstevel@tonic-gate int pslot;
52757c478bd9Sstevel@tonic-gate int fddirsize;
52767c478bd9Sstevel@tonic-gate uf_info_t *fip;
52777c478bd9Sstevel@tonic-gate struct as *as = NULL;
52787c478bd9Sstevel@tonic-gate size_t objdirsize;
52797c478bd9Sstevel@tonic-gate vattr_t vattr;
52807c478bd9Sstevel@tonic-gate vnode_t *vp;
52817c478bd9Sstevel@tonic-gate
52827c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PATHDIR);
52837c478bd9Sstevel@tonic-gate
52847c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
52857c478bd9Sstevel@tonic-gate uiop->uio_resid <= 0 ||
52867c478bd9Sstevel@tonic-gate (uiop->uio_offset % PRSDSIZE) != 0)
52877c478bd9Sstevel@tonic-gate return (EINVAL);
52887c478bd9Sstevel@tonic-gate oresid = uiop->uio_resid;
52897c478bd9Sstevel@tonic-gate bzero(bp, sizeof (bp));
52907c478bd9Sstevel@tonic-gate
52917c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
52927c478bd9Sstevel@tonic-gate return (error);
52937c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
52947c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
52957c478bd9Sstevel@tonic-gate pslot = p->p_slot;
52967c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
52977c478bd9Sstevel@tonic-gate
52987c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
52997c478bd9Sstevel@tonic-gate as = NULL;
53007c478bd9Sstevel@tonic-gate objdirsize = 0;
53017c478bd9Sstevel@tonic-gate } else {
5302*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
53037c478bd9Sstevel@tonic-gate if (as->a_updatedir)
53047c478bd9Sstevel@tonic-gate rebuild_objdir(as);
53057c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
5306*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
53077c478bd9Sstevel@tonic-gate as = NULL;
53087c478bd9Sstevel@tonic-gate }
53097c478bd9Sstevel@tonic-gate
53107c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
53117c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
53127c478bd9Sstevel@tonic-gate fddirsize = 0;
53137c478bd9Sstevel@tonic-gate else
53147c478bd9Sstevel@tonic-gate fddirsize = fip->fi_nfiles;
53157c478bd9Sstevel@tonic-gate
53167c478bd9Sstevel@tonic-gate for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
53177c478bd9Sstevel@tonic-gate /*
53187c478bd9Sstevel@tonic-gate * There are 4 special files in the path directory: ".", "..",
53197c478bd9Sstevel@tonic-gate * "root", and "cwd". We handle those specially here.
53207c478bd9Sstevel@tonic-gate */
53217c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
53227c478bd9Sstevel@tonic-gate idx = off / PRSDSIZE;
53237c478bd9Sstevel@tonic-gate if (off == 0) { /* "." */
53247c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
53257c478bd9Sstevel@tonic-gate dirent->d_name[0] = '.';
53267c478bd9Sstevel@tonic-gate dirent->d_name[1] = '\0';
53277c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(1);
53287c478bd9Sstevel@tonic-gate } else if (idx == 1) { /* ".." */
53297c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
53307c478bd9Sstevel@tonic-gate dirent->d_name[0] = '.';
53317c478bd9Sstevel@tonic-gate dirent->d_name[1] = '.';
53327c478bd9Sstevel@tonic-gate dirent->d_name[2] = '\0';
53337c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(2);
53347c478bd9Sstevel@tonic-gate } else if (idx == 2) { /* "root" */
53357c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
53367c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "root");
53377c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(4);
53387c478bd9Sstevel@tonic-gate } else if (idx == 3) { /* "cwd" */
53397c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
53407c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "cwd");
53417c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(3);
53427c478bd9Sstevel@tonic-gate } else if (idx < 4 + fddirsize) {
53437c478bd9Sstevel@tonic-gate /*
53447c478bd9Sstevel@tonic-gate * In this case, we have one of the file descriptors.
53457c478bd9Sstevel@tonic-gate */
53467c478bd9Sstevel@tonic-gate fd = idx - 4;
53477c478bd9Sstevel@tonic-gate if (fip->fi_list[fd].uf_file == NULL)
53487c478bd9Sstevel@tonic-gate continue;
53497c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
53507c478bd9Sstevel@tonic-gate (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
53517c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(PLNSIZ);
53527c478bd9Sstevel@tonic-gate } else if (idx < 4 + fddirsize + objdirsize) {
53537c478bd9Sstevel@tonic-gate if (fip != NULL) {
53547c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
53557c478bd9Sstevel@tonic-gate fip = NULL;
53567c478bd9Sstevel@tonic-gate }
53577c478bd9Sstevel@tonic-gate
53587c478bd9Sstevel@tonic-gate /*
53597c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
53607c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
53617c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
53627c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
53637c478bd9Sstevel@tonic-gate */
53647c478bd9Sstevel@tonic-gate if (as == NULL) {
53657c478bd9Sstevel@tonic-gate as = p->p_as;
5366*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
53677c478bd9Sstevel@tonic-gate }
53687c478bd9Sstevel@tonic-gate
53697c478bd9Sstevel@tonic-gate if (as->a_updatedir) {
53707c478bd9Sstevel@tonic-gate rebuild_objdir(as);
53717c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
53727c478bd9Sstevel@tonic-gate }
53737c478bd9Sstevel@tonic-gate
53747c478bd9Sstevel@tonic-gate obj = idx - 4 - fddirsize;
53757c478bd9Sstevel@tonic-gate if ((vp = obj_entry(as, obj)) == NULL)
53767c478bd9Sstevel@tonic-gate continue;
53777c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
5378da6c28aaSamw if (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) != 0)
53797c478bd9Sstevel@tonic-gate continue;
53807c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
53817c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "a.out");
53827c478bd9Sstevel@tonic-gate else
53837c478bd9Sstevel@tonic-gate pr_object_name(dirent->d_name, vp, &vattr);
53847c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
53857c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
53867c478bd9Sstevel@tonic-gate } else {
53877c478bd9Sstevel@tonic-gate break;
53887c478bd9Sstevel@tonic-gate }
53897c478bd9Sstevel@tonic-gate
53907c478bd9Sstevel@tonic-gate dirent->d_off = uiop->uio_offset + PRSDSIZE;
53917c478bd9Sstevel@tonic-gate dirent->d_reclen = (ushort_t)reclen;
53927c478bd9Sstevel@tonic-gate if (reclen > uiop->uio_resid) {
53937c478bd9Sstevel@tonic-gate /*
53947c478bd9Sstevel@tonic-gate * Error if no entries have been returned yet.
53957c478bd9Sstevel@tonic-gate */
53967c478bd9Sstevel@tonic-gate if (uiop->uio_resid == oresid)
53977c478bd9Sstevel@tonic-gate error = EINVAL;
53987c478bd9Sstevel@tonic-gate break;
53997c478bd9Sstevel@tonic-gate }
54007c478bd9Sstevel@tonic-gate /*
54017c478bd9Sstevel@tonic-gate * Drop the address space lock to do the uiomove().
54027c478bd9Sstevel@tonic-gate */
54037c478bd9Sstevel@tonic-gate if (as != NULL)
5404*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
54057c478bd9Sstevel@tonic-gate
54067c478bd9Sstevel@tonic-gate error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
54077c478bd9Sstevel@tonic-gate if (as != NULL)
5408*fd435bccSJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
54097c478bd9Sstevel@tonic-gate
54107c478bd9Sstevel@tonic-gate if (error)
54117c478bd9Sstevel@tonic-gate break;
54127c478bd9Sstevel@tonic-gate }
54137c478bd9Sstevel@tonic-gate
54147c478bd9Sstevel@tonic-gate if (error == 0 && eofp)
54157c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
54167c478bd9Sstevel@tonic-gate
54177c478bd9Sstevel@tonic-gate if (fip != NULL)
54187c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
54197c478bd9Sstevel@tonic-gate if (as != NULL)
5420*fd435bccSJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
54217c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
54227c478bd9Sstevel@tonic-gate prunlock(pnp);
54237c478bd9Sstevel@tonic-gate return (error);
54247c478bd9Sstevel@tonic-gate }
54257c478bd9Sstevel@tonic-gate
54267c478bd9Sstevel@tonic-gate static int
pr_readdir_tmpldir(prnode_t * pnp,uio_t * uiop,int * eofp)54277c478bd9Sstevel@tonic-gate pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
54287c478bd9Sstevel@tonic-gate {
54297c478bd9Sstevel@tonic-gate proc_t *p;
54307c478bd9Sstevel@tonic-gate int pslot, tslot;
54317c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
54327c478bd9Sstevel@tonic-gate int error, eof = 0;
54337c478bd9Sstevel@tonic-gate offset_t n;
54347c478bd9Sstevel@tonic-gate
54357c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_TMPLDIR);
54367c478bd9Sstevel@tonic-gate
54377c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
54387c478bd9Sstevel@tonic-gate return (error);
54397c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
54407c478bd9Sstevel@tonic-gate pslot = pnp->pr_common->prc_slot;
54417c478bd9Sstevel@tonic-gate tslot = pnp->pr_common->prc_tslot;
54427c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
54437c478bd9Sstevel@tonic-gate
54447c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
54457c478bd9Sstevel@tonic-gate pmkino(tslot, pslot, PR_LWPDIR),
5446b38f0970Sck153898 pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
54477c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
54487c478bd9Sstevel@tonic-gate prunlock(pnp);
54497c478bd9Sstevel@tonic-gate return (error);
54507c478bd9Sstevel@tonic-gate }
54517c478bd9Sstevel@tonic-gate
54527c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
54537c478bd9Sstevel@tonic-gate /*
54547c478bd9Sstevel@tonic-gate * Check for an active template. Reading a directory's
54557c478bd9Sstevel@tonic-gate * contents is already racy, so we don't bother taking
54567c478bd9Sstevel@tonic-gate * any locks.
54577c478bd9Sstevel@tonic-gate */
54587c478bd9Sstevel@tonic-gate while (n < ct_ntypes &&
54597c478bd9Sstevel@tonic-gate pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
54607c478bd9Sstevel@tonic-gate n++;
54617c478bd9Sstevel@tonic-gate /*
54627c478bd9Sstevel@tonic-gate * Stop when all types have been reported.
54637c478bd9Sstevel@tonic-gate */
54647c478bd9Sstevel@tonic-gate if (n >= ct_ntypes) {
54657c478bd9Sstevel@tonic-gate eof = 1;
54667c478bd9Sstevel@tonic-gate break;
54677c478bd9Sstevel@tonic-gate }
54687c478bd9Sstevel@tonic-gate /*
54697c478bd9Sstevel@tonic-gate * The pmkino invocation below will need to be updated
54707c478bd9Sstevel@tonic-gate * when we create our fifth contract type.
54717c478bd9Sstevel@tonic-gate */
54727c478bd9Sstevel@tonic-gate ASSERT(ct_ntypes <= 4);
54737c478bd9Sstevel@tonic-gate error = gfs_readdir_emit(&gstate, uiop, n,
54747c478bd9Sstevel@tonic-gate pmkino((tslot << 2) | n, pslot, PR_TMPL),
5475b38f0970Sck153898 ct_types[n]->ct_type_name, 0);
54767c478bd9Sstevel@tonic-gate if (error)
54777c478bd9Sstevel@tonic-gate break;
54787c478bd9Sstevel@tonic-gate }
54797c478bd9Sstevel@tonic-gate
54807c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
54817c478bd9Sstevel@tonic-gate prunlock(pnp);
54827c478bd9Sstevel@tonic-gate
54837c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
54847c478bd9Sstevel@tonic-gate }
54857c478bd9Sstevel@tonic-gate
54867c478bd9Sstevel@tonic-gate static int
pr_readdir_ctdir(prnode_t * pnp,uio_t * uiop,int * eofp)54877c478bd9Sstevel@tonic-gate pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
54887c478bd9Sstevel@tonic-gate {
54897c478bd9Sstevel@tonic-gate proc_t *p;
54907c478bd9Sstevel@tonic-gate int pslot;
54917c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
54927c478bd9Sstevel@tonic-gate int error, eof = 0;
54937c478bd9Sstevel@tonic-gate offset_t n;
54947c478bd9Sstevel@tonic-gate uint64_t zid;
54957c478bd9Sstevel@tonic-gate
54967c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_CTDIR);
54977c478bd9Sstevel@tonic-gate
54987c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
54997c478bd9Sstevel@tonic-gate return (error);
55007c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
55017c478bd9Sstevel@tonic-gate pslot = p->p_slot;
55027c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
55037c478bd9Sstevel@tonic-gate
55047c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5505b38f0970Sck153898 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
55067c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
55077c478bd9Sstevel@tonic-gate prunlock(pnp);
55087c478bd9Sstevel@tonic-gate return (error);
55097c478bd9Sstevel@tonic-gate }
55107c478bd9Sstevel@tonic-gate
5511fa9e4066Sahrens zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
55127c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
55137c478bd9Sstevel@tonic-gate id_t next = contract_plookup(p, n, zid);
55147c478bd9Sstevel@tonic-gate if (next == -1) {
55157c478bd9Sstevel@tonic-gate eof = 1;
55167c478bd9Sstevel@tonic-gate break;
55177c478bd9Sstevel@tonic-gate }
55187c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, next,
55197c478bd9Sstevel@tonic-gate pmkino(next, pslot, PR_CT), next);
55207c478bd9Sstevel@tonic-gate if (error)
55217c478bd9Sstevel@tonic-gate break;
55227c478bd9Sstevel@tonic-gate }
55237c478bd9Sstevel@tonic-gate
55247c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
55257c478bd9Sstevel@tonic-gate prunlock(pnp);
55267c478bd9Sstevel@tonic-gate
55277c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
55287c478bd9Sstevel@tonic-gate }
55297c478bd9Sstevel@tonic-gate
55307c478bd9Sstevel@tonic-gate /* ARGSUSED */
55317c478bd9Sstevel@tonic-gate static int
prfsync(vnode_t * vp,int syncflag,cred_t * cr,caller_context_t * ct)5532da6c28aaSamw prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
55337c478bd9Sstevel@tonic-gate {
55347c478bd9Sstevel@tonic-gate return (0);
55357c478bd9Sstevel@tonic-gate }
55367c478bd9Sstevel@tonic-gate
55377c478bd9Sstevel@tonic-gate /*
55387c478bd9Sstevel@tonic-gate * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
55397c478bd9Sstevel@tonic-gate */
55407c478bd9Sstevel@tonic-gate static void
pr_list_unlink(vnode_t * pvp,vnode_t ** listp)55417c478bd9Sstevel@tonic-gate pr_list_unlink(vnode_t *pvp, vnode_t **listp)
55427c478bd9Sstevel@tonic-gate {
55437c478bd9Sstevel@tonic-gate vnode_t *vp;
55447c478bd9Sstevel@tonic-gate prnode_t *pnp;
55457c478bd9Sstevel@tonic-gate
55467c478bd9Sstevel@tonic-gate while ((vp = *listp) != NULL) {
55477c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
55487c478bd9Sstevel@tonic-gate if (vp == pvp) {
55497c478bd9Sstevel@tonic-gate *listp = pnp->pr_next;
55507c478bd9Sstevel@tonic-gate pnp->pr_next = NULL;
55517c478bd9Sstevel@tonic-gate break;
55527c478bd9Sstevel@tonic-gate }
55537c478bd9Sstevel@tonic-gate listp = &pnp->pr_next;
55547c478bd9Sstevel@tonic-gate }
55557c478bd9Sstevel@tonic-gate }
55567c478bd9Sstevel@tonic-gate
55577c478bd9Sstevel@tonic-gate /* ARGSUSED */
55587c478bd9Sstevel@tonic-gate static void
prinactive(vnode_t * vp,cred_t * cr,caller_context_t * ct)5559da6c28aaSamw prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
55607c478bd9Sstevel@tonic-gate {
55617c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
55627c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
55637c478bd9Sstevel@tonic-gate proc_t *p;
55647c478bd9Sstevel@tonic-gate vnode_t *dp;
55657c478bd9Sstevel@tonic-gate vnode_t *ovp = NULL;
55667c478bd9Sstevel@tonic-gate prnode_t *opnp = NULL;
55677c478bd9Sstevel@tonic-gate
55687c478bd9Sstevel@tonic-gate switch (type) {
55697c478bd9Sstevel@tonic-gate case PR_OBJECT:
55707c478bd9Sstevel@tonic-gate case PR_FD:
55717c478bd9Sstevel@tonic-gate case PR_SELF:
55727c478bd9Sstevel@tonic-gate case PR_PATH:
55737c478bd9Sstevel@tonic-gate /* These are not linked into the usual lists */
55747c478bd9Sstevel@tonic-gate ASSERT(vp->v_count == 1);
55757c478bd9Sstevel@tonic-gate if ((dp = pnp->pr_parent) != NULL)
55767c478bd9Sstevel@tonic-gate VN_RELE(dp);
55777c478bd9Sstevel@tonic-gate prfreenode(pnp);
55787c478bd9Sstevel@tonic-gate return;
55797c478bd9Sstevel@tonic-gate default:
55807c478bd9Sstevel@tonic-gate break;
55817c478bd9Sstevel@tonic-gate }
55827c478bd9Sstevel@tonic-gate
55837c478bd9Sstevel@tonic-gate mutex_enter(&pr_pidlock);
55847c478bd9Sstevel@tonic-gate if (pnp->pr_pcommon == NULL)
55857c478bd9Sstevel@tonic-gate p = NULL;
55867c478bd9Sstevel@tonic-gate else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
55877c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
55887c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock);
55897c478bd9Sstevel@tonic-gate
55907c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR || vp->v_count > 1) {
55917c478bd9Sstevel@tonic-gate vp->v_count--;
55927c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock);
55937c478bd9Sstevel@tonic-gate if (p != NULL)
55947c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
55957c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
55967c478bd9Sstevel@tonic-gate return;
55977c478bd9Sstevel@tonic-gate }
55987c478bd9Sstevel@tonic-gate
55997c478bd9Sstevel@tonic-gate if ((dp = pnp->pr_parent) != NULL) {
56007c478bd9Sstevel@tonic-gate prnode_t *dpnp;
56017c478bd9Sstevel@tonic-gate
56027c478bd9Sstevel@tonic-gate switch (type) {
56037c478bd9Sstevel@tonic-gate case PR_PIDFILE:
56047c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
56057c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
56067c478bd9Sstevel@tonic-gate break;
56077c478bd9Sstevel@tonic-gate default:
56087c478bd9Sstevel@tonic-gate dpnp = VTOP(dp);
56097c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
56107c478bd9Sstevel@tonic-gate if (dpnp->pr_files != NULL &&
56117c478bd9Sstevel@tonic-gate dpnp->pr_files[pnp->pr_index] == vp)
56127c478bd9Sstevel@tonic-gate dpnp->pr_files[pnp->pr_index] = NULL;
56137c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
56147c478bd9Sstevel@tonic-gate break;
56157c478bd9Sstevel@tonic-gate }
56167c478bd9Sstevel@tonic-gate pnp->pr_parent = NULL;
56177c478bd9Sstevel@tonic-gate }
56187c478bd9Sstevel@tonic-gate
56197c478bd9Sstevel@tonic-gate ASSERT(vp->v_count == 1);
56207c478bd9Sstevel@tonic-gate
56217c478bd9Sstevel@tonic-gate /*
56227c478bd9Sstevel@tonic-gate * If we allocated an old /proc/pid node, free it too.
56237c478bd9Sstevel@tonic-gate */
56247c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
56257c478bd9Sstevel@tonic-gate ASSERT(type == PR_PIDDIR);
56267c478bd9Sstevel@tonic-gate ovp = pnp->pr_pidfile;
56277c478bd9Sstevel@tonic-gate opnp = VTOP(ovp);
56287c478bd9Sstevel@tonic-gate ASSERT(opnp->pr_type == PR_PIDFILE);
56297c478bd9Sstevel@tonic-gate pnp->pr_pidfile = NULL;
56307c478bd9Sstevel@tonic-gate }
56317c478bd9Sstevel@tonic-gate
56327c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
56337c478bd9Sstevel@tonic-gate
56347c478bd9Sstevel@tonic-gate if (p != NULL) {
56357c478bd9Sstevel@tonic-gate /*
56367c478bd9Sstevel@tonic-gate * Remove the vnodes from the lists of
56377c478bd9Sstevel@tonic-gate * /proc vnodes for the process.
56387c478bd9Sstevel@tonic-gate */
56397c478bd9Sstevel@tonic-gate int slot;
56407c478bd9Sstevel@tonic-gate
56417c478bd9Sstevel@tonic-gate switch (type) {
56427c478bd9Sstevel@tonic-gate case PR_PIDDIR:
56437c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &p->p_trace);
56447c478bd9Sstevel@tonic-gate break;
56457c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
56467c478bd9Sstevel@tonic-gate if ((slot = pnp->pr_common->prc_tslot) != -1) {
56477c478bd9Sstevel@tonic-gate lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
56487c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &lep->le_trace);
56497c478bd9Sstevel@tonic-gate }
56507c478bd9Sstevel@tonic-gate break;
56517c478bd9Sstevel@tonic-gate default:
56527c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &p->p_plist);
56537c478bd9Sstevel@tonic-gate break;
56547c478bd9Sstevel@tonic-gate }
56557c478bd9Sstevel@tonic-gate if (ovp != NULL)
56567c478bd9Sstevel@tonic-gate pr_list_unlink(ovp, &p->p_plist);
56577c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
56587c478bd9Sstevel@tonic-gate }
56597c478bd9Sstevel@tonic-gate
56607c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock);
56617c478bd9Sstevel@tonic-gate
56627c478bd9Sstevel@tonic-gate if (type == PR_CT && pnp->pr_contract != NULL) {
56637c478bd9Sstevel@tonic-gate contract_rele(pnp->pr_contract);
56647c478bd9Sstevel@tonic-gate pnp->pr_contract = NULL;
56657c478bd9Sstevel@tonic-gate }
56667c478bd9Sstevel@tonic-gate
56677c478bd9Sstevel@tonic-gate if (opnp != NULL)
56687c478bd9Sstevel@tonic-gate prfreenode(opnp);
56697c478bd9Sstevel@tonic-gate prfreenode(pnp);
56707c478bd9Sstevel@tonic-gate if (dp != NULL) {
56717c478bd9Sstevel@tonic-gate VN_RELE(dp);
56727c478bd9Sstevel@tonic-gate }
56737c478bd9Sstevel@tonic-gate }
56747c478bd9Sstevel@tonic-gate
56757c478bd9Sstevel@tonic-gate /* ARGSUSED */
56767c478bd9Sstevel@tonic-gate static int
prseek(vnode_t * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)5677da6c28aaSamw prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
56787c478bd9Sstevel@tonic-gate {
56797c478bd9Sstevel@tonic-gate return (0);
56807c478bd9Sstevel@tonic-gate }
56817c478bd9Sstevel@tonic-gate
56827c478bd9Sstevel@tonic-gate /*
56837c478bd9Sstevel@tonic-gate * We use the p_execdir member of proc_t to expand the %d token in core file
56847c478bd9Sstevel@tonic-gate * paths (the directory path for the executable that dumped core; see
56857c478bd9Sstevel@tonic-gate * coreadm(1M) for details). We'd like gcore(1) to be able to expand %d in
56867c478bd9Sstevel@tonic-gate * the same way as core dumping from the kernel, but there's no convenient
56877c478bd9Sstevel@tonic-gate * and comprehensible way to export the path name for p_execdir. To solve
56887c478bd9Sstevel@tonic-gate * this, we try to find the actual path to the executable that was used. In
56897c478bd9Sstevel@tonic-gate * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
56907c478bd9Sstevel@tonic-gate * flag, and use that here to indicate that more work is needed beyond the
56917c478bd9Sstevel@tonic-gate * call to vnodetopath().
56927c478bd9Sstevel@tonic-gate */
56937c478bd9Sstevel@tonic-gate static int
prreadlink_lookup(prnode_t * pnp,char * buf,size_t size,cred_t * cr)56947c478bd9Sstevel@tonic-gate prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
56957c478bd9Sstevel@tonic-gate {
56967c478bd9Sstevel@tonic-gate proc_t *p;
56977c478bd9Sstevel@tonic-gate vnode_t *vp, *execvp, *vrootp;
56987c478bd9Sstevel@tonic-gate int ret;
56997c478bd9Sstevel@tonic-gate size_t len;
57007c478bd9Sstevel@tonic-gate dirent64_t *dp;
57017c478bd9Sstevel@tonic-gate size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
57027c478bd9Sstevel@tonic-gate char *dbuf;
57037c478bd9Sstevel@tonic-gate
57047c478bd9Sstevel@tonic-gate p = curproc;
57057c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
57067c478bd9Sstevel@tonic-gate if ((vrootp = PTOU(p)->u_rdir) == NULL)
57077c478bd9Sstevel@tonic-gate vrootp = rootdir;
57087c478bd9Sstevel@tonic-gate VN_HOLD(vrootp);
57097c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
57107c478bd9Sstevel@tonic-gate
57117c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
57127c478bd9Sstevel@tonic-gate
57137c478bd9Sstevel@tonic-gate /*
57147c478bd9Sstevel@tonic-gate * If PR_AOUT isn't set, then we looked up the path for the vnode;
57157c478bd9Sstevel@tonic-gate * otherwise, we looked up the path for (what we believe to be) the
57167c478bd9Sstevel@tonic-gate * containing directory.
57177c478bd9Sstevel@tonic-gate */
57187c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & PR_AOUT) == 0) {
57197c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
57207c478bd9Sstevel@tonic-gate return (ret);
57217c478bd9Sstevel@tonic-gate }
57227c478bd9Sstevel@tonic-gate
57237c478bd9Sstevel@tonic-gate /*
57247c478bd9Sstevel@tonic-gate * Fail if there's a problem locking the process. This will only
57257c478bd9Sstevel@tonic-gate * occur if the process is changing so the information we would
57267c478bd9Sstevel@tonic-gate * report would already be invalid.
57277c478bd9Sstevel@tonic-gate */
57287c478bd9Sstevel@tonic-gate if (prlock(pnp, ZNO) != 0) {
57297c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
57307c478bd9Sstevel@tonic-gate return (EIO);
57317c478bd9Sstevel@tonic-gate }
57327c478bd9Sstevel@tonic-gate
57337c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
57347c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
57357c478bd9Sstevel@tonic-gate
57367c478bd9Sstevel@tonic-gate execvp = p->p_exec;
57377c478bd9Sstevel@tonic-gate VN_HOLD(execvp);
57387c478bd9Sstevel@tonic-gate
57397c478bd9Sstevel@tonic-gate /*
57407c478bd9Sstevel@tonic-gate * If our initial lookup of the directory failed, fall back to
57417c478bd9Sstevel@tonic-gate * the path name information for p_exec.
57427c478bd9Sstevel@tonic-gate */
57437c478bd9Sstevel@tonic-gate if (ret != 0) {
57447c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
57457c478bd9Sstevel@tonic-gate prunlock(pnp);
57467c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, execvp, buf, size, cr);
57477c478bd9Sstevel@tonic-gate VN_RELE(execvp);
57487c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
57497c478bd9Sstevel@tonic-gate return (ret);
57507c478bd9Sstevel@tonic-gate }
57517c478bd9Sstevel@tonic-gate
57527c478bd9Sstevel@tonic-gate len = strlen(buf);
57537c478bd9Sstevel@tonic-gate
57547c478bd9Sstevel@tonic-gate /*
57557c478bd9Sstevel@tonic-gate * We use u_comm as a guess for the last component of the full
57567c478bd9Sstevel@tonic-gate * executable path name. If there isn't going to be enough space
57577c478bd9Sstevel@tonic-gate * we fall back to using the p_exec so that we can have _an_
57587c478bd9Sstevel@tonic-gate * answer even if it's not perfect.
57597c478bd9Sstevel@tonic-gate */
57607c478bd9Sstevel@tonic-gate if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
57617c478bd9Sstevel@tonic-gate buf[len] = '/';
57627c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
57637c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
57647c478bd9Sstevel@tonic-gate prunlock(pnp);
57657c478bd9Sstevel@tonic-gate
57667c478bd9Sstevel@tonic-gate /*
57677c478bd9Sstevel@tonic-gate * Do a forward lookup of our u_comm guess.
57687c478bd9Sstevel@tonic-gate */
57697c478bd9Sstevel@tonic-gate if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
57707c478bd9Sstevel@tonic-gate &vp, pnp->pr_realvp) == 0) {
57717c478bd9Sstevel@tonic-gate if (vn_compare(vp, execvp)) {
57727c478bd9Sstevel@tonic-gate VN_RELE(vp);
57737c478bd9Sstevel@tonic-gate VN_RELE(execvp);
57747c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
57757c478bd9Sstevel@tonic-gate return (0);
57767c478bd9Sstevel@tonic-gate }
57777c478bd9Sstevel@tonic-gate
57787c478bd9Sstevel@tonic-gate VN_RELE(vp);
57797c478bd9Sstevel@tonic-gate }
57807c478bd9Sstevel@tonic-gate } else {
57817c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
57827c478bd9Sstevel@tonic-gate prunlock(pnp);
57837c478bd9Sstevel@tonic-gate }
57847c478bd9Sstevel@tonic-gate
57857c478bd9Sstevel@tonic-gate dbuf = kmem_alloc(dlen, KM_SLEEP);
57867c478bd9Sstevel@tonic-gate
57877c478bd9Sstevel@tonic-gate /*
57887c478bd9Sstevel@tonic-gate * Try to find a matching vnode by iterating through the directory's
57897c478bd9Sstevel@tonic-gate * entries. If that fails, fall back to the path information for
57907c478bd9Sstevel@tonic-gate * p_exec.
57917c478bd9Sstevel@tonic-gate */
57927c478bd9Sstevel@tonic-gate if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
57937c478bd9Sstevel@tonic-gate dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
57947c478bd9Sstevel@tonic-gate buf[len] = '/';
57957c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, dp->d_name);
57967c478bd9Sstevel@tonic-gate } else {
57977c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, execvp, buf, size, cr);
57987c478bd9Sstevel@tonic-gate }
57997c478bd9Sstevel@tonic-gate
58007c478bd9Sstevel@tonic-gate kmem_free(dbuf, dlen);
58017c478bd9Sstevel@tonic-gate VN_RELE(execvp);
58027c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
58037c478bd9Sstevel@tonic-gate
58047c478bd9Sstevel@tonic-gate return (ret);
58057c478bd9Sstevel@tonic-gate }
58067c478bd9Sstevel@tonic-gate
58077c478bd9Sstevel@tonic-gate /* ARGSUSED */
58087c478bd9Sstevel@tonic-gate static int
prreadlink(vnode_t * vp,uio_t * uiop,cred_t * cr,caller_context_t * ctp)5809da6c28aaSamw prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
58107c478bd9Sstevel@tonic-gate {
58117c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
58127c478bd9Sstevel@tonic-gate char *buf;
58137c478bd9Sstevel@tonic-gate int ret = EINVAL;
58147c478bd9Sstevel@tonic-gate char idbuf[16];
58157c478bd9Sstevel@tonic-gate int length, rlength;
58167c478bd9Sstevel@tonic-gate contract_t *ct;
58177c478bd9Sstevel@tonic-gate
58187c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
58197c478bd9Sstevel@tonic-gate case PR_SELF:
58207c478bd9Sstevel@tonic-gate (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
58217c478bd9Sstevel@tonic-gate ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
58227c478bd9Sstevel@tonic-gate break;
58237c478bd9Sstevel@tonic-gate case PR_OBJECT:
58247c478bd9Sstevel@tonic-gate case PR_FD:
58257c478bd9Sstevel@tonic-gate case PR_CURDIR:
58267c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
58277c478bd9Sstevel@tonic-gate if (pnp->pr_realvp->v_type == VDIR)
58287c478bd9Sstevel@tonic-gate ret = 0;
58297c478bd9Sstevel@tonic-gate break;
58307c478bd9Sstevel@tonic-gate case PR_PATH:
58317c478bd9Sstevel@tonic-gate buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
58327c478bd9Sstevel@tonic-gate
58337c478bd9Sstevel@tonic-gate if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
58347c478bd9Sstevel@tonic-gate ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
58357c478bd9Sstevel@tonic-gate
58367c478bd9Sstevel@tonic-gate kmem_free(buf, MAXPATHLEN);
58377c478bd9Sstevel@tonic-gate break;
58387c478bd9Sstevel@tonic-gate case PR_CT:
58397c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_contract != NULL);
58407c478bd9Sstevel@tonic-gate ct = pnp->pr_contract;
58417c478bd9Sstevel@tonic-gate length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
58427c478bd9Sstevel@tonic-gate strlen(ct->ct_type->ct_type_name);
58437c478bd9Sstevel@tonic-gate buf = kmem_alloc(length, KM_SLEEP);
58447c478bd9Sstevel@tonic-gate rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
58457c478bd9Sstevel@tonic-gate ct->ct_type->ct_type_name, ct->ct_id);
58467c478bd9Sstevel@tonic-gate ASSERT(rlength < length);
58477c478bd9Sstevel@tonic-gate ret = uiomove(buf, rlength, UIO_READ, uiop);
58487c478bd9Sstevel@tonic-gate kmem_free(buf, length);
58497c478bd9Sstevel@tonic-gate break;
58507c478bd9Sstevel@tonic-gate default:
58517c478bd9Sstevel@tonic-gate break;
58527c478bd9Sstevel@tonic-gate }
58537c478bd9Sstevel@tonic-gate
58547c478bd9Sstevel@tonic-gate return (ret);
58557c478bd9Sstevel@tonic-gate }
58567c478bd9Sstevel@tonic-gate
5857da6c28aaSamw /*ARGSUSED2*/
58587c478bd9Sstevel@tonic-gate static int
prcmp(vnode_t * vp1,vnode_t * vp2,caller_context_t * ct)5859da6c28aaSamw prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
58607c478bd9Sstevel@tonic-gate {
58617c478bd9Sstevel@tonic-gate prnode_t *pp1, *pp2;
58627c478bd9Sstevel@tonic-gate
58637c478bd9Sstevel@tonic-gate if (vp1 == vp2)
58647c478bd9Sstevel@tonic-gate return (1);
58657c478bd9Sstevel@tonic-gate
58667c478bd9Sstevel@tonic-gate if (!vn_matchops(vp1, prvnodeops) || !vn_matchops(vp2, prvnodeops))
58677c478bd9Sstevel@tonic-gate return (0);
58687c478bd9Sstevel@tonic-gate
58697c478bd9Sstevel@tonic-gate pp1 = VTOP(vp1);
58707c478bd9Sstevel@tonic-gate pp2 = VTOP(vp2);
58717c478bd9Sstevel@tonic-gate
58727c478bd9Sstevel@tonic-gate if (pp1->pr_type != pp2->pr_type)
58737c478bd9Sstevel@tonic-gate return (0);
58747c478bd9Sstevel@tonic-gate if (pp1->pr_type == PR_PROCDIR)
58757c478bd9Sstevel@tonic-gate return (1);
58767c478bd9Sstevel@tonic-gate if (pp1->pr_ino || pp2->pr_ino)
58777c478bd9Sstevel@tonic-gate return (pp2->pr_ino == pp1->pr_ino);
58787c478bd9Sstevel@tonic-gate
58797c478bd9Sstevel@tonic-gate if (pp1->pr_common == NULL || pp2->pr_common == NULL)
58807c478bd9Sstevel@tonic-gate return (0);
58817c478bd9Sstevel@tonic-gate
58827c478bd9Sstevel@tonic-gate return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
58837c478bd9Sstevel@tonic-gate pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
58847c478bd9Sstevel@tonic-gate }
58857c478bd9Sstevel@tonic-gate
58867c478bd9Sstevel@tonic-gate static int
prrealvp(vnode_t * vp,vnode_t ** vpp,caller_context_t * ct)5887da6c28aaSamw prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
58887c478bd9Sstevel@tonic-gate {
58897c478bd9Sstevel@tonic-gate vnode_t *rvp;
58907c478bd9Sstevel@tonic-gate
58917c478bd9Sstevel@tonic-gate if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
58927c478bd9Sstevel@tonic-gate vp = rvp;
5893da6c28aaSamw if (VOP_REALVP(vp, &rvp, ct) == 0)
58947c478bd9Sstevel@tonic-gate vp = rvp;
58957c478bd9Sstevel@tonic-gate }
58967c478bd9Sstevel@tonic-gate
58977c478bd9Sstevel@tonic-gate *vpp = vp;
58987c478bd9Sstevel@tonic-gate return (0);
58997c478bd9Sstevel@tonic-gate }
59007c478bd9Sstevel@tonic-gate
59017c478bd9Sstevel@tonic-gate /*
59027c478bd9Sstevel@tonic-gate * Return the answer requested to poll().
59037c478bd9Sstevel@tonic-gate * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
59047c478bd9Sstevel@tonic-gate * In addition, these have special meaning for /proc files:
59057c478bd9Sstevel@tonic-gate * POLLPRI process or lwp stopped on an event of interest
59067c478bd9Sstevel@tonic-gate * POLLERR /proc file descriptor is invalid
59077c478bd9Sstevel@tonic-gate * POLLHUP process or lwp has terminated
59087c478bd9Sstevel@tonic-gate */
5909da6c28aaSamw /*ARGSUSED5*/
59107c478bd9Sstevel@tonic-gate static int
prpoll(vnode_t * vp,short events,int anyyet,short * reventsp,pollhead_t ** phpp,caller_context_t * ct)59117c478bd9Sstevel@tonic-gate prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
5912da6c28aaSamw pollhead_t **phpp, caller_context_t *ct)
59137c478bd9Sstevel@tonic-gate {
59147c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
59157c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
59167c478bd9Sstevel@tonic-gate pollhead_t *php = &pcp->prc_pollhead;
59177c478bd9Sstevel@tonic-gate proc_t *p;
59187c478bd9Sstevel@tonic-gate short revents;
59197c478bd9Sstevel@tonic-gate int error;
59207c478bd9Sstevel@tonic-gate int lockstate;
59217c478bd9Sstevel@tonic-gate
59227c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
59237c478bd9Sstevel@tonic-gate
59247c478bd9Sstevel@tonic-gate /*
59257c478bd9Sstevel@tonic-gate * Support for old /proc interface.
59267c478bd9Sstevel@tonic-gate */
59277c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
59287c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
59297c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
59307c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
59317c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_common == pcp);
59327c478bd9Sstevel@tonic-gate }
59337c478bd9Sstevel@tonic-gate
59347c478bd9Sstevel@tonic-gate *reventsp = revents = 0;
59357c478bd9Sstevel@tonic-gate *phpp = (pollhead_t *)NULL;
59367c478bd9Sstevel@tonic-gate
59377c478bd9Sstevel@tonic-gate if (vp->v_type == VDIR) {
59387c478bd9Sstevel@tonic-gate *reventsp |= POLLNVAL;
59397c478bd9Sstevel@tonic-gate return (0);
59407c478bd9Sstevel@tonic-gate }
59417c478bd9Sstevel@tonic-gate
59427c478bd9Sstevel@tonic-gate lockstate = pollunlock(); /* avoid deadlock with prnotify() */
59437c478bd9Sstevel@tonic-gate
59447c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0) {
59457c478bd9Sstevel@tonic-gate pollrelock(lockstate);
59467c478bd9Sstevel@tonic-gate switch (error) {
59477c478bd9Sstevel@tonic-gate case ENOENT: /* process or lwp died */
59487c478bd9Sstevel@tonic-gate *reventsp = POLLHUP;
59497c478bd9Sstevel@tonic-gate error = 0;
59507c478bd9Sstevel@tonic-gate break;
59517c478bd9Sstevel@tonic-gate case EAGAIN: /* invalidated */
59527c478bd9Sstevel@tonic-gate *reventsp = POLLERR;
59537c478bd9Sstevel@tonic-gate error = 0;
59547c478bd9Sstevel@tonic-gate break;
59557c478bd9Sstevel@tonic-gate }
59567c478bd9Sstevel@tonic-gate return (error);
59577c478bd9Sstevel@tonic-gate }
59587c478bd9Sstevel@tonic-gate
59597c478bd9Sstevel@tonic-gate /*
59607c478bd9Sstevel@tonic-gate * We have the process marked locked (P_PR_LOCK) and we are holding
59617c478bd9Sstevel@tonic-gate * its p->p_lock. We want to unmark the process but retain
59627c478bd9Sstevel@tonic-gate * exclusive control w.r.t. other /proc controlling processes
59637c478bd9Sstevel@tonic-gate * before reacquiring the polling locks.
59647c478bd9Sstevel@tonic-gate *
59657c478bd9Sstevel@tonic-gate * prunmark() does this for us. It unmarks the process
59667c478bd9Sstevel@tonic-gate * but retains p->p_lock so we still have exclusive control.
59677c478bd9Sstevel@tonic-gate * We will drop p->p_lock at the end to relinquish control.
59687c478bd9Sstevel@tonic-gate *
59697c478bd9Sstevel@tonic-gate * We cannot call prunlock() at the end to relinquish control
59707c478bd9Sstevel@tonic-gate * because prunlock(), like prunmark(), may drop and reacquire
59717c478bd9Sstevel@tonic-gate * p->p_lock and that would lead to a lock order violation
59727c478bd9Sstevel@tonic-gate * w.r.t. the polling locks we are about to reacquire.
59737c478bd9Sstevel@tonic-gate */
59747c478bd9Sstevel@tonic-gate p = pcp->prc_proc;
59757c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
59767c478bd9Sstevel@tonic-gate prunmark(p);
59777c478bd9Sstevel@tonic-gate
59787c478bd9Sstevel@tonic-gate pollrelock(lockstate); /* reacquire dropped poll locks */
59797c478bd9Sstevel@tonic-gate
59807c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
59817c478bd9Sstevel@tonic-gate revents = POLLNVAL;
59827c478bd9Sstevel@tonic-gate else {
59837c478bd9Sstevel@tonic-gate short ev;
59847c478bd9Sstevel@tonic-gate
59857c478bd9Sstevel@tonic-gate if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
59867c478bd9Sstevel@tonic-gate revents |= ev;
59877c478bd9Sstevel@tonic-gate /*
59887c478bd9Sstevel@tonic-gate * POLLWRNORM (same as POLLOUT) really should not be
59897c478bd9Sstevel@tonic-gate * used to indicate that the process or lwp stopped.
59907c478bd9Sstevel@tonic-gate * However, USL chose to use POLLWRNORM rather than
59917c478bd9Sstevel@tonic-gate * POLLPRI to indicate this, so we just accept either
59927c478bd9Sstevel@tonic-gate * requested event to indicate stopped. (grr...)
59937c478bd9Sstevel@tonic-gate */
59947c478bd9Sstevel@tonic-gate if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
59957c478bd9Sstevel@tonic-gate kthread_t *t;
59967c478bd9Sstevel@tonic-gate
59977c478bd9Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP) {
59987c478bd9Sstevel@tonic-gate t = pcp->prc_thread;
59997c478bd9Sstevel@tonic-gate ASSERT(t != NULL);
60007c478bd9Sstevel@tonic-gate thread_lock(t);
60017c478bd9Sstevel@tonic-gate } else {
60027c478bd9Sstevel@tonic-gate t = prchoose(p); /* returns locked t */
60037c478bd9Sstevel@tonic-gate ASSERT(t != NULL);
60047c478bd9Sstevel@tonic-gate }
60057c478bd9Sstevel@tonic-gate
60067c478bd9Sstevel@tonic-gate if (ISTOPPED(t) || VSTOPPED(t))
60077c478bd9Sstevel@tonic-gate revents |= ev;
60087c478bd9Sstevel@tonic-gate thread_unlock(t);
60097c478bd9Sstevel@tonic-gate }
60107c478bd9Sstevel@tonic-gate }
60117c478bd9Sstevel@tonic-gate
60127c478bd9Sstevel@tonic-gate *reventsp = revents;
60137c478bd9Sstevel@tonic-gate if (!anyyet && revents == 0) {
60147c478bd9Sstevel@tonic-gate /*
60157c478bd9Sstevel@tonic-gate * Arrange to wake up the polling lwp when
60167c478bd9Sstevel@tonic-gate * the target process/lwp stops or terminates
60177c478bd9Sstevel@tonic-gate * or when the file descriptor becomes invalid.
60187c478bd9Sstevel@tonic-gate */
60197c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_POLL;
60207c478bd9Sstevel@tonic-gate *phpp = php;
60217c478bd9Sstevel@tonic-gate }
60227c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
60237c478bd9Sstevel@tonic-gate return (0);
60247c478bd9Sstevel@tonic-gate }
60257c478bd9Sstevel@tonic-gate
60267c478bd9Sstevel@tonic-gate /* in prioctl.c */
6027da6c28aaSamw extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
6028da6c28aaSamw caller_context_t *);
60297c478bd9Sstevel@tonic-gate
60307c478bd9Sstevel@tonic-gate /*
60317c478bd9Sstevel@tonic-gate * /proc vnode operations vector
60327c478bd9Sstevel@tonic-gate */
60337c478bd9Sstevel@tonic-gate const fs_operation_def_t pr_vnodeops_template[] = {
6034aa59c4cbSrsb VOPNAME_OPEN, { .vop_open = propen },
6035aa59c4cbSrsb VOPNAME_CLOSE, { .vop_close = prclose },
6036aa59c4cbSrsb VOPNAME_READ, { .vop_read = prread },
6037aa59c4cbSrsb VOPNAME_WRITE, { .vop_write = prwrite },
6038aa59c4cbSrsb VOPNAME_IOCTL, { .vop_ioctl = prioctl },
6039aa59c4cbSrsb VOPNAME_GETATTR, { .vop_getattr = prgetattr },
6040aa59c4cbSrsb VOPNAME_ACCESS, { .vop_access = praccess },
6041aa59c4cbSrsb VOPNAME_LOOKUP, { .vop_lookup = prlookup },
6042aa59c4cbSrsb VOPNAME_CREATE, { .vop_create = prcreate },
6043aa59c4cbSrsb VOPNAME_READDIR, { .vop_readdir = prreaddir },
6044aa59c4cbSrsb VOPNAME_READLINK, { .vop_readlink = prreadlink },
6045aa59c4cbSrsb VOPNAME_FSYNC, { .vop_fsync = prfsync },
6046aa59c4cbSrsb VOPNAME_INACTIVE, { .vop_inactive = prinactive },
6047aa59c4cbSrsb VOPNAME_SEEK, { .vop_seek = prseek },
6048aa59c4cbSrsb VOPNAME_CMP, { .vop_cmp = prcmp },
6049aa59c4cbSrsb VOPNAME_FRLOCK, { .error = fs_error },
6050aa59c4cbSrsb VOPNAME_REALVP, { .vop_realvp = prrealvp },
6051aa59c4cbSrsb VOPNAME_POLL, { .vop_poll = prpoll },
6052aa59c4cbSrsb VOPNAME_DISPOSE, { .error = fs_error },
6053aa59c4cbSrsb VOPNAME_SHRLOCK, { .error = fs_error },
60547c478bd9Sstevel@tonic-gate NULL, NULL
60557c478bd9Sstevel@tonic-gate };
6056