6514 AS_* lock macros simplification
[illumos-gate.git] / usr / src / uts / common / fs / proc / prvnops.c
blob39f2abbc3244f957a0d1ebff6ca61bd44feac54a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/cred.h>
34 #include <sys/policy.h>
35 #include <sys/debug.h>
36 #include <sys/dirent.h>
37 #include <sys/errno.h>
38 #include <sys/file.h>
39 #include <sys/inline.h>
40 #include <sys/kmem.h>
41 #include <sys/pathname.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/signal.h>
45 #include <sys/stat.h>
46 #include <sys/sysmacros.h>
47 #include <sys/systm.h>
48 #include <sys/zone.h>
49 #include <sys/uio.h>
50 #include <sys/var.h>
51 #include <sys/mode.h>
52 #include <sys/poll.h>
53 #include <sys/user.h>
54 #include <sys/vfs.h>
55 #include <sys/vfs_opreg.h>
56 #include <sys/gfs.h>
57 #include <sys/vnode.h>
58 #include <sys/fault.h>
59 #include <sys/syscall.h>
60 #include <sys/procfs.h>
61 #include <sys/atomic.h>
62 #include <sys/cmn_err.h>
63 #include <sys/contract_impl.h>
64 #include <sys/ctfs.h>
65 #include <sys/avl.h>
66 #include <fs/fs_subr.h>
67 #include <vm/rm.h>
68 #include <vm/as.h>
69 #include <vm/seg.h>
70 #include <vm/seg_vn.h>
71 #include <vm/hat.h>
72 #include <fs/proc/prdata.h>
73 #if defined(__sparc)
74 #include <sys/regset.h>
75 #endif
76 #if defined(__x86)
77 #include <sys/sysi86.h>
78 #endif
81 * Created by prinit.
83 vnodeops_t *prvnodeops;
86 * Directory characteristics (patterned after the s5 file system).
88 #define PRROOTINO 2
90 #define PRDIRSIZE 14
91 struct prdirect {
92 ushort_t d_ino;
93 char d_name[PRDIRSIZE];
96 #define PRSDSIZE (sizeof (struct prdirect))
99 * Directory characteristics.
101 typedef struct prdirent {
102 ino64_t d_ino; /* "inode number" of entry */
103 off64_t d_off; /* offset of disk directory entry */
104 unsigned short d_reclen; /* length of this record */
105 char d_name[14]; /* name of file */
106 } prdirent_t;
109 * Contents of a /proc/<pid> directory.
110 * Reuse d_ino field for the /proc file type.
112 static prdirent_t piddir[] = {
113 { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
114 "." },
115 { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
116 ".." },
117 { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
118 "as" },
119 { PR_CTL, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
120 "ctl" },
121 { PR_STATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
122 "status" },
123 { PR_LSTATUS, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
124 "lstatus" },
125 { PR_PSINFO, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
126 "psinfo" },
127 { PR_LPSINFO, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
128 "lpsinfo" },
129 { PR_MAP, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
130 "map" },
131 { PR_RMAP, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
132 "rmap" },
133 { PR_XMAP, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
134 "xmap" },
135 { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
136 "cred" },
137 { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
138 "sigact" },
139 { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
140 "auxv" },
141 { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
142 "usage" },
143 { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
144 "lusage" },
145 { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
146 "pagedata" },
147 { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
148 "watch" },
149 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
150 "cwd" },
151 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
152 "root" },
153 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
154 "fd" },
155 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
156 "object" },
157 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
158 "lwp" },
159 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
160 "priv" },
161 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
162 "path" },
163 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
164 "contracts" },
165 #if defined(__x86)
166 { PR_LDT, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
167 "ldt" },
168 #endif
171 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
174 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
176 static prdirent_t lwpiddir[] = {
177 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
178 "." },
179 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
180 ".." },
181 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
182 "lwpctl" },
183 { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
184 "lwpstatus" },
185 { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
186 "lwpsinfo" },
187 { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
188 "lwpusage" },
189 { PR_XREGS, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
190 "xregs" },
191 { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
192 "templates" },
193 { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
194 "spymaster" },
195 #if defined(__sparc)
196 { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
197 "gwindows" },
198 { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
199 "asrs" },
200 #endif
203 #define NLWPIDDIRFILES (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
206 * Span of entries in the array files (lstatus, lpsinfo, lusage).
207 * We make the span larger than the size of the structure on purpose,
208 * to make sure that programs cannot use the structure size by mistake.
209 * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
211 #ifdef _LP64
212 #define LSPAN(type) (round16(sizeof (type)) + 16)
213 #define LSPAN32(type) (round8(sizeof (type)) + 8)
214 #else
215 #define LSPAN(type) (round8(sizeof (type)) + 8)
216 #endif
218 static void rebuild_objdir(struct as *);
219 static void prfreecommon(prcommon_t *);
220 static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
222 static int
223 propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
225 vnode_t *vp = *vpp;
226 prnode_t *pnp = VTOP(vp);
227 prcommon_t *pcp = pnp->pr_pcommon;
228 prnodetype_t type = pnp->pr_type;
229 vnode_t *rvp;
230 vtype_t vtype;
231 proc_t *p;
232 int error = 0;
233 prnode_t *npnp = NULL;
236 * Nothing to do for the /proc directory itself.
238 if (type == PR_PROCDIR)
239 return (0);
242 * If we are opening an underlying mapped object, reject opens
243 * for writing regardless of the objects's access modes.
244 * If we are opening a file in the /proc/pid/fd directory,
245 * reject the open for any but a regular file or directory.
246 * Just do it if we are opening the current or root directory.
248 switch (type) {
249 case PR_OBJECT:
250 case PR_FD:
251 case PR_CURDIR:
252 case PR_ROOTDIR:
253 rvp = pnp->pr_realvp;
254 vtype = rvp->v_type;
255 if ((type == PR_OBJECT && (flag & FWRITE)) ||
256 (type == PR_FD && vtype != VREG && vtype != VDIR))
257 error = EACCES;
258 else {
260 * Need to hold rvp since VOP_OPEN() may release it.
262 VN_HOLD(rvp);
263 error = VOP_OPEN(&rvp, flag, cr, ct);
264 if (error) {
265 VN_RELE(rvp);
266 } else {
267 *vpp = rvp;
268 VN_RELE(vp);
271 return (error);
272 default:
273 break;
277 * If we are opening the pagedata file, allocate a prnode now
278 * to avoid calling kmem_alloc() while holding p->p_lock.
280 if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
281 npnp = prgetnode(vp, type);
284 * If the process exists, lock it now.
285 * Otherwise we have a race condition with prclose().
287 p = pr_p_lock(pnp);
288 mutex_exit(&pr_pidlock);
289 if (p == NULL) {
290 if (npnp != NULL)
291 prfreenode(npnp);
292 return (ENOENT);
294 ASSERT(p == pcp->prc_proc);
295 ASSERT(p->p_proc_flag & P_PR_LOCK);
298 * Maintain a count of opens for write. Allow exactly one
299 * O_WRITE|O_EXCL request and fail subsequent ones.
300 * Don't fail opens of old (bletch!) /proc lwp files.
301 * Special case for open by the process itself:
302 * Always allow the open by self and discount this
303 * open for other opens for writing.
305 if (flag & FWRITE) {
306 if (p == curproc) {
307 pcp->prc_selfopens++;
308 pnp->pr_flags |= PR_ISSELF;
309 } else if (type == PR_LWPIDFILE) {
310 /* EMPTY */;
311 } else if (flag & FEXCL) {
312 if (pcp->prc_writers > pcp->prc_selfopens) {
313 error = EBUSY;
314 goto out;
316 /* semantic for old /proc interface */
317 if (type == PR_PIDDIR)
318 pcp->prc_flags |= PRC_EXCL;
319 } else if (pcp->prc_flags & PRC_EXCL) {
320 ASSERT(pcp->prc_writers > pcp->prc_selfopens);
321 error = secpolicy_proc_excl_open(cr);
322 if (error)
323 goto out;
325 pcp->prc_writers++;
327 * The vnode may have become invalid between the
328 * VOP_LOOKUP() of the /proc vnode and the VOP_OPEN().
329 * If so, do now what prinvalidate() should have done.
331 if ((pnp->pr_flags & PR_INVAL) ||
332 (type == PR_PIDDIR &&
333 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
334 if (p != curproc)
335 pcp->prc_selfopens++;
336 ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
337 if (pcp->prc_selfopens == pcp->prc_writers)
338 pcp->prc_flags &= ~PRC_EXCL;
343 * If this is a large file open, indicate that in our flags -- some
344 * procfs structures are not off_t-neutral (e.g., priovec_t), and
345 * the open will need to be differentiated where 32-bit processes
346 * pass these structures across the user/kernel boundary.
348 if (flag & FOFFMAX)
349 pnp->pr_flags |= PR_OFFMAX;
352 * Do file-specific things.
354 switch (type) {
355 default:
356 break;
357 case PR_PAGEDATA:
358 case PR_OPAGEDATA:
360 * Enable data collection for page data file;
361 * get unique id from the hat layer.
364 int id;
367 * Drop p->p_lock to call hat_startstat()
369 mutex_exit(&p->p_lock);
370 if ((p->p_flag & SSYS) || p->p_as == &kas ||
371 (id = hat_startstat(p->p_as)) == -1) {
372 mutex_enter(&p->p_lock);
373 error = ENOMEM;
374 } else if (pnp->pr_hatid == 0) {
375 mutex_enter(&p->p_lock);
376 pnp->pr_hatid = (uint_t)id;
377 } else {
378 mutex_enter(&p->p_lock);
380 * Use our newly allocated prnode.
382 npnp->pr_hatid = (uint_t)id;
384 * prgetnode() initialized most of the prnode.
385 * Duplicate the remainder.
387 npnp->pr_ino = pnp->pr_ino;
388 npnp->pr_common = pnp->pr_common;
389 npnp->pr_pcommon = pnp->pr_pcommon;
390 npnp->pr_parent = pnp->pr_parent;
391 VN_HOLD(npnp->pr_parent);
392 npnp->pr_index = pnp->pr_index;
394 npnp->pr_next = p->p_plist;
395 p->p_plist = PTOV(npnp);
397 VN_RELE(PTOV(pnp));
398 pnp = npnp;
399 npnp = NULL;
400 *vpp = PTOV(pnp);
403 break;
406 out:
407 prunlock(pnp);
409 if (npnp != NULL)
410 prfreenode(npnp);
411 return (error);
414 /* ARGSUSED */
415 static int
416 prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
417 caller_context_t *ct)
419 prnode_t *pnp = VTOP(vp);
420 prcommon_t *pcp = pnp->pr_pcommon;
421 prnodetype_t type = pnp->pr_type;
422 proc_t *p;
423 kthread_t *t;
424 user_t *up;
427 * Nothing to do for the /proc directory itself.
429 if (type == PR_PROCDIR)
430 return (0);
432 ASSERT(type != PR_OBJECT && type != PR_FD &&
433 type != PR_CURDIR && type != PR_ROOTDIR);
436 * If the process exists, lock it now.
437 * Otherwise we have a race condition with propen().
438 * Hold pr_pidlock across the reference to prc_selfopens,
439 * and prc_writers in case there is no process anymore,
440 * to cover the case of concurrent calls to prclose()
441 * after the process has been reaped by freeproc().
443 p = pr_p_lock(pnp);
446 * There is nothing more to do until the last close of
447 * the file table entry except to clear the pr_owner
448 * field of the prnode and notify any waiters
449 * (their file descriptor may have just been closed).
451 if (count > 1) {
452 mutex_exit(&pr_pidlock);
453 if (pnp->pr_owner == curproc && !fisopen(vp))
454 pnp->pr_owner = NULL;
455 if (p != NULL) {
456 prnotify(vp);
457 prunlock(pnp);
459 return (0);
463 * Decrement the count of self-opens for writing.
464 * Decrement the total count of opens for writing.
465 * Cancel exclusive opens when only self-opens remain.
467 if (flag & FWRITE) {
469 * prc_selfopens also contains the count of
470 * invalid writers. See prinvalidate().
472 if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
473 (type == PR_PIDDIR &&
474 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
475 ASSERT(pcp->prc_selfopens != 0);
476 --pcp->prc_selfopens;
478 ASSERT(pcp->prc_writers != 0);
479 if (--pcp->prc_writers == pcp->prc_selfopens)
480 pcp->prc_flags &= ~PRC_EXCL;
482 ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
483 mutex_exit(&pr_pidlock);
484 if (pnp->pr_owner == curproc && !fisopen(vp))
485 pnp->pr_owner = NULL;
488 * If there is no process, there is nothing more to do.
490 if (p == NULL)
491 return (0);
493 ASSERT(p == pcp->prc_proc);
494 prnotify(vp); /* notify waiters */
497 * Do file-specific things.
499 switch (type) {
500 default:
501 break;
502 case PR_PAGEDATA:
503 case PR_OPAGEDATA:
505 * This is a page data file.
506 * Free the hat level statistics.
507 * Drop p->p_lock before calling hat_freestat().
509 mutex_exit(&p->p_lock);
510 if (p->p_as != &kas && pnp->pr_hatid != 0)
511 hat_freestat(p->p_as, pnp->pr_hatid);
512 mutex_enter(&p->p_lock);
513 pnp->pr_hatid = 0;
514 break;
518 * On last close of all writable file descriptors,
519 * perform run-on-last-close and/or kill-on-last-close logic.
520 * Can't do this is the /proc agent lwp still exists.
522 if (pcp->prc_writers == 0 &&
523 p->p_agenttp == NULL &&
524 !(pcp->prc_flags & PRC_DESTROY) &&
525 p->p_stat != SZOMB &&
526 (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
527 int killproc;
530 * Cancel any watchpoints currently in effect.
531 * The process might disappear during this operation.
533 if (pr_cancel_watch(pnp) == NULL)
534 return (0);
536 * If any tracing flags are set, clear them.
538 if (p->p_proc_flag & P_PR_TRACE) {
539 up = PTOU(p);
540 premptyset(&up->u_entrymask);
541 premptyset(&up->u_exitmask);
542 up->u_systrap = 0;
544 premptyset(&p->p_sigmask);
545 premptyset(&p->p_fltmask);
546 killproc = (p->p_proc_flag & P_PR_KILLCL);
547 p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
549 * Cancel any outstanding single-step requests.
551 if ((t = p->p_tlist) != NULL) {
553 * Drop p_lock because prnostep() touches the stack.
554 * The loop is safe because the process is P_PR_LOCK'd.
556 mutex_exit(&p->p_lock);
557 do {
558 prnostep(ttolwp(t));
559 } while ((t = t->t_forw) != p->p_tlist);
560 mutex_enter(&p->p_lock);
563 * Set runnable all lwps stopped by /proc.
565 if (killproc)
566 sigtoproc(p, NULL, SIGKILL);
567 else
568 allsetrun(p);
571 prunlock(pnp);
572 return (0);
576 * Array of read functions, indexed by /proc file type.
578 static int pr_read_inval(), pr_read_as(), pr_read_status(),
579 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
580 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
581 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
582 #if defined(__x86)
583 pr_read_ldt(),
584 #endif
585 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
586 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
587 pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
588 pr_read_spymaster(),
589 #if defined(__sparc)
590 pr_read_gwindows(), pr_read_asrs(),
591 #endif
592 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
594 static int (*pr_read_function[PR_NFILES])() = {
595 pr_read_inval, /* /proc */
596 pr_read_inval, /* /proc/self */
597 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
598 pr_read_as, /* /proc/<pid>/as */
599 pr_read_inval, /* /proc/<pid>/ctl */
600 pr_read_status, /* /proc/<pid>/status */
601 pr_read_lstatus, /* /proc/<pid>/lstatus */
602 pr_read_psinfo, /* /proc/<pid>/psinfo */
603 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
604 pr_read_map, /* /proc/<pid>/map */
605 pr_read_rmap, /* /proc/<pid>/rmap */
606 pr_read_xmap, /* /proc/<pid>/xmap */
607 pr_read_cred, /* /proc/<pid>/cred */
608 pr_read_sigact, /* /proc/<pid>/sigact */
609 pr_read_auxv, /* /proc/<pid>/auxv */
610 #if defined(__x86)
611 pr_read_ldt, /* /proc/<pid>/ldt */
612 #endif
613 pr_read_usage, /* /proc/<pid>/usage */
614 pr_read_lusage, /* /proc/<pid>/lusage */
615 pr_read_pagedata, /* /proc/<pid>/pagedata */
616 pr_read_watch, /* /proc/<pid>/watch */
617 pr_read_inval, /* /proc/<pid>/cwd */
618 pr_read_inval, /* /proc/<pid>/root */
619 pr_read_inval, /* /proc/<pid>/fd */
620 pr_read_inval, /* /proc/<pid>/fd/nn */
621 pr_read_inval, /* /proc/<pid>/object */
622 pr_read_inval, /* /proc/<pid>/object/xxx */
623 pr_read_inval, /* /proc/<pid>/lwp */
624 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
625 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
626 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
627 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
628 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
629 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
630 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
631 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
632 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
633 #if defined(__sparc)
634 pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
635 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
636 #endif
637 pr_read_priv, /* /proc/<pid>/priv */
638 pr_read_inval, /* /proc/<pid>/path */
639 pr_read_inval, /* /proc/<pid>/path/xxx */
640 pr_read_inval, /* /proc/<pid>/contracts */
641 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
642 pr_read_pidfile, /* old process file */
643 pr_read_pidfile, /* old lwp file */
644 pr_read_opagedata, /* old pagedata file */
647 /* ARGSUSED */
648 static int
649 pr_read_inval(prnode_t *pnp, uio_t *uiop)
652 * No read() on any /proc directory, use getdents(2) instead.
653 * Cannot read a control file either.
654 * An underlying mapped object file cannot get here.
656 return (EINVAL);
659 static int
660 pr_uioread(void *base, long count, uio_t *uiop)
662 int error = 0;
664 ASSERT(count >= 0);
665 count -= uiop->uio_offset;
666 if (count > 0 && uiop->uio_offset >= 0) {
667 error = uiomove((char *)base + uiop->uio_offset,
668 count, UIO_READ, uiop);
671 return (error);
674 static int
675 pr_read_as(prnode_t *pnp, uio_t *uiop)
677 int error;
679 ASSERT(pnp->pr_type == PR_AS);
681 if ((error = prlock(pnp, ZNO)) == 0) {
682 proc_t *p = pnp->pr_common->prc_proc;
683 struct as *as = p->p_as;
686 * /proc I/O cannot be done to a system process.
687 * A 32-bit process cannot read a 64-bit process.
689 if ((p->p_flag & SSYS) || as == &kas) {
690 error = 0;
691 #ifdef _SYSCALL32_IMPL
692 } else if (curproc->p_model == DATAMODEL_ILP32 &&
693 PROCESS_NOT_32BIT(p)) {
694 error = EOVERFLOW;
695 #endif
696 } else {
698 * We don't hold p_lock over an i/o operation because
699 * that could lead to deadlock with the clock thread.
701 mutex_exit(&p->p_lock);
702 error = prusrio(p, UIO_READ, uiop, 0);
703 mutex_enter(&p->p_lock);
705 prunlock(pnp);
708 return (error);
711 static int
712 pr_read_status(prnode_t *pnp, uio_t *uiop)
714 pstatus_t *sp;
715 int error;
717 ASSERT(pnp->pr_type == PR_STATUS);
720 * We kmem_alloc() the pstatus structure because
721 * it is so big it might blow the kernel stack.
723 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
724 if ((error = prlock(pnp, ZNO)) == 0) {
725 prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
726 prunlock(pnp);
727 error = pr_uioread(sp, sizeof (*sp), uiop);
729 kmem_free(sp, sizeof (*sp));
730 return (error);
733 static int
734 pr_read_lstatus(prnode_t *pnp, uio_t *uiop)
736 proc_t *p;
737 kthread_t *t;
738 lwpdir_t *ldp;
739 size_t size;
740 prheader_t *php;
741 lwpstatus_t *sp;
742 int error;
743 int nlwp;
744 int i;
746 ASSERT(pnp->pr_type == PR_LSTATUS);
748 if ((error = prlock(pnp, ZNO)) != 0)
749 return (error);
750 p = pnp->pr_common->prc_proc;
751 nlwp = p->p_lwpcnt;
752 size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
754 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
755 mutex_exit(&p->p_lock);
756 php = kmem_zalloc(size, KM_SLEEP);
757 mutex_enter(&p->p_lock);
758 /* p->p_lwpcnt can't change while process is locked */
759 ASSERT(nlwp == p->p_lwpcnt);
761 php->pr_nent = nlwp;
762 php->pr_entsize = LSPAN(lwpstatus_t);
764 sp = (lwpstatus_t *)(php + 1);
765 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
766 if (ldp->ld_entry == NULL ||
767 (t = ldp->ld_entry->le_thread) == NULL)
768 continue;
769 prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
770 sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
772 prunlock(pnp);
774 error = pr_uioread(php, size, uiop);
775 kmem_free(php, size);
776 return (error);
779 static int
780 pr_read_psinfo(prnode_t *pnp, uio_t *uiop)
782 psinfo_t psinfo;
783 proc_t *p;
784 int error = 0;
786 ASSERT(pnp->pr_type == PR_PSINFO);
789 * We don't want the full treatment of prlock(pnp) here.
790 * This file is world-readable and never goes invalid.
791 * It doesn't matter if we are in the middle of an exec().
793 p = pr_p_lock(pnp);
794 mutex_exit(&pr_pidlock);
795 if (p == NULL)
796 error = ENOENT;
797 else {
798 ASSERT(p == pnp->pr_common->prc_proc);
799 prgetpsinfo(p, &psinfo);
800 prunlock(pnp);
801 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
803 return (error);
806 static int
807 pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
809 proc_t *p;
810 kthread_t *t;
811 lwpdir_t *ldp;
812 lwpent_t *lep;
813 size_t size;
814 prheader_t *php;
815 lwpsinfo_t *sp;
816 int error;
817 int nlwp;
818 int i;
820 ASSERT(pnp->pr_type == PR_LPSINFO);
823 * We don't want the full treatment of prlock(pnp) here.
824 * This file is world-readable and never goes invalid.
825 * It doesn't matter if we are in the middle of an exec().
827 p = pr_p_lock(pnp);
828 mutex_exit(&pr_pidlock);
829 if (p == NULL)
830 return (ENOENT);
831 ASSERT(p == pnp->pr_common->prc_proc);
832 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
833 prunlock(pnp);
834 return (ENOENT);
836 size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
838 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
839 mutex_exit(&p->p_lock);
840 php = kmem_zalloc(size, KM_SLEEP);
841 mutex_enter(&p->p_lock);
842 /* p->p_lwpcnt can't change while process is locked */
843 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
845 php->pr_nent = nlwp;
846 php->pr_entsize = LSPAN(lwpsinfo_t);
848 sp = (lwpsinfo_t *)(php + 1);
849 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
850 if ((lep = ldp->ld_entry) == NULL)
851 continue;
852 if ((t = lep->le_thread) != NULL)
853 prgetlwpsinfo(t, sp);
854 else {
855 bzero(sp, sizeof (*sp));
856 sp->pr_lwpid = lep->le_lwpid;
857 sp->pr_state = SZOMB;
858 sp->pr_sname = 'Z';
859 sp->pr_start.tv_sec = lep->le_start;
860 sp->pr_bindpro = PBIND_NONE;
861 sp->pr_bindpset = PS_NONE;
863 sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
865 prunlock(pnp);
867 error = pr_uioread(php, size, uiop);
868 kmem_free(php, size);
869 return (error);
872 static int
873 pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
875 proc_t *p;
876 struct as *as;
877 list_t iolhead;
878 int error;
880 readmap_common:
881 if ((error = prlock(pnp, ZNO)) != 0)
882 return (error);
884 p = pnp->pr_common->prc_proc;
885 as = p->p_as;
887 if ((p->p_flag & SSYS) || as == &kas) {
888 prunlock(pnp);
889 return (0);
892 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
893 prunlock(pnp);
894 delay(1);
895 goto readmap_common;
897 mutex_exit(&p->p_lock);
899 switch (type) {
900 case PR_XMAP:
901 error = prgetxmap(p, &iolhead);
902 break;
903 case PR_RMAP:
904 error = prgetmap(p, 1, &iolhead);
905 break;
906 case PR_MAP:
907 error = prgetmap(p, 0, &iolhead);
908 break;
911 AS_LOCK_EXIT(as);
912 mutex_enter(&p->p_lock);
913 prunlock(pnp);
915 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
917 return (error);
920 static int
921 pr_read_map(prnode_t *pnp, uio_t *uiop)
923 ASSERT(pnp->pr_type == PR_MAP);
924 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
927 static int
928 pr_read_rmap(prnode_t *pnp, uio_t *uiop)
930 ASSERT(pnp->pr_type == PR_RMAP);
931 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
934 static int
935 pr_read_xmap(prnode_t *pnp, uio_t *uiop)
937 ASSERT(pnp->pr_type == PR_XMAP);
938 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
941 static int
942 pr_read_cred(prnode_t *pnp, uio_t *uiop)
944 proc_t *p;
945 prcred_t *pcrp;
946 int error;
947 size_t count;
949 ASSERT(pnp->pr_type == PR_CRED);
952 * We kmem_alloc() the prcred_t structure because
953 * the number of supplementary groups is variable.
955 pcrp =
956 kmem_alloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
957 KM_SLEEP);
959 if ((error = prlock(pnp, ZNO)) != 0)
960 goto out;
961 p = pnp->pr_common->prc_proc;
962 ASSERT(p != NULL);
964 prgetcred(p, pcrp);
965 prunlock(pnp);
967 count = sizeof (prcred_t);
968 if (pcrp->pr_ngroups > 1)
969 count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
970 error = pr_uioread(pcrp, count, uiop);
971 out:
972 kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
973 return (error);
976 static int
977 pr_read_priv(prnode_t *pnp, uio_t *uiop)
979 proc_t *p;
980 size_t psize = prgetprivsize();
981 prpriv_t *ppriv = kmem_alloc(psize, KM_SLEEP);
982 int error;
984 ASSERT(pnp->pr_type == PR_PRIV);
986 if ((error = prlock(pnp, ZNO)) != 0)
987 goto out;
988 p = pnp->pr_common->prc_proc;
989 ASSERT(p != NULL);
991 prgetpriv(p, ppriv);
992 prunlock(pnp);
994 error = pr_uioread(ppriv, psize, uiop);
995 out:
996 kmem_free(ppriv, psize);
997 return (error);
1000 static int
1001 pr_read_sigact(prnode_t *pnp, uio_t *uiop)
1003 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1004 proc_t *p;
1005 struct sigaction *sap;
1006 int sig;
1007 int error;
1008 user_t *up;
1010 ASSERT(pnp->pr_type == PR_SIGACT);
1013 * We kmem_alloc() the sigaction array because
1014 * it is so big it might blow the kernel stack.
1016 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
1018 if ((error = prlock(pnp, ZNO)) != 0)
1019 goto out;
1020 p = pnp->pr_common->prc_proc;
1021 ASSERT(p != NULL);
1023 if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
1024 prunlock(pnp);
1025 goto out;
1028 up = PTOU(p);
1029 for (sig = 1; sig < nsig; sig++)
1030 prgetaction(p, up, sig, &sap[sig-1]);
1031 prunlock(pnp);
1033 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
1034 out:
1035 kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
1036 return (error);
1039 static int
1040 pr_read_auxv(prnode_t *pnp, uio_t *uiop)
1042 auxv_t auxv[__KERN_NAUXV_IMPL];
1043 proc_t *p;
1044 user_t *up;
1045 int error;
1047 ASSERT(pnp->pr_type == PR_AUXV);
1049 if ((error = prlock(pnp, ZNO)) != 0)
1050 return (error);
1052 if (uiop->uio_offset >= sizeof (auxv)) {
1053 prunlock(pnp);
1054 return (0);
1057 p = pnp->pr_common->prc_proc;
1058 up = PTOU(p);
1059 bcopy(up->u_auxv, auxv, sizeof (auxv));
1060 prunlock(pnp);
1062 return (pr_uioread(auxv, sizeof (auxv), uiop));
1065 #if defined(__x86)
1067 * XX64
1068 * This is almost certainly broken for the amd64 kernel, because
1069 * we have two kinds of LDT structures to export -- one for compatibility
1070 * mode, and one for long mode, sigh.
1072 * For now lets just have a ldt of size 0 for 64-bit processes.
1074 static int
1075 pr_read_ldt(prnode_t *pnp, uio_t *uiop)
1077 proc_t *p;
1078 struct ssd *ssd;
1079 size_t size;
1080 int error;
1082 ASSERT(pnp->pr_type == PR_LDT);
1084 if ((error = prlock(pnp, ZNO)) != 0)
1085 return (error);
1086 p = pnp->pr_common->prc_proc;
1088 mutex_exit(&p->p_lock);
1089 mutex_enter(&p->p_ldtlock);
1090 size = prnldt(p) * sizeof (struct ssd);
1091 if (uiop->uio_offset >= size) {
1092 mutex_exit(&p->p_ldtlock);
1093 mutex_enter(&p->p_lock);
1094 prunlock(pnp);
1095 return (0);
1098 ssd = kmem_alloc(size, KM_SLEEP);
1099 prgetldt(p, ssd);
1100 mutex_exit(&p->p_ldtlock);
1101 mutex_enter(&p->p_lock);
1102 prunlock(pnp);
1104 error = pr_uioread(ssd, size, uiop);
1105 kmem_free(ssd, size);
1106 return (error);
1108 #endif /* __x86 */
1110 static int
1111 pr_read_usage(prnode_t *pnp, uio_t *uiop)
1113 prhusage_t *pup;
1114 prusage_t *upup;
1115 proc_t *p;
1116 kthread_t *t;
1117 int error;
1119 ASSERT(pnp->pr_type == PR_USAGE);
1121 /* allocate now, before locking the process */
1122 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1123 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1126 * We don't want the full treatment of prlock(pnp) here.
1127 * This file is world-readable and never goes invalid.
1128 * It doesn't matter if we are in the middle of an exec().
1130 p = pr_p_lock(pnp);
1131 mutex_exit(&pr_pidlock);
1132 if (p == NULL) {
1133 error = ENOENT;
1134 goto out;
1136 ASSERT(p == pnp->pr_common->prc_proc);
1138 if (uiop->uio_offset >= sizeof (prusage_t)) {
1139 prunlock(pnp);
1140 error = 0;
1141 goto out;
1144 pup->pr_tstamp = gethrtime();
1146 pup->pr_count = p->p_defunct;
1147 pup->pr_create = p->p_mstart;
1148 pup->pr_term = p->p_mterm;
1150 pup->pr_rtime = p->p_mlreal;
1151 pup->pr_utime = p->p_acct[LMS_USER];
1152 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1153 pup->pr_ttime = p->p_acct[LMS_TRAP];
1154 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1155 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1156 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1157 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1158 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1159 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1160 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1162 pup->pr_minf = p->p_ru.minflt;
1163 pup->pr_majf = p->p_ru.majflt;
1164 pup->pr_nswap = p->p_ru.nswap;
1165 pup->pr_inblk = p->p_ru.inblock;
1166 pup->pr_oublk = p->p_ru.oublock;
1167 pup->pr_msnd = p->p_ru.msgsnd;
1168 pup->pr_mrcv = p->p_ru.msgrcv;
1169 pup->pr_sigs = p->p_ru.nsignals;
1170 pup->pr_vctx = p->p_ru.nvcsw;
1171 pup->pr_ictx = p->p_ru.nivcsw;
1172 pup->pr_sysc = p->p_ru.sysc;
1173 pup->pr_ioch = p->p_ru.ioch;
1176 * Add the usage information for each active lwp.
1178 if ((t = p->p_tlist) != NULL &&
1179 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
1180 do {
1181 if (t->t_proc_flag & TP_LWPEXIT)
1182 continue;
1183 pup->pr_count++;
1184 praddusage(t, pup);
1185 } while ((t = t->t_forw) != p->p_tlist);
1188 prunlock(pnp);
1190 prcvtusage(pup, upup);
1192 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1193 out:
1194 kmem_free(pup, sizeof (*pup));
1195 kmem_free(upup, sizeof (*upup));
1196 return (error);
1199 static int
1200 pr_read_lusage(prnode_t *pnp, uio_t *uiop)
1202 int nlwp;
1203 prhusage_t *pup;
1204 prheader_t *php;
1205 prusage_t *upup;
1206 size_t size;
1207 hrtime_t curtime;
1208 proc_t *p;
1209 kthread_t *t;
1210 lwpdir_t *ldp;
1211 int error;
1212 int i;
1214 ASSERT(pnp->pr_type == PR_LUSAGE);
1217 * We don't want the full treatment of prlock(pnp) here.
1218 * This file is world-readable and never goes invalid.
1219 * It doesn't matter if we are in the middle of an exec().
1221 p = pr_p_lock(pnp);
1222 mutex_exit(&pr_pidlock);
1223 if (p == NULL)
1224 return (ENOENT);
1225 ASSERT(p == pnp->pr_common->prc_proc);
1226 if ((nlwp = p->p_lwpcnt) == 0) {
1227 prunlock(pnp);
1228 return (ENOENT);
1231 size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
1232 if (uiop->uio_offset >= size) {
1233 prunlock(pnp);
1234 return (0);
1237 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1238 mutex_exit(&p->p_lock);
1239 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
1240 mutex_enter(&p->p_lock);
1241 /* p->p_lwpcnt can't change while process is locked */
1242 ASSERT(nlwp == p->p_lwpcnt);
1244 php = (prheader_t *)(pup + 1);
1245 upup = (prusage_t *)(php + 1);
1247 php->pr_nent = nlwp + 1;
1248 php->pr_entsize = LSPAN(prusage_t);
1250 curtime = gethrtime();
1253 * First the summation over defunct lwps.
1255 pup->pr_count = p->p_defunct;
1256 pup->pr_tstamp = curtime;
1257 pup->pr_create = p->p_mstart;
1258 pup->pr_term = p->p_mterm;
1260 pup->pr_rtime = p->p_mlreal;
1261 pup->pr_utime = p->p_acct[LMS_USER];
1262 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1263 pup->pr_ttime = p->p_acct[LMS_TRAP];
1264 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1265 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1266 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1267 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1268 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1269 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1270 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1272 pup->pr_minf = p->p_ru.minflt;
1273 pup->pr_majf = p->p_ru.majflt;
1274 pup->pr_nswap = p->p_ru.nswap;
1275 pup->pr_inblk = p->p_ru.inblock;
1276 pup->pr_oublk = p->p_ru.oublock;
1277 pup->pr_msnd = p->p_ru.msgsnd;
1278 pup->pr_mrcv = p->p_ru.msgrcv;
1279 pup->pr_sigs = p->p_ru.nsignals;
1280 pup->pr_vctx = p->p_ru.nvcsw;
1281 pup->pr_ictx = p->p_ru.nivcsw;
1282 pup->pr_sysc = p->p_ru.sysc;
1283 pup->pr_ioch = p->p_ru.ioch;
1285 prcvtusage(pup, upup);
1288 * Fill one prusage struct for each active lwp.
1290 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1291 if (ldp->ld_entry == NULL ||
1292 (t = ldp->ld_entry->le_thread) == NULL)
1293 continue;
1294 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1295 ASSERT(nlwp > 0);
1296 --nlwp;
1297 upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
1298 prgetusage(t, pup);
1299 prcvtusage(pup, upup);
1301 ASSERT(nlwp == 0);
1303 prunlock(pnp);
1305 error = pr_uioread(php, size, uiop);
1306 kmem_free(pup, size + sizeof (prhusage_t));
1307 return (error);
1310 static int
1311 pr_read_pagedata(prnode_t *pnp, uio_t *uiop)
1313 proc_t *p;
1314 int error;
1316 ASSERT(pnp->pr_type == PR_PAGEDATA);
1318 if ((error = prlock(pnp, ZNO)) != 0)
1319 return (error);
1321 p = pnp->pr_common->prc_proc;
1322 if ((p->p_flag & SSYS) || p->p_as == &kas) {
1323 prunlock(pnp);
1324 return (0);
1327 mutex_exit(&p->p_lock);
1328 error = prpdread(p, pnp->pr_hatid, uiop);
1329 mutex_enter(&p->p_lock);
1331 prunlock(pnp);
1332 return (error);
1335 static int
1336 pr_read_opagedata(prnode_t *pnp, uio_t *uiop)
1338 proc_t *p;
1339 struct as *as;
1340 int error;
1342 ASSERT(pnp->pr_type == PR_OPAGEDATA);
1344 if ((error = prlock(pnp, ZNO)) != 0)
1345 return (error);
1347 p = pnp->pr_common->prc_proc;
1348 as = p->p_as;
1349 if ((p->p_flag & SSYS) || as == &kas) {
1350 prunlock(pnp);
1351 return (0);
1354 mutex_exit(&p->p_lock);
1355 error = oprpdread(as, pnp->pr_hatid, uiop);
1356 mutex_enter(&p->p_lock);
1358 prunlock(pnp);
1359 return (error);
1362 static int
1363 pr_read_watch(prnode_t *pnp, uio_t *uiop)
1365 proc_t *p;
1366 int error;
1367 prwatch_t *Bpwp;
1368 size_t size;
1369 prwatch_t *pwp;
1370 int nwarea;
1371 struct watched_area *pwarea;
1373 ASSERT(pnp->pr_type == PR_WATCH);
1375 if ((error = prlock(pnp, ZNO)) != 0)
1376 return (error);
1378 p = pnp->pr_common->prc_proc;
1379 nwarea = avl_numnodes(&p->p_warea);
1380 size = nwarea * sizeof (prwatch_t);
1381 if (uiop->uio_offset >= size) {
1382 prunlock(pnp);
1383 return (0);
1386 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1387 mutex_exit(&p->p_lock);
1388 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
1389 mutex_enter(&p->p_lock);
1390 /* p->p_nwarea can't change while process is locked */
1391 ASSERT(nwarea == avl_numnodes(&p->p_warea));
1393 /* gather the watched areas */
1394 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
1395 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
1396 pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
1397 pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
1398 pwp->pr_wflags = (int)pwarea->wa_flags;
1401 prunlock(pnp);
1403 error = pr_uioread(Bpwp, size, uiop);
1404 kmem_free(Bpwp, size);
1405 return (error);
1408 static int
1409 pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop)
1411 lwpstatus_t *sp;
1412 int error;
1414 ASSERT(pnp->pr_type == PR_LWPSTATUS);
1417 * We kmem_alloc() the lwpstatus structure because
1418 * it is so big it might blow the kernel stack.
1420 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1422 if ((error = prlock(pnp, ZNO)) != 0)
1423 goto out;
1425 if (uiop->uio_offset >= sizeof (*sp)) {
1426 prunlock(pnp);
1427 goto out;
1430 prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
1431 prunlock(pnp);
1433 error = pr_uioread(sp, sizeof (*sp), uiop);
1434 out:
1435 kmem_free(sp, sizeof (*sp));
1436 return (error);
1439 static int
1440 pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop)
1442 lwpsinfo_t lwpsinfo;
1443 proc_t *p;
1444 kthread_t *t;
1445 lwpent_t *lep;
1447 ASSERT(pnp->pr_type == PR_LWPSINFO);
1450 * We don't want the full treatment of prlock(pnp) here.
1451 * This file is world-readable and never goes invalid.
1452 * It doesn't matter if we are in the middle of an exec().
1454 p = pr_p_lock(pnp);
1455 mutex_exit(&pr_pidlock);
1456 if (p == NULL)
1457 return (ENOENT);
1458 ASSERT(p == pnp->pr_common->prc_proc);
1459 if (pnp->pr_common->prc_tslot == -1) {
1460 prunlock(pnp);
1461 return (ENOENT);
1464 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
1465 prunlock(pnp);
1466 return (0);
1469 if ((t = pnp->pr_common->prc_thread) != NULL)
1470 prgetlwpsinfo(t, &lwpsinfo);
1471 else {
1472 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
1473 bzero(&lwpsinfo, sizeof (lwpsinfo));
1474 lwpsinfo.pr_lwpid = lep->le_lwpid;
1475 lwpsinfo.pr_state = SZOMB;
1476 lwpsinfo.pr_sname = 'Z';
1477 lwpsinfo.pr_start.tv_sec = lep->le_start;
1478 lwpsinfo.pr_bindpro = PBIND_NONE;
1479 lwpsinfo.pr_bindpset = PS_NONE;
1481 prunlock(pnp);
1483 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
1486 static int
1487 pr_read_lwpusage(prnode_t *pnp, uio_t *uiop)
1489 prhusage_t *pup;
1490 prusage_t *upup;
1491 proc_t *p;
1492 int error;
1494 ASSERT(pnp->pr_type == PR_LWPUSAGE);
1496 /* allocate now, before locking the process */
1497 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1498 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1501 * We don't want the full treatment of prlock(pnp) here.
1502 * This file is world-readable and never goes invalid.
1503 * It doesn't matter if we are in the middle of an exec().
1505 p = pr_p_lock(pnp);
1506 mutex_exit(&pr_pidlock);
1507 if (p == NULL) {
1508 error = ENOENT;
1509 goto out;
1511 ASSERT(p == pnp->pr_common->prc_proc);
1512 if (pnp->pr_common->prc_thread == NULL) {
1513 prunlock(pnp);
1514 error = ENOENT;
1515 goto out;
1517 if (uiop->uio_offset >= sizeof (prusage_t)) {
1518 prunlock(pnp);
1519 error = 0;
1520 goto out;
1523 pup->pr_tstamp = gethrtime();
1524 prgetusage(pnp->pr_common->prc_thread, pup);
1526 prunlock(pnp);
1528 prcvtusage(pup, upup);
1530 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1531 out:
1532 kmem_free(pup, sizeof (*pup));
1533 kmem_free(upup, sizeof (*upup));
1534 return (error);
1537 /* ARGSUSED */
1538 static int
1539 pr_read_xregs(prnode_t *pnp, uio_t *uiop)
1541 #if defined(__sparc)
1542 proc_t *p;
1543 kthread_t *t;
1544 int error;
1545 char *xreg;
1546 size_t size;
1548 ASSERT(pnp->pr_type == PR_XREGS);
1550 xreg = kmem_zalloc(sizeof (prxregset_t), KM_SLEEP);
1552 if ((error = prlock(pnp, ZNO)) != 0)
1553 goto out;
1555 p = pnp->pr_common->prc_proc;
1556 t = pnp->pr_common->prc_thread;
1558 size = prhasx(p)? prgetprxregsize(p) : 0;
1559 if (uiop->uio_offset >= size) {
1560 prunlock(pnp);
1561 goto out;
1564 /* drop p->p_lock while (possibly) touching the stack */
1565 mutex_exit(&p->p_lock);
1566 prgetprxregs(ttolwp(t), xreg);
1567 mutex_enter(&p->p_lock);
1568 prunlock(pnp);
1570 error = pr_uioread(xreg, size, uiop);
1571 out:
1572 kmem_free(xreg, sizeof (prxregset_t));
1573 return (error);
1574 #else
1575 return (0);
1576 #endif
1579 static int
1580 pr_read_spymaster(prnode_t *pnp, uio_t *uiop)
1582 psinfo_t psinfo;
1583 int error;
1584 klwp_t *lwp;
1586 ASSERT(pnp->pr_type == PR_SPYMASTER);
1588 if ((error = prlock(pnp, ZNO)) != 0)
1589 return (error);
1591 lwp = pnp->pr_common->prc_thread->t_lwp;
1593 if (lwp->lwp_spymaster == NULL) {
1594 prunlock(pnp);
1595 return (0);
1598 bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1599 prunlock(pnp);
1601 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1604 #if defined(__sparc)
1606 static int
1607 pr_read_gwindows(prnode_t *pnp, uio_t *uiop)
1609 proc_t *p;
1610 kthread_t *t;
1611 gwindows_t *gwp;
1612 int error;
1613 size_t size;
1615 ASSERT(pnp->pr_type == PR_GWINDOWS);
1617 gwp = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP);
1619 if ((error = prlock(pnp, ZNO)) != 0)
1620 goto out;
1622 p = pnp->pr_common->prc_proc;
1623 t = pnp->pr_common->prc_thread;
1626 * Drop p->p_lock while touching the stack.
1627 * The P_PR_LOCK flag prevents the lwp from
1628 * disappearing while we do this.
1630 mutex_exit(&p->p_lock);
1631 if ((size = prnwindows(ttolwp(t))) != 0)
1632 size = sizeof (gwindows_t) -
1633 (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow);
1634 if (uiop->uio_offset >= size) {
1635 mutex_enter(&p->p_lock);
1636 prunlock(pnp);
1637 goto out;
1639 prgetwindows(ttolwp(t), gwp);
1640 mutex_enter(&p->p_lock);
1641 prunlock(pnp);
1643 error = pr_uioread(gwp, size, uiop);
1644 out:
1645 kmem_free(gwp, sizeof (gwindows_t));
1646 return (error);
1649 /* ARGSUSED */
1650 static int
1651 pr_read_asrs(prnode_t *pnp, uio_t *uiop)
1653 int error;
1655 ASSERT(pnp->pr_type == PR_ASRS);
1657 /* the asrs file exists only for sparc v9 _LP64 processes */
1658 if ((error = prlock(pnp, ZNO)) == 0) {
1659 proc_t *p = pnp->pr_common->prc_proc;
1660 kthread_t *t = pnp->pr_common->prc_thread;
1661 asrset_t asrset;
1663 if (p->p_model != DATAMODEL_LP64 ||
1664 uiop->uio_offset >= sizeof (asrset_t)) {
1665 prunlock(pnp);
1666 return (0);
1670 * Drop p->p_lock while touching the stack.
1671 * The P_PR_LOCK flag prevents the lwp from
1672 * disappearing while we do this.
1674 mutex_exit(&p->p_lock);
1675 prgetasregs(ttolwp(t), asrset);
1676 mutex_enter(&p->p_lock);
1677 prunlock(pnp);
1679 error = pr_uioread(&asrset[0], sizeof (asrset_t), uiop);
1682 return (error);
1685 #endif /* __sparc */
1687 static int
1688 pr_read_piddir(prnode_t *pnp, uio_t *uiop)
1690 ASSERT(pnp->pr_type == PR_PIDDIR);
1691 ASSERT(pnp->pr_pidfile != NULL);
1693 /* use the underlying PR_PIDFILE to read the process */
1694 pnp = VTOP(pnp->pr_pidfile);
1695 ASSERT(pnp->pr_type == PR_PIDFILE);
1697 return (pr_read_pidfile(pnp, uiop));
1700 static int
1701 pr_read_pidfile(prnode_t *pnp, uio_t *uiop)
1703 int error;
1705 ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
1707 if ((error = prlock(pnp, ZNO)) == 0) {
1708 proc_t *p = pnp->pr_common->prc_proc;
1709 struct as *as = p->p_as;
1711 if ((p->p_flag & SSYS) || as == &kas) {
1713 * /proc I/O cannot be done to a system process.
1715 error = EIO; /* old /proc semantics */
1716 } else {
1718 * We drop p_lock because we don't want to hold
1719 * it over an I/O operation because that could
1720 * lead to deadlock with the clock thread.
1721 * The process will not disappear and its address
1722 * space will not change because it is marked P_PR_LOCK.
1724 mutex_exit(&p->p_lock);
1725 error = prusrio(p, UIO_READ, uiop, 1);
1726 mutex_enter(&p->p_lock);
1728 prunlock(pnp);
1731 return (error);
1734 #ifdef _SYSCALL32_IMPL
1737 * Array of ILP32 read functions, indexed by /proc file type.
1739 static int pr_read_status_32(),
1740 pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
1741 pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
1742 pr_read_sigact_32(), pr_read_auxv_32(),
1743 pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
1744 pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1745 pr_read_lwpusage_32(), pr_read_spymaster_32(),
1746 #if defined(__sparc)
1747 pr_read_gwindows_32(),
1748 #endif
1749 pr_read_opagedata_32();
1751 static int (*pr_read_function_32[PR_NFILES])() = {
1752 pr_read_inval, /* /proc */
1753 pr_read_inval, /* /proc/self */
1754 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1755 pr_read_as, /* /proc/<pid>/as */
1756 pr_read_inval, /* /proc/<pid>/ctl */
1757 pr_read_status_32, /* /proc/<pid>/status */
1758 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1759 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1760 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1761 pr_read_map_32, /* /proc/<pid>/map */
1762 pr_read_rmap_32, /* /proc/<pid>/rmap */
1763 pr_read_xmap_32, /* /proc/<pid>/xmap */
1764 pr_read_cred, /* /proc/<pid>/cred */
1765 pr_read_sigact_32, /* /proc/<pid>/sigact */
1766 pr_read_auxv_32, /* /proc/<pid>/auxv */
1767 #if defined(__x86)
1768 pr_read_ldt, /* /proc/<pid>/ldt */
1769 #endif
1770 pr_read_usage_32, /* /proc/<pid>/usage */
1771 pr_read_lusage_32, /* /proc/<pid>/lusage */
1772 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1773 pr_read_watch_32, /* /proc/<pid>/watch */
1774 pr_read_inval, /* /proc/<pid>/cwd */
1775 pr_read_inval, /* /proc/<pid>/root */
1776 pr_read_inval, /* /proc/<pid>/fd */
1777 pr_read_inval, /* /proc/<pid>/fd/nn */
1778 pr_read_inval, /* /proc/<pid>/object */
1779 pr_read_inval, /* /proc/<pid>/object/xxx */
1780 pr_read_inval, /* /proc/<pid>/lwp */
1781 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1782 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1783 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1784 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1785 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1786 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1787 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1788 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1789 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
1790 #if defined(__sparc)
1791 pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
1792 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
1793 #endif
1794 pr_read_priv, /* /proc/<pid>/priv */
1795 pr_read_inval, /* /proc/<pid>/path */
1796 pr_read_inval, /* /proc/<pid>/path/xxx */
1797 pr_read_inval, /* /proc/<pid>/contracts */
1798 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
1799 pr_read_pidfile, /* old process file */
1800 pr_read_pidfile, /* old lwp file */
1801 pr_read_opagedata_32, /* old pagedata file */
1804 static int
1805 pr_read_status_32(prnode_t *pnp, uio_t *uiop)
1807 pstatus32_t *sp;
1808 proc_t *p;
1809 int error;
1811 ASSERT(pnp->pr_type == PR_STATUS);
1814 * We kmem_alloc() the pstatus structure because
1815 * it is so big it might blow the kernel stack.
1817 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1818 if ((error = prlock(pnp, ZNO)) == 0) {
1820 * A 32-bit process cannot get the status of a 64-bit process.
1821 * The fields for the 64-bit quantities are not large enough.
1823 p = pnp->pr_common->prc_proc;
1824 if (PROCESS_NOT_32BIT(p)) {
1825 prunlock(pnp);
1826 error = EOVERFLOW;
1827 } else {
1828 prgetstatus32(pnp->pr_common->prc_proc, sp,
1829 VTOZONE(PTOV(pnp)));
1830 prunlock(pnp);
1831 error = pr_uioread(sp, sizeof (*sp), uiop);
1834 kmem_free((caddr_t)sp, sizeof (*sp));
1835 return (error);
1838 static int
1839 pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop)
1841 proc_t *p;
1842 kthread_t *t;
1843 lwpdir_t *ldp;
1844 size_t size;
1845 prheader32_t *php;
1846 lwpstatus32_t *sp;
1847 int error;
1848 int nlwp;
1849 int i;
1851 ASSERT(pnp->pr_type == PR_LSTATUS);
1853 if ((error = prlock(pnp, ZNO)) != 0)
1854 return (error);
1855 p = pnp->pr_common->prc_proc;
1857 * A 32-bit process cannot get the status of a 64-bit process.
1858 * The fields for the 64-bit quantities are not large enough.
1860 if (PROCESS_NOT_32BIT(p)) {
1861 prunlock(pnp);
1862 return (EOVERFLOW);
1864 nlwp = p->p_lwpcnt;
1865 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
1867 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1868 mutex_exit(&p->p_lock);
1869 php = kmem_zalloc(size, KM_SLEEP);
1870 mutex_enter(&p->p_lock);
1871 /* p->p_lwpcnt can't change while process is locked */
1872 ASSERT(nlwp == p->p_lwpcnt);
1874 php->pr_nent = nlwp;
1875 php->pr_entsize = LSPAN32(lwpstatus32_t);
1877 sp = (lwpstatus32_t *)(php + 1);
1878 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1879 if (ldp->ld_entry == NULL ||
1880 (t = ldp->ld_entry->le_thread) == NULL)
1881 continue;
1882 prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
1883 sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
1885 prunlock(pnp);
1887 error = pr_uioread(php, size, uiop);
1888 kmem_free(php, size);
1889 return (error);
1892 static int
1893 pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop)
1895 psinfo32_t psinfo;
1896 proc_t *p;
1897 int error = 0;
1899 ASSERT(pnp->pr_type == PR_PSINFO);
1902 * We don't want the full treatment of prlock(pnp) here.
1903 * This file is world-readable and never goes invalid.
1904 * It doesn't matter if we are in the middle of an exec().
1906 p = pr_p_lock(pnp);
1907 mutex_exit(&pr_pidlock);
1908 if (p == NULL)
1909 error = ENOENT;
1910 else {
1911 ASSERT(p == pnp->pr_common->prc_proc);
1912 prgetpsinfo32(p, &psinfo);
1913 prunlock(pnp);
1914 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
1916 return (error);
1919 static int
1920 pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop)
1922 proc_t *p;
1923 kthread_t *t;
1924 lwpdir_t *ldp;
1925 lwpent_t *lep;
1926 size_t size;
1927 prheader32_t *php;
1928 lwpsinfo32_t *sp;
1929 int error;
1930 int nlwp;
1931 int i;
1933 ASSERT(pnp->pr_type == PR_LPSINFO);
1936 * We don't want the full treatment of prlock(pnp) here.
1937 * This file is world-readable and never goes invalid.
1938 * It doesn't matter if we are in the middle of an exec().
1940 p = pr_p_lock(pnp);
1941 mutex_exit(&pr_pidlock);
1942 if (p == NULL)
1943 return (ENOENT);
1944 ASSERT(p == pnp->pr_common->prc_proc);
1945 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
1946 prunlock(pnp);
1947 return (ENOENT);
1949 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
1951 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1952 mutex_exit(&p->p_lock);
1953 php = kmem_zalloc(size, KM_SLEEP);
1954 mutex_enter(&p->p_lock);
1955 /* p->p_lwpcnt can't change while process is locked */
1956 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
1958 php->pr_nent = nlwp;
1959 php->pr_entsize = LSPAN32(lwpsinfo32_t);
1961 sp = (lwpsinfo32_t *)(php + 1);
1962 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1963 if ((lep = ldp->ld_entry) == NULL)
1964 continue;
1965 if ((t = lep->le_thread) != NULL)
1966 prgetlwpsinfo32(t, sp);
1967 else {
1968 bzero(sp, sizeof (*sp));
1969 sp->pr_lwpid = lep->le_lwpid;
1970 sp->pr_state = SZOMB;
1971 sp->pr_sname = 'Z';
1972 sp->pr_start.tv_sec = (time32_t)lep->le_start;
1974 sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
1976 prunlock(pnp);
1978 error = pr_uioread(php, size, uiop);
1979 kmem_free(php, size);
1980 return (error);
1983 static int
1984 pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
1986 proc_t *p;
1987 struct as *as;
1988 list_t iolhead;
1989 int error;
1991 readmap32_common:
1992 if ((error = prlock(pnp, ZNO)) != 0)
1993 return (error);
1995 p = pnp->pr_common->prc_proc;
1996 as = p->p_as;
1998 if ((p->p_flag & SSYS) || as == &kas) {
1999 prunlock(pnp);
2000 return (0);
2003 if (PROCESS_NOT_32BIT(p)) {
2004 prunlock(pnp);
2005 return (EOVERFLOW);
2008 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
2009 prunlock(pnp);
2010 delay(1);
2011 goto readmap32_common;
2013 mutex_exit(&p->p_lock);
2015 switch (type) {
2016 case PR_XMAP:
2017 error = prgetxmap32(p, &iolhead);
2018 break;
2019 case PR_RMAP:
2020 error = prgetmap32(p, 1, &iolhead);
2021 break;
2022 case PR_MAP:
2023 error = prgetmap32(p, 0, &iolhead);
2024 break;
2026 AS_LOCK_EXIT(as);
2027 mutex_enter(&p->p_lock);
2028 prunlock(pnp);
2030 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
2032 return (error);
2035 static int
2036 pr_read_map_32(prnode_t *pnp, uio_t *uiop)
2038 ASSERT(pnp->pr_type == PR_MAP);
2039 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2042 static int
2043 pr_read_rmap_32(prnode_t *pnp, uio_t *uiop)
2045 ASSERT(pnp->pr_type == PR_RMAP);
2046 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2049 static int
2050 pr_read_xmap_32(prnode_t *pnp, uio_t *uiop)
2052 ASSERT(pnp->pr_type == PR_XMAP);
2053 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2056 static int
2057 pr_read_sigact_32(prnode_t *pnp, uio_t *uiop)
2059 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
2060 proc_t *p;
2061 struct sigaction32 *sap;
2062 int sig;
2063 int error;
2064 user_t *up;
2066 ASSERT(pnp->pr_type == PR_SIGACT);
2069 * We kmem_alloc() the sigaction32 array because
2070 * it is so big it might blow the kernel stack.
2072 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
2074 if ((error = prlock(pnp, ZNO)) != 0)
2075 goto out;
2076 p = pnp->pr_common->prc_proc;
2078 if (PROCESS_NOT_32BIT(p)) {
2079 prunlock(pnp);
2080 error = EOVERFLOW;
2081 goto out;
2084 if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
2085 prunlock(pnp);
2086 goto out;
2089 up = PTOU(p);
2090 for (sig = 1; sig < nsig; sig++)
2091 prgetaction32(p, up, sig, &sap[sig-1]);
2092 prunlock(pnp);
2094 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
2095 out:
2096 kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
2097 return (error);
2100 static int
2101 pr_read_auxv_32(prnode_t *pnp, uio_t *uiop)
2103 auxv32_t auxv[__KERN_NAUXV_IMPL];
2104 proc_t *p;
2105 user_t *up;
2106 int error;
2107 int i;
2109 ASSERT(pnp->pr_type == PR_AUXV);
2111 if ((error = prlock(pnp, ZNO)) != 0)
2112 return (error);
2113 p = pnp->pr_common->prc_proc;
2115 if (PROCESS_NOT_32BIT(p)) {
2116 prunlock(pnp);
2117 return (EOVERFLOW);
2120 if (uiop->uio_offset >= sizeof (auxv)) {
2121 prunlock(pnp);
2122 return (0);
2125 up = PTOU(p);
2126 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2127 auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
2128 auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
2130 prunlock(pnp);
2132 return (pr_uioread(auxv, sizeof (auxv), uiop));
2135 static int
2136 pr_read_usage_32(prnode_t *pnp, uio_t *uiop)
2138 prhusage_t *pup;
2139 prusage32_t *upup;
2140 proc_t *p;
2141 kthread_t *t;
2142 int error;
2144 ASSERT(pnp->pr_type == PR_USAGE);
2146 /* allocate now, before locking the process */
2147 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2148 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2151 * We don't want the full treatment of prlock(pnp) here.
2152 * This file is world-readable and never goes invalid.
2153 * It doesn't matter if we are in the middle of an exec().
2155 p = pr_p_lock(pnp);
2156 mutex_exit(&pr_pidlock);
2157 if (p == NULL) {
2158 error = ENOENT;
2159 goto out;
2161 ASSERT(p == pnp->pr_common->prc_proc);
2163 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2164 prunlock(pnp);
2165 error = 0;
2166 goto out;
2169 pup->pr_tstamp = gethrtime();
2171 pup->pr_count = p->p_defunct;
2172 pup->pr_create = p->p_mstart;
2173 pup->pr_term = p->p_mterm;
2175 pup->pr_rtime = p->p_mlreal;
2176 pup->pr_utime = p->p_acct[LMS_USER];
2177 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2178 pup->pr_ttime = p->p_acct[LMS_TRAP];
2179 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2180 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2181 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2182 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2183 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2184 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2185 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2187 pup->pr_minf = p->p_ru.minflt;
2188 pup->pr_majf = p->p_ru.majflt;
2189 pup->pr_nswap = p->p_ru.nswap;
2190 pup->pr_inblk = p->p_ru.inblock;
2191 pup->pr_oublk = p->p_ru.oublock;
2192 pup->pr_msnd = p->p_ru.msgsnd;
2193 pup->pr_mrcv = p->p_ru.msgrcv;
2194 pup->pr_sigs = p->p_ru.nsignals;
2195 pup->pr_vctx = p->p_ru.nvcsw;
2196 pup->pr_ictx = p->p_ru.nivcsw;
2197 pup->pr_sysc = p->p_ru.sysc;
2198 pup->pr_ioch = p->p_ru.ioch;
2201 * Add the usage information for each active lwp.
2203 if ((t = p->p_tlist) != NULL &&
2204 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
2205 do {
2206 if (t->t_proc_flag & TP_LWPEXIT)
2207 continue;
2208 pup->pr_count++;
2209 praddusage(t, pup);
2210 } while ((t = t->t_forw) != p->p_tlist);
2213 prunlock(pnp);
2215 prcvtusage32(pup, upup);
2217 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2218 out:
2219 kmem_free(pup, sizeof (*pup));
2220 kmem_free(upup, sizeof (*upup));
2221 return (error);
2224 static int
2225 pr_read_lusage_32(prnode_t *pnp, uio_t *uiop)
2227 int nlwp;
2228 prhusage_t *pup;
2229 prheader32_t *php;
2230 prusage32_t *upup;
2231 size_t size;
2232 hrtime_t curtime;
2233 proc_t *p;
2234 kthread_t *t;
2235 lwpdir_t *ldp;
2236 int error;
2237 int i;
2239 ASSERT(pnp->pr_type == PR_LUSAGE);
2242 * We don't want the full treatment of prlock(pnp) here.
2243 * This file is world-readable and never goes invalid.
2244 * It doesn't matter if we are in the middle of an exec().
2246 p = pr_p_lock(pnp);
2247 mutex_exit(&pr_pidlock);
2248 if (p == NULL)
2249 return (ENOENT);
2250 ASSERT(p == pnp->pr_common->prc_proc);
2251 if ((nlwp = p->p_lwpcnt) == 0) {
2252 prunlock(pnp);
2253 return (ENOENT);
2256 size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
2257 if (uiop->uio_offset >= size) {
2258 prunlock(pnp);
2259 return (0);
2262 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2263 mutex_exit(&p->p_lock);
2264 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
2265 mutex_enter(&p->p_lock);
2266 /* p->p_lwpcnt can't change while process is locked */
2267 ASSERT(nlwp == p->p_lwpcnt);
2269 php = (prheader32_t *)(pup + 1);
2270 upup = (prusage32_t *)(php + 1);
2272 php->pr_nent = nlwp + 1;
2273 php->pr_entsize = LSPAN32(prusage32_t);
2275 curtime = gethrtime();
2278 * First the summation over defunct lwps.
2280 pup->pr_count = p->p_defunct;
2281 pup->pr_tstamp = curtime;
2282 pup->pr_create = p->p_mstart;
2283 pup->pr_term = p->p_mterm;
2285 pup->pr_rtime = p->p_mlreal;
2286 pup->pr_utime = p->p_acct[LMS_USER];
2287 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2288 pup->pr_ttime = p->p_acct[LMS_TRAP];
2289 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2290 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2291 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2292 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2293 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2294 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2295 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2297 pup->pr_minf = p->p_ru.minflt;
2298 pup->pr_majf = p->p_ru.majflt;
2299 pup->pr_nswap = p->p_ru.nswap;
2300 pup->pr_inblk = p->p_ru.inblock;
2301 pup->pr_oublk = p->p_ru.oublock;
2302 pup->pr_msnd = p->p_ru.msgsnd;
2303 pup->pr_mrcv = p->p_ru.msgrcv;
2304 pup->pr_sigs = p->p_ru.nsignals;
2305 pup->pr_vctx = p->p_ru.nvcsw;
2306 pup->pr_ictx = p->p_ru.nivcsw;
2307 pup->pr_sysc = p->p_ru.sysc;
2308 pup->pr_ioch = p->p_ru.ioch;
2310 prcvtusage32(pup, upup);
2313 * Fill one prusage struct for each active lwp.
2315 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2316 if (ldp->ld_entry == NULL ||
2317 (t = ldp->ld_entry->le_thread) == NULL)
2318 continue;
2319 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2320 ASSERT(nlwp > 0);
2321 --nlwp;
2322 upup = (prusage32_t *)
2323 ((caddr_t)upup + LSPAN32(prusage32_t));
2324 prgetusage(t, pup);
2325 prcvtusage32(pup, upup);
2327 ASSERT(nlwp == 0);
2329 prunlock(pnp);
2331 error = pr_uioread(php, size, uiop);
2332 kmem_free(pup, size + sizeof (prhusage_t));
2333 return (error);
2336 static int
2337 pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop)
2339 proc_t *p;
2340 int error;
2342 ASSERT(pnp->pr_type == PR_PAGEDATA);
2344 if ((error = prlock(pnp, ZNO)) != 0)
2345 return (error);
2347 p = pnp->pr_common->prc_proc;
2348 if ((p->p_flag & SSYS) || p->p_as == &kas) {
2349 prunlock(pnp);
2350 return (0);
2353 if (PROCESS_NOT_32BIT(p)) {
2354 prunlock(pnp);
2355 return (EOVERFLOW);
2358 mutex_exit(&p->p_lock);
2359 error = prpdread32(p, pnp->pr_hatid, uiop);
2360 mutex_enter(&p->p_lock);
2362 prunlock(pnp);
2363 return (error);
2366 static int
2367 pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop)
2369 proc_t *p;
2370 struct as *as;
2371 int error;
2373 ASSERT(pnp->pr_type == PR_OPAGEDATA);
2375 if ((error = prlock(pnp, ZNO)) != 0)
2376 return (error);
2378 p = pnp->pr_common->prc_proc;
2379 as = p->p_as;
2381 if ((p->p_flag & SSYS) || as == &kas) {
2382 prunlock(pnp);
2383 return (0);
2386 if (PROCESS_NOT_32BIT(p)) {
2387 prunlock(pnp);
2388 return (EOVERFLOW);
2391 mutex_exit(&p->p_lock);
2392 error = oprpdread32(as, pnp->pr_hatid, uiop);
2393 mutex_enter(&p->p_lock);
2395 prunlock(pnp);
2396 return (error);
2399 static int
2400 pr_read_watch_32(prnode_t *pnp, uio_t *uiop)
2402 proc_t *p;
2403 int error;
2404 prwatch32_t *Bpwp;
2405 size_t size;
2406 prwatch32_t *pwp;
2407 int nwarea;
2408 struct watched_area *pwarea;
2410 ASSERT(pnp->pr_type == PR_WATCH);
2412 if ((error = prlock(pnp, ZNO)) != 0)
2413 return (error);
2415 p = pnp->pr_common->prc_proc;
2416 if (PROCESS_NOT_32BIT(p)) {
2417 prunlock(pnp);
2418 return (EOVERFLOW);
2420 nwarea = avl_numnodes(&p->p_warea);
2421 size = nwarea * sizeof (prwatch32_t);
2422 if (uiop->uio_offset >= size) {
2423 prunlock(pnp);
2424 return (0);
2427 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2428 mutex_exit(&p->p_lock);
2429 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
2430 mutex_enter(&p->p_lock);
2431 /* p->p_nwarea can't change while process is locked */
2432 ASSERT(nwarea == avl_numnodes(&p->p_warea));
2434 /* gather the watched areas */
2435 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
2436 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
2437 pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
2438 pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
2439 pwp->pr_wflags = (int)pwarea->wa_flags;
2442 prunlock(pnp);
2444 error = pr_uioread(Bpwp, size, uiop);
2445 kmem_free(Bpwp, size);
2446 return (error);
2449 static int
2450 pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop)
2452 lwpstatus32_t *sp;
2453 proc_t *p;
2454 int error;
2456 ASSERT(pnp->pr_type == PR_LWPSTATUS);
2459 * We kmem_alloc() the lwpstatus structure because
2460 * it is so big it might blow the kernel stack.
2462 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
2464 if ((error = prlock(pnp, ZNO)) != 0)
2465 goto out;
2468 * A 32-bit process cannot get the status of a 64-bit process.
2469 * The fields for the 64-bit quantities are not large enough.
2471 p = pnp->pr_common->prc_proc;
2472 if (PROCESS_NOT_32BIT(p)) {
2473 prunlock(pnp);
2474 error = EOVERFLOW;
2475 goto out;
2478 if (uiop->uio_offset >= sizeof (*sp)) {
2479 prunlock(pnp);
2480 goto out;
2483 prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
2484 prunlock(pnp);
2486 error = pr_uioread(sp, sizeof (*sp), uiop);
2487 out:
2488 kmem_free(sp, sizeof (*sp));
2489 return (error);
2492 static int
2493 pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop)
2495 lwpsinfo32_t lwpsinfo;
2496 proc_t *p;
2497 kthread_t *t;
2498 lwpent_t *lep;
2500 ASSERT(pnp->pr_type == PR_LWPSINFO);
2503 * We don't want the full treatment of prlock(pnp) here.
2504 * This file is world-readable and never goes invalid.
2505 * It doesn't matter if we are in the middle of an exec().
2507 p = pr_p_lock(pnp);
2508 mutex_exit(&pr_pidlock);
2509 if (p == NULL)
2510 return (ENOENT);
2511 ASSERT(p == pnp->pr_common->prc_proc);
2512 if (pnp->pr_common->prc_tslot == -1) {
2513 prunlock(pnp);
2514 return (ENOENT);
2517 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
2518 prunlock(pnp);
2519 return (0);
2522 if ((t = pnp->pr_common->prc_thread) != NULL)
2523 prgetlwpsinfo32(t, &lwpsinfo);
2524 else {
2525 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
2526 bzero(&lwpsinfo, sizeof (lwpsinfo));
2527 lwpsinfo.pr_lwpid = lep->le_lwpid;
2528 lwpsinfo.pr_state = SZOMB;
2529 lwpsinfo.pr_sname = 'Z';
2530 lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
2532 prunlock(pnp);
2534 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
2537 static int
2538 pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop)
2540 prhusage_t *pup;
2541 prusage32_t *upup;
2542 proc_t *p;
2543 int error;
2545 ASSERT(pnp->pr_type == PR_LWPUSAGE);
2547 /* allocate now, before locking the process */
2548 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2549 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2552 * We don't want the full treatment of prlock(pnp) here.
2553 * This file is world-readable and never goes invalid.
2554 * It doesn't matter if we are in the middle of an exec().
2556 p = pr_p_lock(pnp);
2557 mutex_exit(&pr_pidlock);
2558 if (p == NULL) {
2559 error = ENOENT;
2560 goto out;
2562 ASSERT(p == pnp->pr_common->prc_proc);
2563 if (pnp->pr_common->prc_thread == NULL) {
2564 prunlock(pnp);
2565 error = ENOENT;
2566 goto out;
2568 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2569 prunlock(pnp);
2570 error = 0;
2571 goto out;
2574 pup->pr_tstamp = gethrtime();
2575 prgetusage(pnp->pr_common->prc_thread, pup);
2577 prunlock(pnp);
2579 prcvtusage32(pup, upup);
2581 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2582 out:
2583 kmem_free(pup, sizeof (*pup));
2584 kmem_free(upup, sizeof (*upup));
2585 return (error);
2588 static int
2589 pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop)
2591 psinfo32_t psinfo;
2592 int error;
2593 klwp_t *lwp;
2595 ASSERT(pnp->pr_type == PR_SPYMASTER);
2597 if ((error = prlock(pnp, ZNO)) != 0)
2598 return (error);
2600 lwp = pnp->pr_common->prc_thread->t_lwp;
2602 if (lwp->lwp_spymaster == NULL) {
2603 prunlock(pnp);
2604 return (0);
2607 psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2608 prunlock(pnp);
2610 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2613 #if defined(__sparc)
2614 static int
2615 pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop)
2617 proc_t *p;
2618 kthread_t *t;
2619 gwindows32_t *gwp;
2620 int error;
2621 size_t size;
2623 ASSERT(pnp->pr_type == PR_GWINDOWS);
2625 gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
2627 if ((error = prlock(pnp, ZNO)) != 0)
2628 goto out;
2630 p = pnp->pr_common->prc_proc;
2631 t = pnp->pr_common->prc_thread;
2633 if (PROCESS_NOT_32BIT(p)) {
2634 prunlock(pnp);
2635 error = EOVERFLOW;
2636 goto out;
2640 * Drop p->p_lock while touching the stack.
2641 * The P_PR_LOCK flag prevents the lwp from
2642 * disappearing while we do this.
2644 mutex_exit(&p->p_lock);
2645 if ((size = prnwindows(ttolwp(t))) != 0)
2646 size = sizeof (gwindows32_t) -
2647 (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
2648 if (uiop->uio_offset >= size) {
2649 mutex_enter(&p->p_lock);
2650 prunlock(pnp);
2651 goto out;
2653 prgetwindows32(ttolwp(t), gwp);
2654 mutex_enter(&p->p_lock);
2655 prunlock(pnp);
2657 error = pr_uioread(gwp, size, uiop);
2658 out:
2659 kmem_free(gwp, sizeof (gwindows32_t));
2660 return (error);
2662 #endif /* __sparc */
2664 #endif /* _SYSCALL32_IMPL */
2666 /* ARGSUSED */
2667 static int
2668 prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2670 prnode_t *pnp = VTOP(vp);
2672 ASSERT(pnp->pr_type < PR_NFILES);
2674 #ifdef _SYSCALL32_IMPL
2676 * What is read from the /proc files depends on the data
2677 * model of the caller. An LP64 process will see LP64
2678 * data. An ILP32 process will see ILP32 data.
2680 if (curproc->p_model == DATAMODEL_LP64)
2681 return (pr_read_function[pnp->pr_type](pnp, uiop));
2682 else
2683 return (pr_read_function_32[pnp->pr_type](pnp, uiop));
2684 #else
2685 return (pr_read_function[pnp->pr_type](pnp, uiop));
2686 #endif
2689 /* ARGSUSED */
2690 static int
2691 prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2693 prnode_t *pnp = VTOP(vp);
2694 int old = 0;
2695 int error;
2696 ssize_t resid;
2698 ASSERT(pnp->pr_type < PR_NFILES);
2701 * Only a handful of /proc files are writable, enumerate them here.
2703 switch (pnp->pr_type) {
2704 case PR_PIDDIR: /* directory write()s: visceral revulsion. */
2705 ASSERT(pnp->pr_pidfile != NULL);
2706 /* use the underlying PR_PIDFILE to write the process */
2707 vp = pnp->pr_pidfile;
2708 pnp = VTOP(vp);
2709 ASSERT(pnp->pr_type == PR_PIDFILE);
2710 /* FALLTHROUGH */
2711 case PR_PIDFILE:
2712 case PR_LWPIDFILE:
2713 old = 1;
2714 /* FALLTHROUGH */
2715 case PR_AS:
2716 if ((error = prlock(pnp, ZNO)) == 0) {
2717 proc_t *p = pnp->pr_common->prc_proc;
2718 struct as *as = p->p_as;
2720 if ((p->p_flag & SSYS) || as == &kas) {
2722 * /proc I/O cannot be done to a system process.
2724 error = EIO;
2725 #ifdef _SYSCALL32_IMPL
2726 } else if (curproc->p_model == DATAMODEL_ILP32 &&
2727 PROCESS_NOT_32BIT(p)) {
2728 error = EOVERFLOW;
2729 #endif
2730 } else {
2732 * See comments above (pr_read_pidfile)
2733 * about this locking dance.
2735 mutex_exit(&p->p_lock);
2736 error = prusrio(p, UIO_WRITE, uiop, old);
2737 mutex_enter(&p->p_lock);
2739 prunlock(pnp);
2741 return (error);
2743 case PR_CTL:
2744 case PR_LWPCTL:
2745 resid = uiop->uio_resid;
2747 * Perform the action on the control file
2748 * by passing curthreads credentials
2749 * and not target process's credentials.
2751 #ifdef _SYSCALL32_IMPL
2752 if (curproc->p_model == DATAMODEL_ILP32)
2753 error = prwritectl32(vp, uiop, CRED());
2754 else
2755 error = prwritectl(vp, uiop, CRED());
2756 #else
2757 error = prwritectl(vp, uiop, CRED());
2758 #endif
2760 * This hack makes sure that the EINTR is passed
2761 * all the way back to the caller's write() call.
2763 if (error == EINTR)
2764 uiop->uio_resid = resid;
2765 return (error);
2767 default:
2768 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2770 /* NOTREACHED */
2773 static int
2774 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2775 caller_context_t *ct)
2777 prnode_t *pnp = VTOP(vp);
2778 prnodetype_t type = pnp->pr_type;
2779 prcommon_t *pcp;
2780 proc_t *p;
2781 struct as *as;
2782 int error;
2783 vnode_t *rvp;
2784 timestruc_t now;
2785 extern uint_t nproc;
2786 int ngroups;
2787 int nsig;
2790 * This ugly bit of code allows us to keep both versions of this
2791 * function from the same source.
2793 #ifdef _LP64
2794 int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
2795 #define PR_OBJSIZE(obj32, obj64) \
2796 (iam32bit ? sizeof (obj32) : sizeof (obj64))
2797 #define PR_OBJSPAN(obj32, obj64) \
2798 (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
2799 #else
2800 #define PR_OBJSIZE(obj32, obj64) \
2801 (sizeof (obj64))
2802 #define PR_OBJSPAN(obj32, obj64) \
2803 (LSPAN(obj64))
2804 #endif
2807 * Return all the attributes. Should be refined
2808 * so that it returns only those asked for.
2809 * Most of this is complete fakery anyway.
2813 * For files in the /proc/<pid>/object directory,
2814 * return the attributes of the underlying object.
2815 * For files in the /proc/<pid>/fd directory,
2816 * return the attributes of the underlying file, but
2817 * make it look inaccessible if it is not a regular file.
2818 * Make directories look like symlinks.
2820 switch (type) {
2821 case PR_CURDIR:
2822 case PR_ROOTDIR:
2823 if (!(flags & ATTR_REAL))
2824 break;
2825 /* restrict full knowledge of the attributes to owner or root */
2826 if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
2827 return (error);
2828 /* FALLTHROUGH */
2829 case PR_OBJECT:
2830 case PR_FD:
2831 rvp = pnp->pr_realvp;
2832 error = VOP_GETATTR(rvp, vap, flags, cr, ct);
2833 if (error)
2834 return (error);
2835 if (type == PR_FD) {
2836 if (rvp->v_type != VREG && rvp->v_type != VDIR)
2837 vap->va_mode = 0;
2838 else
2839 vap->va_mode &= pnp->pr_mode;
2841 if (type == PR_OBJECT)
2842 vap->va_mode &= 07555;
2843 if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
2844 vap->va_type = VLNK;
2845 vap->va_size = 0;
2846 vap->va_nlink = 1;
2848 return (0);
2849 default:
2850 break;
2853 bzero(vap, sizeof (*vap));
2855 * Large Files: Internally proc now uses VPROC to indicate
2856 * a proc file. Since we have been returning VREG through
2857 * VOP_GETATTR() until now, we continue to do this so as
2858 * not to break apps depending on this return value.
2860 vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
2861 vap->va_mode = pnp->pr_mode;
2862 vap->va_fsid = vp->v_vfsp->vfs_dev;
2863 vap->va_blksize = DEV_BSIZE;
2864 vap->va_rdev = 0;
2865 vap->va_seq = 0;
2867 if (type == PR_PROCDIR) {
2868 vap->va_uid = 0;
2869 vap->va_gid = 0;
2870 vap->va_nlink = nproc + 2;
2871 vap->va_nodeid = (ino64_t)PRROOTINO;
2872 gethrestime(&now);
2873 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
2874 vap->va_size = (v.v_proc + 2) * PRSDSIZE;
2875 vap->va_nblocks = btod(vap->va_size);
2876 return (0);
2880 * /proc/<pid>/self is a symbolic link, and has no prcommon member
2882 if (type == PR_SELF) {
2883 vap->va_uid = crgetruid(CRED());
2884 vap->va_gid = crgetrgid(CRED());
2885 vap->va_nodeid = (ino64_t)PR_SELF;
2886 gethrestime(&now);
2887 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
2888 vap->va_nlink = 1;
2889 vap->va_type = VLNK;
2890 vap->va_size = 0;
2891 return (0);
2894 p = pr_p_lock(pnp);
2895 mutex_exit(&pr_pidlock);
2896 if (p == NULL)
2897 return (ENOENT);
2898 pcp = pnp->pr_common;
2900 mutex_enter(&p->p_crlock);
2901 vap->va_uid = crgetruid(p->p_cred);
2902 vap->va_gid = crgetrgid(p->p_cred);
2903 mutex_exit(&p->p_crlock);
2905 vap->va_nlink = 1;
2906 vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
2907 pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
2908 if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
2909 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
2910 vap->va_ctime.tv_sec =
2911 p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
2912 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
2913 vap->va_ctime.tv_nsec = 0;
2914 } else {
2915 user_t *up = PTOU(p);
2916 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
2917 vap->va_ctime.tv_sec = up->u_start.tv_sec;
2918 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
2919 vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
2922 switch (type) {
2923 case PR_PIDDIR:
2924 /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
2925 vap->va_nlink = 5;
2926 vap->va_size = sizeof (piddir);
2927 break;
2928 case PR_OBJECTDIR:
2929 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2930 vap->va_size = 2 * PRSDSIZE;
2931 else {
2932 mutex_exit(&p->p_lock);
2933 AS_LOCK_ENTER(as, RW_WRITER);
2934 if (as->a_updatedir)
2935 rebuild_objdir(as);
2936 vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
2937 AS_LOCK_EXIT(as);
2938 mutex_enter(&p->p_lock);
2940 vap->va_nlink = 2;
2941 break;
2942 case PR_PATHDIR:
2943 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2944 vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
2945 else {
2946 mutex_exit(&p->p_lock);
2947 AS_LOCK_ENTER(as, RW_WRITER);
2948 if (as->a_updatedir)
2949 rebuild_objdir(as);
2950 vap->va_size = (as->a_sizedir + 4 +
2951 P_FINFO(p)->fi_nfiles) * PRSDSIZE;
2952 AS_LOCK_EXIT(as);
2953 mutex_enter(&p->p_lock);
2955 vap->va_nlink = 2;
2956 break;
2957 case PR_PATH:
2958 case PR_CURDIR:
2959 case PR_ROOTDIR:
2960 case PR_CT:
2961 vap->va_type = VLNK;
2962 vap->va_size = 0;
2963 break;
2964 case PR_FDDIR:
2965 vap->va_nlink = 2;
2966 vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
2967 break;
2968 case PR_LWPDIR:
2970 * va_nlink: count each lwp as a directory link.
2971 * va_size: size of p_lwpdir + 2
2973 vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
2974 vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
2975 break;
2976 case PR_LWPIDDIR:
2977 vap->va_nlink = 2;
2978 vap->va_size = sizeof (lwpiddir);
2979 break;
2980 case PR_CTDIR:
2981 vap->va_nlink = 2;
2982 vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
2983 break;
2984 case PR_TMPLDIR:
2985 vap->va_nlink = 2;
2986 vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
2987 break;
2988 case PR_AS:
2989 case PR_PIDFILE:
2990 case PR_LWPIDFILE:
2991 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2992 vap->va_size = 0;
2993 else
2994 vap->va_size = as->a_resvsize;
2995 break;
2996 case PR_STATUS:
2997 vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
2998 break;
2999 case PR_LSTATUS:
3000 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3001 p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
3002 break;
3003 case PR_PSINFO:
3004 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3005 break;
3006 case PR_LPSINFO:
3007 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3008 (p->p_lwpcnt + p->p_zombcnt) *
3009 PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
3010 break;
3011 case PR_MAP:
3012 case PR_RMAP:
3013 case PR_XMAP:
3014 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3015 vap->va_size = 0;
3016 else {
3017 mutex_exit(&p->p_lock);
3018 AS_LOCK_ENTER(as, RW_WRITER);
3019 if (type == PR_MAP)
3020 vap->va_mtime = as->a_updatetime;
3021 if (type == PR_XMAP)
3022 vap->va_size = prnsegs(as, 0) *
3023 PR_OBJSIZE(prxmap32_t, prxmap_t);
3024 else
3025 vap->va_size = prnsegs(as, type == PR_RMAP) *
3026 PR_OBJSIZE(prmap32_t, prmap_t);
3027 AS_LOCK_EXIT(as);
3028 mutex_enter(&p->p_lock);
3030 break;
3031 case PR_CRED:
3032 mutex_enter(&p->p_crlock);
3033 vap->va_size = sizeof (prcred_t);
3034 ngroups = crgetngroups(p->p_cred);
3035 if (ngroups > 1)
3036 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3037 mutex_exit(&p->p_crlock);
3038 break;
3039 case PR_PRIV:
3040 vap->va_size = prgetprivsize();
3041 break;
3042 case PR_SIGACT:
3043 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3044 vap->va_size = (nsig-1) *
3045 PR_OBJSIZE(struct sigaction32, struct sigaction);
3046 break;
3047 case PR_AUXV:
3048 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3049 break;
3050 #if defined(__x86)
3051 case PR_LDT:
3052 mutex_exit(&p->p_lock);
3053 mutex_enter(&p->p_ldtlock);
3054 vap->va_size = prnldt(p) * sizeof (struct ssd);
3055 mutex_exit(&p->p_ldtlock);
3056 mutex_enter(&p->p_lock);
3057 break;
3058 #endif
3059 case PR_USAGE:
3060 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3061 break;
3062 case PR_LUSAGE:
3063 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3064 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3065 break;
3066 case PR_PAGEDATA:
3067 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3068 vap->va_size = 0;
3069 else {
3071 * We can drop p->p_lock before grabbing the
3072 * address space lock because p->p_as will not
3073 * change while the process is marked P_PR_LOCK.
3075 mutex_exit(&p->p_lock);
3076 AS_LOCK_ENTER(as, RW_WRITER);
3077 #ifdef _LP64
3078 vap->va_size = iam32bit?
3079 prpdsize32(as) : prpdsize(as);
3080 #else
3081 vap->va_size = prpdsize(as);
3082 #endif
3083 AS_LOCK_EXIT(as);
3084 mutex_enter(&p->p_lock);
3086 break;
3087 case PR_OPAGEDATA:
3088 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3089 vap->va_size = 0;
3090 else {
3091 mutex_exit(&p->p_lock);
3092 AS_LOCK_ENTER(as, RW_WRITER);
3093 #ifdef _LP64
3094 vap->va_size = iam32bit?
3095 oprpdsize32(as) : oprpdsize(as);
3096 #else
3097 vap->va_size = oprpdsize(as);
3098 #endif
3099 AS_LOCK_EXIT(as);
3100 mutex_enter(&p->p_lock);
3102 break;
3103 case PR_WATCH:
3104 vap->va_size = avl_numnodes(&p->p_warea) *
3105 PR_OBJSIZE(prwatch32_t, prwatch_t);
3106 break;
3107 case PR_LWPSTATUS:
3108 vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
3109 break;
3110 case PR_LWPSINFO:
3111 vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
3112 break;
3113 case PR_LWPUSAGE:
3114 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3115 break;
3116 case PR_XREGS:
3117 if (prhasx(p))
3118 vap->va_size = prgetprxregsize(p);
3119 else
3120 vap->va_size = 0;
3121 break;
3122 case PR_SPYMASTER:
3123 if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3124 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3125 } else {
3126 vap->va_size = 0;
3128 break;
3129 #if defined(__sparc)
3130 case PR_GWINDOWS:
3132 kthread_t *t;
3133 int n;
3136 * If there is no lwp then just make the size zero.
3137 * This can happen if the lwp exits between the VOP_LOOKUP()
3138 * of the /proc/<pid>/lwp/<lwpid>/gwindows file and the
3139 * VOP_GETATTR() of the resulting vnode.
3141 if ((t = pcp->prc_thread) == NULL) {
3142 vap->va_size = 0;
3143 break;
3146 * Drop p->p_lock while touching the stack.
3147 * The P_PR_LOCK flag prevents the lwp from
3148 * disappearing while we do this.
3150 mutex_exit(&p->p_lock);
3151 if ((n = prnwindows(ttolwp(t))) == 0)
3152 vap->va_size = 0;
3153 else
3154 vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
3155 (SPARC_MAXREGWINDOW - n) *
3156 PR_OBJSIZE(struct rwindow32, struct rwindow);
3157 mutex_enter(&p->p_lock);
3158 break;
3160 case PR_ASRS:
3161 #ifdef _LP64
3162 if (p->p_model == DATAMODEL_LP64)
3163 vap->va_size = sizeof (asrset_t);
3164 else
3165 #endif
3166 vap->va_size = 0;
3167 break;
3168 #endif
3169 case PR_CTL:
3170 case PR_LWPCTL:
3171 default:
3172 vap->va_size = 0;
3173 break;
3176 prunlock(pnp);
3177 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3178 return (0);
3181 static int
3182 praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3184 prnode_t *pnp = VTOP(vp);
3185 prnodetype_t type = pnp->pr_type;
3186 int vmode;
3187 vtype_t vtype;
3188 proc_t *p;
3189 int error = 0;
3190 vnode_t *rvp;
3191 vnode_t *xvp;
3193 if ((mode & VWRITE) && vn_is_readonly(vp))
3194 return (EROFS);
3196 switch (type) {
3197 case PR_PROCDIR:
3198 break;
3200 case PR_OBJECT:
3201 case PR_FD:
3203 * Disallow write access to the underlying objects.
3204 * Disallow access to underlying non-regular-file fds.
3205 * Disallow access to fds with other than existing open modes.
3207 rvp = pnp->pr_realvp;
3208 vtype = rvp->v_type;
3209 vmode = pnp->pr_mode;
3210 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3211 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3212 (type == PR_FD && (vmode & mode) != mode &&
3213 secpolicy_proc_access(cr) != 0))
3214 return (EACCES);
3215 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3217 case PR_PSINFO: /* these files can be read by anyone */
3218 case PR_LPSINFO:
3219 case PR_LWPSINFO:
3220 case PR_LWPDIR:
3221 case PR_LWPIDDIR:
3222 case PR_USAGE:
3223 case PR_LUSAGE:
3224 case PR_LWPUSAGE:
3225 p = pr_p_lock(pnp);
3226 mutex_exit(&pr_pidlock);
3227 if (p == NULL)
3228 return (ENOENT);
3229 prunlock(pnp);
3230 break;
3232 default:
3234 * Except for the world-readable files above,
3235 * only /proc/pid exists if the process is a zombie.
3237 if ((error = prlock(pnp,
3238 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3239 return (error);
3240 p = pnp->pr_common->prc_proc;
3241 if (p != curproc)
3242 error = priv_proc_cred_perm(cr, p, NULL, mode);
3244 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3245 p->p_as == &kas || (xvp = p->p_exec) == NULL) {
3246 prunlock(pnp);
3247 } else {
3249 * Determine if the process's executable is readable.
3250 * We have to drop p->p_lock before the secpolicy
3251 * and VOP operation.
3253 VN_HOLD(xvp);
3254 prunlock(pnp);
3255 if (secpolicy_proc_access(cr) != 0)
3256 error = VOP_ACCESS(xvp, VREAD, 0, cr, ct);
3257 VN_RELE(xvp);
3259 if (error)
3260 return (error);
3261 break;
3264 if (type == PR_CURDIR || type == PR_ROOTDIR) {
3266 * Final access check on the underlying directory vnode.
3268 return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
3272 * Visceral revulsion: For compatibility with old /proc,
3273 * allow the /proc/<pid> directory to be opened for writing.
3275 vmode = pnp->pr_mode;
3276 if (type == PR_PIDDIR)
3277 vmode |= VWRITE;
3278 if ((vmode & mode) != mode)
3279 error = secpolicy_proc_access(cr);
3280 return (error);
3284 * Array of lookup functions, indexed by /proc file type.
3286 static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3287 *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3288 *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
3289 *pr_lookup_ctdir();
3291 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3292 pr_lookup_procdir, /* /proc */
3293 pr_lookup_notdir, /* /proc/self */
3294 pr_lookup_piddir, /* /proc/<pid> */
3295 pr_lookup_notdir, /* /proc/<pid>/as */
3296 pr_lookup_notdir, /* /proc/<pid>/ctl */
3297 pr_lookup_notdir, /* /proc/<pid>/status */
3298 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3299 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3300 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3301 pr_lookup_notdir, /* /proc/<pid>/map */
3302 pr_lookup_notdir, /* /proc/<pid>/rmap */
3303 pr_lookup_notdir, /* /proc/<pid>/xmap */
3304 pr_lookup_notdir, /* /proc/<pid>/cred */
3305 pr_lookup_notdir, /* /proc/<pid>/sigact */
3306 pr_lookup_notdir, /* /proc/<pid>/auxv */
3307 #if defined(__x86)
3308 pr_lookup_notdir, /* /proc/<pid>/ldt */
3309 #endif
3310 pr_lookup_notdir, /* /proc/<pid>/usage */
3311 pr_lookup_notdir, /* /proc/<pid>/lusage */
3312 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3313 pr_lookup_notdir, /* /proc/<pid>/watch */
3314 pr_lookup_notdir, /* /proc/<pid>/cwd */
3315 pr_lookup_notdir, /* /proc/<pid>/root */
3316 pr_lookup_fddir, /* /proc/<pid>/fd */
3317 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3318 pr_lookup_objectdir, /* /proc/<pid>/object */
3319 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3320 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3321 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3322 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3323 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3324 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3325 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3326 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3327 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3328 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3329 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
3330 #if defined(__sparc)
3331 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
3332 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
3333 #endif
3334 pr_lookup_notdir, /* /proc/<pid>/priv */
3335 pr_lookup_pathdir, /* /proc/<pid>/path */
3336 pr_lookup_notdir, /* /proc/<pid>/path/xxx */
3337 pr_lookup_ctdir, /* /proc/<pid>/contracts */
3338 pr_lookup_notdir, /* /proc/<pid>/contracts/<ctid> */
3339 pr_lookup_notdir, /* old process file */
3340 pr_lookup_notdir, /* old lwp file */
3341 pr_lookup_notdir, /* old pagedata file */
3344 static int
3345 prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3346 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3347 int *direntflags, pathname_t *realpnp)
3349 prnode_t *pnp = VTOP(dp);
3350 prnodetype_t type = pnp->pr_type;
3351 int error;
3353 ASSERT(dp->v_type == VDIR);
3354 ASSERT(type < PR_NFILES);
3356 if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
3357 VN_HOLD(pnp->pr_parent);
3358 *vpp = pnp->pr_parent;
3359 return (0);
3362 if (*comp == '\0' ||
3363 strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
3364 VN_HOLD(dp);
3365 *vpp = dp;
3366 return (0);
3369 switch (type) {
3370 case PR_CURDIR:
3371 case PR_ROOTDIR:
3372 /* restrict lookup permission to owner or root */
3373 if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3374 return (error);
3375 /* FALLTHROUGH */
3376 case PR_FD:
3377 dp = pnp->pr_realvp;
3378 return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3379 direntflags, realpnp));
3380 default:
3381 break;
3384 if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
3385 (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3386 return (error);
3388 /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3389 *vpp = (pr_lookup_function[type](dp, comp));
3391 return ((*vpp == NULL) ? ENOENT : 0);
3394 /* ARGSUSED */
3395 static int
3396 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3397 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3398 vsecattr_t *vsecp)
3400 int error;
3402 if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3403 ct, NULL, NULL)) != 0) {
3404 if (error == ENOENT) /* can't O_CREAT nonexistent files */
3405 error = EACCES; /* unwriteable directories */
3406 } else {
3407 if (excl == EXCL) /* O_EXCL */
3408 error = EEXIST;
3409 else if (vap->va_mask & AT_SIZE) { /* O_TRUNC */
3410 vnode_t *vp = *vpp;
3411 uint_t mask;
3413 if (vp->v_type == VDIR)
3414 error = EISDIR;
3415 else if (vp->v_type != VPROC ||
3416 VTOP(vp)->pr_type != PR_FD)
3417 error = EACCES;
3418 else { /* /proc/<pid>/fd/<n> */
3419 vp = VTOP(vp)->pr_realvp;
3420 mask = vap->va_mask;
3421 vap->va_mask = AT_SIZE;
3422 error = VOP_SETATTR(vp, vap, 0, cr, ct);
3423 vap->va_mask = mask;
3426 if (error) {
3427 VN_RELE(*vpp);
3428 *vpp = NULL;
3431 return (error);
3434 /* ARGSUSED */
3435 static vnode_t *
3436 pr_lookup_notdir(vnode_t *dp, char *comp)
3438 return (NULL);
3442 * Find or construct a process vnode for the given pid.
3444 static vnode_t *
3445 pr_lookup_procdir(vnode_t *dp, char *comp)
3447 pid_t pid;
3448 prnode_t *pnp;
3449 prcommon_t *pcp;
3450 vnode_t *vp;
3451 proc_t *p;
3452 int c;
3454 ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
3456 if (strcmp(comp, "self") == 0) {
3457 pnp = prgetnode(dp, PR_SELF);
3458 return (PTOV(pnp));
3459 } else {
3460 pid = 0;
3461 while ((c = *comp++) != '\0') {
3462 if (c < '0' || c > '9')
3463 return (NULL);
3464 pid = 10*pid + c - '0';
3465 if (pid > maxpid)
3466 return (NULL);
3470 pnp = prgetnode(dp, PR_PIDDIR);
3472 mutex_enter(&pidlock);
3473 if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
3474 mutex_exit(&pidlock);
3475 prfreenode(pnp);
3476 return (NULL);
3478 ASSERT(p->p_stat != 0);
3480 /* NOTE: we're holding pidlock across the policy call. */
3481 if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3482 mutex_exit(&pidlock);
3483 prfreenode(pnp);
3484 return (NULL);
3487 mutex_enter(&p->p_lock);
3488 mutex_exit(&pidlock);
3491 * If a process vnode already exists and it is not invalid
3492 * and it was created by the current process and it belongs
3493 * to the same /proc mount point as our parent vnode, then
3494 * just use it and discard the newly-allocated prnode.
3496 for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3497 if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
3498 VTOP(vp)->pr_owner == curproc &&
3499 vp->v_vfsp == dp->v_vfsp) {
3500 ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
3501 VN_HOLD(vp);
3502 prfreenode(pnp);
3503 mutex_exit(&p->p_lock);
3504 return (vp);
3507 pnp->pr_owner = curproc;
3510 * prgetnode() initialized most of the prnode.
3511 * Finish the job.
3513 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
3514 if ((vp = p->p_trace) != NULL) {
3515 /* discard the new prcommon and use the existing prcommon */
3516 prfreecommon(pcp);
3517 pcp = VTOP(vp)->pr_common;
3518 mutex_enter(&pcp->prc_mutex);
3519 ASSERT(pcp->prc_refcnt > 0);
3520 pcp->prc_refcnt++;
3521 mutex_exit(&pcp->prc_mutex);
3522 pnp->pr_common = pcp;
3523 } else {
3524 /* initialize the new prcommon struct */
3525 if ((p->p_flag & SSYS) || p->p_as == &kas)
3526 pcp->prc_flags |= PRC_SYS;
3527 if (p->p_stat == SZOMB)
3528 pcp->prc_flags |= PRC_DESTROY;
3529 pcp->prc_proc = p;
3530 pcp->prc_datamodel = p->p_model;
3531 pcp->prc_pid = p->p_pid;
3532 pcp->prc_slot = p->p_slot;
3534 pnp->pr_pcommon = pcp;
3535 pnp->pr_parent = dp;
3536 VN_HOLD(dp);
3538 * Link in the old, invalid directory vnode so we
3539 * can later determine the last close of the file.
3541 pnp->pr_next = p->p_trace;
3542 p->p_trace = dp = PTOV(pnp);
3545 * Kludge for old /proc: initialize the PR_PIDFILE as well.
3547 vp = pnp->pr_pidfile;
3548 pnp = VTOP(vp);
3549 pnp->pr_ino = ptoi(pcp->prc_pid);
3550 pnp->pr_common = pcp;
3551 pnp->pr_pcommon = pcp;
3552 pnp->pr_parent = dp;
3553 pnp->pr_next = p->p_plist;
3554 p->p_plist = vp;
3556 mutex_exit(&p->p_lock);
3557 return (dp);
3560 static vnode_t *
3561 pr_lookup_piddir(vnode_t *dp, char *comp)
3563 prnode_t *dpnp = VTOP(dp);
3564 vnode_t *vp;
3565 prnode_t *pnp;
3566 proc_t *p;
3567 user_t *up;
3568 prdirent_t *dirp;
3569 int i;
3570 enum prnodetype type;
3572 ASSERT(dpnp->pr_type == PR_PIDDIR);
3574 for (i = 0; i < NPIDDIRFILES; i++) {
3575 /* Skip "." and ".." */
3576 dirp = &piddir[i+2];
3577 if (strcmp(comp, dirp->d_name) == 0)
3578 break;
3581 if (i >= NPIDDIRFILES)
3582 return (NULL);
3584 type = (int)dirp->d_ino;
3585 pnp = prgetnode(dp, type);
3587 p = pr_p_lock(dpnp);
3588 mutex_exit(&pr_pidlock);
3589 if (p == NULL) {
3590 prfreenode(pnp);
3591 return (NULL);
3593 if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
3594 switch (type) {
3595 case PR_PSINFO:
3596 case PR_USAGE:
3597 break;
3598 default:
3599 prunlock(dpnp);
3600 prfreenode(pnp);
3601 return (NULL);
3605 switch (type) {
3606 case PR_CURDIR:
3607 case PR_ROOTDIR:
3608 up = PTOU(p);
3609 vp = (type == PR_CURDIR)? up->u_cdir :
3610 (up->u_rdir? up->u_rdir : rootdir);
3612 if (vp == NULL) { /* can't happen? */
3613 prunlock(dpnp);
3614 prfreenode(pnp);
3615 return (NULL);
3618 * Fill in the prnode so future references will
3619 * be able to find the underlying object's vnode.
3621 VN_HOLD(vp);
3622 pnp->pr_realvp = vp;
3623 break;
3624 default:
3625 break;
3628 mutex_enter(&dpnp->pr_mutex);
3630 if ((vp = dpnp->pr_files[i]) != NULL &&
3631 !(VTOP(vp)->pr_flags & PR_INVAL)) {
3632 VN_HOLD(vp);
3633 mutex_exit(&dpnp->pr_mutex);
3634 prunlock(dpnp);
3635 prfreenode(pnp);
3636 return (vp);
3640 * prgetnode() initialized most of the prnode.
3641 * Finish the job.
3643 pnp->pr_common = dpnp->pr_common;
3644 pnp->pr_pcommon = dpnp->pr_pcommon;
3645 pnp->pr_parent = dp;
3646 VN_HOLD(dp);
3647 pnp->pr_index = i;
3649 dpnp->pr_files[i] = vp = PTOV(pnp);
3652 * Link new vnode into list of all /proc vnodes for the process.
3654 if (vp->v_type == VPROC) {
3655 pnp->pr_next = p->p_plist;
3656 p->p_plist = vp;
3658 mutex_exit(&dpnp->pr_mutex);
3659 prunlock(dpnp);
3660 return (vp);
3663 static vnode_t *
3664 pr_lookup_objectdir(vnode_t *dp, char *comp)
3666 prnode_t *dpnp = VTOP(dp);
3667 prnode_t *pnp;
3668 proc_t *p;
3669 struct seg *seg;
3670 struct as *as;
3671 vnode_t *vp;
3672 vattr_t vattr;
3674 ASSERT(dpnp->pr_type == PR_OBJECTDIR);
3676 pnp = prgetnode(dp, PR_OBJECT);
3678 if (prlock(dpnp, ZNO) != 0) {
3679 prfreenode(pnp);
3680 return (NULL);
3682 p = dpnp->pr_common->prc_proc;
3683 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3684 prunlock(dpnp);
3685 prfreenode(pnp);
3686 return (NULL);
3690 * We drop p_lock before grabbing the address space lock
3691 * in order to avoid a deadlock with the clock thread.
3692 * The process will not disappear and its address space
3693 * will not change because it is marked P_PR_LOCK.
3695 mutex_exit(&p->p_lock);
3696 AS_LOCK_ENTER(as, RW_READER);
3697 if ((seg = AS_SEGFIRST(as)) == NULL) {
3698 vp = NULL;
3699 goto out;
3701 if (strcmp(comp, "a.out") == 0) {
3702 vp = p->p_exec;
3703 goto out;
3705 do {
3707 * Manufacture a filename for the "object" directory.
3709 vattr.va_mask = AT_FSID|AT_NODEID;
3710 if (seg->s_ops == &segvn_ops &&
3711 SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
3712 vp != NULL && vp->v_type == VREG &&
3713 VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
3714 char name[64];
3716 if (vp == p->p_exec) /* "a.out" */
3717 continue;
3718 pr_object_name(name, vp, &vattr);
3719 if (strcmp(name, comp) == 0)
3720 goto out;
3722 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3724 vp = NULL;
3725 out:
3726 if (vp != NULL) {
3727 VN_HOLD(vp);
3729 AS_LOCK_EXIT(as);
3730 mutex_enter(&p->p_lock);
3731 prunlock(dpnp);
3733 if (vp == NULL)
3734 prfreenode(pnp);
3735 else {
3737 * Fill in the prnode so future references will
3738 * be able to find the underlying object's vnode.
3739 * Don't link this prnode into the list of all
3740 * prnodes for the process; this is a one-use node.
3741 * Its use is entirely to catch and fail opens for writing.
3743 pnp->pr_realvp = vp;
3744 vp = PTOV(pnp);
3747 return (vp);
3751 * Find or construct an lwp vnode for the given lwpid.
3753 static vnode_t *
3754 pr_lookup_lwpdir(vnode_t *dp, char *comp)
3756 id_t tid; /* same type as t->t_tid */
3757 int want_agent;
3758 prnode_t *dpnp = VTOP(dp);
3759 prnode_t *pnp;
3760 prcommon_t *pcp;
3761 vnode_t *vp;
3762 proc_t *p;
3763 kthread_t *t;
3764 lwpdir_t *ldp;
3765 lwpent_t *lep;
3766 int tslot;
3767 int c;
3769 ASSERT(dpnp->pr_type == PR_LWPDIR);
3771 tid = 0;
3772 if (strcmp(comp, "agent") == 0)
3773 want_agent = 1;
3774 else {
3775 want_agent = 0;
3776 while ((c = *comp++) != '\0') {
3777 id_t otid;
3779 if (c < '0' || c > '9')
3780 return (NULL);
3781 otid = tid;
3782 tid = 10*tid + c - '0';
3783 if (tid/10 != otid) /* integer overflow */
3784 return (NULL);
3788 pnp = prgetnode(dp, PR_LWPIDDIR);
3790 p = pr_p_lock(dpnp);
3791 mutex_exit(&pr_pidlock);
3792 if (p == NULL) {
3793 prfreenode(pnp);
3794 return (NULL);
3797 if (want_agent) {
3798 if ((t = p->p_agenttp) == NULL)
3799 lep = NULL;
3800 else {
3801 tid = t->t_tid;
3802 tslot = t->t_dslot;
3803 lep = p->p_lwpdir[tslot].ld_entry;
3805 } else {
3806 if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
3807 lep = NULL;
3808 else {
3809 tslot = (int)(ldp - p->p_lwpdir);
3810 lep = ldp->ld_entry;
3814 if (lep == NULL) {
3815 prunlock(dpnp);
3816 prfreenode(pnp);
3817 return (NULL);
3821 * If an lwp vnode already exists and it is not invalid
3822 * and it was created by the current process and it belongs
3823 * to the same /proc mount point as our parent vnode, then
3824 * just use it and discard the newly-allocated prnode.
3826 for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3827 if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
3828 VTOP(vp)->pr_owner == curproc &&
3829 vp->v_vfsp == dp->v_vfsp) {
3830 VN_HOLD(vp);
3831 prunlock(dpnp);
3832 prfreenode(pnp);
3833 return (vp);
3836 pnp->pr_owner = curproc;
3839 * prgetnode() initialized most of the prnode.
3840 * Finish the job.
3842 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
3843 if ((vp = lep->le_trace) != NULL) {
3844 /* discard the new prcommon and use the existing prcommon */
3845 prfreecommon(pcp);
3846 pcp = VTOP(vp)->pr_common;
3847 mutex_enter(&pcp->prc_mutex);
3848 ASSERT(pcp->prc_refcnt > 0);
3849 pcp->prc_refcnt++;
3850 mutex_exit(&pcp->prc_mutex);
3851 pnp->pr_common = pcp;
3852 } else {
3853 /* initialize the new prcommon struct */
3854 pcp->prc_flags |= PRC_LWP;
3855 if ((p->p_flag & SSYS) || p->p_as == &kas)
3856 pcp->prc_flags |= PRC_SYS;
3857 if ((t = lep->le_thread) == NULL)
3858 pcp->prc_flags |= PRC_DESTROY;
3859 pcp->prc_proc = p;
3860 pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
3861 pcp->prc_pid = p->p_pid;
3862 pcp->prc_slot = p->p_slot;
3863 pcp->prc_thread = t;
3864 pcp->prc_tid = tid;
3865 pcp->prc_tslot = tslot;
3867 pnp->pr_pcommon = dpnp->pr_pcommon;
3868 pnp->pr_parent = dp;
3869 VN_HOLD(dp);
3871 * Link in the old, invalid directory vnode so we
3872 * can later determine the last close of the file.
3874 pnp->pr_next = lep->le_trace;
3875 lep->le_trace = vp = PTOV(pnp);
3876 prunlock(dpnp);
3877 return (vp);
3880 static vnode_t *
3881 pr_lookup_lwpiddir(vnode_t *dp, char *comp)
3883 prnode_t *dpnp = VTOP(dp);
3884 vnode_t *vp;
3885 prnode_t *pnp;
3886 proc_t *p;
3887 prdirent_t *dirp;
3888 int i;
3889 enum prnodetype type;
3891 ASSERT(dpnp->pr_type == PR_LWPIDDIR);
3893 for (i = 0; i < NLWPIDDIRFILES; i++) {
3894 /* Skip "." and ".." */
3895 dirp = &lwpiddir[i+2];
3896 if (strcmp(comp, dirp->d_name) == 0)
3897 break;
3900 if (i >= NLWPIDDIRFILES)
3901 return (NULL);
3903 type = (int)dirp->d_ino;
3904 pnp = prgetnode(dp, type);
3906 p = pr_p_lock(dpnp);
3907 mutex_exit(&pr_pidlock);
3908 if (p == NULL) {
3909 prfreenode(pnp);
3910 return (NULL);
3912 if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
3914 * Only the lwpsinfo file is present for zombie lwps.
3915 * Nothing is present if the lwp has been reaped.
3917 if (dpnp->pr_common->prc_tslot == -1 ||
3918 type != PR_LWPSINFO) {
3919 prunlock(dpnp);
3920 prfreenode(pnp);
3921 return (NULL);
3925 #if defined(__sparc)
3926 /* the asrs file exists only for sparc v9 _LP64 processes */
3927 if (type == PR_ASRS && p->p_model != DATAMODEL_LP64) {
3928 prunlock(dpnp);
3929 prfreenode(pnp);
3930 return (NULL);
3932 #endif
3934 mutex_enter(&dpnp->pr_mutex);
3936 if ((vp = dpnp->pr_files[i]) != NULL &&
3937 !(VTOP(vp)->pr_flags & PR_INVAL)) {
3938 VN_HOLD(vp);
3939 mutex_exit(&dpnp->pr_mutex);
3940 prunlock(dpnp);
3941 prfreenode(pnp);
3942 return (vp);
3946 * prgetnode() initialized most of the prnode.
3947 * Finish the job.
3949 pnp->pr_common = dpnp->pr_common;
3950 pnp->pr_pcommon = dpnp->pr_pcommon;
3951 pnp->pr_parent = dp;
3952 VN_HOLD(dp);
3953 pnp->pr_index = i;
3955 dpnp->pr_files[i] = vp = PTOV(pnp);
3958 * Link new vnode into list of all /proc vnodes for the process.
3960 if (vp->v_type == VPROC) {
3961 pnp->pr_next = p->p_plist;
3962 p->p_plist = vp;
3964 mutex_exit(&dpnp->pr_mutex);
3965 prunlock(dpnp);
3966 return (vp);
3970 * Lookup one of the process's open files.
3972 static vnode_t *
3973 pr_lookup_fddir(vnode_t *dp, char *comp)
3975 prnode_t *dpnp = VTOP(dp);
3976 prnode_t *pnp;
3977 vnode_t *vp = NULL;
3978 proc_t *p;
3979 file_t *fp;
3980 uint_t fd;
3981 int c;
3982 uf_entry_t *ufp;
3983 uf_info_t *fip;
3985 ASSERT(dpnp->pr_type == PR_FDDIR);
3987 fd = 0;
3988 while ((c = *comp++) != '\0') {
3989 int ofd;
3990 if (c < '0' || c > '9')
3991 return (NULL);
3992 ofd = fd;
3993 fd = 10*fd + c - '0';
3994 if (fd/10 != ofd) /* integer overflow */
3995 return (NULL);
3998 pnp = prgetnode(dp, PR_FD);
4000 if (prlock(dpnp, ZNO) != 0) {
4001 prfreenode(pnp);
4002 return (NULL);
4004 p = dpnp->pr_common->prc_proc;
4005 if ((p->p_flag & SSYS) || p->p_as == &kas) {
4006 prunlock(dpnp);
4007 prfreenode(pnp);
4008 return (NULL);
4011 fip = P_FINFO(p);
4012 mutex_exit(&p->p_lock);
4013 mutex_enter(&fip->fi_lock);
4014 if (fd < fip->fi_nfiles) {
4015 UF_ENTER(ufp, fip, fd);
4016 if ((fp = ufp->uf_file) != NULL) {
4017 pnp->pr_mode = 07111;
4018 if (fp->f_flag & FREAD)
4019 pnp->pr_mode |= 0444;
4020 if (fp->f_flag & FWRITE)
4021 pnp->pr_mode |= 0222;
4022 vp = fp->f_vnode;
4023 VN_HOLD(vp);
4025 UF_EXIT(ufp);
4027 mutex_exit(&fip->fi_lock);
4028 mutex_enter(&p->p_lock);
4029 prunlock(dpnp);
4031 if (vp == NULL)
4032 prfreenode(pnp);
4033 else {
4035 * Fill in the prnode so future references will
4036 * be able to find the underlying object's vnode.
4037 * Don't link this prnode into the list of all
4038 * prnodes for the process; this is a one-use node.
4040 pnp->pr_realvp = vp;
4041 pnp->pr_parent = dp; /* needed for prlookup */
4042 VN_HOLD(dp);
4043 vp = PTOV(pnp);
4044 if (pnp->pr_realvp->v_type == VDIR)
4045 vp->v_type = VDIR;
4048 return (vp);
4051 static vnode_t *
4052 pr_lookup_pathdir(vnode_t *dp, char *comp)
4054 prnode_t *dpnp = VTOP(dp);
4055 prnode_t *pnp;
4056 vnode_t *vp = NULL;
4057 proc_t *p;
4058 uint_t fd, flags = 0;
4059 int c;
4060 uf_entry_t *ufp;
4061 uf_info_t *fip;
4062 enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
4063 char *tmp;
4064 int idx;
4065 struct seg *seg;
4066 struct as *as = NULL;
4067 vattr_t vattr;
4069 ASSERT(dpnp->pr_type == PR_PATHDIR);
4072 * First, check if this is a numeric entry, in which case we have a
4073 * file descriptor.
4075 fd = 0;
4076 type = NAME_FD;
4077 tmp = comp;
4078 while ((c = *tmp++) != '\0') {
4079 int ofd;
4080 if (c < '0' || c > '9') {
4081 type = NAME_UNKNOWN;
4082 break;
4084 ofd = fd;
4085 fd = 10*fd + c - '0';
4086 if (fd/10 != ofd) { /* integer overflow */
4087 type = NAME_UNKNOWN;
4088 break;
4093 * Next, see if it is one of the special values {root, cwd}.
4095 if (type == NAME_UNKNOWN) {
4096 if (strcmp(comp, "root") == 0)
4097 type = NAME_ROOT;
4098 else if (strcmp(comp, "cwd") == 0)
4099 type = NAME_CWD;
4103 * Grab the necessary data from the process
4105 if (prlock(dpnp, ZNO) != 0)
4106 return (NULL);
4107 p = dpnp->pr_common->prc_proc;
4109 fip = P_FINFO(p);
4111 switch (type) {
4112 case NAME_ROOT:
4113 if ((vp = PTOU(p)->u_rdir) == NULL)
4114 vp = p->p_zone->zone_rootvp;
4115 VN_HOLD(vp);
4116 break;
4117 case NAME_CWD:
4118 vp = PTOU(p)->u_cdir;
4119 VN_HOLD(vp);
4120 break;
4121 default:
4122 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4123 prunlock(dpnp);
4124 return (NULL);
4127 mutex_exit(&p->p_lock);
4130 * Determine if this is an object entry
4132 if (type == NAME_UNKNOWN) {
4134 * Start with the inode index immediately after the number of
4135 * files.
4137 mutex_enter(&fip->fi_lock);
4138 idx = fip->fi_nfiles + 4;
4139 mutex_exit(&fip->fi_lock);
4141 if (strcmp(comp, "a.out") == 0) {
4142 if (p->p_execdir != NULL) {
4143 vp = p->p_execdir;
4144 VN_HOLD(vp);
4145 type = NAME_OBJECT;
4146 flags |= PR_AOUT;
4147 } else {
4148 vp = p->p_exec;
4149 VN_HOLD(vp);
4150 type = NAME_OBJECT;
4152 } else {
4153 AS_LOCK_ENTER(as, RW_READER);
4154 if ((seg = AS_SEGFIRST(as)) != NULL) {
4155 do {
4157 * Manufacture a filename for the
4158 * "object" directory.
4160 vattr.va_mask = AT_FSID|AT_NODEID;
4161 if (seg->s_ops == &segvn_ops &&
4162 SEGOP_GETVP(seg, seg->s_base, &vp)
4163 == 0 &&
4164 vp != NULL && vp->v_type == VREG &&
4165 VOP_GETATTR(vp, &vattr, 0, CRED(),
4166 NULL) == 0) {
4167 char name[64];
4169 if (vp == p->p_exec)
4170 continue;
4171 idx++;
4172 pr_object_name(name, vp,
4173 &vattr);
4174 if (strcmp(name, comp) == 0)
4175 break;
4177 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4180 if (seg == NULL) {
4181 vp = NULL;
4182 } else {
4183 VN_HOLD(vp);
4184 type = NAME_OBJECT;
4187 AS_LOCK_EXIT(as);
4192 switch (type) {
4193 case NAME_FD:
4194 mutex_enter(&fip->fi_lock);
4195 if (fd < fip->fi_nfiles) {
4196 UF_ENTER(ufp, fip, fd);
4197 if (ufp->uf_file != NULL) {
4198 vp = ufp->uf_file->f_vnode;
4199 VN_HOLD(vp);
4201 UF_EXIT(ufp);
4203 mutex_exit(&fip->fi_lock);
4204 idx = fd + 4;
4205 break;
4206 case NAME_ROOT:
4207 idx = 2;
4208 break;
4209 case NAME_CWD:
4210 idx = 3;
4211 break;
4212 case NAME_OBJECT:
4213 case NAME_UNKNOWN:
4214 /* Nothing to do */
4215 break;
4218 mutex_enter(&p->p_lock);
4219 prunlock(dpnp);
4221 if (vp != NULL) {
4222 pnp = prgetnode(dp, PR_PATH);
4224 pnp->pr_flags |= flags;
4225 pnp->pr_common = dpnp->pr_common;
4226 pnp->pr_pcommon = dpnp->pr_pcommon;
4227 pnp->pr_realvp = vp;
4228 pnp->pr_parent = dp; /* needed for prlookup */
4229 pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
4230 VN_HOLD(dp);
4231 vp = PTOV(pnp);
4232 vp->v_type = VLNK;
4235 return (vp);
4239 * Look up one of the process's active templates.
4241 static vnode_t *
4242 pr_lookup_tmpldir(vnode_t *dp, char *comp)
4244 prnode_t *dpnp = VTOP(dp);
4245 prnode_t *pnp;
4246 vnode_t *vp = NULL;
4247 proc_t *p;
4248 int i;
4250 ASSERT(dpnp->pr_type == PR_TMPLDIR);
4252 for (i = 0; i < ct_ntypes; i++)
4253 if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
4254 break;
4255 if (i == ct_ntypes)
4256 return (NULL);
4258 pnp = prgetnode(dp, PR_TMPL);
4260 if (prlock(dpnp, ZNO) != 0) {
4261 prfreenode(pnp);
4262 return (NULL);
4264 p = dpnp->pr_common->prc_proc;
4265 if ((p->p_flag & SSYS) || p->p_as == &kas ||
4266 (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
4267 prunlock(dpnp);
4268 prfreenode(pnp);
4269 return (NULL);
4271 if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
4272 pnp->pr_common = dpnp->pr_common;
4273 pnp->pr_pcommon = dpnp->pr_pcommon;
4274 pnp->pr_parent = dp;
4275 pnp->pr_cttype = i;
4276 VN_HOLD(dp);
4277 vp = PTOV(pnp);
4278 } else {
4279 prfreenode(pnp);
4281 prunlock(dpnp);
4283 return (vp);
4287 * Look up one of the contracts owned by the process.
4289 static vnode_t *
4290 pr_lookup_ctdir(vnode_t *dp, char *comp)
4292 prnode_t *dpnp = VTOP(dp);
4293 prnode_t *pnp;
4294 vnode_t *vp = NULL;
4295 proc_t *p;
4296 id_t id = 0;
4297 contract_t *ct;
4298 int c;
4300 ASSERT(dpnp->pr_type == PR_CTDIR);
4302 while ((c = *comp++) != '\0') {
4303 id_t oid;
4304 if (c < '0' || c > '9')
4305 return (NULL);
4306 oid = id;
4307 id = 10 * id + c - '0';
4308 if (id / 10 != oid) /* integer overflow */
4309 return (NULL);
4313 * Search all contracts; we'll filter below.
4315 ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
4316 if (ct == NULL)
4317 return (NULL);
4319 pnp = prgetnode(dp, PR_CT);
4321 if (prlock(dpnp, ZNO) != 0) {
4322 prfreenode(pnp);
4323 contract_rele(ct);
4324 return (NULL);
4326 p = dpnp->pr_common->prc_proc;
4328 * We only allow lookups of contracts owned by this process, or,
4329 * if we are zsched and this is a zone's procfs, contracts on
4330 * stuff in the zone which are held by processes or contracts
4331 * outside the zone. (see logic in contract_status_common)
4333 if ((ct->ct_owner != p) &&
4334 !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4335 VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4336 VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
4337 ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
4338 prunlock(dpnp);
4339 prfreenode(pnp);
4340 contract_rele(ct);
4341 return (NULL);
4343 pnp->pr_common = dpnp->pr_common;
4344 pnp->pr_pcommon = dpnp->pr_pcommon;
4345 pnp->pr_contract = ct;
4346 pnp->pr_parent = dp;
4347 pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
4348 VN_HOLD(dp);
4349 prunlock(dpnp);
4350 vp = PTOV(pnp);
4352 return (vp);
4356 * Construct an lwp vnode for the old /proc interface.
4357 * We stand on our head to make the /proc plumbing correct.
4359 vnode_t *
4360 prlwpnode(prnode_t *pnp, uint_t tid)
4362 char comp[12];
4363 vnode_t *dp;
4364 vnode_t *vp;
4365 prcommon_t *pcp;
4366 proc_t *p;
4369 * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
4371 if (pnp->pr_type == PR_PIDFILE) {
4372 dp = pnp->pr_parent; /* /proc/<pid> */
4373 VN_HOLD(dp);
4374 vp = pr_lookup_piddir(dp, "lwp");
4375 VN_RELE(dp);
4376 if ((dp = vp) == NULL) /* /proc/<pid>/lwp */
4377 return (NULL);
4378 } else if (pnp->pr_type == PR_LWPIDFILE) {
4379 dp = pnp->pr_parent; /* /proc/<pid>/lwp/<lwpid> */
4380 dp = VTOP(dp)->pr_parent; /* /proc/<pid>/lwp */
4381 VN_HOLD(dp);
4382 } else {
4383 return (NULL);
4386 (void) pr_u32tos(tid, comp, sizeof (comp));
4387 vp = pr_lookup_lwpdir(dp, comp);
4388 VN_RELE(dp);
4389 if ((dp = vp) == NULL)
4390 return (NULL);
4392 pnp = prgetnode(dp, PR_LWPIDFILE);
4393 vp = PTOV(pnp);
4396 * prgetnode() initialized most of the prnode.
4397 * Finish the job.
4399 pcp = VTOP(dp)->pr_common;
4400 pnp->pr_ino = ptoi(pcp->prc_pid);
4401 pnp->pr_common = pcp;
4402 pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
4403 pnp->pr_parent = dp;
4405 * Link new vnode into list of all /proc vnodes for the process.
4407 p = pr_p_lock(pnp);
4408 mutex_exit(&pr_pidlock);
4409 if (p == NULL) {
4410 VN_RELE(dp);
4411 prfreenode(pnp);
4412 vp = NULL;
4413 } else if (pcp->prc_thread == NULL) {
4414 prunlock(pnp);
4415 VN_RELE(dp);
4416 prfreenode(pnp);
4417 vp = NULL;
4418 } else {
4419 pnp->pr_next = p->p_plist;
4420 p->p_plist = vp;
4421 prunlock(pnp);
4424 return (vp);
4427 #if defined(DEBUG)
4429 static uint32_t nprnode;
4430 static uint32_t nprcommon;
4432 #define INCREMENT(x) atomic_inc_32(&x);
4433 #define DECREMENT(x) atomic_dec_32(&x);
4435 #else
4437 #define INCREMENT(x)
4438 #define DECREMENT(x)
4440 #endif /* DEBUG */
4443 * New /proc vnode required; allocate it and fill in most of the fields.
4445 prnode_t *
4446 prgetnode(vnode_t *dp, prnodetype_t type)
4448 prnode_t *pnp;
4449 prcommon_t *pcp;
4450 vnode_t *vp;
4451 ulong_t nfiles;
4453 INCREMENT(nprnode);
4454 pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
4456 mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
4457 pnp->pr_type = type;
4459 pnp->pr_vnode = vn_alloc(KM_SLEEP);
4461 vp = PTOV(pnp);
4462 vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
4463 vn_setops(vp, prvnodeops);
4464 vp->v_vfsp = dp->v_vfsp;
4465 vp->v_type = VPROC;
4466 vp->v_data = (caddr_t)pnp;
4468 switch (type) {
4469 case PR_PIDDIR:
4470 case PR_LWPIDDIR:
4472 * We need a prcommon and a files array for each of these.
4474 INCREMENT(nprcommon);
4476 pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
4477 pcp->prc_refcnt = 1;
4478 pnp->pr_common = pcp;
4479 mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
4480 cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
4482 nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
4483 pnp->pr_files =
4484 kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
4486 vp->v_type = VDIR;
4488 * Mode should be read-search by all, but we cannot so long
4489 * as we must support compatibility mode with old /proc.
4490 * Make /proc/<pid> be read by owner only, search by all.
4491 * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
4492 * set VDIROPEN on /proc/<pid> so it can be opened for writing.
4494 if (type == PR_PIDDIR) {
4495 /* kludge for old /proc interface */
4496 prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
4497 pnp->pr_pidfile = PTOV(xpnp);
4498 pnp->pr_mode = 0511;
4499 vp->v_flag |= VDIROPEN;
4500 } else {
4501 pnp->pr_mode = 0555;
4504 break;
4506 case PR_CURDIR:
4507 case PR_ROOTDIR:
4508 case PR_FDDIR:
4509 case PR_OBJECTDIR:
4510 case PR_PATHDIR:
4511 case PR_CTDIR:
4512 case PR_TMPLDIR:
4513 vp->v_type = VDIR;
4514 pnp->pr_mode = 0500; /* read-search by owner only */
4515 break;
4517 case PR_CT:
4518 vp->v_type = VLNK;
4519 pnp->pr_mode = 0500; /* read-search by owner only */
4520 break;
4522 case PR_PATH:
4523 case PR_SELF:
4524 vp->v_type = VLNK;
4525 pnp->pr_mode = 0777;
4526 break;
4528 case PR_LWPDIR:
4529 vp->v_type = VDIR;
4530 pnp->pr_mode = 0555; /* read-search by all */
4531 break;
4533 case PR_AS:
4534 case PR_TMPL:
4535 pnp->pr_mode = 0600; /* read-write by owner only */
4536 break;
4538 case PR_CTL:
4539 case PR_LWPCTL:
4540 pnp->pr_mode = 0200; /* write-only by owner only */
4541 break;
4543 case PR_PIDFILE:
4544 case PR_LWPIDFILE:
4545 pnp->pr_mode = 0600; /* read-write by owner only */
4546 break;
4548 case PR_PSINFO:
4549 case PR_LPSINFO:
4550 case PR_LWPSINFO:
4551 case PR_USAGE:
4552 case PR_LUSAGE:
4553 case PR_LWPUSAGE:
4554 pnp->pr_mode = 0444; /* read-only by all */
4555 break;
4557 default:
4558 pnp->pr_mode = 0400; /* read-only by owner only */
4559 break;
4561 vn_exists(vp);
4562 return (pnp);
4566 * Free the storage obtained from prgetnode().
4568 void
4569 prfreenode(prnode_t *pnp)
4571 vnode_t *vp;
4572 ulong_t nfiles;
4574 vn_invalid(PTOV(pnp));
4575 vn_free(PTOV(pnp));
4576 mutex_destroy(&pnp->pr_mutex);
4578 switch (pnp->pr_type) {
4579 case PR_PIDDIR:
4580 /* kludge for old /proc interface */
4581 if (pnp->pr_pidfile != NULL) {
4582 prfreenode(VTOP(pnp->pr_pidfile));
4583 pnp->pr_pidfile = NULL;
4585 /* FALLTHROUGH */
4586 case PR_LWPIDDIR:
4588 * We allocated a prcommon and a files array for each of these.
4590 prfreecommon(pnp->pr_common);
4591 nfiles = (pnp->pr_type == PR_PIDDIR)?
4592 NPIDDIRFILES : NLWPIDDIRFILES;
4593 kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
4594 break;
4595 default:
4596 break;
4599 * If there is an underlying vnode, be sure
4600 * to release it after freeing the prnode.
4602 vp = pnp->pr_realvp;
4603 kmem_free(pnp, sizeof (*pnp));
4604 DECREMENT(nprnode);
4605 if (vp != NULL) {
4606 VN_RELE(vp);
4611 * Free a prcommon structure, if the reference count reaches zero.
4613 static void
4614 prfreecommon(prcommon_t *pcp)
4616 mutex_enter(&pcp->prc_mutex);
4617 ASSERT(pcp->prc_refcnt > 0);
4618 if (--pcp->prc_refcnt != 0)
4619 mutex_exit(&pcp->prc_mutex);
4620 else {
4621 mutex_exit(&pcp->prc_mutex);
4622 ASSERT(pcp->prc_pollhead.ph_list == NULL);
4623 ASSERT(pcp->prc_refcnt == 0);
4624 ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
4625 mutex_destroy(&pcp->prc_mutex);
4626 cv_destroy(&pcp->prc_wait);
4627 kmem_free(pcp, sizeof (prcommon_t));
4628 DECREMENT(nprcommon);
4633 * Array of readdir functions, indexed by /proc file type.
4635 static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4636 pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4637 pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
4638 pr_readdir_ctdir();
4640 static int (*pr_readdir_function[PR_NFILES])() = {
4641 pr_readdir_procdir, /* /proc */
4642 pr_readdir_notdir, /* /proc/self */
4643 pr_readdir_piddir, /* /proc/<pid> */
4644 pr_readdir_notdir, /* /proc/<pid>/as */
4645 pr_readdir_notdir, /* /proc/<pid>/ctl */
4646 pr_readdir_notdir, /* /proc/<pid>/status */
4647 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4648 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4649 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4650 pr_readdir_notdir, /* /proc/<pid>/map */
4651 pr_readdir_notdir, /* /proc/<pid>/rmap */
4652 pr_readdir_notdir, /* /proc/<pid>/xmap */
4653 pr_readdir_notdir, /* /proc/<pid>/cred */
4654 pr_readdir_notdir, /* /proc/<pid>/sigact */
4655 pr_readdir_notdir, /* /proc/<pid>/auxv */
4656 #if defined(__x86)
4657 pr_readdir_notdir, /* /proc/<pid>/ldt */
4658 #endif
4659 pr_readdir_notdir, /* /proc/<pid>/usage */
4660 pr_readdir_notdir, /* /proc/<pid>/lusage */
4661 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4662 pr_readdir_notdir, /* /proc/<pid>/watch */
4663 pr_readdir_notdir, /* /proc/<pid>/cwd */
4664 pr_readdir_notdir, /* /proc/<pid>/root */
4665 pr_readdir_fddir, /* /proc/<pid>/fd */
4666 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4667 pr_readdir_objectdir, /* /proc/<pid>/object */
4668 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4669 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4670 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4671 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4672 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4673 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4674 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4675 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4676 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4677 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4678 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4679 #if defined(__sparc)
4680 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
4681 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
4682 #endif
4683 pr_readdir_notdir, /* /proc/<pid>/priv */
4684 pr_readdir_pathdir, /* /proc/<pid>/path */
4685 pr_readdir_notdir, /* /proc/<pid>/path/xxx */
4686 pr_readdir_ctdir, /* /proc/<pid>/contracts */
4687 pr_readdir_notdir, /* /proc/<pid>/contracts/<ctid> */
4688 pr_readdir_notdir, /* old process file */
4689 pr_readdir_notdir, /* old lwp file */
4690 pr_readdir_notdir, /* old pagedata file */
4693 /* ARGSUSED */
4694 static int
4695 prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
4696 caller_context_t *ct, int flags)
4698 prnode_t *pnp = VTOP(vp);
4700 ASSERT(pnp->pr_type < PR_NFILES);
4702 /* XXX - Do we need to pass ct and flags? */
4703 return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
4706 /* ARGSUSED */
4707 static int
4708 pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4710 return (ENOTDIR);
4713 /* ARGSUSED */
4714 static int
4715 pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4717 zoneid_t zoneid;
4718 gfs_readdir_state_t gstate;
4719 int error, eof = 0;
4720 offset_t n;
4722 ASSERT(pnp->pr_type == PR_PROCDIR);
4724 zoneid = VTOZONE(PTOV(pnp))->zone_id;
4726 if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
4727 PRROOTINO, PRROOTINO, 0)) != 0)
4728 return (error);
4731 * Loop until user's request is satisfied or until all processes
4732 * have been examined.
4734 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
4735 uint_t pid;
4736 int pslot;
4737 proc_t *p;
4740 * Find next entry. Skip processes not visible where
4741 * this /proc was mounted.
4743 mutex_enter(&pidlock);
4744 while (n < v.v_proc &&
4745 ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
4746 (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
4747 secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
4748 n++;
4751 * Stop when entire proc table has been examined.
4753 if (n >= v.v_proc) {
4754 mutex_exit(&pidlock);
4755 eof = 1;
4756 break;
4759 ASSERT(p->p_stat != 0);
4760 pid = p->p_pid;
4761 pslot = p->p_slot;
4762 mutex_exit(&pidlock);
4763 error = gfs_readdir_emitn(&gstate, uiop, n,
4764 pmkino(0, pslot, PR_PIDDIR), pid);
4765 if (error)
4766 break;
4769 return (gfs_readdir_fini(&gstate, error, eofp, eof));
4772 /* ARGSUSED */
4773 static int
4774 pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
4776 int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
4777 prdirent_t dirent;
4778 prdirent_t *dirp;
4779 offset_t off;
4780 int error;
4782 ASSERT(pnp->pr_type == PR_PIDDIR);
4784 if (uiop->uio_offset < 0 ||
4785 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
4786 uiop->uio_resid < sizeof (prdirent_t))
4787 return (EINVAL);
4788 if (pnp->pr_pcommon->prc_proc == NULL)
4789 return (ENOENT);
4790 if (uiop->uio_offset >= sizeof (piddir))
4791 goto out;
4794 * Loop until user's request is satisfied, omitting some
4795 * files along the way if the process is a zombie.
4797 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
4798 uiop->uio_resid >= sizeof (prdirent_t) &&
4799 dirp < &piddir[NPIDDIRFILES+2];
4800 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
4801 off = uiop->uio_offset;
4802 if (zombie) {
4803 switch (dirp->d_ino) {
4804 case PR_PIDDIR:
4805 case PR_PROCDIR:
4806 case PR_PSINFO:
4807 case PR_USAGE:
4808 break;
4809 default:
4810 continue;
4813 bcopy(dirp, &dirent, sizeof (prdirent_t));
4814 if (dirent.d_ino == PR_PROCDIR)
4815 dirent.d_ino = PRROOTINO;
4816 else
4817 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
4818 dirent.d_ino);
4819 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
4820 UIO_READ, uiop)) != 0)
4821 return (error);
4823 out:
4824 if (eofp)
4825 *eofp = (uiop->uio_offset >= sizeof (piddir));
4826 return (0);
4829 static void
4830 rebuild_objdir(struct as *as)
4832 struct seg *seg;
4833 vnode_t *vp;
4834 vattr_t vattr;
4835 vnode_t **dir;
4836 ulong_t nalloc;
4837 ulong_t nentries;
4838 int i, j;
4839 ulong_t nold, nnew;
4841 ASSERT(AS_WRITE_HELD(as));
4843 if (as->a_updatedir == 0 && as->a_objectdir != NULL)
4844 return;
4845 as->a_updatedir = 0;
4847 if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
4848 (seg = AS_SEGFIRST(as)) == NULL) /* can't happen? */
4849 return;
4852 * Allocate space for the new object directory.
4853 * (This is usually about two times too many entries.)
4855 nalloc = (nalloc + 0xf) & ~0xf; /* multiple of 16 */
4856 dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
4858 /* fill in the new directory with desired entries */
4859 nentries = 0;
4860 do {
4861 vattr.va_mask = AT_FSID|AT_NODEID;
4862 if (seg->s_ops == &segvn_ops &&
4863 SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
4864 vp != NULL && vp->v_type == VREG &&
4865 VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
4866 for (i = 0; i < nentries; i++)
4867 if (vp == dir[i])
4868 break;
4869 if (i == nentries) {
4870 ASSERT(nentries < nalloc);
4871 dir[nentries++] = vp;
4874 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4876 if (as->a_objectdir == NULL) { /* first time */
4877 as->a_objectdir = dir;
4878 as->a_sizedir = nalloc;
4879 return;
4883 * Null out all of the defunct entries in the old directory.
4885 nold = 0;
4886 nnew = nentries;
4887 for (i = 0; i < as->a_sizedir; i++) {
4888 if ((vp = as->a_objectdir[i]) != NULL) {
4889 for (j = 0; j < nentries; j++) {
4890 if (vp == dir[j]) {
4891 dir[j] = NULL;
4892 nnew--;
4893 break;
4896 if (j == nentries)
4897 as->a_objectdir[i] = NULL;
4898 else
4899 nold++;
4903 if (nold + nnew > as->a_sizedir) {
4905 * Reallocate the old directory to have enough
4906 * space for the old and new entries combined.
4907 * Round up to the next multiple of 16.
4909 ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
4910 vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
4911 KM_SLEEP);
4912 bcopy(as->a_objectdir, newdir,
4913 as->a_sizedir * sizeof (vnode_t *));
4914 kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
4915 as->a_objectdir = newdir;
4916 as->a_sizedir = newsize;
4920 * Move all new entries to the old directory and
4921 * deallocate the space used by the new directory.
4923 if (nnew) {
4924 for (i = 0, j = 0; i < nentries; i++) {
4925 if ((vp = dir[i]) == NULL)
4926 continue;
4927 for (; j < as->a_sizedir; j++) {
4928 if (as->a_objectdir[j] != NULL)
4929 continue;
4930 as->a_objectdir[j++] = vp;
4931 break;
4935 kmem_free(dir, nalloc * sizeof (vnode_t *));
4939 * Return the vnode from a slot in the process's object directory.
4940 * The caller must have locked the process's address space.
4941 * The only caller is below, in pr_readdir_objectdir().
4943 static vnode_t *
4944 obj_entry(struct as *as, int slot)
4946 ASSERT(AS_LOCK_HELD(as));
4947 if (as->a_objectdir == NULL)
4948 return (NULL);
4949 ASSERT(slot < as->a_sizedir);
4950 return (as->a_objectdir[slot]);
4953 /* ARGSUSED */
4954 static int
4955 pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4957 gfs_readdir_state_t gstate;
4958 int error, eof = 0;
4959 offset_t n;
4960 int pslot;
4961 size_t objdirsize;
4962 proc_t *p;
4963 struct as *as;
4964 vnode_t *vp;
4966 ASSERT(pnp->pr_type == PR_OBJECTDIR);
4968 if ((error = prlock(pnp, ZNO)) != 0)
4969 return (error);
4970 p = pnp->pr_common->prc_proc;
4971 pslot = p->p_slot;
4974 * We drop p_lock before grabbing the address space lock
4975 * in order to avoid a deadlock with the clock thread.
4976 * The process will not disappear and its address space
4977 * will not change because it is marked P_PR_LOCK.
4979 mutex_exit(&p->p_lock);
4981 if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
4982 pmkino(0, pslot, PR_PIDDIR),
4983 pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
4984 mutex_enter(&p->p_lock);
4985 prunlock(pnp);
4986 return (error);
4989 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4990 as = NULL;
4991 objdirsize = 0;
4995 * Loop until user's request is satisfied or until
4996 * all mapped objects have been examined. Cannot hold
4997 * the address space lock for the following call as
4998 * gfs_readdir_pred() utimately causes a call to uiomove().
5000 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5001 vattr_t vattr;
5002 char str[64];
5005 * Set the correct size of the directory just
5006 * in case the process has changed it's address
5007 * space via mmap/munmap calls.
5009 if (as != NULL) {
5010 AS_LOCK_ENTER(as, RW_WRITER);
5011 if (as->a_updatedir)
5012 rebuild_objdir(as);
5013 objdirsize = as->a_sizedir;
5017 * Find next object.
5019 vattr.va_mask = AT_FSID | AT_NODEID;
5020 while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
5021 (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)
5022 != 0))) {
5023 vattr.va_mask = AT_FSID | AT_NODEID;
5024 n++;
5027 if (as != NULL)
5028 AS_LOCK_EXIT(as);
5031 * Stop when all objects have been reported.
5033 if (n >= objdirsize) {
5034 eof = 1;
5035 break;
5038 if (vp == p->p_exec)
5039 (void) strcpy(str, "a.out");
5040 else
5041 pr_object_name(str, vp, &vattr);
5043 error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
5044 str, 0);
5046 if (error)
5047 break;
5050 mutex_enter(&p->p_lock);
5051 prunlock(pnp);
5053 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5056 /* ARGSUSED */
5057 static int
5058 pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5060 gfs_readdir_state_t gstate;
5061 int error, eof = 0;
5062 offset_t tslot;
5063 proc_t *p;
5064 int pslot;
5065 lwpdir_t *lwpdir;
5066 int lwpdirsize;
5068 ASSERT(pnp->pr_type == PR_LWPDIR);
5070 p = pr_p_lock(pnp);
5071 mutex_exit(&pr_pidlock);
5072 if (p == NULL)
5073 return (ENOENT);
5074 ASSERT(p == pnp->pr_common->prc_proc);
5075 pslot = p->p_slot;
5076 lwpdir = p->p_lwpdir;
5077 lwpdirsize = p->p_lwpdir_sz;
5080 * Drop p->p_lock so we can safely do uiomove().
5081 * The lwp directory will not change because
5082 * we have the process locked with P_PR_LOCK.
5084 mutex_exit(&p->p_lock);
5087 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5088 pmkino(0, pslot, PR_PIDDIR),
5089 pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
5090 mutex_enter(&p->p_lock);
5091 prunlock(pnp);
5092 return (error);
5096 * Loop until user's request is satisfied or until all lwps
5097 * have been examined.
5099 while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
5100 lwpent_t *lep;
5101 uint_t tid;
5104 * Find next LWP.
5106 while (tslot < lwpdirsize &&
5107 ((lep = lwpdir[tslot].ld_entry) == NULL))
5108 tslot++;
5110 * Stop when all lwps have been reported.
5112 if (tslot >= lwpdirsize) {
5113 eof = 1;
5114 break;
5117 tid = lep->le_lwpid;
5118 error = gfs_readdir_emitn(&gstate, uiop, tslot,
5119 pmkino(tslot, pslot, PR_LWPIDDIR), tid);
5120 if (error)
5121 break;
5124 mutex_enter(&p->p_lock);
5125 prunlock(pnp);
5127 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5130 /* ARGSUSED */
5131 static int
5132 pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5134 prcommon_t *pcp = pnp->pr_common;
5135 int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
5136 prdirent_t dirent;
5137 prdirent_t *dirp;
5138 offset_t off;
5139 int error;
5140 int pslot;
5141 int tslot;
5143 ASSERT(pnp->pr_type == PR_LWPIDDIR);
5145 if (uiop->uio_offset < 0 ||
5146 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
5147 uiop->uio_resid < sizeof (prdirent_t))
5148 return (EINVAL);
5149 if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
5150 return (ENOENT);
5151 if (uiop->uio_offset >= sizeof (lwpiddir))
5152 goto out;
5155 * Loop until user's request is satisfied, omitting some files
5156 * along the way if the lwp is a zombie and also depending
5157 * on the data model of the process.
5159 pslot = pcp->prc_slot;
5160 tslot = pcp->prc_tslot;
5161 for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
5162 uiop->uio_resid >= sizeof (prdirent_t) &&
5163 dirp < &lwpiddir[NLWPIDDIRFILES+2];
5164 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5165 off = uiop->uio_offset;
5166 if (zombie) {
5167 switch (dirp->d_ino) {
5168 case PR_LWPIDDIR:
5169 case PR_LWPDIR:
5170 case PR_LWPSINFO:
5171 break;
5172 default:
5173 continue;
5176 #if defined(__sparc)
5177 /* the asrs file exists only for sparc v9 _LP64 processes */
5178 if (dirp->d_ino == PR_ASRS &&
5179 pcp->prc_datamodel != DATAMODEL_LP64)
5180 continue;
5181 #endif
5182 bcopy(dirp, &dirent, sizeof (prdirent_t));
5183 if (dirent.d_ino == PR_LWPDIR)
5184 dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5185 else
5186 dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5187 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5188 UIO_READ, uiop)) != 0)
5189 return (error);
5191 out:
5192 if (eofp)
5193 *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5194 return (0);
5197 /* ARGSUSED */
5198 static int
5199 pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5201 gfs_readdir_state_t gstate;
5202 int error, eof = 0;
5203 offset_t n;
5204 proc_t *p;
5205 int pslot;
5206 int fddirsize;
5207 uf_info_t *fip;
5209 ASSERT(pnp->pr_type == PR_FDDIR);
5211 if ((error = prlock(pnp, ZNO)) != 0)
5212 return (error);
5213 p = pnp->pr_common->prc_proc;
5214 pslot = p->p_slot;
5215 fip = P_FINFO(p);
5216 mutex_exit(&p->p_lock);
5218 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5219 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
5220 mutex_enter(&p->p_lock);
5221 prunlock(pnp);
5222 return (error);
5225 mutex_enter(&fip->fi_lock);
5226 if ((p->p_flag & SSYS) || p->p_as == &kas)
5227 fddirsize = 0;
5228 else
5229 fddirsize = fip->fi_nfiles;
5232 * Loop until user's request is satisfied or until
5233 * all file descriptors have been examined.
5235 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5237 * Find next fd.
5239 while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5240 n++;
5242 * Stop when all fds have been reported.
5244 if (n >= fddirsize) {
5245 eof = 1;
5246 break;
5249 error = gfs_readdir_emitn(&gstate, uiop, n,
5250 pmkino(n, pslot, PR_FD), n);
5251 if (error)
5252 break;
5255 mutex_exit(&fip->fi_lock);
5256 mutex_enter(&p->p_lock);
5257 prunlock(pnp);
5259 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5262 /* ARGSUSED */
5263 static int
5264 pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5266 longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5267 dirent64_t *dirent = (dirent64_t *)bp;
5268 int reclen;
5269 ssize_t oresid;
5270 offset_t off, idx;
5271 int error = 0;
5272 proc_t *p;
5273 int fd, obj;
5274 int pslot;
5275 int fddirsize;
5276 uf_info_t *fip;
5277 struct as *as = NULL;
5278 size_t objdirsize;
5279 vattr_t vattr;
5280 vnode_t *vp;
5282 ASSERT(pnp->pr_type == PR_PATHDIR);
5284 if (uiop->uio_offset < 0 ||
5285 uiop->uio_resid <= 0 ||
5286 (uiop->uio_offset % PRSDSIZE) != 0)
5287 return (EINVAL);
5288 oresid = uiop->uio_resid;
5289 bzero(bp, sizeof (bp));
5291 if ((error = prlock(pnp, ZNO)) != 0)
5292 return (error);
5293 p = pnp->pr_common->prc_proc;
5294 fip = P_FINFO(p);
5295 pslot = p->p_slot;
5296 mutex_exit(&p->p_lock);
5298 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5299 as = NULL;
5300 objdirsize = 0;
5301 } else {
5302 AS_LOCK_ENTER(as, RW_WRITER);
5303 if (as->a_updatedir)
5304 rebuild_objdir(as);
5305 objdirsize = as->a_sizedir;
5306 AS_LOCK_EXIT(as);
5307 as = NULL;
5310 mutex_enter(&fip->fi_lock);
5311 if ((p->p_flag & SSYS) || p->p_as == &kas)
5312 fddirsize = 0;
5313 else
5314 fddirsize = fip->fi_nfiles;
5316 for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
5318 * There are 4 special files in the path directory: ".", "..",
5319 * "root", and "cwd". We handle those specially here.
5321 off = uiop->uio_offset;
5322 idx = off / PRSDSIZE;
5323 if (off == 0) { /* "." */
5324 dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
5325 dirent->d_name[0] = '.';
5326 dirent->d_name[1] = '\0';
5327 reclen = DIRENT64_RECLEN(1);
5328 } else if (idx == 1) { /* ".." */
5329 dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
5330 dirent->d_name[0] = '.';
5331 dirent->d_name[1] = '.';
5332 dirent->d_name[2] = '\0';
5333 reclen = DIRENT64_RECLEN(2);
5334 } else if (idx == 2) { /* "root" */
5335 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5336 (void) strcpy(dirent->d_name, "root");
5337 reclen = DIRENT64_RECLEN(4);
5338 } else if (idx == 3) { /* "cwd" */
5339 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5340 (void) strcpy(dirent->d_name, "cwd");
5341 reclen = DIRENT64_RECLEN(3);
5342 } else if (idx < 4 + fddirsize) {
5344 * In this case, we have one of the file descriptors.
5346 fd = idx - 4;
5347 if (fip->fi_list[fd].uf_file == NULL)
5348 continue;
5349 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5350 (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
5351 reclen = DIRENT64_RECLEN(PLNSIZ);
5352 } else if (idx < 4 + fddirsize + objdirsize) {
5353 if (fip != NULL) {
5354 mutex_exit(&fip->fi_lock);
5355 fip = NULL;
5359 * We drop p_lock before grabbing the address space lock
5360 * in order to avoid a deadlock with the clock thread.
5361 * The process will not disappear and its address space
5362 * will not change because it is marked P_PR_LOCK.
5364 if (as == NULL) {
5365 as = p->p_as;
5366 AS_LOCK_ENTER(as, RW_WRITER);
5369 if (as->a_updatedir) {
5370 rebuild_objdir(as);
5371 objdirsize = as->a_sizedir;
5374 obj = idx - 4 - fddirsize;
5375 if ((vp = obj_entry(as, obj)) == NULL)
5376 continue;
5377 vattr.va_mask = AT_FSID|AT_NODEID;
5378 if (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) != 0)
5379 continue;
5380 if (vp == p->p_exec)
5381 (void) strcpy(dirent->d_name, "a.out");
5382 else
5383 pr_object_name(dirent->d_name, vp, &vattr);
5384 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5385 reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
5386 } else {
5387 break;
5390 dirent->d_off = uiop->uio_offset + PRSDSIZE;
5391 dirent->d_reclen = (ushort_t)reclen;
5392 if (reclen > uiop->uio_resid) {
5394 * Error if no entries have been returned yet.
5396 if (uiop->uio_resid == oresid)
5397 error = EINVAL;
5398 break;
5401 * Drop the address space lock to do the uiomove().
5403 if (as != NULL)
5404 AS_LOCK_EXIT(as);
5406 error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
5407 if (as != NULL)
5408 AS_LOCK_ENTER(as, RW_WRITER);
5410 if (error)
5411 break;
5414 if (error == 0 && eofp)
5415 *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
5417 if (fip != NULL)
5418 mutex_exit(&fip->fi_lock);
5419 if (as != NULL)
5420 AS_LOCK_EXIT(as);
5421 mutex_enter(&p->p_lock);
5422 prunlock(pnp);
5423 return (error);
5426 static int
5427 pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
5429 proc_t *p;
5430 int pslot, tslot;
5431 gfs_readdir_state_t gstate;
5432 int error, eof = 0;
5433 offset_t n;
5435 ASSERT(pnp->pr_type == PR_TMPLDIR);
5437 if ((error = prlock(pnp, ZNO)) != 0)
5438 return (error);
5439 p = pnp->pr_common->prc_proc;
5440 pslot = pnp->pr_common->prc_slot;
5441 tslot = pnp->pr_common->prc_tslot;
5442 mutex_exit(&p->p_lock);
5444 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5445 pmkino(tslot, pslot, PR_LWPDIR),
5446 pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
5447 mutex_enter(&p->p_lock);
5448 prunlock(pnp);
5449 return (error);
5452 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5454 * Check for an active template. Reading a directory's
5455 * contents is already racy, so we don't bother taking
5456 * any locks.
5458 while (n < ct_ntypes &&
5459 pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
5460 n++;
5462 * Stop when all types have been reported.
5464 if (n >= ct_ntypes) {
5465 eof = 1;
5466 break;
5469 * The pmkino invocation below will need to be updated
5470 * when we create our fifth contract type.
5472 ASSERT(ct_ntypes <= 4);
5473 error = gfs_readdir_emit(&gstate, uiop, n,
5474 pmkino((tslot << 2) | n, pslot, PR_TMPL),
5475 ct_types[n]->ct_type_name, 0);
5476 if (error)
5477 break;
5480 mutex_enter(&p->p_lock);
5481 prunlock(pnp);
5483 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5486 static int
5487 pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5489 proc_t *p;
5490 int pslot;
5491 gfs_readdir_state_t gstate;
5492 int error, eof = 0;
5493 offset_t n;
5494 uint64_t zid;
5496 ASSERT(pnp->pr_type == PR_CTDIR);
5498 if ((error = prlock(pnp, ZNO)) != 0)
5499 return (error);
5500 p = pnp->pr_common->prc_proc;
5501 pslot = p->p_slot;
5502 mutex_exit(&p->p_lock);
5504 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5505 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
5506 mutex_enter(&p->p_lock);
5507 prunlock(pnp);
5508 return (error);
5511 zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
5512 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5513 id_t next = contract_plookup(p, n, zid);
5514 if (next == -1) {
5515 eof = 1;
5516 break;
5518 error = gfs_readdir_emitn(&gstate, uiop, next,
5519 pmkino(next, pslot, PR_CT), next);
5520 if (error)
5521 break;
5524 mutex_enter(&p->p_lock);
5525 prunlock(pnp);
5527 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5530 /* ARGSUSED */
5531 static int
5532 prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
5534 return (0);
5538 * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
5540 static void
5541 pr_list_unlink(vnode_t *pvp, vnode_t **listp)
5543 vnode_t *vp;
5544 prnode_t *pnp;
5546 while ((vp = *listp) != NULL) {
5547 pnp = VTOP(vp);
5548 if (vp == pvp) {
5549 *listp = pnp->pr_next;
5550 pnp->pr_next = NULL;
5551 break;
5553 listp = &pnp->pr_next;
5557 /* ARGSUSED */
5558 static void
5559 prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5561 prnode_t *pnp = VTOP(vp);
5562 prnodetype_t type = pnp->pr_type;
5563 proc_t *p;
5564 vnode_t *dp;
5565 vnode_t *ovp = NULL;
5566 prnode_t *opnp = NULL;
5568 switch (type) {
5569 case PR_OBJECT:
5570 case PR_FD:
5571 case PR_SELF:
5572 case PR_PATH:
5573 /* These are not linked into the usual lists */
5574 ASSERT(vp->v_count == 1);
5575 if ((dp = pnp->pr_parent) != NULL)
5576 VN_RELE(dp);
5577 prfreenode(pnp);
5578 return;
5579 default:
5580 break;
5583 mutex_enter(&pr_pidlock);
5584 if (pnp->pr_pcommon == NULL)
5585 p = NULL;
5586 else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
5587 mutex_enter(&p->p_lock);
5588 mutex_enter(&vp->v_lock);
5590 if (type == PR_PROCDIR || vp->v_count > 1) {
5591 vp->v_count--;
5592 mutex_exit(&vp->v_lock);
5593 if (p != NULL)
5594 mutex_exit(&p->p_lock);
5595 mutex_exit(&pr_pidlock);
5596 return;
5599 if ((dp = pnp->pr_parent) != NULL) {
5600 prnode_t *dpnp;
5602 switch (type) {
5603 case PR_PIDFILE:
5604 case PR_LWPIDFILE:
5605 case PR_OPAGEDATA:
5606 break;
5607 default:
5608 dpnp = VTOP(dp);
5609 mutex_enter(&dpnp->pr_mutex);
5610 if (dpnp->pr_files != NULL &&
5611 dpnp->pr_files[pnp->pr_index] == vp)
5612 dpnp->pr_files[pnp->pr_index] = NULL;
5613 mutex_exit(&dpnp->pr_mutex);
5614 break;
5616 pnp->pr_parent = NULL;
5619 ASSERT(vp->v_count == 1);
5622 * If we allocated an old /proc/pid node, free it too.
5624 if (pnp->pr_pidfile != NULL) {
5625 ASSERT(type == PR_PIDDIR);
5626 ovp = pnp->pr_pidfile;
5627 opnp = VTOP(ovp);
5628 ASSERT(opnp->pr_type == PR_PIDFILE);
5629 pnp->pr_pidfile = NULL;
5632 mutex_exit(&pr_pidlock);
5634 if (p != NULL) {
5636 * Remove the vnodes from the lists of
5637 * /proc vnodes for the process.
5639 int slot;
5641 switch (type) {
5642 case PR_PIDDIR:
5643 pr_list_unlink(vp, &p->p_trace);
5644 break;
5645 case PR_LWPIDDIR:
5646 if ((slot = pnp->pr_common->prc_tslot) != -1) {
5647 lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
5648 pr_list_unlink(vp, &lep->le_trace);
5650 break;
5651 default:
5652 pr_list_unlink(vp, &p->p_plist);
5653 break;
5655 if (ovp != NULL)
5656 pr_list_unlink(ovp, &p->p_plist);
5657 mutex_exit(&p->p_lock);
5660 mutex_exit(&vp->v_lock);
5662 if (type == PR_CT && pnp->pr_contract != NULL) {
5663 contract_rele(pnp->pr_contract);
5664 pnp->pr_contract = NULL;
5667 if (opnp != NULL)
5668 prfreenode(opnp);
5669 prfreenode(pnp);
5670 if (dp != NULL) {
5671 VN_RELE(dp);
5675 /* ARGSUSED */
5676 static int
5677 prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
5679 return (0);
5683 * We use the p_execdir member of proc_t to expand the %d token in core file
5684 * paths (the directory path for the executable that dumped core; see
5685 * coreadm(1M) for details). We'd like gcore(1) to be able to expand %d in
5686 * the same way as core dumping from the kernel, but there's no convenient
5687 * and comprehensible way to export the path name for p_execdir. To solve
5688 * this, we try to find the actual path to the executable that was used. In
5689 * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
5690 * flag, and use that here to indicate that more work is needed beyond the
5691 * call to vnodetopath().
5693 static int
5694 prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
5696 proc_t *p;
5697 vnode_t *vp, *execvp, *vrootp;
5698 int ret;
5699 size_t len;
5700 dirent64_t *dp;
5701 size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
5702 char *dbuf;
5704 p = curproc;
5705 mutex_enter(&p->p_lock);
5706 if ((vrootp = PTOU(p)->u_rdir) == NULL)
5707 vrootp = rootdir;
5708 VN_HOLD(vrootp);
5709 mutex_exit(&p->p_lock);
5711 ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
5714 * If PR_AOUT isn't set, then we looked up the path for the vnode;
5715 * otherwise, we looked up the path for (what we believe to be) the
5716 * containing directory.
5718 if ((pnp->pr_flags & PR_AOUT) == 0) {
5719 VN_RELE(vrootp);
5720 return (ret);
5724 * Fail if there's a problem locking the process. This will only
5725 * occur if the process is changing so the information we would
5726 * report would already be invalid.
5728 if (prlock(pnp, ZNO) != 0) {
5729 VN_RELE(vrootp);
5730 return (EIO);
5733 p = pnp->pr_common->prc_proc;
5734 mutex_exit(&p->p_lock);
5736 execvp = p->p_exec;
5737 VN_HOLD(execvp);
5740 * If our initial lookup of the directory failed, fall back to
5741 * the path name information for p_exec.
5743 if (ret != 0) {
5744 mutex_enter(&p->p_lock);
5745 prunlock(pnp);
5746 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5747 VN_RELE(execvp);
5748 VN_RELE(vrootp);
5749 return (ret);
5752 len = strlen(buf);
5755 * We use u_comm as a guess for the last component of the full
5756 * executable path name. If there isn't going to be enough space
5757 * we fall back to using the p_exec so that we can have _an_
5758 * answer even if it's not perfect.
5760 if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
5761 buf[len] = '/';
5762 (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
5763 mutex_enter(&p->p_lock);
5764 prunlock(pnp);
5767 * Do a forward lookup of our u_comm guess.
5769 if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
5770 &vp, pnp->pr_realvp) == 0) {
5771 if (vn_compare(vp, execvp)) {
5772 VN_RELE(vp);
5773 VN_RELE(execvp);
5774 VN_RELE(vrootp);
5775 return (0);
5778 VN_RELE(vp);
5780 } else {
5781 mutex_enter(&p->p_lock);
5782 prunlock(pnp);
5785 dbuf = kmem_alloc(dlen, KM_SLEEP);
5788 * Try to find a matching vnode by iterating through the directory's
5789 * entries. If that fails, fall back to the path information for
5790 * p_exec.
5792 if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
5793 dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
5794 buf[len] = '/';
5795 (void) strcpy(buf + len + 1, dp->d_name);
5796 } else {
5797 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5800 kmem_free(dbuf, dlen);
5801 VN_RELE(execvp);
5802 VN_RELE(vrootp);
5804 return (ret);
5807 /* ARGSUSED */
5808 static int
5809 prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
5811 prnode_t *pnp = VTOP(vp);
5812 char *buf;
5813 int ret = EINVAL;
5814 char idbuf[16];
5815 int length, rlength;
5816 contract_t *ct;
5818 switch (pnp->pr_type) {
5819 case PR_SELF:
5820 (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
5821 ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
5822 break;
5823 case PR_OBJECT:
5824 case PR_FD:
5825 case PR_CURDIR:
5826 case PR_ROOTDIR:
5827 if (pnp->pr_realvp->v_type == VDIR)
5828 ret = 0;
5829 break;
5830 case PR_PATH:
5831 buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5833 if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
5834 ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
5836 kmem_free(buf, MAXPATHLEN);
5837 break;
5838 case PR_CT:
5839 ASSERT(pnp->pr_contract != NULL);
5840 ct = pnp->pr_contract;
5841 length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
5842 strlen(ct->ct_type->ct_type_name);
5843 buf = kmem_alloc(length, KM_SLEEP);
5844 rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
5845 ct->ct_type->ct_type_name, ct->ct_id);
5846 ASSERT(rlength < length);
5847 ret = uiomove(buf, rlength, UIO_READ, uiop);
5848 kmem_free(buf, length);
5849 break;
5850 default:
5851 break;
5854 return (ret);
5857 /*ARGSUSED2*/
5858 static int
5859 prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
5861 prnode_t *pp1, *pp2;
5863 if (vp1 == vp2)
5864 return (1);
5866 if (!vn_matchops(vp1, prvnodeops) || !vn_matchops(vp2, prvnodeops))
5867 return (0);
5869 pp1 = VTOP(vp1);
5870 pp2 = VTOP(vp2);
5872 if (pp1->pr_type != pp2->pr_type)
5873 return (0);
5874 if (pp1->pr_type == PR_PROCDIR)
5875 return (1);
5876 if (pp1->pr_ino || pp2->pr_ino)
5877 return (pp2->pr_ino == pp1->pr_ino);
5879 if (pp1->pr_common == NULL || pp2->pr_common == NULL)
5880 return (0);
5882 return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
5883 pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
5886 static int
5887 prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
5889 vnode_t *rvp;
5891 if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
5892 vp = rvp;
5893 if (VOP_REALVP(vp, &rvp, ct) == 0)
5894 vp = rvp;
5897 *vpp = vp;
5898 return (0);
5902 * Return the answer requested to poll().
5903 * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
5904 * In addition, these have special meaning for /proc files:
5905 * POLLPRI process or lwp stopped on an event of interest
5906 * POLLERR /proc file descriptor is invalid
5907 * POLLHUP process or lwp has terminated
5909 /*ARGSUSED5*/
5910 static int
5911 prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
5912 pollhead_t **phpp, caller_context_t *ct)
5914 prnode_t *pnp = VTOP(vp);
5915 prcommon_t *pcp = pnp->pr_common;
5916 pollhead_t *php = &pcp->prc_pollhead;
5917 proc_t *p;
5918 short revents;
5919 int error;
5920 int lockstate;
5922 ASSERT(pnp->pr_type < PR_NFILES);
5925 * Support for old /proc interface.
5927 if (pnp->pr_pidfile != NULL) {
5928 vp = pnp->pr_pidfile;
5929 pnp = VTOP(vp);
5930 ASSERT(pnp->pr_type == PR_PIDFILE);
5931 ASSERT(pnp->pr_common == pcp);
5934 *reventsp = revents = 0;
5935 *phpp = (pollhead_t *)NULL;
5937 if (vp->v_type == VDIR) {
5938 *reventsp |= POLLNVAL;
5939 return (0);
5942 /* avoid deadlock with prnotify() */
5943 if (pollunlock(&lockstate) != 0) {
5944 *reventsp = POLLNVAL;
5945 return (0);
5948 if ((error = prlock(pnp, ZNO)) != 0) {
5949 pollrelock(lockstate);
5950 switch (error) {
5951 case ENOENT: /* process or lwp died */
5952 *reventsp = POLLHUP;
5953 error = 0;
5954 break;
5955 case EAGAIN: /* invalidated */
5956 *reventsp = POLLERR;
5957 error = 0;
5958 break;
5960 return (error);
5964 * We have the process marked locked (P_PR_LOCK) and we are holding
5965 * its p->p_lock. We want to unmark the process but retain
5966 * exclusive control w.r.t. other /proc controlling processes
5967 * before reacquiring the polling locks.
5969 * prunmark() does this for us. It unmarks the process
5970 * but retains p->p_lock so we still have exclusive control.
5971 * We will drop p->p_lock at the end to relinquish control.
5973 * We cannot call prunlock() at the end to relinquish control
5974 * because prunlock(), like prunmark(), may drop and reacquire
5975 * p->p_lock and that would lead to a lock order violation
5976 * w.r.t. the polling locks we are about to reacquire.
5978 p = pcp->prc_proc;
5979 ASSERT(p != NULL);
5980 prunmark(p);
5982 pollrelock(lockstate); /* reacquire dropped poll locks */
5984 if ((p->p_flag & SSYS) || p->p_as == &kas)
5985 revents = POLLNVAL;
5986 else {
5987 short ev;
5989 if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
5990 revents |= ev;
5992 * POLLWRNORM (same as POLLOUT) really should not be
5993 * used to indicate that the process or lwp stopped.
5994 * However, USL chose to use POLLWRNORM rather than
5995 * POLLPRI to indicate this, so we just accept either
5996 * requested event to indicate stopped. (grr...)
5998 if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
5999 kthread_t *t;
6001 if (pcp->prc_flags & PRC_LWP) {
6002 t = pcp->prc_thread;
6003 ASSERT(t != NULL);
6004 thread_lock(t);
6005 } else {
6006 t = prchoose(p); /* returns locked t */
6007 ASSERT(t != NULL);
6010 if (ISTOPPED(t) || VSTOPPED(t))
6011 revents |= ev;
6012 thread_unlock(t);
6016 *reventsp = revents;
6017 if ((!anyyet && revents == 0) || (events & POLLET)) {
6019 * Arrange to wake up the polling lwp when
6020 * the target process/lwp stops or terminates
6021 * or when the file descriptor becomes invalid.
6023 pcp->prc_flags |= PRC_POLL;
6024 *phpp = php;
6026 mutex_exit(&p->p_lock);
6027 return (0);
6030 /* in prioctl.c */
6031 extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
6032 caller_context_t *);
6035 * /proc vnode operations vector
6037 const fs_operation_def_t pr_vnodeops_template[] = {
6038 VOPNAME_OPEN, { .vop_open = propen },
6039 VOPNAME_CLOSE, { .vop_close = prclose },
6040 VOPNAME_READ, { .vop_read = prread },
6041 VOPNAME_WRITE, { .vop_write = prwrite },
6042 VOPNAME_IOCTL, { .vop_ioctl = prioctl },
6043 VOPNAME_GETATTR, { .vop_getattr = prgetattr },
6044 VOPNAME_ACCESS, { .vop_access = praccess },
6045 VOPNAME_LOOKUP, { .vop_lookup = prlookup },
6046 VOPNAME_CREATE, { .vop_create = prcreate },
6047 VOPNAME_READDIR, { .vop_readdir = prreaddir },
6048 VOPNAME_READLINK, { .vop_readlink = prreadlink },
6049 VOPNAME_FSYNC, { .vop_fsync = prfsync },
6050 VOPNAME_INACTIVE, { .vop_inactive = prinactive },
6051 VOPNAME_SEEK, { .vop_seek = prseek },
6052 VOPNAME_CMP, { .vop_cmp = prcmp },
6053 VOPNAME_FRLOCK, { .error = fs_error },
6054 VOPNAME_REALVP, { .vop_realvp = prrealvp },
6055 VOPNAME_POLL, { .vop_poll = prpoll },
6056 VOPNAME_DISPOSE, { .error = fs_error },
6057 VOPNAME_SHRLOCK, { .error = fs_error },
6058 NULL, NULL