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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/proc/prvnops.c
          +++ new/usr/src/uts/common/fs/proc/prvnops.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2018, Joyent, Inc.
  25   25   * Copyright (c) 2017 by Delphix. All rights reserved.
       26 + * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  26   27   */
  27   28  
  28   29  /*      Copyright (c) 1984,      1986, 1987, 1988, 1989 AT&T    */
  29   30  /*        All Rights Reserved   */
  30   31  
  31   32  #include <sys/types.h>
  32   33  #include <sys/param.h>
  33   34  #include <sys/time.h>
  34   35  #include <sys/cred.h>
  35   36  #include <sys/policy.h>
↓ open down ↓ 111 lines elided ↑ open up ↑
 147  148          { PR_PAGEDATA,  17 * sizeof (prdirent_t), sizeof (prdirent_t),
 148  149                  "pagedata" },
 149  150          { PR_WATCH,     18 * sizeof (prdirent_t), sizeof (prdirent_t),
 150  151                  "watch" },
 151  152          { PR_CURDIR,    19 * sizeof (prdirent_t), sizeof (prdirent_t),
 152  153                  "cwd" },
 153  154          { PR_ROOTDIR,   20 * sizeof (prdirent_t), sizeof (prdirent_t),
 154  155                  "root" },
 155  156          { PR_FDDIR,     21 * sizeof (prdirent_t), sizeof (prdirent_t),
 156  157                  "fd" },
 157      -        { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
      158 +        { PR_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
      159 +                "fdinfo" },
      160 +        { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
 158  161                  "object" },
 159      -        { PR_LWPDIR,    23 * sizeof (prdirent_t), sizeof (prdirent_t),
      162 +        { PR_LWPDIR,    24 * sizeof (prdirent_t), sizeof (prdirent_t),
 160  163                  "lwp" },
 161      -        { PR_PRIV,      24 * sizeof (prdirent_t), sizeof (prdirent_t),
      164 +        { PR_PRIV,      25 * sizeof (prdirent_t), sizeof (prdirent_t),
 162  165                  "priv" },
 163      -        { PR_PATHDIR,   25 * sizeof (prdirent_t), sizeof (prdirent_t),
      166 +        { PR_PATHDIR,   26 * sizeof (prdirent_t), sizeof (prdirent_t),
 164  167                  "path" },
 165      -        { PR_CTDIR,     26 * sizeof (prdirent_t), sizeof (prdirent_t),
      168 +        { PR_CTDIR,     27 * sizeof (prdirent_t), sizeof (prdirent_t),
 166  169                  "contracts" },
 167      -        { PR_SECFLAGS,  27 * sizeof (prdirent_t), sizeof (prdirent_t),
      170 +        { PR_SECFLAGS,  28 * sizeof (prdirent_t), sizeof (prdirent_t),
 168  171                  "secflags" },
 169  172  #if defined(__x86)
 170  173          { PR_LDT,       28 * sizeof (prdirent_t), sizeof (prdirent_t),
 171  174                  "ldt" },
 172  175  #endif
 173  176  };
 174  177  
 175  178  #define NPIDDIRFILES    (sizeof (piddir) / sizeof (piddir[0]) - 2)
 176  179  
 177  180  /*
↓ open down ↓ 411 lines elided ↑ open up ↑
 589  592          pr_read_ldt(),
 590  593  #endif
 591  594          pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
 592  595          pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
 593  596          pr_read_lwpusage(), pr_read_lwpname(),
 594  597          pr_read_xregs(), pr_read_priv(),
 595  598          pr_read_spymaster(), pr_read_secflags(),
 596  599  #if defined(__sparc)
 597  600          pr_read_gwindows(), pr_read_asrs(),
 598  601  #endif
 599      -        pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
      602 +        pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
      603 +        pr_read_fdinfo();
 600  604  
 601  605  static int (*pr_read_function[PR_NFILES])() = {
 602  606          pr_read_inval,          /* /proc                                */
 603  607          pr_read_inval,          /* /proc/self                           */
 604  608          pr_read_piddir,         /* /proc/<pid> (old /proc read())       */
 605  609          pr_read_as,             /* /proc/<pid>/as                       */
 606  610          pr_read_inval,          /* /proc/<pid>/ctl                      */
 607  611          pr_read_status,         /* /proc/<pid>/status                   */
 608  612          pr_read_lstatus,        /* /proc/<pid>/lstatus                  */
 609  613          pr_read_psinfo,         /* /proc/<pid>/psinfo                   */
↓ open down ↓ 8 lines elided ↑ open up ↑
 618  622          pr_read_ldt,            /* /proc/<pid>/ldt                      */
 619  623  #endif
 620  624          pr_read_usage,          /* /proc/<pid>/usage                    */
 621  625          pr_read_lusage,         /* /proc/<pid>/lusage                   */
 622  626          pr_read_pagedata,       /* /proc/<pid>/pagedata                 */
 623  627          pr_read_watch,          /* /proc/<pid>/watch                    */
 624  628          pr_read_inval,          /* /proc/<pid>/cwd                      */
 625  629          pr_read_inval,          /* /proc/<pid>/root                     */
 626  630          pr_read_inval,          /* /proc/<pid>/fd                       */
 627  631          pr_read_inval,          /* /proc/<pid>/fd/nn                    */
      632 +        pr_read_inval,          /* /proc/<pid>/fdinfo                   */
      633 +        pr_read_fdinfo,         /* /proc/<pid>/fdinfo/nn                */
 628  634          pr_read_inval,          /* /proc/<pid>/object                   */
 629  635          pr_read_inval,          /* /proc/<pid>/object/xxx               */
 630  636          pr_read_inval,          /* /proc/<pid>/lwp                      */
 631  637          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>              */
 632  638          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
 633  639          pr_read_lwpname,        /* /proc/<pid>/lwp/<lwpid>/lwpname      */
 634  640          pr_read_lwpstatus,      /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
 635  641          pr_read_lwpsinfo,       /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
 636  642          pr_read_lwpusage,       /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
 637  643          pr_read_xregs,          /* /proc/<pid>/lwp/<lwpid>/xregs        */
↓ open down ↓ 168 lines elided ↑ open up ↑
 806  812          else {
 807  813                  ASSERT(p == pnp->pr_common->prc_proc);
 808  814                  prgetpsinfo(p, &psinfo);
 809  815                  prunlock(pnp);
 810  816                  error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
 811  817          }
 812  818          return (error);
 813  819  }
 814  820  
 815  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
 816  906  pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
 817  907  {
 818  908          proc_t *p;
 819  909          kthread_t *t;
 820  910          lwpdir_t *ldp;
 821  911          lwpent_t *lep;
 822  912          size_t size;
 823  913          prheader_t *php;
 824  914          lwpsinfo_t *sp;
 825  915          int error;
↓ open down ↓ 1002 lines elided ↑ open up ↑
1828 1918          pr_read_ldt,            /* /proc/<pid>/ldt                      */
1829 1919  #endif
1830 1920          pr_read_usage_32,       /* /proc/<pid>/usage                    */
1831 1921          pr_read_lusage_32,      /* /proc/<pid>/lusage                   */
1832 1922          pr_read_pagedata_32,    /* /proc/<pid>/pagedata                 */
1833 1923          pr_read_watch_32,       /* /proc/<pid>/watch                    */
1834 1924          pr_read_inval,          /* /proc/<pid>/cwd                      */
1835 1925          pr_read_inval,          /* /proc/<pid>/root                     */
1836 1926          pr_read_inval,          /* /proc/<pid>/fd                       */
1837 1927          pr_read_inval,          /* /proc/<pid>/fd/nn                    */
     1928 +        pr_read_inval,          /* /proc/<pid>/fdinfo                   */
     1929 +        pr_read_fdinfo,         /* /proc/<pid>/fdinfo/nn                */
1838 1930          pr_read_inval,          /* /proc/<pid>/object                   */
1839 1931          pr_read_inval,          /* /proc/<pid>/object/xxx               */
1840 1932          pr_read_inval,          /* /proc/<pid>/lwp                      */
1841 1933          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>              */
1842 1934          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
1843 1935          pr_read_lwpname,        /* /proc/<pid>/lwp/<lwpid>/lwpname      */
1844 1936          pr_read_lwpstatus_32,   /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
1845 1937          pr_read_lwpsinfo_32,    /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
1846 1938          pr_read_lwpusage_32,    /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
1847 1939          pr_read_xregs,          /* /proc/<pid>/lwp/<lwpid>/xregs        */
↓ open down ↓ 1225 lines elided ↑ open up ↑
3073 3165                  vap->va_nlink = 2;
3074 3166                  break;
3075 3167          case PR_PATH:
3076 3168          case PR_CURDIR:
3077 3169          case PR_ROOTDIR:
3078 3170          case PR_CT:
3079 3171                  vap->va_type = VLNK;
3080 3172                  vap->va_size = 0;
3081 3173                  break;
3082 3174          case PR_FDDIR:
     3175 +        case PR_FDINFODIR:
3083 3176                  vap->va_nlink = 2;
3084 3177                  vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
3085 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 +        }
3086 3199          case PR_LWPDIR:
3087 3200                  /*
3088 3201                   * va_nlink: count each lwp as a directory link.
3089 3202                   * va_size: size of p_lwpdir + 2
3090 3203                   */
3091 3204                  vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
3092 3205                  vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
3093 3206                  break;
3094 3207          case PR_LWPIDDIR:
3095 3208                  vap->va_nlink = 2;
↓ open down ↓ 304 lines elided ↑ open up ↑
3400 3513          if ((vmode & mode) != mode)
3401 3514                  error = secpolicy_proc_access(cr);
3402 3515          return (error);
3403 3516  }
3404 3517  
3405 3518  /*
3406 3519   * Array of lookup functions, indexed by /proc file type.
3407 3520   */
3408 3521  static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3409 3522          *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3410      -        *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
3411      -        *pr_lookup_ctdir();
     3523 +        *pr_lookup_fddir(), *pr_lookup_fdinfodir(), *pr_lookup_pathdir(),
     3524 +        *pr_lookup_tmpldir(), *pr_lookup_ctdir();
3412 3525  
3413 3526  static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3414 3527          pr_lookup_procdir,      /* /proc                                */
3415 3528          pr_lookup_notdir,       /* /proc/self                           */
3416 3529          pr_lookup_piddir,       /* /proc/<pid>                          */
3417 3530          pr_lookup_notdir,       /* /proc/<pid>/as                       */
3418 3531          pr_lookup_notdir,       /* /proc/<pid>/ctl                      */
3419 3532          pr_lookup_notdir,       /* /proc/<pid>/status                   */
3420 3533          pr_lookup_notdir,       /* /proc/<pid>/lstatus                  */
3421 3534          pr_lookup_notdir,       /* /proc/<pid>/psinfo                   */
↓ open down ↓ 8 lines elided ↑ open up ↑
3430 3543          pr_lookup_notdir,       /* /proc/<pid>/ldt                      */
3431 3544  #endif
3432 3545          pr_lookup_notdir,       /* /proc/<pid>/usage                    */
3433 3546          pr_lookup_notdir,       /* /proc/<pid>/lusage                   */
3434 3547          pr_lookup_notdir,       /* /proc/<pid>/pagedata                 */
3435 3548          pr_lookup_notdir,       /* /proc/<pid>/watch                    */
3436 3549          pr_lookup_notdir,       /* /proc/<pid>/cwd                      */
3437 3550          pr_lookup_notdir,       /* /proc/<pid>/root                     */
3438 3551          pr_lookup_fddir,        /* /proc/<pid>/fd                       */
3439 3552          pr_lookup_notdir,       /* /proc/<pid>/fd/nn                    */
     3553 +        pr_lookup_fdinfodir,    /* /proc/<pid>/fdinfo                   */
     3554 +        pr_lookup_notdir,       /* /proc/<pid>/fdinfo/nn                */
3440 3555          pr_lookup_objectdir,    /* /proc/<pid>/object                   */
3441 3556          pr_lookup_notdir,       /* /proc/<pid>/object/xxx               */
3442 3557          pr_lookup_lwpdir,       /* /proc/<pid>/lwp                      */
3443 3558          pr_lookup_lwpiddir,     /* /proc/<pid>/lwp/<lwpid>              */
3444 3559          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
3445 3560          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpname      */
3446 3561          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
3447 3562          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
3448 3563          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
3449 3564          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/xregs        */
↓ open down ↓ 67 lines elided ↑ open up ↑
3517 3632                   */
3518 3633                  ASSERT((dp->v_flag & VTRAVERSE) != 0);
3519 3634  
3520 3635                  dp = pnp->pr_realvp;
3521 3636                  return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3522 3637                      direntflags, realpnp));
3523 3638          default:
3524 3639                  break;
3525 3640          }
3526 3641  
3527      -        if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
     3642 +        if ((type == PR_OBJECTDIR || type == PR_FDDIR ||
     3643 +            type == PR_FDINFODIR || type == PR_PATHDIR) &&
3528 3644              (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3529 3645                  return (error);
3530 3646  
3531 3647          /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3532 3648          *vpp = (pr_lookup_function[type](dp, comp));
3533 3649  
3534 3650          return ((*vpp == NULL) ? ENOENT : 0);
3535 3651  }
3536 3652  
3537 3653  /* ARGSUSED */
↓ open down ↓ 593 lines elided ↑ open up ↑
4131 4247  static vnode_t *
4132 4248  pr_lookup_fddir(vnode_t *dp, char *comp)
4133 4249  {
4134 4250          prnode_t *dpnp = VTOP(dp);
4135 4251          prnode_t *pnp;
4136 4252          vnode_t *vp = NULL;
4137 4253          proc_t *p;
4138 4254          file_t *fp;
4139 4255          uint_t fd;
4140 4256          int c;
4141      -        uf_entry_t *ufp;
4142      -        uf_info_t *fip;
4143 4257  
4144 4258          ASSERT(dpnp->pr_type == PR_FDDIR);
4145 4259  
4146 4260          fd = 0;
4147 4261          while ((c = *comp++) != '\0') {
4148 4262                  int ofd;
4149 4263                  if (c < '0' || c > '9')
4150 4264                          return (NULL);
4151 4265                  ofd = fd;
4152      -                fd = 10*fd + c - '0';
4153      -                if (fd/10 != ofd)       /* integer overflow */
     4266 +                fd = 10 * fd + c - '0';
     4267 +                if (fd / 10 != ofd)     /* integer overflow */
4154 4268                          return (NULL);
4155 4269          }
4156 4270  
4157 4271          pnp = prgetnode(dp, PR_FD);
4158 4272  
4159 4273          if (prlock(dpnp, ZNO) != 0) {
4160 4274                  prfreenode(pnp);
4161 4275                  return (NULL);
4162 4276          }
4163 4277          p = dpnp->pr_common->prc_proc;
4164 4278          if ((p->p_flag & SSYS) || p->p_as == &kas) {
4165 4279                  prunlock(dpnp);
4166 4280                  prfreenode(pnp);
4167 4281                  return (NULL);
4168 4282          }
4169 4283  
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);
     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);
