Print this page
    
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
    usr/src/uts/common/fs/proc/prcontrol.c
    usr/src/uts/intel/os/archdep.c
    usr/src/uts/intel/sys/ucontext.h
    usr/src/uts/intel/syscall/getcontext.c
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/proc/prvnops.c
          +++ new/usr/src/uts/common/fs/proc/prvnops.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  
    | 
      ↓ open down ↓ | 
    17 lines elided | 
    
      ↑ open up ↑ | 
  
  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 2019 Joyent, Inc.
  25   25   * Copyright (c) 2017 by Delphix. All rights reserved.
  26   26   * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
  27   27   * Copyright 2022 MNX Cloud, Inc.
  28      - * Copyright 2022 Oxide Computer Company
       28 + * Copyright 2023 Oxide Computer Company
  29   29   */
  30   30  
  31   31  /*      Copyright (c) 1984,      1986, 1987, 1988, 1989 AT&T    */
  32   32  /*        All Rights Reserved   */
  33   33  
  34   34  #include <sys/types.h>
  35   35  #include <sys/param.h>
  36   36  #include <sys/time.h>
  37   37  #include <sys/cred.h>
  38   38  #include <sys/policy.h>
  39   39  #include <sys/debug.h>
  40   40  #include <sys/dirent.h>
  41   41  #include <sys/errno.h>
  42   42  #include <sys/file.h>
  43   43  #include <sys/inline.h>
  44   44  #include <sys/kmem.h>
  45   45  #include <sys/pathname.h>
  46   46  #include <sys/proc.h>
  47   47  #include <sys/brand.h>
  48   48  #include <sys/signal.h>
  49   49  #include <sys/stat.h>
  50   50  #include <sys/sysmacros.h>
  51   51  #include <sys/systm.h>
  52   52  #include <sys/zone.h>
  53   53  #include <sys/uio.h>
  54   54  #include <sys/var.h>
  55   55  #include <sys/mode.h>
  56   56  #include <sys/poll.h>
  57   57  #include <sys/user.h>
  58   58  #include <sys/vfs.h>
  59   59  #include <sys/vfs_opreg.h>
  60   60  #include <sys/gfs.h>
  61   61  #include <sys/vnode.h>
  62   62  #include <sys/fault.h>
  63   63  #include <sys/syscall.h>
  64   64  #include <sys/procfs.h>
  65   65  #include <sys/atomic.h>
  66   66  #include <sys/cmn_err.h>
  67   67  #include <sys/contract_impl.h>
  68   68  #include <sys/ctfs.h>
  69   69  #include <sys/avl.h>
  70   70  #include <sys/ctype.h>
  71   71  #include <fs/fs_subr.h>
  72   72  #include <vm/rm.h>
  73   73  #include <vm/as.h>
  74   74  #include <vm/seg.h>
  75   75  #include <vm/seg_vn.h>
  76   76  #include <vm/hat.h>
  77   77  #include <fs/proc/prdata.h>
  78   78  #if defined(__sparc)
  79   79  #include <sys/regset.h>
  80   80  #endif
  81   81  #if defined(__x86)
  82   82  #include <sys/sysi86.h>
  83   83  #endif
  84   84  
  85   85  /*
  86   86   * Created by prinit.
  87   87   */
  88   88  vnodeops_t *prvnodeops;
  89   89  
  90   90  /*
  91   91   * Directory characteristics (patterned after the s5 file system).
  92   92   */
  93   93  #define PRROOTINO       2
  94   94  
  95   95  #define PRDIRSIZE       14
  96   96  struct prdirect {
  97   97          ushort_t        d_ino;
  98   98          char            d_name[PRDIRSIZE];
  99   99  };
 100  100  
 101  101  #define PRSDSIZE        (sizeof (struct prdirect))
 102  102  
 103  103  /*
 104  104   * Directory characteristics.
 105  105   */
 106  106  typedef struct prdirent {
 107  107          ino64_t         d_ino;          /* "inode number" of entry */
 108  108          off64_t         d_off;          /* offset of disk directory entry */
 109  109          unsigned short  d_reclen;       /* length of this record */
 110  110          char            d_name[14];     /* name of file */
 111  111  } prdirent_t;
 112  112  
 113  113  /*
 114  114   * Contents of a /proc/<pid> directory.
 115  115   * Reuse d_ino field for the /proc file type.
 116  116   */
 117  117  static prdirent_t piddir[] = {
 118  118          { PR_PIDDIR,     1 * sizeof (prdirent_t), sizeof (prdirent_t),
 119  119                  "." },
 120  120          { PR_PROCDIR,    2 * sizeof (prdirent_t), sizeof (prdirent_t),
 121  121                  ".." },
 122  122          { PR_AS,         3 * sizeof (prdirent_t), sizeof (prdirent_t),
 123  123                  "as" },
 124  124          { PR_CTL,        4 * sizeof (prdirent_t), sizeof (prdirent_t),
 125  125                  "ctl" },
 126  126          { PR_STATUS,     5 * sizeof (prdirent_t), sizeof (prdirent_t),
 127  127                  "status" },
 128  128          { PR_LSTATUS,    6 * sizeof (prdirent_t), sizeof (prdirent_t),
 129  129                  "lstatus" },
 130  130          { PR_PSINFO,     7 * sizeof (prdirent_t), sizeof (prdirent_t),
 131  131                  "psinfo" },
 132  132          { PR_LPSINFO,    8 * sizeof (prdirent_t), sizeof (prdirent_t),
 133  133                  "lpsinfo" },
 134  134          { PR_MAP,        9 * sizeof (prdirent_t), sizeof (prdirent_t),
 135  135                  "map" },
 136  136          { PR_RMAP,      10 * sizeof (prdirent_t), sizeof (prdirent_t),
 137  137                  "rmap" },
 138  138          { PR_XMAP,      11 * sizeof (prdirent_t), sizeof (prdirent_t),
 139  139                  "xmap" },
 140  140          { PR_CRED,      12 * sizeof (prdirent_t), sizeof (prdirent_t),
 141  141                  "cred" },
 142  142          { PR_SIGACT,    13 * sizeof (prdirent_t), sizeof (prdirent_t),
 143  143                  "sigact" },
 144  144          { PR_AUXV,      14 * sizeof (prdirent_t), sizeof (prdirent_t),
 145  145                  "auxv" },
 146  146          { PR_USAGE,     15 * sizeof (prdirent_t), sizeof (prdirent_t),
 147  147                  "usage" },
 148  148          { PR_LUSAGE,    16 * sizeof (prdirent_t), sizeof (prdirent_t),
 149  149                  "lusage" },
 150  150          { PR_PAGEDATA,  17 * sizeof (prdirent_t), sizeof (prdirent_t),
 151  151                  "pagedata" },
 152  152          { PR_WATCH,     18 * sizeof (prdirent_t), sizeof (prdirent_t),
 153  153                  "watch" },
 154  154          { PR_CURDIR,    19 * sizeof (prdirent_t), sizeof (prdirent_t),
 155  155                  "cwd" },
 156  156          { PR_ROOTDIR,   20 * sizeof (prdirent_t), sizeof (prdirent_t),
 157  157                  "root" },
 158  158          { PR_FDDIR,     21 * sizeof (prdirent_t), sizeof (prdirent_t),
 159  159                  "fd" },
 160  160          { PR_FDINFODIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
 161  161                  "fdinfo" },
 162  162          { PR_OBJECTDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
 163  163                  "object" },
 164  164          { PR_LWPDIR,    24 * sizeof (prdirent_t), sizeof (prdirent_t),
 165  165                  "lwp" },
 166  166          { PR_PRIV,      25 * sizeof (prdirent_t), sizeof (prdirent_t),
 167  167                  "priv" },
 168  168          { PR_PATHDIR,   26 * sizeof (prdirent_t), sizeof (prdirent_t),
 169  169                  "path" },
 170  170          { PR_CTDIR,     27 * sizeof (prdirent_t), sizeof (prdirent_t),
 171  171                  "contracts" },
 172  172          { PR_SECFLAGS,  28 * sizeof (prdirent_t), sizeof (prdirent_t),
 173  173                  "secflags" },
 174  174          { PR_ARGV,      29 * sizeof (prdirent_t), sizeof (prdirent_t),
 175  175                  "argv" },
 176  176          { PR_CMDLINE,   30 * sizeof (prdirent_t), sizeof (prdirent_t),
 177  177                  "cmdline" },
 178  178  #if defined(__x86)
 179  179          { PR_LDT,       31 * sizeof (prdirent_t), sizeof (prdirent_t),
 180  180                  "ldt" },
 181  181  #endif
 182  182  };
 183  183  
 184  184  #define NPIDDIRFILES    (sizeof (piddir) / sizeof (piddir[0]) - 2)
 185  185  
 186  186  /*
 187  187   * Contents of a /proc/<pid>/lwp/<lwpid> directory.
 188  188   */
 189  189  static prdirent_t lwpiddir[] = {
 190  190          { PR_LWPIDDIR,   1 * sizeof (prdirent_t), sizeof (prdirent_t),
 191  191                  "." },
 192  192          { PR_LWPDIR,     2 * sizeof (prdirent_t), sizeof (prdirent_t),
 193  193                  ".." },
 194  194          { PR_LWPCTL,     3 * sizeof (prdirent_t), sizeof (prdirent_t),
 195  195                  "lwpctl" },
 196  196          { PR_LWPNAME,    4 * sizeof (prdirent_t), sizeof (prdirent_t),
 197  197                  "lwpname" },
 198  198          { PR_LWPSTATUS,  5 * sizeof (prdirent_t), sizeof (prdirent_t),
 199  199                  "lwpstatus" },
 200  200          { PR_LWPSINFO,   6 * sizeof (prdirent_t), sizeof (prdirent_t),
 201  201                  "lwpsinfo" },
 202  202          { PR_LWPUSAGE,   7 * sizeof (prdirent_t), sizeof (prdirent_t),
 203  203                  "lwpusage" },
 204  204          { PR_XREGS,      8 * sizeof (prdirent_t), sizeof (prdirent_t),
 205  205                  "xregs" },
 206  206          { PR_TMPLDIR,    9 * sizeof (prdirent_t), sizeof (prdirent_t),
 207  207                  "templates" },
 208  208          { PR_SPYMASTER,  10 * sizeof (prdirent_t), sizeof (prdirent_t),
 209  209                  "spymaster" },
 210  210  #if defined(__sparc)
 211  211          { PR_GWINDOWS,  11 * sizeof (prdirent_t), sizeof (prdirent_t),
 212  212                  "gwindows" },
 213  213          { PR_ASRS,      12 * sizeof (prdirent_t), sizeof (prdirent_t),
 214  214                  "asrs" },
 215  215  #endif
 216  216  };
 217  217  
 218  218  #define NLWPIDDIRFILES  (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
 219  219  
 220  220  /*
 221  221   * Span of entries in the array files (lstatus, lpsinfo, lusage).
 222  222   * We make the span larger than the size of the structure on purpose,
 223  223   * to make sure that programs cannot use the structure size by mistake.
 224  224   * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
 225  225   */
 226  226  #ifdef _LP64
 227  227  #define LSPAN(type)     (round16(sizeof (type)) + 16)
 228  228  #define LSPAN32(type)   (round8(sizeof (type)) + 8)
 229  229  #else
 230  230  #define LSPAN(type)     (round8(sizeof (type)) + 8)
 231  231  #endif
 232  232  
 233  233  static void rebuild_objdir(struct as *);
 234  234  static void prfreecommon(prcommon_t *);
 235  235  static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
 236  236  
 237  237  static int
 238  238  propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
 239  239  {
 240  240          vnode_t *vp = *vpp;
 241  241          prnode_t *pnp = VTOP(vp);
 242  242          prcommon_t *pcp = pnp->pr_pcommon;
 243  243          prnodetype_t type = pnp->pr_type;
 244  244          vnode_t *rvp;
 245  245          vtype_t vtype;
 246  246          proc_t *p;
 247  247          int error = 0;
 248  248          prnode_t *npnp = NULL;
 249  249  
 250  250          /*
 251  251           * Nothing to do for the /proc directory itself.
 252  252           */
 253  253          if (type == PR_PROCDIR)
 254  254                  return (0);
 255  255  
 256  256          /*
 257  257           * If we are opening an underlying mapped object, reject opens
 258  258           * for writing regardless of the objects's access modes.
 259  259           * If we are opening a file in the /proc/pid/fd directory,
 260  260           * reject the open for any but a regular file or directory.
 261  261           * Just do it if we are opening the current or root directory.
 262  262           */
 263  263          switch (type) {
 264  264          case PR_OBJECT:
 265  265          case PR_FD:
 266  266          case PR_CURDIR:
 267  267          case PR_ROOTDIR:
 268  268                  rvp = pnp->pr_realvp;
 269  269                  vtype = rvp->v_type;
 270  270                  if ((type == PR_OBJECT && (flag & FWRITE)) ||
 271  271                      (type == PR_FD && vtype != VREG && vtype != VDIR))
 272  272                          error = EACCES;
 273  273                  else {
 274  274                          /*
 275  275                           * Need to hold rvp since VOP_OPEN() may release it.
 276  276                           */
 277  277                          VN_HOLD(rvp);
 278  278                          error = VOP_OPEN(&rvp, flag, cr, ct);
 279  279                          if (error) {
 280  280                                  VN_RELE(rvp);
 281  281                          } else {
 282  282                                  *vpp = rvp;
 283  283                                  VN_RELE(vp);
 284  284                          }
 285  285                  }
 286  286                  return (error);
 287  287          default:
 288  288                  break;
 289  289          }
 290  290  
 291  291          /*
 292  292           * If we are opening the pagedata file, allocate a prnode now
 293  293           * to avoid calling kmem_alloc() while holding p->p_lock.
 294  294           */
 295  295          if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
 296  296                  npnp = prgetnode(vp, type);
 297  297  
 298  298          /*
 299  299           * If the process exists, lock it now.
 300  300           * Otherwise we have a race condition with prclose().
 301  301           */
 302  302          p = pr_p_lock(pnp);
 303  303          mutex_exit(&pr_pidlock);
 304  304          if (p == NULL) {
 305  305                  if (npnp != NULL)
 306  306                          prfreenode(npnp);
 307  307                  return (ENOENT);
 308  308          }
 309  309          ASSERT(p == pcp->prc_proc);
 310  310          ASSERT(p->p_proc_flag & P_PR_LOCK);
 311  311  
 312  312          /*
 313  313           * Maintain a count of opens for write.  Allow exactly one
 314  314           * O_WRITE|O_EXCL request and fail subsequent ones.
 315  315           * Don't fail opens of old (bletch!) /proc lwp files.
 316  316           * Special case for open by the process itself:
 317  317           * Always allow the open by self and discount this
 318  318           * open for other opens for writing.
 319  319           */
 320  320          if (flag & FWRITE) {
 321  321                  if (p == curproc) {
 322  322                          pcp->prc_selfopens++;
 323  323                          pnp->pr_flags |= PR_ISSELF;
 324  324                  } else if (type == PR_LWPIDFILE) {
 325  325                          /* EMPTY */;
 326  326                  } else if (flag & FEXCL) {
 327  327                          if (pcp->prc_writers > pcp->prc_selfopens) {
 328  328                                  error = EBUSY;
 329  329                                  goto out;
 330  330                          }
 331  331                          /* semantic for old /proc interface */
 332  332                          if (type == PR_PIDDIR)
 333  333                                  pcp->prc_flags |= PRC_EXCL;
 334  334                  } else if (pcp->prc_flags & PRC_EXCL) {
 335  335                          ASSERT(pcp->prc_writers > pcp->prc_selfopens);
 336  336                          error = secpolicy_proc_excl_open(cr);
 337  337                          if (error)
 338  338                                  goto out;
 339  339                  }
 340  340                  pcp->prc_writers++;
 341  341                  /*
 342  342                   * The vnode may have become invalid between the
 343  343                   * VOP_LOOKUP() of the /proc vnode and the VOP_OPEN().
 344  344                   * If so, do now what prinvalidate() should have done.
 345  345                   */
 346  346                  if ((pnp->pr_flags & PR_INVAL) ||
 347  347                      (type == PR_PIDDIR &&
 348  348                      (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
 349  349                          if (p != curproc)
 350  350                                  pcp->prc_selfopens++;
 351  351                          ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
 352  352                          if (pcp->prc_selfopens == pcp->prc_writers)
 353  353                                  pcp->prc_flags &= ~PRC_EXCL;
 354  354                  }
 355  355          }
 356  356  
 357  357          /*
 358  358           * If this is a large file open, indicate that in our flags -- some
 359  359           * procfs structures are not off_t-neutral (e.g., priovec_t), and
 360  360           * the open will need to be differentiated where 32-bit processes
 361  361           * pass these structures across the user/kernel boundary.
 362  362           */
 363  363          if (flag & FOFFMAX)
 364  364                  pnp->pr_flags |= PR_OFFMAX;
 365  365  
 366  366          /*
 367  367           * Do file-specific things.
 368  368           */
 369  369          switch (type) {
 370  370          default:
 371  371                  break;
 372  372          case PR_PAGEDATA:
 373  373          case PR_OPAGEDATA:
 374  374                  /*
 375  375                   * Enable data collection for page data file;
 376  376                   * get unique id from the hat layer.
 377  377                   */
 378  378                  {
 379  379                          int id;
 380  380  
 381  381                          /*
 382  382                           * Drop p->p_lock to call hat_startstat()
 383  383                           */
 384  384                          mutex_exit(&p->p_lock);
 385  385                          if ((p->p_flag & SSYS) || p->p_as == &kas ||
 386  386                              (id = hat_startstat(p->p_as)) == -1) {
 387  387                                  mutex_enter(&p->p_lock);
 388  388                                  error = ENOMEM;
 389  389                          } else if (pnp->pr_hatid == 0) {
 390  390                                  mutex_enter(&p->p_lock);
 391  391                                  pnp->pr_hatid = (uint_t)id;
 392  392                          } else {
 393  393                                  mutex_enter(&p->p_lock);
 394  394                                  /*
 395  395                                   * Use our newly allocated prnode.
 396  396                                   */
 397  397                                  npnp->pr_hatid = (uint_t)id;
 398  398                                  /*
 399  399                                   * prgetnode() initialized most of the prnode.
 400  400                                   * Duplicate the remainder.
 401  401                                   */
 402  402                                  npnp->pr_ino = pnp->pr_ino;
 403  403                                  npnp->pr_common = pnp->pr_common;
 404  404                                  npnp->pr_pcommon = pnp->pr_pcommon;
 405  405                                  npnp->pr_parent = pnp->pr_parent;
 406  406                                  VN_HOLD(npnp->pr_parent);
 407  407                                  npnp->pr_index = pnp->pr_index;
 408  408  
 409  409                                  npnp->pr_next = p->p_plist;
 410  410                                  p->p_plist = PTOV(npnp);
 411  411  
 412  412                                  VN_RELE(PTOV(pnp));
 413  413                                  pnp = npnp;
 414  414                                  npnp = NULL;
 415  415                                  *vpp = PTOV(pnp);
 416  416                          }
 417  417                  }
 418  418                  break;
 419  419          }
 420  420  
 421  421  out:
 422  422          prunlock(pnp);
 423  423  
 424  424          if (npnp != NULL)
 425  425                  prfreenode(npnp);
 426  426          return (error);
 427  427  }
 428  428  
 429  429  /* ARGSUSED */
 430  430  static int
 431  431  prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
 432  432      caller_context_t *ct)
 433  433  {
 434  434          prnode_t *pnp = VTOP(vp);
 435  435          prcommon_t *pcp = pnp->pr_pcommon;
 436  436          prnodetype_t type = pnp->pr_type;
 437  437          proc_t *p;
 438  438          kthread_t *t;
 439  439          user_t *up;
 440  440  
 441  441          /*
 442  442           * Nothing to do for the /proc directory itself.
 443  443           */
 444  444          if (type == PR_PROCDIR)
 445  445                  return (0);
 446  446  
 447  447          ASSERT(type != PR_OBJECT && type != PR_FD &&
 448  448              type != PR_CURDIR && type != PR_ROOTDIR);
 449  449  
 450  450          /*
 451  451           * If the process exists, lock it now.
 452  452           * Otherwise we have a race condition with propen().
 453  453           * Hold pr_pidlock across the reference to prc_selfopens,
 454  454           * and prc_writers in case there is no process anymore,
 455  455           * to cover the case of concurrent calls to prclose()
 456  456           * after the process has been reaped by freeproc().
 457  457           */
 458  458          p = pr_p_lock(pnp);
 459  459  
 460  460          /*
 461  461           * There is nothing more to do until the last close of
 462  462           * the file table entry except to clear the pr_owner
 463  463           * field of the prnode and notify any waiters
 464  464           * (their file descriptor may have just been closed).
 465  465           */
 466  466          if (count > 1) {
 467  467                  mutex_exit(&pr_pidlock);
 468  468                  if (pnp->pr_owner == curproc && !fisopen(vp))
 469  469                          pnp->pr_owner = NULL;
 470  470                  if (p != NULL) {
 471  471                          prnotify(vp);
 472  472                          prunlock(pnp);
 473  473                  }
 474  474                  return (0);
 475  475          }
 476  476  
 477  477          /*
 478  478           * Decrement the count of self-opens for writing.
 479  479           * Decrement the total count of opens for writing.
 480  480           * Cancel exclusive opens when only self-opens remain.
 481  481           */
 482  482          if (flag & FWRITE) {
 483  483                  /*
 484  484                   * prc_selfopens also contains the count of
 485  485                   * invalid writers.  See prinvalidate().
 486  486                   */
 487  487                  if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
 488  488                      (type == PR_PIDDIR &&
 489  489                      (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
 490  490                          ASSERT(pcp->prc_selfopens != 0);
 491  491                          --pcp->prc_selfopens;
 492  492                  }
 493  493                  ASSERT(pcp->prc_writers != 0);
 494  494                  if (--pcp->prc_writers == pcp->prc_selfopens)
 495  495                          pcp->prc_flags &= ~PRC_EXCL;
 496  496          }
 497  497          ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
 498  498          mutex_exit(&pr_pidlock);
 499  499          if (pnp->pr_owner == curproc && !fisopen(vp))
 500  500                  pnp->pr_owner = NULL;
 501  501  
 502  502          /*
 503  503           * If there is no process, there is nothing more to do.
 504  504           */
 505  505          if (p == NULL)
 506  506                  return (0);
 507  507  
 508  508          ASSERT(p == pcp->prc_proc);
 509  509          prnotify(vp);   /* notify waiters */
 510  510  
 511  511          /*
 512  512           * Do file-specific things.
 513  513           */
 514  514          switch (type) {
 515  515          default:
 516  516                  break;
 517  517          case PR_PAGEDATA:
 518  518          case PR_OPAGEDATA:
 519  519                  /*
 520  520                   * This is a page data file.
 521  521                   * Free the hat level statistics.
 522  522                   * Drop p->p_lock before calling hat_freestat().
 523  523                   */
 524  524                  mutex_exit(&p->p_lock);
 525  525                  if (p->p_as != &kas && pnp->pr_hatid != 0)
 526  526                          hat_freestat(p->p_as, pnp->pr_hatid);
 527  527                  mutex_enter(&p->p_lock);
 528  528                  pnp->pr_hatid = 0;
 529  529                  break;
 530  530          }
 531  531  
 532  532          /*
 533  533           * On last close of all writable file descriptors,
 534  534           * perform run-on-last-close and/or kill-on-last-close logic.
 535  535           * Can't do this is the /proc agent lwp still exists.
 536  536           */
 537  537          if (pcp->prc_writers == 0 &&
 538  538              p->p_agenttp == NULL &&
 539  539              !(pcp->prc_flags & PRC_DESTROY) &&
 540  540              p->p_stat != SZOMB &&
 541  541              (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
 542  542                  int killproc;
 543  543  
 544  544                  /*
 545  545                   * Cancel any watchpoints currently in effect.
 546  546                   * The process might disappear during this operation.
 547  547                   */
 548  548                  if (pr_cancel_watch(pnp) == NULL)
 549  549                          return (0);
 550  550                  /*
 551  551                   * If any tracing flags are set, clear them.
 552  552                   */
 553  553                  if (p->p_proc_flag & P_PR_TRACE) {
 554  554                          up = PTOU(p);
 555  555                          premptyset(&up->u_entrymask);
 556  556                          premptyset(&up->u_exitmask);
 557  557                          up->u_systrap = 0;
 558  558                  }
 559  559                  premptyset(&p->p_sigmask);
 560  560                  premptyset(&p->p_fltmask);
 561  561                  killproc = (p->p_proc_flag & P_PR_KILLCL);
 562  562                  p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
 563  563                  /*
 564  564                   * Cancel any outstanding single-step requests.
 565  565                   */
 566  566                  if ((t = p->p_tlist) != NULL) {
 567  567                          /*
 568  568                           * Drop p_lock because prnostep() touches the stack.
 569  569                           * The loop is safe because the process is P_PR_LOCK'd.
 570  570                           */
 571  571                          mutex_exit(&p->p_lock);
 572  572                          do {
 573  573                                  prnostep(ttolwp(t));
 574  574                          } while ((t = t->t_forw) != p->p_tlist);
 575  575                          mutex_enter(&p->p_lock);
 576  576                  }
 577  577                  /*
 578  578                   * Set runnable all lwps stopped by /proc.
 579  579                   */
 580  580                  if (killproc)
 581  581                          sigtoproc(p, NULL, SIGKILL);
 582  582                  else
 583  583                          allsetrun(p);
 584  584          }
 585  585  
 586  586          prunlock(pnp);
 587  587          return (0);
 588  588  }
 589  589  
 590  590  /*
 591  591   * Array of read functions, indexed by /proc file type.
 592  592   */
 593  593  static int pr_read_inval(), pr_read_as(), pr_read_status(),
 594  594          pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
 595  595          pr_read_map(), pr_read_rmap(), pr_read_xmap(),
 596  596          pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
 597  597  #if defined(__x86)
 598  598          pr_read_ldt(),
 599  599  #endif
 600  600          pr_read_argv(), pr_read_cmdline(),
 601  601          pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
 602  602          pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
 603  603          pr_read_lwpusage(), pr_read_lwpname(),
 604  604          pr_read_xregs(), pr_read_priv(),
 605  605          pr_read_spymaster(), pr_read_secflags(),
 606  606  #if defined(__sparc)
 607  607          pr_read_gwindows(), pr_read_asrs(),
 608  608  #endif
 609  609          pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata(),
 610  610          pr_read_fdinfo();
 611  611  
 612  612  static int (*pr_read_function[PR_NFILES])() = {
 613  613          pr_read_inval,          /* /proc                                */
 614  614          pr_read_inval,          /* /proc/self                           */
 615  615          pr_read_piddir,         /* /proc/<pid> (old /proc read())       */
 616  616          pr_read_as,             /* /proc/<pid>/as                       */
 617  617          pr_read_inval,          /* /proc/<pid>/ctl                      */
 618  618          pr_read_status,         /* /proc/<pid>/status                   */
 619  619          pr_read_lstatus,        /* /proc/<pid>/lstatus                  */
 620  620          pr_read_psinfo,         /* /proc/<pid>/psinfo                   */
 621  621          pr_read_lpsinfo,        /* /proc/<pid>/lpsinfo                  */
 622  622          pr_read_map,            /* /proc/<pid>/map                      */
 623  623          pr_read_rmap,           /* /proc/<pid>/rmap                     */
 624  624          pr_read_xmap,           /* /proc/<pid>/xmap                     */
 625  625          pr_read_cred,           /* /proc/<pid>/cred                     */
 626  626          pr_read_sigact,         /* /proc/<pid>/sigact                   */
 627  627          pr_read_auxv,           /* /proc/<pid>/auxv                     */
 628  628  #if defined(__x86)
 629  629          pr_read_ldt,            /* /proc/<pid>/ldt                      */
 630  630  #endif
 631  631          pr_read_argv,           /* /proc/<pid>/argv                     */
 632  632          pr_read_cmdline,        /* /proc/<pid>/cmdline                  */
 633  633          pr_read_usage,          /* /proc/<pid>/usage                    */
 634  634          pr_read_lusage,         /* /proc/<pid>/lusage                   */
 635  635          pr_read_pagedata,       /* /proc/<pid>/pagedata                 */
 636  636          pr_read_watch,          /* /proc/<pid>/watch                    */
 637  637          pr_read_inval,          /* /proc/<pid>/cwd                      */
 638  638          pr_read_inval,          /* /proc/<pid>/root                     */
 639  639          pr_read_inval,          /* /proc/<pid>/fd                       */
 640  640          pr_read_inval,          /* /proc/<pid>/fd/nn                    */
 641  641          pr_read_inval,          /* /proc/<pid>/fdinfo                   */
 642  642          pr_read_fdinfo,         /* /proc/<pid>/fdinfo/nn                */
 643  643          pr_read_inval,          /* /proc/<pid>/object                   */
 644  644          pr_read_inval,          /* /proc/<pid>/object/xxx               */
 645  645          pr_read_inval,          /* /proc/<pid>/lwp                      */
 646  646          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>              */
 647  647          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
 648  648          pr_read_lwpname,        /* /proc/<pid>/lwp/<lwpid>/lwpname      */
 649  649          pr_read_lwpstatus,      /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
 650  650          pr_read_lwpsinfo,       /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
 651  651          pr_read_lwpusage,       /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
 652  652          pr_read_xregs,          /* /proc/<pid>/lwp/<lwpid>/xregs        */
 653  653          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/templates    */
 654  654          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
 655  655          pr_read_spymaster,      /* /proc/<pid>/lwp/<lwpid>/spymaster    */
 656  656  #if defined(__sparc)
 657  657          pr_read_gwindows,       /* /proc/<pid>/lwp/<lwpid>/gwindows     */
 658  658          pr_read_asrs,           /* /proc/<pid>/lwp/<lwpid>/asrs         */
 659  659  #endif
 660  660          pr_read_priv,           /* /proc/<pid>/priv                     */
 661  661          pr_read_inval,          /* /proc/<pid>/path                     */
 662  662          pr_read_inval,          /* /proc/<pid>/path/xxx                 */
 663  663          pr_read_inval,          /* /proc/<pid>/contracts                */
 664  664          pr_read_inval,          /* /proc/<pid>/contracts/<ctid>         */
 665  665          pr_read_secflags,       /* /proc/<pid>/secflags                 */
 666  666          pr_read_pidfile,        /* old process file                     */
 667  667          pr_read_pidfile,        /* old lwp file                         */
 668  668          pr_read_opagedata,      /* old pagedata file                    */
 669  669  };
 670  670  
 671  671  /* ARGSUSED */
 672  672  static int
 673  673  pr_read_inval(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 674  674  {
 675  675          /*
 676  676           * No read() on any /proc directory, use getdents(2) instead.
 677  677           * Cannot read a control file either.
 678  678           * An underlying mapped object file cannot get here.
 679  679           */
 680  680          return (EINVAL);
 681  681  }
 682  682  
 683  683  static int
 684  684  pr_uioread(void *base, long count, uio_t *uiop)
 685  685  {
 686  686          int error = 0;
 687  687  
 688  688          ASSERT(count >= 0);
 689  689          count -= uiop->uio_offset;
 690  690          if (count > 0 && uiop->uio_offset >= 0) {
 691  691                  error = uiomove((char *)base + uiop->uio_offset,
 692  692                      count, UIO_READ, uiop);
 693  693          }
 694  694  
 695  695          return (error);
 696  696  }
 697  697  
 698  698  static int
 699  699  pr_read_cmdline(prnode_t *pnp, uio_t *uiop)
 700  700  {
 701  701          char *args;
 702  702          int error;
 703  703          size_t asz = PRMAXARGVLEN, sz;
 704  704  
 705  705          /*
 706  706           * Allocate a scratch buffer for collection of the process arguments.
 707  707           */
 708  708          args = kmem_alloc(asz, KM_SLEEP);
 709  709  
 710  710          ASSERT(pnp->pr_type == PR_CMDLINE);
 711  711  
 712  712          if ((error = prlock(pnp, ZNO)) != 0) {
 713  713                  kmem_free(args, asz);
 714  714                  return (error);
 715  715          }
 716  716  
 717  717          if ((error = prreadcmdline(pnp->pr_common->prc_proc, args, asz,
 718  718              &sz)) != 0) {
 719  719                  prunlock(pnp);
 720  720                  kmem_free(args, asz);
 721  721                  return (error);
 722  722          }
 723  723  
 724  724          prunlock(pnp);
 725  725  
 726  726          error = pr_uioread(args, sz, uiop);
 727  727  
 728  728          kmem_free(args, asz);
 729  729  
 730  730          return (error);
 731  731  }
 732  732  
 733  733  static int
 734  734  pr_read_argv(prnode_t *pnp, uio_t *uiop)
 735  735  {
 736  736          char *args;
 737  737          int error;
 738  738          size_t asz = PRMAXARGVLEN, sz;
 739  739  
 740  740          /*
 741  741           * Allocate a scratch buffer for collection of the process arguments.
 742  742           */
 743  743          args = kmem_alloc(asz, KM_SLEEP);
 744  744  
 745  745          ASSERT(pnp->pr_type == PR_ARGV);
 746  746  
 747  747          if ((error = prlock(pnp, ZNO)) != 0) {
 748  748                  kmem_free(args, asz);
 749  749                  return (error);
 750  750          }
 751  751  
 752  752          if ((error = prreadargv(pnp->pr_common->prc_proc, args, asz,
 753  753              &sz)) != 0) {
 754  754                  prunlock(pnp);
 755  755                  kmem_free(args, asz);
 756  756                  return (error);
 757  757          }
 758  758  
 759  759          prunlock(pnp);
 760  760  
 761  761          error = pr_uioread(args, sz, uiop);
 762  762  
 763  763          kmem_free(args, asz);
 764  764  
 765  765          return (error);
 766  766  }
 767  767  
 768  768  static int
 769  769  pr_read_as(prnode_t *pnp, uio_t *uiop)
 770  770  {
 771  771          int error;
 772  772  
 773  773          ASSERT(pnp->pr_type == PR_AS);
 774  774  
 775  775          if ((error = prlock(pnp, ZNO)) == 0) {
 776  776                  proc_t *p = pnp->pr_common->prc_proc;
 777  777                  struct as *as = p->p_as;
 778  778  
 779  779                  /*
 780  780                   * /proc I/O cannot be done to a system process.
 781  781                   * A 32-bit process cannot read a 64-bit process.
 782  782                   */
 783  783                  if ((p->p_flag & SSYS) || as == &kas) {
 784  784                          error = 0;
 785  785  #ifdef _SYSCALL32_IMPL
 786  786                  } else if (curproc->p_model == DATAMODEL_ILP32 &&
 787  787                      PROCESS_NOT_32BIT(p)) {
 788  788                          error = EOVERFLOW;
 789  789  #endif
 790  790                  } else {
 791  791                          /*
 792  792                           * We don't hold p_lock over an i/o operation because
 793  793                           * that could lead to deadlock with the clock thread.
 794  794                           */
 795  795                          mutex_exit(&p->p_lock);
 796  796                          error = prusrio(p, UIO_READ, uiop, 0);
 797  797                          mutex_enter(&p->p_lock);
 798  798                  }
 799  799                  prunlock(pnp);
 800  800          }
 801  801  
 802  802          return (error);
 803  803  }
 804  804  
 805  805  static int
 806  806  pr_read_status(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 807  807  {
 808  808          pstatus_t *sp;
 809  809          int error;
 810  810  
 811  811          ASSERT(pnp->pr_type == PR_STATUS);
 812  812  
 813  813          /*
 814  814           * We kmem_alloc() the pstatus structure because
 815  815           * it is so big it might blow the kernel stack.
 816  816           */
 817  817          sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
 818  818          if ((error = prlock(pnp, ZNO)) == 0) {
 819  819                  prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
 820  820                  prunlock(pnp);
 821  821                  error = pr_uioread(sp, sizeof (*sp), uiop);
 822  822          }
 823  823          kmem_free(sp, sizeof (*sp));
 824  824          return (error);
 825  825  }
 826  826  
 827  827  static int
 828  828  pr_read_lstatus(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 829  829  {
 830  830          proc_t *p;
 831  831          kthread_t *t;
 832  832          lwpdir_t *ldp;
 833  833          size_t size;
 834  834          prheader_t *php;
 835  835          lwpstatus_t *sp;
 836  836          int error;
 837  837          int nlwp;
 838  838          int i;
 839  839  
 840  840          ASSERT(pnp->pr_type == PR_LSTATUS);
 841  841  
 842  842          if ((error = prlock(pnp, ZNO)) != 0)
 843  843                  return (error);
 844  844          p = pnp->pr_common->prc_proc;
 845  845          nlwp = p->p_lwpcnt;
 846  846          size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
 847  847  
 848  848          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
 849  849          mutex_exit(&p->p_lock);
 850  850          php = kmem_zalloc(size, KM_SLEEP);
 851  851          mutex_enter(&p->p_lock);
 852  852          /* p->p_lwpcnt can't change while process is locked */
 853  853          ASSERT(nlwp == p->p_lwpcnt);
 854  854  
 855  855          php->pr_nent = nlwp;
 856  856          php->pr_entsize = LSPAN(lwpstatus_t);
 857  857  
 858  858          sp = (lwpstatus_t *)(php + 1);
 859  859          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
 860  860                  if (ldp->ld_entry == NULL ||
 861  861                      (t = ldp->ld_entry->le_thread) == NULL)
 862  862                          continue;
 863  863                  prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
 864  864                  sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
 865  865          }
 866  866          prunlock(pnp);
 867  867  
 868  868          error = pr_uioread(php, size, uiop);
 869  869          kmem_free(php, size);
 870  870          return (error);
 871  871  }
 872  872  
 873  873  static int
 874  874  pr_read_psinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 875  875  {
 876  876          psinfo_t psinfo;
 877  877          proc_t *p;
 878  878          int error = 0;
 879  879  
 880  880          ASSERT(pnp->pr_type == PR_PSINFO);
 881  881  
 882  882          /*
 883  883           * We don't want the full treatment of prlock(pnp) here.
 884  884           * This file is world-readable and never goes invalid.
 885  885           * It doesn't matter if we are in the middle of an exec().
 886  886           */
 887  887          p = pr_p_lock(pnp);
 888  888          mutex_exit(&pr_pidlock);
 889  889          if (p == NULL)
 890  890                  error = ENOENT;
 891  891          else {
 892  892                  ASSERT(p == pnp->pr_common->prc_proc);
 893  893                  prgetpsinfo(p, &psinfo);
 894  894                  prunlock(pnp);
 895  895                  error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
 896  896          }
 897  897          return (error);
 898  898  }
 899  899  
 900  900  static int
 901  901  pr_read_fdinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 902  902  {
 903  903          prfdinfo_t *fdinfo;
 904  904          list_t data;
 905  905          proc_t *p;
 906  906          uint_t fd;
 907  907          file_t *fp;
 908  908          short ufp_flag;
 909  909          int error = 0;
 910  910  
 911  911          ASSERT(pnp->pr_type == PR_FDINFO);
 912  912  
 913  913          /*
 914  914           * This is a guess at the size of the structure that needs to
 915  915           * be returned. It's a balance between not allocating too much more
 916  916           * space than is required and not requiring too many subsequent
 917  917           * reallocations. Allocate it before acquiring the process lock.
 918  918           */
 919  919          pr_iol_initlist(&data, sizeof (prfdinfo_t) + MAXPATHLEN + 2, 1);
 920  920  
 921  921          if ((error = prlock(pnp, ZNO)) != 0) {
 922  922                  pr_iol_freelist(&data);
 923  923                  return (error);
 924  924          }
 925  925  
 926  926          p = pnp->pr_common->prc_proc;
 927  927  
 928  928          if ((p->p_flag & SSYS) || p->p_as == &kas) {
 929  929                  prunlock(pnp);
 930  930                  pr_iol_freelist(&data);
 931  931                  return (0);
 932  932          }
 933  933  
 934  934          fd = pnp->pr_index;
 935  935  
 936  936          /* Fetch and lock the file_t for this descriptor */
 937  937          fp = pr_getf(p, fd, &ufp_flag);
 938  938  
 939  939          if (fp == NULL) {
 940  940                  error = ENOENT;
 941  941                  prunlock(pnp);
 942  942                  goto out;
 943  943          }
 944  944  
 945  945          /*
 946  946           * For fdinfo, we don't want to include the placeholder pr_misc at the
 947  947           * end of the struct. We'll terminate the data with an empty pr_misc
 948  948           * header before returning.
 949  949           */
 950  950  
 951  951          fdinfo = pr_iol_newbuf(&data, offsetof(prfdinfo_t, pr_misc));
 952  952          fdinfo->pr_fd = fd;
 953  953          fdinfo->pr_fdflags = ufp_flag;
 954  954          fdinfo->pr_fileflags = fp->f_flag2 << 16 | fp->f_flag;
 955  955          if ((fdinfo->pr_fileflags & (FSEARCH | FEXEC)) == 0)
 956  956                  fdinfo->pr_fileflags += FOPEN;
 957  957          fdinfo->pr_offset = fp->f_offset;
 958  958          /*
 959  959           * Information from the vnode (rather than the file_t) is retrieved
 960  960           * later, in prgetfdinfo() - for example sock_getfasync()
 961  961           */
 962  962  
 963  963          prunlock(pnp);
 964  964  
 965  965          error = prgetfdinfo(p, fp->f_vnode, fdinfo, cr, fp->f_cred, &data);
 966  966  
 967  967          pr_releasef(fp);
 968  968  
 969  969  out:
 970  970          if (error == 0)
 971  971                  error = pr_iol_uiomove_and_free(&data, uiop, error);
 972  972          else
 973  973                  pr_iol_freelist(&data);
 974  974  
 975  975          return (error);
 976  976  }
 977  977  
 978  978  static int
 979  979  pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
 980  980  {
 981  981          proc_t *p;
 982  982          kthread_t *t;
 983  983          lwpdir_t *ldp;
 984  984          lwpent_t *lep;
 985  985          size_t size;
 986  986          prheader_t *php;
 987  987          lwpsinfo_t *sp;
 988  988          int error;
 989  989          int nlwp;
 990  990          int i;
 991  991  
 992  992          ASSERT(pnp->pr_type == PR_LPSINFO);
 993  993  
 994  994          /*
 995  995           * We don't want the full treatment of prlock(pnp) here.
 996  996           * This file is world-readable and never goes invalid.
 997  997           * It doesn't matter if we are in the middle of an exec().
 998  998           */
 999  999          p = pr_p_lock(pnp);
1000 1000          mutex_exit(&pr_pidlock);
1001 1001          if (p == NULL)
1002 1002                  return (ENOENT);
1003 1003          ASSERT(p == pnp->pr_common->prc_proc);
1004 1004          if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
1005 1005                  prunlock(pnp);
1006 1006                  return (ENOENT);
1007 1007          }
1008 1008          size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
1009 1009  
1010 1010          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1011 1011          mutex_exit(&p->p_lock);
1012 1012          php = kmem_zalloc(size, KM_SLEEP);
1013 1013          mutex_enter(&p->p_lock);
1014 1014          /* p->p_lwpcnt can't change while process is locked */
1015 1015          ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
1016 1016  
1017 1017          php->pr_nent = nlwp;
1018 1018          php->pr_entsize = LSPAN(lwpsinfo_t);
1019 1019  
1020 1020          sp = (lwpsinfo_t *)(php + 1);
1021 1021          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1022 1022                  if ((lep = ldp->ld_entry) == NULL)
1023 1023                          continue;
1024 1024                  if ((t = lep->le_thread) != NULL)
1025 1025                          prgetlwpsinfo(t, sp);
1026 1026                  else {
1027 1027                          bzero(sp, sizeof (*sp));
1028 1028                          sp->pr_lwpid = lep->le_lwpid;
1029 1029                          sp->pr_state = SZOMB;
1030 1030                          sp->pr_sname = 'Z';
1031 1031                          sp->pr_start.tv_sec = lep->le_start;
1032 1032                          sp->pr_bindpro = PBIND_NONE;
1033 1033                          sp->pr_bindpset = PS_NONE;
1034 1034                  }
1035 1035                  sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
1036 1036          }
1037 1037          prunlock(pnp);
1038 1038  
1039 1039          error = pr_uioread(php, size, uiop);
1040 1040          kmem_free(php, size);
1041 1041          return (error);
1042 1042  }
1043 1043  
1044 1044  static int
1045 1045  pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
1046 1046  {
1047 1047          proc_t *p;
1048 1048          struct as *as;
1049 1049          list_t iolhead;
1050 1050          int error;
1051 1051  
1052 1052  readmap_common:
1053 1053          if ((error = prlock(pnp, ZNO)) != 0)
1054 1054                  return (error);
1055 1055  
1056 1056          p = pnp->pr_common->prc_proc;
1057 1057          as = p->p_as;
1058 1058  
1059 1059          if ((p->p_flag & SSYS) || as == &kas) {
1060 1060                  prunlock(pnp);
1061 1061                  return (0);
1062 1062          }
1063 1063  
1064 1064          if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
1065 1065                  prunlock(pnp);
1066 1066                  delay(1);
1067 1067                  goto readmap_common;
1068 1068          }
1069 1069          mutex_exit(&p->p_lock);
1070 1070  
1071 1071          switch (type) {
1072 1072          case PR_XMAP:
1073 1073                  error = prgetxmap(p, &iolhead);
1074 1074                  break;
1075 1075          case PR_RMAP:
1076 1076                  error = prgetmap(p, 1, &iolhead);
1077 1077                  break;
1078 1078          case PR_MAP:
1079 1079                  error = prgetmap(p, 0, &iolhead);
1080 1080                  break;
1081 1081          }
1082 1082  
1083 1083          AS_LOCK_EXIT(as);
1084 1084          mutex_enter(&p->p_lock);
1085 1085          prunlock(pnp);
1086 1086  
1087 1087          error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
1088 1088  
1089 1089          return (error);
1090 1090  }
1091 1091  
1092 1092  static int
1093 1093  pr_read_map(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1094 1094  {
1095 1095          ASSERT(pnp->pr_type == PR_MAP);
1096 1096          return (pr_read_map_common(pnp, uiop, pnp->pr_type));
1097 1097  }
1098 1098  
1099 1099  static int
1100 1100  pr_read_rmap(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1101 1101  {
1102 1102          ASSERT(pnp->pr_type == PR_RMAP);
1103 1103          return (pr_read_map_common(pnp, uiop, pnp->pr_type));
1104 1104  }
1105 1105  
1106 1106  static int
1107 1107  pr_read_xmap(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1108 1108  {
1109 1109          ASSERT(pnp->pr_type == PR_XMAP);
1110 1110          return (pr_read_map_common(pnp, uiop, pnp->pr_type));
1111 1111  }
1112 1112  
1113 1113  static int
1114 1114  pr_read_cred(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1115 1115  {
1116 1116          proc_t *p;
1117 1117          prcred_t *pcrp;
1118 1118          int error;
1119 1119          size_t count;
1120 1120  
1121 1121          ASSERT(pnp->pr_type == PR_CRED);
1122 1122  
1123 1123          /*
1124 1124           * We kmem_alloc() the prcred_t structure because
1125 1125           * the number of supplementary groups is variable.
1126 1126           */
1127 1127          pcrp =
1128 1128              kmem_alloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
1129 1129              KM_SLEEP);
1130 1130  
1131 1131          if ((error = prlock(pnp, ZNO)) != 0)
1132 1132                  goto out;
1133 1133          p = pnp->pr_common->prc_proc;
1134 1134          ASSERT(p != NULL);
1135 1135  
1136 1136          prgetcred(p, pcrp);
1137 1137          prunlock(pnp);
1138 1138  
1139 1139          count = sizeof (prcred_t);
1140 1140          if (pcrp->pr_ngroups > 1)
1141 1141                  count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
1142 1142          error = pr_uioread(pcrp, count, uiop);
1143 1143  out:
1144 1144          kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
1145 1145          return (error);
1146 1146  }
1147 1147  
1148 1148  static int
1149 1149  pr_read_priv(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1150 1150  {
1151 1151          proc_t *p;
1152 1152          size_t psize = prgetprivsize();
1153 1153          prpriv_t *ppriv = kmem_alloc(psize, KM_SLEEP);
1154 1154          int error;
1155 1155  
1156 1156          ASSERT(pnp->pr_type == PR_PRIV);
1157 1157  
1158 1158          if ((error = prlock(pnp, ZNO)) != 0)
1159 1159                  goto out;
1160 1160          p = pnp->pr_common->prc_proc;
1161 1161          ASSERT(p != NULL);
1162 1162  
1163 1163          prgetpriv(p, ppriv);
1164 1164          prunlock(pnp);
1165 1165  
1166 1166          error = pr_uioread(ppriv, psize, uiop);
1167 1167  out:
1168 1168          kmem_free(ppriv, psize);
1169 1169          return (error);
1170 1170  }
1171 1171  
1172 1172  static int
1173 1173  pr_read_sigact(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1174 1174  {
1175 1175          int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1176 1176          proc_t *p;
1177 1177          struct sigaction *sap;
1178 1178          int sig;
1179 1179          int error;
1180 1180          user_t *up;
1181 1181  
1182 1182          ASSERT(pnp->pr_type == PR_SIGACT);
1183 1183  
1184 1184          /*
1185 1185           * We kmem_alloc() the sigaction array because
1186 1186           * it is so big it might blow the kernel stack.
1187 1187           */
1188 1188          sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
1189 1189  
1190 1190          if ((error = prlock(pnp, ZNO)) != 0)
1191 1191                  goto out;
1192 1192          p = pnp->pr_common->prc_proc;
1193 1193          ASSERT(p != NULL);
1194 1194  
1195 1195          if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
1196 1196                  prunlock(pnp);
1197 1197                  goto out;
1198 1198          }
1199 1199  
1200 1200          up = PTOU(p);
1201 1201          for (sig = 1; sig < nsig; sig++)
1202 1202                  prgetaction(p, up, sig, &sap[sig-1]);
1203 1203          prunlock(pnp);
1204 1204  
1205 1205          error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
1206 1206  out:
1207 1207          kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
1208 1208          return (error);
1209 1209  }
1210 1210  
1211 1211  static int
1212 1212  pr_read_auxv(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1213 1213  {
1214 1214          auxv_t auxv[__KERN_NAUXV_IMPL];
1215 1215          proc_t *p;
1216 1216          user_t *up;
1217 1217          int error;
1218 1218  
1219 1219          ASSERT(pnp->pr_type == PR_AUXV);
1220 1220  
1221 1221          if ((error = prlock(pnp, ZNO)) != 0)
1222 1222                  return (error);
1223 1223  
1224 1224          if (uiop->uio_offset >= sizeof (auxv)) {
1225 1225                  prunlock(pnp);
1226 1226                  return (0);
1227 1227          }
1228 1228  
1229 1229          p = pnp->pr_common->prc_proc;
1230 1230          up = PTOU(p);
1231 1231          bcopy(up->u_auxv, auxv, sizeof (auxv));
1232 1232          prunlock(pnp);
1233 1233  
1234 1234          return (pr_uioread(auxv, sizeof (auxv), uiop));
1235 1235  }
1236 1236  
1237 1237  #if defined(__x86)
1238 1238  /*
1239 1239   * XX64
1240 1240   *      This is almost certainly broken for the amd64 kernel, because
1241 1241   *      we have two kinds of LDT structures to export -- one for compatibility
1242 1242   *      mode, and one for long mode, sigh.
1243 1243   *
1244 1244   *      For now let's just have a ldt of size 0 for 64-bit processes.
1245 1245   */
1246 1246  static int
1247 1247  pr_read_ldt(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1248 1248  {
1249 1249          proc_t *p;
1250 1250          struct ssd *ssd;
1251 1251          size_t size;
1252 1252          int error;
1253 1253  
1254 1254          ASSERT(pnp->pr_type == PR_LDT);
1255 1255  
1256 1256          if ((error = prlock(pnp, ZNO)) != 0)
1257 1257                  return (error);
1258 1258          p = pnp->pr_common->prc_proc;
1259 1259  
1260 1260          mutex_exit(&p->p_lock);
1261 1261          mutex_enter(&p->p_ldtlock);
1262 1262          size = prnldt(p) * sizeof (struct ssd);
1263 1263          if (uiop->uio_offset >= size) {
1264 1264                  mutex_exit(&p->p_ldtlock);
1265 1265                  mutex_enter(&p->p_lock);
1266 1266                  prunlock(pnp);
1267 1267                  return (0);
1268 1268          }
1269 1269  
1270 1270          ssd = kmem_alloc(size, KM_SLEEP);
1271 1271          prgetldt(p, ssd);
1272 1272          mutex_exit(&p->p_ldtlock);
1273 1273          mutex_enter(&p->p_lock);
1274 1274          prunlock(pnp);
1275 1275  
1276 1276          error = pr_uioread(ssd, size, uiop);
1277 1277          kmem_free(ssd, size);
1278 1278          return (error);
1279 1279  }
1280 1280  #endif  /* __x86 */
1281 1281  
1282 1282  static int
1283 1283  pr_read_usage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1284 1284  {
1285 1285          prhusage_t *pup;
1286 1286          prusage_t *upup;
1287 1287          proc_t *p;
1288 1288          kthread_t *t;
1289 1289          int error;
1290 1290  
1291 1291          ASSERT(pnp->pr_type == PR_USAGE);
1292 1292  
1293 1293          /* allocate now, before locking the process */
1294 1294          pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1295 1295          upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1296 1296  
1297 1297          /*
1298 1298           * We don't want the full treatment of prlock(pnp) here.
1299 1299           * This file is world-readable and never goes invalid.
1300 1300           * It doesn't matter if we are in the middle of an exec().
1301 1301           */
1302 1302          p = pr_p_lock(pnp);
1303 1303          mutex_exit(&pr_pidlock);
1304 1304          if (p == NULL) {
1305 1305                  error = ENOENT;
1306 1306                  goto out;
1307 1307          }
1308 1308          ASSERT(p == pnp->pr_common->prc_proc);
1309 1309  
1310 1310          if (uiop->uio_offset >= sizeof (prusage_t)) {
1311 1311                  prunlock(pnp);
1312 1312                  error = 0;
1313 1313                  goto out;
1314 1314          }
1315 1315  
1316 1316          pup->pr_tstamp = gethrtime();
1317 1317  
1318 1318          pup->pr_count  = p->p_defunct;
1319 1319          pup->pr_create = p->p_mstart;
1320 1320          pup->pr_term   = p->p_mterm;
1321 1321  
1322 1322          pup->pr_rtime    = p->p_mlreal;
1323 1323          pup->pr_utime    = p->p_acct[LMS_USER];
1324 1324          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
1325 1325          pup->pr_ttime    = p->p_acct[LMS_TRAP];
1326 1326          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
1327 1327          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
1328 1328          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
1329 1329          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
1330 1330          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
1331 1331          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
1332 1332          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1333 1333  
1334 1334          pup->pr_minf  = p->p_ru.minflt;
1335 1335          pup->pr_majf  = p->p_ru.majflt;
1336 1336          pup->pr_nswap = p->p_ru.nswap;
1337 1337          pup->pr_inblk = p->p_ru.inblock;
1338 1338          pup->pr_oublk = p->p_ru.oublock;
1339 1339          pup->pr_msnd  = p->p_ru.msgsnd;
1340 1340          pup->pr_mrcv  = p->p_ru.msgrcv;
1341 1341          pup->pr_sigs  = p->p_ru.nsignals;
1342 1342          pup->pr_vctx  = p->p_ru.nvcsw;
1343 1343          pup->pr_ictx  = p->p_ru.nivcsw;
1344 1344          pup->pr_sysc  = p->p_ru.sysc;
1345 1345          pup->pr_ioch  = p->p_ru.ioch;
1346 1346  
1347 1347          /*
1348 1348           * Add the usage information for each active lwp.
1349 1349           */
1350 1350          if ((t = p->p_tlist) != NULL &&
1351 1351              !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
1352 1352                  do {
1353 1353                          if (t->t_proc_flag & TP_LWPEXIT)
1354 1354                                  continue;
1355 1355                          pup->pr_count++;
1356 1356                          praddusage(t, pup);
1357 1357                  } while ((t = t->t_forw) != p->p_tlist);
1358 1358          }
1359 1359  
1360 1360          prunlock(pnp);
1361 1361  
1362 1362          prcvtusage(pup, upup);
1363 1363  
1364 1364          error = pr_uioread(upup, sizeof (prusage_t), uiop);
1365 1365  out:
1366 1366          kmem_free(pup, sizeof (*pup));
1367 1367          kmem_free(upup, sizeof (*upup));
1368 1368          return (error);
1369 1369  }
1370 1370  
1371 1371  static int
1372 1372  pr_read_lusage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1373 1373  {
1374 1374          int nlwp;
1375 1375          prhusage_t *pup;
1376 1376          prheader_t *php;
1377 1377          prusage_t *upup;
1378 1378          size_t size;
1379 1379          hrtime_t curtime;
1380 1380          proc_t *p;
1381 1381          kthread_t *t;
1382 1382          lwpdir_t *ldp;
1383 1383          int error;
1384 1384          int i;
1385 1385  
1386 1386          ASSERT(pnp->pr_type == PR_LUSAGE);
1387 1387  
1388 1388          /*
1389 1389           * We don't want the full treatment of prlock(pnp) here.
1390 1390           * This file is world-readable and never goes invalid.
1391 1391           * It doesn't matter if we are in the middle of an exec().
1392 1392           */
1393 1393          p = pr_p_lock(pnp);
1394 1394          mutex_exit(&pr_pidlock);
1395 1395          if (p == NULL)
1396 1396                  return (ENOENT);
1397 1397          ASSERT(p == pnp->pr_common->prc_proc);
1398 1398          if ((nlwp = p->p_lwpcnt) == 0) {
1399 1399                  prunlock(pnp);
1400 1400                  return (ENOENT);
1401 1401          }
1402 1402  
1403 1403          size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
1404 1404          if (uiop->uio_offset >= size) {
1405 1405                  prunlock(pnp);
1406 1406                  return (0);
1407 1407          }
1408 1408  
1409 1409          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1410 1410          mutex_exit(&p->p_lock);
1411 1411          pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
1412 1412          mutex_enter(&p->p_lock);
1413 1413          /* p->p_lwpcnt can't change while process is locked */
1414 1414          ASSERT(nlwp == p->p_lwpcnt);
1415 1415  
1416 1416          php = (prheader_t *)(pup + 1);
1417 1417          upup = (prusage_t *)(php + 1);
1418 1418  
1419 1419          php->pr_nent = nlwp + 1;
1420 1420          php->pr_entsize = LSPAN(prusage_t);
1421 1421  
1422 1422          curtime = gethrtime();
1423 1423  
1424 1424          /*
1425 1425           * First the summation over defunct lwps.
1426 1426           */
1427 1427          pup->pr_count  = p->p_defunct;
1428 1428          pup->pr_tstamp = curtime;
1429 1429          pup->pr_create = p->p_mstart;
1430 1430          pup->pr_term   = p->p_mterm;
1431 1431  
1432 1432          pup->pr_rtime    = p->p_mlreal;
1433 1433          pup->pr_utime    = p->p_acct[LMS_USER];
1434 1434          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
1435 1435          pup->pr_ttime    = p->p_acct[LMS_TRAP];
1436 1436          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
1437 1437          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
1438 1438          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
1439 1439          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
1440 1440          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
1441 1441          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
1442 1442          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1443 1443  
1444 1444          pup->pr_minf  = p->p_ru.minflt;
1445 1445          pup->pr_majf  = p->p_ru.majflt;
1446 1446          pup->pr_nswap = p->p_ru.nswap;
1447 1447          pup->pr_inblk = p->p_ru.inblock;
1448 1448          pup->pr_oublk = p->p_ru.oublock;
1449 1449          pup->pr_msnd  = p->p_ru.msgsnd;
1450 1450          pup->pr_mrcv  = p->p_ru.msgrcv;
1451 1451          pup->pr_sigs  = p->p_ru.nsignals;
1452 1452          pup->pr_vctx  = p->p_ru.nvcsw;
1453 1453          pup->pr_ictx  = p->p_ru.nivcsw;
1454 1454          pup->pr_sysc  = p->p_ru.sysc;
1455 1455          pup->pr_ioch  = p->p_ru.ioch;
1456 1456  
1457 1457          prcvtusage(pup, upup);
1458 1458  
1459 1459          /*
1460 1460           * Fill one prusage struct for each active lwp.
1461 1461           */
1462 1462          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1463 1463                  if (ldp->ld_entry == NULL ||
1464 1464                      (t = ldp->ld_entry->le_thread) == NULL)
1465 1465                          continue;
1466 1466                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1467 1467                  ASSERT(nlwp > 0);
1468 1468                  --nlwp;
1469 1469                  upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
1470 1470                  prgetusage(t, pup);
1471 1471                  prcvtusage(pup, upup);
1472 1472          }
1473 1473          ASSERT(nlwp == 0);
1474 1474  
1475 1475          prunlock(pnp);
1476 1476  
1477 1477          error = pr_uioread(php, size, uiop);
1478 1478          kmem_free(pup, size + sizeof (prhusage_t));
1479 1479          return (error);
1480 1480  }
1481 1481  
1482 1482  static int
1483 1483  pr_read_pagedata(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1484 1484  {
1485 1485          proc_t *p;
1486 1486          int error;
1487 1487  
1488 1488          ASSERT(pnp->pr_type == PR_PAGEDATA);
1489 1489  
1490 1490          if ((error = prlock(pnp, ZNO)) != 0)
1491 1491                  return (error);
1492 1492  
1493 1493          p = pnp->pr_common->prc_proc;
1494 1494          if ((p->p_flag & SSYS) || p->p_as == &kas) {
1495 1495                  prunlock(pnp);
1496 1496                  return (0);
1497 1497          }
1498 1498  
1499 1499          mutex_exit(&p->p_lock);
1500 1500          error = prpdread(p, pnp->pr_hatid, uiop);
1501 1501          mutex_enter(&p->p_lock);
1502 1502  
1503 1503          prunlock(pnp);
1504 1504          return (error);
1505 1505  }
1506 1506  
1507 1507  static int
1508 1508  pr_read_opagedata(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1509 1509  {
1510 1510          proc_t *p;
1511 1511          struct as *as;
1512 1512          int error;
1513 1513  
1514 1514          ASSERT(pnp->pr_type == PR_OPAGEDATA);
1515 1515  
1516 1516          if ((error = prlock(pnp, ZNO)) != 0)
1517 1517                  return (error);
1518 1518  
1519 1519          p = pnp->pr_common->prc_proc;
1520 1520          as = p->p_as;
1521 1521          if ((p->p_flag & SSYS) || as == &kas) {
1522 1522                  prunlock(pnp);
1523 1523                  return (0);
1524 1524          }
1525 1525  
1526 1526          mutex_exit(&p->p_lock);
1527 1527          error = oprpdread(as, pnp->pr_hatid, uiop);
1528 1528          mutex_enter(&p->p_lock);
1529 1529  
1530 1530          prunlock(pnp);
1531 1531          return (error);
1532 1532  }
1533 1533  
1534 1534  static int
1535 1535  pr_read_watch(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1536 1536  {
1537 1537          proc_t *p;
1538 1538          int error;
1539 1539          prwatch_t *Bpwp;
1540 1540          size_t size;
1541 1541          prwatch_t *pwp;
1542 1542          int nwarea;
1543 1543          struct watched_area *pwarea;
1544 1544  
1545 1545          ASSERT(pnp->pr_type == PR_WATCH);
1546 1546  
1547 1547          if ((error = prlock(pnp, ZNO)) != 0)
1548 1548                  return (error);
1549 1549  
1550 1550          p = pnp->pr_common->prc_proc;
1551 1551          nwarea = avl_numnodes(&p->p_warea);
1552 1552          size = nwarea * sizeof (prwatch_t);
1553 1553          if (uiop->uio_offset >= size) {
1554 1554                  prunlock(pnp);
1555 1555                  return (0);
1556 1556          }
1557 1557  
1558 1558          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1559 1559          mutex_exit(&p->p_lock);
1560 1560          Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
1561 1561          mutex_enter(&p->p_lock);
1562 1562          /* p->p_nwarea can't change while process is locked */
1563 1563          ASSERT(nwarea == avl_numnodes(&p->p_warea));
1564 1564  
1565 1565          /* gather the watched areas */
1566 1566          for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
1567 1567              pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
1568 1568                  pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
1569 1569                  pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
1570 1570                  pwp->pr_wflags = (int)pwarea->wa_flags;
1571 1571          }
1572 1572  
1573 1573          prunlock(pnp);
1574 1574  
1575 1575          error = pr_uioread(Bpwp, size, uiop);
1576 1576          kmem_free(Bpwp, size);
1577 1577          return (error);
1578 1578  }
1579 1579  
1580 1580  static int
1581 1581  pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1582 1582  {
1583 1583          lwpstatus_t *sp;
1584 1584          int error;
1585 1585  
1586 1586          ASSERT(pnp->pr_type == PR_LWPSTATUS);
1587 1587  
1588 1588          /*
1589 1589           * We kmem_alloc() the lwpstatus structure because
1590 1590           * it is so big it might blow the kernel stack.
1591 1591           */
1592 1592          sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1593 1593  
1594 1594          if ((error = prlock(pnp, ZNO)) != 0)
1595 1595                  goto out;
1596 1596  
1597 1597          if (uiop->uio_offset >= sizeof (*sp)) {
1598 1598                  prunlock(pnp);
1599 1599                  goto out;
1600 1600          }
1601 1601  
1602 1602          prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
1603 1603          prunlock(pnp);
1604 1604  
1605 1605          error = pr_uioread(sp, sizeof (*sp), uiop);
1606 1606  out:
1607 1607          kmem_free(sp, sizeof (*sp));
1608 1608          return (error);
1609 1609  }
1610 1610  
1611 1611  static int
1612 1612  pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1613 1613  {
1614 1614          lwpsinfo_t lwpsinfo;
1615 1615          proc_t *p;
1616 1616          kthread_t *t;
1617 1617          lwpent_t *lep;
1618 1618  
1619 1619          ASSERT(pnp->pr_type == PR_LWPSINFO);
1620 1620  
1621 1621          /*
1622 1622           * We don't want the full treatment of prlock(pnp) here.
1623 1623           * This file is world-readable and never goes invalid.
1624 1624           * It doesn't matter if we are in the middle of an exec().
1625 1625           */
1626 1626          p = pr_p_lock(pnp);
1627 1627          mutex_exit(&pr_pidlock);
1628 1628          if (p == NULL)
1629 1629                  return (ENOENT);
1630 1630          ASSERT(p == pnp->pr_common->prc_proc);
1631 1631          if (pnp->pr_common->prc_tslot == -1) {
1632 1632                  prunlock(pnp);
1633 1633                  return (ENOENT);
1634 1634          }
1635 1635  
1636 1636          if (uiop->uio_offset >= sizeof (lwpsinfo)) {
1637 1637                  prunlock(pnp);
1638 1638                  return (0);
1639 1639          }
1640 1640  
1641 1641          if ((t = pnp->pr_common->prc_thread) != NULL)
1642 1642                  prgetlwpsinfo(t, &lwpsinfo);
1643 1643          else {
1644 1644                  lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
1645 1645                  bzero(&lwpsinfo, sizeof (lwpsinfo));
1646 1646                  lwpsinfo.pr_lwpid = lep->le_lwpid;
1647 1647                  lwpsinfo.pr_state = SZOMB;
1648 1648                  lwpsinfo.pr_sname = 'Z';
1649 1649                  lwpsinfo.pr_start.tv_sec = lep->le_start;
1650 1650                  lwpsinfo.pr_bindpro = PBIND_NONE;
1651 1651                  lwpsinfo.pr_bindpset = PS_NONE;
1652 1652          }
1653 1653          prunlock(pnp);
1654 1654  
1655 1655          return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
1656 1656  }
1657 1657  
1658 1658  static int
1659 1659  pr_read_lwpusage(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1660 1660  {
1661 1661          prhusage_t *pup;
1662 1662          prusage_t *upup;
1663 1663          proc_t *p;
1664 1664          int error;
1665 1665  
1666 1666          ASSERT(pnp->pr_type == PR_LWPUSAGE);
1667 1667  
1668 1668          /* allocate now, before locking the process */
1669 1669          pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1670 1670          upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1671 1671  
1672 1672          /*
1673 1673           * We don't want the full treatment of prlock(pnp) here.
1674 1674           * This file is world-readable and never goes invalid.
1675 1675           * It doesn't matter if we are in the middle of an exec().
1676 1676           */
1677 1677          p = pr_p_lock(pnp);
1678 1678          mutex_exit(&pr_pidlock);
1679 1679          if (p == NULL) {
1680 1680                  error = ENOENT;
1681 1681                  goto out;
1682 1682          }
1683 1683          ASSERT(p == pnp->pr_common->prc_proc);
1684 1684          if (pnp->pr_common->prc_thread == NULL) {
1685 1685                  prunlock(pnp);
1686 1686                  error = ENOENT;
1687 1687                  goto out;
1688 1688          }
1689 1689          if (uiop->uio_offset >= sizeof (prusage_t)) {
1690 1690                  prunlock(pnp);
1691 1691                  error = 0;
1692 1692                  goto out;
1693 1693          }
1694 1694  
1695 1695          pup->pr_tstamp = gethrtime();
1696 1696          prgetusage(pnp->pr_common->prc_thread, pup);
1697 1697  
1698 1698          prunlock(pnp);
1699 1699  
1700 1700          prcvtusage(pup, upup);
1701 1701  
1702 1702          error = pr_uioread(upup, sizeof (prusage_t), uiop);
1703 1703  out:
1704 1704          kmem_free(pup, sizeof (*pup));
1705 1705          kmem_free(upup, sizeof (*upup));
1706 1706          return (error);
1707 1707  }
1708 1708  
1709 1709  static int
1710 1710  pr_read_lwpname(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1711 1711  {
1712 1712          char lwpname[THREAD_NAME_MAX];
1713 1713          kthread_t *t;
1714 1714          int error;
1715 1715  
1716 1716          ASSERT(pnp->pr_type == PR_LWPNAME);
1717 1717  
1718 1718          if (uiop->uio_offset >= THREAD_NAME_MAX)
1719 1719                  return (0);
1720 1720  
1721 1721          if ((error = prlock(pnp, ZNO)) != 0)
1722 1722                  return (error);
1723 1723  
1724 1724          bzero(lwpname, sizeof (lwpname));
1725 1725  
1726 1726          t = pnp->pr_common->prc_thread;
1727 1727  
1728 1728          if (t->t_name != NULL)
1729 1729                  (void) strlcpy(lwpname, t->t_name, sizeof (lwpname));
  
    | 
      ↓ open down ↓ | 
    1691 lines elided | 
    
      ↑ open up ↑ | 
  
1730 1730  
1731 1731          prunlock(pnp);
1732 1732  
1733 1733          return (pr_uioread(lwpname, sizeof (lwpname), uiop));
1734 1734  }
1735 1735  
1736 1736  /* ARGSUSED */
1737 1737  static int
1738 1738  pr_read_xregs(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1739 1739  {
1740      -#if defined(__sparc)
1741 1740          proc_t *p;
1742 1741          kthread_t *t;
1743 1742          int error;
1744      -        char *xreg;
     1743 +        void *xreg;
1745 1744          size_t size;
1746 1745  
1747 1746          ASSERT(pnp->pr_type == PR_XREGS);
1748 1747  
1749      -        xreg = kmem_zalloc(sizeof (prxregset_t), KM_SLEEP);
1750      -
1751 1748          if ((error = prlock(pnp, ZNO)) != 0)
1752      -                goto out;
     1749 +                return (error);
1753 1750  
1754 1751          p = pnp->pr_common->prc_proc;
1755 1752          t = pnp->pr_common->prc_thread;
1756 1753  
1757      -        size = prhasx(p)? prgetprxregsize(p) : 0;
     1754 +        /*
     1755 +         * While we would prefer to do the allocation with holding the process
     1756 +         * this way, we can only determine this size while holding the process
     1757 +         * as the hold guarantees us:
     1758 +         *
     1759 +         *  o That the process in question actualy exists.
     1760 +         *  o That the process in question cannot change the set of FPU features
     1761 +         *    it has enabled.
     1762 +         *
     1763 +         * We will drop p_lock across the allocation call itself. This should be
     1764 +         * safe as the enabled feature set should not change while the process
     1765 +         * is locked (e.g. enabling extending FPU state like AMX on x86 should
     1766 +         * require the process to be locked).
     1767 +         */
     1768 +        size = prhasx(p) ? prgetprxregsize(p) : 0;
     1769 +        if (size == 0) {
     1770 +                prunlock(pnp);
     1771 +                return (0);
     1772 +        }
     1773 +        mutex_exit(&p->p_lock);
     1774 +        xreg = kmem_zalloc(size, KM_SLEEP);
     1775 +        mutex_enter(&p->p_lock);
     1776 +        ASSERT3U(size, ==, prgetprxregsize(p));
     1777 +
1758 1778          if (uiop->uio_offset >= size) {
1759 1779                  prunlock(pnp);
1760 1780                  goto out;
1761 1781          }
1762 1782  
1763 1783          /* drop p->p_lock while (possibly) touching the stack */
1764 1784          mutex_exit(&p->p_lock);
1765 1785          prgetprxregs(ttolwp(t), xreg);
1766 1786          mutex_enter(&p->p_lock);
1767 1787          prunlock(pnp);
1768 1788  
1769 1789          error = pr_uioread(xreg, size, uiop);
1770 1790  out:
1771      -        kmem_free(xreg, sizeof (prxregset_t));
     1791 +        kmem_free(xreg, size);
1772 1792          return (error);
1773      -#else
1774      -        return (0);
1775      -#endif
1776 1793  }
1777 1794  
1778 1795  static int
1779 1796  pr_read_spymaster(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1780 1797  {
1781 1798          psinfo_t psinfo;
1782 1799          int error;
1783 1800          klwp_t *lwp;
1784 1801  
1785 1802          ASSERT(pnp->pr_type == PR_SPYMASTER);
1786 1803  
1787 1804          if ((error = prlock(pnp, ZNO)) != 0)
1788 1805                  return (error);
1789 1806  
1790 1807          if (pnp->pr_common->prc_thread == NULL) {
1791 1808                  prunlock(pnp);
1792 1809                  return (0);
1793 1810          }
1794 1811  
1795 1812          lwp = pnp->pr_common->prc_thread->t_lwp;
1796 1813  
1797 1814          if (lwp->lwp_spymaster == NULL) {
1798 1815                  prunlock(pnp);
1799 1816                  return (0);
1800 1817          }
1801 1818  
1802 1819          bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1803 1820          prunlock(pnp);
1804 1821  
1805 1822          return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1806 1823  }
1807 1824  
1808 1825  static int
1809 1826  pr_read_secflags(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1810 1827  {
1811 1828          prsecflags_t ret;
1812 1829          int error;
1813 1830          proc_t *p;
1814 1831  
1815 1832          ASSERT(pnp->pr_type == PR_SECFLAGS);
1816 1833  
1817 1834          if ((error = prlock(pnp, ZNO)) != 0)
1818 1835                  return (error);
1819 1836  
1820 1837          p = pnp->pr_common->prc_proc;
1821 1838          prgetsecflags(p, &ret);
1822 1839          prunlock(pnp);
1823 1840  
1824 1841          return (pr_uioread(&ret, sizeof (ret), uiop));
1825 1842  }
1826 1843  
1827 1844  #if defined(__sparc)
1828 1845  
1829 1846  static int
1830 1847  pr_read_gwindows(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1831 1848  {
1832 1849          proc_t *p;
1833 1850          kthread_t *t;
1834 1851          gwindows_t *gwp;
1835 1852          int error;
1836 1853          size_t size;
1837 1854  
1838 1855          ASSERT(pnp->pr_type == PR_GWINDOWS);
1839 1856  
1840 1857          gwp = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP);
1841 1858  
1842 1859          if ((error = prlock(pnp, ZNO)) != 0)
1843 1860                  goto out;
1844 1861  
1845 1862          p = pnp->pr_common->prc_proc;
1846 1863          t = pnp->pr_common->prc_thread;
1847 1864  
1848 1865          /*
1849 1866           * Drop p->p_lock while touching the stack.
1850 1867           * The P_PR_LOCK flag prevents the lwp from
1851 1868           * disappearing while we do this.
1852 1869           */
1853 1870          mutex_exit(&p->p_lock);
1854 1871          if ((size = prnwindows(ttolwp(t))) != 0)
1855 1872                  size = sizeof (gwindows_t) -
1856 1873                      (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow);
1857 1874          if (uiop->uio_offset >= size) {
1858 1875                  mutex_enter(&p->p_lock);
1859 1876                  prunlock(pnp);
1860 1877                  goto out;
1861 1878          }
1862 1879          prgetwindows(ttolwp(t), gwp);
1863 1880          mutex_enter(&p->p_lock);
1864 1881          prunlock(pnp);
1865 1882  
1866 1883          error = pr_uioread(gwp, size, uiop);
1867 1884  out:
1868 1885          kmem_free(gwp, sizeof (gwindows_t));
1869 1886          return (error);
1870 1887  }
1871 1888  
1872 1889  /* ARGSUSED */
1873 1890  static int
1874 1891  pr_read_asrs(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1875 1892  {
1876 1893          int error;
1877 1894  
1878 1895          ASSERT(pnp->pr_type == PR_ASRS);
1879 1896  
1880 1897          /* the asrs file exists only for sparc v9 _LP64 processes */
1881 1898          if ((error = prlock(pnp, ZNO)) == 0) {
1882 1899                  proc_t *p = pnp->pr_common->prc_proc;
1883 1900                  kthread_t *t = pnp->pr_common->prc_thread;
1884 1901                  asrset_t asrset;
1885 1902  
1886 1903                  if (p->p_model != DATAMODEL_LP64 ||
1887 1904                      uiop->uio_offset >= sizeof (asrset_t)) {
1888 1905                          prunlock(pnp);
1889 1906                          return (0);
1890 1907                  }
1891 1908  
1892 1909                  /*
1893 1910                   * Drop p->p_lock while touching the stack.
1894 1911                   * The P_PR_LOCK flag prevents the lwp from
1895 1912                   * disappearing while we do this.
1896 1913                   */
1897 1914                  mutex_exit(&p->p_lock);
1898 1915                  prgetasregs(ttolwp(t), asrset);
1899 1916                  mutex_enter(&p->p_lock);
1900 1917                  prunlock(pnp);
1901 1918  
1902 1919                  error = pr_uioread(&asrset[0], sizeof (asrset_t), uiop);
1903 1920          }
1904 1921  
1905 1922          return (error);
1906 1923  }
1907 1924  
1908 1925  #endif  /* __sparc */
1909 1926  
1910 1927  static int
1911 1928  pr_read_piddir(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1912 1929  {
1913 1930          ASSERT(pnp->pr_type == PR_PIDDIR);
1914 1931          ASSERT(pnp->pr_pidfile != NULL);
1915 1932  
1916 1933          /* use the underlying PR_PIDFILE to read the process */
1917 1934          pnp = VTOP(pnp->pr_pidfile);
1918 1935          ASSERT(pnp->pr_type == PR_PIDFILE);
1919 1936  
1920 1937          return (pr_read_pidfile(pnp, uiop));
1921 1938  }
1922 1939  
1923 1940  static int
1924 1941  pr_read_pidfile(prnode_t *pnp, uio_t *uiop, cred_t *cr)
1925 1942  {
1926 1943          int error;
1927 1944  
1928 1945          ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
1929 1946  
1930 1947          if ((error = prlock(pnp, ZNO)) == 0) {
1931 1948                  proc_t *p = pnp->pr_common->prc_proc;
1932 1949                  struct as *as = p->p_as;
1933 1950  
1934 1951                  if ((p->p_flag & SSYS) || as == &kas) {
1935 1952                          /*
1936 1953                           * /proc I/O cannot be done to a system process.
1937 1954                           */
1938 1955                          error = EIO;    /* old /proc semantics */
1939 1956                  } else {
1940 1957                          /*
1941 1958                           * We drop p_lock because we don't want to hold
1942 1959                           * it over an I/O operation because that could
1943 1960                           * lead to deadlock with the clock thread.
1944 1961                           * The process will not disappear and its address
1945 1962                           * space will not change because it is marked P_PR_LOCK.
1946 1963                           */
1947 1964                          mutex_exit(&p->p_lock);
1948 1965                          error = prusrio(p, UIO_READ, uiop, 1);
1949 1966                          mutex_enter(&p->p_lock);
1950 1967                  }
1951 1968                  prunlock(pnp);
1952 1969          }
1953 1970  
1954 1971          return (error);
1955 1972  }
1956 1973  
1957 1974  #ifdef _SYSCALL32_IMPL
1958 1975  
1959 1976  /*
1960 1977   * Array of ILP32 read functions, indexed by /proc file type.
1961 1978   */
1962 1979  static int pr_read_status_32(),
1963 1980          pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
1964 1981          pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
1965 1982          pr_read_sigact_32(), pr_read_auxv_32(),
1966 1983          pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
1967 1984          pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1968 1985          pr_read_lwpusage_32(), pr_read_spymaster_32(),
1969 1986  #if defined(__sparc)
1970 1987          pr_read_gwindows_32(),
1971 1988  #endif
1972 1989          pr_read_opagedata_32();
1973 1990  
1974 1991  static int (*pr_read_function_32[PR_NFILES])() = {
1975 1992          pr_read_inval,          /* /proc                                */
1976 1993          pr_read_inval,          /* /proc/self                           */
1977 1994          pr_read_piddir,         /* /proc/<pid> (old /proc read())       */
1978 1995          pr_read_as,             /* /proc/<pid>/as                       */
1979 1996          pr_read_inval,          /* /proc/<pid>/ctl                      */
1980 1997          pr_read_status_32,      /* /proc/<pid>/status                   */
1981 1998          pr_read_lstatus_32,     /* /proc/<pid>/lstatus                  */
1982 1999          pr_read_psinfo_32,      /* /proc/<pid>/psinfo                   */
1983 2000          pr_read_lpsinfo_32,     /* /proc/<pid>/lpsinfo                  */
1984 2001          pr_read_map_32,         /* /proc/<pid>/map                      */
1985 2002          pr_read_rmap_32,        /* /proc/<pid>/rmap                     */
1986 2003          pr_read_xmap_32,        /* /proc/<pid>/xmap                     */
1987 2004          pr_read_cred,           /* /proc/<pid>/cred                     */
1988 2005          pr_read_sigact_32,      /* /proc/<pid>/sigact                   */
1989 2006          pr_read_auxv_32,        /* /proc/<pid>/auxv                     */
1990 2007  #if defined(__x86)
1991 2008          pr_read_ldt,            /* /proc/<pid>/ldt                      */
1992 2009  #endif
1993 2010          pr_read_argv,           /* /proc/<pid>/argv                     */
1994 2011          pr_read_cmdline,        /* /proc/<pid>/cmdline                  */
1995 2012          pr_read_usage_32,       /* /proc/<pid>/usage                    */
1996 2013          pr_read_lusage_32,      /* /proc/<pid>/lusage                   */
1997 2014          pr_read_pagedata_32,    /* /proc/<pid>/pagedata                 */
1998 2015          pr_read_watch_32,       /* /proc/<pid>/watch                    */
1999 2016          pr_read_inval,          /* /proc/<pid>/cwd                      */
2000 2017          pr_read_inval,          /* /proc/<pid>/root                     */
2001 2018          pr_read_inval,          /* /proc/<pid>/fd                       */
2002 2019          pr_read_inval,          /* /proc/<pid>/fd/nn                    */
2003 2020          pr_read_inval,          /* /proc/<pid>/fdinfo                   */
2004 2021          pr_read_fdinfo,         /* /proc/<pid>/fdinfo/nn                */
2005 2022          pr_read_inval,          /* /proc/<pid>/object                   */
2006 2023          pr_read_inval,          /* /proc/<pid>/object/xxx               */
2007 2024          pr_read_inval,          /* /proc/<pid>/lwp                      */
2008 2025          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>              */
2009 2026          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
2010 2027          pr_read_lwpname,        /* /proc/<pid>/lwp/<lwpid>/lwpname      */
2011 2028          pr_read_lwpstatus_32,   /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
2012 2029          pr_read_lwpsinfo_32,    /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
2013 2030          pr_read_lwpusage_32,    /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
2014 2031          pr_read_xregs,          /* /proc/<pid>/lwp/<lwpid>/xregs        */
2015 2032          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/templates    */
2016 2033          pr_read_inval,          /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
2017 2034          pr_read_spymaster_32,   /* /proc/<pid>/lwp/<lwpid>/spymaster    */
2018 2035  #if defined(__sparc)
2019 2036          pr_read_gwindows_32,    /* /proc/<pid>/lwp/<lwpid>/gwindows     */
2020 2037          pr_read_asrs,           /* /proc/<pid>/lwp/<lwpid>/asrs         */
2021 2038  #endif
2022 2039          pr_read_priv,           /* /proc/<pid>/priv                     */
2023 2040          pr_read_inval,          /* /proc/<pid>/path                     */
2024 2041          pr_read_inval,          /* /proc/<pid>/path/xxx                 */
2025 2042          pr_read_inval,          /* /proc/<pid>/contracts                */
2026 2043          pr_read_inval,          /* /proc/<pid>/contracts/<ctid>         */
2027 2044          pr_read_secflags,       /* /proc/<pid>/secflags                 */
2028 2045          pr_read_pidfile,        /* old process file                     */
2029 2046          pr_read_pidfile,        /* old lwp file                         */
2030 2047          pr_read_opagedata_32,   /* old pagedata file                    */
2031 2048  };
2032 2049  
2033 2050  static int
2034 2051  pr_read_status_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2035 2052  {
2036 2053          pstatus32_t *sp;
2037 2054          proc_t *p;
2038 2055          int error;
2039 2056  
2040 2057          ASSERT(pnp->pr_type == PR_STATUS);
2041 2058  
2042 2059          /*
2043 2060           * We kmem_alloc() the pstatus structure because
2044 2061           * it is so big it might blow the kernel stack.
2045 2062           */
2046 2063          sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
2047 2064          if ((error = prlock(pnp, ZNO)) == 0) {
2048 2065                  /*
2049 2066                   * A 32-bit process cannot get the status of a 64-bit process.
2050 2067                   * The fields for the 64-bit quantities are not large enough.
2051 2068                   */
2052 2069                  p = pnp->pr_common->prc_proc;
2053 2070                  if (PROCESS_NOT_32BIT(p)) {
2054 2071                          prunlock(pnp);
2055 2072                          error = EOVERFLOW;
2056 2073                  } else {
2057 2074                          prgetstatus32(pnp->pr_common->prc_proc, sp,
2058 2075                              VTOZONE(PTOV(pnp)));
2059 2076                          prunlock(pnp);
2060 2077                          error = pr_uioread(sp, sizeof (*sp), uiop);
2061 2078                  }
2062 2079          }
2063 2080          kmem_free((caddr_t)sp, sizeof (*sp));
2064 2081          return (error);
2065 2082  }
2066 2083  
2067 2084  static int
2068 2085  pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2069 2086  {
2070 2087          proc_t *p;
2071 2088          kthread_t *t;
2072 2089          lwpdir_t *ldp;
2073 2090          size_t size;
2074 2091          prheader32_t *php;
2075 2092          lwpstatus32_t *sp;
2076 2093          int error;
2077 2094          int nlwp;
2078 2095          int i;
2079 2096  
2080 2097          ASSERT(pnp->pr_type == PR_LSTATUS);
2081 2098  
2082 2099          if ((error = prlock(pnp, ZNO)) != 0)
2083 2100                  return (error);
2084 2101          p = pnp->pr_common->prc_proc;
2085 2102          /*
2086 2103           * A 32-bit process cannot get the status of a 64-bit process.
2087 2104           * The fields for the 64-bit quantities are not large enough.
2088 2105           */
2089 2106          if (PROCESS_NOT_32BIT(p)) {
2090 2107                  prunlock(pnp);
2091 2108                  return (EOVERFLOW);
2092 2109          }
2093 2110          nlwp = p->p_lwpcnt;
2094 2111          size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
2095 2112  
2096 2113          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2097 2114          mutex_exit(&p->p_lock);
2098 2115          php = kmem_zalloc(size, KM_SLEEP);
2099 2116          mutex_enter(&p->p_lock);
2100 2117          /* p->p_lwpcnt can't change while process is locked */
2101 2118          ASSERT(nlwp == p->p_lwpcnt);
2102 2119  
2103 2120          php->pr_nent = nlwp;
2104 2121          php->pr_entsize = LSPAN32(lwpstatus32_t);
2105 2122  
2106 2123          sp = (lwpstatus32_t *)(php + 1);
2107 2124          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2108 2125                  if (ldp->ld_entry == NULL ||
2109 2126                      (t = ldp->ld_entry->le_thread) == NULL)
2110 2127                          continue;
2111 2128                  prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
2112 2129                  sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
2113 2130          }
2114 2131          prunlock(pnp);
2115 2132  
2116 2133          error = pr_uioread(php, size, uiop);
2117 2134          kmem_free(php, size);
2118 2135          return (error);
2119 2136  }
2120 2137  
2121 2138  static int
2122 2139  pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2123 2140  {
2124 2141          psinfo32_t psinfo;
2125 2142          proc_t *p;
2126 2143          int error = 0;
2127 2144  
2128 2145          ASSERT(pnp->pr_type == PR_PSINFO);
2129 2146  
2130 2147          /*
2131 2148           * We don't want the full treatment of prlock(pnp) here.
2132 2149           * This file is world-readable and never goes invalid.
2133 2150           * It doesn't matter if we are in the middle of an exec().
2134 2151           */
2135 2152          p = pr_p_lock(pnp);
2136 2153          mutex_exit(&pr_pidlock);
2137 2154          if (p == NULL)
2138 2155                  error = ENOENT;
2139 2156          else {
2140 2157                  ASSERT(p == pnp->pr_common->prc_proc);
2141 2158                  prgetpsinfo32(p, &psinfo);
2142 2159                  prunlock(pnp);
2143 2160                  error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
2144 2161          }
2145 2162          return (error);
2146 2163  }
2147 2164  
2148 2165  static int
2149 2166  pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2150 2167  {
2151 2168          proc_t *p;
2152 2169          kthread_t *t;
2153 2170          lwpdir_t *ldp;
2154 2171          lwpent_t *lep;
2155 2172          size_t size;
2156 2173          prheader32_t *php;
2157 2174          lwpsinfo32_t *sp;
2158 2175          int error;
2159 2176          int nlwp;
2160 2177          int i;
2161 2178  
2162 2179          ASSERT(pnp->pr_type == PR_LPSINFO);
2163 2180  
2164 2181          /*
2165 2182           * We don't want the full treatment of prlock(pnp) here.
2166 2183           * This file is world-readable and never goes invalid.
2167 2184           * It doesn't matter if we are in the middle of an exec().
2168 2185           */
2169 2186          p = pr_p_lock(pnp);
2170 2187          mutex_exit(&pr_pidlock);
2171 2188          if (p == NULL)
2172 2189                  return (ENOENT);
2173 2190          ASSERT(p == pnp->pr_common->prc_proc);
2174 2191          if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
2175 2192                  prunlock(pnp);
2176 2193                  return (ENOENT);
2177 2194          }
2178 2195          size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
2179 2196  
2180 2197          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2181 2198          mutex_exit(&p->p_lock);
2182 2199          php = kmem_zalloc(size, KM_SLEEP);
2183 2200          mutex_enter(&p->p_lock);
2184 2201          /* p->p_lwpcnt can't change while process is locked */
2185 2202          ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
2186 2203  
2187 2204          php->pr_nent = nlwp;
2188 2205          php->pr_entsize = LSPAN32(lwpsinfo32_t);
2189 2206  
2190 2207          sp = (lwpsinfo32_t *)(php + 1);
2191 2208          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2192 2209                  if ((lep = ldp->ld_entry) == NULL)
2193 2210                          continue;
2194 2211                  if ((t = lep->le_thread) != NULL)
2195 2212                          prgetlwpsinfo32(t, sp);
2196 2213                  else {
2197 2214                          bzero(sp, sizeof (*sp));
2198 2215                          sp->pr_lwpid = lep->le_lwpid;
2199 2216                          sp->pr_state = SZOMB;
2200 2217                          sp->pr_sname = 'Z';
2201 2218                          sp->pr_start.tv_sec = (time32_t)lep->le_start;
2202 2219                  }
2203 2220                  sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
2204 2221          }
2205 2222          prunlock(pnp);
2206 2223  
2207 2224          error = pr_uioread(php, size, uiop);
2208 2225          kmem_free(php, size);
2209 2226          return (error);
2210 2227  }
2211 2228  
2212 2229  static int
2213 2230  pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
2214 2231  {
2215 2232          proc_t *p;
2216 2233          struct as *as;
2217 2234          list_t  iolhead;
2218 2235          int error;
2219 2236  
2220 2237  readmap32_common:
2221 2238          if ((error = prlock(pnp, ZNO)) != 0)
2222 2239                  return (error);
2223 2240  
2224 2241          p = pnp->pr_common->prc_proc;
2225 2242          as = p->p_as;
2226 2243  
2227 2244          if ((p->p_flag & SSYS) || as == &kas) {
2228 2245                  prunlock(pnp);
2229 2246                  return (0);
2230 2247          }
2231 2248  
2232 2249          if (PROCESS_NOT_32BIT(p)) {
2233 2250                  prunlock(pnp);
2234 2251                  return (EOVERFLOW);
2235 2252          }
2236 2253  
2237 2254          if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
2238 2255                  prunlock(pnp);
2239 2256                  delay(1);
2240 2257                  goto readmap32_common;
2241 2258          }
2242 2259          mutex_exit(&p->p_lock);
2243 2260  
2244 2261          switch (type) {
2245 2262          case PR_XMAP:
2246 2263                  error = prgetxmap32(p, &iolhead);
2247 2264                  break;
2248 2265          case PR_RMAP:
2249 2266                  error = prgetmap32(p, 1, &iolhead);
2250 2267                  break;
2251 2268          case PR_MAP:
2252 2269                  error = prgetmap32(p, 0, &iolhead);
2253 2270                  break;
2254 2271          }
2255 2272          AS_LOCK_EXIT(as);
2256 2273          mutex_enter(&p->p_lock);
2257 2274          prunlock(pnp);
2258 2275  
2259 2276          error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
2260 2277  
2261 2278          return (error);
2262 2279  }
2263 2280  
2264 2281  static int
2265 2282  pr_read_map_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2266 2283  {
2267 2284          ASSERT(pnp->pr_type == PR_MAP);
2268 2285          return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2269 2286  }
2270 2287  
2271 2288  static int
2272 2289  pr_read_rmap_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2273 2290  {
2274 2291          ASSERT(pnp->pr_type == PR_RMAP);
2275 2292          return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2276 2293  }
2277 2294  
2278 2295  static int
2279 2296  pr_read_xmap_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2280 2297  {
2281 2298          ASSERT(pnp->pr_type == PR_XMAP);
2282 2299          return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2283 2300  }
2284 2301  
2285 2302  static int
2286 2303  pr_read_sigact_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2287 2304  {
2288 2305          int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
2289 2306          proc_t *p;
2290 2307          struct sigaction32 *sap;
2291 2308          int sig;
2292 2309          int error;
2293 2310          user_t *up;
2294 2311  
2295 2312          ASSERT(pnp->pr_type == PR_SIGACT);
2296 2313  
2297 2314          /*
2298 2315           * We kmem_alloc() the sigaction32 array because
2299 2316           * it is so big it might blow the kernel stack.
2300 2317           */
2301 2318          sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
2302 2319  
2303 2320          if ((error = prlock(pnp, ZNO)) != 0)
2304 2321                  goto out;
2305 2322          p = pnp->pr_common->prc_proc;
2306 2323  
2307 2324          if (PROCESS_NOT_32BIT(p)) {
2308 2325                  prunlock(pnp);
2309 2326                  error = EOVERFLOW;
2310 2327                  goto out;
2311 2328          }
2312 2329  
2313 2330          if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
2314 2331                  prunlock(pnp);
2315 2332                  goto out;
2316 2333          }
2317 2334  
2318 2335          up = PTOU(p);
2319 2336          for (sig = 1; sig < nsig; sig++)
2320 2337                  prgetaction32(p, up, sig, &sap[sig-1]);
2321 2338          prunlock(pnp);
2322 2339  
2323 2340          error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
2324 2341  out:
2325 2342          kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
2326 2343          return (error);
2327 2344  }
2328 2345  
2329 2346  static int
2330 2347  pr_read_auxv_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2331 2348  {
2332 2349          auxv32_t auxv[__KERN_NAUXV_IMPL];
2333 2350          proc_t *p;
2334 2351          user_t *up;
2335 2352          int error;
2336 2353          int i;
2337 2354  
2338 2355          ASSERT(pnp->pr_type == PR_AUXV);
2339 2356  
2340 2357          if ((error = prlock(pnp, ZNO)) != 0)
2341 2358                  return (error);
2342 2359          p = pnp->pr_common->prc_proc;
2343 2360  
2344 2361          if (PROCESS_NOT_32BIT(p)) {
2345 2362                  prunlock(pnp);
2346 2363                  return (EOVERFLOW);
2347 2364          }
2348 2365  
2349 2366          if (uiop->uio_offset >= sizeof (auxv)) {
2350 2367                  prunlock(pnp);
2351 2368                  return (0);
2352 2369          }
2353 2370  
2354 2371          up = PTOU(p);
2355 2372          for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2356 2373                  auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
2357 2374                  auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
2358 2375          }
2359 2376          prunlock(pnp);
2360 2377  
2361 2378          return (pr_uioread(auxv, sizeof (auxv), uiop));
2362 2379  }
2363 2380  
2364 2381  static int
2365 2382  pr_read_usage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2366 2383  {
2367 2384          prhusage_t *pup;
2368 2385          prusage32_t *upup;
2369 2386          proc_t *p;
2370 2387          kthread_t *t;
2371 2388          int error;
2372 2389  
2373 2390          ASSERT(pnp->pr_type == PR_USAGE);
2374 2391  
2375 2392          /* allocate now, before locking the process */
2376 2393          pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2377 2394          upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2378 2395  
2379 2396          /*
2380 2397           * We don't want the full treatment of prlock(pnp) here.
2381 2398           * This file is world-readable and never goes invalid.
2382 2399           * It doesn't matter if we are in the middle of an exec().
2383 2400           */
2384 2401          p = pr_p_lock(pnp);
2385 2402          mutex_exit(&pr_pidlock);
2386 2403          if (p == NULL) {
2387 2404                  error = ENOENT;
2388 2405                  goto out;
2389 2406          }
2390 2407          ASSERT(p == pnp->pr_common->prc_proc);
2391 2408  
2392 2409          if (uiop->uio_offset >= sizeof (prusage32_t)) {
2393 2410                  prunlock(pnp);
2394 2411                  error = 0;
2395 2412                  goto out;
2396 2413          }
2397 2414  
2398 2415          pup->pr_tstamp = gethrtime();
2399 2416  
2400 2417          pup->pr_count  = p->p_defunct;
2401 2418          pup->pr_create = p->p_mstart;
2402 2419          pup->pr_term   = p->p_mterm;
2403 2420  
2404 2421          pup->pr_rtime    = p->p_mlreal;
2405 2422          pup->pr_utime    = p->p_acct[LMS_USER];
2406 2423          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
2407 2424          pup->pr_ttime    = p->p_acct[LMS_TRAP];
2408 2425          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
2409 2426          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
2410 2427          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
2411 2428          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
2412 2429          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
2413 2430          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
2414 2431          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2415 2432  
2416 2433          pup->pr_minf  = p->p_ru.minflt;
2417 2434          pup->pr_majf  = p->p_ru.majflt;
2418 2435          pup->pr_nswap = p->p_ru.nswap;
2419 2436          pup->pr_inblk = p->p_ru.inblock;
2420 2437          pup->pr_oublk = p->p_ru.oublock;
2421 2438          pup->pr_msnd  = p->p_ru.msgsnd;
2422 2439          pup->pr_mrcv  = p->p_ru.msgrcv;
2423 2440          pup->pr_sigs  = p->p_ru.nsignals;
2424 2441          pup->pr_vctx  = p->p_ru.nvcsw;
2425 2442          pup->pr_ictx  = p->p_ru.nivcsw;
2426 2443          pup->pr_sysc  = p->p_ru.sysc;
2427 2444          pup->pr_ioch  = p->p_ru.ioch;
2428 2445  
2429 2446          /*
2430 2447           * Add the usage information for each active lwp.
2431 2448           */
2432 2449          if ((t = p->p_tlist) != NULL &&
2433 2450              !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
2434 2451                  do {
2435 2452                          if (t->t_proc_flag & TP_LWPEXIT)
2436 2453                                  continue;
2437 2454                          pup->pr_count++;
2438 2455                          praddusage(t, pup);
2439 2456                  } while ((t = t->t_forw) != p->p_tlist);
2440 2457          }
2441 2458  
2442 2459          prunlock(pnp);
2443 2460  
2444 2461          prcvtusage32(pup, upup);
2445 2462  
2446 2463          error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2447 2464  out:
2448 2465          kmem_free(pup, sizeof (*pup));
2449 2466          kmem_free(upup, sizeof (*upup));
2450 2467          return (error);
2451 2468  }
2452 2469  
2453 2470  static int
2454 2471  pr_read_lusage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2455 2472  {
2456 2473          int nlwp;
2457 2474          prhusage_t *pup;
2458 2475          prheader32_t *php;
2459 2476          prusage32_t *upup;
2460 2477          size_t size;
2461 2478          hrtime_t curtime;
2462 2479          proc_t *p;
2463 2480          kthread_t *t;
2464 2481          lwpdir_t *ldp;
2465 2482          int error;
2466 2483          int i;
2467 2484  
2468 2485          ASSERT(pnp->pr_type == PR_LUSAGE);
2469 2486  
2470 2487          /*
2471 2488           * We don't want the full treatment of prlock(pnp) here.
2472 2489           * This file is world-readable and never goes invalid.
2473 2490           * It doesn't matter if we are in the middle of an exec().
2474 2491           */
2475 2492          p = pr_p_lock(pnp);
2476 2493          mutex_exit(&pr_pidlock);
2477 2494          if (p == NULL)
2478 2495                  return (ENOENT);
2479 2496          ASSERT(p == pnp->pr_common->prc_proc);
2480 2497          if ((nlwp = p->p_lwpcnt) == 0) {
2481 2498                  prunlock(pnp);
2482 2499                  return (ENOENT);
2483 2500          }
2484 2501  
2485 2502          size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
2486 2503          if (uiop->uio_offset >= size) {
2487 2504                  prunlock(pnp);
2488 2505                  return (0);
2489 2506          }
2490 2507  
2491 2508          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2492 2509          mutex_exit(&p->p_lock);
2493 2510          pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
2494 2511          mutex_enter(&p->p_lock);
2495 2512          /* p->p_lwpcnt can't change while process is locked */
2496 2513          ASSERT(nlwp == p->p_lwpcnt);
2497 2514  
2498 2515          php = (prheader32_t *)(pup + 1);
2499 2516          upup = (prusage32_t *)(php + 1);
2500 2517  
2501 2518          php->pr_nent = nlwp + 1;
2502 2519          php->pr_entsize = LSPAN32(prusage32_t);
2503 2520  
2504 2521          curtime = gethrtime();
2505 2522  
2506 2523          /*
2507 2524           * First the summation over defunct lwps.
2508 2525           */
2509 2526          pup->pr_count  = p->p_defunct;
2510 2527          pup->pr_tstamp = curtime;
2511 2528          pup->pr_create = p->p_mstart;
2512 2529          pup->pr_term   = p->p_mterm;
2513 2530  
2514 2531          pup->pr_rtime    = p->p_mlreal;
2515 2532          pup->pr_utime    = p->p_acct[LMS_USER];
2516 2533          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
2517 2534          pup->pr_ttime    = p->p_acct[LMS_TRAP];
2518 2535          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
2519 2536          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
2520 2537          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
2521 2538          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
2522 2539          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
2523 2540          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
2524 2541          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2525 2542  
2526 2543          pup->pr_minf  = p->p_ru.minflt;
2527 2544          pup->pr_majf  = p->p_ru.majflt;
2528 2545          pup->pr_nswap = p->p_ru.nswap;
2529 2546          pup->pr_inblk = p->p_ru.inblock;
2530 2547          pup->pr_oublk = p->p_ru.oublock;
2531 2548          pup->pr_msnd  = p->p_ru.msgsnd;
2532 2549          pup->pr_mrcv  = p->p_ru.msgrcv;
2533 2550          pup->pr_sigs  = p->p_ru.nsignals;
2534 2551          pup->pr_vctx  = p->p_ru.nvcsw;
2535 2552          pup->pr_ictx  = p->p_ru.nivcsw;
2536 2553          pup->pr_sysc  = p->p_ru.sysc;
2537 2554          pup->pr_ioch  = p->p_ru.ioch;
2538 2555  
2539 2556          prcvtusage32(pup, upup);
2540 2557  
2541 2558          /*
2542 2559           * Fill one prusage struct for each active lwp.
2543 2560           */
2544 2561          for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2545 2562                  if (ldp->ld_entry == NULL ||
2546 2563                      (t = ldp->ld_entry->le_thread) == NULL)
2547 2564                          continue;
2548 2565                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2549 2566                  ASSERT(nlwp > 0);
2550 2567                  --nlwp;
2551 2568                  upup = (prusage32_t *)
2552 2569                      ((caddr_t)upup + LSPAN32(prusage32_t));
2553 2570                  prgetusage(t, pup);
2554 2571                  prcvtusage32(pup, upup);
2555 2572          }
2556 2573          ASSERT(nlwp == 0);
2557 2574  
2558 2575          prunlock(pnp);
2559 2576  
2560 2577          error = pr_uioread(php, size, uiop);
2561 2578          kmem_free(pup, size + sizeof (prhusage_t));
2562 2579          return (error);
2563 2580  }
2564 2581  
2565 2582  static int
2566 2583  pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2567 2584  {
2568 2585          proc_t *p;
2569 2586          int error;
2570 2587  
2571 2588          ASSERT(pnp->pr_type == PR_PAGEDATA);
2572 2589  
2573 2590          if ((error = prlock(pnp, ZNO)) != 0)
2574 2591                  return (error);
2575 2592  
2576 2593          p = pnp->pr_common->prc_proc;
2577 2594          if ((p->p_flag & SSYS) || p->p_as == &kas) {
2578 2595                  prunlock(pnp);
2579 2596                  return (0);
2580 2597          }
2581 2598  
2582 2599          if (PROCESS_NOT_32BIT(p)) {
2583 2600                  prunlock(pnp);
2584 2601                  return (EOVERFLOW);
2585 2602          }
2586 2603  
2587 2604          mutex_exit(&p->p_lock);
2588 2605          error = prpdread32(p, pnp->pr_hatid, uiop);
2589 2606          mutex_enter(&p->p_lock);
2590 2607  
2591 2608          prunlock(pnp);
2592 2609          return (error);
2593 2610  }
2594 2611  
2595 2612  static int
2596 2613  pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2597 2614  {
2598 2615          proc_t *p;
2599 2616          struct as *as;
2600 2617          int error;
2601 2618  
2602 2619          ASSERT(pnp->pr_type == PR_OPAGEDATA);
2603 2620  
2604 2621          if ((error = prlock(pnp, ZNO)) != 0)
2605 2622                  return (error);
2606 2623  
2607 2624          p = pnp->pr_common->prc_proc;
2608 2625          as = p->p_as;
2609 2626  
2610 2627          if ((p->p_flag & SSYS) || as == &kas) {
2611 2628                  prunlock(pnp);
2612 2629                  return (0);
2613 2630          }
2614 2631  
2615 2632          if (PROCESS_NOT_32BIT(p)) {
2616 2633                  prunlock(pnp);
2617 2634                  return (EOVERFLOW);
2618 2635          }
2619 2636  
2620 2637          mutex_exit(&p->p_lock);
2621 2638          error = oprpdread32(as, pnp->pr_hatid, uiop);
2622 2639          mutex_enter(&p->p_lock);
2623 2640  
2624 2641          prunlock(pnp);
2625 2642          return (error);
2626 2643  }
2627 2644  
2628 2645  static int
2629 2646  pr_read_watch_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2630 2647  {
2631 2648          proc_t *p;
2632 2649          int error;
2633 2650          prwatch32_t *Bpwp;
2634 2651          size_t size;
2635 2652          prwatch32_t *pwp;
2636 2653          int nwarea;
2637 2654          struct watched_area *pwarea;
2638 2655  
2639 2656          ASSERT(pnp->pr_type == PR_WATCH);
2640 2657  
2641 2658          if ((error = prlock(pnp, ZNO)) != 0)
2642 2659                  return (error);
2643 2660  
2644 2661          p = pnp->pr_common->prc_proc;
2645 2662          if (PROCESS_NOT_32BIT(p)) {
2646 2663                  prunlock(pnp);
2647 2664                  return (EOVERFLOW);
2648 2665          }
2649 2666          nwarea = avl_numnodes(&p->p_warea);
2650 2667          size = nwarea * sizeof (prwatch32_t);
2651 2668          if (uiop->uio_offset >= size) {
2652 2669                  prunlock(pnp);
2653 2670                  return (0);
2654 2671          }
2655 2672  
2656 2673          /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2657 2674          mutex_exit(&p->p_lock);
2658 2675          Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
2659 2676          mutex_enter(&p->p_lock);
2660 2677          /* p->p_nwarea can't change while process is locked */
2661 2678          ASSERT(nwarea == avl_numnodes(&p->p_warea));
2662 2679  
2663 2680          /* gather the watched areas */
2664 2681          for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
2665 2682              pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
2666 2683                  pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
2667 2684                  pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
2668 2685                  pwp->pr_wflags = (int)pwarea->wa_flags;
2669 2686          }
2670 2687  
2671 2688          prunlock(pnp);
2672 2689  
2673 2690          error = pr_uioread(Bpwp, size, uiop);
2674 2691          kmem_free(Bpwp, size);
2675 2692          return (error);
2676 2693  }
2677 2694  
2678 2695  static int
2679 2696  pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2680 2697  {
2681 2698          lwpstatus32_t *sp;
2682 2699          proc_t *p;
2683 2700          int error;
2684 2701  
2685 2702          ASSERT(pnp->pr_type == PR_LWPSTATUS);
2686 2703  
2687 2704          /*
2688 2705           * We kmem_alloc() the lwpstatus structure because
2689 2706           * it is so big it might blow the kernel stack.
2690 2707           */
2691 2708          sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
2692 2709  
2693 2710          if ((error = prlock(pnp, ZNO)) != 0)
2694 2711                  goto out;
2695 2712  
2696 2713          /*
2697 2714           * A 32-bit process cannot get the status of a 64-bit process.
2698 2715           * The fields for the 64-bit quantities are not large enough.
2699 2716           */
2700 2717          p = pnp->pr_common->prc_proc;
2701 2718          if (PROCESS_NOT_32BIT(p)) {
2702 2719                  prunlock(pnp);
2703 2720                  error = EOVERFLOW;
2704 2721                  goto out;
2705 2722          }
2706 2723  
2707 2724          if (uiop->uio_offset >= sizeof (*sp)) {
2708 2725                  prunlock(pnp);
2709 2726                  goto out;
2710 2727          }
2711 2728  
2712 2729          prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
2713 2730          prunlock(pnp);
2714 2731  
2715 2732          error = pr_uioread(sp, sizeof (*sp), uiop);
2716 2733  out:
2717 2734          kmem_free(sp, sizeof (*sp));
2718 2735          return (error);
2719 2736  }
2720 2737  
2721 2738  static int
2722 2739  pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2723 2740  {
2724 2741          lwpsinfo32_t lwpsinfo;
2725 2742          proc_t *p;
2726 2743          kthread_t *t;
2727 2744          lwpent_t *lep;
2728 2745  
2729 2746          ASSERT(pnp->pr_type == PR_LWPSINFO);
2730 2747  
2731 2748          /*
2732 2749           * We don't want the full treatment of prlock(pnp) here.
2733 2750           * This file is world-readable and never goes invalid.
2734 2751           * It doesn't matter if we are in the middle of an exec().
2735 2752           */
2736 2753          p = pr_p_lock(pnp);
2737 2754          mutex_exit(&pr_pidlock);
2738 2755          if (p == NULL)
2739 2756                  return (ENOENT);
2740 2757          ASSERT(p == pnp->pr_common->prc_proc);
2741 2758          if (pnp->pr_common->prc_tslot == -1) {
2742 2759                  prunlock(pnp);
2743 2760                  return (ENOENT);
2744 2761          }
2745 2762  
2746 2763          if (uiop->uio_offset >= sizeof (lwpsinfo)) {
2747 2764                  prunlock(pnp);
2748 2765                  return (0);
2749 2766          }
2750 2767  
2751 2768          if ((t = pnp->pr_common->prc_thread) != NULL)
2752 2769                  prgetlwpsinfo32(t, &lwpsinfo);
2753 2770          else {
2754 2771                  lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
2755 2772                  bzero(&lwpsinfo, sizeof (lwpsinfo));
2756 2773                  lwpsinfo.pr_lwpid = lep->le_lwpid;
2757 2774                  lwpsinfo.pr_state = SZOMB;
2758 2775                  lwpsinfo.pr_sname = 'Z';
2759 2776                  lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
2760 2777          }
2761 2778          prunlock(pnp);
2762 2779  
2763 2780          return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
2764 2781  }
2765 2782  
2766 2783  static int
2767 2784  pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2768 2785  {
2769 2786          prhusage_t *pup;
2770 2787          prusage32_t *upup;
2771 2788          proc_t *p;
2772 2789          int error;
2773 2790  
2774 2791          ASSERT(pnp->pr_type == PR_LWPUSAGE);
2775 2792  
2776 2793          /* allocate now, before locking the process */
2777 2794          pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2778 2795          upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2779 2796  
2780 2797          /*
2781 2798           * We don't want the full treatment of prlock(pnp) here.
2782 2799           * This file is world-readable and never goes invalid.
2783 2800           * It doesn't matter if we are in the middle of an exec().
2784 2801           */
2785 2802          p = pr_p_lock(pnp);
2786 2803          mutex_exit(&pr_pidlock);
2787 2804          if (p == NULL) {
2788 2805                  error = ENOENT;
2789 2806                  goto out;
2790 2807          }
2791 2808          ASSERT(p == pnp->pr_common->prc_proc);
2792 2809          if (pnp->pr_common->prc_thread == NULL) {
2793 2810                  prunlock(pnp);
2794 2811                  error = ENOENT;
2795 2812                  goto out;
2796 2813          }
2797 2814          if (uiop->uio_offset >= sizeof (prusage32_t)) {
2798 2815                  prunlock(pnp);
2799 2816                  error = 0;
2800 2817                  goto out;
2801 2818          }
2802 2819  
2803 2820          pup->pr_tstamp = gethrtime();
2804 2821          prgetusage(pnp->pr_common->prc_thread, pup);
2805 2822  
2806 2823          prunlock(pnp);
2807 2824  
2808 2825          prcvtusage32(pup, upup);
2809 2826  
2810 2827          error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2811 2828  out:
2812 2829          kmem_free(pup, sizeof (*pup));
2813 2830          kmem_free(upup, sizeof (*upup));
2814 2831          return (error);
2815 2832  }
2816 2833  
2817 2834  static int
2818 2835  pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2819 2836  {
2820 2837          psinfo32_t psinfo;
2821 2838          int error;
2822 2839          klwp_t *lwp;
2823 2840  
2824 2841          ASSERT(pnp->pr_type == PR_SPYMASTER);
2825 2842  
2826 2843          if ((error = prlock(pnp, ZNO)) != 0)
2827 2844                  return (error);
2828 2845  
2829 2846          if (pnp->pr_common->prc_thread == NULL) {
2830 2847                  prunlock(pnp);
2831 2848                  return (0);
2832 2849          }
2833 2850  
2834 2851          lwp = pnp->pr_common->prc_thread->t_lwp;
2835 2852  
2836 2853          if (lwp->lwp_spymaster == NULL) {
2837 2854                  prunlock(pnp);
2838 2855                  return (0);
2839 2856          }
2840 2857  
2841 2858          psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2842 2859          prunlock(pnp);
2843 2860  
2844 2861          return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2845 2862  }
2846 2863  
2847 2864  #if defined(__sparc)
2848 2865  static int
2849 2866  pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop, cred_t *cr)
2850 2867  {
2851 2868          proc_t *p;
2852 2869          kthread_t *t;
2853 2870          gwindows32_t *gwp;
2854 2871          int error;
2855 2872          size_t size;
2856 2873  
2857 2874          ASSERT(pnp->pr_type == PR_GWINDOWS);
2858 2875  
2859 2876          gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
2860 2877  
2861 2878          if ((error = prlock(pnp, ZNO)) != 0)
2862 2879                  goto out;
2863 2880  
2864 2881          p = pnp->pr_common->prc_proc;
2865 2882          t = pnp->pr_common->prc_thread;
2866 2883  
2867 2884          if (PROCESS_NOT_32BIT(p)) {
2868 2885                  prunlock(pnp);
2869 2886                  error = EOVERFLOW;
2870 2887                  goto out;
2871 2888          }
2872 2889  
2873 2890          /*
2874 2891           * Drop p->p_lock while touching the stack.
2875 2892           * The P_PR_LOCK flag prevents the lwp from
2876 2893           * disappearing while we do this.
2877 2894           */
2878 2895          mutex_exit(&p->p_lock);
2879 2896          if ((size = prnwindows(ttolwp(t))) != 0)
2880 2897                  size = sizeof (gwindows32_t) -
2881 2898                      (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
2882 2899          if (uiop->uio_offset >= size) {
2883 2900                  mutex_enter(&p->p_lock);
2884 2901                  prunlock(pnp);
2885 2902                  goto out;
2886 2903          }
2887 2904          prgetwindows32(ttolwp(t), gwp);
2888 2905          mutex_enter(&p->p_lock);
2889 2906          prunlock(pnp);
2890 2907  
2891 2908          error = pr_uioread(gwp, size, uiop);
2892 2909  out:
2893 2910          kmem_free(gwp, sizeof (gwindows32_t));
2894 2911          return (error);
2895 2912  }
2896 2913  #endif  /* __sparc */
2897 2914  
2898 2915  #endif  /* _SYSCALL32_IMPL */
2899 2916  
2900 2917  /* ARGSUSED */
2901 2918  static int
2902 2919  prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2903 2920  {
2904 2921          prnode_t *pnp = VTOP(vp);
2905 2922  
2906 2923          ASSERT(pnp->pr_type < PR_NFILES);
2907 2924  
2908 2925  #ifdef _SYSCALL32_IMPL
2909 2926          /*
2910 2927           * What is read from the /proc files depends on the data
2911 2928           * model of the caller.  An LP64 process will see LP64
2912 2929           * data.  An ILP32 process will see ILP32 data.
2913 2930           */
2914 2931          if (curproc->p_model == DATAMODEL_LP64)
2915 2932                  return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2916 2933          else
2917 2934                  return (pr_read_function_32[pnp->pr_type](pnp, uiop, cr));
2918 2935  #else
2919 2936          return (pr_read_function[pnp->pr_type](pnp, uiop, cr));
2920 2937  #endif
2921 2938  }
2922 2939  
2923 2940  /*
2924 2941   * We make pr_write_psinfo_fname() somewhat simpler by asserting at compile
2925 2942   * time that PRFNSZ has the same definition as MAXCOMLEN.
2926 2943   */
2927 2944  #if PRFNSZ != MAXCOMLEN
2928 2945  #error PRFNSZ/MAXCOMLEN mismatch
2929 2946  #endif
2930 2947  
2931 2948  static int
2932 2949  pr_write_psinfo_fname(prnode_t *pnp, uio_t *uiop)
2933 2950  {
2934 2951          char fname[PRFNSZ];
2935 2952          int offset = offsetof(psinfo_t, pr_fname), error;
2936 2953  
2937 2954  #ifdef _SYSCALL32_IMPL
2938 2955          if (curproc->p_model != DATAMODEL_LP64)
2939 2956                  offset = offsetof(psinfo32_t, pr_fname);
2940 2957  #endif
2941 2958  
2942 2959          /*
2943 2960           * If this isn't a write to pr_fname (or if the size doesn't match
2944 2961           * PRFNSZ) return.
2945 2962           */
2946 2963          if (uiop->uio_offset != offset || uiop->uio_resid != PRFNSZ)
2947 2964                  return (0);
2948 2965  
2949 2966          if ((error = uiomove(fname, PRFNSZ, UIO_WRITE, uiop)) != 0)
2950 2967                  return (error);
2951 2968  
2952 2969          fname[PRFNSZ - 1] = '\0';
2953 2970  
2954 2971          if ((error = prlock(pnp, ZNO)) != 0)
2955 2972                  return (error);
2956 2973  
2957 2974          bcopy(fname, pnp->pr_common->prc_proc->p_user.u_comm, PRFNSZ);
2958 2975  
2959 2976          prunlock(pnp);
2960 2977  
2961 2978          return (0);
2962 2979  }
2963 2980  
2964 2981  /*
2965 2982   * We make pr_write_psinfo_psargs() somewhat simpler by asserting at compile
2966 2983   * time that PRARGSZ has the same definition as PSARGSZ.
2967 2984   */
2968 2985  #if PRARGSZ != PSARGSZ
2969 2986  #error PRARGSZ/PSARGSZ mismatch
2970 2987  #endif
2971 2988  
2972 2989  static int
2973 2990  pr_write_psinfo_psargs(prnode_t *pnp, uio_t *uiop)
2974 2991  {
2975 2992          char psargs[PRARGSZ];
2976 2993          int offset = offsetof(psinfo_t, pr_psargs), error;
2977 2994  
2978 2995  #ifdef _SYSCALL32_IMPL
2979 2996          if (curproc->p_model != DATAMODEL_LP64)
2980 2997                  offset = offsetof(psinfo32_t, pr_psargs);
2981 2998  #endif
2982 2999  
2983 3000          /*
2984 3001           * If this isn't a write to pr_psargs (or if the size doesn't match
2985 3002           * PRARGSZ) return.
2986 3003           */
2987 3004          if (uiop->uio_offset != offset || uiop->uio_resid != PRARGSZ)
2988 3005                  return (0);
2989 3006  
2990 3007          if ((error = uiomove(psargs, PRARGSZ, UIO_WRITE, uiop)) != 0)
2991 3008                  return (error);
2992 3009  
2993 3010          psargs[PRARGSZ - 1] = '\0';
2994 3011  
2995 3012          if ((error = prlock(pnp, ZNO)) != 0)
2996 3013                  return (error);
2997 3014  
2998 3015          bcopy(psargs, pnp->pr_common->prc_proc->p_user.u_psargs, PRARGSZ);
2999 3016  
3000 3017          prunlock(pnp);
3001 3018  
3002 3019          return (0);
3003 3020  }
3004 3021  
3005 3022  int
3006 3023  pr_write_psinfo(prnode_t *pnp, uio_t *uiop)
3007 3024  {
3008 3025          int error;
3009 3026  
3010 3027          if ((error = pr_write_psinfo_fname(pnp, uiop)) != 0)
3011 3028                  return (error);
3012 3029  
3013 3030          if ((error = pr_write_psinfo_psargs(pnp, uiop)) != 0)
3014 3031                  return (error);
3015 3032  
3016 3033          return (0);
3017 3034  }
3018 3035  
3019 3036  
3020 3037  /* Note we intentionally don't handle partial writes/updates. */
3021 3038  static int
3022 3039  pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
3023 3040  {
3024 3041          kthread_t *t = NULL;
3025 3042          char *lwpname;
3026 3043          int error;
3027 3044  
3028 3045          lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
3029 3046  
3030 3047          if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
3031 3048                  kmem_free(lwpname, THREAD_NAME_MAX);
3032 3049                  return (error);
3033 3050          }
3034 3051  
3035 3052          /* Somebody tried to write too long a thread name... */
3036 3053          if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
3037 3054                  kmem_free(lwpname, THREAD_NAME_MAX);
3038 3055                  return (EIO);
3039 3056          }
3040 3057  
3041 3058          VERIFY3U(lwpname[THREAD_NAME_MAX - 1], ==, '\0');
3042 3059  
3043 3060          for (size_t i = 0; lwpname[i] != '\0'; i++) {
3044 3061                  if (!ISPRINT(lwpname[i])) {
3045 3062                          kmem_free(lwpname, THREAD_NAME_MAX);
3046 3063                          return (EINVAL);
3047 3064                  }
3048 3065          }
3049 3066  
3050 3067          /* Equivalent of thread_setname(), but with the ZNO magic. */
3051 3068          if ((error = prlock(pnp, ZNO)) != 0) {
3052 3069                  kmem_free(lwpname, THREAD_NAME_MAX);
3053 3070                  return (error);
3054 3071          }
3055 3072  
3056 3073          t = pnp->pr_common->prc_thread;
3057 3074          if (t->t_name == NULL) {
3058 3075                  t->t_name = lwpname;
3059 3076          } else {
3060 3077                  (void) strlcpy(t->t_name, lwpname, THREAD_NAME_MAX);
3061 3078                  kmem_free(lwpname, THREAD_NAME_MAX);
3062 3079          }
3063 3080  
3064 3081          prunlock(pnp);
3065 3082          return (0);
3066 3083  }
3067 3084  
3068 3085  /* ARGSUSED */
3069 3086  static int
3070 3087  prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
3071 3088  {
3072 3089          prnode_t *pnp = VTOP(vp);
3073 3090          int old = 0;
3074 3091          int error;
3075 3092          ssize_t resid;
3076 3093  
3077 3094          ASSERT(pnp->pr_type < PR_NFILES);
3078 3095  
3079 3096          /*
3080 3097           * Only a handful of /proc files are writable, enumerate them here.
3081 3098           */
3082 3099          switch (pnp->pr_type) {
3083 3100          case PR_PIDDIR:         /* directory write()s: visceral revulsion. */
3084 3101                  ASSERT(pnp->pr_pidfile != NULL);
3085 3102                  /* use the underlying PR_PIDFILE to write the process */
3086 3103                  vp = pnp->pr_pidfile;
3087 3104                  pnp = VTOP(vp);
3088 3105                  ASSERT(pnp->pr_type == PR_PIDFILE);
3089 3106                  /* FALLTHROUGH */
3090 3107          case PR_PIDFILE:
3091 3108          case PR_LWPIDFILE:
3092 3109                  old = 1;
3093 3110                  /* FALLTHROUGH */
3094 3111          case PR_AS:
3095 3112                  if ((error = prlock(pnp, ZNO)) == 0) {
3096 3113                          proc_t *p = pnp->pr_common->prc_proc;
3097 3114                          struct as *as = p->p_as;
3098 3115  
3099 3116                          if ((p->p_flag & SSYS) || as == &kas) {
3100 3117                                  /*
3101 3118                                   * /proc I/O cannot be done to a system process.
3102 3119                                   */
3103 3120                                  error = EIO;
3104 3121  #ifdef _SYSCALL32_IMPL
3105 3122                          } else if (curproc->p_model == DATAMODEL_ILP32 &&
3106 3123                              PROCESS_NOT_32BIT(p)) {
3107 3124                                  error = EOVERFLOW;
3108 3125  #endif
3109 3126                          } else {
3110 3127                                  /*
3111 3128                                   * See comments above (pr_read_pidfile)
3112 3129                                   * about this locking dance.
3113 3130                                   */
3114 3131                                  mutex_exit(&p->p_lock);
3115 3132                                  error = prusrio(p, UIO_WRITE, uiop, old);
3116 3133                                  mutex_enter(&p->p_lock);
3117 3134                          }
3118 3135                          prunlock(pnp);
3119 3136                  }
3120 3137                  return (error);
3121 3138  
3122 3139          case PR_CTL:
3123 3140          case PR_LWPCTL:
3124 3141                  resid = uiop->uio_resid;
3125 3142                  /*
3126 3143                   * Perform the action on the control file
3127 3144                   * by passing curthreads credentials
3128 3145                   * and not target process's credentials.
3129 3146                   */
3130 3147  #ifdef _SYSCALL32_IMPL
3131 3148                  if (curproc->p_model == DATAMODEL_ILP32)
3132 3149                          error = prwritectl32(vp, uiop, CRED());
3133 3150                  else
3134 3151                          error = prwritectl(vp, uiop, CRED());
3135 3152  #else
3136 3153                  error = prwritectl(vp, uiop, CRED());
3137 3154  #endif
3138 3155                  /*
3139 3156                   * This hack makes sure that the EINTR is passed
3140 3157                   * all the way back to the caller's write() call.
3141 3158                   */
3142 3159                  if (error == EINTR)
3143 3160                          uiop->uio_resid = resid;
3144 3161                  return (error);
3145 3162  
3146 3163          case PR_PSINFO:
3147 3164                  return (pr_write_psinfo(pnp, uiop));
3148 3165  
3149 3166          case PR_LWPNAME:
3150 3167                  return (pr_write_lwpname(pnp, uiop));
3151 3168  
3152 3169          default:
3153 3170                  return ((vp->v_type == VDIR)? EISDIR : EBADF);
3154 3171          }
3155 3172          /* NOTREACHED */
3156 3173  }
3157 3174  
3158 3175  static int
3159 3176  prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
3160 3177      caller_context_t *ct)
3161 3178  {
3162 3179          prnode_t *pnp = VTOP(vp);
3163 3180          prnodetype_t type = pnp->pr_type;
3164 3181          prcommon_t *pcp;
3165 3182          proc_t *p;
3166 3183          struct as *as;
3167 3184          int error;
3168 3185          vnode_t *rvp;
3169 3186          timestruc_t now;
3170 3187          extern uint_t nproc;
3171 3188          int ngroups;
3172 3189          int nsig;
3173 3190  
3174 3191          /*
3175 3192           * This ugly bit of code allows us to keep both versions of this
3176 3193           * function from the same source.
3177 3194           */
3178 3195  #ifdef _LP64
3179 3196          int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
3180 3197  #define PR_OBJSIZE(obj32, obj64)        \
3181 3198          (iam32bit ? sizeof (obj32) : sizeof (obj64))
3182 3199  #define PR_OBJSPAN(obj32, obj64)        \
3183 3200          (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
3184 3201  #else
3185 3202  #define PR_OBJSIZE(obj32, obj64)        \
3186 3203          (sizeof (obj64))
3187 3204  #define PR_OBJSPAN(obj32, obj64)        \
3188 3205          (LSPAN(obj64))
3189 3206  #endif
3190 3207  
3191 3208          /*
3192 3209           * Return all the attributes.  Should be refined
3193 3210           * so that it returns only those asked for.
3194 3211           * Most of this is complete fakery anyway.
3195 3212           */
3196 3213  
3197 3214          /*
3198 3215           * For files in the /proc/<pid>/object directory,
3199 3216           * return the attributes of the underlying object.
3200 3217           * For files in the /proc/<pid>/fd directory,
3201 3218           * return the attributes of the underlying file, but
3202 3219           * make it look inaccessible if it is not a regular file.
3203 3220           * Make directories look like symlinks.
3204 3221           */
3205 3222          switch (type) {
3206 3223          case PR_CURDIR:
3207 3224          case PR_ROOTDIR:
3208 3225                  if (!(flags & ATTR_REAL))
3209 3226                          break;
3210 3227                  /* restrict full knowledge of the attributes to owner or root */
3211 3228                  if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
3212 3229                          return (error);
3213 3230                  /* FALLTHROUGH */
3214 3231          case PR_OBJECT:
3215 3232          case PR_FD:
3216 3233                  rvp = pnp->pr_realvp;
3217 3234                  error = VOP_GETATTR(rvp, vap, flags, cr, ct);
3218 3235                  if (error)
3219 3236                          return (error);
3220 3237                  if (type == PR_FD) {
3221 3238                          if (rvp->v_type != VREG && rvp->v_type != VDIR)
3222 3239                                  vap->va_mode = 0;
3223 3240                          else
3224 3241                                  vap->va_mode &= pnp->pr_mode;
3225 3242                  }
3226 3243                  if (type == PR_OBJECT)
3227 3244                          vap->va_mode &= 07555;
3228 3245                  if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
3229 3246                          vap->va_type = VLNK;
3230 3247                          vap->va_size = 0;
3231 3248                          vap->va_nlink = 1;
3232 3249                  }
3233 3250                  return (0);
3234 3251          default:
3235 3252                  break;
3236 3253          }
3237 3254  
3238 3255          bzero(vap, sizeof (*vap));
3239 3256          /*
3240 3257           * Large Files: Internally proc now uses VPROC to indicate
3241 3258           * a proc file. Since we have been returning VREG through
3242 3259           * VOP_GETATTR() until now, we continue to do this so as
3243 3260           * not to break apps depending on this return value.
3244 3261           */
3245 3262          vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
3246 3263          vap->va_mode = pnp->pr_mode;
3247 3264          vap->va_fsid = vp->v_vfsp->vfs_dev;
3248 3265          vap->va_blksize = DEV_BSIZE;
3249 3266          vap->va_rdev = 0;
3250 3267          vap->va_seq = 0;
3251 3268  
3252 3269          if (type == PR_PROCDIR) {
3253 3270                  vap->va_uid = 0;
3254 3271                  vap->va_gid = 0;
3255 3272                  vap->va_nlink = nproc + 2;
3256 3273                  vap->va_nodeid = (ino64_t)PRROOTINO;
3257 3274                  gethrestime(&now);
3258 3275                  vap->va_atime = vap->va_mtime = vap->va_ctime = now;
3259 3276                  vap->va_size = (v.v_proc + 2) * PRSDSIZE;
3260 3277                  vap->va_nblocks = btod(vap->va_size);
3261 3278                  return (0);
3262 3279          }
3263 3280  
3264 3281          /*
3265 3282           * /proc/<pid>/self is a symbolic link, and has no prcommon member
3266 3283           */
3267 3284          if (type == PR_SELF) {
3268 3285                  vap->va_uid = crgetruid(CRED());
3269 3286                  vap->va_gid = crgetrgid(CRED());
3270 3287                  vap->va_nodeid = (ino64_t)PR_SELF;
3271 3288                  gethrestime(&now);
3272 3289                  vap->va_atime = vap->va_mtime = vap->va_ctime = now;
3273 3290                  vap->va_nlink = 1;
3274 3291                  vap->va_type = VLNK;
3275 3292                  vap->va_size = 0;
3276 3293                  return (0);
3277 3294          }
3278 3295  
3279 3296          /* A subset of prlock(pnp...) */
3280 3297          p = pr_p_lock(pnp);
3281 3298          mutex_exit(&pr_pidlock);
3282 3299          if (p == NULL)
3283 3300                  return (ENOENT);
3284 3301          pcp = pnp->pr_common;
3285 3302  
3286 3303          /*
3287 3304           * Because we're performing a subset of prlock() inline here, we must
3288 3305           * follow prlock's semantics when encountering a zombie process
3289 3306           * (PRC_DESTROY flag is set) or an exiting process (SEXITING flag is
3290 3307           * set). Those semantics indicate acting as if the process is no
3291 3308           * longer there (return ENOENT).
3292 3309           *
3293 3310           * If we chose to proceed here regardless, we may encounter issues
3294 3311           * when we drop the p_lock (see PR_OBJECTDIR, PR_PATHDIR, PR_*MAP,
3295 3312           * PR_LDT, and PR_*PAGEDATA below). A process-cleanup which was
3296 3313           * blocked on p_lock may ignore the P_PR_LOCK flag we set above, since
3297 3314           * it set one of PRC_DESTROY or SEXITING. If the process then gets
3298 3315           * destroyed our "p" will be useless, as will its p_lock.
3299 3316           *
3300 3317           * It may be desirable to move this check to only places further down
3301 3318           * prior to actual droppages of p->p_lock, but for now, we're playing
3302 3319           * it safe and checking here immediately, like prlock() does..
3303 3320           */
3304 3321          if (((pcp->prc_flags & PRC_DESTROY) || (p->p_flag & SEXITING))) {
3305 3322                  prunlock(pnp);
3306 3323                  return (ENOENT);
3307 3324          }
3308 3325  
3309 3326          mutex_enter(&p->p_crlock);
3310 3327          vap->va_uid = crgetruid(p->p_cred);
3311 3328          vap->va_gid = crgetrgid(p->p_cred);
3312 3329          mutex_exit(&p->p_crlock);
3313 3330  
3314 3331          vap->va_nlink = 1;
3315 3332          vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
3316 3333              pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
3317 3334          if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
3318 3335                  vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
3319 3336                      vap->va_ctime.tv_sec =
3320 3337                      p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
3321 3338                  vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
3322 3339                      vap->va_ctime.tv_nsec = 0;
3323 3340          } else {
3324 3341                  user_t *up = PTOU(p);
3325 3342                  vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
3326 3343                      vap->va_ctime.tv_sec = up->u_start.tv_sec;
3327 3344                  vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
3328 3345                      vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
3329 3346          }
3330 3347  
3331 3348          switch (type) {
3332 3349          case PR_PIDDIR:
3333 3350                  /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
3334 3351                  vap->va_nlink = 5;
3335 3352                  vap->va_size = sizeof (piddir);
3336 3353                  break;
3337 3354          case PR_OBJECTDIR:
3338 3355                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3339 3356                          vap->va_size = 2 * PRSDSIZE;
3340 3357                  else {
3341 3358                          mutex_exit(&p->p_lock);
3342 3359                          AS_LOCK_ENTER(as, RW_WRITER);
3343 3360                          if (as->a_updatedir)
3344 3361                                  rebuild_objdir(as);
3345 3362                          vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
3346 3363                          AS_LOCK_EXIT(as);
3347 3364                          mutex_enter(&p->p_lock);
3348 3365                  }
3349 3366                  vap->va_nlink = 2;
3350 3367                  break;
3351 3368          case PR_PATHDIR:
3352 3369                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3353 3370                          vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
3354 3371                  else {
3355 3372                          mutex_exit(&p->p_lock);
3356 3373                          AS_LOCK_ENTER(as, RW_WRITER);
3357 3374                          if (as->a_updatedir)
3358 3375                                  rebuild_objdir(as);
3359 3376                          vap->va_size = (as->a_sizedir + 4 +
3360 3377                              P_FINFO(p)->fi_nfiles) * PRSDSIZE;
3361 3378                          AS_LOCK_EXIT(as);
3362 3379                          mutex_enter(&p->p_lock);
3363 3380                  }
3364 3381                  vap->va_nlink = 2;
3365 3382                  break;
3366 3383          case PR_PATH:
3367 3384          case PR_CURDIR:
3368 3385          case PR_ROOTDIR:
3369 3386          case PR_CT:
3370 3387                  vap->va_type = VLNK;
3371 3388                  vap->va_size = 0;
3372 3389                  break;
3373 3390          case PR_FDDIR:
3374 3391          case PR_FDINFODIR:
3375 3392                  vap->va_nlink = 2;
3376 3393                  vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
3377 3394                  break;
3378 3395          case PR_FDINFO: {
3379 3396                  file_t *fp;
3380 3397                  int fd = pnp->pr_index;
3381 3398  
3382 3399                  fp = pr_getf(p, fd, NULL);
3383 3400                  if (fp == NULL) {
3384 3401                          prunlock(pnp);
3385 3402                          return (ENOENT);
3386 3403                  }
3387 3404                  prunlock(pnp);
3388 3405                  vap->va_size = prgetfdinfosize(p, fp->f_vnode, cr);
3389 3406                  vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3390 3407                  pr_releasef(fp);
3391 3408                  return (0);
3392 3409          }
3393 3410          case PR_LWPDIR:
3394 3411                  /*
3395 3412                   * va_nlink: count each lwp as a directory link.
3396 3413                   * va_size: size of p_lwpdir + 2
3397 3414                   */
3398 3415                  vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
3399 3416                  vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
3400 3417                  break;
3401 3418          case PR_LWPIDDIR:
3402 3419                  vap->va_nlink = 2;
3403 3420                  vap->va_size = sizeof (lwpiddir);
3404 3421                  break;
3405 3422          case PR_CTDIR:
3406 3423                  vap->va_nlink = 2;
3407 3424                  vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
3408 3425                  break;
3409 3426          case PR_TMPLDIR:
3410 3427                  vap->va_nlink = 2;
3411 3428                  vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
3412 3429                  break;
3413 3430          case PR_AS:
3414 3431          case PR_PIDFILE:
3415 3432          case PR_LWPIDFILE:
3416 3433                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3417 3434                          vap->va_size = 0;
3418 3435                  else
3419 3436                          vap->va_size = as->a_resvsize;
3420 3437                  break;
3421 3438          case PR_STATUS:
3422 3439                  vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
3423 3440                  break;
3424 3441          case PR_LSTATUS:
3425 3442                  vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3426 3443                      p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
3427 3444                  break;
3428 3445          case PR_PSINFO:
3429 3446                  vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3430 3447                  break;
3431 3448          case PR_LPSINFO:
3432 3449                  vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3433 3450                      (p->p_lwpcnt + p->p_zombcnt) *
3434 3451                      PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
3435 3452                  break;
3436 3453          case PR_MAP:
3437 3454          case PR_RMAP:
3438 3455          case PR_XMAP:
3439 3456                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3440 3457                          vap->va_size = 0;
3441 3458                  else {
3442 3459                          mutex_exit(&p->p_lock);
3443 3460                          AS_LOCK_ENTER(as, RW_WRITER);
3444 3461                          if (type == PR_MAP)
3445 3462                                  vap->va_mtime = as->a_updatetime;
3446 3463                          if (type == PR_XMAP)
3447 3464                                  vap->va_size = prnsegs(as, 0) *
3448 3465                                      PR_OBJSIZE(prxmap32_t, prxmap_t);
3449 3466                          else
3450 3467                                  vap->va_size = prnsegs(as, type == PR_RMAP) *
3451 3468                                      PR_OBJSIZE(prmap32_t, prmap_t);
3452 3469                          AS_LOCK_EXIT(as);
3453 3470                          mutex_enter(&p->p_lock);
3454 3471                  }
3455 3472                  break;
3456 3473          case PR_CRED:
3457 3474                  mutex_enter(&p->p_crlock);
3458 3475                  vap->va_size = sizeof (prcred_t);
3459 3476                  ngroups = crgetngroups(p->p_cred);
3460 3477                  if (ngroups > 1)
3461 3478                          vap->va_size += (ngroups - 1) * sizeof (gid_t);
3462 3479                  mutex_exit(&p->p_crlock);
3463 3480                  break;
3464 3481          case PR_PRIV:
3465 3482                  vap->va_size = prgetprivsize();
3466 3483                  break;
3467 3484          case PR_SECFLAGS:
3468 3485                  vap->va_size = sizeof (prsecflags_t);
3469 3486                  break;
3470 3487          case PR_SIGACT:
3471 3488                  nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3472 3489                  vap->va_size = (nsig-1) *
3473 3490                      PR_OBJSIZE(struct sigaction32, struct sigaction);
3474 3491                  break;
3475 3492          case PR_AUXV:
3476 3493                  vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3477 3494                  break;
3478 3495          case PR_ARGV:
3479 3496                  if ((p->p_flag & SSYS) || p->p_as == &kas) {
3480 3497                          vap->va_size = PSARGSZ;
3481 3498                  } else {
3482 3499                          vap->va_size = PRMAXARGVLEN;
3483 3500                  }
3484 3501                  break;
3485 3502  #if defined(__x86)
3486 3503          case PR_LDT:
3487 3504                  mutex_exit(&p->p_lock);
3488 3505                  mutex_enter(&p->p_ldtlock);
3489 3506                  vap->va_size = prnldt(p) * sizeof (struct ssd);
3490 3507                  mutex_exit(&p->p_ldtlock);
3491 3508                  mutex_enter(&p->p_lock);
3492 3509                  break;
3493 3510  #endif
3494 3511          case PR_USAGE:
3495 3512                  vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3496 3513                  break;
3497 3514          case PR_LUSAGE:
3498 3515                  vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3499 3516                      (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3500 3517                  break;
3501 3518          case PR_PAGEDATA:
3502 3519                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3503 3520                          vap->va_size = 0;
3504 3521                  else {
3505 3522                          /*
3506 3523                           * We can drop p->p_lock before grabbing the
3507 3524                           * address space lock because p->p_as will not
3508 3525                           * change while the process is marked P_PR_LOCK.
3509 3526                           */
3510 3527                          mutex_exit(&p->p_lock);
3511 3528                          AS_LOCK_ENTER(as, RW_WRITER);
3512 3529  #ifdef _LP64
3513 3530                          vap->va_size = iam32bit?
3514 3531                              prpdsize32(as) : prpdsize(as);
3515 3532  #else
3516 3533                          vap->va_size = prpdsize(as);
3517 3534  #endif
3518 3535                          AS_LOCK_EXIT(as);
3519 3536                          mutex_enter(&p->p_lock);
3520 3537                  }
3521 3538                  break;
3522 3539          case PR_OPAGEDATA:
3523 3540                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3524 3541                          vap->va_size = 0;
3525 3542                  else {
3526 3543                          mutex_exit(&p->p_lock);
3527 3544                          AS_LOCK_ENTER(as, RW_WRITER);
3528 3545  #ifdef _LP64
3529 3546                          vap->va_size = iam32bit?
3530 3547                              oprpdsize32(as) : oprpdsize(as);
3531 3548  #else
3532 3549                          vap->va_size = oprpdsize(as);
3533 3550  #endif
3534 3551                          AS_LOCK_EXIT(as);
3535 3552                          mutex_enter(&p->p_lock);
3536 3553                  }
3537 3554                  break;
3538 3555          case PR_WATCH:
3539 3556                  vap->va_size = avl_numnodes(&p->p_warea) *
3540 3557                      PR_OBJSIZE(prwatch32_t, prwatch_t);
3541 3558                  break;
3542 3559          case PR_LWPSTATUS:
3543 3560                  vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
3544 3561                  break;
3545 3562          case PR_LWPSINFO:
3546 3563                  vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
3547 3564                  break;
3548 3565          case PR_LWPUSAGE:
3549 3566                  vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3550 3567                  break;
3551 3568          case PR_XREGS:
3552 3569                  if (prhasx(p))
3553 3570                          vap->va_size = prgetprxregsize(p);
3554 3571                  else
3555 3572                          vap->va_size = 0;
3556 3573                  break;
3557 3574          case PR_SPYMASTER:
3558 3575                  if (pnp->pr_common->prc_thread != NULL &&
3559 3576                      pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3560 3577                          vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3561 3578                  } else {
3562 3579                          vap->va_size = 0;
3563 3580                  }
3564 3581                  break;
3565 3582  #if defined(__sparc)
3566 3583          case PR_GWINDOWS:
3567 3584          {
3568 3585                  kthread_t *t;
3569 3586                  int n;
3570 3587  
3571 3588                  /*
3572 3589                   * If there is no lwp then just make the size zero.
3573 3590                   * This can happen if the lwp exits between the VOP_LOOKUP()
3574 3591                   * of the /proc/<pid>/lwp/<lwpid>/gwindows file and the
3575 3592                   * VOP_GETATTR() of the resulting vnode.
3576 3593                   */
3577 3594                  if ((t = pcp->prc_thread) == NULL) {
3578 3595                          vap->va_size = 0;
3579 3596                          break;
3580 3597                  }
3581 3598                  /*
3582 3599                   * Drop p->p_lock while touching the stack.
3583 3600                   * The P_PR_LOCK flag prevents the lwp from
3584 3601                   * disappearing while we do this.
3585 3602                   */
3586 3603                  mutex_exit(&p->p_lock);
3587 3604                  if ((n = prnwindows(ttolwp(t))) == 0)
3588 3605                          vap->va_size = 0;
3589 3606                  else
3590 3607                          vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
3591 3608                              (SPARC_MAXREGWINDOW - n) *
3592 3609                              PR_OBJSIZE(struct rwindow32, struct rwindow);
3593 3610                  mutex_enter(&p->p_lock);
3594 3611                  break;
3595 3612          }
3596 3613          case PR_ASRS:
3597 3614  #ifdef _LP64
3598 3615                  if (p->p_model == DATAMODEL_LP64)
3599 3616                          vap->va_size = sizeof (asrset_t);
3600 3617                  else
3601 3618  #endif
3602 3619                          vap->va_size = 0;
3603 3620                  break;
3604 3621  #endif
3605 3622          case PR_CTL:
3606 3623          case PR_LWPCTL:
3607 3624          case PR_CMDLINE:
3608 3625          default:
3609 3626                  vap->va_size = 0;
3610 3627                  break;
3611 3628          }
3612 3629  
3613 3630          prunlock(pnp);
3614 3631          vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3615 3632          return (0);
3616 3633  }
3617 3634  
3618 3635  static int
3619 3636  praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3620 3637  {
3621 3638          prnode_t *pnp = VTOP(vp);
3622 3639          prnodetype_t type = pnp->pr_type;
3623 3640          int vmode;
3624 3641          vtype_t vtype;
3625 3642          proc_t *p;
3626 3643          int error = 0;
3627 3644          vnode_t *rvp;
3628 3645          vnode_t *xvp;
3629 3646  
3630 3647          if ((mode & VWRITE) && vn_is_readonly(vp))
3631 3648                  return (EROFS);
3632 3649  
3633 3650          switch (type) {
3634 3651          case PR_PROCDIR:
3635 3652                  break;
3636 3653  
3637 3654          case PR_OBJECT:
3638 3655          case PR_FD:
3639 3656                  /*
3640 3657                   * Disallow write access to the underlying objects.
3641 3658                   * Disallow access to underlying non-regular-file fds.
3642 3659                   * Disallow access to fds with other than existing open modes.
3643 3660                   */
3644 3661                  rvp = pnp->pr_realvp;
3645 3662                  vtype = rvp->v_type;
3646 3663                  vmode = pnp->pr_mode;
3647 3664                  if ((type == PR_OBJECT && (mode & VWRITE)) ||
3648 3665                      (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3649 3666                      (type == PR_FD && (vmode & mode) != mode &&
3650 3667                      secpolicy_proc_access(cr) != 0))
3651 3668                          return (EACCES);
3652 3669                  return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3653 3670  
3654 3671          case PR_PSINFO:         /* these files can be read by anyone */
3655 3672          case PR_LPSINFO:
3656 3673          case PR_LWPSINFO:
3657 3674          case PR_LWPDIR:
3658 3675          case PR_LWPIDDIR:
3659 3676          case PR_USAGE:
3660 3677          case PR_LUSAGE:
3661 3678          case PR_LWPUSAGE:
3662 3679          case PR_ARGV:
3663 3680          case PR_CMDLINE:
3664 3681                  p = pr_p_lock(pnp);
3665 3682                  mutex_exit(&pr_pidlock);
3666 3683                  if (p == NULL)
3667 3684                          return (ENOENT);
3668 3685                  prunlock(pnp);
3669 3686                  break;
3670 3687  
3671 3688          default:
3672 3689                  /*
3673 3690                   * Except for the world-readable files above,
3674 3691                   * only /proc/pid exists if the process is a zombie.
3675 3692                   */
3676 3693                  if ((error = prlock(pnp,
3677 3694                      (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3678 3695                          return (error);
3679 3696                  p = pnp->pr_common->prc_proc;
3680 3697                  if (p != curproc)
3681 3698                          error = priv_proc_cred_perm(cr, p, NULL, mode);
3682 3699  
3683 3700                  if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3684 3701                      p->p_as == &kas || (xvp = p->p_exec) == NULL) {
3685 3702                          prunlock(pnp);
3686 3703                  } else {
3687 3704                          /*
3688 3705                           * Determine if the process's executable is readable.
3689 3706                           * We have to drop p->p_lock before the secpolicy
3690 3707                           * and VOP operation.
3691 3708                           */
3692 3709                          VN_HOLD(xvp);
3693 3710                          prunlock(pnp);
3694 3711                          if (secpolicy_proc_access(cr) != 0)
3695 3712                                  error = VOP_ACCESS(xvp, VREAD, 0, cr, ct);
3696 3713                          VN_RELE(xvp);
3697 3714                  }
3698 3715                  if (error)
3699 3716                          return (error);
3700 3717                  break;
3701 3718          }
3702 3719  
3703 3720          if (type == PR_CURDIR || type == PR_ROOTDIR) {
3704 3721                  /*
3705 3722                   * Final access check on the underlying directory vnode.
3706 3723                   */
3707 3724                  return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
3708 3725          }
3709 3726  
3710 3727          /*
3711 3728           * Visceral revulsion:  For compatibility with old /proc,
3712 3729           * allow the /proc/<pid> directory to be opened for writing.
3713 3730           */
3714 3731          vmode = pnp->pr_mode;
3715 3732          if (type == PR_PIDDIR)
3716 3733                  vmode |= VWRITE;
3717 3734          if ((vmode & mode) != mode)
3718 3735                  error = secpolicy_proc_access(cr);
3719 3736          return (error);
3720 3737  }
3721 3738  
3722 3739  /*
3723 3740   * Array of lookup functions, indexed by /proc file type.
3724 3741   */
3725 3742  static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3726 3743          *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3727 3744          *pr_lookup_fddir(), *pr_lookup_fdinfodir(), *pr_lookup_pathdir(),
3728 3745          *pr_lookup_tmpldir(), *pr_lookup_ctdir();
3729 3746  
3730 3747  static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3731 3748          pr_lookup_procdir,      /* /proc                                */
3732 3749          pr_lookup_notdir,       /* /proc/self                           */
3733 3750          pr_lookup_piddir,       /* /proc/<pid>                          */
3734 3751          pr_lookup_notdir,       /* /proc/<pid>/as                       */
3735 3752          pr_lookup_notdir,       /* /proc/<pid>/ctl                      */
3736 3753          pr_lookup_notdir,       /* /proc/<pid>/status                   */
3737 3754          pr_lookup_notdir,       /* /proc/<pid>/lstatus                  */
3738 3755          pr_lookup_notdir,       /* /proc/<pid>/psinfo                   */
3739 3756          pr_lookup_notdir,       /* /proc/<pid>/lpsinfo                  */
3740 3757          pr_lookup_notdir,       /* /proc/<pid>/map                      */
3741 3758          pr_lookup_notdir,       /* /proc/<pid>/rmap                     */
3742 3759          pr_lookup_notdir,       /* /proc/<pid>/xmap                     */
3743 3760          pr_lookup_notdir,       /* /proc/<pid>/cred                     */
3744 3761          pr_lookup_notdir,       /* /proc/<pid>/sigact                   */
3745 3762          pr_lookup_notdir,       /* /proc/<pid>/auxv                     */
3746 3763  #if defined(__x86)
3747 3764          pr_lookup_notdir,       /* /proc/<pid>/ldt                      */
3748 3765  #endif
3749 3766          pr_lookup_notdir,       /* /proc/<pid>/argv                     */
3750 3767          pr_lookup_notdir,       /* /proc/<pid>/cmdline                  */
3751 3768          pr_lookup_notdir,       /* /proc/<pid>/usage                    */
3752 3769          pr_lookup_notdir,       /* /proc/<pid>/lusage                   */
3753 3770          pr_lookup_notdir,       /* /proc/<pid>/pagedata                 */
3754 3771          pr_lookup_notdir,       /* /proc/<pid>/watch                    */
3755 3772          pr_lookup_notdir,       /* /proc/<pid>/cwd                      */
3756 3773          pr_lookup_notdir,       /* /proc/<pid>/root                     */
3757 3774          pr_lookup_fddir,        /* /proc/<pid>/fd                       */
3758 3775          pr_lookup_notdir,       /* /proc/<pid>/fd/nn                    */
3759 3776          pr_lookup_fdinfodir,    /* /proc/<pid>/fdinfo                   */
3760 3777          pr_lookup_notdir,       /* /proc/<pid>/fdinfo/nn                */
3761 3778          pr_lookup_objectdir,    /* /proc/<pid>/object                   */
3762 3779          pr_lookup_notdir,       /* /proc/<pid>/object/xxx               */
3763 3780          pr_lookup_lwpdir,       /* /proc/<pid>/lwp                      */
3764 3781          pr_lookup_lwpiddir,     /* /proc/<pid>/lwp/<lwpid>              */
3765 3782          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
3766 3783          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpname      */
3767 3784          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
3768 3785          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
3769 3786          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
3770 3787          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/xregs        */
3771 3788          pr_lookup_tmpldir,      /* /proc/<pid>/lwp/<lwpid>/templates    */
3772 3789          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3773 3790          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/spymaster    */
3774 3791  #if defined(__sparc)
3775 3792          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/gwindows     */
3776 3793          pr_lookup_notdir,       /* /proc/<pid>/lwp/<lwpid>/asrs         */
3777 3794  #endif
3778 3795          pr_lookup_notdir,       /* /proc/<pid>/priv                     */
3779 3796          pr_lookup_pathdir,      /* /proc/<pid>/path                     */
3780 3797          pr_lookup_notdir,       /* /proc/<pid>/path/xxx                 */
3781 3798          pr_lookup_ctdir,        /* /proc/<pid>/contracts                */
3782 3799          pr_lookup_notdir,       /* /proc/<pid>/contracts/<ctid>         */
3783 3800          pr_lookup_notdir,       /* /proc/<pid>/secflags                 */
3784 3801          pr_lookup_notdir,       /* old process file                     */
3785 3802          pr_lookup_notdir,       /* old lwp file                         */
3786 3803          pr_lookup_notdir,       /* old pagedata file                    */
3787 3804  };
3788 3805  
3789 3806  static int
3790 3807  prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3791 3808      int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3792 3809      int *direntflags, pathname_t *realpnp)
3793 3810  {
3794 3811          prnode_t *pnp = VTOP(dp);
3795 3812          prnodetype_t type = pnp->pr_type;
3796 3813          int error;
3797 3814  
3798 3815          ASSERT(dp->v_type == VDIR);
3799 3816          ASSERT(type < PR_NFILES);
3800 3817  
3801 3818          if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
3802 3819                  VN_HOLD(pnp->pr_parent);
3803 3820                  *vpp = pnp->pr_parent;
3804 3821                  return (0);
3805 3822          }
3806 3823  
3807 3824          if (*comp == '\0' ||
3808 3825              strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
3809 3826                  VN_HOLD(dp);
3810 3827                  *vpp = dp;
3811 3828                  return (0);
3812 3829          }
3813 3830  
3814 3831          switch (type) {
3815 3832          case PR_CURDIR:
3816 3833          case PR_ROOTDIR:
3817 3834                  /* restrict lookup permission to owner or root */
3818 3835                  if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3819 3836                          return (error);
3820 3837                  /* FALLTHROUGH */
3821 3838          case PR_FD:
3822 3839                  /*
3823 3840                   * Performing a VOP_LOOKUP on the underlying vnode and emitting
3824 3841                   * the resulting vnode, without encapsulation, as our own is a
3825 3842                   * very special case when it comes to the assumptions built
3826 3843                   * into VFS.
3827 3844                   *
3828 3845                   * Since the resulting vnode is highly likely to be at some
3829 3846                   * abitrary position in another filesystem, we insist that the
3830 3847                   * VTRAVERSE flag is set on the parent.  This prevents things
3831 3848                   * such as the v_path freshness logic from mistaking the
3832 3849                   * resulting vnode as a "real" child of the parent, rather than
3833 3850                   * a consequence of this "procfs wormhole".
3834 3851                   *
3835 3852                   * Failure to establish such protections can lead to
3836 3853                   * incorrectly calculated v_paths being set on nodes reached
3837 3854                   * through these lookups.
3838 3855                   */
3839 3856                  ASSERT((dp->v_flag & VTRAVERSE) != 0);
3840 3857  
3841 3858                  dp = pnp->pr_realvp;
3842 3859                  return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3843 3860                      direntflags, realpnp));
3844 3861          default:
3845 3862                  break;
3846 3863          }
3847 3864  
3848 3865          if ((type == PR_OBJECTDIR || type == PR_FDDIR ||
3849 3866              type == PR_FDINFODIR || type == PR_PATHDIR) &&
3850 3867              (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3851 3868                  return (error);
3852 3869  
3853 3870          /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3854 3871          *vpp = (pr_lookup_function[type](dp, comp));
3855 3872  
3856 3873          return ((*vpp == NULL) ? ENOENT : 0);
3857 3874  }
3858 3875  
3859 3876  /* ARGSUSED */
3860 3877  static int
3861 3878  prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3862 3879      int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3863 3880      vsecattr_t *vsecp)
3864 3881  {
3865 3882          int error;
3866 3883  
3867 3884          if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3868 3885              ct, NULL, NULL)) != 0) {
3869 3886                  if (error == ENOENT) {
3870 3887                          /* One can't O_CREAT nonexistent files in /proc. */
3871 3888                          error = EACCES;
3872 3889                  }
3873 3890                  return (error);
3874 3891          }
3875 3892  
3876 3893          if (excl == EXCL) {
3877 3894                  /* Disallow the O_EXCL case */
3878 3895                  error = EEXIST;
3879 3896          } else if ((error = praccess(*vpp, mode, 0, cr, ct)) == 0) {
3880 3897                  /* Before proceeding, handle O_TRUNC if necessary. */
3881 3898                  if (vap->va_mask & AT_SIZE) {
3882 3899                          vnode_t *vp = *vpp;
3883 3900  
3884 3901                          if (vp->v_type == VDIR) {
3885 3902                                  /* Only allow O_TRUNC on files */
3886 3903                                  error = EISDIR;
3887 3904                          } else if (vp->v_type != VPROC ||
3888 3905                              VTOP(vp)->pr_type != PR_FD) {
3889 3906                                  /*
3890 3907                                   * Disallow for files outside of the
3891 3908                                   * /proc/<pid>/fd/<n> entries
3892 3909                                   */
3893 3910                                  error = EACCES;
3894 3911                          } else {
3895 3912                                  uint_t mask;
3896 3913  
3897 3914                                  vp = VTOP(vp)->pr_realvp;
3898 3915                                  mask = vap->va_mask;
3899 3916                                  vap->va_mask = AT_SIZE;
3900 3917                                  error = VOP_SETATTR(vp, vap, 0, cr, ct);
3901 3918                                  vap->va_mask = mask;
3902 3919                          }
3903 3920                  }
3904 3921          }
3905 3922  
3906 3923          if (error) {
3907 3924                  VN_RELE(*vpp);
3908 3925                  *vpp = NULL;
3909 3926          }
3910 3927          return (error);
3911 3928  }
3912 3929  
3913 3930  /* ARGSUSED */
3914 3931  static vnode_t *
3915 3932  pr_lookup_notdir(vnode_t *dp, char *comp)
3916 3933  {
3917 3934          return (NULL);
3918 3935  }
3919 3936  
3920 3937  /*
3921 3938   * Find or construct a process vnode for the given pid.
3922 3939   */
3923 3940  static vnode_t *
3924 3941  pr_lookup_procdir(vnode_t *dp, char *comp)
3925 3942  {
3926 3943          pid_t pid;
3927 3944          prnode_t *pnp;
3928 3945          prcommon_t *pcp;
3929 3946          vnode_t *vp;
3930 3947          proc_t *p;
3931 3948          int c;
3932 3949  
3933 3950          ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
3934 3951  
3935 3952          if (strcmp(comp, "self") == 0) {
3936 3953                  pnp = prgetnode(dp, PR_SELF);
3937 3954                  return (PTOV(pnp));
3938 3955          } else {
3939 3956                  pid = 0;
3940 3957                  while ((c = *comp++) != '\0') {
3941 3958                          if (c < '0' || c > '9')
3942 3959                                  return (NULL);
3943 3960                          pid = 10*pid + c - '0';
3944 3961                          if (pid > maxpid)
3945 3962                                  return (NULL);
3946 3963                  }
3947 3964          }
3948 3965  
3949 3966          pnp = prgetnode(dp, PR_PIDDIR);
3950 3967  
3951 3968          mutex_enter(&pidlock);
3952 3969          if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
3953 3970                  mutex_exit(&pidlock);
3954 3971                  prfreenode(pnp);
3955 3972                  return (NULL);
3956 3973          }
3957 3974          ASSERT(p->p_stat != 0);
3958 3975  
3959 3976          /* NOTE: we're holding pidlock across the policy call. */
3960 3977          if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3961 3978                  mutex_exit(&pidlock);
3962 3979                  prfreenode(pnp);
3963 3980                  return (NULL);
3964 3981          }
3965 3982  
3966 3983          mutex_enter(&p->p_lock);
3967 3984          mutex_exit(&pidlock);
3968 3985  
3969 3986          /*
3970 3987           * If a process vnode already exists and it is not invalid
3971 3988           * and it was created by the current process and it belongs
3972 3989           * to the same /proc mount point as our parent vnode, then
3973 3990           * just use it and discard the newly-allocated prnode.
3974 3991           */
3975 3992          for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3976 3993                  if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
3977 3994                      VTOP(vp)->pr_owner == curproc &&
3978 3995                      vp->v_vfsp == dp->v_vfsp) {
3979 3996                          ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
3980 3997                          VN_HOLD(vp);
3981 3998                          prfreenode(pnp);
3982 3999                          mutex_exit(&p->p_lock);
3983 4000                          return (vp);
3984 4001                  }
3985 4002          }
3986 4003          pnp->pr_owner = curproc;
3987 4004  
3988 4005          /*
3989 4006           * prgetnode() initialized most of the prnode.
3990 4007           * Finish the job.
3991 4008           */
3992 4009          pcp = pnp->pr_common;   /* the newly-allocated prcommon struct */
3993 4010          if ((vp = p->p_trace) != NULL) {
3994 4011                  /* discard the new prcommon and use the existing prcommon */
3995 4012                  prfreecommon(pcp);
3996 4013                  pcp = VTOP(vp)->pr_common;
3997 4014                  mutex_enter(&pcp->prc_mutex);
3998 4015                  ASSERT(pcp->prc_refcnt > 0);
3999 4016                  pcp->prc_refcnt++;
4000 4017                  mutex_exit(&pcp->prc_mutex);
4001 4018                  pnp->pr_common = pcp;
4002 4019          } else {
4003 4020                  /* initialize the new prcommon struct */
4004 4021                  if ((p->p_flag & SSYS) || p->p_as == &kas)
4005 4022                          pcp->prc_flags |= PRC_SYS;
4006 4023                  if (p->p_stat == SZOMB || (p->p_flag & SEXITING) != 0)
4007 4024                          pcp->prc_flags |= PRC_DESTROY;
4008 4025                  pcp->prc_proc = p;
4009 4026                  pcp->prc_datamodel = p->p_model;
4010 4027                  pcp->prc_pid = p->p_pid;
4011 4028                  pcp->prc_slot = p->p_slot;
4012 4029          }
4013 4030          pnp->pr_pcommon = pcp;
4014 4031          pnp->pr_parent = dp;
4015 4032          VN_HOLD(dp);
4016 4033          /*
4017 4034           * Link in the old, invalid directory vnode so we
4018 4035           * can later determine the last close of the file.
4019 4036           */
4020 4037          pnp->pr_next = p->p_trace;
4021 4038          p->p_trace = dp = PTOV(pnp);
4022 4039  
4023 4040          /*
4024 4041           * Kludge for old /proc: initialize the PR_PIDFILE as well.
4025 4042           */
4026 4043          vp = pnp->pr_pidfile;
4027 4044          pnp = VTOP(vp);
4028 4045          pnp->pr_ino = ptoi(pcp->prc_pid);
4029 4046          pnp->pr_common = pcp;
4030 4047          pnp->pr_pcommon = pcp;
4031 4048          pnp->pr_parent = dp;
4032 4049          pnp->pr_next = p->p_plist;
4033 4050          p->p_plist = vp;
4034 4051  
4035 4052          mutex_exit(&p->p_lock);
4036 4053          return (dp);
4037 4054  }
4038 4055  
4039 4056  static vnode_t *
4040 4057  pr_lookup_piddir(vnode_t *dp, char *comp)
4041 4058  {
4042 4059          prnode_t *dpnp = VTOP(dp);
4043 4060          vnode_t *vp;
4044 4061          prnode_t *pnp;
4045 4062          proc_t *p;
4046 4063          user_t *up;
4047 4064          prdirent_t *dirp;
4048 4065          int i;
4049 4066          enum prnodetype type;
4050 4067  
4051 4068          ASSERT(dpnp->pr_type == PR_PIDDIR);
4052 4069  
4053 4070          for (i = 0; i < NPIDDIRFILES; i++) {
4054 4071                  /* Skip "." and ".." */
4055 4072                  dirp = &piddir[i+2];
4056 4073                  if (strcmp(comp, dirp->d_name) == 0)
4057 4074                          break;
4058 4075          }
4059 4076  
4060 4077          if (i >= NPIDDIRFILES)
4061 4078                  return (NULL);
4062 4079  
4063 4080          type = (int)dirp->d_ino;
4064 4081          pnp = prgetnode(dp, type);
4065 4082  
4066 4083          p = pr_p_lock(dpnp);
4067 4084          mutex_exit(&pr_pidlock);
4068 4085          if (p == NULL) {
4069 4086                  prfreenode(pnp);
4070 4087                  return (NULL);
4071 4088          }
4072 4089          if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
4073 4090                  switch (type) {
4074 4091                  case PR_PSINFO:
4075 4092                  case PR_USAGE:
4076 4093                          break;
4077 4094                  default:
4078 4095                          prunlock(dpnp);
4079 4096                          prfreenode(pnp);
4080 4097                          return (NULL);
4081 4098                  }
4082 4099          }
4083 4100  
4084 4101          switch (type) {
4085 4102          case PR_CURDIR:
4086 4103          case PR_ROOTDIR:
4087 4104                  up = PTOU(p);
4088 4105                  vp = (type == PR_CURDIR)? up->u_cdir :
4089 4106                      (up->u_rdir? up->u_rdir : rootdir);
4090 4107  
4091 4108                  if (vp == NULL) {
4092 4109                          /* can't happen(?) */
4093 4110                          prunlock(dpnp);
4094 4111                          prfreenode(pnp);
4095 4112                          return (NULL);
4096 4113                  }
4097 4114                  /*
4098 4115                   * Fill in the prnode so future references will
4099 4116                   * be able to find the underlying object's vnode.
4100 4117                   */
4101 4118                  VN_HOLD(vp);
4102 4119                  pnp->pr_realvp = vp;
4103 4120                  PTOV(pnp)->v_flag |= VTRAVERSE;
4104 4121                  break;
4105 4122          default:
4106 4123                  break;
4107 4124          }
4108 4125  
4109 4126          mutex_enter(&dpnp->pr_mutex);
4110 4127  
4111 4128          if ((vp = dpnp->pr_files[i]) != NULL &&
4112 4129              !(VTOP(vp)->pr_flags & PR_INVAL)) {
4113 4130                  VN_HOLD(vp);
4114 4131                  mutex_exit(&dpnp->pr_mutex);
4115 4132                  prunlock(dpnp);
4116 4133                  prfreenode(pnp);
4117 4134                  return (vp);
4118 4135          }
4119 4136  
4120 4137          /*
4121 4138           * prgetnode() initialized most of the prnode.
4122 4139           * Finish the job.
4123 4140           */
4124 4141          pnp->pr_common = dpnp->pr_common;
4125 4142          pnp->pr_pcommon = dpnp->pr_pcommon;
4126 4143          pnp->pr_parent = dp;
4127 4144          VN_HOLD(dp);
4128 4145          pnp->pr_index = i;
4129 4146  
4130 4147          dpnp->pr_files[i] = vp = PTOV(pnp);
4131 4148  
4132 4149          /*
4133 4150           * Link new vnode into list of all /proc vnodes for the process.
4134 4151           */
4135 4152          if (vp->v_type == VPROC) {
4136 4153                  pnp->pr_next = p->p_plist;
4137 4154                  p->p_plist = vp;
4138 4155          }
4139 4156          mutex_exit(&dpnp->pr_mutex);
4140 4157          prunlock(dpnp);
4141 4158          return (vp);
4142 4159  }
4143 4160  
4144 4161  static vnode_t *
4145 4162  pr_lookup_objectdir(vnode_t *dp, char *comp)
4146 4163  {
4147 4164          prnode_t *dpnp = VTOP(dp);
4148 4165          prnode_t *pnp;
4149 4166          proc_t *p;
4150 4167          struct seg *seg;
4151 4168          struct as *as;
4152 4169          vnode_t *vp;
4153 4170          vattr_t vattr;
4154 4171  
4155 4172          ASSERT(dpnp->pr_type == PR_OBJECTDIR);
4156 4173  
4157 4174          pnp = prgetnode(dp, PR_OBJECT);
4158 4175  
4159 4176          if (prlock(dpnp, ZNO) != 0) {
4160 4177                  prfreenode(pnp);
4161 4178                  return (NULL);
4162 4179          }
4163 4180          p = dpnp->pr_common->prc_proc;
4164 4181          if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4165 4182                  prunlock(dpnp);
4166 4183                  prfreenode(pnp);
4167 4184                  return (NULL);
4168 4185          }
4169 4186  
4170 4187          /*
4171 4188           * We drop p_lock before grabbing the address space lock
4172 4189           * in order to avoid a deadlock with the clock thread.
4173 4190           * The process will not disappear and its address space
4174 4191           * will not change because it is marked P_PR_LOCK.
4175 4192           */
4176 4193          mutex_exit(&p->p_lock);
4177 4194          AS_LOCK_ENTER(as, RW_READER);
4178 4195          if ((seg = AS_SEGFIRST(as)) == NULL) {
4179 4196                  vp = NULL;
4180 4197                  goto out;
4181 4198          }
4182 4199          if (strcmp(comp, "a.out") == 0) {
4183 4200                  vp = p->p_exec;
4184 4201                  goto out;
4185 4202          }
4186 4203          do {
4187 4204                  /*
4188 4205                   * Manufacture a filename for the "object" directory.
4189 4206                   */
4190 4207                  vattr.va_mask = AT_FSID|AT_NODEID;
4191 4208                  if (seg->s_ops == &segvn_ops &&
4192 4209                      SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
4193 4210                      vp != NULL && vp->v_type == VREG &&
4194 4211                      VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
4195 4212                          char name[64];
4196 4213  
4197 4214                          if (vp == p->p_exec)    /* "a.out" */
4198 4215                                  continue;
4199 4216                          pr_object_name(name, vp, &vattr);
4200 4217                          if (strcmp(name, comp) == 0)
4201 4218                                  goto out;
4202 4219                  }
4203 4220          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4204 4221  
4205 4222          vp = NULL;
4206 4223  out:
4207 4224          if (vp != NULL) {
4208 4225                  VN_HOLD(vp);
4209 4226          }
4210 4227          AS_LOCK_EXIT(as);
4211 4228          mutex_enter(&p->p_lock);
4212 4229          prunlock(dpnp);
4213 4230  
4214 4231          if (vp == NULL)
4215 4232                  prfreenode(pnp);
4216 4233          else {
4217 4234                  /*
4218 4235                   * Fill in the prnode so future references will
4219 4236                   * be able to find the underlying object's vnode.
4220 4237                   * Don't link this prnode into the list of all
4221 4238                   * prnodes for the process; this is a one-use node.
4222 4239                   * Its use is entirely to catch and fail opens for writing.
4223 4240                   */
4224 4241                  pnp->pr_realvp = vp;
4225 4242                  vp = PTOV(pnp);
4226 4243          }
4227 4244  
4228 4245          return (vp);
4229 4246  }
4230 4247  
4231 4248  /*
4232 4249   * Find or construct an lwp vnode for the given lwpid.
4233 4250   */
4234 4251  static vnode_t *
4235 4252  pr_lookup_lwpdir(vnode_t *dp, char *comp)
4236 4253  {
4237 4254          id_t tid;       /* same type as t->t_tid */
4238 4255          int want_agent;
4239 4256          prnode_t *dpnp = VTOP(dp);
4240 4257          prnode_t *pnp;
4241 4258          prcommon_t *pcp;
4242 4259          vnode_t *vp;
4243 4260          proc_t *p;
4244 4261          kthread_t *t;
4245 4262          lwpdir_t *ldp;
4246 4263          lwpent_t *lep;
4247 4264          int tslot;
4248 4265          int c;
4249 4266  
4250 4267          ASSERT(dpnp->pr_type == PR_LWPDIR);
4251 4268  
4252 4269          tid = 0;
4253 4270          if (strcmp(comp, "agent") == 0)
4254 4271                  want_agent = 1;
4255 4272          else {
4256 4273                  want_agent = 0;
4257 4274                  while ((c = *comp++) != '\0') {
4258 4275                          id_t otid;
4259 4276  
4260 4277                          if (c < '0' || c > '9')
4261 4278                                  return (NULL);
4262 4279                          otid = tid;
4263 4280                          tid = 10*tid + c - '0';
4264 4281                          if (tid/10 != otid)     /* integer overflow */
4265 4282                                  return (NULL);
4266 4283                  }
4267 4284          }
4268 4285  
4269 4286          pnp = prgetnode(dp, PR_LWPIDDIR);
4270 4287  
4271 4288          p = pr_p_lock(dpnp);
4272 4289          mutex_exit(&pr_pidlock);
4273 4290          if (p == NULL) {
4274 4291                  prfreenode(pnp);
4275 4292                  return (NULL);
4276 4293          }
4277 4294  
4278 4295          if (want_agent) {
4279 4296                  if ((t = p->p_agenttp) == NULL)
4280 4297                          lep = NULL;
4281 4298                  else {
4282 4299                          tid = t->t_tid;
4283 4300                          tslot = t->t_dslot;
4284 4301                          lep = p->p_lwpdir[tslot].ld_entry;
4285 4302                  }
4286 4303          } else {
4287 4304                  if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
4288 4305                          lep = NULL;
4289 4306                  else {
4290 4307                          tslot = (int)(ldp - p->p_lwpdir);
4291 4308                          lep = ldp->ld_entry;
4292 4309                  }
4293 4310          }
4294 4311  
4295 4312          if (lep == NULL) {
4296 4313                  prunlock(dpnp);
4297 4314                  prfreenode(pnp);
4298 4315                  return (NULL);
4299 4316          }
4300 4317  
4301 4318          /*
4302 4319           * If an lwp vnode already exists and it is not invalid
4303 4320           * and it was created by the current process and it belongs
4304 4321           * to the same /proc mount point as our parent vnode, then
4305 4322           * just use it and discard the newly-allocated prnode.
4306 4323           */
4307 4324          for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
4308 4325                  if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
4309 4326                      VTOP(vp)->pr_owner == curproc &&
4310 4327                      vp->v_vfsp == dp->v_vfsp) {
4311 4328                          VN_HOLD(vp);
4312 4329                          prunlock(dpnp);
4313 4330                          prfreenode(pnp);
4314 4331                          return (vp);
4315 4332                  }
4316 4333          }
4317 4334          pnp->pr_owner = curproc;
4318 4335  
4319 4336          /*
4320 4337           * prgetnode() initialized most of the prnode.
4321 4338           * Finish the job.
4322 4339           */
4323 4340          pcp = pnp->pr_common;   /* the newly-allocated prcommon struct */
4324 4341          if ((vp = lep->le_trace) != NULL) {
4325 4342                  /* discard the new prcommon and use the existing prcommon */
4326 4343                  prfreecommon(pcp);
4327 4344                  pcp = VTOP(vp)->pr_common;
4328 4345                  mutex_enter(&pcp->prc_mutex);
4329 4346                  ASSERT(pcp->prc_refcnt > 0);
4330 4347                  pcp->prc_refcnt++;
4331 4348                  mutex_exit(&pcp->prc_mutex);
4332 4349                  pnp->pr_common = pcp;
4333 4350          } else {
4334 4351                  /* initialize the new prcommon struct */
4335 4352                  pcp->prc_flags |= PRC_LWP;
4336 4353                  if ((p->p_flag & SSYS) || p->p_as == &kas)
4337 4354                          pcp->prc_flags |= PRC_SYS;
4338 4355                  if ((t = lep->le_thread) == NULL)
4339 4356                          pcp->prc_flags |= PRC_DESTROY;
4340 4357                  pcp->prc_proc = p;
4341 4358                  pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
4342 4359                  pcp->prc_pid = p->p_pid;
4343 4360                  pcp->prc_slot = p->p_slot;
4344 4361                  pcp->prc_thread = t;
4345 4362                  pcp->prc_tid = tid;
4346 4363                  pcp->prc_tslot = tslot;
4347 4364          }
4348 4365          pnp->pr_pcommon = dpnp->pr_pcommon;
4349 4366          pnp->pr_parent = dp;
4350 4367          VN_HOLD(dp);
4351 4368          /*
4352 4369           * Link in the old, invalid directory vnode so we
4353 4370           * can later determine the last close of the file.
4354 4371           */
4355 4372          pnp->pr_next = lep->le_trace;
4356 4373          lep->le_trace = vp = PTOV(pnp);
4357 4374          prunlock(dpnp);
4358 4375          return (vp);
4359 4376  }
4360 4377  
4361 4378  static vnode_t *
4362 4379  pr_lookup_lwpiddir(vnode_t *dp, char *comp)
4363 4380  {
4364 4381          prnode_t *dpnp = VTOP(dp);
4365 4382          vnode_t *vp;
4366 4383          prnode_t *pnp;
4367 4384          proc_t *p;
4368 4385          prdirent_t *dirp;
4369 4386          int i;
4370 4387          enum prnodetype type;
4371 4388  
4372 4389          ASSERT(dpnp->pr_type == PR_LWPIDDIR);
4373 4390  
4374 4391          for (i = 0; i < NLWPIDDIRFILES; i++) {
4375 4392                  /* Skip "." and ".." */
4376 4393                  dirp = &lwpiddir[i+2];
4377 4394                  if (strcmp(comp, dirp->d_name) == 0)
4378 4395                          break;
4379 4396          }
4380 4397  
4381 4398          if (i >= NLWPIDDIRFILES)
4382 4399                  return (NULL);
4383 4400  
4384 4401          type = (int)dirp->d_ino;
4385 4402          pnp = prgetnode(dp, type);
4386 4403  
4387 4404          p = pr_p_lock(dpnp);
4388 4405          mutex_exit(&pr_pidlock);
4389 4406          if (p == NULL) {
4390 4407                  prfreenode(pnp);
4391 4408                  return (NULL);
4392 4409          }
4393 4410          if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
4394 4411                  /*
4395 4412                   * Only the lwpsinfo file is present for zombie lwps.
4396 4413                   * Nothing is present if the lwp has been reaped.
4397 4414                   */
4398 4415                  if (dpnp->pr_common->prc_tslot == -1 ||
4399 4416                      type != PR_LWPSINFO) {
4400 4417                          prunlock(dpnp);
4401 4418                          prfreenode(pnp);
4402 4419                          return (NULL);
4403 4420                  }
4404 4421          }
4405 4422  
4406 4423  #if defined(__sparc)
4407 4424          /* the asrs file exists only for sparc v9 _LP64 processes */
4408 4425          if (type == PR_ASRS && p->p_model != DATAMODEL_LP64) {
4409 4426                  prunlock(dpnp);
4410 4427                  prfreenode(pnp);
4411 4428                  return (NULL);
4412 4429          }
4413 4430  #endif
4414 4431  
4415 4432          mutex_enter(&dpnp->pr_mutex);
4416 4433  
4417 4434          if ((vp = dpnp->pr_files[i]) != NULL &&
4418 4435              !(VTOP(vp)->pr_flags & PR_INVAL)) {
4419 4436                  VN_HOLD(vp);
4420 4437                  mutex_exit(&dpnp->pr_mutex);
4421 4438                  prunlock(dpnp);
4422 4439                  prfreenode(pnp);
4423 4440                  return (vp);
4424 4441          }
4425 4442  
4426 4443          /*
4427 4444           * prgetnode() initialized most of the prnode.
4428 4445           * Finish the job.
4429 4446           */
4430 4447          pnp->pr_common = dpnp->pr_common;
4431 4448          pnp->pr_pcommon = dpnp->pr_pcommon;
4432 4449          pnp->pr_parent = dp;
4433 4450          VN_HOLD(dp);
4434 4451          pnp->pr_index = i;
4435 4452  
4436 4453          dpnp->pr_files[i] = vp = PTOV(pnp);
4437 4454  
4438 4455          /*
4439 4456           * Link new vnode into list of all /proc vnodes for the process.
4440 4457           */
4441 4458          if (vp->v_type == VPROC) {
4442 4459                  pnp->pr_next = p->p_plist;
4443 4460                  p->p_plist = vp;
4444 4461          }
4445 4462          mutex_exit(&dpnp->pr_mutex);
4446 4463          prunlock(dpnp);
4447 4464          return (vp);
4448 4465  }
4449 4466  
4450 4467  /*
4451 4468   * Lookup one of the process's file vnodes.
4452 4469   */
4453 4470  static vnode_t *
4454 4471  pr_lookup_fddir(vnode_t *dp, char *comp)
4455 4472  {
4456 4473          prnode_t *dpnp = VTOP(dp);
4457 4474          prnode_t *pnp;
4458 4475          vnode_t *vp = NULL;
4459 4476          proc_t *p;
4460 4477          file_t *fp;
4461 4478          uint_t fd;
4462 4479          int c;
4463 4480  
4464 4481          ASSERT(dpnp->pr_type == PR_FDDIR);
4465 4482  
4466 4483          fd = 0;
4467 4484          while ((c = *comp++) != '\0') {
4468 4485                  int ofd;
4469 4486                  if (c < '0' || c > '9')
4470 4487                          return (NULL);
4471 4488                  ofd = fd;
4472 4489                  fd = 10 * fd + c - '0';
4473 4490                  if (fd / 10 != ofd)     /* integer overflow */
4474 4491                          return (NULL);
4475 4492          }
4476 4493  
4477 4494          pnp = prgetnode(dp, PR_FD);
4478 4495  
4479 4496          if (prlock(dpnp, ZNO) != 0) {
4480 4497                  prfreenode(pnp);
4481 4498                  return (NULL);
4482 4499          }
4483 4500          p = dpnp->pr_common->prc_proc;
4484 4501          if ((p->p_flag & SSYS) || p->p_as == &kas) {
4485 4502                  prunlock(dpnp);
4486 4503                  prfreenode(pnp);
4487 4504                  return (NULL);
4488 4505          }
4489 4506  
4490 4507          if ((fp = pr_getf(p, fd, NULL)) != NULL) {
4491 4508                  pnp->pr_mode = 07111;
4492 4509                  if (fp->f_flag & FREAD)
4493 4510                          pnp->pr_mode |= 0444;
4494 4511                  if (fp->f_flag & FWRITE)
4495 4512                          pnp->pr_mode |= 0222;
4496 4513                  vp = fp->f_vnode;
4497 4514                  VN_HOLD(vp);
4498 4515          }
4499 4516  
4500 4517          prunlock(dpnp);
4501 4518          if (fp != NULL) {
4502 4519                  pr_releasef(fp);
4503 4520          }
4504 4521  
4505 4522          if (vp == NULL) {
4506 4523                  prfreenode(pnp);
4507 4524                  return (NULL);
4508 4525          }
4509 4526  
4510 4527          /*
4511 4528           * Fill in the prnode so future references will
4512 4529           * be able to find the underlying object's vnode.
4513 4530           * Don't link this prnode into the list of all
4514 4531           * prnodes for the process; this is a one-use node.
4515 4532           */
4516 4533          pnp->pr_realvp = vp;
4517 4534          pnp->pr_parent = dp;            /* needed for prlookup */
4518 4535          VN_HOLD(dp);
4519 4536          vp = PTOV(pnp);
4520 4537          if (pnp->pr_realvp->v_type == VDIR) {
4521 4538                  vp->v_type = VDIR;
4522 4539                  vp->v_flag |= VTRAVERSE;
4523 4540          }
4524 4541  
4525 4542          return (vp);
4526 4543  }
4527 4544  
4528 4545  static vnode_t *
4529 4546  pr_lookup_fdinfodir(vnode_t *dp, char *comp)
4530 4547  {
4531 4548          prnode_t *dpnp = VTOP(dp);
4532 4549          prnode_t *pnp;
4533 4550          vnode_t *vp = NULL;
4534 4551          proc_t *p;
4535 4552          uint_t fd;
4536 4553          int c;
4537 4554  
4538 4555          ASSERT(dpnp->pr_type == PR_FDINFODIR);
4539 4556  
4540 4557          fd = 0;
4541 4558          while ((c = *comp++) != '\0') {
4542 4559                  int ofd;
4543 4560                  if (c < '0' || c > '9')
4544 4561                          return (NULL);
4545 4562                  ofd = fd;
4546 4563                  fd = 10 * fd + c - '0';
4547 4564                  if (fd / 10 != ofd)     /* integer overflow */
4548 4565                          return (NULL);
4549 4566          }
4550 4567  
4551 4568          pnp = prgetnode(dp, PR_FDINFO);
4552 4569  
4553 4570          if (prlock(dpnp, ZNO) != 0) {
4554 4571                  prfreenode(pnp);
4555 4572                  return (NULL);
4556 4573          }
4557 4574          p = dpnp->pr_common->prc_proc;
4558 4575          if ((p->p_flag & SSYS) || p->p_as == &kas) {
4559 4576                  prunlock(dpnp);
4560 4577                  prfreenode(pnp);
4561 4578                  return (NULL);
4562 4579          }
4563 4580  
4564 4581          /*
4565 4582           * Don't link this prnode into the list of all
4566 4583           * prnodes for the process; this is a one-use node.
4567 4584           * Unlike the FDDIR case, the underlying vnode is not stored in
4568 4585           * pnp->pr_realvp. Instead, the fd number is stored in pnp->pr_index
4569 4586           * and used by pr_read_fdinfo() to return information for the right
4570 4587           * file descriptor.
4571 4588           */
4572 4589          pnp->pr_common = dpnp->pr_common;
4573 4590          pnp->pr_pcommon = dpnp->pr_pcommon;
4574 4591          pnp->pr_parent = dp;
4575 4592          pnp->pr_index = fd;
4576 4593          VN_HOLD(dp);
4577 4594          prunlock(dpnp);
4578 4595          vp = PTOV(pnp);
4579 4596  
4580 4597          return (vp);
4581 4598  }
4582 4599  
4583 4600  static vnode_t *
4584 4601  pr_lookup_pathdir(vnode_t *dp, char *comp)
4585 4602  {
4586 4603          prnode_t *dpnp = VTOP(dp);
4587 4604          prnode_t *pnp;
4588 4605          vnode_t *vp = NULL;
4589 4606          proc_t *p;
4590 4607          uint_t fd, flags = 0;
4591 4608          int c;
4592 4609          uf_entry_t *ufp;
4593 4610          uf_info_t *fip;
4594 4611          enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
4595 4612          char *tmp;
4596 4613          int idx;
4597 4614          struct seg *seg;
4598 4615          struct as *as = NULL;
4599 4616          vattr_t vattr;
4600 4617  
4601 4618          ASSERT(dpnp->pr_type == PR_PATHDIR);
4602 4619  
4603 4620          /*
4604 4621           * First, check if this is a numeric entry, in which case we have a
4605 4622           * file descriptor.
4606 4623           */
4607 4624          fd = 0;
4608 4625          type = NAME_FD;
4609 4626          tmp = comp;
4610 4627          while ((c = *tmp++) != '\0') {
4611 4628                  int ofd;
4612 4629                  if (c < '0' || c > '9') {
4613 4630                          type = NAME_UNKNOWN;
4614 4631                          break;
4615 4632                  }
4616 4633                  ofd = fd;
4617 4634                  fd = 10*fd + c - '0';
4618 4635                  if (fd/10 != ofd) {     /* integer overflow */
4619 4636                          type = NAME_UNKNOWN;
4620 4637                          break;
4621 4638                  }
4622 4639          }
4623 4640  
4624 4641          /*
4625 4642           * Next, see if it is one of the special values {root, cwd}.
4626 4643           */
4627 4644          if (type == NAME_UNKNOWN) {
4628 4645                  if (strcmp(comp, "root") == 0)
4629 4646                          type = NAME_ROOT;
4630 4647                  else if (strcmp(comp, "cwd") == 0)
4631 4648                          type = NAME_CWD;
4632 4649          }
4633 4650  
4634 4651          /*
4635 4652           * Grab the necessary data from the process
4636 4653           */
4637 4654          if (prlock(dpnp, ZNO) != 0)
4638 4655                  return (NULL);
4639 4656          p = dpnp->pr_common->prc_proc;
4640 4657  
4641 4658          fip = P_FINFO(p);
4642 4659  
4643 4660          switch (type) {
4644 4661          case NAME_ROOT:
4645 4662                  if ((vp = PTOU(p)->u_rdir) == NULL)
4646 4663                          vp = p->p_zone->zone_rootvp;
4647 4664                  VN_HOLD(vp);
4648 4665                  break;
4649 4666          case NAME_CWD:
4650 4667                  vp = PTOU(p)->u_cdir;
4651 4668                  VN_HOLD(vp);
4652 4669                  break;
4653 4670          default:
4654 4671                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4655 4672                          prunlock(dpnp);
4656 4673                          return (NULL);
4657 4674                  }
4658 4675          }
4659 4676          mutex_exit(&p->p_lock);
4660 4677  
4661 4678          /*
4662 4679           * Determine if this is an object entry
4663 4680           */
4664 4681          if (type == NAME_UNKNOWN) {
4665 4682                  /*
4666 4683                   * Start with the inode index immediately after the number of
4667 4684                   * files.
4668 4685                   */
4669 4686                  mutex_enter(&fip->fi_lock);
4670 4687                  idx = fip->fi_nfiles + 4;
4671 4688                  mutex_exit(&fip->fi_lock);
4672 4689  
4673 4690                  if (strcmp(comp, "a.out") == 0) {
4674 4691                          if (p->p_execdir != NULL) {
4675 4692                                  vp = p->p_execdir;
4676 4693                                  VN_HOLD(vp);
4677 4694                                  type = NAME_OBJECT;
4678 4695                                  flags |= PR_AOUT;
4679 4696                          } else {
4680 4697                                  vp = p->p_exec;
4681 4698                                  VN_HOLD(vp);
4682 4699                                  type = NAME_OBJECT;
4683 4700                          }
4684 4701                  } else {
4685 4702                          AS_LOCK_ENTER(as, RW_READER);
4686 4703                          if ((seg = AS_SEGFIRST(as)) != NULL) {
4687 4704                                  do {
4688 4705                                          /*
4689 4706                                           * Manufacture a filename for the
4690 4707                                           * "object" directory.
4691 4708                                           */
4692 4709                                          vattr.va_mask = AT_FSID|AT_NODEID;
4693 4710                                          if (seg->s_ops == &segvn_ops &&
4694 4711                                              SEGOP_GETVP(seg, seg->s_base, &vp)
4695 4712                                              == 0 &&
4696 4713                                              vp != NULL && vp->v_type == VREG &&
4697 4714                                              VOP_GETATTR(vp, &vattr, 0, CRED(),
4698 4715                                              NULL) == 0) {
4699 4716                                                  char name[64];
4700 4717  
4701 4718                                                  if (vp == p->p_exec)
4702 4719                                                          continue;
4703 4720                                                  idx++;
4704 4721                                                  pr_object_name(name, vp,
4705 4722                                                      &vattr);
4706 4723                                                  if (strcmp(name, comp) == 0)
4707 4724                                                          break;
4708 4725                                          }
4709 4726                                  } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4710 4727                          }
4711 4728  
4712 4729                          if (seg == NULL) {
4713 4730                                  vp = NULL;
4714 4731                          } else {
4715 4732                                  VN_HOLD(vp);
4716 4733                                  type = NAME_OBJECT;
4717 4734                          }
4718 4735  
4719 4736                          AS_LOCK_EXIT(as);
4720 4737                  }
4721 4738          }
4722 4739  
4723 4740  
4724 4741          switch (type) {
4725 4742          case NAME_FD:
4726 4743                  mutex_enter(&fip->fi_lock);
4727 4744                  if (fd < fip->fi_nfiles) {
4728 4745                          UF_ENTER(ufp, fip, fd);
4729 4746                          if (ufp->uf_file != NULL) {
4730 4747                                  vp = ufp->uf_file->f_vnode;
4731 4748                                  VN_HOLD(vp);
4732 4749                          }
4733 4750                          UF_EXIT(ufp);
4734 4751                  }
4735 4752                  mutex_exit(&fip->fi_lock);
4736 4753                  idx = fd + 4;
4737 4754                  break;
4738 4755          case NAME_ROOT:
4739 4756                  idx = 2;
4740 4757                  break;
4741 4758          case NAME_CWD:
4742 4759                  idx = 3;
4743 4760                  break;
4744 4761          case NAME_OBJECT:
4745 4762          case NAME_UNKNOWN:
4746 4763                  /* Nothing to do */
4747 4764                  break;
4748 4765          }
4749 4766  
4750 4767          mutex_enter(&p->p_lock);
4751 4768          prunlock(dpnp);
4752 4769  
4753 4770          if (vp != NULL) {
4754 4771                  pnp = prgetnode(dp, PR_PATH);
4755 4772  
4756 4773                  pnp->pr_flags |= flags;
4757 4774                  pnp->pr_common = dpnp->pr_common;
4758 4775                  pnp->pr_pcommon = dpnp->pr_pcommon;
4759 4776                  pnp->pr_realvp = vp;
4760 4777                  pnp->pr_parent = dp;            /* needed for prlookup */
4761 4778                  pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
4762 4779                  VN_HOLD(dp);
4763 4780                  vp = PTOV(pnp);
4764 4781                  vp->v_type = VLNK;
4765 4782          }
4766 4783  
4767 4784          return (vp);
4768 4785  }
4769 4786  
4770 4787  /*
4771 4788   * Look up one of the process's active templates.
4772 4789   */
4773 4790  static vnode_t *
4774 4791  pr_lookup_tmpldir(vnode_t *dp, char *comp)
4775 4792  {
4776 4793          prnode_t *dpnp = VTOP(dp);
4777 4794          prnode_t *pnp;
4778 4795          vnode_t *vp = NULL;
4779 4796          proc_t *p;
4780 4797          int i;
4781 4798  
4782 4799          ASSERT(dpnp->pr_type == PR_TMPLDIR);
4783 4800  
4784 4801          for (i = 0; i < ct_ntypes; i++)
4785 4802                  if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
4786 4803                          break;
4787 4804          if (i == ct_ntypes)
4788 4805                  return (NULL);
4789 4806  
4790 4807          pnp = prgetnode(dp, PR_TMPL);
4791 4808  
4792 4809          if (prlock(dpnp, ZNO) != 0) {
4793 4810                  prfreenode(pnp);
4794 4811                  return (NULL);
4795 4812          }
4796 4813          p = dpnp->pr_common->prc_proc;
4797 4814          if ((p->p_flag & SSYS) || p->p_as == &kas ||
4798 4815              (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
4799 4816                  prunlock(dpnp);
4800 4817                  prfreenode(pnp);
4801 4818                  return (NULL);
4802 4819          }
4803 4820          if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
4804 4821                  pnp->pr_common = dpnp->pr_common;
4805 4822                  pnp->pr_pcommon = dpnp->pr_pcommon;
4806 4823                  pnp->pr_parent = dp;
4807 4824                  pnp->pr_cttype = i;
4808 4825                  VN_HOLD(dp);
4809 4826                  vp = PTOV(pnp);
4810 4827          } else {
4811 4828                  prfreenode(pnp);
4812 4829          }
4813 4830          prunlock(dpnp);
4814 4831  
4815 4832          return (vp);
4816 4833  }
4817 4834  
4818 4835  /*
4819 4836   * Look up one of the contracts owned by the process.
4820 4837   */
4821 4838  static vnode_t *
4822 4839  pr_lookup_ctdir(vnode_t *dp, char *comp)
4823 4840  {
4824 4841          prnode_t *dpnp = VTOP(dp);
4825 4842          prnode_t *pnp;
4826 4843          vnode_t *vp = NULL;
4827 4844          proc_t *p;
4828 4845          id_t id = 0;
4829 4846          contract_t *ct;
4830 4847          int c;
4831 4848  
4832 4849          ASSERT(dpnp->pr_type == PR_CTDIR);
4833 4850  
4834 4851          while ((c = *comp++) != '\0') {
4835 4852                  id_t oid;
4836 4853                  if (c < '0' || c > '9')
4837 4854                          return (NULL);
4838 4855                  oid = id;
4839 4856                  id = 10 * id + c - '0';
4840 4857                  if (id / 10 != oid)     /* integer overflow */
4841 4858                          return (NULL);
4842 4859          }
4843 4860  
4844 4861          /*
4845 4862           * Search all contracts; we'll filter below.
4846 4863           */
4847 4864          ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
4848 4865          if (ct == NULL)
4849 4866                  return (NULL);
4850 4867  
4851 4868          pnp = prgetnode(dp, PR_CT);
4852 4869  
4853 4870          if (prlock(dpnp, ZNO) != 0) {
4854 4871                  prfreenode(pnp);
4855 4872                  contract_rele(ct);
4856 4873                  return (NULL);
4857 4874          }
4858 4875          p = dpnp->pr_common->prc_proc;
4859 4876          /*
4860 4877           * We only allow lookups of contracts owned by this process, or,
4861 4878           * if we are zsched and this is a zone's procfs, contracts on
4862 4879           * stuff in the zone which are held by processes or contracts
4863 4880           * outside the zone.  (see logic in contract_status_common)
4864 4881           */
4865 4882          if ((ct->ct_owner != p) &&
4866 4883              !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4867 4884              VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4868 4885              VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
4869 4886              ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
4870 4887                  prunlock(dpnp);
4871 4888                  prfreenode(pnp);
4872 4889                  contract_rele(ct);
4873 4890                  return (NULL);
4874 4891          }
4875 4892          pnp->pr_common = dpnp->pr_common;
4876 4893          pnp->pr_pcommon = dpnp->pr_pcommon;
4877 4894          pnp->pr_contract = ct;
4878 4895          pnp->pr_parent = dp;
4879 4896          pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
4880 4897          VN_HOLD(dp);
4881 4898          prunlock(dpnp);
4882 4899          vp = PTOV(pnp);
4883 4900  
4884 4901          return (vp);
4885 4902  }
4886 4903  
4887 4904  /*
4888 4905   * Construct an lwp vnode for the old /proc interface.
4889 4906   * We stand on our head to make the /proc plumbing correct.
4890 4907   */
4891 4908  vnode_t *
4892 4909  prlwpnode(prnode_t *pnp, uint_t tid)
4893 4910  {
4894 4911          char comp[12];
4895 4912          vnode_t *dp;
4896 4913          vnode_t *vp;
4897 4914          prcommon_t *pcp;
4898 4915          proc_t *p;
4899 4916  
4900 4917          /*
4901 4918           * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
4902 4919           */
4903 4920          if (pnp->pr_type == PR_PIDFILE) {
4904 4921                  dp = pnp->pr_parent;            /* /proc/<pid> */
4905 4922                  VN_HOLD(dp);
4906 4923                  vp = pr_lookup_piddir(dp, "lwp");
4907 4924                  VN_RELE(dp);
4908 4925                  if ((dp = vp) == NULL)          /* /proc/<pid>/lwp */
4909 4926                          return (NULL);
4910 4927          } else if (pnp->pr_type == PR_LWPIDFILE) {
4911 4928                  dp = pnp->pr_parent;            /* /proc/<pid>/lwp/<lwpid> */
4912 4929                  dp = VTOP(dp)->pr_parent;       /* /proc/<pid>/lwp */
4913 4930                  VN_HOLD(dp);
4914 4931          } else {
4915 4932                  return (NULL);
4916 4933          }
4917 4934  
4918 4935          (void) pr_u32tos(tid, comp, sizeof (comp));
4919 4936          vp = pr_lookup_lwpdir(dp, comp);
4920 4937          VN_RELE(dp);
4921 4938          if ((dp = vp) == NULL)
4922 4939                  return (NULL);
4923 4940  
4924 4941          pnp = prgetnode(dp, PR_LWPIDFILE);
4925 4942          vp = PTOV(pnp);
4926 4943  
4927 4944          /*
4928 4945           * prgetnode() initialized most of the prnode.
4929 4946           * Finish the job.
4930 4947           */
4931 4948          pcp = VTOP(dp)->pr_common;
4932 4949          pnp->pr_ino = ptoi(pcp->prc_pid);
4933 4950          pnp->pr_common = pcp;
4934 4951          pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
4935 4952          pnp->pr_parent = dp;
4936 4953          /*
4937 4954           * Link new vnode into list of all /proc vnodes for the process.
4938 4955           */
4939 4956          p = pr_p_lock(pnp);
4940 4957          mutex_exit(&pr_pidlock);
4941 4958          if (p == NULL) {
4942 4959                  VN_RELE(dp);
4943 4960                  prfreenode(pnp);
4944 4961                  vp = NULL;
4945 4962          } else if (pcp->prc_thread == NULL) {
4946 4963                  prunlock(pnp);
4947 4964                  VN_RELE(dp);
4948 4965                  prfreenode(pnp);
4949 4966                  vp = NULL;
4950 4967          } else {
4951 4968                  pnp->pr_next = p->p_plist;
4952 4969                  p->p_plist = vp;
4953 4970                  prunlock(pnp);
4954 4971          }
4955 4972  
4956 4973          return (vp);
4957 4974  }
4958 4975  
4959 4976  #if defined(DEBUG)
4960 4977  
4961 4978  static  uint32_t nprnode;
4962 4979  static  uint32_t nprcommon;
4963 4980  
4964 4981  #define INCREMENT(x)    atomic_inc_32(&x);
4965 4982  #define DECREMENT(x)    atomic_dec_32(&x);
4966 4983  
4967 4984  #else
4968 4985  
4969 4986  #define INCREMENT(x)
4970 4987  #define DECREMENT(x)
4971 4988  
4972 4989  #endif  /* DEBUG */
4973 4990  
4974 4991  /*
4975 4992   * New /proc vnode required; allocate it and fill in most of the fields.
4976 4993   */
4977 4994  prnode_t *
4978 4995  prgetnode(vnode_t *dp, prnodetype_t type)
4979 4996  {
4980 4997          prnode_t *pnp;
4981 4998          prcommon_t *pcp;
4982 4999          vnode_t *vp;
4983 5000          ulong_t nfiles;
4984 5001  
4985 5002          INCREMENT(nprnode);
4986 5003          pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
4987 5004  
4988 5005          mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
4989 5006          pnp->pr_type = type;
4990 5007  
4991 5008          pnp->pr_vnode = vn_alloc(KM_SLEEP);
4992 5009  
4993 5010          vp = PTOV(pnp);
4994 5011          vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
4995 5012          vn_setops(vp, prvnodeops);
4996 5013          vp->v_vfsp = dp->v_vfsp;
4997 5014          vp->v_type = VPROC;
4998 5015          vp->v_data = (caddr_t)pnp;
4999 5016  
5000 5017          switch (type) {
5001 5018          case PR_PIDDIR:
5002 5019          case PR_LWPIDDIR:
5003 5020                  /*
5004 5021                   * We need a prcommon and a files array for each of these.
5005 5022                   */
5006 5023                  INCREMENT(nprcommon);
5007 5024  
5008 5025                  pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
5009 5026                  pcp->prc_refcnt = 1;
5010 5027                  pnp->pr_common = pcp;
5011 5028                  mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
5012 5029                  cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
5013 5030  
5014 5031                  nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
5015 5032                  pnp->pr_files =
5016 5033                      kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
5017 5034  
5018 5035                  vp->v_type = VDIR;
5019 5036                  /*
5020 5037                   * Mode should be read-search by all, but we cannot so long
5021 5038                   * as we must support compatibility mode with old /proc.
5022 5039                   * Make /proc/<pid> be read by owner only, search by all.
5023 5040                   * Make /proc/<pid>/lwp/<lwpid> read-search by all.  Also,
5024 5041                   * set VDIROPEN on /proc/<pid> so it can be opened for writing.
5025 5042                   */
5026 5043                  if (type == PR_PIDDIR) {
5027 5044                          /* kludge for old /proc interface */
5028 5045                          prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
5029 5046                          pnp->pr_pidfile = PTOV(xpnp);
5030 5047                          pnp->pr_mode = 0511;
5031 5048                          vp->v_flag |= VDIROPEN;
5032 5049                  } else {
5033 5050                          pnp->pr_mode = 0555;
5034 5051                  }
5035 5052  
5036 5053                  break;
5037 5054  
5038 5055          case PR_CURDIR:
5039 5056          case PR_ROOTDIR:
5040 5057          case PR_FDDIR:
5041 5058          case PR_FDINFODIR:
5042 5059          case PR_OBJECTDIR:
5043 5060          case PR_PATHDIR:
5044 5061          case PR_CTDIR:
5045 5062          case PR_TMPLDIR:
5046 5063                  vp->v_type = VDIR;
5047 5064                  pnp->pr_mode = 0500;    /* read-search by owner only */
5048 5065                  break;
5049 5066  
5050 5067          case PR_CT:
5051 5068                  vp->v_type = VLNK;
5052 5069                  pnp->pr_mode = 0500;    /* read-search by owner only */
5053 5070                  break;
5054 5071  
5055 5072          case PR_PATH:
5056 5073          case PR_SELF:
5057 5074                  vp->v_type = VLNK;
5058 5075                  pnp->pr_mode = 0777;
5059 5076                  break;
5060 5077  
5061 5078          case PR_LWPDIR:
5062 5079                  vp->v_type = VDIR;
5063 5080                  pnp->pr_mode = 0555;    /* read-search by all */
5064 5081                  break;
5065 5082  
5066 5083          case PR_AS:
5067 5084          case PR_TMPL:
5068 5085                  pnp->pr_mode = 0600;    /* read-write by owner only */
5069 5086                  break;
5070 5087  
5071 5088          case PR_CTL:
5072 5089          case PR_LWPCTL:
5073 5090                  pnp->pr_mode = 0200;    /* write-only by owner only */
5074 5091                  break;
5075 5092  
5076 5093          case PR_PIDFILE:
5077 5094          case PR_LWPIDFILE:
5078 5095                  pnp->pr_mode = 0600;    /* read-write by owner only */
5079 5096                  break;
5080 5097  
5081 5098          case PR_PSINFO:
5082 5099          case PR_LWPNAME:
5083 5100                  pnp->pr_mode = 0644;    /* readable by all + owner can write */
5084 5101                  break;
5085 5102  
5086 5103          case PR_LPSINFO:
5087 5104          case PR_LWPSINFO:
5088 5105          case PR_USAGE:
5089 5106          case PR_LUSAGE:
5090 5107          case PR_LWPUSAGE:
5091 5108          case PR_ARGV:
5092 5109          case PR_CMDLINE:
5093 5110                  pnp->pr_mode = 0444;    /* read-only by all */
5094 5111                  break;
5095 5112  
5096 5113          default:
5097 5114                  pnp->pr_mode = 0400;    /* read-only by owner only */
5098 5115                  break;
5099 5116          }
5100 5117          vn_exists(vp);
5101 5118          return (pnp);
5102 5119  }
5103 5120  
5104 5121  /*
5105 5122   * Free the storage obtained from prgetnode().
5106 5123   */
5107 5124  void
5108 5125  prfreenode(prnode_t *pnp)
5109 5126  {
5110 5127          vnode_t *vp;
5111 5128          ulong_t nfiles;
5112 5129  
5113 5130          vn_invalid(PTOV(pnp));
5114 5131          vn_free(PTOV(pnp));
5115 5132          mutex_destroy(&pnp->pr_mutex);
5116 5133  
5117 5134          switch (pnp->pr_type) {
5118 5135          case PR_PIDDIR:
5119 5136                  /* kludge for old /proc interface */
5120 5137                  if (pnp->pr_pidfile != NULL) {
5121 5138                          prfreenode(VTOP(pnp->pr_pidfile));
5122 5139                          pnp->pr_pidfile = NULL;
5123 5140                  }
5124 5141                  /* FALLTHROUGH */
5125 5142          case PR_LWPIDDIR:
5126 5143                  /*
5127 5144                   * We allocated a prcommon and a files array for each of these.
5128 5145                   */
5129 5146                  prfreecommon(pnp->pr_common);
5130 5147                  nfiles = (pnp->pr_type == PR_PIDDIR)?
5131 5148                      NPIDDIRFILES : NLWPIDDIRFILES;
5132 5149                  kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
5133 5150                  break;
5134 5151          default:
5135 5152                  break;
5136 5153          }
5137 5154          /*
5138 5155           * If there is an underlying vnode, be sure
5139 5156           * to release it after freeing the prnode.
5140 5157           */
5141 5158          vp = pnp->pr_realvp;
5142 5159          kmem_free(pnp, sizeof (*pnp));
5143 5160          DECREMENT(nprnode);
5144 5161          if (vp != NULL) {
5145 5162                  VN_RELE(vp);
5146 5163          }
5147 5164  }
5148 5165  
5149 5166  /*
5150 5167   * Free a prcommon structure, if the reference count reaches zero.
5151 5168   */
5152 5169  static void
5153 5170  prfreecommon(prcommon_t *pcp)
5154 5171  {
5155 5172          mutex_enter(&pcp->prc_mutex);
5156 5173          ASSERT(pcp->prc_refcnt > 0);
5157 5174          if (--pcp->prc_refcnt != 0)
5158 5175                  mutex_exit(&pcp->prc_mutex);
5159 5176          else {
5160 5177                  mutex_exit(&pcp->prc_mutex);
5161 5178  
5162 5179                  ASSERT(pcp->prc_refcnt == 0);
5163 5180                  ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
5164 5181  
5165 5182                  pollhead_clean(&pcp->prc_pollhead);
5166 5183                  mutex_destroy(&pcp->prc_mutex);
5167 5184                  cv_destroy(&pcp->prc_wait);
5168 5185                  kmem_free(pcp, sizeof (prcommon_t));
5169 5186                  DECREMENT(nprcommon);
5170 5187          }
5171 5188  }
5172 5189  
5173 5190  /*
5174 5191   * Array of readdir functions, indexed by /proc file type.
5175 5192   */
5176 5193  static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
5177 5194          pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
5178 5195          pr_readdir_fddir(), pr_readdir_fdinfodir(), pr_readdir_pathdir(),
5179 5196          pr_readdir_tmpldir(), pr_readdir_ctdir();
5180 5197  
5181 5198  static int (*pr_readdir_function[PR_NFILES])() = {
5182 5199          pr_readdir_procdir,     /* /proc                                */
5183 5200          pr_readdir_notdir,      /* /proc/self                           */
5184 5201          pr_readdir_piddir,      /* /proc/<pid>                          */
5185 5202          pr_readdir_notdir,      /* /proc/<pid>/as                       */
5186 5203          pr_readdir_notdir,      /* /proc/<pid>/ctl                      */
5187 5204          pr_readdir_notdir,      /* /proc/<pid>/status                   */
5188 5205          pr_readdir_notdir,      /* /proc/<pid>/lstatus                  */
5189 5206          pr_readdir_notdir,      /* /proc/<pid>/psinfo                   */
5190 5207          pr_readdir_notdir,      /* /proc/<pid>/lpsinfo                  */
5191 5208          pr_readdir_notdir,      /* /proc/<pid>/map                      */
5192 5209          pr_readdir_notdir,      /* /proc/<pid>/rmap                     */
5193 5210          pr_readdir_notdir,      /* /proc/<pid>/xmap                     */
5194 5211          pr_readdir_notdir,      /* /proc/<pid>/cred                     */
5195 5212          pr_readdir_notdir,      /* /proc/<pid>/sigact                   */
5196 5213          pr_readdir_notdir,      /* /proc/<pid>/auxv                     */
5197 5214  #if defined(__x86)
5198 5215          pr_readdir_notdir,      /* /proc/<pid>/ldt                      */
5199 5216  #endif
5200 5217          pr_readdir_notdir,      /* /proc/<pid>/argv                     */
5201 5218          pr_readdir_notdir,      /* /proc/<pid>/cmdline                  */
5202 5219          pr_readdir_notdir,      /* /proc/<pid>/usage                    */
5203 5220          pr_readdir_notdir,      /* /proc/<pid>/lusage                   */
5204 5221          pr_readdir_notdir,      /* /proc/<pid>/pagedata                 */
5205 5222          pr_readdir_notdir,      /* /proc/<pid>/watch                    */
5206 5223          pr_readdir_notdir,      /* /proc/<pid>/cwd                      */
5207 5224          pr_readdir_notdir,      /* /proc/<pid>/root                     */
5208 5225          pr_readdir_fddir,       /* /proc/<pid>/fd                       */
5209 5226          pr_readdir_notdir,      /* /proc/<pid>/fd/nn                    */
5210 5227          pr_readdir_fdinfodir,   /* /proc/<pid>/fdinfo                   */
5211 5228          pr_readdir_notdir,      /* /proc/<pid>/fdinfo/nn                */
5212 5229          pr_readdir_objectdir,   /* /proc/<pid>/object                   */
5213 5230          pr_readdir_notdir,      /* /proc/<pid>/object/xxx               */
5214 5231          pr_readdir_lwpdir,      /* /proc/<pid>/lwp                      */
5215 5232          pr_readdir_lwpiddir,    /* /proc/<pid>/lwp/<lwpid>              */
5216 5233          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpctl       */
5217 5234          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpname      */
5218 5235          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpstatus    */
5219 5236          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpsinfo     */
5220 5237          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/lwpusage     */
5221 5238          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/xregs        */
5222 5239          pr_readdir_tmpldir,     /* /proc/<pid>/lwp/<lwpid>/templates    */
5223 5240          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
5224 5241          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/spymaster    */
5225 5242  #if defined(__sparc)
5226 5243          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/gwindows     */
5227 5244          pr_readdir_notdir,      /* /proc/<pid>/lwp/<lwpid>/asrs         */
5228 5245  #endif
5229 5246          pr_readdir_notdir,      /* /proc/<pid>/priv                     */
5230 5247          pr_readdir_pathdir,     /* /proc/<pid>/path                     */
5231 5248          pr_readdir_notdir,      /* /proc/<pid>/path/xxx                 */
5232 5249          pr_readdir_ctdir,       /* /proc/<pid>/contracts                */
5233 5250          pr_readdir_notdir,      /* /proc/<pid>/contracts/<ctid>         */
5234 5251          pr_readdir_notdir,      /* /proc/<pid>/secflags                 */
5235 5252          pr_readdir_notdir,      /* old process file                     */
5236 5253          pr_readdir_notdir,      /* old lwp file                         */
5237 5254          pr_readdir_notdir,      /* old pagedata file                    */
5238 5255  };
5239 5256  
5240 5257  /* ARGSUSED */
5241 5258  static int
5242 5259  prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
5243 5260      caller_context_t *ct, int flags)
5244 5261  {
5245 5262          prnode_t *pnp = VTOP(vp);
5246 5263  
5247 5264          ASSERT(pnp->pr_type < PR_NFILES);
5248 5265  
5249 5266          /* XXX - Do we need to pass ct and flags? */
5250 5267          return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
5251 5268  }
5252 5269  
5253 5270  /* ARGSUSED */
5254 5271  static int
5255 5272  pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5256 5273  {
5257 5274          return (ENOTDIR);
5258 5275  }
5259 5276  
5260 5277  /* ARGSUSED */
5261 5278  static int
5262 5279  pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5263 5280  {
5264 5281          zoneid_t zoneid;
5265 5282          gfs_readdir_state_t gstate;
5266 5283          int error, eof = 0;
5267 5284          offset_t n;
5268 5285  
5269 5286          ASSERT(pnp->pr_type == PR_PROCDIR);
5270 5287  
5271 5288          zoneid = VTOZONE(PTOV(pnp))->zone_id;
5272 5289  
5273 5290          if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
5274 5291              PRROOTINO, PRROOTINO, 0)) != 0)
5275 5292                  return (error);
5276 5293  
5277 5294          /*
5278 5295           * Loop until user's request is satisfied or until all processes
5279 5296           * have been examined.
5280 5297           */
5281 5298          while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5282 5299                  uint_t pid;
5283 5300                  int pslot;
5284 5301                  proc_t *p;
5285 5302  
5286 5303                  /*
5287 5304                   * Find next entry.  Skip processes not visible where
5288 5305                   * this /proc was mounted.
5289 5306                   */
5290 5307                  mutex_enter(&pidlock);
5291 5308                  while (n < v.v_proc &&
5292 5309                      ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
5293 5310                      (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
5294 5311                      secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
5295 5312                          n++;
5296 5313  
5297 5314                  /*
5298 5315                   * Stop when entire proc table has been examined.
5299 5316                   */
5300 5317                  if (n >= v.v_proc) {
5301 5318                          mutex_exit(&pidlock);
5302 5319                          eof = 1;
5303 5320                          break;
5304 5321                  }
5305 5322  
5306 5323                  ASSERT(p->p_stat != 0);
5307 5324                  pid = p->p_pid;
5308 5325                  pslot = p->p_slot;
5309 5326                  mutex_exit(&pidlock);
5310 5327                  error = gfs_readdir_emitn(&gstate, uiop, n,
5311 5328                      pmkino(0, pslot, PR_PIDDIR), pid);
5312 5329                  if (error)
5313 5330                          break;
5314 5331          }
5315 5332  
5316 5333          return (gfs_readdir_fini(&gstate, error, eofp, eof));
5317 5334  }
5318 5335  
5319 5336  /* ARGSUSED */
5320 5337  static int
5321 5338  pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5322 5339  {
5323 5340          int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
5324 5341          prdirent_t dirent;
5325 5342          prdirent_t *dirp;
5326 5343          offset_t off;
5327 5344          int error;
5328 5345  
5329 5346          ASSERT(pnp->pr_type == PR_PIDDIR);
5330 5347  
5331 5348          if (uiop->uio_offset < 0 ||
5332 5349              uiop->uio_offset % sizeof (prdirent_t) != 0 ||
5333 5350              uiop->uio_resid < sizeof (prdirent_t))
5334 5351                  return (EINVAL);
5335 5352          if (pnp->pr_pcommon->prc_proc == NULL)
5336 5353                  return (ENOENT);
5337 5354          if (uiop->uio_offset >= sizeof (piddir))
5338 5355                  goto out;
5339 5356  
5340 5357          /*
5341 5358           * Loop until user's request is satisfied, omitting some
5342 5359           * files along the way if the process is a zombie.
5343 5360           */
5344 5361          for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
5345 5362              uiop->uio_resid >= sizeof (prdirent_t) &&
5346 5363              dirp < &piddir[NPIDDIRFILES+2];
5347 5364              uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5348 5365                  off = uiop->uio_offset;
5349 5366                  if (zombie) {
5350 5367                          switch (dirp->d_ino) {
5351 5368                          case PR_PIDDIR:
5352 5369                          case PR_PROCDIR:
5353 5370                          case PR_PSINFO:
5354 5371                          case PR_USAGE:
5355 5372                          case PR_ARGV:
5356 5373                          case PR_CMDLINE:
5357 5374                                  break;
5358 5375                          default:
5359 5376                                  continue;
5360 5377                          }
5361 5378                  }
5362 5379                  bcopy(dirp, &dirent, sizeof (prdirent_t));
5363 5380                  if (dirent.d_ino == PR_PROCDIR)
5364 5381                          dirent.d_ino = PRROOTINO;
5365 5382                  else
5366 5383                          dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
5367 5384                              dirent.d_ino);
5368 5385                  if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5369 5386                      UIO_READ, uiop)) != 0)
5370 5387                          return (error);
5371 5388          }
5372 5389  out:
5373 5390          if (eofp)
5374 5391                  *eofp = (uiop->uio_offset >= sizeof (piddir));
5375 5392          return (0);
5376 5393  }
5377 5394  
5378 5395  static void
5379 5396  rebuild_objdir(struct as *as)
5380 5397  {
5381 5398          struct seg *seg;
5382 5399          vnode_t *vp;
5383 5400          vattr_t vattr;
5384 5401          vnode_t **dir;
5385 5402          ulong_t nalloc;
5386 5403          ulong_t nentries;
5387 5404          int i, j;
5388 5405          ulong_t nold, nnew;
5389 5406  
5390 5407          ASSERT(AS_WRITE_HELD(as));
5391 5408  
5392 5409          if (as->a_updatedir == 0 && as->a_objectdir != NULL)
5393 5410                  return;
5394 5411          as->a_updatedir = 0;
5395 5412  
5396 5413          if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
5397 5414              (seg = AS_SEGFIRST(as)) == NULL)    /* can't happen? */
5398 5415                  return;
5399 5416  
5400 5417          /*
5401 5418           * Allocate space for the new object directory.
5402 5419           * (This is usually about two times too many entries.)
5403 5420           */
5404 5421          nalloc = (nalloc + 0xf) & ~0xf;         /* multiple of 16 */
5405 5422          dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
5406 5423  
5407 5424          /* fill in the new directory with desired entries */
5408 5425          nentries = 0;
5409 5426          do {
5410 5427                  vattr.va_mask = AT_FSID|AT_NODEID;
5411 5428                  if (seg->s_ops == &segvn_ops &&
5412 5429                      SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
5413 5430                      vp != NULL && vp->v_type == VREG &&
5414 5431                      VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
5415 5432                          for (i = 0; i < nentries; i++)
5416 5433                                  if (vp == dir[i])
5417 5434                                          break;
5418 5435                          if (i == nentries) {
5419 5436                                  ASSERT(nentries < nalloc);
5420 5437                                  dir[nentries++] = vp;
5421 5438                          }
5422 5439                  }
5423 5440          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
5424 5441  
5425 5442          if (as->a_objectdir == NULL) {  /* first time */
5426 5443                  as->a_objectdir = dir;
5427 5444                  as->a_sizedir = nalloc;
5428 5445                  return;
5429 5446          }
5430 5447  
5431 5448          /*
5432 5449           * Null out all of the defunct entries in the old directory.
5433 5450           */
5434 5451          nold = 0;
5435 5452          nnew = nentries;
5436 5453          for (i = 0; i < as->a_sizedir; i++) {
5437 5454                  if ((vp = as->a_objectdir[i]) != NULL) {
5438 5455                          for (j = 0; j < nentries; j++) {
5439 5456                                  if (vp == dir[j]) {
5440 5457                                          dir[j] = NULL;
5441 5458                                          nnew--;
5442 5459                                          break;
5443 5460                                  }
5444 5461                          }
5445 5462                          if (j == nentries)
5446 5463                                  as->a_objectdir[i] = NULL;
5447 5464                          else
5448 5465                                  nold++;
5449 5466                  }
5450 5467          }
5451 5468  
5452 5469          if (nold + nnew > as->a_sizedir) {
5453 5470                  /*
5454 5471                   * Reallocate the old directory to have enough
5455 5472                   * space for the old and new entries combined.
5456 5473                   * Round up to the next multiple of 16.
5457 5474                   */
5458 5475                  ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
5459 5476                  vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
5460 5477                      KM_SLEEP);
5461 5478                  bcopy(as->a_objectdir, newdir,
5462 5479                      as->a_sizedir * sizeof (vnode_t *));
5463 5480                  kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
5464 5481                  as->a_objectdir = newdir;
5465 5482                  as->a_sizedir = newsize;
5466 5483          }
5467 5484  
5468 5485          /*
5469 5486           * Move all new entries to the old directory and
5470 5487           * deallocate the space used by the new directory.
5471 5488           */
5472 5489          if (nnew) {
5473 5490                  for (i = 0, j = 0; i < nentries; i++) {
5474 5491                          if ((vp = dir[i]) == NULL)
5475 5492                                  continue;
5476 5493                          for (; j < as->a_sizedir; j++) {
5477 5494                                  if (as->a_objectdir[j] != NULL)
5478 5495                                          continue;
5479 5496                                  as->a_objectdir[j++] = vp;
5480 5497                                  break;
5481 5498                          }
5482 5499                  }
5483 5500          }
5484 5501          kmem_free(dir, nalloc * sizeof (vnode_t *));
5485 5502  }
5486 5503  
5487 5504  /*
5488 5505   * Return the vnode from a slot in the process's object directory.
5489 5506   * The caller must have locked the process's address space.
5490 5507   * The only caller is below, in pr_readdir_objectdir().
5491 5508   */
5492 5509  static vnode_t *
5493 5510  obj_entry(struct as *as, int slot)
5494 5511  {
5495 5512          ASSERT(AS_LOCK_HELD(as));
5496 5513          if (as->a_objectdir == NULL)
5497 5514                  return (NULL);
5498 5515          ASSERT(slot < as->a_sizedir);
5499 5516          return (as->a_objectdir[slot]);
5500 5517  }
5501 5518  
5502 5519  /* ARGSUSED */
5503 5520  static int
5504 5521  pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5505 5522  {
5506 5523          gfs_readdir_state_t gstate;
5507 5524          int error, eof = 0;
5508 5525          offset_t n;
5509 5526          int pslot;
5510 5527          size_t objdirsize;
5511 5528          proc_t *p;
5512 5529          struct as *as;
5513 5530          vnode_t *vp;
5514 5531  
5515 5532          ASSERT(pnp->pr_type == PR_OBJECTDIR);
5516 5533  
5517 5534          if ((error = prlock(pnp, ZNO)) != 0)
5518 5535                  return (error);
5519 5536          p = pnp->pr_common->prc_proc;
5520 5537          pslot = p->p_slot;
5521 5538  
5522 5539          /*
5523 5540           * We drop p_lock before grabbing the address space lock
5524 5541           * in order to avoid a deadlock with the clock thread.
5525 5542           * The process will not disappear and its address space
5526 5543           * will not change because it is marked P_PR_LOCK.
5527 5544           */
5528 5545          mutex_exit(&p->p_lock);
5529 5546  
5530 5547          if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
5531 5548              pmkino(0, pslot, PR_PIDDIR),
5532 5549              pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
5533 5550                  mutex_enter(&p->p_lock);
5534 5551                  prunlock(pnp);
5535 5552                  return (error);
5536 5553          }
5537 5554  
5538 5555          if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5539 5556                  as = NULL;
5540 5557                  objdirsize = 0;
5541 5558          }
5542 5559  
5543 5560          /*
5544 5561           * Loop until user's request is satisfied or until
5545 5562           * all mapped objects have been examined. Cannot hold
5546 5563           * the address space lock for the following call as
5547 5564           * gfs_readdir_pred() utimately causes a call to uiomove().
5548 5565           */
5549 5566          while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5550 5567                  vattr_t vattr;
5551 5568                  char str[64];
5552 5569  
5553 5570                  /*
5554 5571                   * Set the correct size of the directory just
5555 5572                   * in case the process has changed it's address
5556 5573                   * space via mmap/munmap calls.
5557 5574                   */
5558 5575                  if (as != NULL) {
5559 5576                          AS_LOCK_ENTER(as, RW_WRITER);
5560 5577                          if (as->a_updatedir)
5561 5578                                  rebuild_objdir(as);
5562 5579                          objdirsize = as->a_sizedir;
5563 5580                  }
5564 5581  
5565 5582                  /*
5566 5583                   * Find next object.
5567 5584                   */
5568 5585                  vattr.va_mask = AT_FSID | AT_NODEID;
5569 5586                  while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
5570 5587                      (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)
5571 5588                      != 0))) {
5572 5589                          vattr.va_mask = AT_FSID | AT_NODEID;
5573 5590                          n++;
5574 5591                  }
5575 5592  
5576 5593                  if (as != NULL)
5577 5594                          AS_LOCK_EXIT(as);
5578 5595  
5579 5596                  /*
5580 5597                   * Stop when all objects have been reported.
5581 5598                   */
5582 5599                  if (n >= objdirsize) {
5583 5600                          eof = 1;
5584 5601                          break;
5585 5602                  }
5586 5603  
5587 5604                  if (vp == p->p_exec)
5588 5605                          (void) strcpy(str, "a.out");
5589 5606                  else
5590 5607                          pr_object_name(str, vp, &vattr);
5591 5608  
5592 5609                  error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
5593 5610                      str, 0);
5594 5611  
5595 5612                  if (error)
5596 5613                          break;
5597 5614          }
5598 5615  
5599 5616          mutex_enter(&p->p_lock);
5600 5617          prunlock(pnp);
5601 5618  
5602 5619          return (gfs_readdir_fini(&gstate, error, eofp, eof));
5603 5620  }
5604 5621  
5605 5622  /* ARGSUSED */
5606 5623  static int
5607 5624  pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5608 5625  {
5609 5626          gfs_readdir_state_t gstate;
5610 5627          int error, eof = 0;
5611 5628          offset_t tslot;
5612 5629          proc_t *p;
5613 5630          int pslot;
5614 5631          lwpdir_t *lwpdir;
5615 5632          int lwpdirsize;
5616 5633  
5617 5634          ASSERT(pnp->pr_type == PR_LWPDIR);
5618 5635  
5619 5636          p = pr_p_lock(pnp);
5620 5637          mutex_exit(&pr_pidlock);
5621 5638          if (p == NULL)
5622 5639                  return (ENOENT);
5623 5640          ASSERT(p == pnp->pr_common->prc_proc);
5624 5641          pslot = p->p_slot;
5625 5642          lwpdir = p->p_lwpdir;
5626 5643          lwpdirsize = p->p_lwpdir_sz;
5627 5644  
5628 5645          /*
5629 5646           * Drop p->p_lock so we can safely do uiomove().
5630 5647           * The lwp directory will not change because
5631 5648           * we have the process locked with P_PR_LOCK.
5632 5649           */
5633 5650          mutex_exit(&p->p_lock);
5634 5651  
5635 5652  
5636 5653          if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5637 5654              pmkino(0, pslot, PR_PIDDIR),
5638 5655              pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
5639 5656                  mutex_enter(&p->p_lock);
5640 5657                  prunlock(pnp);
5641 5658                  return (error);
5642 5659          }
5643 5660  
5644 5661          /*
5645 5662           * Loop until user's request is satisfied or until all lwps
5646 5663           * have been examined.
5647 5664           */
5648 5665          while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
5649 5666                  lwpent_t *lep;
5650 5667                  uint_t tid;
5651 5668  
5652 5669                  /*
5653 5670                   * Find next LWP.
5654 5671                   */
5655 5672                  while (tslot < lwpdirsize &&
5656 5673                      ((lep = lwpdir[tslot].ld_entry) == NULL))
5657 5674                          tslot++;
5658 5675                  /*
5659 5676                   * Stop when all lwps have been reported.
5660 5677                   */
5661 5678                  if (tslot >= lwpdirsize) {
5662 5679                          eof = 1;
5663 5680                          break;
5664 5681                  }
5665 5682  
5666 5683                  tid = lep->le_lwpid;
5667 5684                  error = gfs_readdir_emitn(&gstate, uiop, tslot,
5668 5685                      pmkino(tslot, pslot, PR_LWPIDDIR), tid);
5669 5686                  if (error)
5670 5687                          break;
5671 5688          }
5672 5689  
5673 5690          mutex_enter(&p->p_lock);
5674 5691          prunlock(pnp);
5675 5692  
5676 5693          return (gfs_readdir_fini(&gstate, error, eofp, eof));
5677 5694  }
5678 5695  
5679 5696  /* ARGSUSED */
5680 5697  static int
5681 5698  pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5682 5699  {
5683 5700          prcommon_t *pcp = pnp->pr_common;
5684 5701          int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
5685 5702          prdirent_t dirent;
5686 5703          prdirent_t *dirp;
5687 5704          offset_t off;
5688 5705          int error;
5689 5706          int pslot;
5690 5707          int tslot;
5691 5708  
5692 5709          ASSERT(pnp->pr_type == PR_LWPIDDIR);
5693 5710  
5694 5711          if (uiop->uio_offset < 0 ||
5695 5712              uiop->uio_offset % sizeof (prdirent_t) != 0 ||
5696 5713              uiop->uio_resid < sizeof (prdirent_t))
5697 5714                  return (EINVAL);
5698 5715          if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
5699 5716                  return (ENOENT);
5700 5717          if (uiop->uio_offset >= sizeof (lwpiddir))
5701 5718                  goto out;
5702 5719  
5703 5720          /*
5704 5721           * Loop until user's request is satisfied, omitting some files
5705 5722           * along the way if the lwp is a zombie and also depending
5706 5723           * on the data model of the process.
5707 5724           */
5708 5725          pslot = pcp->prc_slot;
5709 5726          tslot = pcp->prc_tslot;
5710 5727          for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
5711 5728              uiop->uio_resid >= sizeof (prdirent_t) &&
5712 5729              dirp < &lwpiddir[NLWPIDDIRFILES+2];
5713 5730              uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5714 5731                  off = uiop->uio_offset;
5715 5732                  if (zombie) {
5716 5733                          switch (dirp->d_ino) {
5717 5734                          case PR_LWPIDDIR:
5718 5735                          case PR_LWPDIR:
5719 5736                          case PR_LWPSINFO:
5720 5737                                  break;
5721 5738                          default:
5722 5739                                  continue;
5723 5740                          }
5724 5741                  }
5725 5742  #if defined(__sparc)
5726 5743                  /* the asrs file exists only for sparc v9 _LP64 processes */
5727 5744                  if (dirp->d_ino == PR_ASRS &&
5728 5745                      pcp->prc_datamodel != DATAMODEL_LP64)
5729 5746                          continue;
5730 5747  #endif
5731 5748                  bcopy(dirp, &dirent, sizeof (prdirent_t));
5732 5749                  if (dirent.d_ino == PR_LWPDIR)
5733 5750                          dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5734 5751                  else
5735 5752                          dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5736 5753                  if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5737 5754                      UIO_READ, uiop)) != 0)
5738 5755                          return (error);
5739 5756          }
5740 5757  out:
5741 5758          if (eofp)
5742 5759                  *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5743 5760          return (0);
5744 5761  }
5745 5762  
5746 5763  /*
5747 5764   * Helper function for reading a directory which lists open file desciptors
5748 5765   */
5749 5766  static int
5750 5767  pr_readdir_fdlist(prnode_t *pnp, uio_t *uiop, int *eofp,
5751 5768      prnodetype_t dirtype, prnodetype_t entrytype)
5752 5769  {
5753 5770          gfs_readdir_state_t gstate;
5754 5771          int error, eof = 0;
5755 5772          offset_t n;
5756 5773          proc_t *p;
5757 5774          int pslot;
5758 5775          int fddirsize;
5759 5776          uf_info_t *fip;
5760 5777  
5761 5778          if ((error = prlock(pnp, ZNO)) != 0)
5762 5779                  return (error);
5763 5780          p = pnp->pr_common->prc_proc;
5764 5781          pslot = p->p_slot;
5765 5782          fip = P_FINFO(p);
5766 5783          mutex_exit(&p->p_lock);
5767 5784  
5768 5785          if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5769 5786              pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, dirtype), 0)) != 0) {
5770 5787                  mutex_enter(&p->p_lock);
5771 5788                  prunlock(pnp);
5772 5789                  return (error);
5773 5790          }
5774 5791  
5775 5792          mutex_enter(&fip->fi_lock);
5776 5793          if ((p->p_flag & SSYS) || p->p_as == &kas)
5777 5794                  fddirsize = 0;
5778 5795          else
5779 5796                  fddirsize = fip->fi_nfiles;
5780 5797  
5781 5798          /*
5782 5799           * Loop until user's request is satisfied or until
5783 5800           * all file descriptors have been examined.
5784 5801           */
5785 5802          while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5786 5803                  /*
5787 5804                   * Find next fd.
5788 5805                   */
5789 5806                  while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5790 5807                          n++;
5791 5808                  /*
5792 5809                   * Stop when all fds have been reported.
5793 5810                   */
5794 5811                  if (n >= fddirsize) {
5795 5812                          eof = 1;
5796 5813                          break;
5797 5814                  }
5798 5815  
5799 5816                  error = gfs_readdir_emitn(&gstate, uiop, n,
5800 5817                      pmkino(n, pslot, entrytype), n);
5801 5818                  if (error)
5802 5819                          break;
5803 5820          }
5804 5821  
5805 5822          mutex_exit(&fip->fi_lock);
5806 5823          mutex_enter(&p->p_lock);
5807 5824          prunlock(pnp);
5808 5825  
5809 5826          return (gfs_readdir_fini(&gstate, error, eofp, eof));
5810 5827  }
5811 5828  
5812 5829  static int
5813 5830  pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5814 5831  {
5815 5832  
5816 5833          ASSERT(pnp->pr_type == PR_FDDIR);
5817 5834  
5818 5835          return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FD));
5819 5836  }
5820 5837  
5821 5838  static int
5822 5839  pr_readdir_fdinfodir(prnode_t *pnp, uio_t *uiop, int *eofp)
5823 5840  {
5824 5841  
5825 5842          ASSERT(pnp->pr_type == PR_FDINFODIR);
5826 5843  
5827 5844          return (pr_readdir_fdlist(pnp, uiop, eofp, pnp->pr_type, PR_FDINFO));
5828 5845  }
5829 5846  
5830 5847  /* ARGSUSED */
5831 5848  static int
5832 5849  pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5833 5850  {
5834 5851          longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5835 5852          dirent64_t *dirent = (dirent64_t *)bp;
5836 5853          int reclen;
5837 5854          ssize_t oresid;
5838 5855          offset_t off, idx;
5839 5856          int error = 0;
5840 5857          proc_t *p;
5841 5858          int fd, obj;
5842 5859          int pslot;
5843 5860          int fddirsize;
5844 5861          uf_info_t *fip;
5845 5862          struct as *as = NULL;
5846 5863          size_t objdirsize;
5847 5864          vattr_t vattr;
5848 5865          vnode_t *vp;
5849 5866  
5850 5867          ASSERT(pnp->pr_type == PR_PATHDIR);
5851 5868  
5852 5869          if (uiop->uio_offset < 0 ||
5853 5870              uiop->uio_resid <= 0 ||
5854 5871              (uiop->uio_offset % PRSDSIZE) != 0)
5855 5872                  return (EINVAL);
5856 5873          oresid = uiop->uio_resid;
5857 5874          bzero(bp, sizeof (bp));
5858 5875  
5859 5876          if ((error = prlock(pnp, ZNO)) != 0)
5860 5877                  return (error);
5861 5878          p = pnp->pr_common->prc_proc;
5862 5879          fip = P_FINFO(p);
5863 5880          pslot = p->p_slot;
5864 5881          mutex_exit(&p->p_lock);
5865 5882  
5866 5883          if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5867 5884                  as = NULL;
5868 5885                  objdirsize = 0;
5869 5886          } else {
5870 5887                  AS_LOCK_ENTER(as, RW_WRITER);
5871 5888                  if (as->a_updatedir)
5872 5889                          rebuild_objdir(as);
5873 5890                  objdirsize = as->a_sizedir;
5874 5891                  AS_LOCK_EXIT(as);
5875 5892                  as = NULL;
5876 5893          }
5877 5894  
5878 5895          mutex_enter(&fip->fi_lock);
5879 5896          if ((p->p_flag & SSYS) || p->p_as == &kas)
5880 5897                  fddirsize = 0;
5881 5898          else
5882 5899                  fddirsize = fip->fi_nfiles;
5883 5900  
5884 5901          for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
5885 5902                  /*
5886 5903                   * There are 4 special files in the path directory: ".", "..",
5887 5904                   * "root", and "cwd".  We handle those specially here.
5888 5905                   */
5889 5906                  off = uiop->uio_offset;
5890 5907                  idx = off / PRSDSIZE;
5891 5908                  if (off == 0) {                         /* "." */
5892 5909                          dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
5893 5910                          dirent->d_name[0] = '.';
5894 5911                          dirent->d_name[1] = '\0';
5895 5912                          reclen = DIRENT64_RECLEN(1);
5896 5913                  } else if (idx == 1) {                  /* ".." */
5897 5914                          dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
5898 5915                          dirent->d_name[0] = '.';
5899 5916                          dirent->d_name[1] = '.';
5900 5917                          dirent->d_name[2] = '\0';
5901 5918                          reclen = DIRENT64_RECLEN(2);
5902 5919                  } else if (idx == 2) {                  /* "root" */
5903 5920                          dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5904 5921                          (void) strcpy(dirent->d_name, "root");
5905 5922                          reclen = DIRENT64_RECLEN(4);
5906 5923                  } else if (idx == 3) {                  /* "cwd" */
5907 5924                          dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5908 5925                          (void) strcpy(dirent->d_name, "cwd");
5909 5926                          reclen = DIRENT64_RECLEN(3);
5910 5927                  } else if (idx < 4 + fddirsize) {
5911 5928                          /*
5912 5929                           * In this case, we have one of the file descriptors.
5913 5930                           */
5914 5931                          fd = idx - 4;
5915 5932                          if (fip->fi_list[fd].uf_file == NULL)
5916 5933                                  continue;
5917 5934                          dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5918 5935                          (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
5919 5936                          reclen = DIRENT64_RECLEN(PLNSIZ);
5920 5937                  } else if (idx < 4 + fddirsize + objdirsize) {
5921 5938                          if (fip != NULL) {
5922 5939                                  mutex_exit(&fip->fi_lock);
5923 5940                                  fip = NULL;
5924 5941                          }
5925 5942  
5926 5943                          /*
5927 5944                           * We drop p_lock before grabbing the address space lock
5928 5945                           * in order to avoid a deadlock with the clock thread.
5929 5946                           * The process will not disappear and its address space
5930 5947                           * will not change because it is marked P_PR_LOCK.
5931 5948                           */
5932 5949                          if (as == NULL) {
5933 5950                                  as = p->p_as;
5934 5951                                  AS_LOCK_ENTER(as, RW_WRITER);
5935 5952                          }
5936 5953  
5937 5954                          if (as->a_updatedir) {
5938 5955                                  rebuild_objdir(as);
5939 5956                                  objdirsize = as->a_sizedir;
5940 5957                          }
5941 5958  
5942 5959                          obj = idx - 4 - fddirsize;
5943 5960                          if ((vp = obj_entry(as, obj)) == NULL)
5944 5961                                  continue;
5945 5962                          vattr.va_mask = AT_FSID|AT_NODEID;
5946 5963                          if (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) != 0)
5947 5964                                  continue;
5948 5965                          if (vp == p->p_exec)
5949 5966                                  (void) strcpy(dirent->d_name, "a.out");
5950 5967                          else
5951 5968                                  pr_object_name(dirent->d_name, vp, &vattr);
5952 5969                          dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5953 5970                          reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
5954 5971                  } else {
5955 5972                          break;
5956 5973                  }
5957 5974  
5958 5975                  dirent->d_off = uiop->uio_offset + PRSDSIZE;
5959 5976                  dirent->d_reclen = (ushort_t)reclen;
5960 5977                  if (reclen > uiop->uio_resid) {
5961 5978                          /*
5962 5979                           * Error if no entries have been returned yet.
5963 5980                           */
5964 5981                          if (uiop->uio_resid == oresid)
5965 5982                                  error = EINVAL;
5966 5983                          break;
5967 5984                  }
5968 5985                  /*
5969 5986                   * Drop the address space lock to do the uiomove().
5970 5987                   */
5971 5988                  if (as != NULL)
5972 5989                          AS_LOCK_EXIT(as);
5973 5990  
5974 5991                  error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
5975 5992                  if (as != NULL)
5976 5993                          AS_LOCK_ENTER(as, RW_WRITER);
5977 5994  
5978 5995                  if (error)
5979 5996                          break;
5980 5997          }
5981 5998  
5982 5999          if (error == 0 && eofp)
5983 6000                  *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
5984 6001  
5985 6002          if (fip != NULL)
5986 6003                  mutex_exit(&fip->fi_lock);
5987 6004          if (as != NULL)
5988 6005                  AS_LOCK_EXIT(as);
5989 6006          mutex_enter(&p->p_lock);
5990 6007          prunlock(pnp);
5991 6008          return (error);
5992 6009  }
5993 6010  
5994 6011  static int
5995 6012  pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
5996 6013  {
5997 6014          proc_t *p;
5998 6015          int pslot, tslot;
5999 6016          gfs_readdir_state_t gstate;
6000 6017          int error, eof = 0;
6001 6018          offset_t n;
6002 6019  
6003 6020          ASSERT(pnp->pr_type == PR_TMPLDIR);
6004 6021  
6005 6022          if ((error = prlock(pnp, ZNO)) != 0)
6006 6023                  return (error);
6007 6024          p = pnp->pr_common->prc_proc;
6008 6025          pslot = pnp->pr_common->prc_slot;
6009 6026          tslot = pnp->pr_common->prc_tslot;
6010 6027          mutex_exit(&p->p_lock);
6011 6028  
6012 6029          if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
6013 6030              pmkino(tslot, pslot, PR_LWPDIR),
6014 6031              pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
6015 6032                  mutex_enter(&p->p_lock);
6016 6033                  prunlock(pnp);
6017 6034                  return (error);
6018 6035          }
6019 6036  
6020 6037          while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
6021 6038                  /*
6022 6039                   * Check for an active template.  Reading a directory's
6023 6040                   * contents is already racy, so we don't bother taking
6024 6041                   * any locks.
6025 6042                   */
6026 6043                  while (n < ct_ntypes &&
6027 6044                      pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
6028 6045                          n++;
6029 6046                  /*
6030 6047                   * Stop when all types have been reported.
6031 6048                   */
6032 6049                  if (n >= ct_ntypes) {
6033 6050                          eof = 1;
6034 6051                          break;
6035 6052                  }
6036 6053                  /*
6037 6054                   * The pmkino invocation below will need to be updated
6038 6055                   * when we create our fifth contract type.
6039 6056                   */
6040 6057                  ASSERT(ct_ntypes <= 4);
6041 6058                  error = gfs_readdir_emit(&gstate, uiop, n,
6042 6059                      pmkino((tslot << 2) | n, pslot, PR_TMPL),
6043 6060                      ct_types[n]->ct_type_name, 0);
6044 6061                  if (error)
6045 6062                          break;
6046 6063          }
6047 6064  
6048 6065          mutex_enter(&p->p_lock);
6049 6066          prunlock(pnp);
6050 6067  
6051 6068          return (gfs_readdir_fini(&gstate, error, eofp, eof));
6052 6069  }
6053 6070  
6054 6071  static int
6055 6072  pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
6056 6073  {
6057 6074          proc_t *p;
6058 6075          int pslot;
6059 6076          gfs_readdir_state_t gstate;
6060 6077          int error, eof = 0;
6061 6078          offset_t n;
6062 6079          uint64_t zid;
6063 6080  
6064 6081          ASSERT(pnp->pr_type == PR_CTDIR);
6065 6082  
6066 6083          if ((error = prlock(pnp, ZNO)) != 0)
6067 6084                  return (error);
6068 6085          p = pnp->pr_common->prc_proc;
6069 6086          pslot = p->p_slot;
6070 6087          mutex_exit(&p->p_lock);
6071 6088  
6072 6089          if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
6073 6090              pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
6074 6091                  mutex_enter(&p->p_lock);
6075 6092                  prunlock(pnp);
6076 6093                  return (error);
6077 6094          }
6078 6095  
6079 6096          zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
6080 6097          while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
6081 6098                  id_t next = contract_plookup(p, n, zid);
6082 6099                  if (next == -1) {
6083 6100                          eof = 1;
6084 6101                          break;
6085 6102                  }
6086 6103                  error = gfs_readdir_emitn(&gstate, uiop, next,
6087 6104                      pmkino(next, pslot, PR_CT), next);
6088 6105                  if (error)
6089 6106                          break;
6090 6107          }
6091 6108  
6092 6109          mutex_enter(&p->p_lock);
6093 6110          prunlock(pnp);
6094 6111  
6095 6112          return (gfs_readdir_fini(&gstate, error, eofp, eof));
6096 6113  }
6097 6114  
6098 6115  /* ARGSUSED */
6099 6116  static int
6100 6117  prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
6101 6118  {
6102 6119          return (0);
6103 6120  }
6104 6121  
6105 6122  /*
6106 6123   * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
6107 6124   */
6108 6125  static void
6109 6126  pr_list_unlink(vnode_t *pvp, vnode_t **listp)
6110 6127  {
6111 6128          vnode_t *vp;
6112 6129          prnode_t *pnp;
6113 6130  
6114 6131          while ((vp = *listp) != NULL) {
6115 6132                  pnp = VTOP(vp);
6116 6133                  if (vp == pvp) {
6117 6134                          *listp = pnp->pr_next;
6118 6135                          pnp->pr_next = NULL;
6119 6136                          break;
6120 6137                  }
6121 6138                  listp = &pnp->pr_next;
6122 6139          }
6123 6140  }
6124 6141  
6125 6142  /* ARGSUSED */
6126 6143  static void
6127 6144  prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
6128 6145  {
6129 6146          prnode_t *pnp = VTOP(vp);
6130 6147          prnodetype_t type = pnp->pr_type;
6131 6148          proc_t *p;
6132 6149          vnode_t *dp;
6133 6150          vnode_t *ovp = NULL;
6134 6151          prnode_t *opnp = NULL;
6135 6152  
6136 6153          switch (type) {
6137 6154          case PR_OBJECT:
6138 6155          case PR_FD:
6139 6156          case PR_FDINFO:
6140 6157          case PR_SELF:
6141 6158          case PR_PATH:
6142 6159                  /* These are not linked into the usual lists */
6143 6160                  ASSERT(vp->v_count == 1);
6144 6161                  if ((dp = pnp->pr_parent) != NULL)
6145 6162                          VN_RELE(dp);
6146 6163                  prfreenode(pnp);
6147 6164                  return;
6148 6165          default:
6149 6166                  break;
6150 6167          }
6151 6168  
6152 6169          mutex_enter(&pr_pidlock);
6153 6170          if (pnp->pr_pcommon == NULL)
6154 6171                  p = NULL;
6155 6172          else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
6156 6173                  mutex_enter(&p->p_lock);
6157 6174          mutex_enter(&vp->v_lock);
6158 6175  
6159 6176          if (type == PR_PROCDIR || vp->v_count > 1) {
6160 6177                  VN_RELE_LOCKED(vp);
6161 6178                  mutex_exit(&vp->v_lock);
6162 6179                  if (p != NULL)
6163 6180                          mutex_exit(&p->p_lock);
6164 6181                  mutex_exit(&pr_pidlock);
6165 6182                  return;
6166 6183          }
6167 6184  
6168 6185          if ((dp = pnp->pr_parent) != NULL) {
6169 6186                  prnode_t *dpnp;
6170 6187  
6171 6188                  switch (type) {
6172 6189                  case PR_PIDFILE:
6173 6190                  case PR_LWPIDFILE:
6174 6191                  case PR_OPAGEDATA:
6175 6192                          break;
6176 6193                  default:
6177 6194                          dpnp = VTOP(dp);
6178 6195                          mutex_enter(&dpnp->pr_mutex);
6179 6196                          if (dpnp->pr_files != NULL &&
6180 6197                              dpnp->pr_files[pnp->pr_index] == vp)
6181 6198                                  dpnp->pr_files[pnp->pr_index] = NULL;
6182 6199                          mutex_exit(&dpnp->pr_mutex);
6183 6200                          break;
6184 6201                  }
6185 6202                  pnp->pr_parent = NULL;
6186 6203          }
6187 6204  
6188 6205          ASSERT(vp->v_count == 1);
6189 6206  
6190 6207          /*
6191 6208           * If we allocated an old /proc/pid node, free it too.
6192 6209           */
6193 6210          if (pnp->pr_pidfile != NULL) {
6194 6211                  ASSERT(type == PR_PIDDIR);
6195 6212                  ovp = pnp->pr_pidfile;
6196 6213                  opnp = VTOP(ovp);
6197 6214                  ASSERT(opnp->pr_type == PR_PIDFILE);
6198 6215                  pnp->pr_pidfile = NULL;
6199 6216          }
6200 6217  
6201 6218          mutex_exit(&pr_pidlock);
6202 6219  
6203 6220          if (p != NULL) {
6204 6221                  /*
6205 6222                   * Remove the vnodes from the lists of
6206 6223                   * /proc vnodes for the process.
6207 6224                   */
6208 6225                  int slot;
6209 6226  
6210 6227                  switch (type) {
6211 6228                  case PR_PIDDIR:
6212 6229                          pr_list_unlink(vp, &p->p_trace);
6213 6230                          break;
6214 6231                  case PR_LWPIDDIR:
6215 6232                          if ((slot = pnp->pr_common->prc_tslot) != -1) {
6216 6233                                  lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
6217 6234                                  pr_list_unlink(vp, &lep->le_trace);
6218 6235                          }
6219 6236                          break;
6220 6237                  default:
6221 6238                          pr_list_unlink(vp, &p->p_plist);
6222 6239                          break;
6223 6240                  }
6224 6241                  if (ovp != NULL)
6225 6242                          pr_list_unlink(ovp, &p->p_plist);
6226 6243                  mutex_exit(&p->p_lock);
6227 6244          }
6228 6245  
6229 6246          mutex_exit(&vp->v_lock);
6230 6247  
6231 6248          if (type == PR_CT && pnp->pr_contract != NULL) {
6232 6249                  contract_rele(pnp->pr_contract);
6233 6250                  pnp->pr_contract = NULL;
6234 6251          }
6235 6252  
6236 6253          if (opnp != NULL)
6237 6254                  prfreenode(opnp);
6238 6255          prfreenode(pnp);
6239 6256          if (dp != NULL) {
6240 6257                  VN_RELE(dp);
6241 6258          }
6242 6259  }
6243 6260  
6244 6261  /* ARGSUSED */
6245 6262  static int
6246 6263  prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
6247 6264  {
6248 6265          return (0);
6249 6266  }
6250 6267  
6251 6268  /*
6252 6269   * We use the p_execdir member of proc_t to expand the %d token in core file
6253 6270   * paths (the directory path for the executable that dumped core; see
6254 6271   * coreadm(8) for details). We'd like gcore(1) to be able to expand %d in
6255 6272   * the same way as core dumping from the kernel, but there's no convenient
6256 6273   * and comprehensible way to export the path name for p_execdir. To solve
6257 6274   * this, we try to find the actual path to the executable that was used. In
6258 6275   * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
6259 6276   * flag, and use that here to indicate that more work is needed beyond the
6260 6277   * call to vnodetopath().
6261 6278   */
6262 6279  static int
6263 6280  prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
6264 6281  {
6265 6282          proc_t *p;
6266 6283          vnode_t *vp, *execvp, *vrootp;
6267 6284          int ret;
6268 6285          size_t len;
6269 6286          dirent64_t *dp;
6270 6287          size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
6271 6288          char *dbuf;
6272 6289  
6273 6290          p = curproc;
6274 6291          mutex_enter(&p->p_lock);
6275 6292          if ((vrootp = PTOU(p)->u_rdir) == NULL)
6276 6293                  vrootp = rootdir;
6277 6294          VN_HOLD(vrootp);
6278 6295          mutex_exit(&p->p_lock);
6279 6296  
6280 6297          ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
6281 6298  
6282 6299          /*
6283 6300           * If PR_AOUT isn't set, then we looked up the path for the vnode;
6284 6301           * otherwise, we looked up the path for (what we believe to be) the
6285 6302           * containing directory.
6286 6303           */
6287 6304          if ((pnp->pr_flags & PR_AOUT) == 0) {
6288 6305                  VN_RELE(vrootp);
6289 6306                  return (ret);
6290 6307          }
6291 6308  
6292 6309          /*
6293 6310           * Fail if there's a problem locking the process. This will only
6294 6311           * occur if the process is changing so the information we would
6295 6312           * report would already be invalid.
6296 6313           */
6297 6314          if (prlock(pnp, ZNO) != 0) {
6298 6315                  VN_RELE(vrootp);
6299 6316                  return (EIO);
6300 6317          }
6301 6318  
6302 6319          p = pnp->pr_common->prc_proc;
6303 6320          mutex_exit(&p->p_lock);
6304 6321  
6305 6322          execvp = p->p_exec;
6306 6323          VN_HOLD(execvp);
6307 6324  
6308 6325          /*
6309 6326           * If our initial lookup of the directory failed, fall back to
6310 6327           * the path name information for p_exec.
6311 6328           */
6312 6329          if (ret != 0) {
6313 6330                  mutex_enter(&p->p_lock);
6314 6331                  prunlock(pnp);
6315 6332                  ret = vnodetopath(vrootp, execvp, buf, size, cr);
6316 6333                  VN_RELE(execvp);
6317 6334                  VN_RELE(vrootp);
6318 6335                  return (ret);
6319 6336          }
6320 6337  
6321 6338          len = strlen(buf);
6322 6339  
6323 6340          /*
6324 6341           * We use u_comm as a guess for the last component of the full
6325 6342           * executable path name. If there isn't going to be enough space
6326 6343           * we fall back to using the p_exec so that we can have _an_
6327 6344           * answer even if it's not perfect.
6328 6345           */
6329 6346          if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
6330 6347                  buf[len] = '/';
6331 6348                  (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
6332 6349                  mutex_enter(&p->p_lock);
6333 6350                  prunlock(pnp);
6334 6351  
6335 6352                  /*
6336 6353                   * Do a forward lookup of our u_comm guess.
6337 6354                   */
6338 6355                  if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
6339 6356                      &vp, pnp->pr_realvp) == 0) {
6340 6357                          if (vn_compare(vp, execvp)) {
6341 6358                                  VN_RELE(vp);
6342 6359                                  VN_RELE(execvp);
6343 6360                                  VN_RELE(vrootp);
6344 6361                                  return (0);
6345 6362                          }
6346 6363  
6347 6364                          VN_RELE(vp);
6348 6365                  }
6349 6366          } else {
6350 6367                  mutex_enter(&p->p_lock);
6351 6368                  prunlock(pnp);
6352 6369          }
6353 6370  
6354 6371          dbuf = kmem_alloc(dlen, KM_SLEEP);
6355 6372  
6356 6373          /*
6357 6374           * Try to find a matching vnode by iterating through the directory's
6358 6375           * entries. If that fails, fall back to the path information for
6359 6376           * p_exec.
6360 6377           */
6361 6378          if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
6362 6379              dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
6363 6380                  buf[len] = '/';
6364 6381                  (void) strcpy(buf + len + 1, dp->d_name);
6365 6382          } else {
6366 6383                  ret = vnodetopath(vrootp, execvp, buf, size, cr);
6367 6384          }
6368 6385  
6369 6386          kmem_free(dbuf, dlen);
6370 6387          VN_RELE(execvp);
6371 6388          VN_RELE(vrootp);
6372 6389  
6373 6390          return (ret);
6374 6391  }
6375 6392  
6376 6393  /* ARGSUSED */
6377 6394  static int
6378 6395  prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
6379 6396  {
6380 6397          prnode_t *pnp = VTOP(vp);
6381 6398          char *buf;
6382 6399          int ret = EINVAL;
6383 6400          char idbuf[16];
6384 6401          int length, rlength;
6385 6402          contract_t *ct;
6386 6403  
6387 6404          switch (pnp->pr_type) {
6388 6405          case PR_SELF:
6389 6406                  (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
6390 6407                  ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
6391 6408                  break;
6392 6409          case PR_OBJECT:
6393 6410          case PR_FD:
6394 6411          case PR_CURDIR:
6395 6412          case PR_ROOTDIR:
6396 6413                  if (pnp->pr_realvp->v_type == VDIR)
6397 6414                          ret = 0;
6398 6415                  break;
6399 6416          case PR_PATH:
6400 6417                  buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6401 6418  
6402 6419                  if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
6403 6420                          ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
6404 6421  
6405 6422                  kmem_free(buf, MAXPATHLEN);
6406 6423                  break;
6407 6424          case PR_CT:
6408 6425                  ASSERT(pnp->pr_contract != NULL);
6409 6426                  ct = pnp->pr_contract;
6410 6427                  length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
6411 6428                      strlen(ct->ct_type->ct_type_name);
6412 6429                  buf = kmem_alloc(length, KM_SLEEP);
6413 6430                  rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
6414 6431                      ct->ct_type->ct_type_name, ct->ct_id);
6415 6432                  ASSERT(rlength < length);
6416 6433                  ret = uiomove(buf, rlength, UIO_READ, uiop);
6417 6434                  kmem_free(buf, length);
6418 6435                  break;
6419 6436          default:
6420 6437                  break;
6421 6438          }
6422 6439  
6423 6440          return (ret);
6424 6441  }
6425 6442  
6426 6443  /*ARGSUSED2*/
6427 6444  static int
6428 6445  prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
6429 6446  {
6430 6447          prnode_t *pp1, *pp2;
6431 6448  
6432 6449          if (vp1 == vp2)
6433 6450                  return (1);
6434 6451  
6435 6452          if (!vn_matchops(vp1, prvnodeops) || !vn_matchops(vp2, prvnodeops))
6436 6453                  return (0);
6437 6454  
6438 6455          pp1 = VTOP(vp1);
6439 6456          pp2 = VTOP(vp2);
6440 6457  
6441 6458          if (pp1->pr_type != pp2->pr_type)
6442 6459                  return (0);
6443 6460          if (pp1->pr_type == PR_PROCDIR)
6444 6461                  return (1);
6445 6462          if (pp1->pr_ino || pp2->pr_ino)
6446 6463                  return (pp2->pr_ino == pp1->pr_ino);
6447 6464  
6448 6465          if (pp1->pr_common == NULL || pp2->pr_common == NULL)
6449 6466                  return (0);
6450 6467  
6451 6468          return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
6452 6469              pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
6453 6470  }
6454 6471  
6455 6472  static int
6456 6473  prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
6457 6474  {
6458 6475          vnode_t *rvp;
6459 6476  
6460 6477          if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
6461 6478                  vp = rvp;
6462 6479                  if (VOP_REALVP(vp, &rvp, ct) == 0)
6463 6480                          vp = rvp;
6464 6481          }
6465 6482  
6466 6483          *vpp = vp;
6467 6484          return (0);
6468 6485  }
6469 6486  
6470 6487  /*
6471 6488   * Return the answer requested to poll().
6472 6489   * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
6473 6490   * In addition, these have special meaning for /proc files:
6474 6491   *      POLLPRI         process or lwp stopped on an event of interest
6475 6492   *      POLLERR         /proc file descriptor is invalid
6476 6493   *      POLLHUP         process or lwp has terminated
6477 6494   */
6478 6495  /*ARGSUSED5*/
6479 6496  static int
6480 6497  prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
6481 6498      pollhead_t **phpp, caller_context_t *ct)
6482 6499  {
6483 6500          prnode_t *pnp = VTOP(vp);
6484 6501          prcommon_t *pcp = pnp->pr_common;
6485 6502          pollhead_t *php = &pcp->prc_pollhead;
6486 6503          proc_t *p;
6487 6504          short revents;
6488 6505          int error;
6489 6506          int lockstate;
6490 6507  
6491 6508          ASSERT(pnp->pr_type < PR_NFILES);
6492 6509  
6493 6510          /*
6494 6511           * Support for old /proc interface.
6495 6512           */
6496 6513          if (pnp->pr_pidfile != NULL) {
6497 6514                  vp = pnp->pr_pidfile;
6498 6515                  pnp = VTOP(vp);
6499 6516                  ASSERT(pnp->pr_type == PR_PIDFILE);
6500 6517                  ASSERT(pnp->pr_common == pcp);
6501 6518          }
6502 6519  
6503 6520          *reventsp = revents = 0;
6504 6521          *phpp = (pollhead_t *)NULL;
6505 6522  
6506 6523          if (vp->v_type == VDIR) {
6507 6524                  *reventsp |= POLLNVAL;
6508 6525                  return (0);
6509 6526          }
6510 6527  
6511 6528          /* avoid deadlock with prnotify() */
6512 6529          if (pollunlock(&lockstate) != 0) {
6513 6530                  *reventsp = POLLNVAL;
6514 6531                  return (0);
6515 6532          }
6516 6533  
6517 6534          if ((error = prlock(pnp, ZNO)) != 0) {
6518 6535                  pollrelock(lockstate);
6519 6536                  switch (error) {
6520 6537                  case ENOENT:            /* process or lwp died */
6521 6538                          *reventsp = POLLHUP;
6522 6539                          error = 0;
6523 6540                          break;
6524 6541                  case EAGAIN:            /* invalidated */
6525 6542                          *reventsp = POLLERR;
6526 6543                          error = 0;
6527 6544                          break;
6528 6545                  }
6529 6546                  return (error);
6530 6547          }
6531 6548  
6532 6549          /*
6533 6550           * We have the process marked locked (P_PR_LOCK) and we are holding
6534 6551           * its p->p_lock.  We want to unmark the process but retain
6535 6552           * exclusive control w.r.t. other /proc controlling processes
6536 6553           * before reacquiring the polling locks.
6537 6554           *
6538 6555           * prunmark() does this for us.  It unmarks the process
6539 6556           * but retains p->p_lock so we still have exclusive control.
6540 6557           * We will drop p->p_lock at the end to relinquish control.
6541 6558           *
6542 6559           * We cannot call prunlock() at the end to relinquish control
6543 6560           * because prunlock(), like prunmark(), may drop and reacquire
6544 6561           * p->p_lock and that would lead to a lock order violation
6545 6562           * w.r.t. the polling locks we are about to reacquire.
6546 6563           */
6547 6564          p = pcp->prc_proc;
6548 6565          ASSERT(p != NULL);
6549 6566          prunmark(p);
6550 6567  
6551 6568          pollrelock(lockstate);          /* reacquire dropped poll locks */
6552 6569  
6553 6570          if ((p->p_flag & SSYS) || p->p_as == &kas)
6554 6571                  revents = POLLNVAL;
6555 6572          else {
6556 6573                  short ev;
6557 6574  
6558 6575                  if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
6559 6576                          revents |= ev;
6560 6577                  /*
6561 6578                   * POLLWRNORM (same as POLLOUT) really should not be
6562 6579                   * used to indicate that the process or lwp stopped.
6563 6580                   * However, USL chose to use POLLWRNORM rather than
6564 6581                   * POLLPRI to indicate this, so we just accept either
6565 6582                   * requested event to indicate stopped.  (grr...)
6566 6583                   */
6567 6584                  if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
6568 6585                          kthread_t *t;
6569 6586  
6570 6587                          if (pcp->prc_flags & PRC_LWP) {
6571 6588                                  t = pcp->prc_thread;
6572 6589                                  ASSERT(t != NULL);
6573 6590                                  thread_lock(t);
6574 6591                          } else {
6575 6592                                  t = prchoose(p);        /* returns locked t */
6576 6593                                  ASSERT(t != NULL);
6577 6594                          }
6578 6595  
6579 6596                          if (ISTOPPED(t) || VSTOPPED(t))
6580 6597                                  revents |= ev;
6581 6598                          thread_unlock(t);
6582 6599                  }
6583 6600          }
6584 6601  
6585 6602          *reventsp = revents;
6586 6603          if ((!anyyet && revents == 0) || (events & POLLET)) {
6587 6604                  /*
6588 6605                   * Arrange to wake up the polling lwp when
6589 6606                   * the target process/lwp stops or terminates
6590 6607                   * or when the file descriptor becomes invalid.
6591 6608                   */
6592 6609                  pcp->prc_flags |= PRC_POLL;
6593 6610                  *phpp = php;
6594 6611          }
6595 6612          mutex_exit(&p->p_lock);
6596 6613          return (0);
6597 6614  }
6598 6615  
6599 6616  /* in prioctl.c */
6600 6617  extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
6601 6618          caller_context_t *);
6602 6619  
6603 6620  /*
6604 6621   * /proc vnode operations vector
6605 6622   */
6606 6623  const fs_operation_def_t pr_vnodeops_template[] = {
6607 6624          VOPNAME_OPEN,           { .vop_open = propen },
6608 6625          VOPNAME_CLOSE,          { .vop_close = prclose },
6609 6626          VOPNAME_READ,           { .vop_read = prread },
6610 6627          VOPNAME_WRITE,          { .vop_write = prwrite },
6611 6628          VOPNAME_IOCTL,          { .vop_ioctl = prioctl },
6612 6629          VOPNAME_GETATTR,        { .vop_getattr = prgetattr },
6613 6630          VOPNAME_ACCESS,         { .vop_access = praccess },
6614 6631          VOPNAME_LOOKUP,         { .vop_lookup = prlookup },
6615 6632          VOPNAME_CREATE,         { .vop_create = prcreate },
6616 6633          VOPNAME_READDIR,        { .vop_readdir = prreaddir },
6617 6634          VOPNAME_READLINK,       { .vop_readlink = prreadlink },
6618 6635          VOPNAME_FSYNC,          { .vop_fsync = prfsync },
6619 6636          VOPNAME_INACTIVE,       { .vop_inactive = prinactive },
6620 6637          VOPNAME_SEEK,           { .vop_seek = prseek },
6621 6638          VOPNAME_CMP,            { .vop_cmp = prcmp },
6622 6639          VOPNAME_FRLOCK,         { .error = fs_error },
6623 6640          VOPNAME_REALVP,         { .vop_realvp = prrealvp },
6624 6641          VOPNAME_POLL,           { .vop_poll = prpoll },
6625 6642          VOPNAME_DISPOSE,        { .error = fs_error },
6626 6643          VOPNAME_SHRLOCK,        { .error = fs_error },
6627 6644          NULL,                   NULL
6628 6645  };
  
    | 
      ↓ open down ↓ | 
    4843 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX