Print this page
12046 Provide /proc/<PID>/fdinfo/


   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) {