4185 4293          }
4186      -        mutex_exit(&fip->fi_lock);
4187      -        mutex_enter(&p->p_lock);
     4294 +
4188 4295          prunlock(dpnp);
4189 4296  
4190      -        if (vp == NULL)
     4297 +        if (vp == NULL) {
4191 4298                  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      -                }
     4299 +                return (NULL);
4207 4300          }
4208 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 +
4209 4317          return (vp);
4210 4318  }
4211 4319  
4212 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 *
4213 4368  pr_lookup_pathdir(vnode_t *dp, char *comp)
4214 4369  {
4215 4370          prnode_t *dpnp = VTOP(dp);
4216 4371          prnode_t *pnp;
4217 4372          vnode_t *vp = NULL;
4218 4373          proc_t *p;
4219 4374          uint_t fd, flags = 0;
4220 4375          int c;
4221 4376          uf_entry_t *ufp;
4222 4377          uf_info_t *fip;
↓ open down ↓ 437 lines elided ↑ open up ↑
4660 4815                          vp->v_flag |= VDIROPEN;
4661 4816                  } else {
4662 4817                          pnp->pr_mode = 0555;
4663 4818                  }
4664 4819  
4665 4820                  break;
4666 4821  
4667 4822          case PR_CURDIR:
4668 4823          case PR_ROOTDIR:
4669 4824          case PR_FDDIR:
     4825 +        case PR_FDINFODIR:
