6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2018, Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/cred.h>
35 #include <sys/policy.h>
36 #include <sys/debug.h>
37 #include <sys/dirent.h>
38 #include <sys/errno.h>
39 #include <sys/file.h>
40 #include <sys/inline.h>
41 #include <sys/kmem.h>
42 #include <sys/pathname.h>
43 #include <sys/proc.h>
44 #include <sys/brand.h>
45 #include <sys/signal.h>
137 { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
138 "cred" },
139 { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
140 "sigact" },
141 { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
142 "auxv" },
143 { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
144 "usage" },
145 { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
146 "lusage" },
147 { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
148 "pagedata" },
149 { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
150 "watch" },
151 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
152 "cwd" },
153 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
154 "root" },
155 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
156 "fd" },
157 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
158 "object" },
159 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
160 "lwp" },
161 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
162 "priv" },
163 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
164 "path" },
165 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
166 "contracts" },
167 { PR_SECFLAGS, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
168 "secflags" },
169 #if defined(__x86)
170 { PR_LDT, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
171 "ldt" },
172 #endif
173 };
174
175 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
176
177 /*
178 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
179 */
180 static prdirent_t lwpiddir[] = {
181 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
182 "." },
183 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
184 ".." },
185 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
186 "lwpctl" },
187 { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
579 }
580
581 /*
582 * Array of read functions, indexed by /proc file type.
583 */
584 static int pr_read_inval(), pr_read_as(), pr_read_status(),
585 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
586 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
587 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
588 #if defined(__x86)
589 pr_read_ldt(),
590 #endif
591 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
592 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
593 pr_read_lwpusage(), pr_read_lwpname(),
594 pr_read_xregs(), pr_read_priv(),
595 pr_read_spymaster(), pr_read_secflags(),
596 #if defined(__sparc)
597 pr_read_gwindows(), pr_read_asrs(),
598 #endif
599 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
600
601 static int (*pr_read_function[PR_NFILES])() = {
602 pr_read_inval, /* /proc */
603 pr_read_inval, /* /proc/self */
604 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
605 pr_read_as, /* /proc/<pid>/as */
606 pr_read_inval, /* /proc/<pid>/ctl */
607 pr_read_status, /* /proc/<pid>/status */
608 pr_read_lstatus, /* /proc/<pid>/lstatus */
609 pr_read_psinfo, /* /proc/<pid>/psinfo */
610 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
611 pr_read_map, /* /proc/<pid>/map */
612 pr_read_rmap, /* /proc/<pid>/rmap */
613 pr_read_xmap, /* /proc/<pid>/xmap */
614 pr_read_cred, /* /proc/<pid>/cred */
615 pr_read_sigact, /* /proc/<pid>/sigact */
616 pr_read_auxv, /* /proc/<pid>/auxv */
617 #if defined(__x86)
618 pr_read_ldt, /* /proc/<pid>/ldt */
619 #endif
620 pr_read_usage, /* /proc/<pid>/usage */
621 pr_read_lusage, /* /proc/<pid>/lusage */
622 pr_read_pagedata, /* /proc/<pid>/pagedata */
623 pr_read_watch, /* /proc/<pid>/watch */
624 pr_read_inval, /* /proc/<pid>/cwd */
625 pr_read_inval, /* /proc/<pid>/root */
626 pr_read_inval, /* /proc/<pid>/fd */
627 pr_read_inval, /* /proc/<pid>/fd/nn */
628 pr_read_inval, /* /proc/<pid>/object */
629 pr_read_inval, /* /proc/<pid>/object/xxx */
630 pr_read_inval, /* /proc/<pid>/lwp */
631 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
632 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
633 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
634 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
635 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
636 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
637 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
638 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
639 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
640 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
641 #if defined(__sparc)
642 pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
643 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
644 #endif
645 pr_read_priv, /* /proc/<pid>/priv */
646 pr_read_inval, /* /proc/<pid>/path */
647 pr_read_inval, /* /proc/<pid>/path/xxx */
796
797 /*
798 * We don't want the full treatment of prlock(pnp) here.
799 * This file is world-readable and never goes invalid.
800 * It doesn't matter if we are in the middle of an exec().
801 */
802 p = pr_p_lock(pnp);
803 mutex_exit(&pr_pidlock);
804 if (p == NULL)
805 error = ENOENT;
806 else {
807 ASSERT(p == pnp->pr_common->prc_proc);
808 prgetpsinfo(p, &psinfo);
809 prunlock(pnp);
810 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
811 }
812 return (error);
813 }
814
815 static int
816 pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
817 {
818 proc_t *p;
819 kthread_t *t;
820 lwpdir_t *ldp;
821 lwpent_t *lep;
822 size_t size;
823 prheader_t *php;
824 lwpsinfo_t *sp;
825 int error;
826 int nlwp;
827 int i;
828
829 ASSERT(pnp->pr_type == PR_LPSINFO);
830
831 /*
832 * We don't want the full treatment of prlock(pnp) here.
833 * This file is world-readable and never goes invalid.
834 * It doesn't matter if we are in the middle of an exec().
835 */
1818 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1819 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1820 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1821 pr_read_map_32, /* /proc/<pid>/map */
1822 pr_read_rmap_32, /* /proc/<pid>/rmap */
1823 pr_read_xmap_32, /* /proc/<pid>/xmap */
1824 pr_read_cred, /* /proc/<pid>/cred */
1825 pr_read_sigact_32, /* /proc/<pid>/sigact */
1826 pr_read_auxv_32, /* /proc/<pid>/auxv */
1827 #if defined(__x86)
1828 pr_read_ldt, /* /proc/<pid>/ldt */
1829 #endif
1830 pr_read_usage_32, /* /proc/<pid>/usage */
1831 pr_read_lusage_32, /* /proc/<pid>/lusage */
1832 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1833 pr_read_watch_32, /* /proc/<pid>/watch */
1834 pr_read_inval, /* /proc/<pid>/cwd */
1835 pr_read_inval, /* /proc/<pid>/root */
1836 pr_read_inval, /* /proc/<pid>/fd */
1837 pr_read_inval, /* /proc/<pid>/fd/nn */
1838 pr_read_inval, /* /proc/<pid>/object */
1839 pr_read_inval, /* /proc/<pid>/object/xxx */
1840 pr_read_inval, /* /proc/<pid>/lwp */
1841 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1842 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1843 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
1844 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1845 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1846 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1847 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1848 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1849 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1850 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
1851 #if defined(__sparc)
1852 pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
1853 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
1854 #endif
1855 pr_read_priv, /* /proc/<pid>/priv */
1856 pr_read_inval, /* /proc/<pid>/path */
1857 pr_read_inval, /* /proc/<pid>/path/xxx */
3063 else {
3064 mutex_exit(&p->p_lock);
3065 AS_LOCK_ENTER(as, RW_WRITER);
3066 if (as->a_updatedir)
3067 rebuild_objdir(as);
3068 vap->va_size = (as->a_sizedir + 4 +
3069 P_FINFO(p)->fi_nfiles) * PRSDSIZE;
3070 AS_LOCK_EXIT(as);
3071 mutex_enter(&p->p_lock);
3072 }
3073 vap->va_nlink = 2;
3074 break;
3075 case PR_PATH:
3076 case PR_CURDIR:
3077 case PR_ROOTDIR:
3078 case PR_CT:
3079 vap->va_type = VLNK;
3080 vap->va_size = 0;
3081 break;
3082 case PR_FDDIR:
3083 vap->va_nlink = 2;
3084 vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
3085 break;
3086 case PR_LWPDIR:
3087 /*
3088 * va_nlink: count each lwp as a directory link.
3089 * va_size: size of p_lwpdir + 2
3090 */
3091 vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
3092 vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
3093 break;
3094 case PR_LWPIDDIR:
3095 vap->va_nlink = 2;
3096 vap->va_size = sizeof (lwpiddir);
3097 break;
3098 case PR_CTDIR:
3099 vap->va_nlink = 2;
3100 vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
3101 break;
3102 case PR_TMPLDIR:
3103 vap->va_nlink = 2;
3104 vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
3105 break;
3390 return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
3391 }
3392
3393 /*
3394 * Visceral revulsion: For compatibility with old /proc,
3395 * allow the /proc/<pid> directory to be opened for writing.
3396 */
3397 vmode = pnp->pr_mode;
3398 if (type == PR_PIDDIR)
3399 vmode |= VWRITE;
3400 if ((vmode & mode) != mode)
3401 error = secpolicy_proc_access(cr);
3402 return (error);
3403 }
3404
3405 /*
3406 * Array of lookup functions, indexed by /proc file type.
3407 */
3408 static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3409 *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3410 *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
3411 *pr_lookup_ctdir();
3412
3413 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3414 pr_lookup_procdir, /* /proc */
3415 pr_lookup_notdir, /* /proc/self */
3416 pr_lookup_piddir, /* /proc/<pid> */
3417 pr_lookup_notdir, /* /proc/<pid>/as */
3418 pr_lookup_notdir, /* /proc/<pid>/ctl */
3419 pr_lookup_notdir, /* /proc/<pid>/status */
3420 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3421 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3422 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3423 pr_lookup_notdir, /* /proc/<pid>/map */
3424 pr_lookup_notdir, /* /proc/<pid>/rmap */
3425 pr_lookup_notdir, /* /proc/<pid>/xmap */
3426 pr_lookup_notdir, /* /proc/<pid>/cred */
3427 pr_lookup_notdir, /* /proc/<pid>/sigact */
3428 pr_lookup_notdir, /* /proc/<pid>/auxv */
3429 #if defined(__x86)
3430 pr_lookup_notdir, /* /proc/<pid>/ldt */
3431 #endif
3432 pr_lookup_notdir, /* /proc/<pid>/usage */
3433 pr_lookup_notdir, /* /proc/<pid>/lusage */
3434 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3435 pr_lookup_notdir, /* /proc/<pid>/watch */
3436 pr_lookup_notdir, /* /proc/<pid>/cwd */
3437 pr_lookup_notdir, /* /proc/<pid>/root */
3438 pr_lookup_fddir, /* /proc/<pid>/fd */
3439 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3440 pr_lookup_objectdir, /* /proc/<pid>/object */
3441 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3442 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3443 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3444 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3445 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
3446 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3447 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3448 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3449 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3450 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3451 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3452 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
3453 #if defined(__sparc)
3454 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
3455 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
3456 #endif
3457 pr_lookup_notdir, /* /proc/<pid>/priv */
3458 pr_lookup_pathdir, /* /proc/<pid>/path */
3459 pr_lookup_notdir, /* /proc/<pid>/path/xxx */
3507 * Since the resulting vnode is highly likely to be at some
3508 * abitrary position in another filesystem, we insist that the
3509 * VTRAVERSE flag is set on the parent. This prevents things
3510 * such as the v_path freshness logic from mistaking the
3511 * resulting vnode as a "real" child of the parent, rather than
3512 * a consequence of this "procfs wormhole".
3513 *
3514 * Failure to establish such protections can lead to
3515 * incorrectly calculated v_paths being set on nodes reached
3516 * through these lookups.
3517 */
3518 ASSERT((dp->v_flag & VTRAVERSE) != 0);
3519
3520 dp = pnp->pr_realvp;
3521 return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3522 direntflags, realpnp));
3523 default:
3524 break;
3525 }
3526
3527 if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
3528 (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3529 return (error);
3530
3531 /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3532 *vpp = (pr_lookup_function[type](dp, comp));
3533
3534 return ((*vpp == NULL) ? ENOENT : 0);
3535 }
3536
3537 /* ARGSUSED */
3538 static int
3539 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3540 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3541 vsecattr_t *vsecp)
3542 {
3543 int error;
3544
3545 if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3546 ct, NULL, NULL)) != 0) {
3547 if (error == ENOENT) {
4121 p->p_plist = vp;
4122 }
4123 mutex_exit(&dpnp->pr_mutex);
4124 prunlock(dpnp);
4125 return (vp);
4126 }
4127
4128 /*
4129 * Lookup one of the process's open files.
4130 */
4131 static vnode_t *
4132 pr_lookup_fddir(vnode_t *dp, char *comp)
4133 {
4134 prnode_t *dpnp = VTOP(dp);
4135 prnode_t *pnp;
4136 vnode_t *vp = NULL;
4137 proc_t *p;
4138 file_t *fp;
4139 uint_t fd;
4140 int c;
4141 uf_entry_t *ufp;
4142 uf_info_t *fip;
4143
4144 ASSERT(dpnp->pr_type == PR_FDDIR);
4145
4146 fd = 0;
4147 while ((c = *comp++) != '\0') {
4148 int ofd;
4149 if (c < '0' || c > '9')
4150 return (NULL);
4151 ofd = fd;
4152 fd = 10*fd + c - '0';
4153 if (fd/10 != ofd) /* integer overflow */
4154 return (NULL);
4155 }
4156
4157 pnp = prgetnode(dp, PR_FD);
4158
4159 if (prlock(dpnp, ZNO) != 0) {
4160 prfreenode(pnp);
4161 return (NULL);
4162 }
4163 p = dpnp->pr_common->prc_proc;
4164 if ((p->p_flag & SSYS) || p->p_as == &kas) {
4165 prunlock(dpnp);
4166 prfreenode(pnp);
4167 return (NULL);
4168 }
4169
4170 fip = P_FINFO(p);
4171 mutex_exit(&p->p_lock);
4172 mutex_enter(&fip->fi_lock);
4173 if (fd < fip->fi_nfiles) {
4174 UF_ENTER(ufp, fip, fd);
4175 if ((fp = ufp->uf_file) != NULL) {
4176 pnp->pr_mode = 07111;
4177 if (fp->f_flag & FREAD)
4178 pnp->pr_mode |= 0444;
4179 if (fp->f_flag & FWRITE)
4180 pnp->pr_mode |= 0222;
4181 vp = fp->f_vnode;
4182 VN_HOLD(vp);
4183 }
4184 UF_EXIT(ufp);
4185 }
4186 mutex_exit(&fip->fi_lock);
4187 mutex_enter(&p->p_lock);
4188 prunlock(dpnp);
4189
4190 if (vp == NULL)
4191 prfreenode(pnp);
4192 else {
4193 /*
4194 * Fill in the prnode so future references will
4195 * be able to find the underlying object's vnode.
4196 * Don't link this prnode into the list of all
4197 * prnodes for the process; this is a one-use node.
4198 */
4199 pnp->pr_realvp = vp;
4200 pnp->pr_parent = dp; /* needed for prlookup */
4201 VN_HOLD(dp);
4202 vp = PTOV(pnp);
4203 if (pnp->pr_realvp->v_type == VDIR) {
4204 vp->v_type = VDIR;
4205 vp->v_flag |= VTRAVERSE;
4206 }
4207 }
4208
4209 return (vp);
4210 }
4211
4212 static vnode_t *
4213 pr_lookup_pathdir(vnode_t *dp, char *comp)
4214 {
4215 prnode_t *dpnp = VTOP(dp);
4216 prnode_t *pnp;
4217 vnode_t *vp = NULL;
4218 proc_t *p;
4219 uint_t fd, flags = 0;
4220 int c;
4221 uf_entry_t *ufp;
4222 uf_info_t *fip;
4223 enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
4224 char *tmp;
4225 int idx;
4226 struct seg *seg;
4227 struct as *as = NULL;
4228 vattr_t vattr;
4650 * as we must support compatibility mode with old /proc.
4651 * Make /proc/<pid> be read by owner only, search by all.
4652 * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
4653 * set VDIROPEN on /proc/<pid> so it can be opened for writing.
4654 */
4655 if (type == PR_PIDDIR) {
4656 /* kludge for old /proc interface */
4657 prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
4658 pnp->pr_pidfile = PTOV(xpnp);
4659 pnp->pr_mode = 0511;
4660 vp->v_flag |= VDIROPEN;
4661 } else {
4662 pnp->pr_mode = 0555;
4663 }
4664
4665 break;
4666
4667 case PR_CURDIR:
4668 case PR_ROOTDIR:
4669 case PR_FDDIR:
4670 case PR_OBJECTDIR:
4671 case PR_PATHDIR:
4672 case PR_CTDIR:
4673 case PR_TMPLDIR:
4674 vp->v_type = VDIR;
4675 pnp->pr_mode = 0500; /* read-search by owner only */
4676 break;
4677
4678 case PR_CT:
4679 vp->v_type = VLNK;
4680 pnp->pr_mode = 0500; /* read-search by owner only */
4681 break;
4682
4683 case PR_PATH:
4684 case PR_SELF:
4685 vp->v_type = VLNK;
4686 pnp->pr_mode = 0777;
4687 break;
4688
4689 case PR_LWPDIR:
4782 ASSERT(pcp->prc_refcnt > 0);
4783 if (--pcp->prc_refcnt != 0)
4784 mutex_exit(&pcp->prc_mutex);
4785 else {
4786 mutex_exit(&pcp->prc_mutex);
4787 ASSERT(pcp->prc_pollhead.ph_list == NULL);
4788 ASSERT(pcp->prc_refcnt == 0);
4789 ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
4790 mutex_destroy(&pcp->prc_mutex);
4791 cv_destroy(&pcp->prc_wait);
4792 kmem_free(pcp, sizeof (prcommon_t));
4793 DECREMENT(nprcommon);
4794 }
4795 }
4796
4797 /*
4798 * Array of readdir functions, indexed by /proc file type.
4799 */
4800 static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4801 pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4802 pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
4803 pr_readdir_ctdir();
4804
4805 static int (*pr_readdir_function[PR_NFILES])() = {
4806 pr_readdir_procdir, /* /proc */
4807 pr_readdir_notdir, /* /proc/self */
4808 pr_readdir_piddir, /* /proc/<pid> */
4809 pr_readdir_notdir, /* /proc/<pid>/as */
4810 pr_readdir_notdir, /* /proc/<pid>/ctl */
4811 pr_readdir_notdir, /* /proc/<pid>/status */
4812 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4813 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4814 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4815 pr_readdir_notdir, /* /proc/<pid>/map */
4816 pr_readdir_notdir, /* /proc/<pid>/rmap */
4817 pr_readdir_notdir, /* /proc/<pid>/xmap */
4818 pr_readdir_notdir, /* /proc/<pid>/cred */
4819 pr_readdir_notdir, /* /proc/<pid>/sigact */
4820 pr_readdir_notdir, /* /proc/<pid>/auxv */
4821 #if defined(__x86)
4822 pr_readdir_notdir, /* /proc/<pid>/ldt */
4823 #endif
4824 pr_readdir_notdir, /* /proc/<pid>/usage */
4825 pr_readdir_notdir, /* /proc/<pid>/lusage */
4826 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4827 pr_readdir_notdir, /* /proc/<pid>/watch */
4828 pr_readdir_notdir, /* /proc/<pid>/cwd */
4829 pr_readdir_notdir, /* /proc/<pid>/root */
4830 pr_readdir_fddir, /* /proc/<pid>/fd */
4831 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4832 pr_readdir_objectdir, /* /proc/<pid>/object */
4833 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4834 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4835 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4836 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4837 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
4838 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4839 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4840 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4841 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4842 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4843 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4844 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4845 #if defined(__sparc)
4846 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
4847 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
4848 #endif
4849 pr_readdir_notdir, /* /proc/<pid>/priv */
4850 pr_readdir_pathdir, /* /proc/<pid>/path */
4851 pr_readdir_notdir, /* /proc/<pid>/path/xxx */
5344 /* the asrs file exists only for sparc v9 _LP64 processes */
5345 if (dirp->d_ino == PR_ASRS &&
5346 pcp->prc_datamodel != DATAMODEL_LP64)
5347 continue;
5348 #endif
5349 bcopy(dirp, &dirent, sizeof (prdirent_t));
5350 if (dirent.d_ino == PR_LWPDIR)
5351 dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5352 else
5353 dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5354 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5355 UIO_READ, uiop)) != 0)
5356 return (error);
5357 }
5358 out:
5359 if (eofp)
5360 *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5361 return (0);
5362 }
5363
5364 /* ARGSUSED */
5365 static int
5366 pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5367 {
5368 gfs_readdir_state_t gstate;
5369 int error, eof = 0;
5370 offset_t n;
5371 proc_t *p;
5372 int pslot;
5373 int fddirsize;
5374 uf_info_t *fip;
5375
5376 ASSERT(pnp->pr_type == PR_FDDIR);
5377
5378 if ((error = prlock(pnp, ZNO)) != 0)
5379 return (error);
5380 p = pnp->pr_common->prc_proc;
5381 pslot = p->p_slot;
5382 fip = P_FINFO(p);
5383 mutex_exit(&p->p_lock);
5384
5385 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5386 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
5387 mutex_enter(&p->p_lock);
5388 prunlock(pnp);
5389 return (error);
5390 }
5391
5392 mutex_enter(&fip->fi_lock);
5393 if ((p->p_flag & SSYS) || p->p_as == &kas)
5394 fddirsize = 0;
5395 else
5396 fddirsize = fip->fi_nfiles;
5397
5398 /*
5399 * Loop until user's request is satisfied or until
5400 * all file descriptors have been examined.
5401 */
5402 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5403 /*
5404 * Find next fd.
5405 */
5406 while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5407 n++;
5408 /*
5409 * Stop when all fds have been reported.
5410 */
5411 if (n >= fddirsize) {
5412 eof = 1;
5413 break;
5414 }
5415
5416 error = gfs_readdir_emitn(&gstate, uiop, n,
5417 pmkino(n, pslot, PR_FD), n);
5418 if (error)
5419 break;
5420 }
5421
5422 mutex_exit(&fip->fi_lock);
5423 mutex_enter(&p->p_lock);
5424 prunlock(pnp);
5425
5426 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5427 }
5428
5429 /* ARGSUSED */
5430 static int
5431 pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5432 {
5433 longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5434 dirent64_t *dirent = (dirent64_t *)bp;
5435 int reclen;
5436 ssize_t oresid;
5437 offset_t off, idx;
5438 int error = 0;
5439 proc_t *p;
5440 int fd, obj;
5441 int pslot;
5442 int fddirsize;
5443 uf_info_t *fip;
5444 struct as *as = NULL;
5445 size_t objdirsize;
5446 vattr_t vattr;
5447 vnode_t *vp;
5448
5718 break;
5719 }
5720 listp = &pnp->pr_next;
5721 }
5722 }
5723
5724 /* ARGSUSED */
5725 static void
5726 prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5727 {
5728 prnode_t *pnp = VTOP(vp);
5729 prnodetype_t type = pnp->pr_type;
5730 proc_t *p;
5731 vnode_t *dp;
5732 vnode_t *ovp = NULL;
5733 prnode_t *opnp = NULL;
5734
5735 switch (type) {
5736 case PR_OBJECT:
5737 case PR_FD:
5738 case PR_SELF:
5739 case PR_PATH:
5740 /* These are not linked into the usual lists */
5741 ASSERT(vp->v_count == 1);
5742 if ((dp = pnp->pr_parent) != NULL)
5743 VN_RELE(dp);
5744 prfreenode(pnp);
5745 return;
5746 default:
5747 break;
5748 }
5749
5750 mutex_enter(&pr_pidlock);
5751 if (pnp->pr_pcommon == NULL)
5752 p = NULL;
5753 else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
5754 mutex_enter(&p->p_lock);
5755 mutex_enter(&vp->v_lock);
5756
5757 if (type == PR_PROCDIR || vp->v_count > 1) {
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2018, Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
26 * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
27 */
28
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/time.h>
35 #include <sys/cred.h>
36 #include <sys/policy.h>
37 #include <sys/debug.h>
38 #include <sys/dirent.h>
39 #include <sys/errno.h>
40 #include <sys/file.h>
41 #include <sys/inline.h>
42 #include <sys/kmem.h>
43 #include <sys/pathname.h>
44 #include <sys/proc.h>
45 #include <sys/brand.h>
46 #include <sys/signal.h>
138 { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
139 "cred" },
140 { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
141 "sigact" },
142 { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
143 "auxv" },
144 { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
145 "usage" },
146 { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
147 "lusage" },
148 { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
149 "pagedata" },
150 { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
151 "watch" },
152 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
153 "cwd" },
154 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
155 "root" },
156 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
157 "fd" },
158 { PR_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
159 "fdinfo" },
160 { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
161 "object" },
162 { PR_LWPDIR, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
163 "lwp" },
164 { PR_PRIV, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
165 "priv" },
166 { PR_PATHDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "path" },
168 { PR_CTDIR, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
169 "contracts" },
170 { PR_SECFLAGS, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
171 "secflags" },
172 #if defined(__x86)
173 { PR_LDT, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
174 "ldt" },
175 #endif
176 };
177
178 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
179
180 /*
181 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
182 */
183 static prdirent_t lwpiddir[] = {
184 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
185 "." },
186 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
187 ".." },
188 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
189 "lwpctl" },
190 { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
582 }
583
584 /*
585 * Array of read functions, indexed by /proc file type.
586 */
587 static int pr_read_inval(), pr_read_as(), pr_read_status(),
588 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
589 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
590 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
591 #if defined(__x86)
592 pr_read_ldt(),
593 #endif
594 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
595 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
596 pr_read_lwpusage(), pr_read_lwpname(),
597 pr_read_xregs(), pr_read_priv(),
598 pr_read_spymaster(), pr_read_secflags(),
599 #if defined(__sparc)
600 pr_read_gwindows(), pr_read_asrs(),
601 #endif
602 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
603 pr_read_fdinfo();
604
605 static int (*pr_read_function[PR_NFILES])() = {
606 pr_read_inval, /* /proc */
607 pr_read_inval, /* /proc/self */
608 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
609 pr_read_as, /* /proc/<pid>/as */
610 pr_read_inval, /* /proc/<pid>/ctl */
611 pr_read_status, /* /proc/<pid>/status */
612 pr_read_lstatus, /* /proc/<pid>/lstatus */
613 pr_read_psinfo, /* /proc/<pid>/psinfo */
614 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
615 pr_read_map, /* /proc/<pid>/map */
616 pr_read_rmap, /* /proc/<pid>/rmap */
617 pr_read_xmap, /* /proc/<pid>/xmap */
618 pr_read_cred, /* /proc/<pid>/cred */
619 pr_read_sigact, /* /proc/<pid>/sigact */
620 pr_read_auxv, /* /proc/<pid>/auxv */
621 #if defined(__x86)
622 pr_read_ldt, /* /proc/<pid>/ldt */
623 #endif
624 pr_read_usage, /* /proc/<pid>/usage */
625 pr_read_lusage, /* /proc/<pid>/lusage */
626 pr_read_pagedata, /* /proc/<pid>/pagedata */
627 pr_read_watch, /* /proc/<pid>/watch */
628 pr_read_inval, /* /proc/<pid>/cwd */
629 pr_read_inval, /* /proc/<pid>/root */
630 pr_read_inval, /* /proc/<pid>/fd */
631 pr_read_inval, /* /proc/<pid>/fd/nn */
632 pr_read_inval, /* /proc/<pid>/fdinfo */
633 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
634 pr_read_inval, /* /proc/<pid>/object */
635 pr_read_inval, /* /proc/<pid>/object/xxx */
636 pr_read_inval, /* /proc/<pid>/lwp */
637 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
638 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
639 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
640 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
641 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
642 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
643 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
644 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
645 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
646 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
647 #if defined(__sparc)
648 pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
649 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
650 #endif
651 pr_read_priv, /* /proc/<pid>/priv */
652 pr_read_inval, /* /proc/<pid>/path */
653 pr_read_inval, /* /proc/<pid>/path/xxx */
802
803 /*
804 * We don't want the full treatment of prlock(pnp) here.
805 * This file is world-readable and never goes invalid.
806 * It doesn't matter if we are in the middle of an exec().
807 */
808 p = pr_p_lock(pnp);
809 mutex_exit(&pr_pidlock);
810 if (p == NULL)
811 error = ENOENT;
812 else {
813 ASSERT(p == pnp->pr_common->prc_proc);
814 prgetpsinfo(p, &psinfo);
815 prunlock(pnp);
816 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
817 }
818 return (error);
819 }
820
821 static int
822 pr_read_fdinfo(prnode_t *pnp, uio_t *uiop)
823 {
824 prfdinfov2_t *fdinfo;
825 list_t data;
826 proc_t *p;
827 vnode_t *vp;
828 uint_t fd;
829 file_t *fp;
830 cred_t *cred;
831 short ufp_flag;
832 int error = 0;
833
834 ASSERT(pnp->pr_type == PR_FDINFO);
835
836 /*
837 * This is a guess at the size of the structure that needs to
838 * be returned. It's a balance between not allocating too much more
839 * space than is required and not requiring too many subsequent
840 * reallocations. Allocate it before acquiring the process lock.
841 */
842 pr_iol_initlist(&data, sizeof (prfdinfov2_t) + MAXPATHLEN + 2, 1);
843
844 if ((error = prlock(pnp, ZNO)) != 0) {
845 pr_iol_freelist(&data);
846 return (error);
847 }
848
849 p = pnp->pr_common->prc_proc;
850
851 if ((p->p_flag & SSYS) || p->p_as == &kas) {
852 prunlock(pnp);
853 pr_iol_freelist(&data);
854 return (0);
855 }
856
857 fd = pnp->pr_index;
858
859 /* Fetch and lock the file_t for this descriptor */
860 fp = pr_getf(p, fd, &ufp_flag);
861
862 if (fp == NULL) {
863 error = ENOENT;
864 prunlock(pnp);
865 goto out;
866 }
867
868 vp = fp->f_vnode;
869 VN_HOLD(vp);
870
871 /*
872 * For fdinfo, we don't want to include the placeholder pr_misc at the
873 * end of the struct. We'll termninate the data with an empty pr_misc
874 * header before returning.
875 */
876
877 fdinfo = pr_iol_newbuf(&data, offsetof(prfdinfov2_t, pr_misc));
878 fdinfo->pr_fd = fd;
879 fdinfo->pr_fdflags = ufp_flag;
880 fdinfo->pr_fileflags = fp->f_flag2 << 16 | fp->f_flag;
881 if ((fdinfo->pr_fileflags & (FSEARCH | FEXEC)) == 0)
882 fdinfo->pr_fileflags += FOPEN;
883 fdinfo->pr_offset = fp->f_offset;
884 cred = fp->f_cred;
885 crhold(cred);
886 pr_releasef(p, fd);
887
888 prunlock(pnp);
889
890 error = prgetfdinfo(p, vp, fdinfo, cred, &data);
891
892 crfree(cred);
893
894 VN_RELE(vp);
895
896 out:
897 if (error == 0)
898 error = pr_iol_uiomove_and_free(&data, uiop, error);
899 else
900 pr_iol_freelist(&data);
901
902 return (error);
903 }
904
905 static int
906 pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
907 {
908 proc_t *p;
909 kthread_t *t;
910 lwpdir_t *ldp;
911 lwpent_t *lep;
912 size_t size;
913 prheader_t *php;
914 lwpsinfo_t *sp;
915 int error;
916 int nlwp;
917 int i;
918
919 ASSERT(pnp->pr_type == PR_LPSINFO);
920
921 /*
922 * We don't want the full treatment of prlock(pnp) here.
923 * This file is world-readable and never goes invalid.
924 * It doesn't matter if we are in the middle of an exec().
925 */
1908 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1909 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1910 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1911 pr_read_map_32, /* /proc/<pid>/map */
1912 pr_read_rmap_32, /* /proc/<pid>/rmap */
1913 pr_read_xmap_32, /* /proc/<pid>/xmap */
1914 pr_read_cred, /* /proc/<pid>/cred */
1915 pr_read_sigact_32, /* /proc/<pid>/sigact */
1916 pr_read_auxv_32, /* /proc/<pid>/auxv */
1917 #if defined(__x86)
1918 pr_read_ldt, /* /proc/<pid>/ldt */
1919 #endif
1920 pr_read_usage_32, /* /proc/<pid>/usage */
1921 pr_read_lusage_32, /* /proc/<pid>/lusage */
1922 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1923 pr_read_watch_32, /* /proc/<pid>/watch */
1924 pr_read_inval, /* /proc/<pid>/cwd */
1925 pr_read_inval, /* /proc/<pid>/root */
1926 pr_read_inval, /* /proc/<pid>/fd */
1927 pr_read_inval, /* /proc/<pid>/fd/nn */
1928 pr_read_inval, /* /proc/<pid>/fdinfo */
1929 pr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
1930 pr_read_inval, /* /proc/<pid>/object */
1931 pr_read_inval, /* /proc/<pid>/object/xxx */
1932 pr_read_inval, /* /proc/<pid>/lwp */
1933 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1934 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1935 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
1936 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1937 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1938 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1939 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1940 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1941 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1942 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
1943 #if defined(__sparc)
1944 pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
1945 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
1946 #endif
1947 pr_read_priv, /* /proc/<pid>/priv */
1948 pr_read_inval, /* /proc/<pid>/path */
1949 pr_read_inval, /* /proc/<pid>/path/xxx */
3155 else {
3156 mutex_exit(&p->p_lock);
3157 AS_LOCK_ENTER(as, RW_WRITER);
3158 if (as->a_updatedir)
3159 rebuild_objdir(as);
3160 vap->va_size = (as->a_sizedir + 4 +
3161 P_FINFO(p)->fi_nfiles) * PRSDSIZE;
3162 AS_LOCK_EXIT(as);
3163 mutex_enter(&p->p_lock);
3164 }
3165 vap->va_nlink = 2;
3166 break;
3167 case PR_PATH:
3168 case PR_CURDIR:
3169 case PR_ROOTDIR:
3170 case PR_CT:
3171 vap->va_type = VLNK;
3172 vap->va_size = 0;
3173 break;
3174 case PR_FDDIR:
3175 case PR_FDINFODIR:
3176 vap->va_nlink = 2;
3177 vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
3178 break;
3179 case PR_FDINFO: {
3180 file_t *fp;
3181 vnode_t *vp;
3182 int fd = pnp->pr_index;
3183
3184 fp = pr_getf(p, fd, NULL);
3185 if (fp == NULL) {
3186 prunlock(pnp);
3187 return (ENOENT);
3188 }
3189 vp = fp->f_vnode;
3190 VN_HOLD(vp);
3191 pr_releasef(p, fd);
3192 prunlock(pnp);
3193 vap->va_size = prgetfdinfosize(p, vp, cr);
3194 VN_RELE(vp);
3195 /* prunlock() has already been called. */
3196 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3197 return (0);
3198 }
3199 case PR_LWPDIR:
3200 /*
3201 * va_nlink: count each lwp as a directory link.
3202 * va_size: size of p_lwpdir + 2
3203 */
3204 vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
3205 vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
3206 break;
3207 case PR_LWPIDDIR:
3208 vap->va_nlink = 2;
3209 vap->va_size = sizeof (lwpiddir);
3210 break;
3211 case PR_CTDIR:
3212 vap->va_nlink = 2;
3213 vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
3214 break;
3215 case PR_TMPLDIR:
3216 vap->va_nlink = 2;
3217 vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
3218 break;
3503 return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
3504 }
3505
3506 /*
3507 * Visceral revulsion: For compatibility with old /proc,
3508 * allow the /proc/<pid> directory to be opened for writing.
3509 */
3510 vmode = pnp->pr_mode;
3511 if (type == PR_PIDDIR)
3512 vmode |= VWRITE;
3513 if ((vmode & mode) != mode)
3514 error = secpolicy_proc_access(cr);
3515 return (error);
3516 }
3517
3518 /*
3519 * Array of lookup functions, indexed by /proc file type.
3520 */
3521 static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3522 *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3523 *pr_lookup_fddir(), *pr_lookup_fdinfodir(), *pr_lookup_pathdir(),
3524 *pr_lookup_tmpldir(), *pr_lookup_ctdir();
3525
3526 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3527 pr_lookup_procdir, /* /proc */
3528 pr_lookup_notdir, /* /proc/self */
3529 pr_lookup_piddir, /* /proc/<pid> */
3530 pr_lookup_notdir, /* /proc/<pid>/as */
3531 pr_lookup_notdir, /* /proc/<pid>/ctl */
3532 pr_lookup_notdir, /* /proc/<pid>/status */
3533 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3534 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3535 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3536 pr_lookup_notdir, /* /proc/<pid>/map */
3537 pr_lookup_notdir, /* /proc/<pid>/rmap */
3538 pr_lookup_notdir, /* /proc/<pid>/xmap */
3539 pr_lookup_notdir, /* /proc/<pid>/cred */
3540 pr_lookup_notdir, /* /proc/<pid>/sigact */
3541 pr_lookup_notdir, /* /proc/<pid>/auxv */
3542 #if defined(__x86)
3543 pr_lookup_notdir, /* /proc/<pid>/ldt */
3544 #endif
3545 pr_lookup_notdir, /* /proc/<pid>/usage */
3546 pr_lookup_notdir, /* /proc/<pid>/lusage */
3547 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3548 pr_lookup_notdir, /* /proc/<pid>/watch */
3549 pr_lookup_notdir, /* /proc/<pid>/cwd */
3550 pr_lookup_notdir, /* /proc/<pid>/root */
3551 pr_lookup_fddir, /* /proc/<pid>/fd */
3552 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3553 pr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */
3554 pr_lookup_notdir, /* /proc/<pid>/fdinfo/nn */
3555 pr_lookup_objectdir, /* /proc/<pid>/object */
3556 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3557 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3558 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3559 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3560 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
3561 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3562 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3563 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3564 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3565 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3566 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3567 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
3568 #if defined(__sparc)
3569 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
3570 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
3571 #endif
3572 pr_lookup_notdir, /* /proc/<pid>/priv */
3573 pr_lookup_pathdir, /* /proc/<pid>/path */
3574 pr_lookup_notdir, /* /proc/<pid>/path/xxx */
3622 * Since the resulting vnode is highly likely to be at some
3623 * abitrary position in another filesystem, we insist that the
3624 * VTRAVERSE flag is set on the parent. This prevents things
3625 * such as the v_path freshness logic from mistaking the
3626 * resulting vnode as a "real" child of the parent, rather than
3627 * a consequence of this "procfs wormhole".
3628 *
3629 * Failure to establish such protections can lead to
3630 * incorrectly calculated v_paths being set on nodes reached
3631 * through these lookups.
3632 */
3633 ASSERT((dp->v_flag & VTRAVERSE) != 0);
3634
3635 dp = pnp->pr_realvp;
3636 return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3637 direntflags, realpnp));
3638 default:
3639 break;
3640 }
3641
3642 if ((type == PR_OBJECTDIR || type == PR_FDDIR ||
3643 type == PR_FDINFODIR || type == PR_PATHDIR) &&
3644 (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3645 return (error);
3646
3647 /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3648 *vpp = (pr_lookup_function[type](dp, comp));
3649
3650 return ((*vpp == NULL) ? ENOENT : 0);
3651 }
3652
3653 /* ARGSUSED */
3654 static int
3655 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3656 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3657 vsecattr_t *vsecp)
3658 {
3659 int error;
3660
3661 if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3662 ct, NULL, NULL)) != 0) {
3663 if (error == ENOENT) {
4237 p->p_plist = vp;
4238 }
4239 mutex_exit(&dpnp->pr_mutex);
4240 prunlock(dpnp);
4241 return (vp);
4242 }
4243
4244 /*
4245 * Lookup one of the process's open files.
4246 */
4247 static vnode_t *
4248 pr_lookup_fddir(vnode_t *dp, char *comp)
4249 {
4250 prnode_t *dpnp = VTOP(dp);
4251 prnode_t *pnp;
4252 vnode_t *vp = NULL;
4253 proc_t *p;
4254 file_t *fp;
4255 uint_t fd;
4256 int c;
4257
4258 ASSERT(dpnp->pr_type == PR_FDDIR);
4259
4260 fd = 0;
4261 while ((c = *comp++) != '\0') {
4262 int ofd;
4263 if (c < '0' || c > '9')
4264 return (NULL);
4265 ofd = fd;
4266 fd = 10 * fd + c - '0';
4267 if (fd / 10 != ofd) /* integer overflow */
4268 return (NULL);
4269 }
4270
4271 pnp = prgetnode(dp, PR_FD);
4272
4273 if (prlock(dpnp, ZNO) != 0) {
4274 prfreenode(pnp);
4275 return (NULL);
4276 }
4277 p = dpnp->pr_common->prc_proc;
4278 if ((p->p_flag & SSYS) || p->p_as == &kas) {
4279 prunlock(dpnp);
4280 prfreenode(pnp);
4281 return (NULL);
4282 }
4283
4284 if ((fp = pr_getf(p, fd, NULL)) != NULL) {
4285 pnp->pr_mode = 07111;
4286 if (fp->f_flag & FREAD)
4287 pnp->pr_mode |= 0444;
4288 if (fp->f_flag & FWRITE)
4289 pnp->pr_mode |= 0222;
4290 vp = fp->f_vnode;
4291 VN_HOLD(vp);
4292 pr_releasef(p, fd);
4293 }
4294
4295 prunlock(dpnp);
4296
4297 if (vp == NULL) {
4298 prfreenode(pnp);
4299 return (NULL);
4300 }
4301
4302 /*
4303 * Fill in the prnode so future references will
4304 * be able to find the underlying object's vnode.
4305 * Don't link this prnode into the list of all
4306 * prnodes for the process; this is a one-use node.
4307 */
4308 pnp->pr_realvp = vp;
4309 pnp->pr_parent = dp; /* needed for prlookup */
4310 VN_HOLD(dp);
4311 vp = PTOV(pnp);
4312 if (pnp->pr_realvp->v_type == VDIR) {
4313 vp->v_type = VDIR;
4314 vp->v_flag |= VTRAVERSE;
4315 }
4316
4317 return (vp);
4318 }
4319
4320 static vnode_t *
4321 pr_lookup_fdinfodir(vnode_t *dp, char *comp)
4322 {
4323 prnode_t *dpnp = VTOP(dp);
4324 prnode_t *pnp;
4325 vnode_t *vp = NULL;
4326 proc_t *p;
4327 uint_t fd;
4328 int c;
4329
4330 ASSERT(dpnp->pr_type == PR_FDINFODIR);
4331
4332 fd = 0;
4333 while ((c = *comp++) != '\0') {
4334 int ofd;
4335 if (c < '0' || c > '9')
4336 return (NULL);
4337 ofd = fd;
4338 fd = 10 * fd + c - '0';
4339 if (fd / 10 != ofd) /* integer overflow */
4340 return (NULL);
4341 }
4342
4343 pnp = prgetnode(dp, PR_FDINFO);
4344
4345 if (prlock(dpnp, ZNO) != 0) {
4346 prfreenode(pnp);
4347 return (NULL);
4348 }
4349 p = dpnp->pr_common->prc_proc;
4350 if ((p->p_flag & SSYS) || p->p_as == &kas) {
4351 prunlock(dpnp);
4352 prfreenode(pnp);
4353 return (NULL);
4354 }
4355
4356 pnp->pr_common = dpnp->pr_common;
4357 pnp->pr_pcommon = dpnp->pr_pcommon;
4358 pnp->pr_parent = dp;
4359 pnp->pr_index = fd;
4360 VN_HOLD(dp);
4361 prunlock(dpnp);
4362 vp = PTOV(pnp);
4363
4364 return (vp);
4365 }
4366
4367 static vnode_t *
4368 pr_lookup_pathdir(vnode_t *dp, char *comp)
4369 {
4370 prnode_t *dpnp = VTOP(dp);
4371 prnode_t *pnp;
4372 vnode_t *vp = NULL;
4373 proc_t *p;
4374 uint_t fd, flags = 0;
4375 int c;
4376 uf_entry_t *ufp;
4377 uf_info_t *fip;
4378 enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
4379 char *tmp;
4380 int idx;
4381 struct seg *seg;
4382 struct as *as = NULL;
4383 vattr_t vattr;
4805 * as we must support compatibility mode with old /proc.
4806 * Make /proc/<pid> be read by owner only, search by all.
4807 * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
4808 * set VDIROPEN on /proc/<pid> so it can be opened for writing.
4809 */
4810 if (type == PR_PIDDIR) {
4811 /* kludge for old /proc interface */
4812 prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
4813 pnp->pr_pidfile = PTOV(xpnp);
4814 pnp->pr_mode = 0511;
4815 vp->v_flag |= VDIROPEN;
4816 } else {
4817 pnp->pr_mode = 0555;
4818 }
4819
4820 break;
4821
4822 case PR_CURDIR:
4823 case PR_ROOTDIR:
4824 case PR_FDDIR:
4825 case PR_FDINFODIR:
4826 case PR_OBJECTDIR:
4827 case PR_PATHDIR:
4828 case PR_CTDIR:
4829 case PR_TMPLDIR:
4830 vp->v_type = VDIR;
4831 pnp->pr_mode = 0500; /* read-search by owner only */
4832 break;
4833
4834 case PR_CT:
4835 vp->v_type = VLNK;
4836 pnp->pr_mode = 0500; /* read-search by owner only */
4837 break;
4838
4839 case PR_PATH:
4840 case PR_SELF:
4841 vp->v_type = VLNK;
4842 pnp->pr_mode = 0777;
4843 break;
4844
4845 case PR_LWPDIR:
4938 ASSERT(pcp->prc_refcnt > 0);
4939 if (--pcp->prc_refcnt != 0)
4940 mutex_exit(&pcp->prc_mutex);
4941 else {
4942 mutex_exit(&pcp->prc_mutex);
4943 ASSERT(pcp->prc_pollhead.ph_list == NULL);
4944 ASSERT(pcp->prc_refcnt == 0);
4945 ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
4946 mutex_destroy(&pcp->prc_mutex);
4947 cv_destroy(&pcp->prc_wait);
4948 kmem_free(pcp, sizeof (prcommon_t));
4949 DECREMENT(nprcommon);
4950 }
4951 }
4952
4953 /*
4954 * Array of readdir functions, indexed by /proc file type.
4955 */
4956 static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4957 pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4958 pr_readdir_fddir(), pr_readdir_fdinfodir(), pr_readdir_pathdir(),
4959 pr_readdir_tmpldir(), pr_readdir_ctdir();
4960
4961 static int (*pr_readdir_function[PR_NFILES])() = {
4962 pr_readdir_procdir, /* /proc */
4963 pr_readdir_notdir, /* /proc/self */
4964 pr_readdir_piddir, /* /proc/<pid> */
4965 pr_readdir_notdir, /* /proc/<pid>/as */
4966 pr_readdir_notdir, /* /proc/<pid>/ctl */
4967 pr_readdir_notdir, /* /proc/<pid>/status */
4968 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4969 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4970 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4971 pr_readdir_notdir, /* /proc/<pid>/map */
4972 pr_readdir_notdir, /* /proc/<pid>/rmap */
4973 pr_readdir_notdir, /* /proc/<pid>/xmap */
4974 pr_readdir_notdir, /* /proc/<pid>/cred */
4975 pr_readdir_notdir, /* /proc/<pid>/sigact */
4976 pr_readdir_notdir, /* /proc/<pid>/auxv */
4977 #if defined(__x86)
4978 pr_readdir_notdir, /* /proc/<pid>/ldt */
4979 #endif
4980 pr_readdir_notdir, /* /proc/<pid>/usage */
4981 pr_readdir_notdir, /* /proc/<pid>/lusage */
4982 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4983 pr_readdir_notdir, /* /proc/<pid>/watch */
4984 pr_readdir_notdir, /* /proc/<pid>/cwd */
4985 pr_readdir_notdir, /* /proc/<pid>/root */
4986 pr_readdir_fddir, /* /proc/<pid>/fd */
4987 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4988 pr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */
4989 pr_readdir_notdir, /* /proc/<pid>/fdinfo/nn */
4990 pr_readdir_objectdir, /* /proc/<pid>/object */
4991 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4992 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4993 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4994 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4995 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
4996 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4997 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4998 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4999 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
5000 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
5001 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
5002 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
5003 #if defined(__sparc)
5004 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
5005 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
5006 #endif
5007 pr_readdir_notdir, /* /proc/<pid>/priv */
5008 pr_readdir_pathdir, /* /proc/<pid>/path */
5009 pr_readdir_notdir, /* /proc/<pid>/path/xxx */
5502 /* the asrs file exists only for sparc v9 _LP64 processes */
5503 if (dirp->d_ino == PR_ASRS &&
5504 pcp->prc_datamodel != DATAMODEL_LP64)
5505 continue;
5506 #endif
5507 bcopy(dirp, &dirent, sizeof (prdirent_t));
5508 if (dirent.d_ino == PR_LWPDIR)
5509 dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5510 else
5511 dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5512 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5513 UIO_READ, uiop)) != 0)
5514 return (error);
5515 }
5516 out:
5517 if (eofp)
5518 *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5519 return (0);
5520 }
5521
5522 /*
5523 * Helper function for reading a directory which lists open file desciptors
5524 */
5525 static int
5526 pr_readdir_fdlist(prnode_t *pnp, uio_t *uiop, int *eofp,
5527 prnodetype_t dirtype, prnodetype_t entrytype)
5528 {
5529 gfs_readdir_state_t gstate;
5530 int error, eof = 0;
5531 offset_t n;
5532 proc_t *p;
5533 int pslot;
5534 int fddirsize;
5535 uf_info_t *fip;
5536
5537 if ((error = prlock(pnp, ZNO)) != 0)
5538 return (error);
5539 p = pnp->pr_common->prc_proc;
5540 pslot = p->p_slot;
5541 fip = P_FINFO(p);
5542 mutex_exit(&p->p_lock);
5543
5544 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5545 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, dirtype), 0)) != 0) {
5546 mutex_enter(&p->p_lock);
5547 prunlock(pnp);
5548 return (error);
5549 }
5550
5551 mutex_enter(&fip->fi_lock);
5552 if ((p->p_flag & SSYS) || p->p_as == &kas)
5553 fddirsize = 0;
5554 else
5555 fddirsize = fip->fi_nfiles;
5556
5557 /*
5558 * Loop until user's request is satisfied or until
5559 * all file descriptors have been examined.
5560 */
5561 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5562 /*
5563 * Find next fd.
5564 */
5565 while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5566 n++;
5567 /*
5568 * Stop when all fds have been reported.
5569 */
5570 if (n >= fddirsize) {
5571 eof = 1;
5572 break;
5573 }
5574
5575 error = gfs_readdir_emitn(&gstate, uiop, n,
5576 pmkino(n, pslot, entrytype), n);
5577 if (error)
5578 break;
5579 }
5580
5581 mutex_exit(&fip->fi_lock);
5582 mutex_enter(&p->p_lock);
5583 prunlock(pnp);
5584
5585 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5586 }
5587
5588 static int
5589 pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5590 {
5591
5592 ASSERT(pnp->pr_type == PR_FDDIR);
5593
5594 return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FD));
5595 }
5596
5597 static int
5598 pr_readdir_fdinfodir(prnode_t *pnp, uio_t *uiop, int *eofp)
5599 {
5600
5601 ASSERT(pnp->pr_type == PR_FDINFODIR);
5602
5603 return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FDINFO));
5604 }
5605
5606 /* ARGSUSED */
5607 static int
5608 pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5609 {
5610 longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5611 dirent64_t *dirent = (dirent64_t *)bp;
5612 int reclen;
5613 ssize_t oresid;
5614 offset_t off, idx;
5615 int error = 0;
5616 proc_t *p;
5617 int fd, obj;
5618 int pslot;
5619 int fddirsize;
5620 uf_info_t *fip;
5621 struct as *as = NULL;
5622 size_t objdirsize;
5623 vattr_t vattr;
5624 vnode_t *vp;
5625
5895 break;
5896 }
5897 listp = &pnp->pr_next;
5898 }
5899 }
5900
5901 /* ARGSUSED */
5902 static void
5903 prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5904 {
5905 prnode_t *pnp = VTOP(vp);
5906 prnodetype_t type = pnp->pr_type;
5907 proc_t *p;
5908 vnode_t *dp;
5909 vnode_t *ovp = NULL;
5910 prnode_t *opnp = NULL;
5911
5912 switch (type) {
5913 case PR_OBJECT:
5914 case PR_FD:
5915 case PR_FDDIR:
5916 case PR_SELF:
5917 case PR_PATH:
5918 /* These are not linked into the usual lists */
5919 ASSERT(vp->v_count == 1);
5920 if ((dp = pnp->pr_parent) != NULL)
5921 VN_RELE(dp);
5922 prfreenode(pnp);
5923 return;
5924 default:
5925 break;
5926 }
5927
5928 mutex_enter(&pr_pidlock);
5929 if (pnp->pr_pcommon == NULL)
5930 p = NULL;
5931 else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
5932 mutex_enter(&p->p_lock);
5933 mutex_enter(&vp->v_lock);
5934
5935 if (type == PR_PROCDIR || vp->v_count > 1) {
|