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