4670 4826          case PR_OBJECTDIR:
4671 4827          case PR_PATHDIR:
4672 4828          case PR_CTDIR:
4673 4829          case PR_TMPLDIR:
4674 4830                  vp->v_type = VDIR;
4675 4831                  pnp->pr_mode = 0500;    /* read-search by owner only */
4676 4832                  break;
4677 4833  
4678 4834          case PR_CT:
4679 4835                  vp->v_type = VLNK;
↓ open down ↓ 112 lines elided ↑ open up ↑
4792 4948                  kmem_free(pcp, sizeof (prcommon_t));
4793 4949                  DECREMENT(nprcommon);
4794 4950          }
4795 4951  }
4796 4952  
4797 4953  /*
4798 4954   * Array of readdir functions, indexed by /proc file type.
4799 4955   */
4800 4956  static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4801 4957          pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4802      -        pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
4803      -        pr_readdir_ctdir();
     4958 +        pr_readdir_fddir(), pr_readdir_fdinfodir(), pr_readdir_pathdir(),
     4959 +        pr_readdir_tmpldir(), pr_readdir_ctdir();
4804 4960  
4805 4961  static int (*pr_readdir_function[PR_NFILES])() = {
4806 4962          pr_readdir_procdir,     /* /proc                                */
4807 4963          pr_readdir_notdir,      /* /proc/self                           */
4808 4964          pr_readdir_piddir,      /* /proc/<pid>                          */
4809 4965          pr_readdir_notdir,      /* /proc/<pid>/as                       */
4810 4966          pr_readdir_notdir,      /* /proc/<pid>/ctl                      */
4811 4967          pr_readdir_notdir,      /* /proc/<pid>/status                   */
4812 4968          pr_readdir_notdir,      /* /proc/<pid>/lstatus                  */
4813 4969          pr_readdir_notdir,      /* /proc/<pid>/psinfo                   */
↓ open down ↓ 8 lines elided ↑ open up ↑
4822 4978          pr_readdir_notdir,      /* /proc/<pid>/ldt                      */
4823 4979  #endif
4824 4980          pr_readdir_notdir,      /* /proc/<pid>/usage                    */
4825 4981          pr_readdir_notdir,      /* /proc/<pid>/lusage                   */
4826 4982          pr_readdir_notdir,      /* /proc/<pid>/pagedata                 */
4827 4983          pr_readdir_notdir,      /* /proc/<pid>/watch                    */
4828 4984          pr_readdir_notdir,      /* /proc/<pid>/cwd                      */
4829 4985          pr_readdir_notdir,      /* /proc/<pid>/root                     */
4830 4986          pr_readdir_fddir,       /* /proc/<pid>/fd                       */
4831 4987          pr_readdir_notdir,      /* /proc/<pid>/fd/nn                    */
     4988 +        pr_readdir_fdinfodir,   /* /proc/<pid>/fdinfo                   */
     4989 +        pr_readdir_notdir,      /* /proc/<pid>/fdinfo/nn                */
4832 4990          pr_readdir_objectdir,   /* /proc/<pid>/object                   */
4833 4991          pr_readdir_notdir,      /* /proc/<pid>/object/xxx               */
4834 4992          pr_readdir_lwpdir,      /* /proc/<pid>/lwp                      */
4835 4993          pr_readdir_lwpiddir,    /* /proc/<pid>/lwp/<lwpid>              */
4836 4994          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
4837 4995          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpname      */
4838 4996          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
4839 4997          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
4840 4998          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
4841 4999          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/xregs        */
↓ open down ↓ 512 lines elided ↑ open up ↑
5354 5512                  if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5355 5513                      UIO_READ, uiop)) != 0)
5356 5514                          return (error);
5357 5515          }
5358 5516  out:
5359 5517          if (eofp)
5360 5518                  *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5361 5519          return (0);
5362 5520  }
5363 5521  
5364      -/* ARGSUSED */
     5522 +/*
     5523 + * Helper function for reading a directory which lists open file desciptors
     5524 + */
