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.
24ab618543SJohn Levon * Copyright (c) 2018, Joyent, Inc.
25ade42b55SSebastien Roy * Copyright (c) 2017 by Delphix. All rights reserved.
26a02120c4SAndy Fiddaman * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
27da29c6a3SDan McDonald * Copyright 2022 MNX Cloud, Inc.
28ed093b41SRobert Mustacchi * Copyright 2023 Oxide Computer Company
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
327c478bd9Sstevel@tonic-gate /* All Rights Reserved */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/param.h>
367c478bd9Sstevel@tonic-gate #include <sys/time.h>
377c478bd9Sstevel@tonic-gate #include <sys/cred.h>
387c478bd9Sstevel@tonic-gate #include <sys/policy.h>
397c478bd9Sstevel@tonic-gate #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
417c478bd9Sstevel@tonic-gate #include <sys/errno.h>
427c478bd9Sstevel@tonic-gate #include <sys/file.h>
437c478bd9Sstevel@tonic-gate #include <sys/inline.h>
447c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
457c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
467c478bd9Sstevel@tonic-gate #include <sys/proc.h>
47eb9dbf0cSRoger A. Faulkner #include <sys/brand.h>
487c478bd9Sstevel@tonic-gate #include <sys/signal.h>
497c478bd9Sstevel@tonic-gate #include <sys/stat.h>
507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
517c478bd9Sstevel@tonic-gate #include <sys/systm.h>
527c478bd9Sstevel@tonic-gate #include <sys/zone.h>
537c478bd9Sstevel@tonic-gate #include <sys/uio.h>
547c478bd9Sstevel@tonic-gate #include <sys/var.h>
557c478bd9Sstevel@tonic-gate #include <sys/mode.h>
567c478bd9Sstevel@tonic-gate #include <sys/poll.h>
577c478bd9Sstevel@tonic-gate #include <sys/user.h>
587c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
59aa59c4cbSrsb #include <sys/vfs_opreg.h>
607c478bd9Sstevel@tonic-gate #include <sys/gfs.h>
617c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
627c478bd9Sstevel@tonic-gate #include <sys/fault.h>
637c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
647c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
657c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
667c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
677c478bd9Sstevel@tonic-gate #include <sys/contract_impl.h>
687c478bd9Sstevel@tonic-gate #include <sys/ctfs.h>
697c478bd9Sstevel@tonic-gate #include <sys/avl.h>
70ab618543SJohn Levon #include <sys/ctype.h>
717c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
727c478bd9Sstevel@tonic-gate #include <vm/rm.h>
737c478bd9Sstevel@tonic-gate #include <vm/as.h>
747c478bd9Sstevel@tonic-gate #include <vm/seg.h>
757c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
767c478bd9Sstevel@tonic-gate #include <vm/hat.h>
777c478bd9Sstevel@tonic-gate #include <fs/proc/prdata.h>
787c478bd9Sstevel@tonic-gate #if defined(__sparc)
797c478bd9Sstevel@tonic-gate #include <sys/regset.h>
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate #if defined(__x86)
827c478bd9Sstevel@tonic-gate #include <sys/sysi86.h>
837c478bd9Sstevel@tonic-gate #endif
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate * Created by prinit.
877c478bd9Sstevel@tonic-gate */
887c478bd9Sstevel@tonic-gate vnodeops_t *prvnodeops;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate * Directory characteristics (patterned after the s5 file system).
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate #define PRROOTINO 2
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate #define PRDIRSIZE 14
967c478bd9Sstevel@tonic-gate struct prdirect {
977c478bd9Sstevel@tonic-gate ushort_t d_ino;
987c478bd9Sstevel@tonic-gate char d_name[PRDIRSIZE];
997c478bd9Sstevel@tonic-gate };
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate #define PRSDSIZE (sizeof (struct prdirect))
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * Directory characteristics.
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate typedef struct prdirent {
1077c478bd9Sstevel@tonic-gate ino64_t d_ino; /* "inode number" of entry */
1087c478bd9Sstevel@tonic-gate off64_t d_off; /* offset of disk directory entry */
1097c478bd9Sstevel@tonic-gate unsigned short d_reclen; /* length of this record */
1107c478bd9Sstevel@tonic-gate char d_name[14]; /* name of file */
1117c478bd9Sstevel@tonic-gate } prdirent_t;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate * Contents of a /proc/<pid> directory.
1157c478bd9Sstevel@tonic-gate * Reuse d_ino field for the /proc file type.
1167c478bd9Sstevel@tonic-gate */
1177c478bd9Sstevel@tonic-gate static prdirent_t piddir[] = {
1187c478bd9Sstevel@tonic-gate { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
1197c478bd9Sstevel@tonic-gate "." },
1207c478bd9Sstevel@tonic-gate { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
1217c478bd9Sstevel@tonic-gate ".." },
1227c478bd9Sstevel@tonic-gate { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
1237c478bd9Sstevel@tonic-gate "as" },
1247c478bd9Sstevel@tonic-gate { PR_CTL, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
1257c478bd9Sstevel@tonic-gate "ctl" },
1267c478bd9Sstevel@tonic-gate { PR_STATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
1277c478bd9Sstevel@tonic-gate "status" },
1287c478bd9Sstevel@tonic-gate { PR_LSTATUS, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
1297c478bd9Sstevel@tonic-gate "lstatus" },
1307c478bd9Sstevel@tonic-gate { PR_PSINFO, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
1317c478bd9Sstevel@tonic-gate "psinfo" },
1327c478bd9Sstevel@tonic-gate { PR_LPSINFO, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
1337c478bd9Sstevel@tonic-gate "lpsinfo" },
1347c478bd9Sstevel@tonic-gate { PR_MAP, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
1357c478bd9Sstevel@tonic-gate "map" },
1367c478bd9Sstevel@tonic-gate { PR_RMAP, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
1377c478bd9Sstevel@tonic-gate "rmap" },
1387c478bd9Sstevel@tonic-gate { PR_XMAP, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
1397c478bd9Sstevel@tonic-gate "xmap" },
1407c478bd9Sstevel@tonic-gate { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
1417c478bd9Sstevel@tonic-gate "cred" },
1427c478bd9Sstevel@tonic-gate { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
1437c478bd9Sstevel@tonic-gate "sigact" },
1447c478bd9Sstevel@tonic-gate { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
1457c478bd9Sstevel@tonic-gate "auxv" },
1467c478bd9Sstevel@tonic-gate { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
1477c478bd9Sstevel@tonic-gate "usage" },
1487c478bd9Sstevel@tonic-gate { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
1497c478bd9Sstevel@tonic-gate "lusage" },
1507c478bd9Sstevel@tonic-gate { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
1517c478bd9Sstevel@tonic-gate "pagedata" },
1527c478bd9Sstevel@tonic-gate { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
1537c478bd9Sstevel@tonic-gate "watch" },
1547c478bd9Sstevel@tonic-gate { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
1557c478bd9Sstevel@tonic-gate "cwd" },
1567c478bd9Sstevel@tonic-gate { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
1577c478bd9Sstevel@tonic-gate "root" },
1587c478bd9Sstevel@tonic-gate { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
1597c478bd9Sstevel@tonic-gate "fd" },
160a02120c4SAndy Fiddaman { PR_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
161a02120c4SAndy Fiddaman "fdinfo" },
162a02120c4SAndy Fiddaman { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
1637c478bd9Sstevel@tonic-gate "object" },
164a02120c4SAndy Fiddaman { PR_LWPDIR, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
1657c478bd9Sstevel@tonic-gate "lwp" },
166a02120c4SAndy Fiddaman { PR_PRIV, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
1677c478bd9Sstevel@tonic-gate "priv" },
168a02120c4SAndy Fiddaman { PR_PATHDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
1697c478bd9Sstevel@tonic-gate "path" },
170a02120c4SAndy Fiddaman { PR_CTDIR, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
1717c478bd9Sstevel@tonic-gate "contracts" },
172a02120c4SAndy Fiddaman { PR_SECFLAGS, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
173d2a70789SRichard Lowe "secflags" },
1747c478bd9Sstevel@tonic-gate #if defined(__x86)
175a02120c4SAndy Fiddaman { PR_LDT, 29 * sizeof (prdirent_t), sizeof (prdirent_t),
1767c478bd9Sstevel@tonic-gate "ldt" },
1777c478bd9Sstevel@tonic-gate #endif
1787c478bd9Sstevel@tonic-gate };
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * Contents of a /proc/<pid>/lwp/<lwpid> directory.
1847c478bd9Sstevel@tonic-gate */
1857c478bd9Sstevel@tonic-gate static prdirent_t lwpiddir[] = {
1867c478bd9Sstevel@tonic-gate { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
1877c478bd9Sstevel@tonic-gate "." },
1887c478bd9Sstevel@tonic-gate { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
1897c478bd9Sstevel@tonic-gate ".." },
1907c478bd9Sstevel@tonic-gate { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
1917c478bd9Sstevel@tonic-gate "lwpctl" },
192ab618543SJohn Levon { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
193ab618543SJohn Levon "lwpname" },
194ab618543SJohn Levon { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
1957c478bd9Sstevel@tonic-gate "lwpstatus" },
196ab618543SJohn Levon { PR_LWPSINFO, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
1977c478bd9Sstevel@tonic-gate "lwpsinfo" },
198ab618543SJohn Levon { PR_LWPUSAGE, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
1997c478bd9Sstevel@tonic-gate "lwpusage" },
200ab618543SJohn Levon { PR_XREGS, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
2017c478bd9Sstevel@tonic-gate "xregs" },
202ab618543SJohn Levon { PR_TMPLDIR, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
2037c478bd9Sstevel@tonic-gate "templates" },
204ab618543SJohn Levon { PR_SPYMASTER, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
205f971a346SBryan Cantrill "spymaster" },
2067c478bd9Sstevel@tonic-gate #if defined(__sparc)
207ab618543SJohn Levon { PR_GWINDOWS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
2087c478bd9Sstevel@tonic-gate "gwindows" },
209ab618543SJohn Levon { PR_ASRS, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
2107c478bd9Sstevel@tonic-gate "asrs" },
2117c478bd9Sstevel@tonic-gate #endif
2127c478bd9Sstevel@tonic-gate };
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate #define NLWPIDDIRFILES (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * Span of entries in the array files (lstatus, lpsinfo, lusage).
2187c478bd9Sstevel@tonic-gate * We make the span larger than the size of the structure on purpose,
2197c478bd9Sstevel@tonic-gate * to make sure that programs cannot use the structure size by mistake.
2207c478bd9Sstevel@tonic-gate * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate #ifdef _LP64
2237c478bd9Sstevel@tonic-gate #define LSPAN(type) (round16(sizeof (type)) + 16)
2247c478bd9Sstevel@tonic-gate #define LSPAN32(type) (round8(sizeof (type)) + 8)
2257c478bd9Sstevel@tonic-gate #else
2267c478bd9Sstevel@tonic-gate #define LSPAN(type) (round8(sizeof (type)) + 8)
2277c478bd9Sstevel@tonic-gate #endif
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate static void rebuild_objdir(struct as *);
2307c478bd9Sstevel@tonic-gate static void prfreecommon(prcommon_t *);
231da6c28aaSamw static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate static int
propen(vnode_t ** vpp,int flag,cred_t * cr,caller_context_t * ct)234da6c28aaSamw propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate vnode_t *vp = *vpp;
2377c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
2387c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_pcommon;
2397c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
2407c478bd9Sstevel@tonic-gate vnode_t *rvp;
2417c478bd9Sstevel@tonic-gate vtype_t vtype;
2427c478bd9Sstevel@tonic-gate proc_t *p;
2437c478bd9Sstevel@tonic-gate int error = 0;
2447c478bd9Sstevel@tonic-gate prnode_t *npnp = NULL;
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate * Nothing to do for the /proc directory itself.
2487c478bd9Sstevel@tonic-gate */
2497c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR)
2507c478bd9Sstevel@tonic-gate return (0);
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate * If we are opening an underlying mapped object, reject opens
2547c478bd9Sstevel@tonic-gate * for writing regardless of the objects's access modes.
2557c478bd9Sstevel@tonic-gate * If we are opening a file in the /proc/pid/fd directory,
2567c478bd9Sstevel@tonic-gate * reject the open for any but a regular file or directory.
2577c478bd9Sstevel@tonic-gate * Just do it if we are opening the current or root directory.
2587c478bd9Sstevel@tonic-gate */
2597c478bd9Sstevel@tonic-gate switch (type) {
2607c478bd9Sstevel@tonic-gate case PR_OBJECT:
2617c478bd9Sstevel@tonic-gate case PR_FD:
2627c478bd9Sstevel@tonic-gate case PR_CURDIR:
2637c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
2647c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
2657c478bd9Sstevel@tonic-gate vtype = rvp->v_type;
2667c478bd9Sstevel@tonic-gate if ((type == PR_OBJECT && (flag & FWRITE)) ||
2677c478bd9Sstevel@tonic-gate (type == PR_FD && vtype != VREG && vtype != VDIR))
2687c478bd9Sstevel@tonic-gate error = EACCES;
2697c478bd9Sstevel@tonic-gate else {
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate * Need to hold rvp since VOP_OPEN() may release it.
2727c478bd9Sstevel@tonic-gate */
2737c478bd9Sstevel@tonic-gate VN_HOLD(rvp);
274da6c28aaSamw error = VOP_OPEN(&rvp, flag, cr, ct);
2757c478bd9Sstevel@tonic-gate if (error) {
2767c478bd9Sstevel@tonic-gate VN_RELE(rvp);
2777c478bd9Sstevel@tonic-gate } else {
2787c478bd9Sstevel@tonic-gate *vpp = rvp;
2797c478bd9Sstevel@tonic-gate VN_RELE(vp);
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate return (error);
2837c478bd9Sstevel@tonic-gate default:
2847c478bd9Sstevel@tonic-gate break;
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * If we are opening the pagedata file, allocate a prnode now
2897c478bd9Sstevel@tonic-gate * to avoid calling kmem_alloc() while holding p->p_lock.
2907c478bd9Sstevel@tonic-gate */
2917c478bd9Sstevel@tonic-gate if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
2927c478bd9Sstevel@tonic-gate npnp = prgetnode(vp, type);
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * If the process exists, lock it now.
2967c478bd9Sstevel@tonic-gate * Otherwise we have a race condition with prclose().
2977c478bd9Sstevel@tonic-gate */
2987c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
2997c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
3007c478bd9Sstevel@tonic-gate if (p == NULL) {
3017c478bd9Sstevel@tonic-gate if (npnp != NULL)
3027c478bd9Sstevel@tonic-gate prfreenode(npnp);
3037c478bd9Sstevel@tonic-gate return (ENOENT);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
3067c478bd9Sstevel@tonic-gate ASSERT(p->p_proc_flag & P_PR_LOCK);
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * Maintain a count of opens for write. Allow exactly one
3107c478bd9Sstevel@tonic-gate * O_WRITE|O_EXCL request and fail subsequent ones.
3117c478bd9Sstevel@tonic-gate * Don't fail opens of old (bletch!) /proc lwp files.
3127c478bd9Sstevel@tonic-gate * Special case for open by the process itself:
3137c478bd9Sstevel@tonic-gate * Always allow the open by self and discount this
3147c478bd9Sstevel@tonic-gate * open for other opens for writing.
3157c478bd9Sstevel@tonic-gate */
3167c478bd9Sstevel@tonic-gate if (flag & FWRITE) {
3177c478bd9Sstevel@tonic-gate if (p == curproc) {
3187c478bd9Sstevel@tonic-gate pcp->prc_selfopens++;
3197c478bd9Sstevel@tonic-gate pnp->pr_flags |= PR_ISSELF;
3207c478bd9Sstevel@tonic-gate } else if (type == PR_LWPIDFILE) {
3217c478bd9Sstevel@tonic-gate /* EMPTY */;
3227c478bd9Sstevel@tonic-gate } else if (flag & FEXCL) {
3237c478bd9Sstevel@tonic-gate if (pcp->prc_writers > pcp->prc_selfopens) {
3247c478bd9Sstevel@tonic-gate error = EBUSY;
3257c478bd9Sstevel@tonic-gate goto out;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate /* semantic for old /proc interface */
3287c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR)
3297c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_EXCL;
3307c478bd9Sstevel@tonic-gate } else if (pcp->prc_flags & PRC_EXCL) {
3317c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers > pcp->prc_selfopens);
3327c478bd9Sstevel@tonic-gate error = secpolicy_proc_excl_open(cr);
3337c478bd9Sstevel@tonic-gate if (error)
3347c478bd9Sstevel@tonic-gate goto out;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate pcp->prc_writers++;
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate * The vnode may have become invalid between the
3397c478bd9Sstevel@tonic-gate * VOP_LOOKUP() of the /proc vnode and the VOP_OPEN().
3407c478bd9Sstevel@tonic-gate * If so, do now what prinvalidate() should have done.
3417c478bd9Sstevel@tonic-gate */
3427c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & PR_INVAL) ||
3437c478bd9Sstevel@tonic-gate (type == PR_PIDDIR &&
3447c478bd9Sstevel@tonic-gate (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
3457c478bd9Sstevel@tonic-gate if (p != curproc)
3467c478bd9Sstevel@tonic-gate pcp->prc_selfopens++;
3477c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
3487c478bd9Sstevel@tonic-gate if (pcp->prc_selfopens == pcp->prc_writers)
3497c478bd9Sstevel@tonic-gate pcp->prc_flags &= ~PRC_EXCL;
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /*
354d1b18d1aSBryan Cantrill * If this is a large file open, indicate that in our flags -- some
355d1b18d1aSBryan Cantrill * procfs structures are not off_t-neutral (e.g., priovec_t), and
356d1b18d1aSBryan Cantrill * the open will need to be differentiated where 32-bit processes
357d1b18d1aSBryan Cantrill * pass these structures across the user/kernel boundary.
358d1b18d1aSBryan Cantrill */
359d1b18d1aSBryan Cantrill if (flag & FOFFMAX)
360d1b18d1aSBryan Cantrill pnp->pr_flags |= PR_OFFMAX;
361d1b18d1aSBryan Cantrill
362d1b18d1aSBryan Cantrill /*
3637c478bd9Sstevel@tonic-gate * Do file-specific things.
3647c478bd9Sstevel@tonic-gate */
3657c478bd9Sstevel@tonic-gate switch (type) {
3667c478bd9Sstevel@tonic-gate default:
3677c478bd9Sstevel@tonic-gate break;
3687c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
3697c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
3707c478bd9Sstevel@tonic-gate /*
3717c478bd9Sstevel@tonic-gate * Enable data collection for page data file;
3727c478bd9Sstevel@tonic-gate * get unique id from the hat layer.
3737c478bd9Sstevel@tonic-gate */
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate int id;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * Drop p->p_lock to call hat_startstat()
3797c478bd9Sstevel@tonic-gate */
3807c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3817c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas ||
3827c478bd9Sstevel@tonic-gate (id = hat_startstat(p->p_as)) == -1) {
3837c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3847c478bd9Sstevel@tonic-gate error = ENOMEM;
3857c478bd9Sstevel@tonic-gate } else if (pnp->pr_hatid == 0) {
3867c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3877c478bd9Sstevel@tonic-gate pnp->pr_hatid = (uint_t)id;
3887c478bd9Sstevel@tonic-gate } else {
3897c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3907c478bd9Sstevel@tonic-gate /*
3917c478bd9Sstevel@tonic-gate * Use our newly allocated prnode.
3927c478bd9Sstevel@tonic-gate */
3937c478bd9Sstevel@tonic-gate npnp->pr_hatid = (uint_t)id;
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
3967c478bd9Sstevel@tonic-gate * Duplicate the remainder.
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate npnp->pr_ino = pnp->pr_ino;
3997c478bd9Sstevel@tonic-gate npnp->pr_common = pnp->pr_common;
4007c478bd9Sstevel@tonic-gate npnp->pr_pcommon = pnp->pr_pcommon;
4017c478bd9Sstevel@tonic-gate npnp->pr_parent = pnp->pr_parent;
4027c478bd9Sstevel@tonic-gate VN_HOLD(npnp->pr_parent);
4037c478bd9Sstevel@tonic-gate npnp->pr_index = pnp->pr_index;
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate npnp->pr_next = p->p_plist;
4067c478bd9Sstevel@tonic-gate p->p_plist = PTOV(npnp);
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate VN_RELE(PTOV(pnp));
4097c478bd9Sstevel@tonic-gate pnp = npnp;
4107c478bd9Sstevel@tonic-gate npnp = NULL;
4117c478bd9Sstevel@tonic-gate *vpp = PTOV(pnp);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate break;
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate out:
4187c478bd9Sstevel@tonic-gate prunlock(pnp);
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate if (npnp != NULL)
4217c478bd9Sstevel@tonic-gate prfreenode(npnp);
4227c478bd9Sstevel@tonic-gate return (error);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /* ARGSUSED */
4267c478bd9Sstevel@tonic-gate static int
prclose(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)427da6c28aaSamw prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
428da6c28aaSamw caller_context_t *ct)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
4317c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_pcommon;
4327c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
4337c478bd9Sstevel@tonic-gate proc_t *p;
4347c478bd9Sstevel@tonic-gate kthread_t *t;
4357c478bd9Sstevel@tonic-gate user_t *up;
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * Nothing to do for the /proc directory itself.
4397c478bd9Sstevel@tonic-gate */
4407c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR)
4417c478bd9Sstevel@tonic-gate return (0);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate ASSERT(type != PR_OBJECT && type != PR_FD &&
4447c478bd9Sstevel@tonic-gate type != PR_CURDIR && type != PR_ROOTDIR);
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate * If the process exists, lock it now.
4487c478bd9Sstevel@tonic-gate * Otherwise we have a race condition with propen().
4497c478bd9Sstevel@tonic-gate * Hold pr_pidlock across the reference to prc_selfopens,
4507c478bd9Sstevel@tonic-gate * and prc_writers in case there is no process anymore,
4517c478bd9Sstevel@tonic-gate * to cover the case of concurrent calls to prclose()
4527c478bd9Sstevel@tonic-gate * after the process has been reaped by freeproc().
4537c478bd9Sstevel@tonic-gate */
4547c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate * There is nothing more to do until the last close of
4587c478bd9Sstevel@tonic-gate * the file table entry except to clear the pr_owner
4597c478bd9Sstevel@tonic-gate * field of the prnode and notify any waiters
4607c478bd9Sstevel@tonic-gate * (their file descriptor may have just been closed).
4617c478bd9Sstevel@tonic-gate */
4627c478bd9Sstevel@tonic-gate if (count > 1) {
4637c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
4647c478bd9Sstevel@tonic-gate if (pnp->pr_owner == curproc && !fisopen(vp))
4657c478bd9Sstevel@tonic-gate pnp->pr_owner = NULL;
4667c478bd9Sstevel@tonic-gate if (p != NULL) {
4677c478bd9Sstevel@tonic-gate prnotify(vp);
4687c478bd9Sstevel@tonic-gate prunlock(pnp);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate return (0);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate * Decrement the count of self-opens for writing.
4757c478bd9Sstevel@tonic-gate * Decrement the total count of opens for writing.
4767c478bd9Sstevel@tonic-gate * Cancel exclusive opens when only self-opens remain.
4777c478bd9Sstevel@tonic-gate */
4787c478bd9Sstevel@tonic-gate if (flag & FWRITE) {
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * prc_selfopens also contains the count of
4817c478bd9Sstevel@tonic-gate * invalid writers. See prinvalidate().
4827c478bd9Sstevel@tonic-gate */
4837c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
4847c478bd9Sstevel@tonic-gate (type == PR_PIDDIR &&
4857c478bd9Sstevel@tonic-gate (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
4867c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens != 0);
4877c478bd9Sstevel@tonic-gate --pcp->prc_selfopens;
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers != 0);
4907c478bd9Sstevel@tonic-gate if (--pcp->prc_writers == pcp->prc_selfopens)
4917c478bd9Sstevel@tonic-gate pcp->prc_flags &= ~PRC_EXCL;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
4947c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
4957c478bd9Sstevel@tonic-gate if (pnp->pr_owner == curproc && !fisopen(vp))
4967c478bd9Sstevel@tonic-gate pnp->pr_owner = NULL;
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate /*
4997c478bd9Sstevel@tonic-gate * If there is no process, there is nothing more to do.
5007c478bd9Sstevel@tonic-gate */
5017c478bd9Sstevel@tonic-gate if (p == NULL)
5027c478bd9Sstevel@tonic-gate return (0);
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate ASSERT(p == pcp->prc_proc);
5057c478bd9Sstevel@tonic-gate prnotify(vp); /* notify waiters */
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * Do file-specific things.
5097c478bd9Sstevel@tonic-gate */
5107c478bd9Sstevel@tonic-gate switch (type) {
5117c478bd9Sstevel@tonic-gate default:
5127c478bd9Sstevel@tonic-gate break;
5137c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
5147c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate * This is a page data file.
5177c478bd9Sstevel@tonic-gate * Free the hat level statistics.
5187c478bd9Sstevel@tonic-gate * Drop p->p_lock before calling hat_freestat().
5197c478bd9Sstevel@tonic-gate */
5207c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
5217c478bd9Sstevel@tonic-gate if (p->p_as != &kas && pnp->pr_hatid != 0)
5227c478bd9Sstevel@tonic-gate hat_freestat(p->p_as, pnp->pr_hatid);
5237c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
5247c478bd9Sstevel@tonic-gate pnp->pr_hatid = 0;
5257c478bd9Sstevel@tonic-gate break;
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * On last close of all writable file descriptors,
5307c478bd9Sstevel@tonic-gate * perform run-on-last-close and/or kill-on-last-close logic.
5317c478bd9Sstevel@tonic-gate * Can't do this is the /proc agent lwp still exists.
5327c478bd9Sstevel@tonic-gate */
5337c478bd9Sstevel@tonic-gate if (pcp->prc_writers == 0 &&
5347c478bd9Sstevel@tonic-gate p->p_agenttp == NULL &&
5357c478bd9Sstevel@tonic-gate !(pcp->prc_flags & PRC_DESTROY) &&
5367c478bd9Sstevel@tonic-gate p->p_stat != SZOMB &&
5377c478bd9Sstevel@tonic-gate (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
5387c478bd9Sstevel@tonic-gate int killproc;
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate * Cancel any watchpoints currently in effect.
5427c478bd9Sstevel@tonic-gate * The process might disappear during this operation.
5437c478bd9Sstevel@tonic-gate */
5447c478bd9Sstevel@tonic-gate if (pr_cancel_watch(pnp) == NULL)
5457c478bd9Sstevel@tonic-gate return (0);
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * If any tracing flags are set, clear them.
5487c478bd9Sstevel@tonic-gate */
5497c478bd9Sstevel@tonic-gate if (p->p_proc_flag & P_PR_TRACE) {
5507c478bd9Sstevel@tonic-gate up = PTOU(p);
5517c478bd9Sstevel@tonic-gate premptyset(&up->u_entrymask);
5527c478bd9Sstevel@tonic-gate premptyset(&up->u_exitmask);
5537c478bd9Sstevel@tonic-gate up->u_systrap = 0;
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate premptyset(&p->p_sigmask);
5567c478bd9Sstevel@tonic-gate premptyset(&p->p_fltmask);
5577c478bd9Sstevel@tonic-gate killproc = (p->p_proc_flag & P_PR_KILLCL);
5587c478bd9Sstevel@tonic-gate p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate * Cancel any outstanding single-step requests.
5617c478bd9Sstevel@tonic-gate */
5627c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL) {
5637c478bd9Sstevel@tonic-gate /*
5647c478bd9Sstevel@tonic-gate * Drop p_lock because prnostep() touches the stack.
5657c478bd9Sstevel@tonic-gate * The loop is safe because the process is P_PR_LOCK'd.
5667c478bd9Sstevel@tonic-gate */
5677c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
5687c478bd9Sstevel@tonic-gate do {
5697c478bd9Sstevel@tonic-gate prnostep(ttolwp(t));
5707c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
5717c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate /*
5747c478bd9Sstevel@tonic-gate * Set runnable all lwps stopped by /proc.
5757c478bd9Sstevel@tonic-gate */
5767c478bd9Sstevel@tonic-gate if (killproc)
5777c478bd9Sstevel@tonic-gate sigtoproc(p, NULL, SIGKILL);
5787c478bd9Sstevel@tonic-gate else
5797c478bd9Sstevel@tonic-gate allsetrun(p);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate prunlock(pnp);
5837c478bd9Sstevel@tonic-gate return (0);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * Array of read functions, indexed by /proc file type.
5887c478bd9Sstevel@tonic-gate */
5897c478bd9Sstevel@tonic-gate static int pr_read_inval(), pr_read_as(), pr_read_status(),
5907c478bd9Sstevel@tonic-gate pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
5917c478bd9Sstevel@tonic-gate pr_read_map(), pr_read_rmap(), pr_read_xmap(),
5927c478bd9Sstevel@tonic-gate pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
5937c478bd9Sstevel@tonic-gate #if defined(__x86)
5947c478bd9Sstevel@tonic-gate pr_read_ldt(),
5957c478bd9Sstevel@tonic-gate #endif
5967c478bd9Sstevel@tonic-gate pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
5977c478bd9Sstevel@tonic-gate pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
598ab618543SJohn Levon pr_read_lwpusage(), pr_read_lwpname(),
599ab618543SJohn Levon pr_read_xregs(), pr_read_priv(),
600d2a70789SRichard Lowe pr_read_spymaster(), pr_read_secflags(),
6017c478bd9Sstevel@tonic-gate #if defined(__sparc)
6027c478bd9Sstevel@tonic-gate pr_read_gwindows(), pr_read_asrs(),
6037c478bd9Sstevel@tonic-gate #endif
604a02120c4SAndy Fiddaman pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
605a02120c4SAndy Fiddaman pr_read_fdinfo();
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate static int (*pr_read_function[PR_NFILES])() = {
6087c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc */
6097c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/self */
6107c478bd9Sstevel@tonic-gate pr_read_piddir, /* /proc/<pid> (old /proc read()) */
6117c478bd9Sstevel@tonic-gate pr_read_as, /* /proc/<pid>/as */
6127c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/ctl */
6137c478bd9Sstevel@tonic-gate pr_read_status, /* /proc/<pid>/status */
6147c478bd9Sstevel@tonic-gate pr_read_lstatus, /* /proc/<pid>/lstatus */
6157c478bd9Sstevel@tonic-gate pr_read_psinfo, /* /proc/<pid>/psinfo */
6167c478bd9Sstevel@tonic-gate pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
6177c478bd9Sstevel@tonic-gate pr_read_map, /* /proc/<pid>/map */
6187c478bd9Sstevel@tonic-gate pr_read_rmap, /* /proc/<pid>/rmap */
6197c478bd9Sstevel@tonic-gate pr_read_xmap, /* /proc/<pid>/xmap */
6207c478bd9Sstevel@tonic-gate pr_read_cred, /* /proc/<pid>/cred */
6217c478bd9Sstevel@tonic-gate pr_read_sigact, /* /proc/<pid>/sigact */
6227c478bd9Sstevel@tonic-gate pr_read_auxv, /* /proc/<pid>/auxv */
6237c478bd9Sstevel@tonic-gate #if defined(__x86)
6247c478bd9Sstevel@tonic-gate pr_read_ldt, /* /proc/<pid>/ldt */
6257c478bd9Sstevel@tonic-gate #endif
6267c478bd9Sstevel@tonic-gate pr_read_usage, /* /proc/<pid>/usage */
6277c478bd9Sstevel@tonic-gate pr_read_lusage, /* /proc/<pid>/lusage */
6287c478bd9Sstevel@tonic-gate pr_read_pagedata, /* /proc/<pid>/pagedata */
6297c478bd9Sstevel@tonic-gate pr_read_watch, /* /proc/<pid>/watch */
6307c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/cwd */
6317c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/root */
6327c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd */
6337c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd/nn */
634a02120c4SAndy Fiddaman pr_read_inval, /* /proc/<pid>/fdinfo */
635a02120c4SAndy Fiddaman pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
6367c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object */
6377c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object/xxx */
6387c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp */
6397c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
6407c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
641ab618543SJohn Levon pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
6427c478bd9Sstevel@tonic-gate pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
6437c478bd9Sstevel@tonic-gate pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
6447c478bd9Sstevel@tonic-gate pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
6457c478bd9Sstevel@tonic-gate pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
6467c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
6477c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
648f971a346SBryan Cantrill pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
6497c478bd9Sstevel@tonic-gate #if defined(__sparc)
6507c478bd9Sstevel@tonic-gate pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
6517c478bd9Sstevel@tonic-gate pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
6527c478bd9Sstevel@tonic-gate #endif
6537c478bd9Sstevel@tonic-gate pr_read_priv, /* /proc/<pid>/priv */
6547c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path */
6557c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path/xxx */
6567c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts */
6577c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
658d2a70789SRichard Lowe pr_read_secflags, /* /proc/<pid>/secflags */
6597c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old process file */
6607c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old lwp file */
6617c478bd9Sstevel@tonic-gate pr_read_opagedata, /* old pagedata file */
6627c478bd9Sstevel@tonic-gate };
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate /* ARGSUSED */
6657c478bd9Sstevel@tonic-gate static int
pr_read_inval(prnode_t * pnp,uio_t * uiop,cred_t * cr)66619ee9cd1SAndy Fiddaman pr_read_inval(prnode_t *pnp, uio_t *uiop, cred_t *cr)
6677c478bd9Sstevel@tonic-gate {
6687c478bd9Sstevel@tonic-gate /*
6697c478bd9Sstevel@tonic-gate * No read() on any /proc directory, use getdents(2) instead.
6707c478bd9Sstevel@tonic-gate * Cannot read a control file either.
6717c478bd9Sstevel@tonic-gate * An underlying mapped object file cannot get here.
6727c478bd9Sstevel@tonic-gate */
6737c478bd9Sstevel@tonic-gate return (EINVAL);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate static int
pr_uioread(void * base,long count,uio_t * uiop)6777c478bd9Sstevel@tonic-gate pr_uioread(void *base, long count, uio_t *uiop)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate int error = 0;
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate ASSERT(count >= 0);
6827c478bd9Sstevel@tonic-gate count -= uiop->uio_offset;
6837c478bd9Sstevel@tonic-gate if (count > 0 && uiop->uio_offset >= 0) {
6847c478bd9Sstevel@tonic-gate error = uiomove((char *)base + uiop->uio_offset,
6857c478bd9Sstevel@tonic-gate count, UIO_READ, uiop);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate return (error);
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate static int
pr_read_as(prnode_t * pnp,uio_t * uiop)6927c478bd9Sstevel@tonic-gate pr_read_as(prnode_t *pnp, uio_t *uiop)
6937c478bd9Sstevel@tonic-gate {
6947c478bd9Sstevel@tonic-gate int error;
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AS);
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
6997c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
7007c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate /*
7037c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
7047c478bd9Sstevel@tonic-gate * A 32-bit process cannot read a 64-bit process.
7057c478bd9Sstevel@tonic-gate */
7067c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
7077c478bd9Sstevel@tonic-gate error = 0;
7087c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
7097c478bd9Sstevel@tonic-gate } else if (curproc->p_model == DATAMODEL_ILP32 &&
7107c478bd9Sstevel@tonic-gate PROCESS_NOT_32BIT(p)) {
7117c478bd9Sstevel@tonic-gate error = EOVERFLOW;
7127c478bd9Sstevel@tonic-gate #endif
7137c478bd9Sstevel@tonic-gate } else {
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate * We don't hold p_lock over an i/o operation because
7167c478bd9Sstevel@tonic-gate * that could lead to deadlock with the clock thread.
7177c478bd9Sstevel@tonic-gate */
7187c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
7197c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_READ, uiop, 0);
7207c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate prunlock(pnp);
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate return (error);
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate static int
pr_read_status(prnode_t * pnp,uio_t * uiop,cred_t * cr)72919ee9cd1SAndy Fiddaman pr_read_status(prnode_t *pnp, uio_t *uiop, cred_t *cr)
7307c478bd9Sstevel@tonic-gate {
7317c478bd9Sstevel@tonic-gate pstatus_t *sp;
7327c478bd9Sstevel@tonic-gate int error;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_STATUS);
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate /*
7377c478bd9Sstevel@tonic-gate * We kmem_alloc() the pstatus structure because
7387c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
7397c478bd9Sstevel@tonic-gate */
7407c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
7417c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
742fa9e4066Sahrens prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
7437c478bd9Sstevel@tonic-gate prunlock(pnp);
7447c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
7477c478bd9Sstevel@tonic-gate return (error);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate static int
pr_read_lstatus(prnode_t * pnp,uio_t * uiop,cred_t * cr)75119ee9cd1SAndy Fiddaman pr_read_lstatus(prnode_t *pnp, uio_t *uiop, cred_t *cr)
7527c478bd9Sstevel@tonic-gate {
7537c478bd9Sstevel@tonic-gate proc_t *p;
7547c478bd9Sstevel@tonic-gate kthread_t *t;
7557c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
7567c478bd9Sstevel@tonic-gate size_t size;
7577c478bd9Sstevel@tonic-gate prheader_t *php;
7587c478bd9Sstevel@tonic-gate lwpstatus_t *sp;
7597c478bd9Sstevel@tonic-gate int error;
7607c478bd9Sstevel@tonic-gate int nlwp;
7617c478bd9Sstevel@tonic-gate int i;
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LSTATUS);
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
7667c478bd9Sstevel@tonic-gate return (error);
7677c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
7687c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt;
7697c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
7727c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
7737c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
7747c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
7757c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
7767c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
7797c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(lwpstatus_t);
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate sp = (lwpstatus_t *)(php + 1);
7827c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
7837c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
7847c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
7857c478bd9Sstevel@tonic-gate continue;
786fa9e4066Sahrens prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
7877c478bd9Sstevel@tonic-gate sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate prunlock(pnp);
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
7927c478bd9Sstevel@tonic-gate kmem_free(php, size);
7937c478bd9Sstevel@tonic-gate return (error);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate
7967c478bd9Sstevel@tonic-gate static int
pr_read_psinfo(prnode_t * pnp,uio_t * uiop,cred_t * cr)79719ee9cd1SAndy Fiddaman pr_read_psinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
7987c478bd9Sstevel@tonic-gate {
7997c478bd9Sstevel@tonic-gate psinfo_t psinfo;
8007c478bd9Sstevel@tonic-gate proc_t *p;
8017c478bd9Sstevel@tonic-gate int error = 0;
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PSINFO);
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
8077c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
8087c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
8097c478bd9Sstevel@tonic-gate */
8107c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
8117c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
8127c478bd9Sstevel@tonic-gate if (p == NULL)
8137c478bd9Sstevel@tonic-gate error = ENOENT;
8147c478bd9Sstevel@tonic-gate else {
8157c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
8167c478bd9Sstevel@tonic-gate prgetpsinfo(p, &psinfo);
8177c478bd9Sstevel@tonic-gate prunlock(pnp);
8187c478bd9Sstevel@tonic-gate error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate return (error);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate static int
pr_read_fdinfo(prnode_t * pnp,uio_t * uiop,cred_t * cr)82419ee9cd1SAndy Fiddaman pr_read_fdinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
825a02120c4SAndy Fiddaman {
826a02120c4SAndy Fiddaman prfdinfo_t *fdinfo;
827a02120c4SAndy Fiddaman list_t data;
828a02120c4SAndy Fiddaman proc_t *p;
829a02120c4SAndy Fiddaman uint_t fd;
830a02120c4SAndy Fiddaman file_t *fp;
831a02120c4SAndy Fiddaman short ufp_flag;
832a02120c4SAndy Fiddaman int error = 0;
833a02120c4SAndy Fiddaman
834a02120c4SAndy Fiddaman ASSERT(pnp->pr_type == PR_FDINFO);
835a02120c4SAndy Fiddaman
836a02120c4SAndy Fiddaman /*
837a02120c4SAndy Fiddaman * This is a guess at the size of the structure that needs to
838a02120c4SAndy Fiddaman * be returned. It's a balance between not allocating too much more
839a02120c4SAndy Fiddaman * space than is required and not requiring too many subsequent
840a02120c4SAndy Fiddaman * reallocations. Allocate it before acquiring the process lock.
841a02120c4SAndy Fiddaman */
842a02120c4SAndy Fiddaman pr_iol_initlist(&data, sizeof (prfdinfo_t) + MAXPATHLEN + 2, 1);
843a02120c4SAndy Fiddaman
844a02120c4SAndy Fiddaman if ((error = prlock(pnp, ZNO)) != 0) {
845a02120c4SAndy Fiddaman pr_iol_freelist(&data);
846a02120c4SAndy Fiddaman return (error);
847a02120c4SAndy Fiddaman }
848a02120c4SAndy Fiddaman
849a02120c4SAndy Fiddaman p = pnp->pr_common->prc_proc;
850a02120c4SAndy Fiddaman
851a02120c4SAndy Fiddaman if ((p->p_flag & SSYS) || p->p_as == &kas) {
852a02120c4SAndy Fiddaman prunlock(pnp);
853a02120c4SAndy Fiddaman pr_iol_freelist(&data);
854a02120c4SAndy Fiddaman return (0);
855a02120c4SAndy Fiddaman }
856a02120c4SAndy Fiddaman
857a02120c4SAndy Fiddaman fd = pnp->pr_index;
858a02120c4SAndy Fiddaman
859a02120c4SAndy Fiddaman /* Fetch and lock the file_t for this descriptor */
860a02120c4SAndy Fiddaman fp = pr_getf(p, fd, &ufp_flag);
861a02120c4SAndy Fiddaman
862a02120c4SAndy Fiddaman if (fp == NULL) {
863a02120c4SAndy Fiddaman error = ENOENT;
864a02120c4SAndy Fiddaman prunlock(pnp);
865a02120c4SAndy Fiddaman goto out;
866a02120c4SAndy Fiddaman }
867a02120c4SAndy Fiddaman
868a02120c4SAndy Fiddaman /*
869a02120c4SAndy Fiddaman * For fdinfo, we don't want to include the placeholder pr_misc at the
870a02120c4SAndy Fiddaman * end of the struct. We'll terminate the data with an empty pr_misc
871a02120c4SAndy Fiddaman * header before returning.
872a02120c4SAndy Fiddaman */
873a02120c4SAndy Fiddaman
874a02120c4SAndy Fiddaman fdinfo = pr_iol_newbuf(&data, offsetof(prfdinfo_t, pr_misc));
875a02120c4SAndy Fiddaman fdinfo->pr_fd = fd;
876a02120c4SAndy Fiddaman fdinfo->pr_fdflags = ufp_flag;
877086d9687SPatrick Mooney fdinfo->pr_fileflags = fp->f_flag2 << 16 | fp->f_flag;
878a02120c4SAndy Fiddaman if ((fdinfo->pr_fileflags & (FSEARCH | FEXEC)) == 0)
879a02120c4SAndy Fiddaman fdinfo->pr_fileflags += FOPEN;
880a02120c4SAndy Fiddaman fdinfo->pr_offset = fp->f_offset;
881a02120c4SAndy Fiddaman /*
882a02120c4SAndy Fiddaman * Information from the vnode (rather than the file_t) is retrieved
883a02120c4SAndy Fiddaman * later, in prgetfdinfo() - for example sock_getfasync()
884a02120c4SAndy Fiddaman */
885a02120c4SAndy Fiddaman
886a02120c4SAndy Fiddaman prunlock(pnp);
887a02120c4SAndy Fiddaman
888da29c6a3SDan McDonald error = prgetfdinfo(p, fp->f_vnode, fdinfo, cr, fp->f_cred, &data);
889a02120c4SAndy Fiddaman
89037e2cd25SPatrick Mooney pr_releasef(fp);
891a02120c4SAndy Fiddaman
892a02120c4SAndy Fiddaman out:
893a02120c4SAndy Fiddaman if (error == 0)
894a02120c4SAndy Fiddaman error = pr_iol_uiomove_and_free(&data, uiop, error);
895a02120c4SAndy Fiddaman else
896a02120c4SAndy Fiddaman pr_iol_freelist(&data);
897a02120c4SAndy Fiddaman
898a02120c4SAndy Fiddaman return (error);
899a02120c4SAndy Fiddaman }
900a02120c4SAndy Fiddaman
901a02120c4SAndy Fiddaman static int
pr_read_lpsinfo(prnode_t * pnp,uio_t * uiop,cred_t * cr)90219ee9cd1SAndy Fiddaman pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
9037c478bd9Sstevel@tonic-gate {
9047c478bd9Sstevel@tonic-gate proc_t *p;
9057c478bd9Sstevel@tonic-gate kthread_t *t;
9067c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
9077c478bd9Sstevel@tonic-gate lwpent_t *lep;
9087c478bd9Sstevel@tonic-gate size_t size;
9097c478bd9Sstevel@tonic-gate prheader_t *php;
9107c478bd9Sstevel@tonic-gate lwpsinfo_t *sp;
9117c478bd9Sstevel@tonic-gate int error;
9127c478bd9Sstevel@tonic-gate int nlwp;
9137c478bd9Sstevel@tonic-gate int i;
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LPSINFO);
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate /*
9187c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
9197c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
9207c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
9217c478bd9Sstevel@tonic-gate */
9227c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
9237c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
9247c478bd9Sstevel@tonic-gate if (p == NULL)
9257c478bd9Sstevel@tonic-gate return (ENOENT);
9267c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
9277c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
9287c478bd9Sstevel@tonic-gate prunlock(pnp);
9297c478bd9Sstevel@tonic-gate return (ENOENT);
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
9347c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
9357c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
9367c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
9377c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
9387c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
9417c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(lwpsinfo_t);
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate sp = (lwpsinfo_t *)(php + 1);
9447c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
9457c478bd9Sstevel@tonic-gate if ((lep = ldp->ld_entry) == NULL)
9467c478bd9Sstevel@tonic-gate continue;
9477c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) != NULL)
9487c478bd9Sstevel@tonic-gate prgetlwpsinfo(t, sp);
9497c478bd9Sstevel@tonic-gate else {
9507c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp));
9517c478bd9Sstevel@tonic-gate sp->pr_lwpid = lep->le_lwpid;
9527c478bd9Sstevel@tonic-gate sp->pr_state = SZOMB;
9537c478bd9Sstevel@tonic-gate sp->pr_sname = 'Z';
9547c478bd9Sstevel@tonic-gate sp->pr_start.tv_sec = lep->le_start;
9557c478bd9Sstevel@tonic-gate sp->pr_bindpro = PBIND_NONE;
9567c478bd9Sstevel@tonic-gate sp->pr_bindpset = PS_NONE;
9577c478bd9Sstevel@tonic-gate }
9587c478bd9Sstevel@tonic-gate sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate prunlock(pnp);
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
9637c478bd9Sstevel@tonic-gate kmem_free(php, size);
9647c478bd9Sstevel@tonic-gate return (error);
9657c478bd9Sstevel@tonic-gate }
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate static int
pr_read_map_common(prnode_t * pnp,uio_t * uiop,prnodetype_t type)968870619e9Sfrankho pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
9697c478bd9Sstevel@tonic-gate {
9707c478bd9Sstevel@tonic-gate proc_t *p;
9717c478bd9Sstevel@tonic-gate struct as *as;
972870619e9Sfrankho list_t iolhead;
9737c478bd9Sstevel@tonic-gate int error;
9747c478bd9Sstevel@tonic-gate
975e24ad047SChristopher Baumbauer - Oracle America - San Diego United States readmap_common:
9767c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
9777c478bd9Sstevel@tonic-gate return (error);
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
9807c478bd9Sstevel@tonic-gate as = p->p_as;
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
9837c478bd9Sstevel@tonic-gate prunlock(pnp);
9847c478bd9Sstevel@tonic-gate return (0);
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate
987dc32d872SJosef 'Jeff' Sipek if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
988e24ad047SChristopher Baumbauer - Oracle America - San Diego United States prunlock(pnp);
989e24ad047SChristopher Baumbauer - Oracle America - San Diego United States delay(1);
990e24ad047SChristopher Baumbauer - Oracle America - San Diego United States goto readmap_common;
991e24ad047SChristopher Baumbauer - Oracle America - San Diego United States }
9927c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
993e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
994870619e9Sfrankho switch (type) {
995870619e9Sfrankho case PR_XMAP:
996870619e9Sfrankho error = prgetxmap(p, &iolhead);
997870619e9Sfrankho break;
998870619e9Sfrankho case PR_RMAP:
999870619e9Sfrankho error = prgetmap(p, 1, &iolhead);
1000870619e9Sfrankho break;
1001870619e9Sfrankho case PR_MAP:
1002870619e9Sfrankho error = prgetmap(p, 0, &iolhead);
1003870619e9Sfrankho break;
1004870619e9Sfrankho }
1005e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
1006dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
10077c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
10087c478bd9Sstevel@tonic-gate prunlock(pnp);
10097c478bd9Sstevel@tonic-gate
1010870619e9Sfrankho error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
1011870619e9Sfrankho
10127c478bd9Sstevel@tonic-gate return (error);
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate static int
pr_read_map(prnode_t * pnp,uio_t * uiop,cred_t * cr)101619ee9cd1SAndy Fiddaman pr_read_map(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10177c478bd9Sstevel@tonic-gate {
10187c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_MAP);
1019870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate static int
pr_read_rmap(prnode_t * pnp,uio_t * uiop,cred_t * cr)102319ee9cd1SAndy Fiddaman pr_read_rmap(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10247c478bd9Sstevel@tonic-gate {
10257c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_RMAP);
1026870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate static int
pr_read_xmap(prnode_t * pnp,uio_t * uiop,cred_t * cr)103019ee9cd1SAndy Fiddaman pr_read_xmap(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10317c478bd9Sstevel@tonic-gate {
10327c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XMAP);
1033870619e9Sfrankho return (pr_read_map_common(pnp, uiop, pnp->pr_type));
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate static int
pr_read_cred(prnode_t * pnp,uio_t * uiop,cred_t * cr)103719ee9cd1SAndy Fiddaman pr_read_cred(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate proc_t *p;
10407c478bd9Sstevel@tonic-gate prcred_t *pcrp;
10417c478bd9Sstevel@tonic-gate int error;
10427c478bd9Sstevel@tonic-gate size_t count;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_CRED);
10457c478bd9Sstevel@tonic-gate
10467c478bd9Sstevel@tonic-gate /*
10477c478bd9Sstevel@tonic-gate * We kmem_alloc() the prcred_t structure because
10487c478bd9Sstevel@tonic-gate * the number of supplementary groups is variable.
10497c478bd9Sstevel@tonic-gate */
10507c478bd9Sstevel@tonic-gate pcrp =
1051*552c19f2SRobert Mustacchi kmem_zalloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
10527c478bd9Sstevel@tonic-gate KM_SLEEP);
10537c478bd9Sstevel@tonic-gate
10547c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
10557c478bd9Sstevel@tonic-gate goto out;
10567c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
10577c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate prgetcred(p, pcrp);
10607c478bd9Sstevel@tonic-gate prunlock(pnp);
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate count = sizeof (prcred_t);
10637c478bd9Sstevel@tonic-gate if (pcrp->pr_ngroups > 1)
10647c478bd9Sstevel@tonic-gate count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
10657c478bd9Sstevel@tonic-gate error = pr_uioread(pcrp, count, uiop);
10667c478bd9Sstevel@tonic-gate out:
10677c478bd9Sstevel@tonic-gate kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
10687c478bd9Sstevel@tonic-gate return (error);
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate static int
pr_read_priv(prnode_t * pnp,uio_t * uiop,cred_t * cr)107219ee9cd1SAndy Fiddaman pr_read_priv(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10737c478bd9Sstevel@tonic-gate {
10747c478bd9Sstevel@tonic-gate proc_t *p;
10757c478bd9Sstevel@tonic-gate size_t psize = prgetprivsize();
1076*552c19f2SRobert Mustacchi prpriv_t *ppriv = kmem_zalloc(psize, KM_SLEEP);
10777c478bd9Sstevel@tonic-gate int error;
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PRIV);
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
10827c478bd9Sstevel@tonic-gate goto out;
10837c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
10847c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate prgetpriv(p, ppriv);
10877c478bd9Sstevel@tonic-gate prunlock(pnp);
10887c478bd9Sstevel@tonic-gate
10897c478bd9Sstevel@tonic-gate error = pr_uioread(ppriv, psize, uiop);
10907c478bd9Sstevel@tonic-gate out:
10917c478bd9Sstevel@tonic-gate kmem_free(ppriv, psize);
10927c478bd9Sstevel@tonic-gate return (error);
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate static int
pr_read_sigact(prnode_t * pnp,uio_t * uiop,cred_t * cr)109619ee9cd1SAndy Fiddaman pr_read_sigact(prnode_t *pnp, uio_t *uiop, cred_t *cr)
10977c478bd9Sstevel@tonic-gate {
1098eb9dbf0cSRoger A. Faulkner int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
10997c478bd9Sstevel@tonic-gate proc_t *p;
11007c478bd9Sstevel@tonic-gate struct sigaction *sap;
11017c478bd9Sstevel@tonic-gate int sig;
11027c478bd9Sstevel@tonic-gate int error;
11037c478bd9Sstevel@tonic-gate user_t *up;
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_SIGACT);
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate /*
11087c478bd9Sstevel@tonic-gate * We kmem_alloc() the sigaction array because
11097c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
11107c478bd9Sstevel@tonic-gate */
1111eb9dbf0cSRoger A. Faulkner sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
11147c478bd9Sstevel@tonic-gate goto out;
11157c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
11167c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
11177c478bd9Sstevel@tonic-gate
1118eb9dbf0cSRoger A. Faulkner if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
11197c478bd9Sstevel@tonic-gate prunlock(pnp);
11207c478bd9Sstevel@tonic-gate goto out;
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate up = PTOU(p);
1124eb9dbf0cSRoger A. Faulkner for (sig = 1; sig < nsig; sig++)
11257c478bd9Sstevel@tonic-gate prgetaction(p, up, sig, &sap[sig-1]);
11267c478bd9Sstevel@tonic-gate prunlock(pnp);
11277c478bd9Sstevel@tonic-gate
1128eb9dbf0cSRoger A. Faulkner error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
11297c478bd9Sstevel@tonic-gate out:
1130eb9dbf0cSRoger A. Faulkner kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
11317c478bd9Sstevel@tonic-gate return (error);
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate static int
pr_read_auxv(prnode_t * pnp,uio_t * uiop,cred_t * cr)113519ee9cd1SAndy Fiddaman pr_read_auxv(prnode_t *pnp, uio_t *uiop, cred_t *cr)
11367c478bd9Sstevel@tonic-gate {
11377c478bd9Sstevel@tonic-gate auxv_t auxv[__KERN_NAUXV_IMPL];
11387c478bd9Sstevel@tonic-gate proc_t *p;
11397c478bd9Sstevel@tonic-gate user_t *up;
11407c478bd9Sstevel@tonic-gate int error;
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AUXV);
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
11457c478bd9Sstevel@tonic-gate return (error);
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (auxv)) {
11487c478bd9Sstevel@tonic-gate prunlock(pnp);
11497c478bd9Sstevel@tonic-gate return (0);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
11537c478bd9Sstevel@tonic-gate up = PTOU(p);
11547c478bd9Sstevel@tonic-gate bcopy(up->u_auxv, auxv, sizeof (auxv));
11557c478bd9Sstevel@tonic-gate prunlock(pnp);
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate return (pr_uioread(auxv, sizeof (auxv), uiop));
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate #if defined(__x86)
11617c478bd9Sstevel@tonic-gate /*
11627c478bd9Sstevel@tonic-gate * XX64
11637c478bd9Sstevel@tonic-gate * This is almost certainly broken for the amd64 kernel, because
11647c478bd9Sstevel@tonic-gate * we have two kinds of LDT structures to export -- one for compatibility
11657c478bd9Sstevel@tonic-gate * mode, and one for long mode, sigh.
11667c478bd9Sstevel@tonic-gate *
1167ab618543SJohn Levon * For now let's just have a ldt of size 0 for 64-bit processes.
11687c478bd9Sstevel@tonic-gate */
11697c478bd9Sstevel@tonic-gate static int
pr_read_ldt(prnode_t * pnp,uio_t * uiop,cred_t * cr)117019ee9cd1SAndy Fiddaman pr_read_ldt(prnode_t *pnp, uio_t *uiop, cred_t *cr)
11717c478bd9Sstevel@tonic-gate {
11727c478bd9Sstevel@tonic-gate proc_t *p;
11737c478bd9Sstevel@tonic-gate struct ssd *ssd;
11747c478bd9Sstevel@tonic-gate size_t size;
11757c478bd9Sstevel@tonic-gate int error;
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LDT);
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
11807c478bd9Sstevel@tonic-gate return (error);
11817c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
11847c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
11857c478bd9Sstevel@tonic-gate size = prnldt(p) * sizeof (struct ssd);
11867c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
11877c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
11887c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
11897c478bd9Sstevel@tonic-gate prunlock(pnp);
11907c478bd9Sstevel@tonic-gate return (0);
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate ssd = kmem_alloc(size, KM_SLEEP);
11947c478bd9Sstevel@tonic-gate prgetldt(p, ssd);
11957c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
11967c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
11977c478bd9Sstevel@tonic-gate prunlock(pnp);
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate error = pr_uioread(ssd, size, uiop);
12007c478bd9Sstevel@tonic-gate kmem_free(ssd, size);
12017c478bd9Sstevel@tonic-gate return (error);
12027c478bd9Sstevel@tonic-gate }
12037c478bd9Sstevel@tonic-gate #endif /* __x86 */
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate static int
pr_read_usage(prnode_t * pnp,uio_t * uiop,cred_t * cr)120619ee9cd1SAndy Fiddaman pr_read_usage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
12077c478bd9Sstevel@tonic-gate {
12087c478bd9Sstevel@tonic-gate prhusage_t *pup;
12097c478bd9Sstevel@tonic-gate prusage_t *upup;
12107c478bd9Sstevel@tonic-gate proc_t *p;
12117c478bd9Sstevel@tonic-gate kthread_t *t;
12127c478bd9Sstevel@tonic-gate int error;
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_USAGE);
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
12177c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
12187c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
12197c478bd9Sstevel@tonic-gate
12207c478bd9Sstevel@tonic-gate /*
12217c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
12227c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
12237c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
12247c478bd9Sstevel@tonic-gate */
12257c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
12267c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
12277c478bd9Sstevel@tonic-gate if (p == NULL) {
12287c478bd9Sstevel@tonic-gate error = ENOENT;
12297c478bd9Sstevel@tonic-gate goto out;
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage_t)) {
12347c478bd9Sstevel@tonic-gate prunlock(pnp);
12357c478bd9Sstevel@tonic-gate error = 0;
12367c478bd9Sstevel@tonic-gate goto out;
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
12407c478bd9Sstevel@tonic-gate
12417c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
12427c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
12437c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
12467c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
12477c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
12487c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
12497c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
12507c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
12517c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
12527c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
12537c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
12547c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
12557c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
12587c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
12597c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
12607c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
12617c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
12627c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
12637c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
12647c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
12657c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
12667c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
12677c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
12687c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate /*
12717c478bd9Sstevel@tonic-gate * Add the usage information for each active lwp.
12727c478bd9Sstevel@tonic-gate */
12737c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
12747c478bd9Sstevel@tonic-gate !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
12757c478bd9Sstevel@tonic-gate do {
12767c478bd9Sstevel@tonic-gate if (t->t_proc_flag & TP_LWPEXIT)
12777c478bd9Sstevel@tonic-gate continue;
12787c478bd9Sstevel@tonic-gate pup->pr_count++;
12797c478bd9Sstevel@tonic-gate praddusage(t, pup);
12807c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
12817c478bd9Sstevel@tonic-gate }
12827c478bd9Sstevel@tonic-gate
12837c478bd9Sstevel@tonic-gate prunlock(pnp);
12847c478bd9Sstevel@tonic-gate
12857c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage_t), uiop);
12887c478bd9Sstevel@tonic-gate out:
12897c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
12907c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
12917c478bd9Sstevel@tonic-gate return (error);
12927c478bd9Sstevel@tonic-gate }
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate static int
pr_read_lusage(prnode_t * pnp,uio_t * uiop,cred_t * cr)129519ee9cd1SAndy Fiddaman pr_read_lusage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
12967c478bd9Sstevel@tonic-gate {
12977c478bd9Sstevel@tonic-gate int nlwp;
12987c478bd9Sstevel@tonic-gate prhusage_t *pup;
12997c478bd9Sstevel@tonic-gate prheader_t *php;
13007c478bd9Sstevel@tonic-gate prusage_t *upup;
13017c478bd9Sstevel@tonic-gate size_t size;
13027c478bd9Sstevel@tonic-gate hrtime_t curtime;
13037c478bd9Sstevel@tonic-gate proc_t *p;
13047c478bd9Sstevel@tonic-gate kthread_t *t;
13057c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
13067c478bd9Sstevel@tonic-gate int error;
13077c478bd9Sstevel@tonic-gate int i;
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LUSAGE);
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate /*
13127c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
13137c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
13147c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
13157c478bd9Sstevel@tonic-gate */
13167c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
13177c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
13187c478bd9Sstevel@tonic-gate if (p == NULL)
13197c478bd9Sstevel@tonic-gate return (ENOENT);
13207c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
13217c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt) == 0) {
13227c478bd9Sstevel@tonic-gate prunlock(pnp);
13237c478bd9Sstevel@tonic-gate return (ENOENT);
13247c478bd9Sstevel@tonic-gate }
13257c478bd9Sstevel@tonic-gate
13267c478bd9Sstevel@tonic-gate size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
13277c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
13287c478bd9Sstevel@tonic-gate prunlock(pnp);
13297c478bd9Sstevel@tonic-gate return (0);
13307c478bd9Sstevel@tonic-gate }
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
13337c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
13347c478bd9Sstevel@tonic-gate pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
13357c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
13367c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
13377c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate php = (prheader_t *)(pup + 1);
13407c478bd9Sstevel@tonic-gate upup = (prusage_t *)(php + 1);
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate php->pr_nent = nlwp + 1;
13437c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN(prusage_t);
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate curtime = gethrtime();
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate /*
13487c478bd9Sstevel@tonic-gate * First the summation over defunct lwps.
13497c478bd9Sstevel@tonic-gate */
13507c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
13517c478bd9Sstevel@tonic-gate pup->pr_tstamp = curtime;
13527c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
13537c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
13567c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
13577c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
13587c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
13597c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
13607c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
13617c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
13627c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
13637c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
13647c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
13657c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
13667c478bd9Sstevel@tonic-gate
13677c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
13687c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
13697c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
13707c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
13717c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
13727c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
13737c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
13747c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
13757c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
13767c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
13777c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
13787c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate /*
13837c478bd9Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
13847c478bd9Sstevel@tonic-gate */
13857c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
13867c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
13877c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
13887c478bd9Sstevel@tonic-gate continue;
13897c478bd9Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
13907c478bd9Sstevel@tonic-gate ASSERT(nlwp > 0);
13917c478bd9Sstevel@tonic-gate --nlwp;
13927c478bd9Sstevel@tonic-gate upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
13937c478bd9Sstevel@tonic-gate prgetusage(t, pup);
13947c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
13957c478bd9Sstevel@tonic-gate }
13967c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0);
13977c478bd9Sstevel@tonic-gate
13987c478bd9Sstevel@tonic-gate prunlock(pnp);
13997c478bd9Sstevel@tonic-gate
14007c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
14017c478bd9Sstevel@tonic-gate kmem_free(pup, size + sizeof (prhusage_t));
14027c478bd9Sstevel@tonic-gate return (error);
14037c478bd9Sstevel@tonic-gate }
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate static int
pr_read_pagedata(prnode_t * pnp,uio_t * uiop,cred_t * cr)140619ee9cd1SAndy Fiddaman pr_read_pagedata(prnode_t *pnp, uio_t *uiop, cred_t *cr)
14077c478bd9Sstevel@tonic-gate {
14087c478bd9Sstevel@tonic-gate proc_t *p;
14097c478bd9Sstevel@tonic-gate int error;
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PAGEDATA);
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
14147c478bd9Sstevel@tonic-gate return (error);
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
14177c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
14187c478bd9Sstevel@tonic-gate prunlock(pnp);
14197c478bd9Sstevel@tonic-gate return (0);
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
14237c478bd9Sstevel@tonic-gate error = prpdread(p, pnp->pr_hatid, uiop);
14247c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
14257c478bd9Sstevel@tonic-gate
14267c478bd9Sstevel@tonic-gate prunlock(pnp);
14277c478bd9Sstevel@tonic-gate return (error);
14287c478bd9Sstevel@tonic-gate }
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate static int
pr_read_opagedata(prnode_t * pnp,uio_t * uiop,cred_t * cr)143119ee9cd1SAndy Fiddaman pr_read_opagedata(prnode_t *pnp, uio_t *uiop, cred_t *cr)
14327c478bd9Sstevel@tonic-gate {
14337c478bd9Sstevel@tonic-gate proc_t *p;
14347c478bd9Sstevel@tonic-gate struct as *as;
14357c478bd9Sstevel@tonic-gate int error;
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OPAGEDATA);
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
14407c478bd9Sstevel@tonic-gate return (error);
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
14437c478bd9Sstevel@tonic-gate as = p->p_as;
14447c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
14457c478bd9Sstevel@tonic-gate prunlock(pnp);
14467c478bd9Sstevel@tonic-gate return (0);
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
14507c478bd9Sstevel@tonic-gate error = oprpdread(as, pnp->pr_hatid, uiop);
14517c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate prunlock(pnp);
14547c478bd9Sstevel@tonic-gate return (error);
14557c478bd9Sstevel@tonic-gate }
14567c478bd9Sstevel@tonic-gate
14577c478bd9Sstevel@tonic-gate static int
pr_read_watch(prnode_t * pnp,uio_t * uiop,cred_t * cr)145819ee9cd1SAndy Fiddaman pr_read_watch(prnode_t *pnp, uio_t *uiop, cred_t *cr)
14597c478bd9Sstevel@tonic-gate {
14607c478bd9Sstevel@tonic-gate proc_t *p;
14617c478bd9Sstevel@tonic-gate int error;
14627c478bd9Sstevel@tonic-gate prwatch_t *Bpwp;
14637c478bd9Sstevel@tonic-gate size_t size;
14647c478bd9Sstevel@tonic-gate prwatch_t *pwp;
14657c478bd9Sstevel@tonic-gate int nwarea;
14667c478bd9Sstevel@tonic-gate struct watched_area *pwarea;
14677c478bd9Sstevel@tonic-gate
14687c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_WATCH);
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
14717c478bd9Sstevel@tonic-gate return (error);
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
14747c478bd9Sstevel@tonic-gate nwarea = avl_numnodes(&p->p_warea);
14757c478bd9Sstevel@tonic-gate size = nwarea * sizeof (prwatch_t);
14767c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
14777c478bd9Sstevel@tonic-gate prunlock(pnp);
14787c478bd9Sstevel@tonic-gate return (0);
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
14827c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
14837c478bd9Sstevel@tonic-gate Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
14847c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
14857c478bd9Sstevel@tonic-gate /* p->p_nwarea can't change while process is locked */
14867c478bd9Sstevel@tonic-gate ASSERT(nwarea == avl_numnodes(&p->p_warea));
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate /* gather the watched areas */
14897c478bd9Sstevel@tonic-gate for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
14907c478bd9Sstevel@tonic-gate pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
14917c478bd9Sstevel@tonic-gate pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
14927c478bd9Sstevel@tonic-gate pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
14937c478bd9Sstevel@tonic-gate pwp->pr_wflags = (int)pwarea->wa_flags;
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate prunlock(pnp);
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate error = pr_uioread(Bpwp, size, uiop);
14997c478bd9Sstevel@tonic-gate kmem_free(Bpwp, size);
15007c478bd9Sstevel@tonic-gate return (error);
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate static int
pr_read_lwpstatus(prnode_t * pnp,uio_t * uiop,cred_t * cr)150419ee9cd1SAndy Fiddaman pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop, cred_t *cr)
15057c478bd9Sstevel@tonic-gate {
15067c478bd9Sstevel@tonic-gate lwpstatus_t *sp;
15077c478bd9Sstevel@tonic-gate int error;
15087c478bd9Sstevel@tonic-gate
15097c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSTATUS);
15107c478bd9Sstevel@tonic-gate
15117c478bd9Sstevel@tonic-gate /*
15127c478bd9Sstevel@tonic-gate * We kmem_alloc() the lwpstatus structure because
15137c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
15147c478bd9Sstevel@tonic-gate */
15157c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
15187c478bd9Sstevel@tonic-gate goto out;
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (*sp)) {
15217c478bd9Sstevel@tonic-gate prunlock(pnp);
15227c478bd9Sstevel@tonic-gate goto out;
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate
1525fa9e4066Sahrens prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
15267c478bd9Sstevel@tonic-gate prunlock(pnp);
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
15297c478bd9Sstevel@tonic-gate out:
15307c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
15317c478bd9Sstevel@tonic-gate return (error);
15327c478bd9Sstevel@tonic-gate }
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate static int
pr_read_lwpsinfo(prnode_t * pnp,uio_t * uiop,cred_t * cr)153519ee9cd1SAndy Fiddaman pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
15367c478bd9Sstevel@tonic-gate {
15377c478bd9Sstevel@tonic-gate lwpsinfo_t lwpsinfo;
15387c478bd9Sstevel@tonic-gate proc_t *p;
15397c478bd9Sstevel@tonic-gate kthread_t *t;
15407c478bd9Sstevel@tonic-gate lwpent_t *lep;
15417c478bd9Sstevel@tonic-gate
15427c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSINFO);
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate /*
15457c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
15467c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
15477c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
15487c478bd9Sstevel@tonic-gate */
15497c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
15507c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
15517c478bd9Sstevel@tonic-gate if (p == NULL)
15527c478bd9Sstevel@tonic-gate return (ENOENT);
15537c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
15547c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_tslot == -1) {
15557c478bd9Sstevel@tonic-gate prunlock(pnp);
15567c478bd9Sstevel@tonic-gate return (ENOENT);
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate
15597c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpsinfo)) {
15607c478bd9Sstevel@tonic-gate prunlock(pnp);
15617c478bd9Sstevel@tonic-gate return (0);
15627c478bd9Sstevel@tonic-gate }
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate if ((t = pnp->pr_common->prc_thread) != NULL)
15657c478bd9Sstevel@tonic-gate prgetlwpsinfo(t, &lwpsinfo);
15667c478bd9Sstevel@tonic-gate else {
15677c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
15687c478bd9Sstevel@tonic-gate bzero(&lwpsinfo, sizeof (lwpsinfo));
15697c478bd9Sstevel@tonic-gate lwpsinfo.pr_lwpid = lep->le_lwpid;
15707c478bd9Sstevel@tonic-gate lwpsinfo.pr_state = SZOMB;
15717c478bd9Sstevel@tonic-gate lwpsinfo.pr_sname = 'Z';
15727c478bd9Sstevel@tonic-gate lwpsinfo.pr_start.tv_sec = lep->le_start;
15737c478bd9Sstevel@tonic-gate lwpsinfo.pr_bindpro = PBIND_NONE;
15747c478bd9Sstevel@tonic-gate lwpsinfo.pr_bindpset = PS_NONE;
15757c478bd9Sstevel@tonic-gate }
15767c478bd9Sstevel@tonic-gate prunlock(pnp);
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate static int
pr_read_lwpusage(prnode_t * pnp,uio_t * uiop,cred_t * cr)158219ee9cd1SAndy Fiddaman pr_read_lwpusage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
15837c478bd9Sstevel@tonic-gate {
15847c478bd9Sstevel@tonic-gate prhusage_t *pup;
15857c478bd9Sstevel@tonic-gate prusage_t *upup;
15867c478bd9Sstevel@tonic-gate proc_t *p;
15877c478bd9Sstevel@tonic-gate int error;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPUSAGE);
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
15927c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
15937c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate /*
15967c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
15977c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
15987c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
15997c478bd9Sstevel@tonic-gate */
16007c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
16017c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
16027c478bd9Sstevel@tonic-gate if (p == NULL) {
16037c478bd9Sstevel@tonic-gate error = ENOENT;
16047c478bd9Sstevel@tonic-gate goto out;
16057c478bd9Sstevel@tonic-gate }
16067c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
16077c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_thread == NULL) {
16087c478bd9Sstevel@tonic-gate prunlock(pnp);
16097c478bd9Sstevel@tonic-gate error = ENOENT;
16107c478bd9Sstevel@tonic-gate goto out;
16117c478bd9Sstevel@tonic-gate }
16127c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage_t)) {
16137c478bd9Sstevel@tonic-gate prunlock(pnp);
16147c478bd9Sstevel@tonic-gate error = 0;
16157c478bd9Sstevel@tonic-gate goto out;
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
16197c478bd9Sstevel@tonic-gate prgetusage(pnp->pr_common->prc_thread, pup);
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate prunlock(pnp);
16227c478bd9Sstevel@tonic-gate
16237c478bd9Sstevel@tonic-gate prcvtusage(pup, upup);
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage_t), uiop);
16267c478bd9Sstevel@tonic-gate out:
16277c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
16287c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
16297c478bd9Sstevel@tonic-gate return (error);
16307c478bd9Sstevel@tonic-gate }
16317c478bd9Sstevel@tonic-gate
1632ab618543SJohn Levon static int
pr_read_lwpname(prnode_t * pnp,uio_t * uiop,cred_t * cr)163319ee9cd1SAndy Fiddaman pr_read_lwpname(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1634ab618543SJohn Levon {
1635ab618543SJohn Levon char lwpname[THREAD_NAME_MAX];
1636ab618543SJohn Levon kthread_t *t;
1637ab618543SJohn Levon int error;
1638ab618543SJohn Levon
1639ab618543SJohn Levon ASSERT(pnp->pr_type == PR_LWPNAME);
1640ab618543SJohn Levon
1641ab618543SJohn Levon if (uiop->uio_offset >= THREAD_NAME_MAX)
1642ab618543SJohn Levon return (0);
1643ab618543SJohn Levon
1644ab618543SJohn Levon if ((error = prlock(pnp, ZNO)) != 0)
1645ab618543SJohn Levon return (error);
1646ab618543SJohn Levon
1647ab618543SJohn Levon bzero(lwpname, sizeof (lwpname));
1648ab618543SJohn Levon
1649ab618543SJohn Levon t = pnp->pr_common->prc_thread;
1650ab618543SJohn Levon
1651ab618543SJohn Levon if (t->t_name != NULL)
1652ab618543SJohn Levon (void) strlcpy(lwpname, t->t_name, sizeof (lwpname));
1653ab618543SJohn Levon
1654ab618543SJohn Levon prunlock(pnp);
1655ab618543SJohn Levon
1656ab618543SJohn Levon return (pr_uioread(lwpname, sizeof (lwpname), uiop));
1657ab618543SJohn Levon }
1658ab618543SJohn Levon
16597c478bd9Sstevel@tonic-gate /* ARGSUSED */
16607c478bd9Sstevel@tonic-gate static int
pr_read_xregs(prnode_t * pnp,uio_t * uiop,cred_t * cr)166119ee9cd1SAndy Fiddaman pr_read_xregs(prnode_t *pnp, uio_t *uiop, cred_t *cr)
16627c478bd9Sstevel@tonic-gate {
16637c478bd9Sstevel@tonic-gate proc_t *p;
16647c478bd9Sstevel@tonic-gate kthread_t *t;
16657c478bd9Sstevel@tonic-gate int error;
1666ed093b41SRobert Mustacchi void *xreg;
16677c478bd9Sstevel@tonic-gate size_t size;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XREGS);
16707c478bd9Sstevel@tonic-gate
16717c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
1672ed093b41SRobert Mustacchi return (error);
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
16757c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
16767c478bd9Sstevel@tonic-gate
1677ed093b41SRobert Mustacchi /*
1678ed093b41SRobert Mustacchi * While we would prefer to do the allocation without holding the
1679ed093b41SRobert Mustacchi * process under a prlock(), we can only determine this size while
1680ed093b41SRobert Mustacchi * holding the process as the hold guarantees us:
1681ed093b41SRobert Mustacchi *
1682ed093b41SRobert Mustacchi * o That the process in question actualy exists.
1683ed093b41SRobert Mustacchi * o That the process in question cannot change the set of FPU features
1684ed093b41SRobert Mustacchi * it has enabled.
1685ed093b41SRobert Mustacchi *
1686ed093b41SRobert Mustacchi * We will drop p_lock across the allocation call itself. This should be
1687ed093b41SRobert Mustacchi * safe as the enabled feature set should not change while the process
1688ed093b41SRobert Mustacchi * is locked (e.g. enabling extending FPU state like AMX on x86 should
1689ed093b41SRobert Mustacchi * require the process to be locked).
1690ed093b41SRobert Mustacchi */
16917c478bd9Sstevel@tonic-gate size = prhasx(p) ? prgetprxregsize(p) : 0;
1692ed093b41SRobert Mustacchi if (size == 0) {
1693ed093b41SRobert Mustacchi prunlock(pnp);
1694ed093b41SRobert Mustacchi return (0);
1695ed093b41SRobert Mustacchi }
1696a14132dbSRobert Mustacchi
1697a14132dbSRobert Mustacchi /*
1698a14132dbSRobert Mustacchi * To read the extended register set we require that the thread be
1699a14132dbSRobert Mustacchi * stopped as this state is only valid in the kernel when it is. An
1700a14132dbSRobert Mustacchi * exception made if the target thread and the current thread are one
1701a14132dbSRobert Mustacchi * and the same. We won't stop you from doing something... weird.
1702a14132dbSRobert Mustacchi */
1703a14132dbSRobert Mustacchi thread_lock(t);
1704a14132dbSRobert Mustacchi if (t != curthread && !ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t)) {
1705a14132dbSRobert Mustacchi thread_unlock(t);
1706a14132dbSRobert Mustacchi prunlock(pnp);
1707a14132dbSRobert Mustacchi return (EBUSY);
1708a14132dbSRobert Mustacchi }
1709a14132dbSRobert Mustacchi thread_unlock(t);
1710a14132dbSRobert Mustacchi
1711ed093b41SRobert Mustacchi mutex_exit(&p->p_lock);
1712ed093b41SRobert Mustacchi xreg = kmem_zalloc(size, KM_SLEEP);
1713ed093b41SRobert Mustacchi mutex_enter(&p->p_lock);
1714ed093b41SRobert Mustacchi ASSERT3U(size, ==, prgetprxregsize(p));
1715ed093b41SRobert Mustacchi
17167c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
17177c478bd9Sstevel@tonic-gate prunlock(pnp);
17187c478bd9Sstevel@tonic-gate goto out;
17197c478bd9Sstevel@tonic-gate }
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate /* drop p->p_lock while (possibly) touching the stack */
17227c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
17237c478bd9Sstevel@tonic-gate prgetprxregs(ttolwp(t), xreg);
17247c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
17257c478bd9Sstevel@tonic-gate prunlock(pnp);
17267c478bd9Sstevel@tonic-gate
17277c478bd9Sstevel@tonic-gate error = pr_uioread(xreg, size, uiop);
17287c478bd9Sstevel@tonic-gate out:
1729ed093b41SRobert Mustacchi kmem_free(xreg, size);
17307c478bd9Sstevel@tonic-gate return (error);
17317c478bd9Sstevel@tonic-gate }
17327c478bd9Sstevel@tonic-gate
1733f971a346SBryan Cantrill static int
pr_read_spymaster(prnode_t * pnp,uio_t * uiop,cred_t * cr)173419ee9cd1SAndy Fiddaman pr_read_spymaster(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1735f971a346SBryan Cantrill {
1736f971a346SBryan Cantrill psinfo_t psinfo;
1737f971a346SBryan Cantrill int error;
1738f971a346SBryan Cantrill klwp_t *lwp;
1739f971a346SBryan Cantrill
1740f971a346SBryan Cantrill ASSERT(pnp->pr_type == PR_SPYMASTER);
1741f971a346SBryan Cantrill
1742f971a346SBryan Cantrill if ((error = prlock(pnp, ZNO)) != 0)
1743f971a346SBryan Cantrill return (error);
1744f971a346SBryan Cantrill
1745614f1d63SJerry Jelinek if (pnp->pr_common->prc_thread == NULL) {
1746614f1d63SJerry Jelinek prunlock(pnp);
1747614f1d63SJerry Jelinek return (0);
1748614f1d63SJerry Jelinek }
1749614f1d63SJerry Jelinek
1750f971a346SBryan Cantrill lwp = pnp->pr_common->prc_thread->t_lwp;
1751f971a346SBryan Cantrill
1752f971a346SBryan Cantrill if (lwp->lwp_spymaster == NULL) {
1753f971a346SBryan Cantrill prunlock(pnp);
1754f971a346SBryan Cantrill return (0);
1755f971a346SBryan Cantrill }
1756f971a346SBryan Cantrill
1757f971a346SBryan Cantrill bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1758f971a346SBryan Cantrill prunlock(pnp);
1759f971a346SBryan Cantrill
1760f971a346SBryan Cantrill return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1761f971a346SBryan Cantrill }
1762f971a346SBryan Cantrill
1763d2a70789SRichard Lowe static int
pr_read_secflags(prnode_t * pnp,uio_t * uiop,cred_t * cr)176419ee9cd1SAndy Fiddaman pr_read_secflags(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1765d2a70789SRichard Lowe {
1766d2a70789SRichard Lowe prsecflags_t ret;
1767d2a70789SRichard Lowe int error;
1768d2a70789SRichard Lowe proc_t *p;
1769d2a70789SRichard Lowe
1770d2a70789SRichard Lowe ASSERT(pnp->pr_type == PR_SECFLAGS);
1771d2a70789SRichard Lowe
1772d2a70789SRichard Lowe if ((error = prlock(pnp, ZNO)) != 0)
1773d2a70789SRichard Lowe return (error);
1774d2a70789SRichard Lowe
1775d2a70789SRichard Lowe p = pnp->pr_common->prc_proc;
1776d2a70789SRichard Lowe prgetsecflags(p, &ret);
1777d2a70789SRichard Lowe prunlock(pnp);
1778d2a70789SRichard Lowe
1779d2a70789SRichard Lowe return (pr_uioread(&ret, sizeof (ret), uiop));
1780d2a70789SRichard Lowe }
1781d2a70789SRichard Lowe
17827c478bd9Sstevel@tonic-gate #if defined(__sparc)
17837c478bd9Sstevel@tonic-gate
17847c478bd9Sstevel@tonic-gate static int
pr_read_gwindows(prnode_t * pnp,uio_t * uiop,cred_t * cr)178519ee9cd1SAndy Fiddaman pr_read_gwindows(prnode_t *pnp, uio_t *uiop, cred_t *cr)
17867c478bd9Sstevel@tonic-gate {
17877c478bd9Sstevel@tonic-gate proc_t *p;
17887c478bd9Sstevel@tonic-gate kthread_t *t;
17897c478bd9Sstevel@tonic-gate gwindows_t *gwp;
17907c478bd9Sstevel@tonic-gate int error;
17917c478bd9Sstevel@tonic-gate size_t size;
17927c478bd9Sstevel@tonic-gate
17937c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_GWINDOWS);
17947c478bd9Sstevel@tonic-gate
17957c478bd9Sstevel@tonic-gate gwp = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP);
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
17987c478bd9Sstevel@tonic-gate goto out;
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
18017c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
18027c478bd9Sstevel@tonic-gate
18037c478bd9Sstevel@tonic-gate /*
18047c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
18057c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
18067c478bd9Sstevel@tonic-gate * disappearing while we do this.
18077c478bd9Sstevel@tonic-gate */
18087c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
18097c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0)
18107c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) -
18117c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow);
18127c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
18137c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
18147c478bd9Sstevel@tonic-gate prunlock(pnp);
18157c478bd9Sstevel@tonic-gate goto out;
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate prgetwindows(ttolwp(t), gwp);
18187c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
18197c478bd9Sstevel@tonic-gate prunlock(pnp);
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate error = pr_uioread(gwp, size, uiop);
18227c478bd9Sstevel@tonic-gate out:
18237c478bd9Sstevel@tonic-gate kmem_free(gwp, sizeof (gwindows_t));
18247c478bd9Sstevel@tonic-gate return (error);
18257c478bd9Sstevel@tonic-gate }
18267c478bd9Sstevel@tonic-gate
18277c478bd9Sstevel@tonic-gate /* ARGSUSED */
18287c478bd9Sstevel@tonic-gate static int
pr_read_asrs(prnode_t * pnp,uio_t * uiop,cred_t * cr)182919ee9cd1SAndy Fiddaman pr_read_asrs(prnode_t *pnp, uio_t *uiop, cred_t *cr)
18307c478bd9Sstevel@tonic-gate {
18317c478bd9Sstevel@tonic-gate int error;
18327c478bd9Sstevel@tonic-gate
18337c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_ASRS);
18347c478bd9Sstevel@tonic-gate
18357c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
18367c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
18377c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
18387c478bd9Sstevel@tonic-gate kthread_t *t = pnp->pr_common->prc_thread;
18397c478bd9Sstevel@tonic-gate asrset_t asrset;
18407c478bd9Sstevel@tonic-gate
18417c478bd9Sstevel@tonic-gate if (p->p_model != DATAMODEL_LP64 ||
18427c478bd9Sstevel@tonic-gate uiop->uio_offset >= sizeof (asrset_t)) {
18437c478bd9Sstevel@tonic-gate prunlock(pnp);
18447c478bd9Sstevel@tonic-gate return (0);
18457c478bd9Sstevel@tonic-gate }
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate /*
18487c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
18497c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
18507c478bd9Sstevel@tonic-gate * disappearing while we do this.
18517c478bd9Sstevel@tonic-gate */
18527c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
18537c478bd9Sstevel@tonic-gate prgetasregs(ttolwp(t), asrset);
18547c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
18557c478bd9Sstevel@tonic-gate prunlock(pnp);
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate error = pr_uioread(&asrset[0], sizeof (asrset_t), uiop);
18587c478bd9Sstevel@tonic-gate }
18597c478bd9Sstevel@tonic-gate
18607c478bd9Sstevel@tonic-gate return (error);
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate
18637c478bd9Sstevel@tonic-gate #endif /* __sparc */
18647c478bd9Sstevel@tonic-gate
18657c478bd9Sstevel@tonic-gate static int
pr_read_piddir(prnode_t * pnp,uio_t * uiop,cred_t * cr)186619ee9cd1SAndy Fiddaman pr_read_piddir(prnode_t *pnp, uio_t *uiop, cred_t *cr)
18677c478bd9Sstevel@tonic-gate {
18687c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
18697c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_pidfile != NULL);
18707c478bd9Sstevel@tonic-gate
18717c478bd9Sstevel@tonic-gate /* use the underlying PR_PIDFILE to read the process */
18727c478bd9Sstevel@tonic-gate pnp = VTOP(pnp->pr_pidfile);
18737c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate return (pr_read_pidfile(pnp, uiop));
18767c478bd9Sstevel@tonic-gate }
18777c478bd9Sstevel@tonic-gate
18787c478bd9Sstevel@tonic-gate static int
pr_read_pidfile(prnode_t * pnp,uio_t * uiop,cred_t * cr)187919ee9cd1SAndy Fiddaman pr_read_pidfile(prnode_t *pnp, uio_t *uiop, cred_t *cr)
18807c478bd9Sstevel@tonic-gate {
18817c478bd9Sstevel@tonic-gate int error;
18827c478bd9Sstevel@tonic-gate
18837c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
18847c478bd9Sstevel@tonic-gate
18857c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
18867c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
18877c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
18887c478bd9Sstevel@tonic-gate
18897c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
18907c478bd9Sstevel@tonic-gate /*
18917c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
18927c478bd9Sstevel@tonic-gate */
18937c478bd9Sstevel@tonic-gate error = EIO; /* old /proc semantics */
18947c478bd9Sstevel@tonic-gate } else {
18957c478bd9Sstevel@tonic-gate /*
18967c478bd9Sstevel@tonic-gate * We drop p_lock because we don't want to hold
18977c478bd9Sstevel@tonic-gate * it over an I/O operation because that could
18987c478bd9Sstevel@tonic-gate * lead to deadlock with the clock thread.
18997c478bd9Sstevel@tonic-gate * The process will not disappear and its address
19007c478bd9Sstevel@tonic-gate * space will not change because it is marked P_PR_LOCK.
19017c478bd9Sstevel@tonic-gate */
19027c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
19037c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_READ, uiop, 1);
19047c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
19057c478bd9Sstevel@tonic-gate }
19067c478bd9Sstevel@tonic-gate prunlock(pnp);
19077c478bd9Sstevel@tonic-gate }
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate return (error);
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate /*
19157c478bd9Sstevel@tonic-gate * Array of ILP32 read functions, indexed by /proc file type.
19167c478bd9Sstevel@tonic-gate */
19177c478bd9Sstevel@tonic-gate static int pr_read_status_32(),
19187c478bd9Sstevel@tonic-gate pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
19197c478bd9Sstevel@tonic-gate pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
19207c478bd9Sstevel@tonic-gate pr_read_sigact_32(), pr_read_auxv_32(),
19217c478bd9Sstevel@tonic-gate pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
19227c478bd9Sstevel@tonic-gate pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1923f971a346SBryan Cantrill pr_read_lwpusage_32(), pr_read_spymaster_32(),
19247c478bd9Sstevel@tonic-gate #if defined(__sparc)
19257c478bd9Sstevel@tonic-gate pr_read_gwindows_32(),
19267c478bd9Sstevel@tonic-gate #endif
19277c478bd9Sstevel@tonic-gate pr_read_opagedata_32();
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate static int (*pr_read_function_32[PR_NFILES])() = {
19307c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc */
19317c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/self */
19327c478bd9Sstevel@tonic-gate pr_read_piddir, /* /proc/<pid> (old /proc read()) */
19337c478bd9Sstevel@tonic-gate pr_read_as, /* /proc/<pid>/as */
19347c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/ctl */
19357c478bd9Sstevel@tonic-gate pr_read_status_32, /* /proc/<pid>/status */
19367c478bd9Sstevel@tonic-gate pr_read_lstatus_32, /* /proc/<pid>/lstatus */
19377c478bd9Sstevel@tonic-gate pr_read_psinfo_32, /* /proc/<pid>/psinfo */
19387c478bd9Sstevel@tonic-gate pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
19397c478bd9Sstevel@tonic-gate pr_read_map_32, /* /proc/<pid>/map */
19407c478bd9Sstevel@tonic-gate pr_read_rmap_32, /* /proc/<pid>/rmap */
19417c478bd9Sstevel@tonic-gate pr_read_xmap_32, /* /proc/<pid>/xmap */
19427c478bd9Sstevel@tonic-gate pr_read_cred, /* /proc/<pid>/cred */
19437c478bd9Sstevel@tonic-gate pr_read_sigact_32, /* /proc/<pid>/sigact */
19447c478bd9Sstevel@tonic-gate pr_read_auxv_32, /* /proc/<pid>/auxv */
19457c478bd9Sstevel@tonic-gate #if defined(__x86)
19467c478bd9Sstevel@tonic-gate pr_read_ldt, /* /proc/<pid>/ldt */
19477c478bd9Sstevel@tonic-gate #endif
19487c478bd9Sstevel@tonic-gate pr_read_usage_32, /* /proc/<pid>/usage */
19497c478bd9Sstevel@tonic-gate pr_read_lusage_32, /* /proc/<pid>/lusage */
19507c478bd9Sstevel@tonic-gate pr_read_pagedata_32, /* /proc/<pid>/pagedata */
19517c478bd9Sstevel@tonic-gate pr_read_watch_32, /* /proc/<pid>/watch */
19527c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/cwd */
19537c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/root */
19547c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd */
19557c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/fd/nn */
1956a02120c4SAndy Fiddaman pr_read_inval, /* /proc/<pid>/fdinfo */
1957a02120c4SAndy Fiddaman pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
19587c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object */
19597c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/object/xxx */
19607c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp */
19617c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
19627c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1963ab618543SJohn Levon pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
19647c478bd9Sstevel@tonic-gate pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
19657c478bd9Sstevel@tonic-gate pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
19667c478bd9Sstevel@tonic-gate pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
19677c478bd9Sstevel@tonic-gate pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
19687c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
19697c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1970f971a346SBryan Cantrill pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
19717c478bd9Sstevel@tonic-gate #if defined(__sparc)
19727c478bd9Sstevel@tonic-gate pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
19737c478bd9Sstevel@tonic-gate pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
19747c478bd9Sstevel@tonic-gate #endif
19757c478bd9Sstevel@tonic-gate pr_read_priv, /* /proc/<pid>/priv */
19767c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path */
19777c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/path/xxx */
19787c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts */
19797c478bd9Sstevel@tonic-gate pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
1980d2a70789SRichard Lowe pr_read_secflags, /* /proc/<pid>/secflags */
19817c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old process file */
19827c478bd9Sstevel@tonic-gate pr_read_pidfile, /* old lwp file */
19837c478bd9Sstevel@tonic-gate pr_read_opagedata_32, /* old pagedata file */
19847c478bd9Sstevel@tonic-gate };
19857c478bd9Sstevel@tonic-gate
19867c478bd9Sstevel@tonic-gate static int
pr_read_status_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)198719ee9cd1SAndy Fiddaman pr_read_status_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
19887c478bd9Sstevel@tonic-gate {
19897c478bd9Sstevel@tonic-gate pstatus32_t *sp;
19907c478bd9Sstevel@tonic-gate proc_t *p;
19917c478bd9Sstevel@tonic-gate int error;
19927c478bd9Sstevel@tonic-gate
19937c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_STATUS);
19947c478bd9Sstevel@tonic-gate
19957c478bd9Sstevel@tonic-gate /*
19967c478bd9Sstevel@tonic-gate * We kmem_alloc() the pstatus structure because
19977c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
19987c478bd9Sstevel@tonic-gate */
19997c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
20007c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
20017c478bd9Sstevel@tonic-gate /*
20027c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
20037c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
20047c478bd9Sstevel@tonic-gate */
20057c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
20067c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
20077c478bd9Sstevel@tonic-gate prunlock(pnp);
20087c478bd9Sstevel@tonic-gate error = EOVERFLOW;
20097c478bd9Sstevel@tonic-gate } else {
20107c478bd9Sstevel@tonic-gate prgetstatus32(pnp->pr_common->prc_proc, sp,
2011fa9e4066Sahrens VTOZONE(PTOV(pnp)));
20127c478bd9Sstevel@tonic-gate prunlock(pnp);
20137c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
20147c478bd9Sstevel@tonic-gate }
20157c478bd9Sstevel@tonic-gate }
20167c478bd9Sstevel@tonic-gate kmem_free((caddr_t)sp, sizeof (*sp));
20177c478bd9Sstevel@tonic-gate return (error);
20187c478bd9Sstevel@tonic-gate }
20197c478bd9Sstevel@tonic-gate
20207c478bd9Sstevel@tonic-gate static int
pr_read_lstatus_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)202119ee9cd1SAndy Fiddaman pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
20227c478bd9Sstevel@tonic-gate {
20237c478bd9Sstevel@tonic-gate proc_t *p;
20247c478bd9Sstevel@tonic-gate kthread_t *t;
20257c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
20267c478bd9Sstevel@tonic-gate size_t size;
20277c478bd9Sstevel@tonic-gate prheader32_t *php;
20287c478bd9Sstevel@tonic-gate lwpstatus32_t *sp;
20297c478bd9Sstevel@tonic-gate int error;
20307c478bd9Sstevel@tonic-gate int nlwp;
20317c478bd9Sstevel@tonic-gate int i;
20327c478bd9Sstevel@tonic-gate
20337c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LSTATUS);
20347c478bd9Sstevel@tonic-gate
20357c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
20367c478bd9Sstevel@tonic-gate return (error);
20377c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
20387c478bd9Sstevel@tonic-gate /*
20397c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
20407c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
20417c478bd9Sstevel@tonic-gate */
20427c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
20437c478bd9Sstevel@tonic-gate prunlock(pnp);
20447c478bd9Sstevel@tonic-gate return (EOVERFLOW);
20457c478bd9Sstevel@tonic-gate }
20467c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt;
20477c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
20487c478bd9Sstevel@tonic-gate
20497c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
20507c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
20517c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
20527c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
20537c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
20547c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
20557c478bd9Sstevel@tonic-gate
20567c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
20577c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(lwpstatus32_t);
20587c478bd9Sstevel@tonic-gate
20597c478bd9Sstevel@tonic-gate sp = (lwpstatus32_t *)(php + 1);
20607c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
20617c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
20627c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
20637c478bd9Sstevel@tonic-gate continue;
2064fa9e4066Sahrens prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
20657c478bd9Sstevel@tonic-gate sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
20667c478bd9Sstevel@tonic-gate }
20677c478bd9Sstevel@tonic-gate prunlock(pnp);
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
20707c478bd9Sstevel@tonic-gate kmem_free(php, size);
20717c478bd9Sstevel@tonic-gate return (error);
20727c478bd9Sstevel@tonic-gate }
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate static int
pr_read_psinfo_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)207519ee9cd1SAndy Fiddaman pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
20767c478bd9Sstevel@tonic-gate {
20777c478bd9Sstevel@tonic-gate psinfo32_t psinfo;
20787c478bd9Sstevel@tonic-gate proc_t *p;
20797c478bd9Sstevel@tonic-gate int error = 0;
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PSINFO);
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate /*
20847c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
20857c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
20867c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
20877c478bd9Sstevel@tonic-gate */
20887c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
20897c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
20907c478bd9Sstevel@tonic-gate if (p == NULL)
20917c478bd9Sstevel@tonic-gate error = ENOENT;
20927c478bd9Sstevel@tonic-gate else {
20937c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
20947c478bd9Sstevel@tonic-gate prgetpsinfo32(p, &psinfo);
20957c478bd9Sstevel@tonic-gate prunlock(pnp);
20967c478bd9Sstevel@tonic-gate error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
20977c478bd9Sstevel@tonic-gate }
20987c478bd9Sstevel@tonic-gate return (error);
20997c478bd9Sstevel@tonic-gate }
21007c478bd9Sstevel@tonic-gate
21017c478bd9Sstevel@tonic-gate static int
pr_read_lpsinfo_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)210219ee9cd1SAndy Fiddaman pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
21037c478bd9Sstevel@tonic-gate {
21047c478bd9Sstevel@tonic-gate proc_t *p;
21057c478bd9Sstevel@tonic-gate kthread_t *t;
21067c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
21077c478bd9Sstevel@tonic-gate lwpent_t *lep;
21087c478bd9Sstevel@tonic-gate size_t size;
21097c478bd9Sstevel@tonic-gate prheader32_t *php;
21107c478bd9Sstevel@tonic-gate lwpsinfo32_t *sp;
21117c478bd9Sstevel@tonic-gate int error;
21127c478bd9Sstevel@tonic-gate int nlwp;
21137c478bd9Sstevel@tonic-gate int i;
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LPSINFO);
21167c478bd9Sstevel@tonic-gate
21177c478bd9Sstevel@tonic-gate /*
21187c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
21197c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
21207c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
21217c478bd9Sstevel@tonic-gate */
21227c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
21237c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
21247c478bd9Sstevel@tonic-gate if (p == NULL)
21257c478bd9Sstevel@tonic-gate return (ENOENT);
21267c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
21277c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
21287c478bd9Sstevel@tonic-gate prunlock(pnp);
21297c478bd9Sstevel@tonic-gate return (ENOENT);
21307c478bd9Sstevel@tonic-gate }
21317c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
21327c478bd9Sstevel@tonic-gate
21337c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
21347c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
21357c478bd9Sstevel@tonic-gate php = kmem_zalloc(size, KM_SLEEP);
21367c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
21377c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
21387c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
21397c478bd9Sstevel@tonic-gate
21407c478bd9Sstevel@tonic-gate php->pr_nent = nlwp;
21417c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(lwpsinfo32_t);
21427c478bd9Sstevel@tonic-gate
21437c478bd9Sstevel@tonic-gate sp = (lwpsinfo32_t *)(php + 1);
21447c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
21457c478bd9Sstevel@tonic-gate if ((lep = ldp->ld_entry) == NULL)
21467c478bd9Sstevel@tonic-gate continue;
21477c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) != NULL)
21487c478bd9Sstevel@tonic-gate prgetlwpsinfo32(t, sp);
21497c478bd9Sstevel@tonic-gate else {
21507c478bd9Sstevel@tonic-gate bzero(sp, sizeof (*sp));
21517c478bd9Sstevel@tonic-gate sp->pr_lwpid = lep->le_lwpid;
21527c478bd9Sstevel@tonic-gate sp->pr_state = SZOMB;
21537c478bd9Sstevel@tonic-gate sp->pr_sname = 'Z';
21547c478bd9Sstevel@tonic-gate sp->pr_start.tv_sec = (time32_t)lep->le_start;
21557c478bd9Sstevel@tonic-gate }
21567c478bd9Sstevel@tonic-gate sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
21577c478bd9Sstevel@tonic-gate }
21587c478bd9Sstevel@tonic-gate prunlock(pnp);
21597c478bd9Sstevel@tonic-gate
21607c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
21617c478bd9Sstevel@tonic-gate kmem_free(php, size);
21627c478bd9Sstevel@tonic-gate return (error);
21637c478bd9Sstevel@tonic-gate }
21647c478bd9Sstevel@tonic-gate
21657c478bd9Sstevel@tonic-gate static int
pr_read_map_common_32(prnode_t * pnp,uio_t * uiop,prnodetype_t type)2166870619e9Sfrankho pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
21677c478bd9Sstevel@tonic-gate {
21687c478bd9Sstevel@tonic-gate proc_t *p;
21697c478bd9Sstevel@tonic-gate struct as *as;
2170870619e9Sfrankho list_t iolhead;
21717c478bd9Sstevel@tonic-gate int error;
21727c478bd9Sstevel@tonic-gate
2173e24ad047SChristopher Baumbauer - Oracle America - San Diego United States readmap32_common:
21747c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
21757c478bd9Sstevel@tonic-gate return (error);
21767c478bd9Sstevel@tonic-gate
21777c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
21787c478bd9Sstevel@tonic-gate as = p->p_as;
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
21817c478bd9Sstevel@tonic-gate prunlock(pnp);
21827c478bd9Sstevel@tonic-gate return (0);
21837c478bd9Sstevel@tonic-gate }
21847c478bd9Sstevel@tonic-gate
21857c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
21867c478bd9Sstevel@tonic-gate prunlock(pnp);
21877c478bd9Sstevel@tonic-gate return (EOVERFLOW);
21887c478bd9Sstevel@tonic-gate }
21897c478bd9Sstevel@tonic-gate
2190dc32d872SJosef 'Jeff' Sipek if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
2191e24ad047SChristopher Baumbauer - Oracle America - San Diego United States prunlock(pnp);
2192e24ad047SChristopher Baumbauer - Oracle America - San Diego United States delay(1);
2193e24ad047SChristopher Baumbauer - Oracle America - San Diego United States goto readmap32_common;
2194e24ad047SChristopher Baumbauer - Oracle America - San Diego United States }
21957c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
2196e24ad047SChristopher Baumbauer - Oracle America - San Diego United States
2197870619e9Sfrankho switch (type) {
2198870619e9Sfrankho case PR_XMAP:
2199870619e9Sfrankho error = prgetxmap32(p, &iolhead);
2200870619e9Sfrankho break;
2201870619e9Sfrankho case PR_RMAP:
2202870619e9Sfrankho error = prgetmap32(p, 1, &iolhead);
2203870619e9Sfrankho break;
2204870619e9Sfrankho case PR_MAP:
2205870619e9Sfrankho error = prgetmap32(p, 0, &iolhead);
2206870619e9Sfrankho break;
2207870619e9Sfrankho }
2208dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
22097c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
22107c478bd9Sstevel@tonic-gate prunlock(pnp);
22117c478bd9Sstevel@tonic-gate
2212870619e9Sfrankho error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
2213870619e9Sfrankho
22147c478bd9Sstevel@tonic-gate return (error);
22157c478bd9Sstevel@tonic-gate }
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gate static int
pr_read_map_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)221819ee9cd1SAndy Fiddaman pr_read_map_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
22197c478bd9Sstevel@tonic-gate {
22207c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_MAP);
2221870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
22227c478bd9Sstevel@tonic-gate }
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate static int
pr_read_rmap_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)222519ee9cd1SAndy Fiddaman pr_read_rmap_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
22267c478bd9Sstevel@tonic-gate {
22277c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_RMAP);
2228870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
22297c478bd9Sstevel@tonic-gate }
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate static int
pr_read_xmap_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)223219ee9cd1SAndy Fiddaman pr_read_xmap_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
22337c478bd9Sstevel@tonic-gate {
22347c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_XMAP);
2235870619e9Sfrankho return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
22367c478bd9Sstevel@tonic-gate }
22377c478bd9Sstevel@tonic-gate
22387c478bd9Sstevel@tonic-gate static int
pr_read_sigact_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)223919ee9cd1SAndy Fiddaman pr_read_sigact_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
22407c478bd9Sstevel@tonic-gate {
2241eb9dbf0cSRoger A. Faulkner int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
22427c478bd9Sstevel@tonic-gate proc_t *p;
22437c478bd9Sstevel@tonic-gate struct sigaction32 *sap;
22447c478bd9Sstevel@tonic-gate int sig;
22457c478bd9Sstevel@tonic-gate int error;
22467c478bd9Sstevel@tonic-gate user_t *up;
22477c478bd9Sstevel@tonic-gate
22487c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_SIGACT);
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate /*
22517c478bd9Sstevel@tonic-gate * We kmem_alloc() the sigaction32 array because
22527c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
22537c478bd9Sstevel@tonic-gate */
2254eb9dbf0cSRoger A. Faulkner sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
22577c478bd9Sstevel@tonic-gate goto out;
22587c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
22617c478bd9Sstevel@tonic-gate prunlock(pnp);
22627c478bd9Sstevel@tonic-gate error = EOVERFLOW;
22637c478bd9Sstevel@tonic-gate goto out;
22647c478bd9Sstevel@tonic-gate }
22657c478bd9Sstevel@tonic-gate
2266eb9dbf0cSRoger A. Faulkner if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
22677c478bd9Sstevel@tonic-gate prunlock(pnp);
22687c478bd9Sstevel@tonic-gate goto out;
22697c478bd9Sstevel@tonic-gate }
22707c478bd9Sstevel@tonic-gate
22717c478bd9Sstevel@tonic-gate up = PTOU(p);
2272eb9dbf0cSRoger A. Faulkner for (sig = 1; sig < nsig; sig++)
22737c478bd9Sstevel@tonic-gate prgetaction32(p, up, sig, &sap[sig-1]);
22747c478bd9Sstevel@tonic-gate prunlock(pnp);
22757c478bd9Sstevel@tonic-gate
2276eb9dbf0cSRoger A. Faulkner error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
22777c478bd9Sstevel@tonic-gate out:
2278eb9dbf0cSRoger A. Faulkner kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
22797c478bd9Sstevel@tonic-gate return (error);
22807c478bd9Sstevel@tonic-gate }
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate static int
pr_read_auxv_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)228319ee9cd1SAndy Fiddaman pr_read_auxv_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
22847c478bd9Sstevel@tonic-gate {
22857c478bd9Sstevel@tonic-gate auxv32_t auxv[__KERN_NAUXV_IMPL];
22867c478bd9Sstevel@tonic-gate proc_t *p;
22877c478bd9Sstevel@tonic-gate user_t *up;
22887c478bd9Sstevel@tonic-gate int error;
22897c478bd9Sstevel@tonic-gate int i;
22907c478bd9Sstevel@tonic-gate
22917c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_AUXV);
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
22947c478bd9Sstevel@tonic-gate return (error);
22957c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
22967c478bd9Sstevel@tonic-gate
22977c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
22987c478bd9Sstevel@tonic-gate prunlock(pnp);
22997c478bd9Sstevel@tonic-gate return (EOVERFLOW);
23007c478bd9Sstevel@tonic-gate }
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (auxv)) {
23037c478bd9Sstevel@tonic-gate prunlock(pnp);
23047c478bd9Sstevel@tonic-gate return (0);
23057c478bd9Sstevel@tonic-gate }
23067c478bd9Sstevel@tonic-gate
23077c478bd9Sstevel@tonic-gate up = PTOU(p);
23087c478bd9Sstevel@tonic-gate for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
23097c478bd9Sstevel@tonic-gate auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
23107c478bd9Sstevel@tonic-gate auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
23117c478bd9Sstevel@tonic-gate }
23127c478bd9Sstevel@tonic-gate prunlock(pnp);
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gate return (pr_uioread(auxv, sizeof (auxv), uiop));
23157c478bd9Sstevel@tonic-gate }
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate static int
pr_read_usage_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)231819ee9cd1SAndy Fiddaman pr_read_usage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
23197c478bd9Sstevel@tonic-gate {
23207c478bd9Sstevel@tonic-gate prhusage_t *pup;
23217c478bd9Sstevel@tonic-gate prusage32_t *upup;
23227c478bd9Sstevel@tonic-gate proc_t *p;
23237c478bd9Sstevel@tonic-gate kthread_t *t;
23247c478bd9Sstevel@tonic-gate int error;
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_USAGE);
23277c478bd9Sstevel@tonic-gate
23287c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
23297c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
23307c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
23317c478bd9Sstevel@tonic-gate
23327c478bd9Sstevel@tonic-gate /*
23337c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
23347c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
23357c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
23367c478bd9Sstevel@tonic-gate */
23377c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
23387c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
23397c478bd9Sstevel@tonic-gate if (p == NULL) {
23407c478bd9Sstevel@tonic-gate error = ENOENT;
23417c478bd9Sstevel@tonic-gate goto out;
23427c478bd9Sstevel@tonic-gate }
23437c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
23447c478bd9Sstevel@tonic-gate
23457c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage32_t)) {
23467c478bd9Sstevel@tonic-gate prunlock(pnp);
23477c478bd9Sstevel@tonic-gate error = 0;
23487c478bd9Sstevel@tonic-gate goto out;
23497c478bd9Sstevel@tonic-gate }
23507c478bd9Sstevel@tonic-gate
23517c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
23527c478bd9Sstevel@tonic-gate
23537c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
23547c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
23557c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
23567c478bd9Sstevel@tonic-gate
23577c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
23587c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
23597c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
23607c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
23617c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
23627c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
23637c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
23647c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
23657c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
23667c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
23677c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
23687c478bd9Sstevel@tonic-gate
23697c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
23707c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
23717c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
23727c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
23737c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
23747c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
23757c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
23767c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
23777c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
23787c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
23797c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
23807c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
23817c478bd9Sstevel@tonic-gate
23827c478bd9Sstevel@tonic-gate /*
23837c478bd9Sstevel@tonic-gate * Add the usage information for each active lwp.
23847c478bd9Sstevel@tonic-gate */
23857c478bd9Sstevel@tonic-gate if ((t = p->p_tlist) != NULL &&
23867c478bd9Sstevel@tonic-gate !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
23877c478bd9Sstevel@tonic-gate do {
23887c478bd9Sstevel@tonic-gate if (t->t_proc_flag & TP_LWPEXIT)
23897c478bd9Sstevel@tonic-gate continue;
23907c478bd9Sstevel@tonic-gate pup->pr_count++;
23917c478bd9Sstevel@tonic-gate praddusage(t, pup);
23927c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist);
23937c478bd9Sstevel@tonic-gate }
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate prunlock(pnp);
23967c478bd9Sstevel@tonic-gate
23977c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
23987c478bd9Sstevel@tonic-gate
23997c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage32_t), uiop);
24007c478bd9Sstevel@tonic-gate out:
24017c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
24027c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
24037c478bd9Sstevel@tonic-gate return (error);
24047c478bd9Sstevel@tonic-gate }
24057c478bd9Sstevel@tonic-gate
24067c478bd9Sstevel@tonic-gate static int
pr_read_lusage_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)240719ee9cd1SAndy Fiddaman pr_read_lusage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
24087c478bd9Sstevel@tonic-gate {
24097c478bd9Sstevel@tonic-gate int nlwp;
24107c478bd9Sstevel@tonic-gate prhusage_t *pup;
24117c478bd9Sstevel@tonic-gate prheader32_t *php;
24127c478bd9Sstevel@tonic-gate prusage32_t *upup;
24137c478bd9Sstevel@tonic-gate size_t size;
24147c478bd9Sstevel@tonic-gate hrtime_t curtime;
24157c478bd9Sstevel@tonic-gate proc_t *p;
24167c478bd9Sstevel@tonic-gate kthread_t *t;
24177c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
24187c478bd9Sstevel@tonic-gate int error;
24197c478bd9Sstevel@tonic-gate int i;
24207c478bd9Sstevel@tonic-gate
24217c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LUSAGE);
24227c478bd9Sstevel@tonic-gate
24237c478bd9Sstevel@tonic-gate /*
24247c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
24257c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
24267c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
24277c478bd9Sstevel@tonic-gate */
24287c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
24297c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
24307c478bd9Sstevel@tonic-gate if (p == NULL)
24317c478bd9Sstevel@tonic-gate return (ENOENT);
24327c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
24337c478bd9Sstevel@tonic-gate if ((nlwp = p->p_lwpcnt) == 0) {
24347c478bd9Sstevel@tonic-gate prunlock(pnp);
24357c478bd9Sstevel@tonic-gate return (ENOENT);
24367c478bd9Sstevel@tonic-gate }
24377c478bd9Sstevel@tonic-gate
24387c478bd9Sstevel@tonic-gate size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
24397c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
24407c478bd9Sstevel@tonic-gate prunlock(pnp);
24417c478bd9Sstevel@tonic-gate return (0);
24427c478bd9Sstevel@tonic-gate }
24437c478bd9Sstevel@tonic-gate
24447c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
24457c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
24467c478bd9Sstevel@tonic-gate pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
24477c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
24487c478bd9Sstevel@tonic-gate /* p->p_lwpcnt can't change while process is locked */
24497c478bd9Sstevel@tonic-gate ASSERT(nlwp == p->p_lwpcnt);
24507c478bd9Sstevel@tonic-gate
24517c478bd9Sstevel@tonic-gate php = (prheader32_t *)(pup + 1);
24527c478bd9Sstevel@tonic-gate upup = (prusage32_t *)(php + 1);
24537c478bd9Sstevel@tonic-gate
24547c478bd9Sstevel@tonic-gate php->pr_nent = nlwp + 1;
24557c478bd9Sstevel@tonic-gate php->pr_entsize = LSPAN32(prusage32_t);
24567c478bd9Sstevel@tonic-gate
24577c478bd9Sstevel@tonic-gate curtime = gethrtime();
24587c478bd9Sstevel@tonic-gate
24597c478bd9Sstevel@tonic-gate /*
24607c478bd9Sstevel@tonic-gate * First the summation over defunct lwps.
24617c478bd9Sstevel@tonic-gate */
24627c478bd9Sstevel@tonic-gate pup->pr_count = p->p_defunct;
24637c478bd9Sstevel@tonic-gate pup->pr_tstamp = curtime;
24647c478bd9Sstevel@tonic-gate pup->pr_create = p->p_mstart;
24657c478bd9Sstevel@tonic-gate pup->pr_term = p->p_mterm;
24667c478bd9Sstevel@tonic-gate
24677c478bd9Sstevel@tonic-gate pup->pr_rtime = p->p_mlreal;
24687c478bd9Sstevel@tonic-gate pup->pr_utime = p->p_acct[LMS_USER];
24697c478bd9Sstevel@tonic-gate pup->pr_stime = p->p_acct[LMS_SYSTEM];
24707c478bd9Sstevel@tonic-gate pup->pr_ttime = p->p_acct[LMS_TRAP];
24717c478bd9Sstevel@tonic-gate pup->pr_tftime = p->p_acct[LMS_TFAULT];
24727c478bd9Sstevel@tonic-gate pup->pr_dftime = p->p_acct[LMS_DFAULT];
24737c478bd9Sstevel@tonic-gate pup->pr_kftime = p->p_acct[LMS_KFAULT];
24747c478bd9Sstevel@tonic-gate pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
24757c478bd9Sstevel@tonic-gate pup->pr_slptime = p->p_acct[LMS_SLEEP];
24767c478bd9Sstevel@tonic-gate pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
24777c478bd9Sstevel@tonic-gate pup->pr_stoptime = p->p_acct[LMS_STOPPED];
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate pup->pr_minf = p->p_ru.minflt;
24807c478bd9Sstevel@tonic-gate pup->pr_majf = p->p_ru.majflt;
24817c478bd9Sstevel@tonic-gate pup->pr_nswap = p->p_ru.nswap;
24827c478bd9Sstevel@tonic-gate pup->pr_inblk = p->p_ru.inblock;
24837c478bd9Sstevel@tonic-gate pup->pr_oublk = p->p_ru.oublock;
24847c478bd9Sstevel@tonic-gate pup->pr_msnd = p->p_ru.msgsnd;
24857c478bd9Sstevel@tonic-gate pup->pr_mrcv = p->p_ru.msgrcv;
24867c478bd9Sstevel@tonic-gate pup->pr_sigs = p->p_ru.nsignals;
24877c478bd9Sstevel@tonic-gate pup->pr_vctx = p->p_ru.nvcsw;
24887c478bd9Sstevel@tonic-gate pup->pr_ictx = p->p_ru.nivcsw;
24897c478bd9Sstevel@tonic-gate pup->pr_sysc = p->p_ru.sysc;
24907c478bd9Sstevel@tonic-gate pup->pr_ioch = p->p_ru.ioch;
24917c478bd9Sstevel@tonic-gate
24927c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate /*
24957c478bd9Sstevel@tonic-gate * Fill one prusage struct for each active lwp.
24967c478bd9Sstevel@tonic-gate */
24977c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
24987c478bd9Sstevel@tonic-gate if (ldp->ld_entry == NULL ||
24997c478bd9Sstevel@tonic-gate (t = ldp->ld_entry->le_thread) == NULL)
25007c478bd9Sstevel@tonic-gate continue;
25017c478bd9Sstevel@tonic-gate ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
25027c478bd9Sstevel@tonic-gate ASSERT(nlwp > 0);
25037c478bd9Sstevel@tonic-gate --nlwp;
25047c478bd9Sstevel@tonic-gate upup = (prusage32_t *)
25057c478bd9Sstevel@tonic-gate ((caddr_t)upup + LSPAN32(prusage32_t));
25067c478bd9Sstevel@tonic-gate prgetusage(t, pup);
25077c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
25087c478bd9Sstevel@tonic-gate }
25097c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0);
25107c478bd9Sstevel@tonic-gate
25117c478bd9Sstevel@tonic-gate prunlock(pnp);
25127c478bd9Sstevel@tonic-gate
25137c478bd9Sstevel@tonic-gate error = pr_uioread(php, size, uiop);
25147c478bd9Sstevel@tonic-gate kmem_free(pup, size + sizeof (prhusage_t));
25157c478bd9Sstevel@tonic-gate return (error);
25167c478bd9Sstevel@tonic-gate }
25177c478bd9Sstevel@tonic-gate
25187c478bd9Sstevel@tonic-gate static int
pr_read_pagedata_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)251919ee9cd1SAndy Fiddaman pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
25207c478bd9Sstevel@tonic-gate {
25217c478bd9Sstevel@tonic-gate proc_t *p;
25227c478bd9Sstevel@tonic-gate int error;
25237c478bd9Sstevel@tonic-gate
25247c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PAGEDATA);
25257c478bd9Sstevel@tonic-gate
25267c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
25277c478bd9Sstevel@tonic-gate return (error);
25287c478bd9Sstevel@tonic-gate
25297c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
25307c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
25317c478bd9Sstevel@tonic-gate prunlock(pnp);
25327c478bd9Sstevel@tonic-gate return (0);
25337c478bd9Sstevel@tonic-gate }
25347c478bd9Sstevel@tonic-gate
25357c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
25367c478bd9Sstevel@tonic-gate prunlock(pnp);
25377c478bd9Sstevel@tonic-gate return (EOVERFLOW);
25387c478bd9Sstevel@tonic-gate }
25397c478bd9Sstevel@tonic-gate
25407c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
25417c478bd9Sstevel@tonic-gate error = prpdread32(p, pnp->pr_hatid, uiop);
25427c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
25437c478bd9Sstevel@tonic-gate
25447c478bd9Sstevel@tonic-gate prunlock(pnp);
25457c478bd9Sstevel@tonic-gate return (error);
25467c478bd9Sstevel@tonic-gate }
25477c478bd9Sstevel@tonic-gate
25487c478bd9Sstevel@tonic-gate static int
pr_read_opagedata_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)254919ee9cd1SAndy Fiddaman pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
25507c478bd9Sstevel@tonic-gate {
25517c478bd9Sstevel@tonic-gate proc_t *p;
25527c478bd9Sstevel@tonic-gate struct as *as;
25537c478bd9Sstevel@tonic-gate int error;
25547c478bd9Sstevel@tonic-gate
25557c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OPAGEDATA);
25567c478bd9Sstevel@tonic-gate
25577c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
25587c478bd9Sstevel@tonic-gate return (error);
25597c478bd9Sstevel@tonic-gate
25607c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
25617c478bd9Sstevel@tonic-gate as = p->p_as;
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
25647c478bd9Sstevel@tonic-gate prunlock(pnp);
25657c478bd9Sstevel@tonic-gate return (0);
25667c478bd9Sstevel@tonic-gate }
25677c478bd9Sstevel@tonic-gate
25687c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
25697c478bd9Sstevel@tonic-gate prunlock(pnp);
25707c478bd9Sstevel@tonic-gate return (EOVERFLOW);
25717c478bd9Sstevel@tonic-gate }
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
25747c478bd9Sstevel@tonic-gate error = oprpdread32(as, pnp->pr_hatid, uiop);
25757c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate prunlock(pnp);
25787c478bd9Sstevel@tonic-gate return (error);
25797c478bd9Sstevel@tonic-gate }
25807c478bd9Sstevel@tonic-gate
25817c478bd9Sstevel@tonic-gate static int
pr_read_watch_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)258219ee9cd1SAndy Fiddaman pr_read_watch_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
25837c478bd9Sstevel@tonic-gate {
25847c478bd9Sstevel@tonic-gate proc_t *p;
25857c478bd9Sstevel@tonic-gate int error;
25867c478bd9Sstevel@tonic-gate prwatch32_t *Bpwp;
25877c478bd9Sstevel@tonic-gate size_t size;
25887c478bd9Sstevel@tonic-gate prwatch32_t *pwp;
25897c478bd9Sstevel@tonic-gate int nwarea;
25907c478bd9Sstevel@tonic-gate struct watched_area *pwarea;
25917c478bd9Sstevel@tonic-gate
25927c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_WATCH);
25937c478bd9Sstevel@tonic-gate
25947c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
25957c478bd9Sstevel@tonic-gate return (error);
25967c478bd9Sstevel@tonic-gate
25977c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
25987c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
25997c478bd9Sstevel@tonic-gate prunlock(pnp);
26007c478bd9Sstevel@tonic-gate return (EOVERFLOW);
26017c478bd9Sstevel@tonic-gate }
26027c478bd9Sstevel@tonic-gate nwarea = avl_numnodes(&p->p_warea);
26037c478bd9Sstevel@tonic-gate size = nwarea * sizeof (prwatch32_t);
26047c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
26057c478bd9Sstevel@tonic-gate prunlock(pnp);
26067c478bd9Sstevel@tonic-gate return (0);
26077c478bd9Sstevel@tonic-gate }
26087c478bd9Sstevel@tonic-gate
26097c478bd9Sstevel@tonic-gate /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
26107c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
26117c478bd9Sstevel@tonic-gate Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
26127c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
26137c478bd9Sstevel@tonic-gate /* p->p_nwarea can't change while process is locked */
26147c478bd9Sstevel@tonic-gate ASSERT(nwarea == avl_numnodes(&p->p_warea));
26157c478bd9Sstevel@tonic-gate
26167c478bd9Sstevel@tonic-gate /* gather the watched areas */
26177c478bd9Sstevel@tonic-gate for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
26187c478bd9Sstevel@tonic-gate pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
26197c478bd9Sstevel@tonic-gate pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
26207c478bd9Sstevel@tonic-gate pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
26217c478bd9Sstevel@tonic-gate pwp->pr_wflags = (int)pwarea->wa_flags;
26227c478bd9Sstevel@tonic-gate }
26237c478bd9Sstevel@tonic-gate
26247c478bd9Sstevel@tonic-gate prunlock(pnp);
26257c478bd9Sstevel@tonic-gate
26267c478bd9Sstevel@tonic-gate error = pr_uioread(Bpwp, size, uiop);
26277c478bd9Sstevel@tonic-gate kmem_free(Bpwp, size);
26287c478bd9Sstevel@tonic-gate return (error);
26297c478bd9Sstevel@tonic-gate }
26307c478bd9Sstevel@tonic-gate
26317c478bd9Sstevel@tonic-gate static int
pr_read_lwpstatus_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)263219ee9cd1SAndy Fiddaman pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
26337c478bd9Sstevel@tonic-gate {
26347c478bd9Sstevel@tonic-gate lwpstatus32_t *sp;
26357c478bd9Sstevel@tonic-gate proc_t *p;
26367c478bd9Sstevel@tonic-gate int error;
26377c478bd9Sstevel@tonic-gate
26387c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSTATUS);
26397c478bd9Sstevel@tonic-gate
26407c478bd9Sstevel@tonic-gate /*
26417c478bd9Sstevel@tonic-gate * We kmem_alloc() the lwpstatus structure because
26427c478bd9Sstevel@tonic-gate * it is so big it might blow the kernel stack.
26437c478bd9Sstevel@tonic-gate */
26447c478bd9Sstevel@tonic-gate sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
26457c478bd9Sstevel@tonic-gate
26467c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
26477c478bd9Sstevel@tonic-gate goto out;
26487c478bd9Sstevel@tonic-gate
26497c478bd9Sstevel@tonic-gate /*
26507c478bd9Sstevel@tonic-gate * A 32-bit process cannot get the status of a 64-bit process.
26517c478bd9Sstevel@tonic-gate * The fields for the 64-bit quantities are not large enough.
26527c478bd9Sstevel@tonic-gate */
26537c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
26547c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
26557c478bd9Sstevel@tonic-gate prunlock(pnp);
26567c478bd9Sstevel@tonic-gate error = EOVERFLOW;
26577c478bd9Sstevel@tonic-gate goto out;
26587c478bd9Sstevel@tonic-gate }
26597c478bd9Sstevel@tonic-gate
26607c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (*sp)) {
26617c478bd9Sstevel@tonic-gate prunlock(pnp);
26627c478bd9Sstevel@tonic-gate goto out;
26637c478bd9Sstevel@tonic-gate }
26647c478bd9Sstevel@tonic-gate
2665fa9e4066Sahrens prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
26667c478bd9Sstevel@tonic-gate prunlock(pnp);
26677c478bd9Sstevel@tonic-gate
26687c478bd9Sstevel@tonic-gate error = pr_uioread(sp, sizeof (*sp), uiop);
26697c478bd9Sstevel@tonic-gate out:
26707c478bd9Sstevel@tonic-gate kmem_free(sp, sizeof (*sp));
26717c478bd9Sstevel@tonic-gate return (error);
26727c478bd9Sstevel@tonic-gate }
26737c478bd9Sstevel@tonic-gate
26747c478bd9Sstevel@tonic-gate static int
pr_read_lwpsinfo_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)267519ee9cd1SAndy Fiddaman pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
26767c478bd9Sstevel@tonic-gate {
26777c478bd9Sstevel@tonic-gate lwpsinfo32_t lwpsinfo;
26787c478bd9Sstevel@tonic-gate proc_t *p;
26797c478bd9Sstevel@tonic-gate kthread_t *t;
26807c478bd9Sstevel@tonic-gate lwpent_t *lep;
26817c478bd9Sstevel@tonic-gate
26827c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPSINFO);
26837c478bd9Sstevel@tonic-gate
26847c478bd9Sstevel@tonic-gate /*
26857c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
26867c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
26877c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
26887c478bd9Sstevel@tonic-gate */
26897c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
26907c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
26917c478bd9Sstevel@tonic-gate if (p == NULL)
26927c478bd9Sstevel@tonic-gate return (ENOENT);
26937c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
26947c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_tslot == -1) {
26957c478bd9Sstevel@tonic-gate prunlock(pnp);
26967c478bd9Sstevel@tonic-gate return (ENOENT);
26977c478bd9Sstevel@tonic-gate }
26987c478bd9Sstevel@tonic-gate
26997c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpsinfo)) {
27007c478bd9Sstevel@tonic-gate prunlock(pnp);
27017c478bd9Sstevel@tonic-gate return (0);
27027c478bd9Sstevel@tonic-gate }
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate if ((t = pnp->pr_common->prc_thread) != NULL)
27057c478bd9Sstevel@tonic-gate prgetlwpsinfo32(t, &lwpsinfo);
27067c478bd9Sstevel@tonic-gate else {
27077c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
27087c478bd9Sstevel@tonic-gate bzero(&lwpsinfo, sizeof (lwpsinfo));
27097c478bd9Sstevel@tonic-gate lwpsinfo.pr_lwpid = lep->le_lwpid;
27107c478bd9Sstevel@tonic-gate lwpsinfo.pr_state = SZOMB;
27117c478bd9Sstevel@tonic-gate lwpsinfo.pr_sname = 'Z';
27127c478bd9Sstevel@tonic-gate lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
27137c478bd9Sstevel@tonic-gate }
27147c478bd9Sstevel@tonic-gate prunlock(pnp);
27157c478bd9Sstevel@tonic-gate
27167c478bd9Sstevel@tonic-gate return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
27177c478bd9Sstevel@tonic-gate }
27187c478bd9Sstevel@tonic-gate
27197c478bd9Sstevel@tonic-gate static int
pr_read_lwpusage_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)272019ee9cd1SAndy Fiddaman pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
27217c478bd9Sstevel@tonic-gate {
27227c478bd9Sstevel@tonic-gate prhusage_t *pup;
27237c478bd9Sstevel@tonic-gate prusage32_t *upup;
27247c478bd9Sstevel@tonic-gate proc_t *p;
27257c478bd9Sstevel@tonic-gate int error;
27267c478bd9Sstevel@tonic-gate
27277c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPUSAGE);
27287c478bd9Sstevel@tonic-gate
27297c478bd9Sstevel@tonic-gate /* allocate now, before locking the process */
27307c478bd9Sstevel@tonic-gate pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
27317c478bd9Sstevel@tonic-gate upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
27327c478bd9Sstevel@tonic-gate
27337c478bd9Sstevel@tonic-gate /*
27347c478bd9Sstevel@tonic-gate * We don't want the full treatment of prlock(pnp) here.
27357c478bd9Sstevel@tonic-gate * This file is world-readable and never goes invalid.
27367c478bd9Sstevel@tonic-gate * It doesn't matter if we are in the middle of an exec().
27377c478bd9Sstevel@tonic-gate */
27387c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
27397c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
27407c478bd9Sstevel@tonic-gate if (p == NULL) {
27417c478bd9Sstevel@tonic-gate error = ENOENT;
27427c478bd9Sstevel@tonic-gate goto out;
27437c478bd9Sstevel@tonic-gate }
27447c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
27457c478bd9Sstevel@tonic-gate if (pnp->pr_common->prc_thread == NULL) {
27467c478bd9Sstevel@tonic-gate prunlock(pnp);
27477c478bd9Sstevel@tonic-gate error = ENOENT;
27487c478bd9Sstevel@tonic-gate goto out;
27497c478bd9Sstevel@tonic-gate }
27507c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (prusage32_t)) {
27517c478bd9Sstevel@tonic-gate prunlock(pnp);
27527c478bd9Sstevel@tonic-gate error = 0;
27537c478bd9Sstevel@tonic-gate goto out;
27547c478bd9Sstevel@tonic-gate }
27557c478bd9Sstevel@tonic-gate
27567c478bd9Sstevel@tonic-gate pup->pr_tstamp = gethrtime();
27577c478bd9Sstevel@tonic-gate prgetusage(pnp->pr_common->prc_thread, pup);
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate prunlock(pnp);
27607c478bd9Sstevel@tonic-gate
27617c478bd9Sstevel@tonic-gate prcvtusage32(pup, upup);
27627c478bd9Sstevel@tonic-gate
27637c478bd9Sstevel@tonic-gate error = pr_uioread(upup, sizeof (prusage32_t), uiop);
27647c478bd9Sstevel@tonic-gate out:
27657c478bd9Sstevel@tonic-gate kmem_free(pup, sizeof (*pup));
27667c478bd9Sstevel@tonic-gate kmem_free(upup, sizeof (*upup));
27677c478bd9Sstevel@tonic-gate return (error);
27687c478bd9Sstevel@tonic-gate }
27697c478bd9Sstevel@tonic-gate
2770f971a346SBryan Cantrill static int
pr_read_spymaster_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)277119ee9cd1SAndy Fiddaman pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2772f971a346SBryan Cantrill {
2773f971a346SBryan Cantrill psinfo32_t psinfo;
2774f971a346SBryan Cantrill int error;
2775f971a346SBryan Cantrill klwp_t *lwp;
2776f971a346SBryan Cantrill
2777f971a346SBryan Cantrill ASSERT(pnp->pr_type == PR_SPYMASTER);
2778f971a346SBryan Cantrill
2779f971a346SBryan Cantrill if ((error = prlock(pnp, ZNO)) != 0)
2780f971a346SBryan Cantrill return (error);
2781f971a346SBryan Cantrill
2782614f1d63SJerry Jelinek if (pnp->pr_common->prc_thread == NULL) {
2783614f1d63SJerry Jelinek prunlock(pnp);
2784614f1d63SJerry Jelinek return (0);
2785614f1d63SJerry Jelinek }
2786614f1d63SJerry Jelinek
2787f971a346SBryan Cantrill lwp = pnp->pr_common->prc_thread->t_lwp;
2788f971a346SBryan Cantrill
2789f971a346SBryan Cantrill if (lwp->lwp_spymaster == NULL) {
2790f971a346SBryan Cantrill prunlock(pnp);
2791f971a346SBryan Cantrill return (0);
2792f971a346SBryan Cantrill }
2793f971a346SBryan Cantrill
2794f971a346SBryan Cantrill psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2795f971a346SBryan Cantrill prunlock(pnp);
2796f971a346SBryan Cantrill
2797f971a346SBryan Cantrill return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2798f971a346SBryan Cantrill }
2799f971a346SBryan Cantrill
28007c478bd9Sstevel@tonic-gate #if defined(__sparc)
28017c478bd9Sstevel@tonic-gate static int
pr_read_gwindows_32(prnode_t * pnp,uio_t * uiop,cred_t * cr)280219ee9cd1SAndy Fiddaman pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
28037c478bd9Sstevel@tonic-gate {
28047c478bd9Sstevel@tonic-gate proc_t *p;
28057c478bd9Sstevel@tonic-gate kthread_t *t;
28067c478bd9Sstevel@tonic-gate gwindows32_t *gwp;
28077c478bd9Sstevel@tonic-gate int error;
28087c478bd9Sstevel@tonic-gate size_t size;
28097c478bd9Sstevel@tonic-gate
28107c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_GWINDOWS);
28117c478bd9Sstevel@tonic-gate
28127c478bd9Sstevel@tonic-gate gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
28137c478bd9Sstevel@tonic-gate
28147c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
28157c478bd9Sstevel@tonic-gate goto out;
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
28187c478bd9Sstevel@tonic-gate t = pnp->pr_common->prc_thread;
28197c478bd9Sstevel@tonic-gate
28207c478bd9Sstevel@tonic-gate if (PROCESS_NOT_32BIT(p)) {
28217c478bd9Sstevel@tonic-gate prunlock(pnp);
28227c478bd9Sstevel@tonic-gate error = EOVERFLOW;
28237c478bd9Sstevel@tonic-gate goto out;
28247c478bd9Sstevel@tonic-gate }
28257c478bd9Sstevel@tonic-gate
28267c478bd9Sstevel@tonic-gate /*
28277c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
28287c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
28297c478bd9Sstevel@tonic-gate * disappearing while we do this.
28307c478bd9Sstevel@tonic-gate */
28317c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
28327c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0)
28337c478bd9Sstevel@tonic-gate size = sizeof (gwindows32_t) -
28347c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
28357c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= size) {
28367c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
28377c478bd9Sstevel@tonic-gate prunlock(pnp);
28387c478bd9Sstevel@tonic-gate goto out;
28397c478bd9Sstevel@tonic-gate }
28407c478bd9Sstevel@tonic-gate prgetwindows32(ttolwp(t), gwp);
28417c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
28427c478bd9Sstevel@tonic-gate prunlock(pnp);
28437c478bd9Sstevel@tonic-gate
28447c478bd9Sstevel@tonic-gate error = pr_uioread(gwp, size, uiop);
28457c478bd9Sstevel@tonic-gate out:
28467c478bd9Sstevel@tonic-gate kmem_free(gwp, sizeof (gwindows32_t));
28477c478bd9Sstevel@tonic-gate return (error);
28487c478bd9Sstevel@tonic-gate }
28497c478bd9Sstevel@tonic-gate #endif /* __sparc */
28507c478bd9Sstevel@tonic-gate
28517c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
28527c478bd9Sstevel@tonic-gate
28537c478bd9Sstevel@tonic-gate /* ARGSUSED */
28547c478bd9Sstevel@tonic-gate static int
prread(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)28557c478bd9Sstevel@tonic-gate prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
28567c478bd9Sstevel@tonic-gate {
28577c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
28587c478bd9Sstevel@tonic-gate
28597c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
28607c478bd9Sstevel@tonic-gate
28617c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
28627c478bd9Sstevel@tonic-gate /*
28637c478bd9Sstevel@tonic-gate * What is read from the /proc files depends on the data
28647c478bd9Sstevel@tonic-gate * model of the caller. An LP64 process will see LP64
28657c478bd9Sstevel@tonic-gate * data. An ILP32 process will see ILP32 data.
28667c478bd9Sstevel@tonic-gate */
28677c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_LP64)
286819ee9cd1SAndy Fiddaman return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
28697c478bd9Sstevel@tonic-gate else
287019ee9cd1SAndy Fiddaman return (pr_read_function_32[pnp->pr_type](pnp, uiop, cr));
28717c478bd9Sstevel@tonic-gate #else
287219ee9cd1SAndy Fiddaman return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
28737c478bd9Sstevel@tonic-gate #endif
28747c478bd9Sstevel@tonic-gate }
28757c478bd9Sstevel@tonic-gate
2876ab618543SJohn Levon /* Note we intentionally don't handle partial writes/updates. */
2877ab618543SJohn Levon static int
pr_write_lwpname(prnode_t * pnp,uio_t * uiop)2878ab618543SJohn Levon pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
2879ab618543SJohn Levon {
2880ab618543SJohn Levon kthread_t *t = NULL;
2881ab618543SJohn Levon char *lwpname;
2882ab618543SJohn Levon int error;
2883ab618543SJohn Levon
2884ab618543SJohn Levon lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
2885ab618543SJohn Levon
2886ab618543SJohn Levon if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
2887ab618543SJohn Levon kmem_free(lwpname, THREAD_NAME_MAX);
2888ab618543SJohn Levon return (error);
2889ab618543SJohn Levon }
2890ab618543SJohn Levon
2891ab618543SJohn Levon /* Somebody tried to write too long a thread name... */
2892ab618543SJohn Levon if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
2893ab618543SJohn Levon kmem_free(lwpname, THREAD_NAME_MAX);
2894ab618543SJohn Levon return (EIO);
2895ab618543SJohn Levon }
2896ab618543SJohn Levon
2897ab618543SJohn Levon VERIFY3U(lwpname[THREAD_NAME_MAX - 1], ==, '\0');
2898ab618543SJohn Levon
2899ab618543SJohn Levon for (size_t i = 0; lwpname[i] != '\0'; i++) {
2900ab618543SJohn Levon if (!ISPRINT(lwpname[i])) {
2901ab618543SJohn Levon kmem_free(lwpname, THREAD_NAME_MAX);
2902ab618543SJohn Levon return (EINVAL);
2903ab618543SJohn Levon }
2904ab618543SJohn Levon }
2905ab618543SJohn Levon
2906ab618543SJohn Levon /* Equivalent of thread_setname(), but with the ZNO magic. */
2907ab618543SJohn Levon if ((error = prlock(pnp, ZNO)) != 0) {
2908ab618543SJohn Levon kmem_free(lwpname, THREAD_NAME_MAX);
2909ab618543SJohn Levon return (error);
2910ab618543SJohn Levon }
2911ab618543SJohn Levon
2912ab618543SJohn Levon t = pnp->pr_common->prc_thread;
2913ab618543SJohn Levon if (t->t_name == NULL) {
2914ab618543SJohn Levon t->t_name = lwpname;
2915ab618543SJohn Levon } else {
2916ab618543SJohn Levon (void) strlcpy(t->t_name, lwpname, THREAD_NAME_MAX);
2917ab618543SJohn Levon kmem_free(lwpname, THREAD_NAME_MAX);
2918ab618543SJohn Levon }
2919ab618543SJohn Levon
2920ab618543SJohn Levon prunlock(pnp);
2921ab618543SJohn Levon return (0);
2922ab618543SJohn Levon }
2923ab618543SJohn Levon
29247c478bd9Sstevel@tonic-gate /* ARGSUSED */
29257c478bd9Sstevel@tonic-gate static int
prwrite(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)29267c478bd9Sstevel@tonic-gate prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
29277c478bd9Sstevel@tonic-gate {
29287c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
29297c478bd9Sstevel@tonic-gate int old = 0;
29307c478bd9Sstevel@tonic-gate int error;
29317c478bd9Sstevel@tonic-gate ssize_t resid;
29327c478bd9Sstevel@tonic-gate
29337c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
29347c478bd9Sstevel@tonic-gate
29357c478bd9Sstevel@tonic-gate /*
29367c478bd9Sstevel@tonic-gate * Only a handful of /proc files are writable, enumerate them here.
29377c478bd9Sstevel@tonic-gate */
29387c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
29397c478bd9Sstevel@tonic-gate case PR_PIDDIR: /* directory write()s: visceral revulsion. */
29407c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_pidfile != NULL);
29417c478bd9Sstevel@tonic-gate /* use the underlying PR_PIDFILE to write the process */
29427c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
29437c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
29447c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
29457c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
29467c478bd9Sstevel@tonic-gate case PR_PIDFILE:
29477c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
29487c478bd9Sstevel@tonic-gate old = 1;
29497c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
29507c478bd9Sstevel@tonic-gate case PR_AS:
29517c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) == 0) {
29527c478bd9Sstevel@tonic-gate proc_t *p = pnp->pr_common->prc_proc;
29537c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
29547c478bd9Sstevel@tonic-gate
29557c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || as == &kas) {
29567c478bd9Sstevel@tonic-gate /*
29577c478bd9Sstevel@tonic-gate * /proc I/O cannot be done to a system process.
29587c478bd9Sstevel@tonic-gate */
29597c478bd9Sstevel@tonic-gate error = EIO;
29607c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
29617c478bd9Sstevel@tonic-gate } else if (curproc->p_model == DATAMODEL_ILP32 &&
29627c478bd9Sstevel@tonic-gate PROCESS_NOT_32BIT(p)) {
29637c478bd9Sstevel@tonic-gate error = EOVERFLOW;
29647c478bd9Sstevel@tonic-gate #endif
29657c478bd9Sstevel@tonic-gate } else {
29667c478bd9Sstevel@tonic-gate /*
29677c478bd9Sstevel@tonic-gate * See comments above (pr_read_pidfile)
29687c478bd9Sstevel@tonic-gate * about this locking dance.
29697c478bd9Sstevel@tonic-gate */
29707c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
29717c478bd9Sstevel@tonic-gate error = prusrio(p, UIO_WRITE, uiop, old);
29727c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
29737c478bd9Sstevel@tonic-gate }
29747c478bd9Sstevel@tonic-gate prunlock(pnp);
29757c478bd9Sstevel@tonic-gate }
29767c478bd9Sstevel@tonic-gate return (error);
29777c478bd9Sstevel@tonic-gate
29787c478bd9Sstevel@tonic-gate case PR_CTL:
29797c478bd9Sstevel@tonic-gate case PR_LWPCTL:
29807c478bd9Sstevel@tonic-gate resid = uiop->uio_resid;
29817c478bd9Sstevel@tonic-gate /*
29827c478bd9Sstevel@tonic-gate * Perform the action on the control file
29837c478bd9Sstevel@tonic-gate * by passing curthreads credentials
29847c478bd9Sstevel@tonic-gate * and not target process's credentials.
29857c478bd9Sstevel@tonic-gate */
29867c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
29877c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_ILP32)
29887c478bd9Sstevel@tonic-gate error = prwritectl32(vp, uiop, CRED());
29897c478bd9Sstevel@tonic-gate else
29907c478bd9Sstevel@tonic-gate error = prwritectl(vp, uiop, CRED());
29917c478bd9Sstevel@tonic-gate #else
29927c478bd9Sstevel@tonic-gate error = prwritectl(vp, uiop, CRED());
29937c478bd9Sstevel@tonic-gate #endif
29947c478bd9Sstevel@tonic-gate /*
29957c478bd9Sstevel@tonic-gate * This hack makes sure that the EINTR is passed
29967c478bd9Sstevel@tonic-gate * all the way back to the caller's write() call.
29977c478bd9Sstevel@tonic-gate */
29987c478bd9Sstevel@tonic-gate if (error == EINTR)
29997c478bd9Sstevel@tonic-gate uiop->uio_resid = resid;
30007c478bd9Sstevel@tonic-gate return (error);
30017c478bd9Sstevel@tonic-gate
3002ab618543SJohn Levon case PR_LWPNAME:
3003ab618543SJohn Levon return (pr_write_lwpname(pnp, uiop));
3004ab618543SJohn Levon
30057c478bd9Sstevel@tonic-gate default:
30067c478bd9Sstevel@tonic-gate return ((vp->v_type == VDIR)? EISDIR : EBADF);
30077c478bd9Sstevel@tonic-gate }
30087c478bd9Sstevel@tonic-gate /* NOTREACHED */
30097c478bd9Sstevel@tonic-gate }
30107c478bd9Sstevel@tonic-gate
30117c478bd9Sstevel@tonic-gate static int
prgetattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)3012da6c28aaSamw prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
3013da6c28aaSamw caller_context_t *ct)
30147c478bd9Sstevel@tonic-gate {
30157c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
30167c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
30177c478bd9Sstevel@tonic-gate prcommon_t *pcp;
30187c478bd9Sstevel@tonic-gate proc_t *p;
30197c478bd9Sstevel@tonic-gate struct as *as;
30207c478bd9Sstevel@tonic-gate int error;
30217c478bd9Sstevel@tonic-gate vnode_t *rvp;
30227c478bd9Sstevel@tonic-gate timestruc_t now;
30237c478bd9Sstevel@tonic-gate extern uint_t nproc;
30247c478bd9Sstevel@tonic-gate int ngroups;
3025eb9dbf0cSRoger A. Faulkner int nsig;
30267c478bd9Sstevel@tonic-gate
30277c478bd9Sstevel@tonic-gate /*
30287c478bd9Sstevel@tonic-gate * This ugly bit of code allows us to keep both versions of this
30297c478bd9Sstevel@tonic-gate * function from the same source.
30307c478bd9Sstevel@tonic-gate */
30317c478bd9Sstevel@tonic-gate #ifdef _LP64
30327c478bd9Sstevel@tonic-gate int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
30337c478bd9Sstevel@tonic-gate #define PR_OBJSIZE(obj32, obj64) \
30347c478bd9Sstevel@tonic-gate (iam32bit ? sizeof (obj32) : sizeof (obj64))
30357c478bd9Sstevel@tonic-gate #define PR_OBJSPAN(obj32, obj64) \
30367c478bd9Sstevel@tonic-gate (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
30377c478bd9Sstevel@tonic-gate #else
30387c478bd9Sstevel@tonic-gate #define PR_OBJSIZE(obj32, obj64) \
30397c478bd9Sstevel@tonic-gate (sizeof (obj64))
30407c478bd9Sstevel@tonic-gate #define PR_OBJSPAN(obj32, obj64) \
30417c478bd9Sstevel@tonic-gate (LSPAN(obj64))
30427c478bd9Sstevel@tonic-gate #endif
30437c478bd9Sstevel@tonic-gate
30447c478bd9Sstevel@tonic-gate /*
30457c478bd9Sstevel@tonic-gate * Return all the attributes. Should be refined
30467c478bd9Sstevel@tonic-gate * so that it returns only those asked for.
30477c478bd9Sstevel@tonic-gate * Most of this is complete fakery anyway.
30487c478bd9Sstevel@tonic-gate */
30497c478bd9Sstevel@tonic-gate
30507c478bd9Sstevel@tonic-gate /*
30517c478bd9Sstevel@tonic-gate * For files in the /proc/<pid>/object directory,
30527c478bd9Sstevel@tonic-gate * return the attributes of the underlying object.
30537c478bd9Sstevel@tonic-gate * For files in the /proc/<pid>/fd directory,
30547c478bd9Sstevel@tonic-gate * return the attributes of the underlying file, but
30557c478bd9Sstevel@tonic-gate * make it look inaccessible if it is not a regular file.
30567c478bd9Sstevel@tonic-gate * Make directories look like symlinks.
30577c478bd9Sstevel@tonic-gate */
30587c478bd9Sstevel@tonic-gate switch (type) {
30597c478bd9Sstevel@tonic-gate case PR_CURDIR:
30607c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
30617c478bd9Sstevel@tonic-gate if (!(flags & ATTR_REAL))
30627c478bd9Sstevel@tonic-gate break;
30637c478bd9Sstevel@tonic-gate /* restrict full knowledge of the attributes to owner or root */
3064da6c28aaSamw if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
30657c478bd9Sstevel@tonic-gate return (error);
30667c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
30677c478bd9Sstevel@tonic-gate case PR_OBJECT:
30687c478bd9Sstevel@tonic-gate case PR_FD:
30697c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
3070da6c28aaSamw error = VOP_GETATTR(rvp, vap, flags, cr, ct);
30717c478bd9Sstevel@tonic-gate if (error)
30727c478bd9Sstevel@tonic-gate return (error);
30737c478bd9Sstevel@tonic-gate if (type == PR_FD) {
30747c478bd9Sstevel@tonic-gate if (rvp->v_type != VREG && rvp->v_type != VDIR)
30757c478bd9Sstevel@tonic-gate vap->va_mode = 0;
30767c478bd9Sstevel@tonic-gate else
30777c478bd9Sstevel@tonic-gate vap->va_mode &= pnp->pr_mode;
30787c478bd9Sstevel@tonic-gate }
30797c478bd9Sstevel@tonic-gate if (type == PR_OBJECT)
30807c478bd9Sstevel@tonic-gate vap->va_mode &= 07555;
30817c478bd9Sstevel@tonic-gate if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
30827c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
30837c478bd9Sstevel@tonic-gate vap->va_size = 0;
30847c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
30857c478bd9Sstevel@tonic-gate }
30867c478bd9Sstevel@tonic-gate return (0);
30877c478bd9Sstevel@tonic-gate default:
30887c478bd9Sstevel@tonic-gate break;
30897c478bd9Sstevel@tonic-gate }
30907c478bd9Sstevel@tonic-gate
30917c478bd9Sstevel@tonic-gate bzero(vap, sizeof (*vap));
30927c478bd9Sstevel@tonic-gate /*
30937c478bd9Sstevel@tonic-gate * Large Files: Internally proc now uses VPROC to indicate
30947c478bd9Sstevel@tonic-gate * a proc file. Since we have been returning VREG through
30957c478bd9Sstevel@tonic-gate * VOP_GETATTR() until now, we continue to do this so as
30967c478bd9Sstevel@tonic-gate * not to break apps depending on this return value.
30977c478bd9Sstevel@tonic-gate */
30987c478bd9Sstevel@tonic-gate vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
30997c478bd9Sstevel@tonic-gate vap->va_mode = pnp->pr_mode;
31007c478bd9Sstevel@tonic-gate vap->va_fsid = vp->v_vfsp->vfs_dev;
31017c478bd9Sstevel@tonic-gate vap->va_blksize = DEV_BSIZE;
31027c478bd9Sstevel@tonic-gate vap->va_rdev = 0;
31037c478bd9Sstevel@tonic-gate vap->va_seq = 0;
31047c478bd9Sstevel@tonic-gate
31057c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR) {
31067c478bd9Sstevel@tonic-gate vap->va_uid = 0;
31077c478bd9Sstevel@tonic-gate vap->va_gid = 0;
31087c478bd9Sstevel@tonic-gate vap->va_nlink = nproc + 2;
31097c478bd9Sstevel@tonic-gate vap->va_nodeid = (ino64_t)PRROOTINO;
31107c478bd9Sstevel@tonic-gate gethrestime(&now);
31117c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_mtime = vap->va_ctime = now;
31127c478bd9Sstevel@tonic-gate vap->va_size = (v.v_proc + 2) * PRSDSIZE;
31137c478bd9Sstevel@tonic-gate vap->va_nblocks = btod(vap->va_size);
31147c478bd9Sstevel@tonic-gate return (0);
31157c478bd9Sstevel@tonic-gate }
31167c478bd9Sstevel@tonic-gate
31177c478bd9Sstevel@tonic-gate /*
31187c478bd9Sstevel@tonic-gate * /proc/<pid>/self is a symbolic link, and has no prcommon member
31197c478bd9Sstevel@tonic-gate */
31207c478bd9Sstevel@tonic-gate if (type == PR_SELF) {
31217c478bd9Sstevel@tonic-gate vap->va_uid = crgetruid(CRED());
31227c478bd9Sstevel@tonic-gate vap->va_gid = crgetrgid(CRED());
31237c478bd9Sstevel@tonic-gate vap->va_nodeid = (ino64_t)PR_SELF;
31247c478bd9Sstevel@tonic-gate gethrestime(&now);
31257c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_mtime = vap->va_ctime = now;
31267c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
31277c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
31287c478bd9Sstevel@tonic-gate vap->va_size = 0;
31297c478bd9Sstevel@tonic-gate return (0);
31307c478bd9Sstevel@tonic-gate }
31317c478bd9Sstevel@tonic-gate
3132da29c6a3SDan McDonald /* A subset of prlock(pnp...) */
31337c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
31347c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
31357c478bd9Sstevel@tonic-gate if (p == NULL)
31367c478bd9Sstevel@tonic-gate return (ENOENT);
31377c478bd9Sstevel@tonic-gate pcp = pnp->pr_common;
31387c478bd9Sstevel@tonic-gate
3139da29c6a3SDan McDonald /*
3140da29c6a3SDan McDonald * Because we're performing a subset of prlock() inline here, we must
3141da29c6a3SDan McDonald * follow prlock's semantics when encountering a zombie process
3142da29c6a3SDan McDonald * (PRC_DESTROY flag is set) or an exiting process (SEXITING flag is
3143da29c6a3SDan McDonald * set). Those semantics indicate acting as if the process is no
3144da29c6a3SDan McDonald * longer there (return ENOENT).
3145da29c6a3SDan McDonald *
3146da29c6a3SDan McDonald * If we chose to proceed here regardless, we may encounter issues
3147da29c6a3SDan McDonald * when we drop the p_lock (see PR_OBJECTDIR, PR_PATHDIR, PR_*MAP,
3148da29c6a3SDan McDonald * PR_LDT, and PR_*PAGEDATA below). A process-cleanup which was
3149da29c6a3SDan McDonald * blocked on p_lock may ignore the P_PR_LOCK flag we set above, since
3150da29c6a3SDan McDonald * it set one of PRC_DESTROY or SEXITING. If the process then gets
3151da29c6a3SDan McDonald * destroyed our "p" will be useless, as will its p_lock.
3152da29c6a3SDan McDonald *
3153da29c6a3SDan McDonald * It may be desirable to move this check to only places further down
3154da29c6a3SDan McDonald * prior to actual droppages of p->p_lock, but for now, we're playing
3155da29c6a3SDan McDonald * it safe and checking here immediately, like prlock() does..
3156da29c6a3SDan McDonald */
3157da29c6a3SDan McDonald if (((pcp->prc_flags & PRC_DESTROY) || (p->p_flag & SEXITING))) {
3158da29c6a3SDan McDonald prunlock(pnp);
3159da29c6a3SDan McDonald return (ENOENT);
3160da29c6a3SDan McDonald }
3161da29c6a3SDan McDonald
31627c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
31637c478bd9Sstevel@tonic-gate vap->va_uid = crgetruid(p->p_cred);
31647c478bd9Sstevel@tonic-gate vap->va_gid = crgetrgid(p->p_cred);
31657c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
31667c478bd9Sstevel@tonic-gate
31677c478bd9Sstevel@tonic-gate vap->va_nlink = 1;
31687c478bd9Sstevel@tonic-gate vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
31697c478bd9Sstevel@tonic-gate pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
31707c478bd9Sstevel@tonic-gate if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
31717c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
31727c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec =
31737c478bd9Sstevel@tonic-gate p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
31747c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
31757c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = 0;
31767c478bd9Sstevel@tonic-gate } else {
31777c478bd9Sstevel@tonic-gate user_t *up = PTOU(p);
31787c478bd9Sstevel@tonic-gate vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
31797c478bd9Sstevel@tonic-gate vap->va_ctime.tv_sec = up->u_start.tv_sec;
31807c478bd9Sstevel@tonic-gate vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
31817c478bd9Sstevel@tonic-gate vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
31827c478bd9Sstevel@tonic-gate }
31837c478bd9Sstevel@tonic-gate
31847c478bd9Sstevel@tonic-gate switch (type) {
31857c478bd9Sstevel@tonic-gate case PR_PIDDIR:
31867c478bd9Sstevel@tonic-gate /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
31877c478bd9Sstevel@tonic-gate vap->va_nlink = 5;
31887c478bd9Sstevel@tonic-gate vap->va_size = sizeof (piddir);
31897c478bd9Sstevel@tonic-gate break;
31907c478bd9Sstevel@tonic-gate case PR_OBJECTDIR:
31917c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
31927c478bd9Sstevel@tonic-gate vap->va_size = 2 * PRSDSIZE;
31937c478bd9Sstevel@tonic-gate else {
31947c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3195dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
31967c478bd9Sstevel@tonic-gate if (as->a_updatedir)
31977c478bd9Sstevel@tonic-gate rebuild_objdir(as);
31987c478bd9Sstevel@tonic-gate vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
3199dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
32007c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
32017c478bd9Sstevel@tonic-gate }
32027c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32037c478bd9Sstevel@tonic-gate break;
32047c478bd9Sstevel@tonic-gate case PR_PATHDIR:
32057c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
32067c478bd9Sstevel@tonic-gate vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
32077c478bd9Sstevel@tonic-gate else {
32087c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3209dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
32107c478bd9Sstevel@tonic-gate if (as->a_updatedir)
32117c478bd9Sstevel@tonic-gate rebuild_objdir(as);
32127c478bd9Sstevel@tonic-gate vap->va_size = (as->a_sizedir + 4 +
32137c478bd9Sstevel@tonic-gate P_FINFO(p)->fi_nfiles) * PRSDSIZE;
3214dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
32157c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
32167c478bd9Sstevel@tonic-gate }
32177c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32187c478bd9Sstevel@tonic-gate break;
32197c478bd9Sstevel@tonic-gate case PR_PATH:
32207c478bd9Sstevel@tonic-gate case PR_CURDIR:
32217c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
32227c478bd9Sstevel@tonic-gate case PR_CT:
32237c478bd9Sstevel@tonic-gate vap->va_type = VLNK;
32247c478bd9Sstevel@tonic-gate vap->va_size = 0;
32257c478bd9Sstevel@tonic-gate break;
32267c478bd9Sstevel@tonic-gate case PR_FDDIR:
3227a02120c4SAndy Fiddaman case PR_FDINFODIR:
32287c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32297c478bd9Sstevel@tonic-gate vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
32307c478bd9Sstevel@tonic-gate break;
3231a02120c4SAndy Fiddaman case PR_FDINFO: {
3232a02120c4SAndy Fiddaman file_t *fp;
3233a02120c4SAndy Fiddaman int fd = pnp->pr_index;
3234a02120c4SAndy Fiddaman
3235a02120c4SAndy Fiddaman fp = pr_getf(p, fd, NULL);
3236a02120c4SAndy Fiddaman if (fp == NULL) {
3237a02120c4SAndy Fiddaman prunlock(pnp);
3238a02120c4SAndy Fiddaman return (ENOENT);
3239a02120c4SAndy Fiddaman }
3240a02120c4SAndy Fiddaman prunlock(pnp);
3241da29c6a3SDan McDonald vap->va_size = prgetfdinfosize(p, fp->f_vnode, cr);
3242a02120c4SAndy Fiddaman vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
324337e2cd25SPatrick Mooney pr_releasef(fp);
3244a02120c4SAndy Fiddaman return (0);
3245a02120c4SAndy Fiddaman }
32467c478bd9Sstevel@tonic-gate case PR_LWPDIR:
32477c478bd9Sstevel@tonic-gate /*
32487c478bd9Sstevel@tonic-gate * va_nlink: count each lwp as a directory link.
32497c478bd9Sstevel@tonic-gate * va_size: size of p_lwpdir + 2
32507c478bd9Sstevel@tonic-gate */
32517c478bd9Sstevel@tonic-gate vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
32527c478bd9Sstevel@tonic-gate vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
32537c478bd9Sstevel@tonic-gate break;
32547c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
32557c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32567c478bd9Sstevel@tonic-gate vap->va_size = sizeof (lwpiddir);
32577c478bd9Sstevel@tonic-gate break;
32587c478bd9Sstevel@tonic-gate case PR_CTDIR:
32597c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32607c478bd9Sstevel@tonic-gate vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
32617c478bd9Sstevel@tonic-gate break;
32627c478bd9Sstevel@tonic-gate case PR_TMPLDIR:
32637c478bd9Sstevel@tonic-gate vap->va_nlink = 2;
32647c478bd9Sstevel@tonic-gate vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
32657c478bd9Sstevel@tonic-gate break;
32667c478bd9Sstevel@tonic-gate case PR_AS:
32677c478bd9Sstevel@tonic-gate case PR_PIDFILE:
32687c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
32697c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
32707c478bd9Sstevel@tonic-gate vap->va_size = 0;
327140688216SSudheer A else
327240688216SSudheer A vap->va_size = as->a_resvsize;
32737c478bd9Sstevel@tonic-gate break;
32747c478bd9Sstevel@tonic-gate case PR_STATUS:
32757c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
32767c478bd9Sstevel@tonic-gate break;
32777c478bd9Sstevel@tonic-gate case PR_LSTATUS:
32787c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
32797c478bd9Sstevel@tonic-gate p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
32807c478bd9Sstevel@tonic-gate break;
32817c478bd9Sstevel@tonic-gate case PR_PSINFO:
32827c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
32837c478bd9Sstevel@tonic-gate break;
32847c478bd9Sstevel@tonic-gate case PR_LPSINFO:
32857c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
32867c478bd9Sstevel@tonic-gate (p->p_lwpcnt + p->p_zombcnt) *
32877c478bd9Sstevel@tonic-gate PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
32887c478bd9Sstevel@tonic-gate break;
32897c478bd9Sstevel@tonic-gate case PR_MAP:
32907c478bd9Sstevel@tonic-gate case PR_RMAP:
32917c478bd9Sstevel@tonic-gate case PR_XMAP:
32927c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
32937c478bd9Sstevel@tonic-gate vap->va_size = 0;
32947c478bd9Sstevel@tonic-gate else {
32957c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3296dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
32977c478bd9Sstevel@tonic-gate if (type == PR_MAP)
32987c478bd9Sstevel@tonic-gate vap->va_mtime = as->a_updatetime;
32997c478bd9Sstevel@tonic-gate if (type == PR_XMAP)
33007c478bd9Sstevel@tonic-gate vap->va_size = prnsegs(as, 0) *
33017c478bd9Sstevel@tonic-gate PR_OBJSIZE(prxmap32_t, prxmap_t);
33027c478bd9Sstevel@tonic-gate else
33037c478bd9Sstevel@tonic-gate vap->va_size = prnsegs(as, type == PR_RMAP) *
33047c478bd9Sstevel@tonic-gate PR_OBJSIZE(prmap32_t, prmap_t);
3305dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
33067c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
33077c478bd9Sstevel@tonic-gate }
33087c478bd9Sstevel@tonic-gate break;
33097c478bd9Sstevel@tonic-gate case PR_CRED:
33107c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock);
33117c478bd9Sstevel@tonic-gate vap->va_size = sizeof (prcred_t);
33127c478bd9Sstevel@tonic-gate ngroups = crgetngroups(p->p_cred);
33137c478bd9Sstevel@tonic-gate if (ngroups > 1)
33147c478bd9Sstevel@tonic-gate vap->va_size += (ngroups - 1) * sizeof (gid_t);
33157c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock);
33167c478bd9Sstevel@tonic-gate break;
33177c478bd9Sstevel@tonic-gate case PR_PRIV:
33187c478bd9Sstevel@tonic-gate vap->va_size = prgetprivsize();
33197c478bd9Sstevel@tonic-gate break;
3320d2a70789SRichard Lowe case PR_SECFLAGS:
3321d2a70789SRichard Lowe vap->va_size = sizeof (prsecflags_t);
3322d2a70789SRichard Lowe break;
33237c478bd9Sstevel@tonic-gate case PR_SIGACT:
3324eb9dbf0cSRoger A. Faulkner nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3325eb9dbf0cSRoger A. Faulkner vap->va_size = (nsig-1) *
33267c478bd9Sstevel@tonic-gate PR_OBJSIZE(struct sigaction32, struct sigaction);
33277c478bd9Sstevel@tonic-gate break;
33287c478bd9Sstevel@tonic-gate case PR_AUXV:
33297c478bd9Sstevel@tonic-gate vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
33307c478bd9Sstevel@tonic-gate break;
33317c478bd9Sstevel@tonic-gate #if defined(__x86)
33327c478bd9Sstevel@tonic-gate case PR_LDT:
33336e092be7SVamsi Nagineni mutex_exit(&p->p_lock);
33347c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock);
33357c478bd9Sstevel@tonic-gate vap->va_size = prnldt(p) * sizeof (struct ssd);
33367c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock);
33376e092be7SVamsi Nagineni mutex_enter(&p->p_lock);
33387c478bd9Sstevel@tonic-gate break;
33397c478bd9Sstevel@tonic-gate #endif
33407c478bd9Sstevel@tonic-gate case PR_USAGE:
33417c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
33427c478bd9Sstevel@tonic-gate break;
33437c478bd9Sstevel@tonic-gate case PR_LUSAGE:
33447c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
33457c478bd9Sstevel@tonic-gate (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
33467c478bd9Sstevel@tonic-gate break;
33477c478bd9Sstevel@tonic-gate case PR_PAGEDATA:
33487c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
33497c478bd9Sstevel@tonic-gate vap->va_size = 0;
33507c478bd9Sstevel@tonic-gate else {
33517c478bd9Sstevel@tonic-gate /*
33527c478bd9Sstevel@tonic-gate * We can drop p->p_lock before grabbing the
33537c478bd9Sstevel@tonic-gate * address space lock because p->p_as will not
33547c478bd9Sstevel@tonic-gate * change while the process is marked P_PR_LOCK.
33557c478bd9Sstevel@tonic-gate */
33567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3357dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
33587c478bd9Sstevel@tonic-gate #ifdef _LP64
33597c478bd9Sstevel@tonic-gate vap->va_size = iam32bit?
33607c478bd9Sstevel@tonic-gate prpdsize32(as) : prpdsize(as);
33617c478bd9Sstevel@tonic-gate #else
33627c478bd9Sstevel@tonic-gate vap->va_size = prpdsize(as);
33637c478bd9Sstevel@tonic-gate #endif
3364dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
33657c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
33667c478bd9Sstevel@tonic-gate }
33677c478bd9Sstevel@tonic-gate break;
33687c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
33697c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
33707c478bd9Sstevel@tonic-gate vap->va_size = 0;
33717c478bd9Sstevel@tonic-gate else {
33727c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3373dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
33747c478bd9Sstevel@tonic-gate #ifdef _LP64
33757c478bd9Sstevel@tonic-gate vap->va_size = iam32bit?
33767c478bd9Sstevel@tonic-gate oprpdsize32(as) : oprpdsize(as);
33777c478bd9Sstevel@tonic-gate #else
33787c478bd9Sstevel@tonic-gate vap->va_size = oprpdsize(as);
33797c478bd9Sstevel@tonic-gate #endif
3380dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
33817c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
33827c478bd9Sstevel@tonic-gate }
33837c478bd9Sstevel@tonic-gate break;
33847c478bd9Sstevel@tonic-gate case PR_WATCH:
33857c478bd9Sstevel@tonic-gate vap->va_size = avl_numnodes(&p->p_warea) *
33867c478bd9Sstevel@tonic-gate PR_OBJSIZE(prwatch32_t, prwatch_t);
33877c478bd9Sstevel@tonic-gate break;
33887c478bd9Sstevel@tonic-gate case PR_LWPSTATUS:
33897c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
33907c478bd9Sstevel@tonic-gate break;
33917c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
33927c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
33937c478bd9Sstevel@tonic-gate break;
33947c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
33957c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
33967c478bd9Sstevel@tonic-gate break;
33977c478bd9Sstevel@tonic-gate case PR_XREGS:
33987c478bd9Sstevel@tonic-gate if (prhasx(p))
33997c478bd9Sstevel@tonic-gate vap->va_size = prgetprxregsize(p);
34007c478bd9Sstevel@tonic-gate else
34017c478bd9Sstevel@tonic-gate vap->va_size = 0;
34027c478bd9Sstevel@tonic-gate break;
3403f971a346SBryan Cantrill case PR_SPYMASTER:
3404614f1d63SJerry Jelinek if (pnp->pr_common->prc_thread != NULL &&
3405614f1d63SJerry Jelinek pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3406f971a346SBryan Cantrill vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3407f971a346SBryan Cantrill } else {
3408f971a346SBryan Cantrill vap->va_size = 0;
3409f971a346SBryan Cantrill }
3410f971a346SBryan Cantrill break;
34117c478bd9Sstevel@tonic-gate #if defined(__sparc)
34127c478bd9Sstevel@tonic-gate case PR_GWINDOWS:
34137c478bd9Sstevel@tonic-gate {
34147c478bd9Sstevel@tonic-gate kthread_t *t;
34157c478bd9Sstevel@tonic-gate int n;
34167c478bd9Sstevel@tonic-gate
34177c478bd9Sstevel@tonic-gate /*
34187c478bd9Sstevel@tonic-gate * If there is no lwp then just make the size zero.
34197c478bd9Sstevel@tonic-gate * This can happen if the lwp exits between the VOP_LOOKUP()
34207c478bd9Sstevel@tonic-gate * of the /proc/<pid>/lwp/<lwpid>/gwindows file and the
34217c478bd9Sstevel@tonic-gate * VOP_GETATTR() of the resulting vnode.
34227c478bd9Sstevel@tonic-gate */
34237c478bd9Sstevel@tonic-gate if ((t = pcp->prc_thread) == NULL) {
34247c478bd9Sstevel@tonic-gate vap->va_size = 0;
34257c478bd9Sstevel@tonic-gate break;
34267c478bd9Sstevel@tonic-gate }
34277c478bd9Sstevel@tonic-gate /*
34287c478bd9Sstevel@tonic-gate * Drop p->p_lock while touching the stack.
34297c478bd9Sstevel@tonic-gate * The P_PR_LOCK flag prevents the lwp from
34307c478bd9Sstevel@tonic-gate * disappearing while we do this.
34317c478bd9Sstevel@tonic-gate */
34327c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
34337c478bd9Sstevel@tonic-gate if ((n = prnwindows(ttolwp(t))) == 0)
34347c478bd9Sstevel@tonic-gate vap->va_size = 0;
34357c478bd9Sstevel@tonic-gate else
34367c478bd9Sstevel@tonic-gate vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
34377c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - n) *
34387c478bd9Sstevel@tonic-gate PR_OBJSIZE(struct rwindow32, struct rwindow);
34397c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
34407c478bd9Sstevel@tonic-gate break;
34417c478bd9Sstevel@tonic-gate }
34427c478bd9Sstevel@tonic-gate case PR_ASRS:
34437c478bd9Sstevel@tonic-gate #ifdef _LP64
34447c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_LP64)
34457c478bd9Sstevel@tonic-gate vap->va_size = sizeof (asrset_t);
34467c478bd9Sstevel@tonic-gate else
34477c478bd9Sstevel@tonic-gate #endif
34487c478bd9Sstevel@tonic-gate vap->va_size = 0;
34497c478bd9Sstevel@tonic-gate break;
34507c478bd9Sstevel@tonic-gate #endif
34517c478bd9Sstevel@tonic-gate case PR_CTL:
34527c478bd9Sstevel@tonic-gate case PR_LWPCTL:
34537c478bd9Sstevel@tonic-gate default:
34547c478bd9Sstevel@tonic-gate vap->va_size = 0;
34557c478bd9Sstevel@tonic-gate break;
34567c478bd9Sstevel@tonic-gate }
34577c478bd9Sstevel@tonic-gate
34587c478bd9Sstevel@tonic-gate prunlock(pnp);
34597c478bd9Sstevel@tonic-gate vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
34607c478bd9Sstevel@tonic-gate return (0);
34617c478bd9Sstevel@tonic-gate }
34627c478bd9Sstevel@tonic-gate
34637c478bd9Sstevel@tonic-gate static int
praccess(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)3464da6c28aaSamw praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
34657c478bd9Sstevel@tonic-gate {
34667c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
34677c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
34687c478bd9Sstevel@tonic-gate int vmode;
34697c478bd9Sstevel@tonic-gate vtype_t vtype;
34707c478bd9Sstevel@tonic-gate proc_t *p;
34717c478bd9Sstevel@tonic-gate int error = 0;
34727c478bd9Sstevel@tonic-gate vnode_t *rvp;
34737c478bd9Sstevel@tonic-gate vnode_t *xvp;
34747c478bd9Sstevel@tonic-gate
34757c478bd9Sstevel@tonic-gate if ((mode & VWRITE) && vn_is_readonly(vp))
34767c478bd9Sstevel@tonic-gate return (EROFS);
34777c478bd9Sstevel@tonic-gate
34787c478bd9Sstevel@tonic-gate switch (type) {
34797c478bd9Sstevel@tonic-gate case PR_PROCDIR:
34807c478bd9Sstevel@tonic-gate break;
34817c478bd9Sstevel@tonic-gate
34827c478bd9Sstevel@tonic-gate case PR_OBJECT:
34837c478bd9Sstevel@tonic-gate case PR_FD:
34847c478bd9Sstevel@tonic-gate /*
34857c478bd9Sstevel@tonic-gate * Disallow write access to the underlying objects.
34867c478bd9Sstevel@tonic-gate * Disallow access to underlying non-regular-file fds.
34877c478bd9Sstevel@tonic-gate * Disallow access to fds with other than existing open modes.
34887c478bd9Sstevel@tonic-gate */
34897c478bd9Sstevel@tonic-gate rvp = pnp->pr_realvp;
34907c478bd9Sstevel@tonic-gate vtype = rvp->v_type;
34917c478bd9Sstevel@tonic-gate vmode = pnp->pr_mode;
34927c478bd9Sstevel@tonic-gate if ((type == PR_OBJECT && (mode & VWRITE)) ||
34937c478bd9Sstevel@tonic-gate (type == PR_FD && vtype != VREG && vtype != VDIR) ||
34947c478bd9Sstevel@tonic-gate (type == PR_FD && (vmode & mode) != mode &&
34957c478bd9Sstevel@tonic-gate secpolicy_proc_access(cr) != 0))
34967c478bd9Sstevel@tonic-gate return (EACCES);
3497da6c28aaSamw return (VOP_ACCESS(rvp, mode, flags, cr, ct));
34987c478bd9Sstevel@tonic-gate
34997c478bd9Sstevel@tonic-gate case PR_PSINFO: /* these files can be read by anyone */
35007c478bd9Sstevel@tonic-gate case PR_LPSINFO:
35017c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
35027c478bd9Sstevel@tonic-gate case PR_LWPDIR:
35037c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
35047c478bd9Sstevel@tonic-gate case PR_USAGE:
35057c478bd9Sstevel@tonic-gate case PR_LUSAGE:
35067c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
35077c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
35087c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
35097c478bd9Sstevel@tonic-gate if (p == NULL)
35107c478bd9Sstevel@tonic-gate return (ENOENT);
35117c478bd9Sstevel@tonic-gate prunlock(pnp);
35127c478bd9Sstevel@tonic-gate break;
35137c478bd9Sstevel@tonic-gate
35147c478bd9Sstevel@tonic-gate default:
35157c478bd9Sstevel@tonic-gate /*
35167c478bd9Sstevel@tonic-gate * Except for the world-readable files above,
35177c478bd9Sstevel@tonic-gate * only /proc/pid exists if the process is a zombie.
35187c478bd9Sstevel@tonic-gate */
35197c478bd9Sstevel@tonic-gate if ((error = prlock(pnp,
35207c478bd9Sstevel@tonic-gate (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
35217c478bd9Sstevel@tonic-gate return (error);
35227c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
35237c478bd9Sstevel@tonic-gate if (p != curproc)
35247c478bd9Sstevel@tonic-gate error = priv_proc_cred_perm(cr, p, NULL, mode);
35257c478bd9Sstevel@tonic-gate
35267c478bd9Sstevel@tonic-gate if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3527ddf7fe95Scasper p->p_as == &kas || (xvp = p->p_exec) == NULL) {
35287c478bd9Sstevel@tonic-gate prunlock(pnp);
35297c478bd9Sstevel@tonic-gate } else {
35307c478bd9Sstevel@tonic-gate /*
35317c478bd9Sstevel@tonic-gate * Determine if the process's executable is readable.
3532ddf7fe95Scasper * We have to drop p->p_lock before the secpolicy
3533ddf7fe95Scasper * and VOP operation.
35347c478bd9Sstevel@tonic-gate */
35357c478bd9Sstevel@tonic-gate VN_HOLD(xvp);
35367c478bd9Sstevel@tonic-gate prunlock(pnp);
3537ddf7fe95Scasper if (secpolicy_proc_access(cr) != 0)
3538da6c28aaSamw error = VOP_ACCESS(xvp, VREAD, 0, cr, ct);
35397c478bd9Sstevel@tonic-gate VN_RELE(xvp);
35407c478bd9Sstevel@tonic-gate }
35417c478bd9Sstevel@tonic-gate if (error)
35427c478bd9Sstevel@tonic-gate return (error);
35437c478bd9Sstevel@tonic-gate break;
35447c478bd9Sstevel@tonic-gate }
35457c478bd9Sstevel@tonic-gate
35467c478bd9Sstevel@tonic-gate if (type == PR_CURDIR || type == PR_ROOTDIR) {
35477c478bd9Sstevel@tonic-gate /*
35487c478bd9Sstevel@tonic-gate * Final access check on the underlying directory vnode.
35497c478bd9Sstevel@tonic-gate */
3550da6c28aaSamw return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
35517c478bd9Sstevel@tonic-gate }
35527c478bd9Sstevel@tonic-gate
35537c478bd9Sstevel@tonic-gate /*
35547c478bd9Sstevel@tonic-gate * Visceral revulsion: For compatibility with old /proc,
35557c478bd9Sstevel@tonic-gate * allow the /proc/<pid> directory to be opened for writing.
35567c478bd9Sstevel@tonic-gate */
35577c478bd9Sstevel@tonic-gate vmode = pnp->pr_mode;
35587c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR)
35597c478bd9Sstevel@tonic-gate vmode |= VWRITE;
35607c478bd9Sstevel@tonic-gate if ((vmode & mode) != mode)
35617c478bd9Sstevel@tonic-gate error = secpolicy_proc_access(cr);
35627c478bd9Sstevel@tonic-gate return (error);
35637c478bd9Sstevel@tonic-gate }
35647c478bd9Sstevel@tonic-gate
35657c478bd9Sstevel@tonic-gate /*
35667c478bd9Sstevel@tonic-gate * Array of lookup functions, indexed by /proc file type.
35677c478bd9Sstevel@tonic-gate */
35687c478bd9Sstevel@tonic-gate static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
35697c478bd9Sstevel@tonic-gate *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3570a02120c4SAndy Fiddaman *pr_lookup_fddir(), *pr_lookup_fdinfodir(), *pr_lookup_pathdir(),
3571a02120c4SAndy Fiddaman *pr_lookup_tmpldir(), *pr_lookup_ctdir();
35727c478bd9Sstevel@tonic-gate
35737c478bd9Sstevel@tonic-gate static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
35747c478bd9Sstevel@tonic-gate pr_lookup_procdir, /* /proc */
35757c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/self */
35767c478bd9Sstevel@tonic-gate pr_lookup_piddir, /* /proc/<pid> */
35777c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/as */
35787c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/ctl */
35797c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/status */
35807c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lstatus */
35817c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/psinfo */
35827c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
35837c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/map */
35847c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/rmap */
35857c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/xmap */
35867c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/cred */
35877c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/sigact */
35887c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/auxv */
35897c478bd9Sstevel@tonic-gate #if defined(__x86)
35907c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/ldt */
35917c478bd9Sstevel@tonic-gate #endif
35927c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/usage */
35937c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lusage */
35947c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/pagedata */
35957c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/watch */
35967c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/cwd */
35977c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/root */
35987c478bd9Sstevel@tonic-gate pr_lookup_fddir, /* /proc/<pid>/fd */
35997c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3600a02120c4SAndy Fiddaman pr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */
3601a02120c4SAndy Fiddaman pr_lookup_notdir, /* /proc/<pid>/fdinfo/nn */
36027c478bd9Sstevel@tonic-gate pr_lookup_objectdir, /* /proc/<pid>/object */
36037c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/object/xxx */
36047c478bd9Sstevel@tonic-gate pr_lookup_lwpdir, /* /proc/<pid>/lwp */
36057c478bd9Sstevel@tonic-gate pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
36067c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3607ab618543SJohn Levon pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
36087c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
36097c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
36107c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
36117c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
36127c478bd9Sstevel@tonic-gate pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
36137c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3614f971a346SBryan Cantrill pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
36157c478bd9Sstevel@tonic-gate #if defined(__sparc)
36167c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
36177c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
36187c478bd9Sstevel@tonic-gate #endif
36197c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/priv */
36207c478bd9Sstevel@tonic-gate pr_lookup_pathdir, /* /proc/<pid>/path */
36217c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/path/xxx */
36227c478bd9Sstevel@tonic-gate pr_lookup_ctdir, /* /proc/<pid>/contracts */
36237c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* /proc/<pid>/contracts/<ctid> */
3624d2a70789SRichard Lowe pr_lookup_notdir, /* /proc/<pid>/secflags */
36257c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old process file */
36267c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old lwp file */
36277c478bd9Sstevel@tonic-gate pr_lookup_notdir, /* old pagedata file */
36287c478bd9Sstevel@tonic-gate };
36297c478bd9Sstevel@tonic-gate
36307c478bd9Sstevel@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)36317c478bd9Sstevel@tonic-gate prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3632da6c28aaSamw int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3633da6c28aaSamw int *direntflags, pathname_t *realpnp)
36347c478bd9Sstevel@tonic-gate {
36357c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(dp);
36367c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
36377c478bd9Sstevel@tonic-gate int error;
36387c478bd9Sstevel@tonic-gate
36397c478bd9Sstevel@tonic-gate ASSERT(dp->v_type == VDIR);
36407c478bd9Sstevel@tonic-gate ASSERT(type < PR_NFILES);
36417c478bd9Sstevel@tonic-gate
36427c478bd9Sstevel@tonic-gate if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
36437c478bd9Sstevel@tonic-gate VN_HOLD(pnp->pr_parent);
36447c478bd9Sstevel@tonic-gate *vpp = pnp->pr_parent;
36457c478bd9Sstevel@tonic-gate return (0);
36467c478bd9Sstevel@tonic-gate }
36477c478bd9Sstevel@tonic-gate
36487c478bd9Sstevel@tonic-gate if (*comp == '\0' ||
36497c478bd9Sstevel@tonic-gate strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
36507c478bd9Sstevel@tonic-gate VN_HOLD(dp);
36517c478bd9Sstevel@tonic-gate *vpp = dp;
36527c478bd9Sstevel@tonic-gate return (0);
36537c478bd9Sstevel@tonic-gate }
36547c478bd9Sstevel@tonic-gate
36557c478bd9Sstevel@tonic-gate switch (type) {
36567c478bd9Sstevel@tonic-gate case PR_CURDIR:
36577c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
36587c478bd9Sstevel@tonic-gate /* restrict lookup permission to owner or root */
3659da6c28aaSamw if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
36607c478bd9Sstevel@tonic-gate return (error);
36617c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
36627c478bd9Sstevel@tonic-gate case PR_FD:
3663e2fc3408SPatrick Mooney /*
3664e2fc3408SPatrick Mooney * Performing a VOP_LOOKUP on the underlying vnode and emitting
3665e2fc3408SPatrick Mooney * the resulting vnode, without encapsulation, as our own is a
3666e2fc3408SPatrick Mooney * very special case when it comes to the assumptions built
3667e2fc3408SPatrick Mooney * into VFS.
3668e2fc3408SPatrick Mooney *
3669e2fc3408SPatrick Mooney * Since the resulting vnode is highly likely to be at some
3670e2fc3408SPatrick Mooney * abitrary position in another filesystem, we insist that the
3671e2fc3408SPatrick Mooney * VTRAVERSE flag is set on the parent. This prevents things
3672e2fc3408SPatrick Mooney * such as the v_path freshness logic from mistaking the
3673e2fc3408SPatrick Mooney * resulting vnode as a "real" child of the parent, rather than
3674e2fc3408SPatrick Mooney * a consequence of this "procfs wormhole".
3675e2fc3408SPatrick Mooney *
3676e2fc3408SPatrick Mooney * Failure to establish such protections can lead to
3677e2fc3408SPatrick Mooney * incorrectly calculated v_paths being set on nodes reached
3678e2fc3408SPatrick Mooney * through these lookups.
3679e2fc3408SPatrick Mooney */
3680e2fc3408SPatrick Mooney ASSERT((dp->v_flag & VTRAVERSE) != 0);
3681e2fc3408SPatrick Mooney
36827c478bd9Sstevel@tonic-gate dp = pnp->pr_realvp;
3683da6c28aaSamw return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3684da6c28aaSamw direntflags, realpnp));
36857c478bd9Sstevel@tonic-gate default:
36867c478bd9Sstevel@tonic-gate break;
36877c478bd9Sstevel@tonic-gate }
36887c478bd9Sstevel@tonic-gate
3689a02120c4SAndy Fiddaman if ((type == PR_OBJECTDIR || type == PR_FDDIR ||
3690a02120c4SAndy Fiddaman type == PR_FDINFODIR || type == PR_PATHDIR) &&
3691da6c28aaSamw (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
36927c478bd9Sstevel@tonic-gate return (error);
36937c478bd9Sstevel@tonic-gate
3694da6c28aaSamw /* XXX - Do we need to pass ct, direntflags, or realpnp? */
36957c478bd9Sstevel@tonic-gate *vpp = (pr_lookup_function[type](dp, comp));
36967c478bd9Sstevel@tonic-gate
36977c478bd9Sstevel@tonic-gate return ((*vpp == NULL) ? ENOENT : 0);
36987c478bd9Sstevel@tonic-gate }
36997c478bd9Sstevel@tonic-gate
37007c478bd9Sstevel@tonic-gate /* ARGSUSED */
37017c478bd9Sstevel@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)37027c478bd9Sstevel@tonic-gate prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3703da6c28aaSamw int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3704da6c28aaSamw vsecattr_t *vsecp)
37057c478bd9Sstevel@tonic-gate {
37067c478bd9Sstevel@tonic-gate int error;
37077c478bd9Sstevel@tonic-gate
3708da6c28aaSamw if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3709da6c28aaSamw ct, NULL, NULL)) != 0) {
3710fee52838SPatrick Mooney if (error == ENOENT) {
3711fee52838SPatrick Mooney /* One can't O_CREAT nonexistent files in /proc. */
3712fee52838SPatrick Mooney error = EACCES;
3713fee52838SPatrick Mooney }
3714fee52838SPatrick Mooney return (error);
3715fee52838SPatrick Mooney }
3716fee52838SPatrick Mooney
3717fee52838SPatrick Mooney if (excl == EXCL) {
3718fee52838SPatrick Mooney /* Disallow the O_EXCL case */
37197c478bd9Sstevel@tonic-gate error = EEXIST;
3720fee52838SPatrick Mooney } else if ((error = praccess(*vpp, mode, 0, cr, ct)) == 0) {
3721fee52838SPatrick Mooney /* Before proceeding, handle O_TRUNC if necessary. */
3722fee52838SPatrick Mooney if (vap->va_mask & AT_SIZE) {
37237c478bd9Sstevel@tonic-gate vnode_t *vp = *vpp;
3724fee52838SPatrick Mooney
3725fee52838SPatrick Mooney if (vp->v_type == VDIR) {
3726fee52838SPatrick Mooney /* Only allow O_TRUNC on files */
3727fee52838SPatrick Mooney error = EISDIR;
3728fee52838SPatrick Mooney } else if (vp->v_type != VPROC ||
3729fee52838SPatrick Mooney VTOP(vp)->pr_type != PR_FD) {
3730fee52838SPatrick Mooney /*
3731fee52838SPatrick Mooney * Disallow for files outside of the
3732fee52838SPatrick Mooney * /proc/<pid>/fd/<n> entries
3733fee52838SPatrick Mooney */
3734fee52838SPatrick Mooney error = EACCES;
3735fee52838SPatrick Mooney } else {
37367c478bd9Sstevel@tonic-gate uint_t mask;
37377c478bd9Sstevel@tonic-gate
37387c478bd9Sstevel@tonic-gate vp = VTOP(vp)->pr_realvp;
37397c478bd9Sstevel@tonic-gate mask = vap->va_mask;
37407c478bd9Sstevel@tonic-gate vap->va_mask = AT_SIZE;
3741da6c28aaSamw error = VOP_SETATTR(vp, vap, 0, cr, ct);
37427c478bd9Sstevel@tonic-gate vap->va_mask = mask;
37437c478bd9Sstevel@tonic-gate }
37447c478bd9Sstevel@tonic-gate }
3745fee52838SPatrick Mooney }
3746fee52838SPatrick Mooney
37477c478bd9Sstevel@tonic-gate if (error) {
37487c478bd9Sstevel@tonic-gate VN_RELE(*vpp);
37497c478bd9Sstevel@tonic-gate *vpp = NULL;
37507c478bd9Sstevel@tonic-gate }
37517c478bd9Sstevel@tonic-gate return (error);
37527c478bd9Sstevel@tonic-gate }
37537c478bd9Sstevel@tonic-gate
37547c478bd9Sstevel@tonic-gate /* ARGSUSED */
37557c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_notdir(vnode_t * dp,char * comp)37567c478bd9Sstevel@tonic-gate pr_lookup_notdir(vnode_t *dp, char *comp)
37577c478bd9Sstevel@tonic-gate {
37587c478bd9Sstevel@tonic-gate return (NULL);
37597c478bd9Sstevel@tonic-gate }
37607c478bd9Sstevel@tonic-gate
37617c478bd9Sstevel@tonic-gate /*
37627c478bd9Sstevel@tonic-gate * Find or construct a process vnode for the given pid.
37637c478bd9Sstevel@tonic-gate */
37647c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_procdir(vnode_t * dp,char * comp)37657c478bd9Sstevel@tonic-gate pr_lookup_procdir(vnode_t *dp, char *comp)
37667c478bd9Sstevel@tonic-gate {
37677c478bd9Sstevel@tonic-gate pid_t pid;
37687c478bd9Sstevel@tonic-gate prnode_t *pnp;
37697c478bd9Sstevel@tonic-gate prcommon_t *pcp;
37707c478bd9Sstevel@tonic-gate vnode_t *vp;
37717c478bd9Sstevel@tonic-gate proc_t *p;
37727c478bd9Sstevel@tonic-gate int c;
37737c478bd9Sstevel@tonic-gate
37747c478bd9Sstevel@tonic-gate ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
37757c478bd9Sstevel@tonic-gate
37767c478bd9Sstevel@tonic-gate if (strcmp(comp, "self") == 0) {
37777c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_SELF);
37787c478bd9Sstevel@tonic-gate return (PTOV(pnp));
37797c478bd9Sstevel@tonic-gate } else {
37807c478bd9Sstevel@tonic-gate pid = 0;
37817c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
37827c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
37837c478bd9Sstevel@tonic-gate return (NULL);
37847c478bd9Sstevel@tonic-gate pid = 10*pid + c - '0';
37857c478bd9Sstevel@tonic-gate if (pid > maxpid)
37867c478bd9Sstevel@tonic-gate return (NULL);
37877c478bd9Sstevel@tonic-gate }
37887c478bd9Sstevel@tonic-gate }
37897c478bd9Sstevel@tonic-gate
37907c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_PIDDIR);
37917c478bd9Sstevel@tonic-gate
37927c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
37937c478bd9Sstevel@tonic-gate if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
37947c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
37957c478bd9Sstevel@tonic-gate prfreenode(pnp);
37967c478bd9Sstevel@tonic-gate return (NULL);
37977c478bd9Sstevel@tonic-gate }
37987c478bd9Sstevel@tonic-gate ASSERT(p->p_stat != 0);
37997c478bd9Sstevel@tonic-gate
3800ddf7fe95Scasper /* NOTE: we're holding pidlock across the policy call. */
38017c478bd9Sstevel@tonic-gate if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3802ddf7fe95Scasper mutex_exit(&pidlock);
38037c478bd9Sstevel@tonic-gate prfreenode(pnp);
38047c478bd9Sstevel@tonic-gate return (NULL);
38057c478bd9Sstevel@tonic-gate }
38067c478bd9Sstevel@tonic-gate
3807ddf7fe95Scasper mutex_enter(&p->p_lock);
3808ddf7fe95Scasper mutex_exit(&pidlock);
3809ddf7fe95Scasper
38107c478bd9Sstevel@tonic-gate /*
38117c478bd9Sstevel@tonic-gate * If a process vnode already exists and it is not invalid
38127c478bd9Sstevel@tonic-gate * and it was created by the current process and it belongs
38137c478bd9Sstevel@tonic-gate * to the same /proc mount point as our parent vnode, then
38147c478bd9Sstevel@tonic-gate * just use it and discard the newly-allocated prnode.
38157c478bd9Sstevel@tonic-gate */
38167c478bd9Sstevel@tonic-gate for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
38177c478bd9Sstevel@tonic-gate if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
38187c478bd9Sstevel@tonic-gate VTOP(vp)->pr_owner == curproc &&
38197c478bd9Sstevel@tonic-gate vp->v_vfsp == dp->v_vfsp) {
38207c478bd9Sstevel@tonic-gate ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
38217c478bd9Sstevel@tonic-gate VN_HOLD(vp);
38227c478bd9Sstevel@tonic-gate prfreenode(pnp);
38237c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
38247c478bd9Sstevel@tonic-gate return (vp);
38257c478bd9Sstevel@tonic-gate }
38267c478bd9Sstevel@tonic-gate }
38277c478bd9Sstevel@tonic-gate pnp->pr_owner = curproc;
38287c478bd9Sstevel@tonic-gate
38297c478bd9Sstevel@tonic-gate /*
38307c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
38317c478bd9Sstevel@tonic-gate * Finish the job.
38327c478bd9Sstevel@tonic-gate */
38337c478bd9Sstevel@tonic-gate pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
38347c478bd9Sstevel@tonic-gate if ((vp = p->p_trace) != NULL) {
38357c478bd9Sstevel@tonic-gate /* discard the new prcommon and use the existing prcommon */
38367c478bd9Sstevel@tonic-gate prfreecommon(pcp);
38377c478bd9Sstevel@tonic-gate pcp = VTOP(vp)->pr_common;
38387c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
38397c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
38407c478bd9Sstevel@tonic-gate pcp->prc_refcnt++;
38417c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
38427c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
38437c478bd9Sstevel@tonic-gate } else {
38447c478bd9Sstevel@tonic-gate /* initialize the new prcommon struct */
38457c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
38467c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_SYS;
38475203e56bSJerry Jelinek if (p->p_stat == SZOMB || (p->p_flag & SEXITING) != 0)
38487c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_DESTROY;
38497c478bd9Sstevel@tonic-gate pcp->prc_proc = p;
38507c478bd9Sstevel@tonic-gate pcp->prc_datamodel = p->p_model;
38517c478bd9Sstevel@tonic-gate pcp->prc_pid = p->p_pid;
38527c478bd9Sstevel@tonic-gate pcp->prc_slot = p->p_slot;
38537c478bd9Sstevel@tonic-gate }
38547c478bd9Sstevel@tonic-gate pnp->pr_pcommon = pcp;
38557c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
38567c478bd9Sstevel@tonic-gate VN_HOLD(dp);
38577c478bd9Sstevel@tonic-gate /*
38587c478bd9Sstevel@tonic-gate * Link in the old, invalid directory vnode so we
38597c478bd9Sstevel@tonic-gate * can later determine the last close of the file.
38607c478bd9Sstevel@tonic-gate */
38617c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_trace;
38627c478bd9Sstevel@tonic-gate p->p_trace = dp = PTOV(pnp);
38637c478bd9Sstevel@tonic-gate
38647c478bd9Sstevel@tonic-gate /*
38657c478bd9Sstevel@tonic-gate * Kludge for old /proc: initialize the PR_PIDFILE as well.
38667c478bd9Sstevel@tonic-gate */
38677c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
38687c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
38697c478bd9Sstevel@tonic-gate pnp->pr_ino = ptoi(pcp->prc_pid);
38707c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
38717c478bd9Sstevel@tonic-gate pnp->pr_pcommon = pcp;
38727c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
38737c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
38747c478bd9Sstevel@tonic-gate p->p_plist = vp;
38757c478bd9Sstevel@tonic-gate
38767c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
38777c478bd9Sstevel@tonic-gate return (dp);
38787c478bd9Sstevel@tonic-gate }
38797c478bd9Sstevel@tonic-gate
38807c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_piddir(vnode_t * dp,char * comp)38817c478bd9Sstevel@tonic-gate pr_lookup_piddir(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 user_t *up;
38887c478bd9Sstevel@tonic-gate prdirent_t *dirp;
38897c478bd9Sstevel@tonic-gate int i;
38907c478bd9Sstevel@tonic-gate enum prnodetype type;
38917c478bd9Sstevel@tonic-gate
38927c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_PIDDIR);
38937c478bd9Sstevel@tonic-gate
38947c478bd9Sstevel@tonic-gate for (i = 0; i < NPIDDIRFILES; i++) {
38957c478bd9Sstevel@tonic-gate /* Skip "." and ".." */
38967c478bd9Sstevel@tonic-gate dirp = &piddir[i+2];
38977c478bd9Sstevel@tonic-gate if (strcmp(comp, dirp->d_name) == 0)
38987c478bd9Sstevel@tonic-gate break;
38997c478bd9Sstevel@tonic-gate }
39007c478bd9Sstevel@tonic-gate
39017c478bd9Sstevel@tonic-gate if (i >= NPIDDIRFILES)
39027c478bd9Sstevel@tonic-gate return (NULL);
39037c478bd9Sstevel@tonic-gate
39047c478bd9Sstevel@tonic-gate type = (int)dirp->d_ino;
39057c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, type);
39067c478bd9Sstevel@tonic-gate
39077c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
39087c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
39097c478bd9Sstevel@tonic-gate if (p == NULL) {
39107c478bd9Sstevel@tonic-gate prfreenode(pnp);
39117c478bd9Sstevel@tonic-gate return (NULL);
39127c478bd9Sstevel@tonic-gate }
39137c478bd9Sstevel@tonic-gate if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
39147c478bd9Sstevel@tonic-gate switch (type) {
39157c478bd9Sstevel@tonic-gate case PR_PSINFO:
39167c478bd9Sstevel@tonic-gate case PR_USAGE:
39177c478bd9Sstevel@tonic-gate break;
39187c478bd9Sstevel@tonic-gate default:
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 switch (type) {
39267c478bd9Sstevel@tonic-gate case PR_CURDIR:
39277c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
39287c478bd9Sstevel@tonic-gate up = PTOU(p);
39297c478bd9Sstevel@tonic-gate vp = (type == PR_CURDIR)? up->u_cdir :
39307c478bd9Sstevel@tonic-gate (up->u_rdir? up->u_rdir : rootdir);
39317c478bd9Sstevel@tonic-gate
3932e2fc3408SPatrick Mooney if (vp == NULL) {
3933e2fc3408SPatrick Mooney /* can't happen(?) */
39347c478bd9Sstevel@tonic-gate prunlock(dpnp);
39357c478bd9Sstevel@tonic-gate prfreenode(pnp);
39367c478bd9Sstevel@tonic-gate return (NULL);
39377c478bd9Sstevel@tonic-gate }
39387c478bd9Sstevel@tonic-gate /*
39397c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
39407c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
39417c478bd9Sstevel@tonic-gate */
39427c478bd9Sstevel@tonic-gate VN_HOLD(vp);
39437c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
3944e2fc3408SPatrick Mooney PTOV(pnp)->v_flag |= VTRAVERSE;
39457c478bd9Sstevel@tonic-gate break;
39467c478bd9Sstevel@tonic-gate default:
39477c478bd9Sstevel@tonic-gate break;
39487c478bd9Sstevel@tonic-gate }
39497c478bd9Sstevel@tonic-gate
39507c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
39517c478bd9Sstevel@tonic-gate
39527c478bd9Sstevel@tonic-gate if ((vp = dpnp->pr_files[i]) != NULL &&
39537c478bd9Sstevel@tonic-gate !(VTOP(vp)->pr_flags & PR_INVAL)) {
39547c478bd9Sstevel@tonic-gate VN_HOLD(vp);
39557c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
39567c478bd9Sstevel@tonic-gate prunlock(dpnp);
39577c478bd9Sstevel@tonic-gate prfreenode(pnp);
39587c478bd9Sstevel@tonic-gate return (vp);
39597c478bd9Sstevel@tonic-gate }
39607c478bd9Sstevel@tonic-gate
39617c478bd9Sstevel@tonic-gate /*
39627c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
39637c478bd9Sstevel@tonic-gate * Finish the job.
39647c478bd9Sstevel@tonic-gate */
39657c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
39667c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
39677c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
39687c478bd9Sstevel@tonic-gate VN_HOLD(dp);
39697c478bd9Sstevel@tonic-gate pnp->pr_index = i;
39707c478bd9Sstevel@tonic-gate
39717c478bd9Sstevel@tonic-gate dpnp->pr_files[i] = vp = PTOV(pnp);
39727c478bd9Sstevel@tonic-gate
39737c478bd9Sstevel@tonic-gate /*
39747c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
39757c478bd9Sstevel@tonic-gate */
39767c478bd9Sstevel@tonic-gate if (vp->v_type == VPROC) {
39777c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
39787c478bd9Sstevel@tonic-gate p->p_plist = vp;
39797c478bd9Sstevel@tonic-gate }
39807c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
39817c478bd9Sstevel@tonic-gate prunlock(dpnp);
39827c478bd9Sstevel@tonic-gate return (vp);
39837c478bd9Sstevel@tonic-gate }
39847c478bd9Sstevel@tonic-gate
39857c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_objectdir(vnode_t * dp,char * comp)39867c478bd9Sstevel@tonic-gate pr_lookup_objectdir(vnode_t *dp, char *comp)
39877c478bd9Sstevel@tonic-gate {
39887c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
39897c478bd9Sstevel@tonic-gate prnode_t *pnp;
39907c478bd9Sstevel@tonic-gate proc_t *p;
39917c478bd9Sstevel@tonic-gate struct seg *seg;
39927c478bd9Sstevel@tonic-gate struct as *as;
39937c478bd9Sstevel@tonic-gate vnode_t *vp;
39947c478bd9Sstevel@tonic-gate vattr_t vattr;
39957c478bd9Sstevel@tonic-gate
39967c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_OBJECTDIR);
39977c478bd9Sstevel@tonic-gate
39987c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_OBJECT);
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) || (as = 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 /*
40127c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
40137c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
40147c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
40157c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
40167c478bd9Sstevel@tonic-gate */
40177c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4018dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_READER);
40197c478bd9Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) == NULL) {
40207c478bd9Sstevel@tonic-gate vp = NULL;
40217c478bd9Sstevel@tonic-gate goto out;
40227c478bd9Sstevel@tonic-gate }
40237c478bd9Sstevel@tonic-gate if (strcmp(comp, "a.out") == 0) {
40247c478bd9Sstevel@tonic-gate vp = p->p_exec;
40257c478bd9Sstevel@tonic-gate goto out;
40267c478bd9Sstevel@tonic-gate }
40277c478bd9Sstevel@tonic-gate do {
40287c478bd9Sstevel@tonic-gate /*
40297c478bd9Sstevel@tonic-gate * Manufacture a filename for the "object" directory.
40307c478bd9Sstevel@tonic-gate */
40317c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
40327c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
40337c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
40347c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
4035da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
40367c478bd9Sstevel@tonic-gate char name[64];
40377c478bd9Sstevel@tonic-gate
40387c478bd9Sstevel@tonic-gate if (vp == p->p_exec) /* "a.out" */
40397c478bd9Sstevel@tonic-gate continue;
40407c478bd9Sstevel@tonic-gate pr_object_name(name, vp, &vattr);
40417c478bd9Sstevel@tonic-gate if (strcmp(name, comp) == 0)
40427c478bd9Sstevel@tonic-gate goto out;
40437c478bd9Sstevel@tonic-gate }
40447c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
40457c478bd9Sstevel@tonic-gate
40467c478bd9Sstevel@tonic-gate vp = NULL;
40477c478bd9Sstevel@tonic-gate out:
40487c478bd9Sstevel@tonic-gate if (vp != NULL) {
40497c478bd9Sstevel@tonic-gate VN_HOLD(vp);
40507c478bd9Sstevel@tonic-gate }
4051dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
40527c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
40537c478bd9Sstevel@tonic-gate prunlock(dpnp);
40547c478bd9Sstevel@tonic-gate
40557c478bd9Sstevel@tonic-gate if (vp == NULL)
40567c478bd9Sstevel@tonic-gate prfreenode(pnp);
40577c478bd9Sstevel@tonic-gate else {
40587c478bd9Sstevel@tonic-gate /*
40597c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
40607c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
40617c478bd9Sstevel@tonic-gate * Don't link this prnode into the list of all
40627c478bd9Sstevel@tonic-gate * prnodes for the process; this is a one-use node.
40637c478bd9Sstevel@tonic-gate * Its use is entirely to catch and fail opens for writing.
40647c478bd9Sstevel@tonic-gate */
40657c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
40667c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
40677c478bd9Sstevel@tonic-gate }
40687c478bd9Sstevel@tonic-gate
40697c478bd9Sstevel@tonic-gate return (vp);
40707c478bd9Sstevel@tonic-gate }
40717c478bd9Sstevel@tonic-gate
40727c478bd9Sstevel@tonic-gate /*
40737c478bd9Sstevel@tonic-gate * Find or construct an lwp vnode for the given lwpid.
40747c478bd9Sstevel@tonic-gate */
40757c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_lwpdir(vnode_t * dp,char * comp)40767c478bd9Sstevel@tonic-gate pr_lookup_lwpdir(vnode_t *dp, char *comp)
40777c478bd9Sstevel@tonic-gate {
40787c478bd9Sstevel@tonic-gate id_t tid; /* same type as t->t_tid */
40797c478bd9Sstevel@tonic-gate int want_agent;
40807c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
40817c478bd9Sstevel@tonic-gate prnode_t *pnp;
40827c478bd9Sstevel@tonic-gate prcommon_t *pcp;
40837c478bd9Sstevel@tonic-gate vnode_t *vp;
40847c478bd9Sstevel@tonic-gate proc_t *p;
40857c478bd9Sstevel@tonic-gate kthread_t *t;
40867c478bd9Sstevel@tonic-gate lwpdir_t *ldp;
40877c478bd9Sstevel@tonic-gate lwpent_t *lep;
40887c478bd9Sstevel@tonic-gate int tslot;
40897c478bd9Sstevel@tonic-gate int c;
40907c478bd9Sstevel@tonic-gate
40917c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_LWPDIR);
40927c478bd9Sstevel@tonic-gate
40937c478bd9Sstevel@tonic-gate tid = 0;
40947c478bd9Sstevel@tonic-gate if (strcmp(comp, "agent") == 0)
40957c478bd9Sstevel@tonic-gate want_agent = 1;
40967c478bd9Sstevel@tonic-gate else {
40977c478bd9Sstevel@tonic-gate want_agent = 0;
40987c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
40997c478bd9Sstevel@tonic-gate id_t otid;
41007c478bd9Sstevel@tonic-gate
41017c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
41027c478bd9Sstevel@tonic-gate return (NULL);
41037c478bd9Sstevel@tonic-gate otid = tid;
41047c478bd9Sstevel@tonic-gate tid = 10*tid + c - '0';
41057c478bd9Sstevel@tonic-gate if (tid/10 != otid) /* integer overflow */
41067c478bd9Sstevel@tonic-gate return (NULL);
41077c478bd9Sstevel@tonic-gate }
41087c478bd9Sstevel@tonic-gate }
41097c478bd9Sstevel@tonic-gate
41107c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_LWPIDDIR);
41117c478bd9Sstevel@tonic-gate
41127c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
41137c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
41147c478bd9Sstevel@tonic-gate if (p == NULL) {
41157c478bd9Sstevel@tonic-gate prfreenode(pnp);
41167c478bd9Sstevel@tonic-gate return (NULL);
41177c478bd9Sstevel@tonic-gate }
41187c478bd9Sstevel@tonic-gate
41197c478bd9Sstevel@tonic-gate if (want_agent) {
41207c478bd9Sstevel@tonic-gate if ((t = p->p_agenttp) == NULL)
41217c478bd9Sstevel@tonic-gate lep = NULL;
41227c478bd9Sstevel@tonic-gate else {
41237c478bd9Sstevel@tonic-gate tid = t->t_tid;
41247c478bd9Sstevel@tonic-gate tslot = t->t_dslot;
41257c478bd9Sstevel@tonic-gate lep = p->p_lwpdir[tslot].ld_entry;
41267c478bd9Sstevel@tonic-gate }
41277c478bd9Sstevel@tonic-gate } else {
41287c478bd9Sstevel@tonic-gate if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
41297c478bd9Sstevel@tonic-gate lep = NULL;
41307c478bd9Sstevel@tonic-gate else {
41317c478bd9Sstevel@tonic-gate tslot = (int)(ldp - p->p_lwpdir);
41327c478bd9Sstevel@tonic-gate lep = ldp->ld_entry;
41337c478bd9Sstevel@tonic-gate }
41347c478bd9Sstevel@tonic-gate }
41357c478bd9Sstevel@tonic-gate
41367c478bd9Sstevel@tonic-gate if (lep == NULL) {
41377c478bd9Sstevel@tonic-gate prunlock(dpnp);
41387c478bd9Sstevel@tonic-gate prfreenode(pnp);
41397c478bd9Sstevel@tonic-gate return (NULL);
41407c478bd9Sstevel@tonic-gate }
41417c478bd9Sstevel@tonic-gate
41427c478bd9Sstevel@tonic-gate /*
41437c478bd9Sstevel@tonic-gate * If an lwp vnode already exists and it is not invalid
41447c478bd9Sstevel@tonic-gate * and it was created by the current process and it belongs
41457c478bd9Sstevel@tonic-gate * to the same /proc mount point as our parent vnode, then
41467c478bd9Sstevel@tonic-gate * just use it and discard the newly-allocated prnode.
41477c478bd9Sstevel@tonic-gate */
41487c478bd9Sstevel@tonic-gate for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
41497c478bd9Sstevel@tonic-gate if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
41507c478bd9Sstevel@tonic-gate VTOP(vp)->pr_owner == curproc &&
41517c478bd9Sstevel@tonic-gate vp->v_vfsp == dp->v_vfsp) {
41527c478bd9Sstevel@tonic-gate VN_HOLD(vp);
41537c478bd9Sstevel@tonic-gate prunlock(dpnp);
41547c478bd9Sstevel@tonic-gate prfreenode(pnp);
41557c478bd9Sstevel@tonic-gate return (vp);
41567c478bd9Sstevel@tonic-gate }
41577c478bd9Sstevel@tonic-gate }
41587c478bd9Sstevel@tonic-gate pnp->pr_owner = curproc;
41597c478bd9Sstevel@tonic-gate
41607c478bd9Sstevel@tonic-gate /*
41617c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
41627c478bd9Sstevel@tonic-gate * Finish the job.
41637c478bd9Sstevel@tonic-gate */
41647c478bd9Sstevel@tonic-gate pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
41657c478bd9Sstevel@tonic-gate if ((vp = lep->le_trace) != NULL) {
41667c478bd9Sstevel@tonic-gate /* discard the new prcommon and use the existing prcommon */
41677c478bd9Sstevel@tonic-gate prfreecommon(pcp);
41687c478bd9Sstevel@tonic-gate pcp = VTOP(vp)->pr_common;
41697c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
41707c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
41717c478bd9Sstevel@tonic-gate pcp->prc_refcnt++;
41727c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
41737c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
41747c478bd9Sstevel@tonic-gate } else {
41757c478bd9Sstevel@tonic-gate /* initialize the new prcommon struct */
41767c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_LWP;
41777c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
41787c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_SYS;
41797c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) == NULL)
41807c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_DESTROY;
41817c478bd9Sstevel@tonic-gate pcp->prc_proc = p;
41827c478bd9Sstevel@tonic-gate pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
41837c478bd9Sstevel@tonic-gate pcp->prc_pid = p->p_pid;
41847c478bd9Sstevel@tonic-gate pcp->prc_slot = p->p_slot;
41857c478bd9Sstevel@tonic-gate pcp->prc_thread = t;
41867c478bd9Sstevel@tonic-gate pcp->prc_tid = tid;
41877c478bd9Sstevel@tonic-gate pcp->prc_tslot = tslot;
41887c478bd9Sstevel@tonic-gate }
41897c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
41907c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
41917c478bd9Sstevel@tonic-gate VN_HOLD(dp);
41927c478bd9Sstevel@tonic-gate /*
41937c478bd9Sstevel@tonic-gate * Link in the old, invalid directory vnode so we
41947c478bd9Sstevel@tonic-gate * can later determine the last close of the file.
41957c478bd9Sstevel@tonic-gate */
41967c478bd9Sstevel@tonic-gate pnp->pr_next = lep->le_trace;
41977c478bd9Sstevel@tonic-gate lep->le_trace = vp = PTOV(pnp);
41987c478bd9Sstevel@tonic-gate prunlock(dpnp);
41997c478bd9Sstevel@tonic-gate return (vp);
42007c478bd9Sstevel@tonic-gate }
42017c478bd9Sstevel@tonic-gate
42027c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_lwpiddir(vnode_t * dp,char * comp)42037c478bd9Sstevel@tonic-gate pr_lookup_lwpiddir(vnode_t *dp, char *comp)
42047c478bd9Sstevel@tonic-gate {
42057c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
42067c478bd9Sstevel@tonic-gate vnode_t *vp;
42077c478bd9Sstevel@tonic-gate prnode_t *pnp;
42087c478bd9Sstevel@tonic-gate proc_t *p;
42097c478bd9Sstevel@tonic-gate prdirent_t *dirp;
42107c478bd9Sstevel@tonic-gate int i;
42117c478bd9Sstevel@tonic-gate enum prnodetype type;
42127c478bd9Sstevel@tonic-gate
42137c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_LWPIDDIR);
42147c478bd9Sstevel@tonic-gate
42157c478bd9Sstevel@tonic-gate for (i = 0; i < NLWPIDDIRFILES; i++) {
42167c478bd9Sstevel@tonic-gate /* Skip "." and ".." */
42177c478bd9Sstevel@tonic-gate dirp = &lwpiddir[i+2];
42187c478bd9Sstevel@tonic-gate if (strcmp(comp, dirp->d_name) == 0)
42197c478bd9Sstevel@tonic-gate break;
42207c478bd9Sstevel@tonic-gate }
42217c478bd9Sstevel@tonic-gate
42227c478bd9Sstevel@tonic-gate if (i >= NLWPIDDIRFILES)
42237c478bd9Sstevel@tonic-gate return (NULL);
42247c478bd9Sstevel@tonic-gate
42257c478bd9Sstevel@tonic-gate type = (int)dirp->d_ino;
42267c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, type);
42277c478bd9Sstevel@tonic-gate
42287c478bd9Sstevel@tonic-gate p = pr_p_lock(dpnp);
42297c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
42307c478bd9Sstevel@tonic-gate if (p == NULL) {
42317c478bd9Sstevel@tonic-gate prfreenode(pnp);
42327c478bd9Sstevel@tonic-gate return (NULL);
42337c478bd9Sstevel@tonic-gate }
42347c478bd9Sstevel@tonic-gate if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
42357c478bd9Sstevel@tonic-gate /*
42367c478bd9Sstevel@tonic-gate * Only the lwpsinfo file is present for zombie lwps.
42377c478bd9Sstevel@tonic-gate * Nothing is present if the lwp has been reaped.
42387c478bd9Sstevel@tonic-gate */
42397c478bd9Sstevel@tonic-gate if (dpnp->pr_common->prc_tslot == -1 ||
42407c478bd9Sstevel@tonic-gate type != PR_LWPSINFO) {
42417c478bd9Sstevel@tonic-gate prunlock(dpnp);
42427c478bd9Sstevel@tonic-gate prfreenode(pnp);
42437c478bd9Sstevel@tonic-gate return (NULL);
42447c478bd9Sstevel@tonic-gate }
42457c478bd9Sstevel@tonic-gate }
42467c478bd9Sstevel@tonic-gate
42477c478bd9Sstevel@tonic-gate #if defined(__sparc)
42487c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
42497c478bd9Sstevel@tonic-gate if (type == PR_ASRS && p->p_model != DATAMODEL_LP64) {
42507c478bd9Sstevel@tonic-gate prunlock(dpnp);
42517c478bd9Sstevel@tonic-gate prfreenode(pnp);
42527c478bd9Sstevel@tonic-gate return (NULL);
42537c478bd9Sstevel@tonic-gate }
42547c478bd9Sstevel@tonic-gate #endif
42557c478bd9Sstevel@tonic-gate
42567c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
42577c478bd9Sstevel@tonic-gate
42587c478bd9Sstevel@tonic-gate if ((vp = dpnp->pr_files[i]) != NULL &&
42597c478bd9Sstevel@tonic-gate !(VTOP(vp)->pr_flags & PR_INVAL)) {
42607c478bd9Sstevel@tonic-gate VN_HOLD(vp);
42617c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
42627c478bd9Sstevel@tonic-gate prunlock(dpnp);
42637c478bd9Sstevel@tonic-gate prfreenode(pnp);
42647c478bd9Sstevel@tonic-gate return (vp);
42657c478bd9Sstevel@tonic-gate }
42667c478bd9Sstevel@tonic-gate
42677c478bd9Sstevel@tonic-gate /*
42687c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
42697c478bd9Sstevel@tonic-gate * Finish the job.
42707c478bd9Sstevel@tonic-gate */
42717c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
42727c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
42737c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
42747c478bd9Sstevel@tonic-gate VN_HOLD(dp);
42757c478bd9Sstevel@tonic-gate pnp->pr_index = i;
42767c478bd9Sstevel@tonic-gate
42777c478bd9Sstevel@tonic-gate dpnp->pr_files[i] = vp = PTOV(pnp);
42787c478bd9Sstevel@tonic-gate
42797c478bd9Sstevel@tonic-gate /*
42807c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
42817c478bd9Sstevel@tonic-gate */
42827c478bd9Sstevel@tonic-gate if (vp->v_type == VPROC) {
42837c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
42847c478bd9Sstevel@tonic-gate p->p_plist = vp;
42857c478bd9Sstevel@tonic-gate }
42867c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
42877c478bd9Sstevel@tonic-gate prunlock(dpnp);
42887c478bd9Sstevel@tonic-gate return (vp);
42897c478bd9Sstevel@tonic-gate }
42907c478bd9Sstevel@tonic-gate
42917c478bd9Sstevel@tonic-gate /*
4292da29c6a3SDan McDonald * Lookup one of the process's file vnodes.
42937c478bd9Sstevel@tonic-gate */
42947c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_fddir(vnode_t * dp,char * comp)42957c478bd9Sstevel@tonic-gate pr_lookup_fddir(vnode_t *dp, char *comp)
42967c478bd9Sstevel@tonic-gate {
42977c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
42987c478bd9Sstevel@tonic-gate prnode_t *pnp;
42997c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
43007c478bd9Sstevel@tonic-gate proc_t *p;
43017c478bd9Sstevel@tonic-gate file_t *fp;
43027c478bd9Sstevel@tonic-gate uint_t fd;
43037c478bd9Sstevel@tonic-gate int c;
43047c478bd9Sstevel@tonic-gate
43057c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_FDDIR);
43067c478bd9Sstevel@tonic-gate
43077c478bd9Sstevel@tonic-gate fd = 0;
43087c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
43097c478bd9Sstevel@tonic-gate int ofd;
43107c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
43117c478bd9Sstevel@tonic-gate return (NULL);
43127c478bd9Sstevel@tonic-gate ofd = fd;
43137c478bd9Sstevel@tonic-gate fd = 10 * fd + c - '0';
43147c478bd9Sstevel@tonic-gate if (fd / 10 != ofd) /* integer overflow */
43157c478bd9Sstevel@tonic-gate return (NULL);
43167c478bd9Sstevel@tonic-gate }
43177c478bd9Sstevel@tonic-gate
43187c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_FD);
43197c478bd9Sstevel@tonic-gate
43207c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
43217c478bd9Sstevel@tonic-gate prfreenode(pnp);
43227c478bd9Sstevel@tonic-gate return (NULL);
43237c478bd9Sstevel@tonic-gate }
43247c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
43257c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas) {
43267c478bd9Sstevel@tonic-gate prunlock(dpnp);
43277c478bd9Sstevel@tonic-gate prfreenode(pnp);
43287c478bd9Sstevel@tonic-gate return (NULL);
43297c478bd9Sstevel@tonic-gate }
43307c478bd9Sstevel@tonic-gate
4331a02120c4SAndy Fiddaman if ((fp = pr_getf(p, fd, NULL)) != NULL) {
43327c478bd9Sstevel@tonic-gate pnp->pr_mode = 07111;
43337c478bd9Sstevel@tonic-gate if (fp->f_flag & FREAD)
43347c478bd9Sstevel@tonic-gate pnp->pr_mode |= 0444;
43357c478bd9Sstevel@tonic-gate if (fp->f_flag & FWRITE)
43367c478bd9Sstevel@tonic-gate pnp->pr_mode |= 0222;
43377c478bd9Sstevel@tonic-gate vp = fp->f_vnode;
43387c478bd9Sstevel@tonic-gate VN_HOLD(vp);
43397c478bd9Sstevel@tonic-gate }
4340a02120c4SAndy Fiddaman
43417c478bd9Sstevel@tonic-gate prunlock(dpnp);
434237e2cd25SPatrick Mooney if (fp != NULL) {
434337e2cd25SPatrick Mooney pr_releasef(fp);
434437e2cd25SPatrick Mooney }
43457c478bd9Sstevel@tonic-gate
4346a02120c4SAndy Fiddaman if (vp == NULL) {
43477c478bd9Sstevel@tonic-gate prfreenode(pnp);
4348a02120c4SAndy Fiddaman return (NULL);
4349a02120c4SAndy Fiddaman }
4350a02120c4SAndy Fiddaman
43517c478bd9Sstevel@tonic-gate /*
43527c478bd9Sstevel@tonic-gate * Fill in the prnode so future references will
43537c478bd9Sstevel@tonic-gate * be able to find the underlying object's vnode.
43547c478bd9Sstevel@tonic-gate * Don't link this prnode into the list of all
43557c478bd9Sstevel@tonic-gate * prnodes for the process; this is a one-use node.
43567c478bd9Sstevel@tonic-gate */
43577c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
43587c478bd9Sstevel@tonic-gate pnp->pr_parent = dp; /* needed for prlookup */
43597c478bd9Sstevel@tonic-gate VN_HOLD(dp);
43607c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
4361e2fc3408SPatrick Mooney if (pnp->pr_realvp->v_type == VDIR) {
43627c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
4363e2fc3408SPatrick Mooney vp->v_flag |= VTRAVERSE;
4364e2fc3408SPatrick Mooney }
4365a02120c4SAndy Fiddaman
4366a02120c4SAndy Fiddaman return (vp);
43677c478bd9Sstevel@tonic-gate }
43687c478bd9Sstevel@tonic-gate
4369a02120c4SAndy Fiddaman static vnode_t *
pr_lookup_fdinfodir(vnode_t * dp,char * comp)4370a02120c4SAndy Fiddaman pr_lookup_fdinfodir(vnode_t *dp, char *comp)
4371a02120c4SAndy Fiddaman {
4372a02120c4SAndy Fiddaman prnode_t *dpnp = VTOP(dp);
4373a02120c4SAndy Fiddaman prnode_t *pnp;
4374a02120c4SAndy Fiddaman vnode_t *vp = NULL;
4375a02120c4SAndy Fiddaman proc_t *p;
4376a02120c4SAndy Fiddaman uint_t fd;
4377a02120c4SAndy Fiddaman int c;
4378a02120c4SAndy Fiddaman
4379a02120c4SAndy Fiddaman ASSERT(dpnp->pr_type == PR_FDINFODIR);
4380a02120c4SAndy Fiddaman
4381a02120c4SAndy Fiddaman fd = 0;
4382a02120c4SAndy Fiddaman while ((c = *comp++) != '\0') {
4383a02120c4SAndy Fiddaman int ofd;
4384a02120c4SAndy Fiddaman if (c < '0' || c > '9')
4385a02120c4SAndy Fiddaman return (NULL);
4386a02120c4SAndy Fiddaman ofd = fd;
4387a02120c4SAndy Fiddaman fd = 10 * fd + c - '0';
4388a02120c4SAndy Fiddaman if (fd / 10 != ofd) /* integer overflow */
4389a02120c4SAndy Fiddaman return (NULL);
4390a02120c4SAndy Fiddaman }
4391a02120c4SAndy Fiddaman
4392a02120c4SAndy Fiddaman pnp = prgetnode(dp, PR_FDINFO);
4393a02120c4SAndy Fiddaman
4394a02120c4SAndy Fiddaman if (prlock(dpnp, ZNO) != 0) {
4395a02120c4SAndy Fiddaman prfreenode(pnp);
4396a02120c4SAndy Fiddaman return (NULL);
4397a02120c4SAndy Fiddaman }
4398a02120c4SAndy Fiddaman p = dpnp->pr_common->prc_proc;
4399a02120c4SAndy Fiddaman if ((p->p_flag & SSYS) || p->p_as == &kas) {
4400a02120c4SAndy Fiddaman prunlock(dpnp);
4401a02120c4SAndy Fiddaman prfreenode(pnp);
4402a02120c4SAndy Fiddaman return (NULL);
4403a02120c4SAndy Fiddaman }
4404a02120c4SAndy Fiddaman
4405a02120c4SAndy Fiddaman /*
4406a02120c4SAndy Fiddaman * Don't link this prnode into the list of all
4407a02120c4SAndy Fiddaman * prnodes for the process; this is a one-use node.
4408a02120c4SAndy Fiddaman * Unlike the FDDIR case, the underlying vnode is not stored in
4409a02120c4SAndy Fiddaman * pnp->pr_realvp. Instead, the fd number is stored in pnp->pr_index
4410a02120c4SAndy Fiddaman * and used by pr_read_fdinfo() to return information for the right
4411a02120c4SAndy Fiddaman * file descriptor.
4412a02120c4SAndy Fiddaman */
4413a02120c4SAndy Fiddaman pnp->pr_common = dpnp->pr_common;
4414a02120c4SAndy Fiddaman pnp->pr_pcommon = dpnp->pr_pcommon;
4415a02120c4SAndy Fiddaman pnp->pr_parent = dp;
4416a02120c4SAndy Fiddaman pnp->pr_index = fd;
4417a02120c4SAndy Fiddaman VN_HOLD(dp);
4418a02120c4SAndy Fiddaman prunlock(dpnp);
4419a02120c4SAndy Fiddaman vp = PTOV(pnp);
4420a02120c4SAndy Fiddaman
44217c478bd9Sstevel@tonic-gate return (vp);
44227c478bd9Sstevel@tonic-gate }
44237c478bd9Sstevel@tonic-gate
44247c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_pathdir(vnode_t * dp,char * comp)44257c478bd9Sstevel@tonic-gate pr_lookup_pathdir(vnode_t *dp, char *comp)
44267c478bd9Sstevel@tonic-gate {
44277c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
44287c478bd9Sstevel@tonic-gate prnode_t *pnp;
44297c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
44307c478bd9Sstevel@tonic-gate proc_t *p;
44317c478bd9Sstevel@tonic-gate uint_t fd, flags = 0;
44327c478bd9Sstevel@tonic-gate int c;
44337c478bd9Sstevel@tonic-gate uf_entry_t *ufp;
44347c478bd9Sstevel@tonic-gate uf_info_t *fip;
44357c478bd9Sstevel@tonic-gate enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
44367c478bd9Sstevel@tonic-gate char *tmp;
44377c478bd9Sstevel@tonic-gate int idx;
44387c478bd9Sstevel@tonic-gate struct seg *seg;
44397c478bd9Sstevel@tonic-gate struct as *as = NULL;
44407c478bd9Sstevel@tonic-gate vattr_t vattr;
44417c478bd9Sstevel@tonic-gate
44427c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_PATHDIR);
44437c478bd9Sstevel@tonic-gate
44447c478bd9Sstevel@tonic-gate /*
44457c478bd9Sstevel@tonic-gate * First, check if this is a numeric entry, in which case we have a
44467c478bd9Sstevel@tonic-gate * file descriptor.
44477c478bd9Sstevel@tonic-gate */
44487c478bd9Sstevel@tonic-gate fd = 0;
44497c478bd9Sstevel@tonic-gate type = NAME_FD;
44507c478bd9Sstevel@tonic-gate tmp = comp;
44517c478bd9Sstevel@tonic-gate while ((c = *tmp++) != '\0') {
44527c478bd9Sstevel@tonic-gate int ofd;
44537c478bd9Sstevel@tonic-gate if (c < '0' || c > '9') {
44547c478bd9Sstevel@tonic-gate type = NAME_UNKNOWN;
44557c478bd9Sstevel@tonic-gate break;
44567c478bd9Sstevel@tonic-gate }
44577c478bd9Sstevel@tonic-gate ofd = fd;
44587c478bd9Sstevel@tonic-gate fd = 10*fd + c - '0';
44597c478bd9Sstevel@tonic-gate if (fd/10 != ofd) { /* integer overflow */
44607c478bd9Sstevel@tonic-gate type = NAME_UNKNOWN;
44617c478bd9Sstevel@tonic-gate break;
44627c478bd9Sstevel@tonic-gate }
44637c478bd9Sstevel@tonic-gate }
44647c478bd9Sstevel@tonic-gate
44657c478bd9Sstevel@tonic-gate /*
44667c478bd9Sstevel@tonic-gate * Next, see if it is one of the special values {root, cwd}.
44677c478bd9Sstevel@tonic-gate */
44687c478bd9Sstevel@tonic-gate if (type == NAME_UNKNOWN) {
44697c478bd9Sstevel@tonic-gate if (strcmp(comp, "root") == 0)
44707c478bd9Sstevel@tonic-gate type = NAME_ROOT;
44717c478bd9Sstevel@tonic-gate else if (strcmp(comp, "cwd") == 0)
44727c478bd9Sstevel@tonic-gate type = NAME_CWD;
44737c478bd9Sstevel@tonic-gate }
44747c478bd9Sstevel@tonic-gate
44757c478bd9Sstevel@tonic-gate /*
44767c478bd9Sstevel@tonic-gate * Grab the necessary data from the process
44777c478bd9Sstevel@tonic-gate */
44787c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0)
44797c478bd9Sstevel@tonic-gate return (NULL);
44807c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
44817c478bd9Sstevel@tonic-gate
44827c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
44837c478bd9Sstevel@tonic-gate
44847c478bd9Sstevel@tonic-gate switch (type) {
44857c478bd9Sstevel@tonic-gate case NAME_ROOT:
44867c478bd9Sstevel@tonic-gate if ((vp = PTOU(p)->u_rdir) == NULL)
44877c478bd9Sstevel@tonic-gate vp = p->p_zone->zone_rootvp;
44887c478bd9Sstevel@tonic-gate VN_HOLD(vp);
44897c478bd9Sstevel@tonic-gate break;
44907c478bd9Sstevel@tonic-gate case NAME_CWD:
44917c478bd9Sstevel@tonic-gate vp = PTOU(p)->u_cdir;
44927c478bd9Sstevel@tonic-gate VN_HOLD(vp);
44937c478bd9Sstevel@tonic-gate break;
44947c478bd9Sstevel@tonic-gate default:
44957c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
44967c478bd9Sstevel@tonic-gate prunlock(dpnp);
44977c478bd9Sstevel@tonic-gate return (NULL);
44987c478bd9Sstevel@tonic-gate }
44997c478bd9Sstevel@tonic-gate }
45007c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
45017c478bd9Sstevel@tonic-gate
45027c478bd9Sstevel@tonic-gate /*
45037c478bd9Sstevel@tonic-gate * Determine if this is an object entry
45047c478bd9Sstevel@tonic-gate */
45057c478bd9Sstevel@tonic-gate if (type == NAME_UNKNOWN) {
45067c478bd9Sstevel@tonic-gate /*
45077c478bd9Sstevel@tonic-gate * Start with the inode index immediately after the number of
45087c478bd9Sstevel@tonic-gate * files.
45097c478bd9Sstevel@tonic-gate */
45107c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
45117c478bd9Sstevel@tonic-gate idx = fip->fi_nfiles + 4;
45127c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
45137c478bd9Sstevel@tonic-gate
45147c478bd9Sstevel@tonic-gate if (strcmp(comp, "a.out") == 0) {
45157c478bd9Sstevel@tonic-gate if (p->p_execdir != NULL) {
45167c478bd9Sstevel@tonic-gate vp = p->p_execdir;
45177c478bd9Sstevel@tonic-gate VN_HOLD(vp);
45187c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
45197c478bd9Sstevel@tonic-gate flags |= PR_AOUT;
45207c478bd9Sstevel@tonic-gate } else {
45217c478bd9Sstevel@tonic-gate vp = p->p_exec;
45227c478bd9Sstevel@tonic-gate VN_HOLD(vp);
45237c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
45247c478bd9Sstevel@tonic-gate }
45257c478bd9Sstevel@tonic-gate } else {
4526dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_READER);
45277c478bd9Sstevel@tonic-gate if ((seg = AS_SEGFIRST(as)) != NULL) {
45287c478bd9Sstevel@tonic-gate do {
45297c478bd9Sstevel@tonic-gate /*
45307c478bd9Sstevel@tonic-gate * Manufacture a filename for the
45317c478bd9Sstevel@tonic-gate * "object" directory.
45327c478bd9Sstevel@tonic-gate */
45337c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
45347c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
45357c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp)
45367c478bd9Sstevel@tonic-gate == 0 &&
45377c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
4538da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(),
4539da6c28aaSamw NULL) == 0) {
45407c478bd9Sstevel@tonic-gate char name[64];
45417c478bd9Sstevel@tonic-gate
45427c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
45437c478bd9Sstevel@tonic-gate continue;
45447c478bd9Sstevel@tonic-gate idx++;
45457c478bd9Sstevel@tonic-gate pr_object_name(name, vp,
45467c478bd9Sstevel@tonic-gate &vattr);
45477c478bd9Sstevel@tonic-gate if (strcmp(name, comp) == 0)
45487c478bd9Sstevel@tonic-gate break;
45497c478bd9Sstevel@tonic-gate }
45507c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
45517c478bd9Sstevel@tonic-gate }
45527c478bd9Sstevel@tonic-gate
45537c478bd9Sstevel@tonic-gate if (seg == NULL) {
45547c478bd9Sstevel@tonic-gate vp = NULL;
45557c478bd9Sstevel@tonic-gate } else {
45567c478bd9Sstevel@tonic-gate VN_HOLD(vp);
45577c478bd9Sstevel@tonic-gate type = NAME_OBJECT;
45587c478bd9Sstevel@tonic-gate }
45597c478bd9Sstevel@tonic-gate
4560dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
45617c478bd9Sstevel@tonic-gate }
45627c478bd9Sstevel@tonic-gate }
45637c478bd9Sstevel@tonic-gate
45647c478bd9Sstevel@tonic-gate
45657c478bd9Sstevel@tonic-gate switch (type) {
45667c478bd9Sstevel@tonic-gate case NAME_FD:
45677c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
45687c478bd9Sstevel@tonic-gate if (fd < fip->fi_nfiles) {
45697c478bd9Sstevel@tonic-gate UF_ENTER(ufp, fip, fd);
45707c478bd9Sstevel@tonic-gate if (ufp->uf_file != NULL) {
45717c478bd9Sstevel@tonic-gate vp = ufp->uf_file->f_vnode;
45727c478bd9Sstevel@tonic-gate VN_HOLD(vp);
45737c478bd9Sstevel@tonic-gate }
45747c478bd9Sstevel@tonic-gate UF_EXIT(ufp);
45757c478bd9Sstevel@tonic-gate }
45767c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
45777c478bd9Sstevel@tonic-gate idx = fd + 4;
45787c478bd9Sstevel@tonic-gate break;
45797c478bd9Sstevel@tonic-gate case NAME_ROOT:
45807c478bd9Sstevel@tonic-gate idx = 2;
45817c478bd9Sstevel@tonic-gate break;
45827c478bd9Sstevel@tonic-gate case NAME_CWD:
45837c478bd9Sstevel@tonic-gate idx = 3;
45847c478bd9Sstevel@tonic-gate break;
45857c478bd9Sstevel@tonic-gate case NAME_OBJECT:
45867c478bd9Sstevel@tonic-gate case NAME_UNKNOWN:
45877c478bd9Sstevel@tonic-gate /* Nothing to do */
45887c478bd9Sstevel@tonic-gate break;
45897c478bd9Sstevel@tonic-gate }
45907c478bd9Sstevel@tonic-gate
45917c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
45927c478bd9Sstevel@tonic-gate prunlock(dpnp);
45937c478bd9Sstevel@tonic-gate
45947c478bd9Sstevel@tonic-gate if (vp != NULL) {
45957c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_PATH);
45967c478bd9Sstevel@tonic-gate
45977c478bd9Sstevel@tonic-gate pnp->pr_flags |= flags;
45987c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
45997c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
46007c478bd9Sstevel@tonic-gate pnp->pr_realvp = vp;
46017c478bd9Sstevel@tonic-gate pnp->pr_parent = dp; /* needed for prlookup */
46027c478bd9Sstevel@tonic-gate pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
46037c478bd9Sstevel@tonic-gate VN_HOLD(dp);
46047c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
46057c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
46067c478bd9Sstevel@tonic-gate }
46077c478bd9Sstevel@tonic-gate
46087c478bd9Sstevel@tonic-gate return (vp);
46097c478bd9Sstevel@tonic-gate }
46107c478bd9Sstevel@tonic-gate
46117c478bd9Sstevel@tonic-gate /*
46127c478bd9Sstevel@tonic-gate * Look up one of the process's active templates.
46137c478bd9Sstevel@tonic-gate */
46147c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_tmpldir(vnode_t * dp,char * comp)46157c478bd9Sstevel@tonic-gate pr_lookup_tmpldir(vnode_t *dp, char *comp)
46167c478bd9Sstevel@tonic-gate {
46177c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
46187c478bd9Sstevel@tonic-gate prnode_t *pnp;
46197c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
46207c478bd9Sstevel@tonic-gate proc_t *p;
46217c478bd9Sstevel@tonic-gate int i;
46227c478bd9Sstevel@tonic-gate
46237c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_TMPLDIR);
46247c478bd9Sstevel@tonic-gate
46257c478bd9Sstevel@tonic-gate for (i = 0; i < ct_ntypes; i++)
46267c478bd9Sstevel@tonic-gate if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
46277c478bd9Sstevel@tonic-gate break;
46287c478bd9Sstevel@tonic-gate if (i == ct_ntypes)
46297c478bd9Sstevel@tonic-gate return (NULL);
46307c478bd9Sstevel@tonic-gate
46317c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_TMPL);
46327c478bd9Sstevel@tonic-gate
46337c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
46347c478bd9Sstevel@tonic-gate prfreenode(pnp);
46357c478bd9Sstevel@tonic-gate return (NULL);
46367c478bd9Sstevel@tonic-gate }
46377c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
46387c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas ||
46397c478bd9Sstevel@tonic-gate (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
46407c478bd9Sstevel@tonic-gate prunlock(dpnp);
46417c478bd9Sstevel@tonic-gate prfreenode(pnp);
46427c478bd9Sstevel@tonic-gate return (NULL);
46437c478bd9Sstevel@tonic-gate }
46447c478bd9Sstevel@tonic-gate if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
46457c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
46467c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
46477c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
46487c478bd9Sstevel@tonic-gate pnp->pr_cttype = i;
46497c478bd9Sstevel@tonic-gate VN_HOLD(dp);
46507c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
46517c478bd9Sstevel@tonic-gate } else {
46527c478bd9Sstevel@tonic-gate prfreenode(pnp);
46537c478bd9Sstevel@tonic-gate }
46547c478bd9Sstevel@tonic-gate prunlock(dpnp);
46557c478bd9Sstevel@tonic-gate
46567c478bd9Sstevel@tonic-gate return (vp);
46577c478bd9Sstevel@tonic-gate }
46587c478bd9Sstevel@tonic-gate
46597c478bd9Sstevel@tonic-gate /*
46607c478bd9Sstevel@tonic-gate * Look up one of the contracts owned by the process.
46617c478bd9Sstevel@tonic-gate */
46627c478bd9Sstevel@tonic-gate static vnode_t *
pr_lookup_ctdir(vnode_t * dp,char * comp)46637c478bd9Sstevel@tonic-gate pr_lookup_ctdir(vnode_t *dp, char *comp)
46647c478bd9Sstevel@tonic-gate {
46657c478bd9Sstevel@tonic-gate prnode_t *dpnp = VTOP(dp);
46667c478bd9Sstevel@tonic-gate prnode_t *pnp;
46677c478bd9Sstevel@tonic-gate vnode_t *vp = NULL;
46687c478bd9Sstevel@tonic-gate proc_t *p;
46697c478bd9Sstevel@tonic-gate id_t id = 0;
46707c478bd9Sstevel@tonic-gate contract_t *ct;
46717c478bd9Sstevel@tonic-gate int c;
46727c478bd9Sstevel@tonic-gate
46737c478bd9Sstevel@tonic-gate ASSERT(dpnp->pr_type == PR_CTDIR);
46747c478bd9Sstevel@tonic-gate
46757c478bd9Sstevel@tonic-gate while ((c = *comp++) != '\0') {
46767c478bd9Sstevel@tonic-gate id_t oid;
46777c478bd9Sstevel@tonic-gate if (c < '0' || c > '9')
46787c478bd9Sstevel@tonic-gate return (NULL);
46797c478bd9Sstevel@tonic-gate oid = id;
46807c478bd9Sstevel@tonic-gate id = 10 * id + c - '0';
46817c478bd9Sstevel@tonic-gate if (id / 10 != oid) /* integer overflow */
46827c478bd9Sstevel@tonic-gate return (NULL);
46837c478bd9Sstevel@tonic-gate }
46847c478bd9Sstevel@tonic-gate
46857c478bd9Sstevel@tonic-gate /*
46867c478bd9Sstevel@tonic-gate * Search all contracts; we'll filter below.
46877c478bd9Sstevel@tonic-gate */
46887c478bd9Sstevel@tonic-gate ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
46897c478bd9Sstevel@tonic-gate if (ct == NULL)
46907c478bd9Sstevel@tonic-gate return (NULL);
46917c478bd9Sstevel@tonic-gate
46927c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_CT);
46937c478bd9Sstevel@tonic-gate
46947c478bd9Sstevel@tonic-gate if (prlock(dpnp, ZNO) != 0) {
46957c478bd9Sstevel@tonic-gate prfreenode(pnp);
46967c478bd9Sstevel@tonic-gate contract_rele(ct);
46977c478bd9Sstevel@tonic-gate return (NULL);
46987c478bd9Sstevel@tonic-gate }
46997c478bd9Sstevel@tonic-gate p = dpnp->pr_common->prc_proc;
47007c478bd9Sstevel@tonic-gate /*
47017c478bd9Sstevel@tonic-gate * We only allow lookups of contracts owned by this process, or,
47027c478bd9Sstevel@tonic-gate * if we are zsched and this is a zone's procfs, contracts on
47037c478bd9Sstevel@tonic-gate * stuff in the zone which are held by processes or contracts
47047c478bd9Sstevel@tonic-gate * outside the zone. (see logic in contract_status_common)
47057c478bd9Sstevel@tonic-gate */
47067c478bd9Sstevel@tonic-gate if ((ct->ct_owner != p) &&
4707fa9e4066Sahrens !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4708fa9e4066Sahrens VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4709fa9e4066Sahrens VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
47107c478bd9Sstevel@tonic-gate ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
47117c478bd9Sstevel@tonic-gate prunlock(dpnp);
47127c478bd9Sstevel@tonic-gate prfreenode(pnp);
47137c478bd9Sstevel@tonic-gate contract_rele(ct);
47147c478bd9Sstevel@tonic-gate return (NULL);
47157c478bd9Sstevel@tonic-gate }
47167c478bd9Sstevel@tonic-gate pnp->pr_common = dpnp->pr_common;
47177c478bd9Sstevel@tonic-gate pnp->pr_pcommon = dpnp->pr_pcommon;
47187c478bd9Sstevel@tonic-gate pnp->pr_contract = ct;
47197c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
47207c478bd9Sstevel@tonic-gate pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
47217c478bd9Sstevel@tonic-gate VN_HOLD(dp);
47227c478bd9Sstevel@tonic-gate prunlock(dpnp);
47237c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
47247c478bd9Sstevel@tonic-gate
47257c478bd9Sstevel@tonic-gate return (vp);
47267c478bd9Sstevel@tonic-gate }
47277c478bd9Sstevel@tonic-gate
47287c478bd9Sstevel@tonic-gate /*
47297c478bd9Sstevel@tonic-gate * Construct an lwp vnode for the old /proc interface.
47307c478bd9Sstevel@tonic-gate * We stand on our head to make the /proc plumbing correct.
47317c478bd9Sstevel@tonic-gate */
47327c478bd9Sstevel@tonic-gate vnode_t *
prlwpnode(prnode_t * pnp,uint_t tid)47337c478bd9Sstevel@tonic-gate prlwpnode(prnode_t *pnp, uint_t tid)
47347c478bd9Sstevel@tonic-gate {
47357c478bd9Sstevel@tonic-gate char comp[12];
47367c478bd9Sstevel@tonic-gate vnode_t *dp;
47377c478bd9Sstevel@tonic-gate vnode_t *vp;
47387c478bd9Sstevel@tonic-gate prcommon_t *pcp;
47397c478bd9Sstevel@tonic-gate proc_t *p;
47407c478bd9Sstevel@tonic-gate
47417c478bd9Sstevel@tonic-gate /*
47427c478bd9Sstevel@tonic-gate * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
47437c478bd9Sstevel@tonic-gate */
47447c478bd9Sstevel@tonic-gate if (pnp->pr_type == PR_PIDFILE) {
47457c478bd9Sstevel@tonic-gate dp = pnp->pr_parent; /* /proc/<pid> */
47467c478bd9Sstevel@tonic-gate VN_HOLD(dp);
47477c478bd9Sstevel@tonic-gate vp = pr_lookup_piddir(dp, "lwp");
47487c478bd9Sstevel@tonic-gate VN_RELE(dp);
47497c478bd9Sstevel@tonic-gate if ((dp = vp) == NULL) /* /proc/<pid>/lwp */
47507c478bd9Sstevel@tonic-gate return (NULL);
47517c478bd9Sstevel@tonic-gate } else if (pnp->pr_type == PR_LWPIDFILE) {
47527c478bd9Sstevel@tonic-gate dp = pnp->pr_parent; /* /proc/<pid>/lwp/<lwpid> */
47537c478bd9Sstevel@tonic-gate dp = VTOP(dp)->pr_parent; /* /proc/<pid>/lwp */
47547c478bd9Sstevel@tonic-gate VN_HOLD(dp);
47557c478bd9Sstevel@tonic-gate } else {
47567c478bd9Sstevel@tonic-gate return (NULL);
47577c478bd9Sstevel@tonic-gate }
47587c478bd9Sstevel@tonic-gate
47597c478bd9Sstevel@tonic-gate (void) pr_u32tos(tid, comp, sizeof (comp));
47607c478bd9Sstevel@tonic-gate vp = pr_lookup_lwpdir(dp, comp);
47617c478bd9Sstevel@tonic-gate VN_RELE(dp);
47627c478bd9Sstevel@tonic-gate if ((dp = vp) == NULL)
47637c478bd9Sstevel@tonic-gate return (NULL);
47647c478bd9Sstevel@tonic-gate
47657c478bd9Sstevel@tonic-gate pnp = prgetnode(dp, PR_LWPIDFILE);
47667c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
47677c478bd9Sstevel@tonic-gate
47687c478bd9Sstevel@tonic-gate /*
47697c478bd9Sstevel@tonic-gate * prgetnode() initialized most of the prnode.
47707c478bd9Sstevel@tonic-gate * Finish the job.
47717c478bd9Sstevel@tonic-gate */
47727c478bd9Sstevel@tonic-gate pcp = VTOP(dp)->pr_common;
47737c478bd9Sstevel@tonic-gate pnp->pr_ino = ptoi(pcp->prc_pid);
47747c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
47757c478bd9Sstevel@tonic-gate pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
47767c478bd9Sstevel@tonic-gate pnp->pr_parent = dp;
47777c478bd9Sstevel@tonic-gate /*
47787c478bd9Sstevel@tonic-gate * Link new vnode into list of all /proc vnodes for the process.
47797c478bd9Sstevel@tonic-gate */
47807c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
47817c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
47827c478bd9Sstevel@tonic-gate if (p == NULL) {
47837c478bd9Sstevel@tonic-gate VN_RELE(dp);
47847c478bd9Sstevel@tonic-gate prfreenode(pnp);
47857c478bd9Sstevel@tonic-gate vp = NULL;
47867c478bd9Sstevel@tonic-gate } else if (pcp->prc_thread == NULL) {
47877c478bd9Sstevel@tonic-gate prunlock(pnp);
47887c478bd9Sstevel@tonic-gate VN_RELE(dp);
47897c478bd9Sstevel@tonic-gate prfreenode(pnp);
47907c478bd9Sstevel@tonic-gate vp = NULL;
47917c478bd9Sstevel@tonic-gate } else {
47927c478bd9Sstevel@tonic-gate pnp->pr_next = p->p_plist;
47937c478bd9Sstevel@tonic-gate p->p_plist = vp;
47947c478bd9Sstevel@tonic-gate prunlock(pnp);
47957c478bd9Sstevel@tonic-gate }
47967c478bd9Sstevel@tonic-gate
47977c478bd9Sstevel@tonic-gate return (vp);
47987c478bd9Sstevel@tonic-gate }
47997c478bd9Sstevel@tonic-gate
48007c478bd9Sstevel@tonic-gate #if defined(DEBUG)
48017c478bd9Sstevel@tonic-gate
48027c478bd9Sstevel@tonic-gate static uint32_t nprnode;
48037c478bd9Sstevel@tonic-gate static uint32_t nprcommon;
48047c478bd9Sstevel@tonic-gate
48051a5e258fSJosef 'Jeff' Sipek #define INCREMENT(x) atomic_inc_32(&x);
48061a5e258fSJosef 'Jeff' Sipek #define DECREMENT(x) atomic_dec_32(&x);
48077c478bd9Sstevel@tonic-gate
48087c478bd9Sstevel@tonic-gate #else
48097c478bd9Sstevel@tonic-gate
48107c478bd9Sstevel@tonic-gate #define INCREMENT(x)
48117c478bd9Sstevel@tonic-gate #define DECREMENT(x)
48127c478bd9Sstevel@tonic-gate
48137c478bd9Sstevel@tonic-gate #endif /* DEBUG */
48147c478bd9Sstevel@tonic-gate
48157c478bd9Sstevel@tonic-gate /*
48167c478bd9Sstevel@tonic-gate * New /proc vnode required; allocate it and fill in most of the fields.
48177c478bd9Sstevel@tonic-gate */
48187c478bd9Sstevel@tonic-gate prnode_t *
prgetnode(vnode_t * dp,prnodetype_t type)48197c478bd9Sstevel@tonic-gate prgetnode(vnode_t *dp, prnodetype_t type)
48207c478bd9Sstevel@tonic-gate {
48217c478bd9Sstevel@tonic-gate prnode_t *pnp;
48227c478bd9Sstevel@tonic-gate prcommon_t *pcp;
48237c478bd9Sstevel@tonic-gate vnode_t *vp;
48247c478bd9Sstevel@tonic-gate ulong_t nfiles;
48257c478bd9Sstevel@tonic-gate
48267c478bd9Sstevel@tonic-gate INCREMENT(nprnode);
48277c478bd9Sstevel@tonic-gate pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
48287c478bd9Sstevel@tonic-gate
48297c478bd9Sstevel@tonic-gate mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
48307c478bd9Sstevel@tonic-gate pnp->pr_type = type;
48317c478bd9Sstevel@tonic-gate
48327c478bd9Sstevel@tonic-gate pnp->pr_vnode = vn_alloc(KM_SLEEP);
48337c478bd9Sstevel@tonic-gate
48347c478bd9Sstevel@tonic-gate vp = PTOV(pnp);
48357c478bd9Sstevel@tonic-gate vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
48367c478bd9Sstevel@tonic-gate vn_setops(vp, prvnodeops);
48377c478bd9Sstevel@tonic-gate vp->v_vfsp = dp->v_vfsp;
48387c478bd9Sstevel@tonic-gate vp->v_type = VPROC;
48397c478bd9Sstevel@tonic-gate vp->v_data = (caddr_t)pnp;
48407c478bd9Sstevel@tonic-gate
48417c478bd9Sstevel@tonic-gate switch (type) {
48427c478bd9Sstevel@tonic-gate case PR_PIDDIR:
48437c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
48447c478bd9Sstevel@tonic-gate /*
48457c478bd9Sstevel@tonic-gate * We need a prcommon and a files array for each of these.
48467c478bd9Sstevel@tonic-gate */
48477c478bd9Sstevel@tonic-gate INCREMENT(nprcommon);
48487c478bd9Sstevel@tonic-gate
48497c478bd9Sstevel@tonic-gate pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
48507c478bd9Sstevel@tonic-gate pcp->prc_refcnt = 1;
48517c478bd9Sstevel@tonic-gate pnp->pr_common = pcp;
48527c478bd9Sstevel@tonic-gate mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
48537c478bd9Sstevel@tonic-gate cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
48547c478bd9Sstevel@tonic-gate
48557c478bd9Sstevel@tonic-gate nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
48567c478bd9Sstevel@tonic-gate pnp->pr_files =
48577c478bd9Sstevel@tonic-gate kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
48587c478bd9Sstevel@tonic-gate
48597c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
48607c478bd9Sstevel@tonic-gate /*
48617c478bd9Sstevel@tonic-gate * Mode should be read-search by all, but we cannot so long
48627c478bd9Sstevel@tonic-gate * as we must support compatibility mode with old /proc.
48637c478bd9Sstevel@tonic-gate * Make /proc/<pid> be read by owner only, search by all.
48647c478bd9Sstevel@tonic-gate * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
48657c478bd9Sstevel@tonic-gate * set VDIROPEN on /proc/<pid> so it can be opened for writing.
48667c478bd9Sstevel@tonic-gate */
48677c478bd9Sstevel@tonic-gate if (type == PR_PIDDIR) {
48687c478bd9Sstevel@tonic-gate /* kludge for old /proc interface */
48697c478bd9Sstevel@tonic-gate prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
48707c478bd9Sstevel@tonic-gate pnp->pr_pidfile = PTOV(xpnp);
48717c478bd9Sstevel@tonic-gate pnp->pr_mode = 0511;
48727c478bd9Sstevel@tonic-gate vp->v_flag |= VDIROPEN;
48737c478bd9Sstevel@tonic-gate } else {
48747c478bd9Sstevel@tonic-gate pnp->pr_mode = 0555;
48757c478bd9Sstevel@tonic-gate }
48767c478bd9Sstevel@tonic-gate
48777c478bd9Sstevel@tonic-gate break;
48787c478bd9Sstevel@tonic-gate
48797c478bd9Sstevel@tonic-gate case PR_CURDIR:
48807c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
48817c478bd9Sstevel@tonic-gate case PR_FDDIR:
4882a02120c4SAndy Fiddaman case PR_FDINFODIR:
48837c478bd9Sstevel@tonic-gate case PR_OBJECTDIR:
48847c478bd9Sstevel@tonic-gate case PR_PATHDIR:
48857c478bd9Sstevel@tonic-gate case PR_CTDIR:
48867c478bd9Sstevel@tonic-gate case PR_TMPLDIR:
48877c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
48887c478bd9Sstevel@tonic-gate pnp->pr_mode = 0500; /* read-search by owner only */
48897c478bd9Sstevel@tonic-gate break;
48907c478bd9Sstevel@tonic-gate
48917c478bd9Sstevel@tonic-gate case PR_CT:
48927c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
48937c478bd9Sstevel@tonic-gate pnp->pr_mode = 0500; /* read-search by owner only */
48947c478bd9Sstevel@tonic-gate break;
48957c478bd9Sstevel@tonic-gate
48967c478bd9Sstevel@tonic-gate case PR_PATH:
48977c478bd9Sstevel@tonic-gate case PR_SELF:
48987c478bd9Sstevel@tonic-gate vp->v_type = VLNK;
48997c478bd9Sstevel@tonic-gate pnp->pr_mode = 0777;
49007c478bd9Sstevel@tonic-gate break;
49017c478bd9Sstevel@tonic-gate
49027c478bd9Sstevel@tonic-gate case PR_LWPDIR:
49037c478bd9Sstevel@tonic-gate vp->v_type = VDIR;
49047c478bd9Sstevel@tonic-gate pnp->pr_mode = 0555; /* read-search by all */
49057c478bd9Sstevel@tonic-gate break;
49067c478bd9Sstevel@tonic-gate
49077c478bd9Sstevel@tonic-gate case PR_AS:
49087c478bd9Sstevel@tonic-gate case PR_TMPL:
49097c478bd9Sstevel@tonic-gate pnp->pr_mode = 0600; /* read-write by owner only */
49107c478bd9Sstevel@tonic-gate break;
49117c478bd9Sstevel@tonic-gate
49127c478bd9Sstevel@tonic-gate case PR_CTL:
49137c478bd9Sstevel@tonic-gate case PR_LWPCTL:
49147c478bd9Sstevel@tonic-gate pnp->pr_mode = 0200; /* write-only by owner only */
49157c478bd9Sstevel@tonic-gate break;
49167c478bd9Sstevel@tonic-gate
49177c478bd9Sstevel@tonic-gate case PR_PIDFILE:
49187c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
49197c478bd9Sstevel@tonic-gate pnp->pr_mode = 0600; /* read-write by owner only */
49207c478bd9Sstevel@tonic-gate break;
49217c478bd9Sstevel@tonic-gate
4922ab618543SJohn Levon case PR_LWPNAME:
4923ab618543SJohn Levon pnp->pr_mode = 0644; /* readable by all + owner can write */
4924ab618543SJohn Levon break;
4925ab618543SJohn Levon
49267c478bd9Sstevel@tonic-gate case PR_PSINFO:
49277c478bd9Sstevel@tonic-gate case PR_LPSINFO:
49287c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
49297c478bd9Sstevel@tonic-gate case PR_USAGE:
49307c478bd9Sstevel@tonic-gate case PR_LUSAGE:
49317c478bd9Sstevel@tonic-gate case PR_LWPUSAGE:
49327c478bd9Sstevel@tonic-gate pnp->pr_mode = 0444; /* read-only by all */
49337c478bd9Sstevel@tonic-gate break;
49347c478bd9Sstevel@tonic-gate
49357c478bd9Sstevel@tonic-gate default:
49367c478bd9Sstevel@tonic-gate pnp->pr_mode = 0400; /* read-only by owner only */
49377c478bd9Sstevel@tonic-gate break;
49387c478bd9Sstevel@tonic-gate }
49397c478bd9Sstevel@tonic-gate vn_exists(vp);
49407c478bd9Sstevel@tonic-gate return (pnp);
49417c478bd9Sstevel@tonic-gate }
49427c478bd9Sstevel@tonic-gate
49437c478bd9Sstevel@tonic-gate /*
49447c478bd9Sstevel@tonic-gate * Free the storage obtained from prgetnode().
49457c478bd9Sstevel@tonic-gate */
49467c478bd9Sstevel@tonic-gate void
prfreenode(prnode_t * pnp)49477c478bd9Sstevel@tonic-gate prfreenode(prnode_t *pnp)
49487c478bd9Sstevel@tonic-gate {
49497c478bd9Sstevel@tonic-gate vnode_t *vp;
49507c478bd9Sstevel@tonic-gate ulong_t nfiles;
49517c478bd9Sstevel@tonic-gate
49527c478bd9Sstevel@tonic-gate vn_invalid(PTOV(pnp));
49537c478bd9Sstevel@tonic-gate vn_free(PTOV(pnp));
49547c478bd9Sstevel@tonic-gate mutex_destroy(&pnp->pr_mutex);
49557c478bd9Sstevel@tonic-gate
49567c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
49577c478bd9Sstevel@tonic-gate case PR_PIDDIR:
49587c478bd9Sstevel@tonic-gate /* kludge for old /proc interface */
49597c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
49607c478bd9Sstevel@tonic-gate prfreenode(VTOP(pnp->pr_pidfile));
49617c478bd9Sstevel@tonic-gate pnp->pr_pidfile = NULL;
49627c478bd9Sstevel@tonic-gate }
49637c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
49647c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
49657c478bd9Sstevel@tonic-gate /*
49667c478bd9Sstevel@tonic-gate * We allocated a prcommon and a files array for each of these.
49677c478bd9Sstevel@tonic-gate */
49687c478bd9Sstevel@tonic-gate prfreecommon(pnp->pr_common);
49697c478bd9Sstevel@tonic-gate nfiles = (pnp->pr_type == PR_PIDDIR)?
49707c478bd9Sstevel@tonic-gate NPIDDIRFILES : NLWPIDDIRFILES;
49717c478bd9Sstevel@tonic-gate kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
49727c478bd9Sstevel@tonic-gate break;
49737c478bd9Sstevel@tonic-gate default:
49747c478bd9Sstevel@tonic-gate break;
49757c478bd9Sstevel@tonic-gate }
49767c478bd9Sstevel@tonic-gate /*
49777c478bd9Sstevel@tonic-gate * If there is an underlying vnode, be sure
49787c478bd9Sstevel@tonic-gate * to release it after freeing the prnode.
49797c478bd9Sstevel@tonic-gate */
49807c478bd9Sstevel@tonic-gate vp = pnp->pr_realvp;
49817c478bd9Sstevel@tonic-gate kmem_free(pnp, sizeof (*pnp));
49827c478bd9Sstevel@tonic-gate DECREMENT(nprnode);
49837c478bd9Sstevel@tonic-gate if (vp != NULL) {
49847c478bd9Sstevel@tonic-gate VN_RELE(vp);
49857c478bd9Sstevel@tonic-gate }
49867c478bd9Sstevel@tonic-gate }
49877c478bd9Sstevel@tonic-gate
49887c478bd9Sstevel@tonic-gate /*
4989da6c28aaSamw * Free a prcommon structure, if the reference count reaches zero.
49907c478bd9Sstevel@tonic-gate */
49917c478bd9Sstevel@tonic-gate static void
prfreecommon(prcommon_t * pcp)49927c478bd9Sstevel@tonic-gate prfreecommon(prcommon_t *pcp)
49937c478bd9Sstevel@tonic-gate {
49947c478bd9Sstevel@tonic-gate mutex_enter(&pcp->prc_mutex);
49957c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt > 0);
49967c478bd9Sstevel@tonic-gate if (--pcp->prc_refcnt != 0)
49977c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
49987c478bd9Sstevel@tonic-gate else {
49997c478bd9Sstevel@tonic-gate mutex_exit(&pcp->prc_mutex);
50002c76d751SPatrick Mooney
50017c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_refcnt == 0);
50027c478bd9Sstevel@tonic-gate ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
50032c76d751SPatrick Mooney
50042c76d751SPatrick Mooney pollhead_clean(&pcp->prc_pollhead);
50057c478bd9Sstevel@tonic-gate mutex_destroy(&pcp->prc_mutex);
50067c478bd9Sstevel@tonic-gate cv_destroy(&pcp->prc_wait);
50077c478bd9Sstevel@tonic-gate kmem_free(pcp, sizeof (prcommon_t));
50087c478bd9Sstevel@tonic-gate DECREMENT(nprcommon);
50097c478bd9Sstevel@tonic-gate }
50107c478bd9Sstevel@tonic-gate }
50117c478bd9Sstevel@tonic-gate
50127c478bd9Sstevel@tonic-gate /*
50137c478bd9Sstevel@tonic-gate * Array of readdir functions, indexed by /proc file type.
50147c478bd9Sstevel@tonic-gate */
50157c478bd9Sstevel@tonic-gate static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
50167c478bd9Sstevel@tonic-gate pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
5017a02120c4SAndy Fiddaman pr_readdir_fddir(), pr_readdir_fdinfodir(), pr_readdir_pathdir(),
5018a02120c4SAndy Fiddaman pr_readdir_tmpldir(), pr_readdir_ctdir();
50197c478bd9Sstevel@tonic-gate
50207c478bd9Sstevel@tonic-gate static int (*pr_readdir_function[PR_NFILES])() = {
50217c478bd9Sstevel@tonic-gate pr_readdir_procdir, /* /proc */
50227c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/self */
50237c478bd9Sstevel@tonic-gate pr_readdir_piddir, /* /proc/<pid> */
50247c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/as */
50257c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/ctl */
50267c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/status */
50277c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lstatus */
50287c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/psinfo */
50297c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
50307c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/map */
50317c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/rmap */
50327c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/xmap */
50337c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/cred */
50347c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/sigact */
50357c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/auxv */
50367c478bd9Sstevel@tonic-gate #if defined(__x86)
50377c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/ldt */
50387c478bd9Sstevel@tonic-gate #endif
50397c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/usage */
50407c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lusage */
50417c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/pagedata */
50427c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/watch */
50437c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/cwd */
50447c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/root */
50457c478bd9Sstevel@tonic-gate pr_readdir_fddir, /* /proc/<pid>/fd */
50467c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/fd/nn */
5047a02120c4SAndy Fiddaman pr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */
5048a02120c4SAndy Fiddaman pr_readdir_notdir, /* /proc/<pid>/fdinfo/nn */
50497c478bd9Sstevel@tonic-gate pr_readdir_objectdir, /* /proc/<pid>/object */
50507c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/object/xxx */
50517c478bd9Sstevel@tonic-gate pr_readdir_lwpdir, /* /proc/<pid>/lwp */
50527c478bd9Sstevel@tonic-gate pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
50537c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
5054ab618543SJohn Levon pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
50557c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
50567c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
50577c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
50587c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
50597c478bd9Sstevel@tonic-gate pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
50607c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
5061f971a346SBryan Cantrill pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
50627c478bd9Sstevel@tonic-gate #if defined(__sparc)
50637c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
50647c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
50657c478bd9Sstevel@tonic-gate #endif
50667c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/priv */
50677c478bd9Sstevel@tonic-gate pr_readdir_pathdir, /* /proc/<pid>/path */
50687c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/path/xxx */
50697c478bd9Sstevel@tonic-gate pr_readdir_ctdir, /* /proc/<pid>/contracts */
50707c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* /proc/<pid>/contracts/<ctid> */
5071d2a70789SRichard Lowe pr_readdir_notdir, /* /proc/<pid>/secflags */
50727c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old process file */
50737c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old lwp file */
50747c478bd9Sstevel@tonic-gate pr_readdir_notdir, /* old pagedata file */
50757c478bd9Sstevel@tonic-gate };
50767c478bd9Sstevel@tonic-gate
50777c478bd9Sstevel@tonic-gate /* ARGSUSED */
50787c478bd9Sstevel@tonic-gate static int
prreaddir(vnode_t * vp,uio_t * uiop,cred_t * cr,int * eofp,caller_context_t * ct,int flags)5079da6c28aaSamw prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
5080da6c28aaSamw caller_context_t *ct, int flags)
50817c478bd9Sstevel@tonic-gate {
50827c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
50837c478bd9Sstevel@tonic-gate
50847c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
50857c478bd9Sstevel@tonic-gate
5086da6c28aaSamw /* XXX - Do we need to pass ct and flags? */
50877c478bd9Sstevel@tonic-gate return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
50887c478bd9Sstevel@tonic-gate }
50897c478bd9Sstevel@tonic-gate
50907c478bd9Sstevel@tonic-gate /* ARGSUSED */
50917c478bd9Sstevel@tonic-gate static int
pr_readdir_notdir(prnode_t * pnp,uio_t * uiop,int * eofp)50927c478bd9Sstevel@tonic-gate pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
50937c478bd9Sstevel@tonic-gate {
50947c478bd9Sstevel@tonic-gate return (ENOTDIR);
50957c478bd9Sstevel@tonic-gate }
50967c478bd9Sstevel@tonic-gate
50977c478bd9Sstevel@tonic-gate /* ARGSUSED */
50987c478bd9Sstevel@tonic-gate static int
pr_readdir_procdir(prnode_t * pnp,uio_t * uiop,int * eofp)50997c478bd9Sstevel@tonic-gate pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
51007c478bd9Sstevel@tonic-gate {
51017c478bd9Sstevel@tonic-gate zoneid_t zoneid;
51027c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
51037c478bd9Sstevel@tonic-gate int error, eof = 0;
51047c478bd9Sstevel@tonic-gate offset_t n;
51057c478bd9Sstevel@tonic-gate
51067c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PROCDIR);
51077c478bd9Sstevel@tonic-gate
5108fa9e4066Sahrens zoneid = VTOZONE(PTOV(pnp))->zone_id;
51097c478bd9Sstevel@tonic-gate
51107c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
5111b38f0970Sck153898 PRROOTINO, PRROOTINO, 0)) != 0)
51127c478bd9Sstevel@tonic-gate return (error);
51137c478bd9Sstevel@tonic-gate
51147c478bd9Sstevel@tonic-gate /*
51157c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until all processes
51167c478bd9Sstevel@tonic-gate * have been examined.
51177c478bd9Sstevel@tonic-gate */
51187c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
51197c478bd9Sstevel@tonic-gate uint_t pid;
51207c478bd9Sstevel@tonic-gate int pslot;
51217c478bd9Sstevel@tonic-gate proc_t *p;
51227c478bd9Sstevel@tonic-gate
51237c478bd9Sstevel@tonic-gate /*
51247c478bd9Sstevel@tonic-gate * Find next entry. Skip processes not visible where
51257c478bd9Sstevel@tonic-gate * this /proc was mounted.
51267c478bd9Sstevel@tonic-gate */
51277c478bd9Sstevel@tonic-gate mutex_enter(&pidlock);
51287c478bd9Sstevel@tonic-gate while (n < v.v_proc &&
51297c478bd9Sstevel@tonic-gate ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
51307c478bd9Sstevel@tonic-gate (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
51317c478bd9Sstevel@tonic-gate secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
51327c478bd9Sstevel@tonic-gate n++;
51337c478bd9Sstevel@tonic-gate
51347c478bd9Sstevel@tonic-gate /*
51357c478bd9Sstevel@tonic-gate * Stop when entire proc table has been examined.
51367c478bd9Sstevel@tonic-gate */
51377c478bd9Sstevel@tonic-gate if (n >= v.v_proc) {
51387c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
51397c478bd9Sstevel@tonic-gate eof = 1;
51407c478bd9Sstevel@tonic-gate break;
51417c478bd9Sstevel@tonic-gate }
51427c478bd9Sstevel@tonic-gate
51437c478bd9Sstevel@tonic-gate ASSERT(p->p_stat != 0);
51447c478bd9Sstevel@tonic-gate pid = p->p_pid;
51457c478bd9Sstevel@tonic-gate pslot = p->p_slot;
51467c478bd9Sstevel@tonic-gate mutex_exit(&pidlock);
51477c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, n,
51487c478bd9Sstevel@tonic-gate pmkino(0, pslot, PR_PIDDIR), pid);
51497c478bd9Sstevel@tonic-gate if (error)
51507c478bd9Sstevel@tonic-gate break;
51517c478bd9Sstevel@tonic-gate }
51527c478bd9Sstevel@tonic-gate
51537c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
51547c478bd9Sstevel@tonic-gate }
51557c478bd9Sstevel@tonic-gate
51567c478bd9Sstevel@tonic-gate /* ARGSUSED */
51577c478bd9Sstevel@tonic-gate static int
pr_readdir_piddir(prnode_t * pnp,uio_t * uiop,int * eofp)51587c478bd9Sstevel@tonic-gate pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
51597c478bd9Sstevel@tonic-gate {
51607c478bd9Sstevel@tonic-gate int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
51617c478bd9Sstevel@tonic-gate prdirent_t dirent;
51627c478bd9Sstevel@tonic-gate prdirent_t *dirp;
51637c478bd9Sstevel@tonic-gate offset_t off;
51647c478bd9Sstevel@tonic-gate int error;
51657c478bd9Sstevel@tonic-gate
51667c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDDIR);
51677c478bd9Sstevel@tonic-gate
51687c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
51697c478bd9Sstevel@tonic-gate uiop->uio_offset % sizeof (prdirent_t) != 0 ||
51707c478bd9Sstevel@tonic-gate uiop->uio_resid < sizeof (prdirent_t))
51717c478bd9Sstevel@tonic-gate return (EINVAL);
51727c478bd9Sstevel@tonic-gate if (pnp->pr_pcommon->prc_proc == NULL)
51737c478bd9Sstevel@tonic-gate return (ENOENT);
51747c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (piddir))
51757c478bd9Sstevel@tonic-gate goto out;
51767c478bd9Sstevel@tonic-gate
51777c478bd9Sstevel@tonic-gate /*
51787c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied, omitting some
51797c478bd9Sstevel@tonic-gate * files along the way if the process is a zombie.
51807c478bd9Sstevel@tonic-gate */
51817c478bd9Sstevel@tonic-gate for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
51827c478bd9Sstevel@tonic-gate uiop->uio_resid >= sizeof (prdirent_t) &&
51837c478bd9Sstevel@tonic-gate dirp < &piddir[NPIDDIRFILES+2];
51847c478bd9Sstevel@tonic-gate uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
51857c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
51867c478bd9Sstevel@tonic-gate if (zombie) {
51877c478bd9Sstevel@tonic-gate switch (dirp->d_ino) {
51887c478bd9Sstevel@tonic-gate case PR_PIDDIR:
51897c478bd9Sstevel@tonic-gate case PR_PROCDIR:
51907c478bd9Sstevel@tonic-gate case PR_PSINFO:
51917c478bd9Sstevel@tonic-gate case PR_USAGE:
51927c478bd9Sstevel@tonic-gate break;
51937c478bd9Sstevel@tonic-gate default:
51947c478bd9Sstevel@tonic-gate continue;
51957c478bd9Sstevel@tonic-gate }
51967c478bd9Sstevel@tonic-gate }
51977c478bd9Sstevel@tonic-gate bcopy(dirp, &dirent, sizeof (prdirent_t));
51987c478bd9Sstevel@tonic-gate if (dirent.d_ino == PR_PROCDIR)
51997c478bd9Sstevel@tonic-gate dirent.d_ino = PRROOTINO;
52007c478bd9Sstevel@tonic-gate else
52017c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
52027c478bd9Sstevel@tonic-gate dirent.d_ino);
52037c478bd9Sstevel@tonic-gate if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
52047c478bd9Sstevel@tonic-gate UIO_READ, uiop)) != 0)
52057c478bd9Sstevel@tonic-gate return (error);
52067c478bd9Sstevel@tonic-gate }
52077c478bd9Sstevel@tonic-gate out:
52087c478bd9Sstevel@tonic-gate if (eofp)
52097c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= sizeof (piddir));
52107c478bd9Sstevel@tonic-gate return (0);
52117c478bd9Sstevel@tonic-gate }
52127c478bd9Sstevel@tonic-gate
52137c478bd9Sstevel@tonic-gate static void
rebuild_objdir(struct as * as)52147c478bd9Sstevel@tonic-gate rebuild_objdir(struct as *as)
52157c478bd9Sstevel@tonic-gate {
52167c478bd9Sstevel@tonic-gate struct seg *seg;
52177c478bd9Sstevel@tonic-gate vnode_t *vp;
52187c478bd9Sstevel@tonic-gate vattr_t vattr;
52197c478bd9Sstevel@tonic-gate vnode_t **dir;
52207c478bd9Sstevel@tonic-gate ulong_t nalloc;
52217c478bd9Sstevel@tonic-gate ulong_t nentries;
52227c478bd9Sstevel@tonic-gate int i, j;
52237c478bd9Sstevel@tonic-gate ulong_t nold, nnew;
52247c478bd9Sstevel@tonic-gate
5225dc32d872SJosef 'Jeff' Sipek ASSERT(AS_WRITE_HELD(as));
52267c478bd9Sstevel@tonic-gate
52277c478bd9Sstevel@tonic-gate if (as->a_updatedir == 0 && as->a_objectdir != NULL)
52287c478bd9Sstevel@tonic-gate return;
52297c478bd9Sstevel@tonic-gate as->a_updatedir = 0;
52307c478bd9Sstevel@tonic-gate
52317c478bd9Sstevel@tonic-gate if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
52327c478bd9Sstevel@tonic-gate (seg = AS_SEGFIRST(as)) == NULL) /* can't happen? */
52337c478bd9Sstevel@tonic-gate return;
52347c478bd9Sstevel@tonic-gate
52357c478bd9Sstevel@tonic-gate /*
52367c478bd9Sstevel@tonic-gate * Allocate space for the new object directory.
52377c478bd9Sstevel@tonic-gate * (This is usually about two times too many entries.)
52387c478bd9Sstevel@tonic-gate */
52397c478bd9Sstevel@tonic-gate nalloc = (nalloc + 0xf) & ~0xf; /* multiple of 16 */
52407c478bd9Sstevel@tonic-gate dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
52417c478bd9Sstevel@tonic-gate
52427c478bd9Sstevel@tonic-gate /* fill in the new directory with desired entries */
52437c478bd9Sstevel@tonic-gate nentries = 0;
52447c478bd9Sstevel@tonic-gate do {
52457c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
52467c478bd9Sstevel@tonic-gate if (seg->s_ops == &segvn_ops &&
52477c478bd9Sstevel@tonic-gate SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
52487c478bd9Sstevel@tonic-gate vp != NULL && vp->v_type == VREG &&
5249da6c28aaSamw VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
52507c478bd9Sstevel@tonic-gate for (i = 0; i < nentries; i++)
52517c478bd9Sstevel@tonic-gate if (vp == dir[i])
52527c478bd9Sstevel@tonic-gate break;
52537c478bd9Sstevel@tonic-gate if (i == nentries) {
52547c478bd9Sstevel@tonic-gate ASSERT(nentries < nalloc);
52557c478bd9Sstevel@tonic-gate dir[nentries++] = vp;
52567c478bd9Sstevel@tonic-gate }
52577c478bd9Sstevel@tonic-gate }
52587c478bd9Sstevel@tonic-gate } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
52597c478bd9Sstevel@tonic-gate
52607c478bd9Sstevel@tonic-gate if (as->a_objectdir == NULL) { /* first time */
52617c478bd9Sstevel@tonic-gate as->a_objectdir = dir;
52627c478bd9Sstevel@tonic-gate as->a_sizedir = nalloc;
52637c478bd9Sstevel@tonic-gate return;
52647c478bd9Sstevel@tonic-gate }
52657c478bd9Sstevel@tonic-gate
52667c478bd9Sstevel@tonic-gate /*
52677c478bd9Sstevel@tonic-gate * Null out all of the defunct entries in the old directory.
52687c478bd9Sstevel@tonic-gate */
52697c478bd9Sstevel@tonic-gate nold = 0;
52707c478bd9Sstevel@tonic-gate nnew = nentries;
52717c478bd9Sstevel@tonic-gate for (i = 0; i < as->a_sizedir; i++) {
52727c478bd9Sstevel@tonic-gate if ((vp = as->a_objectdir[i]) != NULL) {
52737c478bd9Sstevel@tonic-gate for (j = 0; j < nentries; j++) {
52747c478bd9Sstevel@tonic-gate if (vp == dir[j]) {
52757c478bd9Sstevel@tonic-gate dir[j] = NULL;
52767c478bd9Sstevel@tonic-gate nnew--;
52777c478bd9Sstevel@tonic-gate break;
52787c478bd9Sstevel@tonic-gate }
52797c478bd9Sstevel@tonic-gate }
52807c478bd9Sstevel@tonic-gate if (j == nentries)
52817c478bd9Sstevel@tonic-gate as->a_objectdir[i] = NULL;
52827c478bd9Sstevel@tonic-gate else
52837c478bd9Sstevel@tonic-gate nold++;
52847c478bd9Sstevel@tonic-gate }
52857c478bd9Sstevel@tonic-gate }
52867c478bd9Sstevel@tonic-gate
52877c478bd9Sstevel@tonic-gate if (nold + nnew > as->a_sizedir) {
52887c478bd9Sstevel@tonic-gate /*
52897c478bd9Sstevel@tonic-gate * Reallocate the old directory to have enough
52907c478bd9Sstevel@tonic-gate * space for the old and new entries combined.
52917c478bd9Sstevel@tonic-gate * Round up to the next multiple of 16.
52927c478bd9Sstevel@tonic-gate */
52937c478bd9Sstevel@tonic-gate ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
52947c478bd9Sstevel@tonic-gate vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
52957c478bd9Sstevel@tonic-gate KM_SLEEP);
52967c478bd9Sstevel@tonic-gate bcopy(as->a_objectdir, newdir,
52977c478bd9Sstevel@tonic-gate as->a_sizedir * sizeof (vnode_t *));
52987c478bd9Sstevel@tonic-gate kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
52997c478bd9Sstevel@tonic-gate as->a_objectdir = newdir;
53007c478bd9Sstevel@tonic-gate as->a_sizedir = newsize;
53017c478bd9Sstevel@tonic-gate }
53027c478bd9Sstevel@tonic-gate
53037c478bd9Sstevel@tonic-gate /*
53047c478bd9Sstevel@tonic-gate * Move all new entries to the old directory and
53057c478bd9Sstevel@tonic-gate * deallocate the space used by the new directory.
53067c478bd9Sstevel@tonic-gate */
53077c478bd9Sstevel@tonic-gate if (nnew) {
53087c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < nentries; i++) {
53097c478bd9Sstevel@tonic-gate if ((vp = dir[i]) == NULL)
53107c478bd9Sstevel@tonic-gate continue;
53117c478bd9Sstevel@tonic-gate for (; j < as->a_sizedir; j++) {
53127c478bd9Sstevel@tonic-gate if (as->a_objectdir[j] != NULL)
53137c478bd9Sstevel@tonic-gate continue;
53147c478bd9Sstevel@tonic-gate as->a_objectdir[j++] = vp;
53157c478bd9Sstevel@tonic-gate break;
53167c478bd9Sstevel@tonic-gate }
53177c478bd9Sstevel@tonic-gate }
53187c478bd9Sstevel@tonic-gate }
53197c478bd9Sstevel@tonic-gate kmem_free(dir, nalloc * sizeof (vnode_t *));
53207c478bd9Sstevel@tonic-gate }
53217c478bd9Sstevel@tonic-gate
53227c478bd9Sstevel@tonic-gate /*
53237c478bd9Sstevel@tonic-gate * Return the vnode from a slot in the process's object directory.
53247c478bd9Sstevel@tonic-gate * The caller must have locked the process's address space.
53257c478bd9Sstevel@tonic-gate * The only caller is below, in pr_readdir_objectdir().
53267c478bd9Sstevel@tonic-gate */
53277c478bd9Sstevel@tonic-gate static vnode_t *
obj_entry(struct as * as,int slot)53287c478bd9Sstevel@tonic-gate obj_entry(struct as *as, int slot)
53297c478bd9Sstevel@tonic-gate {
5330dc32d872SJosef 'Jeff' Sipek ASSERT(AS_LOCK_HELD(as));
53317c478bd9Sstevel@tonic-gate if (as->a_objectdir == NULL)
53327c478bd9Sstevel@tonic-gate return (NULL);
53337c478bd9Sstevel@tonic-gate ASSERT(slot < as->a_sizedir);
53347c478bd9Sstevel@tonic-gate return (as->a_objectdir[slot]);
53357c478bd9Sstevel@tonic-gate }
53367c478bd9Sstevel@tonic-gate
53377c478bd9Sstevel@tonic-gate /* ARGSUSED */
53387c478bd9Sstevel@tonic-gate static int
pr_readdir_objectdir(prnode_t * pnp,uio_t * uiop,int * eofp)53397c478bd9Sstevel@tonic-gate pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
53407c478bd9Sstevel@tonic-gate {
53417c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
53427c478bd9Sstevel@tonic-gate int error, eof = 0;
53437c478bd9Sstevel@tonic-gate offset_t n;
53447c478bd9Sstevel@tonic-gate int pslot;
53457c478bd9Sstevel@tonic-gate size_t objdirsize;
53467c478bd9Sstevel@tonic-gate proc_t *p;
53477c478bd9Sstevel@tonic-gate struct as *as;
53487c478bd9Sstevel@tonic-gate vnode_t *vp;
53497c478bd9Sstevel@tonic-gate
53507c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_OBJECTDIR);
53517c478bd9Sstevel@tonic-gate
53527c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
53537c478bd9Sstevel@tonic-gate return (error);
53547c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
53557c478bd9Sstevel@tonic-gate pslot = p->p_slot;
53567c478bd9Sstevel@tonic-gate
53577c478bd9Sstevel@tonic-gate /*
53587c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
53597c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
53607c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
53617c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
53627c478bd9Sstevel@tonic-gate */
53637c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
53647c478bd9Sstevel@tonic-gate
53657c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
53667c478bd9Sstevel@tonic-gate pmkino(0, pslot, PR_PIDDIR),
5367b38f0970Sck153898 pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
53687c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
53697c478bd9Sstevel@tonic-gate prunlock(pnp);
53707c478bd9Sstevel@tonic-gate return (error);
53717c478bd9Sstevel@tonic-gate }
53727c478bd9Sstevel@tonic-gate
53737c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
53747c478bd9Sstevel@tonic-gate as = NULL;
53757c478bd9Sstevel@tonic-gate objdirsize = 0;
537643d09bd4Spetede }
537743d09bd4Spetede
537843d09bd4Spetede /*
537943d09bd4Spetede * Loop until user's request is satisfied or until
538043d09bd4Spetede * all mapped objects have been examined. Cannot hold
538143d09bd4Spetede * the address space lock for the following call as
538243d09bd4Spetede * gfs_readdir_pred() utimately causes a call to uiomove().
538343d09bd4Spetede */
538443d09bd4Spetede while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
538543d09bd4Spetede vattr_t vattr;
538643d09bd4Spetede char str[64];
538743d09bd4Spetede
538843d09bd4Spetede /*
538943d09bd4Spetede * Set the correct size of the directory just
539043d09bd4Spetede * in case the process has changed it's address
539143d09bd4Spetede * space via mmap/munmap calls.
539243d09bd4Spetede */
539343d09bd4Spetede if (as != NULL) {
5394dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
53957c478bd9Sstevel@tonic-gate if (as->a_updatedir)
53967c478bd9Sstevel@tonic-gate rebuild_objdir(as);
53977c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
53987c478bd9Sstevel@tonic-gate }
53997c478bd9Sstevel@tonic-gate
54007c478bd9Sstevel@tonic-gate /*
54017c478bd9Sstevel@tonic-gate * Find next object.
54027c478bd9Sstevel@tonic-gate */
54037c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID | AT_NODEID;
54047c478bd9Sstevel@tonic-gate while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
5405da6c28aaSamw (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)
5406da6c28aaSamw != 0))) {
54077c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID | AT_NODEID;
54087c478bd9Sstevel@tonic-gate n++;
54097c478bd9Sstevel@tonic-gate }
54107c478bd9Sstevel@tonic-gate
541143d09bd4Spetede if (as != NULL)
5412dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
541343d09bd4Spetede
54147c478bd9Sstevel@tonic-gate /*
54157c478bd9Sstevel@tonic-gate * Stop when all objects have been reported.
54167c478bd9Sstevel@tonic-gate */
54177c478bd9Sstevel@tonic-gate if (n >= objdirsize) {
54187c478bd9Sstevel@tonic-gate eof = 1;
54197c478bd9Sstevel@tonic-gate break;
54207c478bd9Sstevel@tonic-gate }
54217c478bd9Sstevel@tonic-gate
54227c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
54237c478bd9Sstevel@tonic-gate (void) strcpy(str, "a.out");
54247c478bd9Sstevel@tonic-gate else
54257c478bd9Sstevel@tonic-gate pr_object_name(str, vp, &vattr);
54267c478bd9Sstevel@tonic-gate
54277c478bd9Sstevel@tonic-gate error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
5428b38f0970Sck153898 str, 0);
542943d09bd4Spetede
54307c478bd9Sstevel@tonic-gate if (error)
54317c478bd9Sstevel@tonic-gate break;
54327c478bd9Sstevel@tonic-gate }
54337c478bd9Sstevel@tonic-gate
54347c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
54357c478bd9Sstevel@tonic-gate prunlock(pnp);
54367c478bd9Sstevel@tonic-gate
54377c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
54387c478bd9Sstevel@tonic-gate }
54397c478bd9Sstevel@tonic-gate
54407c478bd9Sstevel@tonic-gate /* ARGSUSED */
54417c478bd9Sstevel@tonic-gate static int
pr_readdir_lwpdir(prnode_t * pnp,uio_t * uiop,int * eofp)54427c478bd9Sstevel@tonic-gate pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
54437c478bd9Sstevel@tonic-gate {
54447c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
54457c478bd9Sstevel@tonic-gate int error, eof = 0;
54467c478bd9Sstevel@tonic-gate offset_t tslot;
54477c478bd9Sstevel@tonic-gate proc_t *p;
54487c478bd9Sstevel@tonic-gate int pslot;
54497c478bd9Sstevel@tonic-gate lwpdir_t *lwpdir;
54507c478bd9Sstevel@tonic-gate int lwpdirsize;
54517c478bd9Sstevel@tonic-gate
54527c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPDIR);
54537c478bd9Sstevel@tonic-gate
54547c478bd9Sstevel@tonic-gate p = pr_p_lock(pnp);
54557c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
54567c478bd9Sstevel@tonic-gate if (p == NULL)
54577c478bd9Sstevel@tonic-gate return (ENOENT);
54587c478bd9Sstevel@tonic-gate ASSERT(p == pnp->pr_common->prc_proc);
54597c478bd9Sstevel@tonic-gate pslot = p->p_slot;
54607c478bd9Sstevel@tonic-gate lwpdir = p->p_lwpdir;
54617c478bd9Sstevel@tonic-gate lwpdirsize = p->p_lwpdir_sz;
54627c478bd9Sstevel@tonic-gate
54637c478bd9Sstevel@tonic-gate /*
54647c478bd9Sstevel@tonic-gate * Drop p->p_lock so we can safely do uiomove().
54657c478bd9Sstevel@tonic-gate * The lwp directory will not change because
54667c478bd9Sstevel@tonic-gate * we have the process locked with P_PR_LOCK.
54677c478bd9Sstevel@tonic-gate */
54687c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
54697c478bd9Sstevel@tonic-gate
54707c478bd9Sstevel@tonic-gate
54717c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5472b38f0970Sck153898 pmkino(0, pslot, PR_PIDDIR),
5473b38f0970Sck153898 pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
54747c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
54757c478bd9Sstevel@tonic-gate prunlock(pnp);
54767c478bd9Sstevel@tonic-gate return (error);
54777c478bd9Sstevel@tonic-gate }
54787c478bd9Sstevel@tonic-gate
54797c478bd9Sstevel@tonic-gate /*
54807c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until all lwps
54817c478bd9Sstevel@tonic-gate * have been examined.
54827c478bd9Sstevel@tonic-gate */
54837c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
54847c478bd9Sstevel@tonic-gate lwpent_t *lep;
54857c478bd9Sstevel@tonic-gate uint_t tid;
54867c478bd9Sstevel@tonic-gate
54877c478bd9Sstevel@tonic-gate /*
54887c478bd9Sstevel@tonic-gate * Find next LWP.
54897c478bd9Sstevel@tonic-gate */
54907c478bd9Sstevel@tonic-gate while (tslot < lwpdirsize &&
54917c478bd9Sstevel@tonic-gate ((lep = lwpdir[tslot].ld_entry) == NULL))
54927c478bd9Sstevel@tonic-gate tslot++;
54937c478bd9Sstevel@tonic-gate /*
54947c478bd9Sstevel@tonic-gate * Stop when all lwps have been reported.
54957c478bd9Sstevel@tonic-gate */
54967c478bd9Sstevel@tonic-gate if (tslot >= lwpdirsize) {
54977c478bd9Sstevel@tonic-gate eof = 1;
54987c478bd9Sstevel@tonic-gate break;
54997c478bd9Sstevel@tonic-gate }
55007c478bd9Sstevel@tonic-gate
55017c478bd9Sstevel@tonic-gate tid = lep->le_lwpid;
55027c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, tslot,
55037c478bd9Sstevel@tonic-gate pmkino(tslot, pslot, PR_LWPIDDIR), tid);
55047c478bd9Sstevel@tonic-gate if (error)
55057c478bd9Sstevel@tonic-gate break;
55067c478bd9Sstevel@tonic-gate }
55077c478bd9Sstevel@tonic-gate
55087c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
55097c478bd9Sstevel@tonic-gate prunlock(pnp);
55107c478bd9Sstevel@tonic-gate
55117c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
55127c478bd9Sstevel@tonic-gate }
55137c478bd9Sstevel@tonic-gate
55147c478bd9Sstevel@tonic-gate /* ARGSUSED */
55157c478bd9Sstevel@tonic-gate static int
pr_readdir_lwpiddir(prnode_t * pnp,uio_t * uiop,int * eofp)55167c478bd9Sstevel@tonic-gate pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
55177c478bd9Sstevel@tonic-gate {
55187c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
55197c478bd9Sstevel@tonic-gate int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
55207c478bd9Sstevel@tonic-gate prdirent_t dirent;
55217c478bd9Sstevel@tonic-gate prdirent_t *dirp;
55227c478bd9Sstevel@tonic-gate offset_t off;
55237c478bd9Sstevel@tonic-gate int error;
55247c478bd9Sstevel@tonic-gate int pslot;
55257c478bd9Sstevel@tonic-gate int tslot;
55267c478bd9Sstevel@tonic-gate
55277c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_LWPIDDIR);
55287c478bd9Sstevel@tonic-gate
55297c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
55307c478bd9Sstevel@tonic-gate uiop->uio_offset % sizeof (prdirent_t) != 0 ||
55317c478bd9Sstevel@tonic-gate uiop->uio_resid < sizeof (prdirent_t))
55327c478bd9Sstevel@tonic-gate return (EINVAL);
55337c478bd9Sstevel@tonic-gate if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
55347c478bd9Sstevel@tonic-gate return (ENOENT);
55357c478bd9Sstevel@tonic-gate if (uiop->uio_offset >= sizeof (lwpiddir))
55367c478bd9Sstevel@tonic-gate goto out;
55377c478bd9Sstevel@tonic-gate
55387c478bd9Sstevel@tonic-gate /*
55397c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied, omitting some files
55407c478bd9Sstevel@tonic-gate * along the way if the lwp is a zombie and also depending
55417c478bd9Sstevel@tonic-gate * on the data model of the process.
55427c478bd9Sstevel@tonic-gate */
55437c478bd9Sstevel@tonic-gate pslot = pcp->prc_slot;
55447c478bd9Sstevel@tonic-gate tslot = pcp->prc_tslot;
55457c478bd9Sstevel@tonic-gate for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
55467c478bd9Sstevel@tonic-gate uiop->uio_resid >= sizeof (prdirent_t) &&
55477c478bd9Sstevel@tonic-gate dirp < &lwpiddir[NLWPIDDIRFILES+2];
55487c478bd9Sstevel@tonic-gate uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
55497c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
55507c478bd9Sstevel@tonic-gate if (zombie) {
55517c478bd9Sstevel@tonic-gate switch (dirp->d_ino) {
55527c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
55537c478bd9Sstevel@tonic-gate case PR_LWPDIR:
55547c478bd9Sstevel@tonic-gate case PR_LWPSINFO:
55557c478bd9Sstevel@tonic-gate break;
55567c478bd9Sstevel@tonic-gate default:
55577c478bd9Sstevel@tonic-gate continue;
55587c478bd9Sstevel@tonic-gate }
55597c478bd9Sstevel@tonic-gate }
55607c478bd9Sstevel@tonic-gate #if defined(__sparc)
55617c478bd9Sstevel@tonic-gate /* the asrs file exists only for sparc v9 _LP64 processes */
55627c478bd9Sstevel@tonic-gate if (dirp->d_ino == PR_ASRS &&
55637c478bd9Sstevel@tonic-gate pcp->prc_datamodel != DATAMODEL_LP64)
55647c478bd9Sstevel@tonic-gate continue;
55657c478bd9Sstevel@tonic-gate #endif
55667c478bd9Sstevel@tonic-gate bcopy(dirp, &dirent, sizeof (prdirent_t));
55677c478bd9Sstevel@tonic-gate if (dirent.d_ino == PR_LWPDIR)
55687c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
55697c478bd9Sstevel@tonic-gate else
55707c478bd9Sstevel@tonic-gate dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
55717c478bd9Sstevel@tonic-gate if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
55727c478bd9Sstevel@tonic-gate UIO_READ, uiop)) != 0)
55737c478bd9Sstevel@tonic-gate return (error);
55747c478bd9Sstevel@tonic-gate }
55757c478bd9Sstevel@tonic-gate out:
55767c478bd9Sstevel@tonic-gate if (eofp)
55777c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
55787c478bd9Sstevel@tonic-gate return (0);
55797c478bd9Sstevel@tonic-gate }
55807c478bd9Sstevel@tonic-gate
5581a02120c4SAndy Fiddaman /*
5582a02120c4SAndy Fiddaman * Helper function for reading a directory which lists open file desciptors
5583a02120c4SAndy Fiddaman */
55847c478bd9Sstevel@tonic-gate static int
pr_readdir_fdlist(prnode_t * pnp,uio_t * uiop,int * eofp,prnodetype_t dirtype,prnodetype_t entrytype)5585a02120c4SAndy Fiddaman pr_readdir_fdlist(prnode_t *pnp, uio_t *uiop, int *eofp,
5586a02120c4SAndy Fiddaman prnodetype_t dirtype, prnodetype_t entrytype)
55877c478bd9Sstevel@tonic-gate {
55887c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
55897c478bd9Sstevel@tonic-gate int error, eof = 0;
55907c478bd9Sstevel@tonic-gate offset_t n;
55917c478bd9Sstevel@tonic-gate proc_t *p;
55927c478bd9Sstevel@tonic-gate int pslot;
55937c478bd9Sstevel@tonic-gate int fddirsize;
55947c478bd9Sstevel@tonic-gate uf_info_t *fip;
55957c478bd9Sstevel@tonic-gate
55967c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
55977c478bd9Sstevel@tonic-gate return (error);
55987c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
55997c478bd9Sstevel@tonic-gate pslot = p->p_slot;
56007c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
56017c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
56027c478bd9Sstevel@tonic-gate
56037c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5604a02120c4SAndy Fiddaman pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, dirtype), 0)) != 0) {
56057c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
56067c478bd9Sstevel@tonic-gate prunlock(pnp);
56077c478bd9Sstevel@tonic-gate return (error);
56087c478bd9Sstevel@tonic-gate }
56097c478bd9Sstevel@tonic-gate
56107c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
56117c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
56127c478bd9Sstevel@tonic-gate fddirsize = 0;
56137c478bd9Sstevel@tonic-gate else
56147c478bd9Sstevel@tonic-gate fddirsize = fip->fi_nfiles;
56157c478bd9Sstevel@tonic-gate
56167c478bd9Sstevel@tonic-gate /*
56177c478bd9Sstevel@tonic-gate * Loop until user's request is satisfied or until
56187c478bd9Sstevel@tonic-gate * all file descriptors have been examined.
56197c478bd9Sstevel@tonic-gate */
56207c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
56217c478bd9Sstevel@tonic-gate /*
56227c478bd9Sstevel@tonic-gate * Find next fd.
56237c478bd9Sstevel@tonic-gate */
56247c478bd9Sstevel@tonic-gate while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
56257c478bd9Sstevel@tonic-gate n++;
56267c478bd9Sstevel@tonic-gate /*
56277c478bd9Sstevel@tonic-gate * Stop when all fds have been reported.
56287c478bd9Sstevel@tonic-gate */
56297c478bd9Sstevel@tonic-gate if (n >= fddirsize) {
56307c478bd9Sstevel@tonic-gate eof = 1;
56317c478bd9Sstevel@tonic-gate break;
56327c478bd9Sstevel@tonic-gate }
56337c478bd9Sstevel@tonic-gate
56347c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, n,
5635a02120c4SAndy Fiddaman pmkino(n, pslot, entrytype), n);
56367c478bd9Sstevel@tonic-gate if (error)
56377c478bd9Sstevel@tonic-gate break;
56387c478bd9Sstevel@tonic-gate }
56397c478bd9Sstevel@tonic-gate
56407c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
56417c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
56427c478bd9Sstevel@tonic-gate prunlock(pnp);
56437c478bd9Sstevel@tonic-gate
56447c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
56457c478bd9Sstevel@tonic-gate }
56467c478bd9Sstevel@tonic-gate
5647a02120c4SAndy Fiddaman static int
pr_readdir_fddir(prnode_t * pnp,uio_t * uiop,int * eofp)5648a02120c4SAndy Fiddaman pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5649a02120c4SAndy Fiddaman {
5650a02120c4SAndy Fiddaman
5651a02120c4SAndy Fiddaman ASSERT(pnp->pr_type == PR_FDDIR);
5652a02120c4SAndy Fiddaman
5653a02120c4SAndy Fiddaman return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FD));
5654a02120c4SAndy Fiddaman }
5655a02120c4SAndy Fiddaman
5656a02120c4SAndy Fiddaman static int
pr_readdir_fdinfodir(prnode_t * pnp,uio_t * uiop,int * eofp)5657a02120c4SAndy Fiddaman pr_readdir_fdinfodir(prnode_t *pnp, uio_t *uiop, int *eofp)
5658a02120c4SAndy Fiddaman {
5659a02120c4SAndy Fiddaman
5660a02120c4SAndy Fiddaman ASSERT(pnp->pr_type == PR_FDINFODIR);
5661a02120c4SAndy Fiddaman
5662a02120c4SAndy Fiddaman return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FDINFO));
5663a02120c4SAndy Fiddaman }
5664a02120c4SAndy Fiddaman
56657c478bd9Sstevel@tonic-gate /* ARGSUSED */
56667c478bd9Sstevel@tonic-gate static int
pr_readdir_pathdir(prnode_t * pnp,uio_t * uiop,int * eofp)56677c478bd9Sstevel@tonic-gate pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
56687c478bd9Sstevel@tonic-gate {
56697c478bd9Sstevel@tonic-gate longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
56707c478bd9Sstevel@tonic-gate dirent64_t *dirent = (dirent64_t *)bp;
56717c478bd9Sstevel@tonic-gate int reclen;
56727c478bd9Sstevel@tonic-gate ssize_t oresid;
56737c478bd9Sstevel@tonic-gate offset_t off, idx;
56747c478bd9Sstevel@tonic-gate int error = 0;
56757c478bd9Sstevel@tonic-gate proc_t *p;
56767c478bd9Sstevel@tonic-gate int fd, obj;
56777c478bd9Sstevel@tonic-gate int pslot;
56787c478bd9Sstevel@tonic-gate int fddirsize;
56797c478bd9Sstevel@tonic-gate uf_info_t *fip;
56807c478bd9Sstevel@tonic-gate struct as *as = NULL;
56817c478bd9Sstevel@tonic-gate size_t objdirsize;
56827c478bd9Sstevel@tonic-gate vattr_t vattr;
56837c478bd9Sstevel@tonic-gate vnode_t *vp;
56847c478bd9Sstevel@tonic-gate
56857c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PATHDIR);
56867c478bd9Sstevel@tonic-gate
56877c478bd9Sstevel@tonic-gate if (uiop->uio_offset < 0 ||
56887c478bd9Sstevel@tonic-gate uiop->uio_resid <= 0 ||
56897c478bd9Sstevel@tonic-gate (uiop->uio_offset % PRSDSIZE) != 0)
56907c478bd9Sstevel@tonic-gate return (EINVAL);
56917c478bd9Sstevel@tonic-gate oresid = uiop->uio_resid;
56927c478bd9Sstevel@tonic-gate bzero(bp, sizeof (bp));
56937c478bd9Sstevel@tonic-gate
56947c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
56957c478bd9Sstevel@tonic-gate return (error);
56967c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
56977c478bd9Sstevel@tonic-gate fip = P_FINFO(p);
56987c478bd9Sstevel@tonic-gate pslot = p->p_slot;
56997c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
57007c478bd9Sstevel@tonic-gate
57017c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
57027c478bd9Sstevel@tonic-gate as = NULL;
57037c478bd9Sstevel@tonic-gate objdirsize = 0;
57047c478bd9Sstevel@tonic-gate } else {
5705dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
57067c478bd9Sstevel@tonic-gate if (as->a_updatedir)
57077c478bd9Sstevel@tonic-gate rebuild_objdir(as);
57087c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
5709dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
57107c478bd9Sstevel@tonic-gate as = NULL;
57117c478bd9Sstevel@tonic-gate }
57127c478bd9Sstevel@tonic-gate
57137c478bd9Sstevel@tonic-gate mutex_enter(&fip->fi_lock);
57147c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
57157c478bd9Sstevel@tonic-gate fddirsize = 0;
57167c478bd9Sstevel@tonic-gate else
57177c478bd9Sstevel@tonic-gate fddirsize = fip->fi_nfiles;
57187c478bd9Sstevel@tonic-gate
57197c478bd9Sstevel@tonic-gate for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
57207c478bd9Sstevel@tonic-gate /*
57217c478bd9Sstevel@tonic-gate * There are 4 special files in the path directory: ".", "..",
57227c478bd9Sstevel@tonic-gate * "root", and "cwd". We handle those specially here.
57237c478bd9Sstevel@tonic-gate */
57247c478bd9Sstevel@tonic-gate off = uiop->uio_offset;
57257c478bd9Sstevel@tonic-gate idx = off / PRSDSIZE;
57267c478bd9Sstevel@tonic-gate if (off == 0) { /* "." */
57277c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
57287c478bd9Sstevel@tonic-gate dirent->d_name[0] = '.';
57297c478bd9Sstevel@tonic-gate dirent->d_name[1] = '\0';
57307c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(1);
57317c478bd9Sstevel@tonic-gate } else if (idx == 1) { /* ".." */
57327c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
57337c478bd9Sstevel@tonic-gate dirent->d_name[0] = '.';
57347c478bd9Sstevel@tonic-gate dirent->d_name[1] = '.';
57357c478bd9Sstevel@tonic-gate dirent->d_name[2] = '\0';
57367c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(2);
57377c478bd9Sstevel@tonic-gate } else if (idx == 2) { /* "root" */
57387c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
57397c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "root");
57407c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(4);
57417c478bd9Sstevel@tonic-gate } else if (idx == 3) { /* "cwd" */
57427c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
57437c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "cwd");
57447c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(3);
57457c478bd9Sstevel@tonic-gate } else if (idx < 4 + fddirsize) {
57467c478bd9Sstevel@tonic-gate /*
57477c478bd9Sstevel@tonic-gate * In this case, we have one of the file descriptors.
57487c478bd9Sstevel@tonic-gate */
57497c478bd9Sstevel@tonic-gate fd = idx - 4;
57507c478bd9Sstevel@tonic-gate if (fip->fi_list[fd].uf_file == NULL)
57517c478bd9Sstevel@tonic-gate continue;
57527c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
57537c478bd9Sstevel@tonic-gate (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
57547c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(PLNSIZ);
57557c478bd9Sstevel@tonic-gate } else if (idx < 4 + fddirsize + objdirsize) {
57567c478bd9Sstevel@tonic-gate if (fip != NULL) {
57577c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
57587c478bd9Sstevel@tonic-gate fip = NULL;
57597c478bd9Sstevel@tonic-gate }
57607c478bd9Sstevel@tonic-gate
57617c478bd9Sstevel@tonic-gate /*
57627c478bd9Sstevel@tonic-gate * We drop p_lock before grabbing the address space lock
57637c478bd9Sstevel@tonic-gate * in order to avoid a deadlock with the clock thread.
57647c478bd9Sstevel@tonic-gate * The process will not disappear and its address space
57657c478bd9Sstevel@tonic-gate * will not change because it is marked P_PR_LOCK.
57667c478bd9Sstevel@tonic-gate */
57677c478bd9Sstevel@tonic-gate if (as == NULL) {
57687c478bd9Sstevel@tonic-gate as = p->p_as;
5769dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
57707c478bd9Sstevel@tonic-gate }
57717c478bd9Sstevel@tonic-gate
57727c478bd9Sstevel@tonic-gate if (as->a_updatedir) {
57737c478bd9Sstevel@tonic-gate rebuild_objdir(as);
57747c478bd9Sstevel@tonic-gate objdirsize = as->a_sizedir;
57757c478bd9Sstevel@tonic-gate }
57767c478bd9Sstevel@tonic-gate
57777c478bd9Sstevel@tonic-gate obj = idx - 4 - fddirsize;
57787c478bd9Sstevel@tonic-gate if ((vp = obj_entry(as, obj)) == NULL)
57797c478bd9Sstevel@tonic-gate continue;
57807c478bd9Sstevel@tonic-gate vattr.va_mask = AT_FSID|AT_NODEID;
5781da6c28aaSamw if (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) != 0)
57827c478bd9Sstevel@tonic-gate continue;
57837c478bd9Sstevel@tonic-gate if (vp == p->p_exec)
57847c478bd9Sstevel@tonic-gate (void) strcpy(dirent->d_name, "a.out");
57857c478bd9Sstevel@tonic-gate else
57867c478bd9Sstevel@tonic-gate pr_object_name(dirent->d_name, vp, &vattr);
57877c478bd9Sstevel@tonic-gate dirent->d_ino = pmkino(idx, pslot, PR_PATH);
57887c478bd9Sstevel@tonic-gate reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
57897c478bd9Sstevel@tonic-gate } else {
57907c478bd9Sstevel@tonic-gate break;
57917c478bd9Sstevel@tonic-gate }
57927c478bd9Sstevel@tonic-gate
57937c478bd9Sstevel@tonic-gate dirent->d_off = uiop->uio_offset + PRSDSIZE;
57947c478bd9Sstevel@tonic-gate dirent->d_reclen = (ushort_t)reclen;
57957c478bd9Sstevel@tonic-gate if (reclen > uiop->uio_resid) {
57967c478bd9Sstevel@tonic-gate /*
57977c478bd9Sstevel@tonic-gate * Error if no entries have been returned yet.
57987c478bd9Sstevel@tonic-gate */
57997c478bd9Sstevel@tonic-gate if (uiop->uio_resid == oresid)
58007c478bd9Sstevel@tonic-gate error = EINVAL;
58017c478bd9Sstevel@tonic-gate break;
58027c478bd9Sstevel@tonic-gate }
58037c478bd9Sstevel@tonic-gate /*
58047c478bd9Sstevel@tonic-gate * Drop the address space lock to do the uiomove().
58057c478bd9Sstevel@tonic-gate */
58067c478bd9Sstevel@tonic-gate if (as != NULL)
5807dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
58087c478bd9Sstevel@tonic-gate
58097c478bd9Sstevel@tonic-gate error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
58107c478bd9Sstevel@tonic-gate if (as != NULL)
5811dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_WRITER);
58127c478bd9Sstevel@tonic-gate
58137c478bd9Sstevel@tonic-gate if (error)
58147c478bd9Sstevel@tonic-gate break;
58157c478bd9Sstevel@tonic-gate }
58167c478bd9Sstevel@tonic-gate
58177c478bd9Sstevel@tonic-gate if (error == 0 && eofp)
58187c478bd9Sstevel@tonic-gate *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
58197c478bd9Sstevel@tonic-gate
58207c478bd9Sstevel@tonic-gate if (fip != NULL)
58217c478bd9Sstevel@tonic-gate mutex_exit(&fip->fi_lock);
58227c478bd9Sstevel@tonic-gate if (as != NULL)
5823dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
58247c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
58257c478bd9Sstevel@tonic-gate prunlock(pnp);
58267c478bd9Sstevel@tonic-gate return (error);
58277c478bd9Sstevel@tonic-gate }
58287c478bd9Sstevel@tonic-gate
58297c478bd9Sstevel@tonic-gate static int
pr_readdir_tmpldir(prnode_t * pnp,uio_t * uiop,int * eofp)58307c478bd9Sstevel@tonic-gate pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
58317c478bd9Sstevel@tonic-gate {
58327c478bd9Sstevel@tonic-gate proc_t *p;
58337c478bd9Sstevel@tonic-gate int pslot, tslot;
58347c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
58357c478bd9Sstevel@tonic-gate int error, eof = 0;
58367c478bd9Sstevel@tonic-gate offset_t n;
58377c478bd9Sstevel@tonic-gate
58387c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_TMPLDIR);
58397c478bd9Sstevel@tonic-gate
58407c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
58417c478bd9Sstevel@tonic-gate return (error);
58427c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
58437c478bd9Sstevel@tonic-gate pslot = pnp->pr_common->prc_slot;
58447c478bd9Sstevel@tonic-gate tslot = pnp->pr_common->prc_tslot;
58457c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
58467c478bd9Sstevel@tonic-gate
58477c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
58487c478bd9Sstevel@tonic-gate pmkino(tslot, pslot, PR_LWPDIR),
5849b38f0970Sck153898 pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
58507c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
58517c478bd9Sstevel@tonic-gate prunlock(pnp);
58527c478bd9Sstevel@tonic-gate return (error);
58537c478bd9Sstevel@tonic-gate }
58547c478bd9Sstevel@tonic-gate
58557c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
58567c478bd9Sstevel@tonic-gate /*
58577c478bd9Sstevel@tonic-gate * Check for an active template. Reading a directory's
58587c478bd9Sstevel@tonic-gate * contents is already racy, so we don't bother taking
58597c478bd9Sstevel@tonic-gate * any locks.
58607c478bd9Sstevel@tonic-gate */
58617c478bd9Sstevel@tonic-gate while (n < ct_ntypes &&
58627c478bd9Sstevel@tonic-gate pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
58637c478bd9Sstevel@tonic-gate n++;
58647c478bd9Sstevel@tonic-gate /*
58657c478bd9Sstevel@tonic-gate * Stop when all types have been reported.
58667c478bd9Sstevel@tonic-gate */
58677c478bd9Sstevel@tonic-gate if (n >= ct_ntypes) {
58687c478bd9Sstevel@tonic-gate eof = 1;
58697c478bd9Sstevel@tonic-gate break;
58707c478bd9Sstevel@tonic-gate }
58717c478bd9Sstevel@tonic-gate /*
58727c478bd9Sstevel@tonic-gate * The pmkino invocation below will need to be updated
58737c478bd9Sstevel@tonic-gate * when we create our fifth contract type.
58747c478bd9Sstevel@tonic-gate */
58757c478bd9Sstevel@tonic-gate ASSERT(ct_ntypes <= 4);
58767c478bd9Sstevel@tonic-gate error = gfs_readdir_emit(&gstate, uiop, n,
58777c478bd9Sstevel@tonic-gate pmkino((tslot << 2) | n, pslot, PR_TMPL),
5878b38f0970Sck153898 ct_types[n]->ct_type_name, 0);
58797c478bd9Sstevel@tonic-gate if (error)
58807c478bd9Sstevel@tonic-gate break;
58817c478bd9Sstevel@tonic-gate }
58827c478bd9Sstevel@tonic-gate
58837c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
58847c478bd9Sstevel@tonic-gate prunlock(pnp);
58857c478bd9Sstevel@tonic-gate
58867c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
58877c478bd9Sstevel@tonic-gate }
58887c478bd9Sstevel@tonic-gate
58897c478bd9Sstevel@tonic-gate static int
pr_readdir_ctdir(prnode_t * pnp,uio_t * uiop,int * eofp)58907c478bd9Sstevel@tonic-gate pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
58917c478bd9Sstevel@tonic-gate {
58927c478bd9Sstevel@tonic-gate proc_t *p;
58937c478bd9Sstevel@tonic-gate int pslot;
58947c478bd9Sstevel@tonic-gate gfs_readdir_state_t gstate;
58957c478bd9Sstevel@tonic-gate int error, eof = 0;
58967c478bd9Sstevel@tonic-gate offset_t n;
58977c478bd9Sstevel@tonic-gate uint64_t zid;
58987c478bd9Sstevel@tonic-gate
58997c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_CTDIR);
59007c478bd9Sstevel@tonic-gate
59017c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0)
59027c478bd9Sstevel@tonic-gate return (error);
59037c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
59047c478bd9Sstevel@tonic-gate pslot = p->p_slot;
59057c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
59067c478bd9Sstevel@tonic-gate
59077c478bd9Sstevel@tonic-gate if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5908b38f0970Sck153898 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
59097c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
59107c478bd9Sstevel@tonic-gate prunlock(pnp);
59117c478bd9Sstevel@tonic-gate return (error);
59127c478bd9Sstevel@tonic-gate }
59137c478bd9Sstevel@tonic-gate
5914fa9e4066Sahrens zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
59157c478bd9Sstevel@tonic-gate while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
59167c478bd9Sstevel@tonic-gate id_t next = contract_plookup(p, n, zid);
59177c478bd9Sstevel@tonic-gate if (next == -1) {
59187c478bd9Sstevel@tonic-gate eof = 1;
59197c478bd9Sstevel@tonic-gate break;
59207c478bd9Sstevel@tonic-gate }
59217c478bd9Sstevel@tonic-gate error = gfs_readdir_emitn(&gstate, uiop, next,
59227c478bd9Sstevel@tonic-gate pmkino(next, pslot, PR_CT), next);
59237c478bd9Sstevel@tonic-gate if (error)
59247c478bd9Sstevel@tonic-gate break;
59257c478bd9Sstevel@tonic-gate }
59267c478bd9Sstevel@tonic-gate
59277c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
59287c478bd9Sstevel@tonic-gate prunlock(pnp);
59297c478bd9Sstevel@tonic-gate
59307c478bd9Sstevel@tonic-gate return (gfs_readdir_fini(&gstate, error, eofp, eof));
59317c478bd9Sstevel@tonic-gate }
59327c478bd9Sstevel@tonic-gate
59337c478bd9Sstevel@tonic-gate /* ARGSUSED */
59347c478bd9Sstevel@tonic-gate static int
prfsync(vnode_t * vp,int syncflag,cred_t * cr,caller_context_t * ct)5935da6c28aaSamw prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
59367c478bd9Sstevel@tonic-gate {
59377c478bd9Sstevel@tonic-gate return (0);
59387c478bd9Sstevel@tonic-gate }
59397c478bd9Sstevel@tonic-gate
59407c478bd9Sstevel@tonic-gate /*
59417c478bd9Sstevel@tonic-gate * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
59427c478bd9Sstevel@tonic-gate */
59437c478bd9Sstevel@tonic-gate static void
pr_list_unlink(vnode_t * pvp,vnode_t ** listp)59447c478bd9Sstevel@tonic-gate pr_list_unlink(vnode_t *pvp, vnode_t **listp)
59457c478bd9Sstevel@tonic-gate {
59467c478bd9Sstevel@tonic-gate vnode_t *vp;
59477c478bd9Sstevel@tonic-gate prnode_t *pnp;
59487c478bd9Sstevel@tonic-gate
59497c478bd9Sstevel@tonic-gate while ((vp = *listp) != NULL) {
59507c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
59517c478bd9Sstevel@tonic-gate if (vp == pvp) {
59527c478bd9Sstevel@tonic-gate *listp = pnp->pr_next;
59537c478bd9Sstevel@tonic-gate pnp->pr_next = NULL;
59547c478bd9Sstevel@tonic-gate break;
59557c478bd9Sstevel@tonic-gate }
59567c478bd9Sstevel@tonic-gate listp = &pnp->pr_next;
59577c478bd9Sstevel@tonic-gate }
59587c478bd9Sstevel@tonic-gate }
59597c478bd9Sstevel@tonic-gate
59607c478bd9Sstevel@tonic-gate /* ARGSUSED */
59617c478bd9Sstevel@tonic-gate static void
prinactive(vnode_t * vp,cred_t * cr,caller_context_t * ct)5962da6c28aaSamw prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
59637c478bd9Sstevel@tonic-gate {
59647c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
59657c478bd9Sstevel@tonic-gate prnodetype_t type = pnp->pr_type;
59667c478bd9Sstevel@tonic-gate proc_t *p;
59677c478bd9Sstevel@tonic-gate vnode_t *dp;
59687c478bd9Sstevel@tonic-gate vnode_t *ovp = NULL;
59697c478bd9Sstevel@tonic-gate prnode_t *opnp = NULL;
59707c478bd9Sstevel@tonic-gate
59717c478bd9Sstevel@tonic-gate switch (type) {
59727c478bd9Sstevel@tonic-gate case PR_OBJECT:
59737c478bd9Sstevel@tonic-gate case PR_FD:
5974a02120c4SAndy Fiddaman case PR_FDINFO:
59757c478bd9Sstevel@tonic-gate case PR_SELF:
59767c478bd9Sstevel@tonic-gate case PR_PATH:
59777c478bd9Sstevel@tonic-gate /* These are not linked into the usual lists */
59787c478bd9Sstevel@tonic-gate ASSERT(vp->v_count == 1);
59797c478bd9Sstevel@tonic-gate if ((dp = pnp->pr_parent) != NULL)
59807c478bd9Sstevel@tonic-gate VN_RELE(dp);
59817c478bd9Sstevel@tonic-gate prfreenode(pnp);
59827c478bd9Sstevel@tonic-gate return;
59837c478bd9Sstevel@tonic-gate default:
59847c478bd9Sstevel@tonic-gate break;
59857c478bd9Sstevel@tonic-gate }
59867c478bd9Sstevel@tonic-gate
59877c478bd9Sstevel@tonic-gate mutex_enter(&pr_pidlock);
59887c478bd9Sstevel@tonic-gate if (pnp->pr_pcommon == NULL)
59897c478bd9Sstevel@tonic-gate p = NULL;
59907c478bd9Sstevel@tonic-gate else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
59917c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
59927c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock);
59937c478bd9Sstevel@tonic-gate
59947c478bd9Sstevel@tonic-gate if (type == PR_PROCDIR || vp->v_count > 1) {
5995ade42b55SSebastien Roy VN_RELE_LOCKED(vp);
59967c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock);
59977c478bd9Sstevel@tonic-gate if (p != NULL)
59987c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
59997c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
60007c478bd9Sstevel@tonic-gate return;
60017c478bd9Sstevel@tonic-gate }
60027c478bd9Sstevel@tonic-gate
60037c478bd9Sstevel@tonic-gate if ((dp = pnp->pr_parent) != NULL) {
60047c478bd9Sstevel@tonic-gate prnode_t *dpnp;
60057c478bd9Sstevel@tonic-gate
60067c478bd9Sstevel@tonic-gate switch (type) {
60077c478bd9Sstevel@tonic-gate case PR_PIDFILE:
60087c478bd9Sstevel@tonic-gate case PR_LWPIDFILE:
60097c478bd9Sstevel@tonic-gate case PR_OPAGEDATA:
60107c478bd9Sstevel@tonic-gate break;
60117c478bd9Sstevel@tonic-gate default:
60127c478bd9Sstevel@tonic-gate dpnp = VTOP(dp);
60137c478bd9Sstevel@tonic-gate mutex_enter(&dpnp->pr_mutex);
60147c478bd9Sstevel@tonic-gate if (dpnp->pr_files != NULL &&
60157c478bd9Sstevel@tonic-gate dpnp->pr_files[pnp->pr_index] == vp)
60167c478bd9Sstevel@tonic-gate dpnp->pr_files[pnp->pr_index] = NULL;
60177c478bd9Sstevel@tonic-gate mutex_exit(&dpnp->pr_mutex);
60187c478bd9Sstevel@tonic-gate break;
60197c478bd9Sstevel@tonic-gate }
60207c478bd9Sstevel@tonic-gate pnp->pr_parent = NULL;
60217c478bd9Sstevel@tonic-gate }
60227c478bd9Sstevel@tonic-gate
60237c478bd9Sstevel@tonic-gate ASSERT(vp->v_count == 1);
60247c478bd9Sstevel@tonic-gate
60257c478bd9Sstevel@tonic-gate /*
60267c478bd9Sstevel@tonic-gate * If we allocated an old /proc/pid node, free it too.
60277c478bd9Sstevel@tonic-gate */
60287c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
60297c478bd9Sstevel@tonic-gate ASSERT(type == PR_PIDDIR);
60307c478bd9Sstevel@tonic-gate ovp = pnp->pr_pidfile;
60317c478bd9Sstevel@tonic-gate opnp = VTOP(ovp);
60327c478bd9Sstevel@tonic-gate ASSERT(opnp->pr_type == PR_PIDFILE);
60337c478bd9Sstevel@tonic-gate pnp->pr_pidfile = NULL;
60347c478bd9Sstevel@tonic-gate }
60357c478bd9Sstevel@tonic-gate
60367c478bd9Sstevel@tonic-gate mutex_exit(&pr_pidlock);
60377c478bd9Sstevel@tonic-gate
60387c478bd9Sstevel@tonic-gate if (p != NULL) {
60397c478bd9Sstevel@tonic-gate /*
60407c478bd9Sstevel@tonic-gate * Remove the vnodes from the lists of
60417c478bd9Sstevel@tonic-gate * /proc vnodes for the process.
60427c478bd9Sstevel@tonic-gate */
60437c478bd9Sstevel@tonic-gate int slot;
60447c478bd9Sstevel@tonic-gate
60457c478bd9Sstevel@tonic-gate switch (type) {
60467c478bd9Sstevel@tonic-gate case PR_PIDDIR:
60477c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &p->p_trace);
60487c478bd9Sstevel@tonic-gate break;
60497c478bd9Sstevel@tonic-gate case PR_LWPIDDIR:
60507c478bd9Sstevel@tonic-gate if ((slot = pnp->pr_common->prc_tslot) != -1) {
60517c478bd9Sstevel@tonic-gate lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
60527c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &lep->le_trace);
60537c478bd9Sstevel@tonic-gate }
60547c478bd9Sstevel@tonic-gate break;
60557c478bd9Sstevel@tonic-gate default:
60567c478bd9Sstevel@tonic-gate pr_list_unlink(vp, &p->p_plist);
60577c478bd9Sstevel@tonic-gate break;
60587c478bd9Sstevel@tonic-gate }
60597c478bd9Sstevel@tonic-gate if (ovp != NULL)
60607c478bd9Sstevel@tonic-gate pr_list_unlink(ovp, &p->p_plist);
60617c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
60627c478bd9Sstevel@tonic-gate }
60637c478bd9Sstevel@tonic-gate
60647c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock);
60657c478bd9Sstevel@tonic-gate
60667c478bd9Sstevel@tonic-gate if (type == PR_CT && pnp->pr_contract != NULL) {
60677c478bd9Sstevel@tonic-gate contract_rele(pnp->pr_contract);
60687c478bd9Sstevel@tonic-gate pnp->pr_contract = NULL;
60697c478bd9Sstevel@tonic-gate }
60707c478bd9Sstevel@tonic-gate
60717c478bd9Sstevel@tonic-gate if (opnp != NULL)
60727c478bd9Sstevel@tonic-gate prfreenode(opnp);
60737c478bd9Sstevel@tonic-gate prfreenode(pnp);
60747c478bd9Sstevel@tonic-gate if (dp != NULL) {
60757c478bd9Sstevel@tonic-gate VN_RELE(dp);
60767c478bd9Sstevel@tonic-gate }
60777c478bd9Sstevel@tonic-gate }
60787c478bd9Sstevel@tonic-gate
60797c478bd9Sstevel@tonic-gate /* ARGSUSED */
60807c478bd9Sstevel@tonic-gate static int
prseek(vnode_t * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)6081da6c28aaSamw prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
60827c478bd9Sstevel@tonic-gate {
60837c478bd9Sstevel@tonic-gate return (0);
60847c478bd9Sstevel@tonic-gate }
60857c478bd9Sstevel@tonic-gate
60867c478bd9Sstevel@tonic-gate /*
60877c478bd9Sstevel@tonic-gate * We use the p_execdir member of proc_t to expand the %d token in core file
60887c478bd9Sstevel@tonic-gate * paths (the directory path for the executable that dumped core; see
6089bbf21555SRichard Lowe * coreadm(8) for details). We'd like gcore(1) to be able to expand %d in
60907c478bd9Sstevel@tonic-gate * the same way as core dumping from the kernel, but there's no convenient
60917c478bd9Sstevel@tonic-gate * and comprehensible way to export the path name for p_execdir. To solve
60927c478bd9Sstevel@tonic-gate * this, we try to find the actual path to the executable that was used. In
60937c478bd9Sstevel@tonic-gate * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
60947c478bd9Sstevel@tonic-gate * flag, and use that here to indicate that more work is needed beyond the
60957c478bd9Sstevel@tonic-gate * call to vnodetopath().
60967c478bd9Sstevel@tonic-gate */
60977c478bd9Sstevel@tonic-gate static int
prreadlink_lookup(prnode_t * pnp,char * buf,size_t size,cred_t * cr)60987c478bd9Sstevel@tonic-gate prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
60997c478bd9Sstevel@tonic-gate {
61007c478bd9Sstevel@tonic-gate proc_t *p;
61017c478bd9Sstevel@tonic-gate vnode_t *vp, *execvp, *vrootp;
61027c478bd9Sstevel@tonic-gate int ret;
61037c478bd9Sstevel@tonic-gate size_t len;
61047c478bd9Sstevel@tonic-gate dirent64_t *dp;
61057c478bd9Sstevel@tonic-gate size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
61067c478bd9Sstevel@tonic-gate char *dbuf;
61077c478bd9Sstevel@tonic-gate
61087c478bd9Sstevel@tonic-gate p = curproc;
61097c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
61107c478bd9Sstevel@tonic-gate if ((vrootp = PTOU(p)->u_rdir) == NULL)
61117c478bd9Sstevel@tonic-gate vrootp = rootdir;
61127c478bd9Sstevel@tonic-gate VN_HOLD(vrootp);
61137c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
61147c478bd9Sstevel@tonic-gate
61157c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
61167c478bd9Sstevel@tonic-gate
61177c478bd9Sstevel@tonic-gate /*
61187c478bd9Sstevel@tonic-gate * If PR_AOUT isn't set, then we looked up the path for the vnode;
61197c478bd9Sstevel@tonic-gate * otherwise, we looked up the path for (what we believe to be) the
61207c478bd9Sstevel@tonic-gate * containing directory.
61217c478bd9Sstevel@tonic-gate */
61227c478bd9Sstevel@tonic-gate if ((pnp->pr_flags & PR_AOUT) == 0) {
61237c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
61247c478bd9Sstevel@tonic-gate return (ret);
61257c478bd9Sstevel@tonic-gate }
61267c478bd9Sstevel@tonic-gate
61277c478bd9Sstevel@tonic-gate /*
61287c478bd9Sstevel@tonic-gate * Fail if there's a problem locking the process. This will only
61297c478bd9Sstevel@tonic-gate * occur if the process is changing so the information we would
61307c478bd9Sstevel@tonic-gate * report would already be invalid.
61317c478bd9Sstevel@tonic-gate */
61327c478bd9Sstevel@tonic-gate if (prlock(pnp, ZNO) != 0) {
61337c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
61347c478bd9Sstevel@tonic-gate return (EIO);
61357c478bd9Sstevel@tonic-gate }
61367c478bd9Sstevel@tonic-gate
61377c478bd9Sstevel@tonic-gate p = pnp->pr_common->prc_proc;
61387c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
61397c478bd9Sstevel@tonic-gate
61407c478bd9Sstevel@tonic-gate execvp = p->p_exec;
61417c478bd9Sstevel@tonic-gate VN_HOLD(execvp);
61427c478bd9Sstevel@tonic-gate
61437c478bd9Sstevel@tonic-gate /*
61447c478bd9Sstevel@tonic-gate * If our initial lookup of the directory failed, fall back to
61457c478bd9Sstevel@tonic-gate * the path name information for p_exec.
61467c478bd9Sstevel@tonic-gate */
61477c478bd9Sstevel@tonic-gate if (ret != 0) {
61487c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
61497c478bd9Sstevel@tonic-gate prunlock(pnp);
61507c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, execvp, buf, size, cr);
61517c478bd9Sstevel@tonic-gate VN_RELE(execvp);
61527c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
61537c478bd9Sstevel@tonic-gate return (ret);
61547c478bd9Sstevel@tonic-gate }
61557c478bd9Sstevel@tonic-gate
61567c478bd9Sstevel@tonic-gate len = strlen(buf);
61577c478bd9Sstevel@tonic-gate
61587c478bd9Sstevel@tonic-gate /*
61597c478bd9Sstevel@tonic-gate * We use u_comm as a guess for the last component of the full
61607c478bd9Sstevel@tonic-gate * executable path name. If there isn't going to be enough space
61617c478bd9Sstevel@tonic-gate * we fall back to using the p_exec so that we can have _an_
61627c478bd9Sstevel@tonic-gate * answer even if it's not perfect.
61637c478bd9Sstevel@tonic-gate */
61647c478bd9Sstevel@tonic-gate if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
61657c478bd9Sstevel@tonic-gate buf[len] = '/';
61667c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
61677c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
61687c478bd9Sstevel@tonic-gate prunlock(pnp);
61697c478bd9Sstevel@tonic-gate
61707c478bd9Sstevel@tonic-gate /*
61717c478bd9Sstevel@tonic-gate * Do a forward lookup of our u_comm guess.
61727c478bd9Sstevel@tonic-gate */
61737c478bd9Sstevel@tonic-gate if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
61747c478bd9Sstevel@tonic-gate &vp, pnp->pr_realvp) == 0) {
61757c478bd9Sstevel@tonic-gate if (vn_compare(vp, execvp)) {
61767c478bd9Sstevel@tonic-gate VN_RELE(vp);
61777c478bd9Sstevel@tonic-gate VN_RELE(execvp);
61787c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
61797c478bd9Sstevel@tonic-gate return (0);
61807c478bd9Sstevel@tonic-gate }
61817c478bd9Sstevel@tonic-gate
61827c478bd9Sstevel@tonic-gate VN_RELE(vp);
61837c478bd9Sstevel@tonic-gate }
61847c478bd9Sstevel@tonic-gate } else {
61857c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
61867c478bd9Sstevel@tonic-gate prunlock(pnp);
61877c478bd9Sstevel@tonic-gate }
61887c478bd9Sstevel@tonic-gate
61897c478bd9Sstevel@tonic-gate dbuf = kmem_alloc(dlen, KM_SLEEP);
61907c478bd9Sstevel@tonic-gate
61917c478bd9Sstevel@tonic-gate /*
61927c478bd9Sstevel@tonic-gate * Try to find a matching vnode by iterating through the directory's
61937c478bd9Sstevel@tonic-gate * entries. If that fails, fall back to the path information for
61947c478bd9Sstevel@tonic-gate * p_exec.
61957c478bd9Sstevel@tonic-gate */
61967c478bd9Sstevel@tonic-gate if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
61977c478bd9Sstevel@tonic-gate dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
61987c478bd9Sstevel@tonic-gate buf[len] = '/';
61997c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, dp->d_name);
62007c478bd9Sstevel@tonic-gate } else {
62017c478bd9Sstevel@tonic-gate ret = vnodetopath(vrootp, execvp, buf, size, cr);
62027c478bd9Sstevel@tonic-gate }
62037c478bd9Sstevel@tonic-gate
62047c478bd9Sstevel@tonic-gate kmem_free(dbuf, dlen);
62057c478bd9Sstevel@tonic-gate VN_RELE(execvp);
62067c478bd9Sstevel@tonic-gate VN_RELE(vrootp);
62077c478bd9Sstevel@tonic-gate
62087c478bd9Sstevel@tonic-gate return (ret);
62097c478bd9Sstevel@tonic-gate }
62107c478bd9Sstevel@tonic-gate
62117c478bd9Sstevel@tonic-gate /* ARGSUSED */
62127c478bd9Sstevel@tonic-gate static int
prreadlink(vnode_t * vp,uio_t * uiop,cred_t * cr,caller_context_t * ctp)6213da6c28aaSamw prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
62147c478bd9Sstevel@tonic-gate {
62157c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
62167c478bd9Sstevel@tonic-gate char *buf;
62177c478bd9Sstevel@tonic-gate int ret = EINVAL;
62187c478bd9Sstevel@tonic-gate char idbuf[16];
62197c478bd9Sstevel@tonic-gate int length, rlength;
62207c478bd9Sstevel@tonic-gate contract_t *ct;
62217c478bd9Sstevel@tonic-gate
62227c478bd9Sstevel@tonic-gate switch (pnp->pr_type) {
62237c478bd9Sstevel@tonic-gate case PR_SELF:
62247c478bd9Sstevel@tonic-gate (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
62257c478bd9Sstevel@tonic-gate ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
62267c478bd9Sstevel@tonic-gate break;
62277c478bd9Sstevel@tonic-gate case PR_OBJECT:
62287c478bd9Sstevel@tonic-gate case PR_FD:
62297c478bd9Sstevel@tonic-gate case PR_CURDIR:
62307c478bd9Sstevel@tonic-gate case PR_ROOTDIR:
62317c478bd9Sstevel@tonic-gate if (pnp->pr_realvp->v_type == VDIR)
62327c478bd9Sstevel@tonic-gate ret = 0;
62337c478bd9Sstevel@tonic-gate break;
62347c478bd9Sstevel@tonic-gate case PR_PATH:
62357c478bd9Sstevel@tonic-gate buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
62367c478bd9Sstevel@tonic-gate
62377c478bd9Sstevel@tonic-gate if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
62387c478bd9Sstevel@tonic-gate ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
62397c478bd9Sstevel@tonic-gate
62407c478bd9Sstevel@tonic-gate kmem_free(buf, MAXPATHLEN);
62417c478bd9Sstevel@tonic-gate break;
62427c478bd9Sstevel@tonic-gate case PR_CT:
62437c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_contract != NULL);
62447c478bd9Sstevel@tonic-gate ct = pnp->pr_contract;
62457c478bd9Sstevel@tonic-gate length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
62467c478bd9Sstevel@tonic-gate strlen(ct->ct_type->ct_type_name);
62477c478bd9Sstevel@tonic-gate buf = kmem_alloc(length, KM_SLEEP);
62487c478bd9Sstevel@tonic-gate rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
62497c478bd9Sstevel@tonic-gate ct->ct_type->ct_type_name, ct->ct_id);
62507c478bd9Sstevel@tonic-gate ASSERT(rlength < length);
62517c478bd9Sstevel@tonic-gate ret = uiomove(buf, rlength, UIO_READ, uiop);
62527c478bd9Sstevel@tonic-gate kmem_free(buf, length);
62537c478bd9Sstevel@tonic-gate break;
62547c478bd9Sstevel@tonic-gate default:
62557c478bd9Sstevel@tonic-gate break;
62567c478bd9Sstevel@tonic-gate }
62577c478bd9Sstevel@tonic-gate
62587c478bd9Sstevel@tonic-gate return (ret);
62597c478bd9Sstevel@tonic-gate }
62607c478bd9Sstevel@tonic-gate
6261da6c28aaSamw /*ARGSUSED2*/
62627c478bd9Sstevel@tonic-gate static int
prcmp(vnode_t * vp1,vnode_t * vp2,caller_context_t * ct)6263da6c28aaSamw prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
62647c478bd9Sstevel@tonic-gate {
62657c478bd9Sstevel@tonic-gate prnode_t *pp1, *pp2;
62667c478bd9Sstevel@tonic-gate
62677c478bd9Sstevel@tonic-gate if (vp1 == vp2)
62687c478bd9Sstevel@tonic-gate return (1);
62697c478bd9Sstevel@tonic-gate
62707c478bd9Sstevel@tonic-gate if (!vn_matchops(vp1, prvnodeops) || !vn_matchops(vp2, prvnodeops))
62717c478bd9Sstevel@tonic-gate return (0);
62727c478bd9Sstevel@tonic-gate
62737c478bd9Sstevel@tonic-gate pp1 = VTOP(vp1);
62747c478bd9Sstevel@tonic-gate pp2 = VTOP(vp2);
62757c478bd9Sstevel@tonic-gate
62767c478bd9Sstevel@tonic-gate if (pp1->pr_type != pp2->pr_type)
62777c478bd9Sstevel@tonic-gate return (0);
62787c478bd9Sstevel@tonic-gate if (pp1->pr_type == PR_PROCDIR)
62797c478bd9Sstevel@tonic-gate return (1);
62807c478bd9Sstevel@tonic-gate if (pp1->pr_ino || pp2->pr_ino)
62817c478bd9Sstevel@tonic-gate return (pp2->pr_ino == pp1->pr_ino);
62827c478bd9Sstevel@tonic-gate
62837c478bd9Sstevel@tonic-gate if (pp1->pr_common == NULL || pp2->pr_common == NULL)
62847c478bd9Sstevel@tonic-gate return (0);
62857c478bd9Sstevel@tonic-gate
62867c478bd9Sstevel@tonic-gate return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
62877c478bd9Sstevel@tonic-gate pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
62887c478bd9Sstevel@tonic-gate }
62897c478bd9Sstevel@tonic-gate
62907c478bd9Sstevel@tonic-gate static int
prrealvp(vnode_t * vp,vnode_t ** vpp,caller_context_t * ct)6291da6c28aaSamw prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
62927c478bd9Sstevel@tonic-gate {
62937c478bd9Sstevel@tonic-gate vnode_t *rvp;
62947c478bd9Sstevel@tonic-gate
62957c478bd9Sstevel@tonic-gate if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
62967c478bd9Sstevel@tonic-gate vp = rvp;
6297da6c28aaSamw if (VOP_REALVP(vp, &rvp, ct) == 0)
62987c478bd9Sstevel@tonic-gate vp = rvp;
62997c478bd9Sstevel@tonic-gate }
63007c478bd9Sstevel@tonic-gate
63017c478bd9Sstevel@tonic-gate *vpp = vp;
63027c478bd9Sstevel@tonic-gate return (0);
63037c478bd9Sstevel@tonic-gate }
63047c478bd9Sstevel@tonic-gate
63057c478bd9Sstevel@tonic-gate /*
63067c478bd9Sstevel@tonic-gate * Return the answer requested to poll().
63077c478bd9Sstevel@tonic-gate * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
63087c478bd9Sstevel@tonic-gate * In addition, these have special meaning for /proc files:
63097c478bd9Sstevel@tonic-gate * POLLPRI process or lwp stopped on an event of interest
63107c478bd9Sstevel@tonic-gate * POLLERR /proc file descriptor is invalid
63117c478bd9Sstevel@tonic-gate * POLLHUP process or lwp has terminated
63127c478bd9Sstevel@tonic-gate */
6313da6c28aaSamw /*ARGSUSED5*/
63147c478bd9Sstevel@tonic-gate static int
prpoll(vnode_t * vp,short events,int anyyet,short * reventsp,pollhead_t ** phpp,caller_context_t * ct)63157c478bd9Sstevel@tonic-gate prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
6316da6c28aaSamw pollhead_t **phpp, caller_context_t *ct)
63177c478bd9Sstevel@tonic-gate {
63187c478bd9Sstevel@tonic-gate prnode_t *pnp = VTOP(vp);
63197c478bd9Sstevel@tonic-gate prcommon_t *pcp = pnp->pr_common;
63207c478bd9Sstevel@tonic-gate pollhead_t *php = &pcp->prc_pollhead;
63217c478bd9Sstevel@tonic-gate proc_t *p;
63227c478bd9Sstevel@tonic-gate short revents;
63237c478bd9Sstevel@tonic-gate int error;
63247c478bd9Sstevel@tonic-gate int lockstate;
63257c478bd9Sstevel@tonic-gate
63267c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type < PR_NFILES);
63277c478bd9Sstevel@tonic-gate
63287c478bd9Sstevel@tonic-gate /*
63297c478bd9Sstevel@tonic-gate * Support for old /proc interface.
63307c478bd9Sstevel@tonic-gate */
63317c478bd9Sstevel@tonic-gate if (pnp->pr_pidfile != NULL) {
63327c478bd9Sstevel@tonic-gate vp = pnp->pr_pidfile;
63337c478bd9Sstevel@tonic-gate pnp = VTOP(vp);
63347c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_type == PR_PIDFILE);
63357c478bd9Sstevel@tonic-gate ASSERT(pnp->pr_common == pcp);
63367c478bd9Sstevel@tonic-gate }
63377c478bd9Sstevel@tonic-gate
63387c478bd9Sstevel@tonic-gate *reventsp = revents = 0;
63397c478bd9Sstevel@tonic-gate *phpp = (pollhead_t *)NULL;
63407c478bd9Sstevel@tonic-gate
63417c478bd9Sstevel@tonic-gate if (vp->v_type == VDIR) {
63427c478bd9Sstevel@tonic-gate *reventsp |= POLLNVAL;
63437c478bd9Sstevel@tonic-gate return (0);
63447c478bd9Sstevel@tonic-gate }
63457c478bd9Sstevel@tonic-gate
6346f3bb54f3SPatrick Mooney /* avoid deadlock with prnotify() */
6347f3bb54f3SPatrick Mooney if (pollunlock(&lockstate) != 0) {
6348f3bb54f3SPatrick Mooney *reventsp = POLLNVAL;
6349f3bb54f3SPatrick Mooney return (0);
6350f3bb54f3SPatrick Mooney }
63517c478bd9Sstevel@tonic-gate
63527c478bd9Sstevel@tonic-gate if ((error = prlock(pnp, ZNO)) != 0) {
63537c478bd9Sstevel@tonic-gate pollrelock(lockstate);
63547c478bd9Sstevel@tonic-gate switch (error) {
63557c478bd9Sstevel@tonic-gate case ENOENT: /* process or lwp died */
63567c478bd9Sstevel@tonic-gate *reventsp = POLLHUP;
63577c478bd9Sstevel@tonic-gate error = 0;
63587c478bd9Sstevel@tonic-gate break;
63597c478bd9Sstevel@tonic-gate case EAGAIN: /* invalidated */
63607c478bd9Sstevel@tonic-gate *reventsp = POLLERR;
63617c478bd9Sstevel@tonic-gate error = 0;
63627c478bd9Sstevel@tonic-gate break;
63637c478bd9Sstevel@tonic-gate }
63647c478bd9Sstevel@tonic-gate return (error);
63657c478bd9Sstevel@tonic-gate }
63667c478bd9Sstevel@tonic-gate
63677c478bd9Sstevel@tonic-gate /*
63687c478bd9Sstevel@tonic-gate * We have the process marked locked (P_PR_LOCK) and we are holding
63697c478bd9Sstevel@tonic-gate * its p->p_lock. We want to unmark the process but retain
63707c478bd9Sstevel@tonic-gate * exclusive control w.r.t. other /proc controlling processes
63717c478bd9Sstevel@tonic-gate * before reacquiring the polling locks.
63727c478bd9Sstevel@tonic-gate *
63737c478bd9Sstevel@tonic-gate * prunmark() does this for us. It unmarks the process
63747c478bd9Sstevel@tonic-gate * but retains p->p_lock so we still have exclusive control.
63757c478bd9Sstevel@tonic-gate * We will drop p->p_lock at the end to relinquish control.
63767c478bd9Sstevel@tonic-gate *
63777c478bd9Sstevel@tonic-gate * We cannot call prunlock() at the end to relinquish control
63787c478bd9Sstevel@tonic-gate * because prunlock(), like prunmark(), may drop and reacquire
63797c478bd9Sstevel@tonic-gate * p->p_lock and that would lead to a lock order violation
63807c478bd9Sstevel@tonic-gate * w.r.t. the polling locks we are about to reacquire.
63817c478bd9Sstevel@tonic-gate */
63827c478bd9Sstevel@tonic-gate p = pcp->prc_proc;
63837c478bd9Sstevel@tonic-gate ASSERT(p != NULL);
63847c478bd9Sstevel@tonic-gate prunmark(p);
63857c478bd9Sstevel@tonic-gate
63867c478bd9Sstevel@tonic-gate pollrelock(lockstate); /* reacquire dropped poll locks */
63877c478bd9Sstevel@tonic-gate
63887c478bd9Sstevel@tonic-gate if ((p->p_flag & SSYS) || p->p_as == &kas)
63897c478bd9Sstevel@tonic-gate revents = POLLNVAL;
63907c478bd9Sstevel@tonic-gate else {
63917c478bd9Sstevel@tonic-gate short ev;
63927c478bd9Sstevel@tonic-gate
63937c478bd9Sstevel@tonic-gate if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
63947c478bd9Sstevel@tonic-gate revents |= ev;
63957c478bd9Sstevel@tonic-gate /*
63967c478bd9Sstevel@tonic-gate * POLLWRNORM (same as POLLOUT) really should not be
63977c478bd9Sstevel@tonic-gate * used to indicate that the process or lwp stopped.
63987c478bd9Sstevel@tonic-gate * However, USL chose to use POLLWRNORM rather than
63997c478bd9Sstevel@tonic-gate * POLLPRI to indicate this, so we just accept either
64007c478bd9Sstevel@tonic-gate * requested event to indicate stopped. (grr...)
64017c478bd9Sstevel@tonic-gate */
64027c478bd9Sstevel@tonic-gate if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
64037c478bd9Sstevel@tonic-gate kthread_t *t;
64047c478bd9Sstevel@tonic-gate
64057c478bd9Sstevel@tonic-gate if (pcp->prc_flags & PRC_LWP) {
64067c478bd9Sstevel@tonic-gate t = pcp->prc_thread;
64077c478bd9Sstevel@tonic-gate ASSERT(t != NULL);
64087c478bd9Sstevel@tonic-gate thread_lock(t);
64097c478bd9Sstevel@tonic-gate } else {
64107c478bd9Sstevel@tonic-gate t = prchoose(p); /* returns locked t */
64117c478bd9Sstevel@tonic-gate ASSERT(t != NULL);
64127c478bd9Sstevel@tonic-gate }
64137c478bd9Sstevel@tonic-gate
64147c478bd9Sstevel@tonic-gate if (ISTOPPED(t) || VSTOPPED(t))
64157c478bd9Sstevel@tonic-gate revents |= ev;
64167c478bd9Sstevel@tonic-gate thread_unlock(t);
64177c478bd9Sstevel@tonic-gate }
64187c478bd9Sstevel@tonic-gate }
64197c478bd9Sstevel@tonic-gate
64207c478bd9Sstevel@tonic-gate *reventsp = revents;
6421a5eb7107SBryan Cantrill if ((!anyyet && revents == 0) || (events & POLLET)) {
64227c478bd9Sstevel@tonic-gate /*
64237c478bd9Sstevel@tonic-gate * Arrange to wake up the polling lwp when
64247c478bd9Sstevel@tonic-gate * the target process/lwp stops or terminates
64257c478bd9Sstevel@tonic-gate * or when the file descriptor becomes invalid.
64267c478bd9Sstevel@tonic-gate */
64277c478bd9Sstevel@tonic-gate pcp->prc_flags |= PRC_POLL;
64287c478bd9Sstevel@tonic-gate *phpp = php;
64297c478bd9Sstevel@tonic-gate }
64307c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
64317c478bd9Sstevel@tonic-gate return (0);
64327c478bd9Sstevel@tonic-gate }
64337c478bd9Sstevel@tonic-gate
64347c478bd9Sstevel@tonic-gate /* in prioctl.c */
6435da6c28aaSamw extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
6436da6c28aaSamw caller_context_t *);
64377c478bd9Sstevel@tonic-gate
64387c478bd9Sstevel@tonic-gate /*
64397c478bd9Sstevel@tonic-gate * /proc vnode operations vector
64407c478bd9Sstevel@tonic-gate */
64417c478bd9Sstevel@tonic-gate const fs_operation_def_t pr_vnodeops_template[] = {
6442aa59c4cbSrsb VOPNAME_OPEN, { .vop_open = propen },
6443aa59c4cbSrsb VOPNAME_CLOSE, { .vop_close = prclose },
6444aa59c4cbSrsb VOPNAME_READ, { .vop_read = prread },
6445aa59c4cbSrsb VOPNAME_WRITE, { .vop_write = prwrite },
6446aa59c4cbSrsb VOPNAME_IOCTL, { .vop_ioctl = prioctl },
6447aa59c4cbSrsb VOPNAME_GETATTR, { .vop_getattr = prgetattr },
6448aa59c4cbSrsb VOPNAME_ACCESS, { .vop_access = praccess },
6449aa59c4cbSrsb VOPNAME_LOOKUP, { .vop_lookup = prlookup },
6450aa59c4cbSrsb VOPNAME_CREATE, { .vop_create = prcreate },
6451aa59c4cbSrsb VOPNAME_READDIR, { .vop_readdir = prreaddir },
6452aa59c4cbSrsb VOPNAME_READLINK, { .vop_readlink = prreadlink },
6453aa59c4cbSrsb VOPNAME_FSYNC, { .vop_fsync = prfsync },
6454aa59c4cbSrsb VOPNAME_INACTIVE, { .vop_inactive = prinactive },
6455aa59c4cbSrsb VOPNAME_SEEK, { .vop_seek = prseek },
6456aa59c4cbSrsb VOPNAME_CMP, { .vop_cmp = prcmp },
6457aa59c4cbSrsb VOPNAME_FRLOCK, { .error = fs_error },
6458aa59c4cbSrsb VOPNAME_REALVP, { .vop_realvp = prrealvp },
6459aa59c4cbSrsb VOPNAME_POLL, { .vop_poll = prpoll },
6460aa59c4cbSrsb VOPNAME_DISPOSE, { .error = fs_error },
6461aa59c4cbSrsb VOPNAME_SHRLOCK, { .error = fs_error },
64627c478bd9Sstevel@tonic-gate NULL, NULL
64637c478bd9Sstevel@tonic-gate };
6464