5365 5525  static int
5366      -pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
     5526 +pr_readdir_fdlist(prnode_t *pnp, uio_t *uiop, int *eofp,
     5527 +    prnodetype_t dirtype, prnodetype_t entrytype)
5367 5528  {
5368 5529          gfs_readdir_state_t gstate;
5369 5530          int error, eof = 0;
5370 5531          offset_t n;
5371 5532          proc_t *p;
5372 5533          int pslot;
5373 5534          int fddirsize;
5374 5535          uf_info_t *fip;
5375 5536  
5376      -        ASSERT(pnp->pr_type == PR_FDDIR);
5377      -
5378 5537          if ((error = prlock(pnp, ZNO)) != 0)
5379 5538                  return (error);
5380 5539          p = pnp->pr_common->prc_proc;
5381 5540          pslot = p->p_slot;
5382 5541          fip = P_FINFO(p);
5383 5542          mutex_exit(&p->p_lock);
5384 5543  
5385 5544          if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5386      -            pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
     5545 +            pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, dirtype), 0)) != 0) {
5387 5546                  mutex_enter(&p->p_lock);
5388 5547                  prunlock(pnp);
5389 5548                  return (error);
5390 5549          }
5391 5550  
5392 5551          mutex_enter(&fip->fi_lock);
5393 5552          if ((p->p_flag & SSYS) || p->p_as == &kas)
5394 5553                  fddirsize = 0;
5395 5554          else
5396 5555                  fddirsize = fip->fi_nfiles;
↓ open down ↓ 10 lines elided ↑ open up ↑
5407 5566                          n++;
5408 5567                  /*
5409 5568                   * Stop when all fds have been reported.
5410 5569                   */
5411 5570                  if (n >= fddirsize) {
5412 5571                          eof = 1;
5413 5572                          break;
5414 5573                  }
5415 5574  
5416 5575                  error = gfs_readdir_emitn(&gstate, uiop, n,
5417      -                    pmkino(n, pslot, PR_FD), n);
     5576 +                    pmkino(n, pslot, entrytype), n);
5418 5577                  if (error)
5419 5578                          break;
5420 5579          }
5421 5580  
5422 5581          mutex_exit(&fip->fi_lock);
5423 5582          mutex_enter(&p->p_lock);
5424 5583          prunlock(pnp);
5425 5584  
5426 5585          return (gfs_readdir_fini(&gstate, error, eofp, eof));
5427 5586  }
5428 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 +
5429 5606  /* ARGSUSED */
5430 5607  static int
5431 5608  pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5432 5609  {
5433 5610          longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5434 5611          dirent64_t *dirent = (dirent64_t *)bp;
5435 5612          int reclen;
5436 5613          ssize_t oresid;
5437 5614          offset_t off, idx;
5438 5615          int error = 0;
↓ open down ↓ 289 lines elided ↑ open up ↑
5728 5905          prnode_t *pnp = VTOP(vp);
5729 5906          prnodetype_t type = pnp->pr_type;
5730 5907          proc_t *p;
5731 5908          vnode_t *dp;
5732 5909          vnode_t *ovp = NULL;
5733 5910          prnode_t *opnp = NULL;
5734 5911  
5735 5912          switch (type) {
5736 5913          case PR_OBJECT:
5737 5914          case PR_FD:
     5915 +        case PR_FDDIR:
5738 5916          case PR_SELF:
5739 5917          case PR_PATH:
5740 5918                  /* These are not linked into the usual lists */
5741 5919                  ASSERT(vp->v_count == 1);
5742 5920                  if ((dp = pnp->pr_parent) != NULL)
5743 5921                          VN_RELE(dp);
5744 5922                  prfreenode(pnp);
5745 5923                  return;
5746 5924          default:
5747 5925                  break;
↓ open down ↓ 479 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX