remove unnecessary uint_t casts of 0
[unleashed.git] / kernel / fs / proc / prvnops.c
blobab452255afd46d7212b0d7c6a5fd6e49e1a1ed15
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) 2017, Joyent, Inc.
25 * Copyright (c) 2017 by Delphix. All rights reserved.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/cred.h>
35 #include <sys/policy.h>
36 #include <sys/debug.h>
37 #include <sys/dirent.h>
38 #include <sys/errno.h>
39 #include <sys/file.h>
40 #include <sys/inline.h>
41 #include <sys/kmem.h>
42 #include <sys/pathname.h>
43 #include <sys/proc.h>
44 #include <sys/brand.h>
45 #include <sys/signal.h>
46 #include <sys/stat.h>
47 #include <sys/sysmacros.h>
48 #include <sys/systm.h>
49 #include <sys/zone.h>
50 #include <sys/uio.h>
51 #include <sys/var.h>
52 #include <sys/mode.h>
53 #include <sys/poll.h>
54 #include <sys/user.h>
55 #include <sys/vfs.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 <sys/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 <sys/proc/prdata.h>
73 #if defined(__x86)
74 #include <sys/sysi86.h>
75 #endif
78 * Directory characteristics (patterned after the s5 file system).
80 #define PRROOTINO 2
82 #define PRDIRSIZE 14
83 struct prdirect {
84 ushort_t d_ino;
85 char d_name[PRDIRSIZE];
88 #define PRSDSIZE (sizeof (struct prdirect))
91 * Directory characteristics.
93 typedef struct prdirent {
94 ino64_t d_ino; /* "inode number" of entry */
95 off64_t d_off; /* offset of disk directory entry */
96 unsigned short d_reclen; /* length of this record */
97 char d_name[14]; /* name of file */
98 } prdirent_t;
101 * Contents of a /proc/<pid> directory.
102 * Reuse d_ino field for the /proc file type.
104 static prdirent_t piddir[] = {
105 { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
106 "." },
107 { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
108 ".." },
109 { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
110 "as" },
111 { PR_CTL, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
112 "ctl" },
113 { PR_STATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
114 "status" },
115 { PR_LSTATUS, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
116 "lstatus" },
117 { PR_PSINFO, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
118 "psinfo" },
119 { PR_LPSINFO, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
120 "lpsinfo" },
121 { PR_MAP, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
122 "map" },
123 { PR_RMAP, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
124 "rmap" },
125 { PR_XMAP, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
126 "xmap" },
127 { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
128 "cred" },
129 { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
130 "sigact" },
131 { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
132 "auxv" },
133 { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
134 "usage" },
135 { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
136 "lusage" },
137 { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
138 "pagedata" },
139 { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
140 "watch" },
141 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
142 "cwd" },
143 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
144 "root" },
145 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
146 "fd" },
147 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
148 "object" },
149 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
150 "lwp" },
151 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
152 "priv" },
153 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
154 "path" },
155 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
156 "contracts" },
157 { PR_SECFLAGS, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
158 "secflags" },
159 #if defined(__x86)
160 { PR_LDT, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
161 "ldt" },
162 #endif
165 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
168 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
170 static prdirent_t lwpiddir[] = {
171 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
172 "." },
173 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
174 ".." },
175 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
176 "lwpctl" },
177 { PR_LWPSTATUS, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
178 "lwpstatus" },
179 { PR_LWPSINFO, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
180 "lwpsinfo" },
181 { PR_LWPUSAGE, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
182 "lwpusage" },
183 { PR_XREGS, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
184 "xregs" },
185 { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
186 "templates" },
187 { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
188 "spymaster" },
191 #define NLWPIDDIRFILES (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
194 * Span of entries in the array files (lstatus, lpsinfo, lusage).
195 * We make the span larger than the size of the structure on purpose,
196 * to make sure that programs cannot use the structure size by mistake.
197 * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
199 #ifdef _LP64
200 #define LSPAN(type) (round16(sizeof (type)) + 16)
201 #define LSPAN32(type) (round8(sizeof (type)) + 8)
202 #else
203 #define LSPAN(type) (round8(sizeof (type)) + 8)
204 #endif
206 static void rebuild_objdir(struct as *);
207 static void prfreecommon(prcommon_t *);
208 static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
210 static int
211 propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
213 vnode_t *vp = *vpp;
214 prnode_t *pnp = VTOP(vp);
215 prcommon_t *pcp = pnp->pr_pcommon;
216 prnodetype_t type = pnp->pr_type;
217 vnode_t *rvp;
218 vtype_t vtype;
219 proc_t *p;
220 int error = 0;
221 prnode_t *npnp = NULL;
224 * Nothing to do for the /proc directory itself.
226 if (type == PR_PROCDIR)
227 return (0);
230 * If we are opening an underlying mapped object, reject opens
231 * for writing regardless of the objects's access modes.
232 * If we are opening a file in the /proc/pid/fd directory,
233 * reject the open for any but a regular file or directory.
234 * Just do it if we are opening the current or root directory.
236 switch (type) {
237 case PR_OBJECT:
238 case PR_FD:
239 case PR_CURDIR:
240 case PR_ROOTDIR:
241 rvp = pnp->pr_realvp;
242 vtype = rvp->v_type;
243 if ((type == PR_OBJECT && (flag & FWRITE)) ||
244 (type == PR_FD && vtype != VREG && vtype != VDIR))
245 error = EACCES;
246 else {
248 * Need to hold rvp since fop_open() may release it.
250 VN_HOLD(rvp);
251 error = fop_open(&rvp, flag, cr, ct);
252 if (error) {
253 VN_RELE(rvp);
254 } else {
255 *vpp = rvp;
256 VN_RELE(vp);
259 return (error);
260 default:
261 break;
265 * If we are opening the pagedata file, allocate a prnode now
266 * to avoid calling kmem_alloc() while holding p->p_lock.
268 if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
269 npnp = prgetnode(vp, type);
272 * If the process exists, lock it now.
273 * Otherwise we have a race condition with prclose().
275 p = pr_p_lock(pnp);
276 mutex_exit(&pr_pidlock);
277 if (p == NULL) {
278 if (npnp != NULL)
279 prfreenode(npnp);
280 return (ENOENT);
282 ASSERT(p == pcp->prc_proc);
283 ASSERT(p->p_proc_flag & P_PR_LOCK);
286 * Maintain a count of opens for write. Allow exactly one
287 * O_WRITE|O_EXCL request and fail subsequent ones.
288 * Don't fail opens of old (bletch!) /proc lwp files.
289 * Special case for open by the process itself:
290 * Always allow the open by self and discount this
291 * open for other opens for writing.
293 if (flag & FWRITE) {
294 if (p == curproc) {
295 pcp->prc_selfopens++;
296 pnp->pr_flags |= PR_ISSELF;
297 } else if (type == PR_LWPIDFILE) {
298 /* EMPTY */;
299 } else if (flag & FEXCL) {
300 if (pcp->prc_writers > pcp->prc_selfopens) {
301 error = EBUSY;
302 goto out;
304 /* semantic for old /proc interface */
305 if (type == PR_PIDDIR)
306 pcp->prc_flags |= PRC_EXCL;
307 } else if (pcp->prc_flags & PRC_EXCL) {
308 ASSERT(pcp->prc_writers > pcp->prc_selfopens);
309 error = secpolicy_proc_excl_open(cr);
310 if (error)
311 goto out;
313 pcp->prc_writers++;
315 * The vnode may have become invalid between the
316 * fop_lookup() of the /proc vnode and the fop_open().
317 * If so, do now what prinvalidate() should have done.
319 if ((pnp->pr_flags & PR_INVAL) ||
320 (type == PR_PIDDIR &&
321 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
322 if (p != curproc)
323 pcp->prc_selfopens++;
324 ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
325 if (pcp->prc_selfopens == pcp->prc_writers)
326 pcp->prc_flags &= ~PRC_EXCL;
331 * If this is a large file open, indicate that in our flags -- some
332 * procfs structures are not off_t-neutral (e.g., priovec_t), and
333 * the open will need to be differentiated where 32-bit processes
334 * pass these structures across the user/kernel boundary.
336 if (flag & FOFFMAX)
337 pnp->pr_flags |= PR_OFFMAX;
340 * Do file-specific things.
342 switch (type) {
343 default:
344 break;
345 case PR_PAGEDATA:
346 case PR_OPAGEDATA:
348 * Enable data collection for page data file;
349 * get unique id from the hat layer.
352 int id;
355 * Drop p->p_lock to call hat_startstat()
357 mutex_exit(&p->p_lock);
358 if ((p->p_flag & SSYS) || p->p_as == &kas ||
359 (id = hat_startstat(p->p_as)) == -1) {
360 mutex_enter(&p->p_lock);
361 error = ENOMEM;
362 } else if (pnp->pr_hatid == 0) {
363 mutex_enter(&p->p_lock);
364 pnp->pr_hatid = (uint_t)id;
365 } else {
366 mutex_enter(&p->p_lock);
368 * Use our newly allocated prnode.
370 npnp->pr_hatid = (uint_t)id;
372 * prgetnode() initialized most of the prnode.
373 * Duplicate the remainder.
375 npnp->pr_ino = pnp->pr_ino;
376 npnp->pr_common = pnp->pr_common;
377 npnp->pr_pcommon = pnp->pr_pcommon;
378 npnp->pr_parent = pnp->pr_parent;
379 VN_HOLD(npnp->pr_parent);
380 npnp->pr_index = pnp->pr_index;
382 npnp->pr_next = p->p_plist;
383 p->p_plist = PTOV(npnp);
385 VN_RELE(PTOV(pnp));
386 pnp = npnp;
387 npnp = NULL;
388 *vpp = PTOV(pnp);
391 break;
394 out:
395 prunlock(pnp);
397 if (npnp != NULL)
398 prfreenode(npnp);
399 return (error);
402 /* ARGSUSED */
403 static int
404 prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
405 caller_context_t *ct)
407 prnode_t *pnp = VTOP(vp);
408 prcommon_t *pcp = pnp->pr_pcommon;
409 prnodetype_t type = pnp->pr_type;
410 proc_t *p;
411 kthread_t *t;
412 user_t *up;
415 * Nothing to do for the /proc directory itself.
417 if (type == PR_PROCDIR)
418 return (0);
420 ASSERT(type != PR_OBJECT && type != PR_FD &&
421 type != PR_CURDIR && type != PR_ROOTDIR);
424 * If the process exists, lock it now.
425 * Otherwise we have a race condition with propen().
426 * Hold pr_pidlock across the reference to prc_selfopens,
427 * and prc_writers in case there is no process anymore,
428 * to cover the case of concurrent calls to prclose()
429 * after the process has been reaped by freeproc().
431 p = pr_p_lock(pnp);
434 * There is nothing more to do until the last close of
435 * the file table entry except to clear the pr_owner
436 * field of the prnode and notify any waiters
437 * (their file descriptor may have just been closed).
439 if (count > 1) {
440 mutex_exit(&pr_pidlock);
441 if (pnp->pr_owner == curproc && !fisopen(vp))
442 pnp->pr_owner = NULL;
443 if (p != NULL) {
444 prnotify(vp);
445 prunlock(pnp);
447 return (0);
451 * Decrement the count of self-opens for writing.
452 * Decrement the total count of opens for writing.
453 * Cancel exclusive opens when only self-opens remain.
455 if (flag & FWRITE) {
457 * prc_selfopens also contains the count of
458 * invalid writers. See prinvalidate().
460 if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
461 (type == PR_PIDDIR &&
462 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
463 ASSERT(pcp->prc_selfopens != 0);
464 --pcp->prc_selfopens;
466 ASSERT(pcp->prc_writers != 0);
467 if (--pcp->prc_writers == pcp->prc_selfopens)
468 pcp->prc_flags &= ~PRC_EXCL;
470 ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
471 mutex_exit(&pr_pidlock);
472 if (pnp->pr_owner == curproc && !fisopen(vp))
473 pnp->pr_owner = NULL;
476 * If there is no process, there is nothing more to do.
478 if (p == NULL)
479 return (0);
481 ASSERT(p == pcp->prc_proc);
482 prnotify(vp); /* notify waiters */
485 * Do file-specific things.
487 switch (type) {
488 default:
489 break;
490 case PR_PAGEDATA:
491 case PR_OPAGEDATA:
493 * This is a page data file.
494 * Free the hat level statistics.
495 * Drop p->p_lock before calling hat_freestat().
497 mutex_exit(&p->p_lock);
498 if (p->p_as != &kas && pnp->pr_hatid != 0)
499 hat_freestat(p->p_as, pnp->pr_hatid);
500 mutex_enter(&p->p_lock);
501 pnp->pr_hatid = 0;
502 break;
506 * On last close of all writable file descriptors,
507 * perform run-on-last-close and/or kill-on-last-close logic.
508 * Can't do this is the /proc agent lwp still exists.
510 if (pcp->prc_writers == 0 &&
511 p->p_agenttp == NULL &&
512 !(pcp->prc_flags & PRC_DESTROY) &&
513 p->p_stat != SZOMB &&
514 (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
515 int killproc;
518 * Cancel any watchpoints currently in effect.
519 * The process might disappear during this operation.
521 if (pr_cancel_watch(pnp) == NULL)
522 return (0);
524 * If any tracing flags are set, clear them.
526 if (p->p_proc_flag & P_PR_TRACE) {
527 up = PTOU(p);
528 premptyset(&up->u_entrymask);
529 premptyset(&up->u_exitmask);
530 up->u_systrap = 0;
532 premptyset(&p->p_sigmask);
533 premptyset(&p->p_fltmask);
534 killproc = (p->p_proc_flag & P_PR_KILLCL);
535 p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
537 * Cancel any outstanding single-step requests.
539 if ((t = p->p_tlist) != NULL) {
541 * Drop p_lock because prnostep() touches the stack.
542 * The loop is safe because the process is P_PR_LOCK'd.
544 mutex_exit(&p->p_lock);
545 do {
546 prnostep(ttolwp(t));
547 } while ((t = t->t_forw) != p->p_tlist);
548 mutex_enter(&p->p_lock);
551 * Set runnable all lwps stopped by /proc.
553 if (killproc)
554 sigtoproc(p, NULL, SIGKILL);
555 else
556 allsetrun(p);
559 prunlock(pnp);
560 return (0);
564 * Array of read functions, indexed by /proc file type.
566 static int pr_read_inval(), pr_read_as(), pr_read_status(),
567 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
568 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
569 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
570 #if defined(__x86)
571 pr_read_ldt(),
572 #endif
573 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
574 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
575 pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
576 pr_read_spymaster(), pr_read_secflags(),
577 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
579 static int (*pr_read_function[PR_NFILES])() = {
580 pr_read_inval, /* /proc */
581 pr_read_inval, /* /proc/self */
582 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
583 pr_read_as, /* /proc/<pid>/as */
584 pr_read_inval, /* /proc/<pid>/ctl */
585 pr_read_status, /* /proc/<pid>/status */
586 pr_read_lstatus, /* /proc/<pid>/lstatus */
587 pr_read_psinfo, /* /proc/<pid>/psinfo */
588 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
589 pr_read_map, /* /proc/<pid>/map */
590 pr_read_rmap, /* /proc/<pid>/rmap */
591 pr_read_xmap, /* /proc/<pid>/xmap */
592 pr_read_cred, /* /proc/<pid>/cred */
593 pr_read_sigact, /* /proc/<pid>/sigact */
594 pr_read_auxv, /* /proc/<pid>/auxv */
595 #if defined(__x86)
596 pr_read_ldt, /* /proc/<pid>/ldt */
597 #endif
598 pr_read_usage, /* /proc/<pid>/usage */
599 pr_read_lusage, /* /proc/<pid>/lusage */
600 pr_read_pagedata, /* /proc/<pid>/pagedata */
601 pr_read_watch, /* /proc/<pid>/watch */
602 pr_read_inval, /* /proc/<pid>/cwd */
603 pr_read_inval, /* /proc/<pid>/root */
604 pr_read_inval, /* /proc/<pid>/fd */
605 pr_read_inval, /* /proc/<pid>/fd/nn */
606 pr_read_inval, /* /proc/<pid>/object */
607 pr_read_inval, /* /proc/<pid>/object/xxx */
608 pr_read_inval, /* /proc/<pid>/lwp */
609 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
610 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
611 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
612 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
613 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
614 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
615 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
616 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
617 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
618 pr_read_priv, /* /proc/<pid>/priv */
619 pr_read_inval, /* /proc/<pid>/path */
620 pr_read_inval, /* /proc/<pid>/path/xxx */
621 pr_read_inval, /* /proc/<pid>/contracts */
622 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
623 pr_read_secflags, /* /proc/<pid>/secflags */
624 pr_read_pidfile, /* old process file */
625 pr_read_pidfile, /* old lwp file */
626 pr_read_opagedata, /* old pagedata file */
629 /* ARGSUSED */
630 static int
631 pr_read_inval(prnode_t *pnp, uio_t *uiop)
634 * No read() on any /proc directory, use getdents(2) instead.
635 * Cannot read a control file either.
636 * An underlying mapped object file cannot get here.
638 return (EINVAL);
641 static int
642 pr_uioread(void *base, long count, uio_t *uiop)
644 int error = 0;
646 ASSERT(count >= 0);
647 count -= uiop->uio_offset;
648 if (count > 0 && uiop->uio_offset >= 0) {
649 error = uiomove((char *)base + uiop->uio_offset,
650 count, UIO_READ, uiop);
653 return (error);
656 static int
657 pr_read_as(prnode_t *pnp, uio_t *uiop)
659 int error;
661 ASSERT(pnp->pr_type == PR_AS);
663 if ((error = prlock(pnp, ZNO)) == 0) {
664 proc_t *p = pnp->pr_common->prc_proc;
665 struct as *as = p->p_as;
668 * /proc I/O cannot be done to a system process.
669 * A 32-bit process cannot read a 64-bit process.
671 if ((p->p_flag & SSYS) || as == &kas) {
672 error = 0;
673 #ifdef _SYSCALL32_IMPL
674 } else if (curproc->p_model == DATAMODEL_ILP32 &&
675 PROCESS_NOT_32BIT(p)) {
676 error = EOVERFLOW;
677 #endif
678 } else {
680 * We don't hold p_lock over an i/o operation because
681 * that could lead to deadlock with the clock thread.
683 mutex_exit(&p->p_lock);
684 error = prusrio(p, UIO_READ, uiop, 0);
685 mutex_enter(&p->p_lock);
687 prunlock(pnp);
690 return (error);
693 static int
694 pr_read_status(prnode_t *pnp, uio_t *uiop)
696 pstatus_t *sp;
697 int error;
699 ASSERT(pnp->pr_type == PR_STATUS);
702 * We kmem_alloc() the pstatus structure because
703 * it is so big it might blow the kernel stack.
705 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
706 if ((error = prlock(pnp, ZNO)) == 0) {
707 prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
708 prunlock(pnp);
709 error = pr_uioread(sp, sizeof (*sp), uiop);
711 kmem_free(sp, sizeof (*sp));
712 return (error);
715 static int
716 pr_read_lstatus(prnode_t *pnp, uio_t *uiop)
718 proc_t *p;
719 kthread_t *t;
720 lwpdir_t *ldp;
721 size_t size;
722 prheader_t *php;
723 lwpstatus_t *sp;
724 int error;
725 int nlwp;
726 int i;
728 ASSERT(pnp->pr_type == PR_LSTATUS);
730 if ((error = prlock(pnp, ZNO)) != 0)
731 return (error);
732 p = pnp->pr_common->prc_proc;
733 nlwp = p->p_lwpcnt;
734 size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
736 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
737 mutex_exit(&p->p_lock);
738 php = kmem_zalloc(size, KM_SLEEP);
739 mutex_enter(&p->p_lock);
740 /* p->p_lwpcnt can't change while process is locked */
741 ASSERT(nlwp == p->p_lwpcnt);
743 php->pr_nent = nlwp;
744 php->pr_entsize = LSPAN(lwpstatus_t);
746 sp = (lwpstatus_t *)(php + 1);
747 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
748 if (ldp->ld_entry == NULL ||
749 (t = ldp->ld_entry->le_thread) == NULL)
750 continue;
751 prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
752 sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
754 prunlock(pnp);
756 error = pr_uioread(php, size, uiop);
757 kmem_free(php, size);
758 return (error);
761 static int
762 pr_read_psinfo(prnode_t *pnp, uio_t *uiop)
764 psinfo_t psinfo;
765 proc_t *p;
766 int error = 0;
768 ASSERT(pnp->pr_type == PR_PSINFO);
771 * We don't want the full treatment of prlock(pnp) here.
772 * This file is world-readable and never goes invalid.
773 * It doesn't matter if we are in the middle of an exec().
775 p = pr_p_lock(pnp);
776 mutex_exit(&pr_pidlock);
777 if (p == NULL)
778 error = ENOENT;
779 else {
780 ASSERT(p == pnp->pr_common->prc_proc);
781 prgetpsinfo(p, &psinfo);
782 prunlock(pnp);
783 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
785 return (error);
788 static int
789 pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
791 proc_t *p;
792 kthread_t *t;
793 lwpdir_t *ldp;
794 lwpent_t *lep;
795 size_t size;
796 prheader_t *php;
797 lwpsinfo_t *sp;
798 int error;
799 int nlwp;
800 int i;
802 ASSERT(pnp->pr_type == PR_LPSINFO);
805 * We don't want the full treatment of prlock(pnp) here.
806 * This file is world-readable and never goes invalid.
807 * It doesn't matter if we are in the middle of an exec().
809 p = pr_p_lock(pnp);
810 mutex_exit(&pr_pidlock);
811 if (p == NULL)
812 return (ENOENT);
813 ASSERT(p == pnp->pr_common->prc_proc);
814 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
815 prunlock(pnp);
816 return (ENOENT);
818 size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
820 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
821 mutex_exit(&p->p_lock);
822 php = kmem_zalloc(size, KM_SLEEP);
823 mutex_enter(&p->p_lock);
824 /* p->p_lwpcnt can't change while process is locked */
825 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
827 php->pr_nent = nlwp;
828 php->pr_entsize = LSPAN(lwpsinfo_t);
830 sp = (lwpsinfo_t *)(php + 1);
831 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
832 if ((lep = ldp->ld_entry) == NULL)
833 continue;
834 if ((t = lep->le_thread) != NULL)
835 prgetlwpsinfo(t, sp);
836 else {
837 bzero(sp, sizeof (*sp));
838 sp->pr_lwpid = lep->le_lwpid;
839 sp->pr_state = SZOMB;
840 sp->pr_sname = 'Z';
841 sp->pr_start.tv_sec = lep->le_start;
842 sp->pr_bindpro = PBIND_NONE;
843 sp->pr_bindpset = PS_NONE;
845 sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
847 prunlock(pnp);
849 error = pr_uioread(php, size, uiop);
850 kmem_free(php, size);
851 return (error);
854 static int
855 pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
857 proc_t *p;
858 struct as *as;
859 list_t iolhead;
860 int error;
862 readmap_common:
863 if ((error = prlock(pnp, ZNO)) != 0)
864 return (error);
866 p = pnp->pr_common->prc_proc;
867 as = p->p_as;
869 if ((p->p_flag & SSYS) || as == &kas) {
870 prunlock(pnp);
871 return (0);
874 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
875 prunlock(pnp);
876 delay(1);
877 goto readmap_common;
879 mutex_exit(&p->p_lock);
881 switch (type) {
882 case PR_XMAP:
883 error = prgetxmap(p, &iolhead);
884 break;
885 case PR_RMAP:
886 error = prgetmap(p, 1, &iolhead);
887 break;
888 case PR_MAP:
889 error = prgetmap(p, 0, &iolhead);
890 break;
893 AS_LOCK_EXIT(as);
894 mutex_enter(&p->p_lock);
895 prunlock(pnp);
897 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
899 return (error);
902 static int
903 pr_read_map(prnode_t *pnp, uio_t *uiop)
905 ASSERT(pnp->pr_type == PR_MAP);
906 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
909 static int
910 pr_read_rmap(prnode_t *pnp, uio_t *uiop)
912 ASSERT(pnp->pr_type == PR_RMAP);
913 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
916 static int
917 pr_read_xmap(prnode_t *pnp, uio_t *uiop)
919 ASSERT(pnp->pr_type == PR_XMAP);
920 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
923 static int
924 pr_read_cred(prnode_t *pnp, uio_t *uiop)
926 proc_t *p;
927 prcred_t *pcrp;
928 int error;
929 size_t count;
931 ASSERT(pnp->pr_type == PR_CRED);
934 * We kmem_alloc() the prcred_t structure because
935 * the number of supplementary groups is variable.
937 pcrp =
938 kmem_alloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
939 KM_SLEEP);
941 if ((error = prlock(pnp, ZNO)) != 0)
942 goto out;
943 p = pnp->pr_common->prc_proc;
944 ASSERT(p != NULL);
946 prgetcred(p, pcrp);
947 prunlock(pnp);
949 count = sizeof (prcred_t);
950 if (pcrp->pr_ngroups > 1)
951 count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
952 error = pr_uioread(pcrp, count, uiop);
953 out:
954 kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
955 return (error);
958 static int
959 pr_read_priv(prnode_t *pnp, uio_t *uiop)
961 proc_t *p;
962 size_t psize = prgetprivsize();
963 prpriv_t *ppriv = kmem_alloc(psize, KM_SLEEP);
964 int error;
966 ASSERT(pnp->pr_type == PR_PRIV);
968 if ((error = prlock(pnp, ZNO)) != 0)
969 goto out;
970 p = pnp->pr_common->prc_proc;
971 ASSERT(p != NULL);
973 prgetpriv(p, ppriv);
974 prunlock(pnp);
976 error = pr_uioread(ppriv, psize, uiop);
977 out:
978 kmem_free(ppriv, psize);
979 return (error);
982 static int
983 pr_read_sigact(prnode_t *pnp, uio_t *uiop)
985 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
986 proc_t *p;
987 struct sigaction *sap;
988 int sig;
989 int error;
990 user_t *up;
992 ASSERT(pnp->pr_type == PR_SIGACT);
995 * We kmem_alloc() the sigaction array because
996 * it is so big it might blow the kernel stack.
998 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
1000 if ((error = prlock(pnp, ZNO)) != 0)
1001 goto out;
1002 p = pnp->pr_common->prc_proc;
1003 ASSERT(p != NULL);
1005 if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
1006 prunlock(pnp);
1007 goto out;
1010 up = PTOU(p);
1011 for (sig = 1; sig < nsig; sig++)
1012 prgetaction(p, up, sig, &sap[sig-1]);
1013 prunlock(pnp);
1015 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
1016 out:
1017 kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
1018 return (error);
1021 static int
1022 pr_read_auxv(prnode_t *pnp, uio_t *uiop)
1024 auxv_t auxv[__KERN_NAUXV_IMPL];
1025 proc_t *p;
1026 user_t *up;
1027 int error;
1029 ASSERT(pnp->pr_type == PR_AUXV);
1031 if ((error = prlock(pnp, ZNO)) != 0)
1032 return (error);
1034 if (uiop->uio_offset >= sizeof (auxv)) {
1035 prunlock(pnp);
1036 return (0);
1039 p = pnp->pr_common->prc_proc;
1040 up = PTOU(p);
1041 bcopy(up->u_auxv, auxv, sizeof (auxv));
1042 prunlock(pnp);
1044 return (pr_uioread(auxv, sizeof (auxv), uiop));
1047 #if defined(__x86)
1049 * XX64
1050 * This is almost certainly broken for the amd64 kernel, because
1051 * we have two kinds of LDT structures to export -- one for compatibility
1052 * mode, and one for long mode, sigh.
1054 * For now lets just have a ldt of size 0 for 64-bit processes.
1056 static int
1057 pr_read_ldt(prnode_t *pnp, uio_t *uiop)
1059 proc_t *p;
1060 struct ssd *ssd;
1061 size_t size;
1062 int error;
1064 ASSERT(pnp->pr_type == PR_LDT);
1066 if ((error = prlock(pnp, ZNO)) != 0)
1067 return (error);
1068 p = pnp->pr_common->prc_proc;
1070 mutex_exit(&p->p_lock);
1071 mutex_enter(&p->p_ldtlock);
1072 size = prnldt(p) * sizeof (struct ssd);
1073 if (uiop->uio_offset >= size) {
1074 mutex_exit(&p->p_ldtlock);
1075 mutex_enter(&p->p_lock);
1076 prunlock(pnp);
1077 return (0);
1080 ssd = kmem_alloc(size, KM_SLEEP);
1081 prgetldt(p, ssd);
1082 mutex_exit(&p->p_ldtlock);
1083 mutex_enter(&p->p_lock);
1084 prunlock(pnp);
1086 error = pr_uioread(ssd, size, uiop);
1087 kmem_free(ssd, size);
1088 return (error);
1090 #endif /* __x86 */
1092 static int
1093 pr_read_usage(prnode_t *pnp, uio_t *uiop)
1095 prhusage_t *pup;
1096 prusage_t *upup;
1097 proc_t *p;
1098 kthread_t *t;
1099 int error;
1101 ASSERT(pnp->pr_type == PR_USAGE);
1103 /* allocate now, before locking the process */
1104 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1105 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1108 * We don't want the full treatment of prlock(pnp) here.
1109 * This file is world-readable and never goes invalid.
1110 * It doesn't matter if we are in the middle of an exec().
1112 p = pr_p_lock(pnp);
1113 mutex_exit(&pr_pidlock);
1114 if (p == NULL) {
1115 error = ENOENT;
1116 goto out;
1118 ASSERT(p == pnp->pr_common->prc_proc);
1120 if (uiop->uio_offset >= sizeof (prusage_t)) {
1121 prunlock(pnp);
1122 error = 0;
1123 goto out;
1126 pup->pr_tstamp = gethrtime();
1128 pup->pr_count = p->p_defunct;
1129 pup->pr_create = p->p_mstart;
1130 pup->pr_term = p->p_mterm;
1132 pup->pr_rtime = p->p_mlreal;
1133 pup->pr_utime = p->p_acct[LMS_USER];
1134 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1135 pup->pr_ttime = p->p_acct[LMS_TRAP];
1136 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1137 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1138 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1139 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1140 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1141 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1142 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1144 pup->pr_minf = p->p_ru.minflt;
1145 pup->pr_majf = p->p_ru.majflt;
1146 pup->pr_nswap = p->p_ru.nswap;
1147 pup->pr_inblk = p->p_ru.inblock;
1148 pup->pr_oublk = p->p_ru.oublock;
1149 pup->pr_msnd = p->p_ru.msgsnd;
1150 pup->pr_mrcv = p->p_ru.msgrcv;
1151 pup->pr_sigs = p->p_ru.nsignals;
1152 pup->pr_vctx = p->p_ru.nvcsw;
1153 pup->pr_ictx = p->p_ru.nivcsw;
1154 pup->pr_sysc = p->p_ru.sysc;
1155 pup->pr_ioch = p->p_ru.ioch;
1158 * Add the usage information for each active lwp.
1160 if ((t = p->p_tlist) != NULL &&
1161 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
1162 do {
1163 if (t->t_proc_flag & TP_LWPEXIT)
1164 continue;
1165 pup->pr_count++;
1166 praddusage(t, pup);
1167 } while ((t = t->t_forw) != p->p_tlist);
1170 prunlock(pnp);
1172 prcvtusage(pup, upup);
1174 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1175 out:
1176 kmem_free(pup, sizeof (*pup));
1177 kmem_free(upup, sizeof (*upup));
1178 return (error);
1181 static int
1182 pr_read_lusage(prnode_t *pnp, uio_t *uiop)
1184 int nlwp;
1185 prhusage_t *pup;
1186 prheader_t *php;
1187 prusage_t *upup;
1188 size_t size;
1189 hrtime_t curtime;
1190 proc_t *p;
1191 kthread_t *t;
1192 lwpdir_t *ldp;
1193 int error;
1194 int i;
1196 ASSERT(pnp->pr_type == PR_LUSAGE);
1199 * We don't want the full treatment of prlock(pnp) here.
1200 * This file is world-readable and never goes invalid.
1201 * It doesn't matter if we are in the middle of an exec().
1203 p = pr_p_lock(pnp);
1204 mutex_exit(&pr_pidlock);
1205 if (p == NULL)
1206 return (ENOENT);
1207 ASSERT(p == pnp->pr_common->prc_proc);
1208 if ((nlwp = p->p_lwpcnt) == 0) {
1209 prunlock(pnp);
1210 return (ENOENT);
1213 size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
1214 if (uiop->uio_offset >= size) {
1215 prunlock(pnp);
1216 return (0);
1219 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1220 mutex_exit(&p->p_lock);
1221 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
1222 mutex_enter(&p->p_lock);
1223 /* p->p_lwpcnt can't change while process is locked */
1224 ASSERT(nlwp == p->p_lwpcnt);
1226 php = (prheader_t *)(pup + 1);
1227 upup = (prusage_t *)(php + 1);
1229 php->pr_nent = nlwp + 1;
1230 php->pr_entsize = LSPAN(prusage_t);
1232 curtime = gethrtime();
1235 * First the summation over defunct lwps.
1237 pup->pr_count = p->p_defunct;
1238 pup->pr_tstamp = curtime;
1239 pup->pr_create = p->p_mstart;
1240 pup->pr_term = p->p_mterm;
1242 pup->pr_rtime = p->p_mlreal;
1243 pup->pr_utime = p->p_acct[LMS_USER];
1244 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1245 pup->pr_ttime = p->p_acct[LMS_TRAP];
1246 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1247 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1248 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1249 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1250 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1251 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1252 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1254 pup->pr_minf = p->p_ru.minflt;
1255 pup->pr_majf = p->p_ru.majflt;
1256 pup->pr_nswap = p->p_ru.nswap;
1257 pup->pr_inblk = p->p_ru.inblock;
1258 pup->pr_oublk = p->p_ru.oublock;
1259 pup->pr_msnd = p->p_ru.msgsnd;
1260 pup->pr_mrcv = p->p_ru.msgrcv;
1261 pup->pr_sigs = p->p_ru.nsignals;
1262 pup->pr_vctx = p->p_ru.nvcsw;
1263 pup->pr_ictx = p->p_ru.nivcsw;
1264 pup->pr_sysc = p->p_ru.sysc;
1265 pup->pr_ioch = p->p_ru.ioch;
1267 prcvtusage(pup, upup);
1270 * Fill one prusage struct for each active lwp.
1272 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1273 if (ldp->ld_entry == NULL ||
1274 (t = ldp->ld_entry->le_thread) == NULL)
1275 continue;
1276 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1277 ASSERT(nlwp > 0);
1278 --nlwp;
1279 upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
1280 prgetusage(t, pup);
1281 prcvtusage(pup, upup);
1283 ASSERT(nlwp == 0);
1285 prunlock(pnp);
1287 error = pr_uioread(php, size, uiop);
1288 kmem_free(pup, size + sizeof (prhusage_t));
1289 return (error);
1292 static int
1293 pr_read_pagedata(prnode_t *pnp, uio_t *uiop)
1295 proc_t *p;
1296 int error;
1298 ASSERT(pnp->pr_type == PR_PAGEDATA);
1300 if ((error = prlock(pnp, ZNO)) != 0)
1301 return (error);
1303 p = pnp->pr_common->prc_proc;
1304 if ((p->p_flag & SSYS) || p->p_as == &kas) {
1305 prunlock(pnp);
1306 return (0);
1309 mutex_exit(&p->p_lock);
1310 error = prpdread(p, pnp->pr_hatid, uiop);
1311 mutex_enter(&p->p_lock);
1313 prunlock(pnp);
1314 return (error);
1317 static int
1318 pr_read_opagedata(prnode_t *pnp, uio_t *uiop)
1320 proc_t *p;
1321 struct as *as;
1322 int error;
1324 ASSERT(pnp->pr_type == PR_OPAGEDATA);
1326 if ((error = prlock(pnp, ZNO)) != 0)
1327 return (error);
1329 p = pnp->pr_common->prc_proc;
1330 as = p->p_as;
1331 if ((p->p_flag & SSYS) || as == &kas) {
1332 prunlock(pnp);
1333 return (0);
1336 mutex_exit(&p->p_lock);
1337 error = oprpdread(as, pnp->pr_hatid, uiop);
1338 mutex_enter(&p->p_lock);
1340 prunlock(pnp);
1341 return (error);
1344 static int
1345 pr_read_watch(prnode_t *pnp, uio_t *uiop)
1347 proc_t *p;
1348 int error;
1349 prwatch_t *Bpwp;
1350 size_t size;
1351 prwatch_t *pwp;
1352 int nwarea;
1353 struct watched_area *pwarea;
1355 ASSERT(pnp->pr_type == PR_WATCH);
1357 if ((error = prlock(pnp, ZNO)) != 0)
1358 return (error);
1360 p = pnp->pr_common->prc_proc;
1361 nwarea = avl_numnodes(&p->p_warea);
1362 size = nwarea * sizeof (prwatch_t);
1363 if (uiop->uio_offset >= size) {
1364 prunlock(pnp);
1365 return (0);
1368 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1369 mutex_exit(&p->p_lock);
1370 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
1371 mutex_enter(&p->p_lock);
1372 /* p->p_nwarea can't change while process is locked */
1373 ASSERT(nwarea == avl_numnodes(&p->p_warea));
1375 /* gather the watched areas */
1376 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
1377 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
1378 pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
1379 pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
1380 pwp->pr_wflags = (int)pwarea->wa_flags;
1383 prunlock(pnp);
1385 error = pr_uioread(Bpwp, size, uiop);
1386 kmem_free(Bpwp, size);
1387 return (error);
1390 static int
1391 pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop)
1393 lwpstatus_t *sp;
1394 int error;
1396 ASSERT(pnp->pr_type == PR_LWPSTATUS);
1399 * We kmem_alloc() the lwpstatus structure because
1400 * it is so big it might blow the kernel stack.
1402 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1404 if ((error = prlock(pnp, ZNO)) != 0)
1405 goto out;
1407 if (uiop->uio_offset >= sizeof (*sp)) {
1408 prunlock(pnp);
1409 goto out;
1412 prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
1413 prunlock(pnp);
1415 error = pr_uioread(sp, sizeof (*sp), uiop);
1416 out:
1417 kmem_free(sp, sizeof (*sp));
1418 return (error);
1421 static int
1422 pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop)
1424 lwpsinfo_t lwpsinfo;
1425 proc_t *p;
1426 kthread_t *t;
1427 lwpent_t *lep;
1429 ASSERT(pnp->pr_type == PR_LWPSINFO);
1432 * We don't want the full treatment of prlock(pnp) here.
1433 * This file is world-readable and never goes invalid.
1434 * It doesn't matter if we are in the middle of an exec().
1436 p = pr_p_lock(pnp);
1437 mutex_exit(&pr_pidlock);
1438 if (p == NULL)
1439 return (ENOENT);
1440 ASSERT(p == pnp->pr_common->prc_proc);
1441 if (pnp->pr_common->prc_tslot == -1) {
1442 prunlock(pnp);
1443 return (ENOENT);
1446 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
1447 prunlock(pnp);
1448 return (0);
1451 if ((t = pnp->pr_common->prc_thread) != NULL)
1452 prgetlwpsinfo(t, &lwpsinfo);
1453 else {
1454 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
1455 bzero(&lwpsinfo, sizeof (lwpsinfo));
1456 lwpsinfo.pr_lwpid = lep->le_lwpid;
1457 lwpsinfo.pr_state = SZOMB;
1458 lwpsinfo.pr_sname = 'Z';
1459 lwpsinfo.pr_start.tv_sec = lep->le_start;
1460 lwpsinfo.pr_bindpro = PBIND_NONE;
1461 lwpsinfo.pr_bindpset = PS_NONE;
1463 prunlock(pnp);
1465 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
1468 static int
1469 pr_read_lwpusage(prnode_t *pnp, uio_t *uiop)
1471 prhusage_t *pup;
1472 prusage_t *upup;
1473 proc_t *p;
1474 int error;
1476 ASSERT(pnp->pr_type == PR_LWPUSAGE);
1478 /* allocate now, before locking the process */
1479 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1480 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1483 * We don't want the full treatment of prlock(pnp) here.
1484 * This file is world-readable and never goes invalid.
1485 * It doesn't matter if we are in the middle of an exec().
1487 p = pr_p_lock(pnp);
1488 mutex_exit(&pr_pidlock);
1489 if (p == NULL) {
1490 error = ENOENT;
1491 goto out;
1493 ASSERT(p == pnp->pr_common->prc_proc);
1494 if (pnp->pr_common->prc_thread == NULL) {
1495 prunlock(pnp);
1496 error = ENOENT;
1497 goto out;
1499 if (uiop->uio_offset >= sizeof (prusage_t)) {
1500 prunlock(pnp);
1501 error = 0;
1502 goto out;
1505 pup->pr_tstamp = gethrtime();
1506 prgetusage(pnp->pr_common->prc_thread, pup);
1508 prunlock(pnp);
1510 prcvtusage(pup, upup);
1512 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1513 out:
1514 kmem_free(pup, sizeof (*pup));
1515 kmem_free(upup, sizeof (*upup));
1516 return (error);
1519 /* ARGSUSED */
1520 static int
1521 pr_read_xregs(prnode_t *pnp, uio_t *uiop)
1523 return (0);
1526 static int
1527 pr_read_spymaster(prnode_t *pnp, uio_t *uiop)
1529 psinfo_t psinfo;
1530 int error;
1531 klwp_t *lwp;
1533 ASSERT(pnp->pr_type == PR_SPYMASTER);
1535 if ((error = prlock(pnp, ZNO)) != 0)
1536 return (error);
1538 lwp = pnp->pr_common->prc_thread->t_lwp;
1540 if (lwp->lwp_spymaster == NULL) {
1541 prunlock(pnp);
1542 return (0);
1545 bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1546 prunlock(pnp);
1548 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1551 static int
1552 pr_read_secflags(prnode_t *pnp, uio_t *uiop)
1554 prsecflags_t ret;
1555 int error;
1556 proc_t *p;
1558 ASSERT(pnp->pr_type == PR_SECFLAGS);
1560 if ((error = prlock(pnp, ZNO)) != 0)
1561 return (error);
1563 p = pnp->pr_common->prc_proc;
1564 prgetsecflags(p, &ret);
1565 prunlock(pnp);
1567 return (pr_uioread(&ret, sizeof (ret), uiop));
1571 static int
1572 pr_read_piddir(prnode_t *pnp, uio_t *uiop)
1574 ASSERT(pnp->pr_type == PR_PIDDIR);
1575 ASSERT(pnp->pr_pidfile != NULL);
1577 /* use the underlying PR_PIDFILE to read the process */
1578 pnp = VTOP(pnp->pr_pidfile);
1579 ASSERT(pnp->pr_type == PR_PIDFILE);
1581 return (pr_read_pidfile(pnp, uiop));
1584 static int
1585 pr_read_pidfile(prnode_t *pnp, uio_t *uiop)
1587 int error;
1589 ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
1591 if ((error = prlock(pnp, ZNO)) == 0) {
1592 proc_t *p = pnp->pr_common->prc_proc;
1593 struct as *as = p->p_as;
1595 if ((p->p_flag & SSYS) || as == &kas) {
1597 * /proc I/O cannot be done to a system process.
1599 error = EIO; /* old /proc semantics */
1600 } else {
1602 * We drop p_lock because we don't want to hold
1603 * it over an I/O operation because that could
1604 * lead to deadlock with the clock thread.
1605 * The process will not disappear and its address
1606 * space will not change because it is marked P_PR_LOCK.
1608 mutex_exit(&p->p_lock);
1609 error = prusrio(p, UIO_READ, uiop, 1);
1610 mutex_enter(&p->p_lock);
1612 prunlock(pnp);
1615 return (error);
1618 #ifdef _SYSCALL32_IMPL
1621 * Array of ILP32 read functions, indexed by /proc file type.
1623 static int pr_read_status_32(),
1624 pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
1625 pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
1626 pr_read_sigact_32(), pr_read_auxv_32(),
1627 pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
1628 pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1629 pr_read_lwpusage_32(), pr_read_spymaster_32(),
1630 #if defined(__sparc)
1631 pr_read_gwindows_32(),
1632 #endif
1633 pr_read_opagedata_32();
1635 static int (*pr_read_function_32[PR_NFILES])() = {
1636 pr_read_inval, /* /proc */
1637 pr_read_inval, /* /proc/self */
1638 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1639 pr_read_as, /* /proc/<pid>/as */
1640 pr_read_inval, /* /proc/<pid>/ctl */
1641 pr_read_status_32, /* /proc/<pid>/status */
1642 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1643 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1644 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1645 pr_read_map_32, /* /proc/<pid>/map */
1646 pr_read_rmap_32, /* /proc/<pid>/rmap */
1647 pr_read_xmap_32, /* /proc/<pid>/xmap */
1648 pr_read_cred, /* /proc/<pid>/cred */
1649 pr_read_sigact_32, /* /proc/<pid>/sigact */
1650 pr_read_auxv_32, /* /proc/<pid>/auxv */
1651 #if defined(__x86)
1652 pr_read_ldt, /* /proc/<pid>/ldt */
1653 #endif
1654 pr_read_usage_32, /* /proc/<pid>/usage */
1655 pr_read_lusage_32, /* /proc/<pid>/lusage */
1656 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1657 pr_read_watch_32, /* /proc/<pid>/watch */
1658 pr_read_inval, /* /proc/<pid>/cwd */
1659 pr_read_inval, /* /proc/<pid>/root */
1660 pr_read_inval, /* /proc/<pid>/fd */
1661 pr_read_inval, /* /proc/<pid>/fd/nn */
1662 pr_read_inval, /* /proc/<pid>/object */
1663 pr_read_inval, /* /proc/<pid>/object/xxx */
1664 pr_read_inval, /* /proc/<pid>/lwp */
1665 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1666 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1667 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1668 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1669 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1670 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1671 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1672 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1673 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
1674 #if defined(__sparc)
1675 pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
1676 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
1677 #endif
1678 pr_read_priv, /* /proc/<pid>/priv */
1679 pr_read_inval, /* /proc/<pid>/path */
1680 pr_read_inval, /* /proc/<pid>/path/xxx */
1681 pr_read_inval, /* /proc/<pid>/contracts */
1682 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
1683 pr_read_secflags, /* /proc/<pid>/secflags */
1684 pr_read_pidfile, /* old process file */
1685 pr_read_pidfile, /* old lwp file */
1686 pr_read_opagedata_32, /* old pagedata file */
1689 static int
1690 pr_read_status_32(prnode_t *pnp, uio_t *uiop)
1692 pstatus32_t *sp;
1693 proc_t *p;
1694 int error;
1696 ASSERT(pnp->pr_type == PR_STATUS);
1699 * We kmem_alloc() the pstatus structure because
1700 * it is so big it might blow the kernel stack.
1702 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1703 if ((error = prlock(pnp, ZNO)) == 0) {
1705 * A 32-bit process cannot get the status of a 64-bit process.
1706 * The fields for the 64-bit quantities are not large enough.
1708 p = pnp->pr_common->prc_proc;
1709 if (PROCESS_NOT_32BIT(p)) {
1710 prunlock(pnp);
1711 error = EOVERFLOW;
1712 } else {
1713 prgetstatus32(pnp->pr_common->prc_proc, sp,
1714 VTOZONE(PTOV(pnp)));
1715 prunlock(pnp);
1716 error = pr_uioread(sp, sizeof (*sp), uiop);
1719 kmem_free((caddr_t)sp, sizeof (*sp));
1720 return (error);
1723 static int
1724 pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop)
1726 proc_t *p;
1727 kthread_t *t;
1728 lwpdir_t *ldp;
1729 size_t size;
1730 prheader32_t *php;
1731 lwpstatus32_t *sp;
1732 int error;
1733 int nlwp;
1734 int i;
1736 ASSERT(pnp->pr_type == PR_LSTATUS);
1738 if ((error = prlock(pnp, ZNO)) != 0)
1739 return (error);
1740 p = pnp->pr_common->prc_proc;
1742 * A 32-bit process cannot get the status of a 64-bit process.
1743 * The fields for the 64-bit quantities are not large enough.
1745 if (PROCESS_NOT_32BIT(p)) {
1746 prunlock(pnp);
1747 return (EOVERFLOW);
1749 nlwp = p->p_lwpcnt;
1750 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
1752 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1753 mutex_exit(&p->p_lock);
1754 php = kmem_zalloc(size, KM_SLEEP);
1755 mutex_enter(&p->p_lock);
1756 /* p->p_lwpcnt can't change while process is locked */
1757 ASSERT(nlwp == p->p_lwpcnt);
1759 php->pr_nent = nlwp;
1760 php->pr_entsize = LSPAN32(lwpstatus32_t);
1762 sp = (lwpstatus32_t *)(php + 1);
1763 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1764 if (ldp->ld_entry == NULL ||
1765 (t = ldp->ld_entry->le_thread) == NULL)
1766 continue;
1767 prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
1768 sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
1770 prunlock(pnp);
1772 error = pr_uioread(php, size, uiop);
1773 kmem_free(php, size);
1774 return (error);
1777 static int
1778 pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop)
1780 psinfo32_t psinfo;
1781 proc_t *p;
1782 int error = 0;
1784 ASSERT(pnp->pr_type == PR_PSINFO);
1787 * We don't want the full treatment of prlock(pnp) here.
1788 * This file is world-readable and never goes invalid.
1789 * It doesn't matter if we are in the middle of an exec().
1791 p = pr_p_lock(pnp);
1792 mutex_exit(&pr_pidlock);
1793 if (p == NULL)
1794 error = ENOENT;
1795 else {
1796 ASSERT(p == pnp->pr_common->prc_proc);
1797 prgetpsinfo32(p, &psinfo);
1798 prunlock(pnp);
1799 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
1801 return (error);
1804 static int
1805 pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop)
1807 proc_t *p;
1808 kthread_t *t;
1809 lwpdir_t *ldp;
1810 lwpent_t *lep;
1811 size_t size;
1812 prheader32_t *php;
1813 lwpsinfo32_t *sp;
1814 int error;
1815 int nlwp;
1816 int i;
1818 ASSERT(pnp->pr_type == PR_LPSINFO);
1821 * We don't want the full treatment of prlock(pnp) here.
1822 * This file is world-readable and never goes invalid.
1823 * It doesn't matter if we are in the middle of an exec().
1825 p = pr_p_lock(pnp);
1826 mutex_exit(&pr_pidlock);
1827 if (p == NULL)
1828 return (ENOENT);
1829 ASSERT(p == pnp->pr_common->prc_proc);
1830 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
1831 prunlock(pnp);
1832 return (ENOENT);
1834 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
1836 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1837 mutex_exit(&p->p_lock);
1838 php = kmem_zalloc(size, KM_SLEEP);
1839 mutex_enter(&p->p_lock);
1840 /* p->p_lwpcnt can't change while process is locked */
1841 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
1843 php->pr_nent = nlwp;
1844 php->pr_entsize = LSPAN32(lwpsinfo32_t);
1846 sp = (lwpsinfo32_t *)(php + 1);
1847 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1848 if ((lep = ldp->ld_entry) == NULL)
1849 continue;
1850 if ((t = lep->le_thread) != NULL)
1851 prgetlwpsinfo32(t, sp);
1852 else {
1853 bzero(sp, sizeof (*sp));
1854 sp->pr_lwpid = lep->le_lwpid;
1855 sp->pr_state = SZOMB;
1856 sp->pr_sname = 'Z';
1857 sp->pr_start.tv_sec = (time32_t)lep->le_start;
1859 sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
1861 prunlock(pnp);
1863 error = pr_uioread(php, size, uiop);
1864 kmem_free(php, size);
1865 return (error);
1868 static int
1869 pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
1871 proc_t *p;
1872 struct as *as;
1873 list_t iolhead;
1874 int error;
1876 readmap32_common:
1877 if ((error = prlock(pnp, ZNO)) != 0)
1878 return (error);
1880 p = pnp->pr_common->prc_proc;
1881 as = p->p_as;
1883 if ((p->p_flag & SSYS) || as == &kas) {
1884 prunlock(pnp);
1885 return (0);
1888 if (PROCESS_NOT_32BIT(p)) {
1889 prunlock(pnp);
1890 return (EOVERFLOW);
1893 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
1894 prunlock(pnp);
1895 delay(1);
1896 goto readmap32_common;
1898 mutex_exit(&p->p_lock);
1900 switch (type) {
1901 case PR_XMAP:
1902 error = prgetxmap32(p, &iolhead);
1903 break;
1904 case PR_RMAP:
1905 error = prgetmap32(p, 1, &iolhead);
1906 break;
1907 case PR_MAP:
1908 error = prgetmap32(p, 0, &iolhead);
1909 break;
1911 AS_LOCK_EXIT(as);
1912 mutex_enter(&p->p_lock);
1913 prunlock(pnp);
1915 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
1917 return (error);
1920 static int
1921 pr_read_map_32(prnode_t *pnp, uio_t *uiop)
1923 ASSERT(pnp->pr_type == PR_MAP);
1924 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
1927 static int
1928 pr_read_rmap_32(prnode_t *pnp, uio_t *uiop)
1930 ASSERT(pnp->pr_type == PR_RMAP);
1931 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
1934 static int
1935 pr_read_xmap_32(prnode_t *pnp, uio_t *uiop)
1937 ASSERT(pnp->pr_type == PR_XMAP);
1938 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
1941 static int
1942 pr_read_sigact_32(prnode_t *pnp, uio_t *uiop)
1944 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1945 proc_t *p;
1946 struct sigaction32 *sap;
1947 int sig;
1948 int error;
1949 user_t *up;
1951 ASSERT(pnp->pr_type == PR_SIGACT);
1954 * We kmem_alloc() the sigaction32 array because
1955 * it is so big it might blow the kernel stack.
1957 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
1959 if ((error = prlock(pnp, ZNO)) != 0)
1960 goto out;
1961 p = pnp->pr_common->prc_proc;
1963 if (PROCESS_NOT_32BIT(p)) {
1964 prunlock(pnp);
1965 error = EOVERFLOW;
1966 goto out;
1969 if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
1970 prunlock(pnp);
1971 goto out;
1974 up = PTOU(p);
1975 for (sig = 1; sig < nsig; sig++)
1976 prgetaction32(p, up, sig, &sap[sig-1]);
1977 prunlock(pnp);
1979 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
1980 out:
1981 kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
1982 return (error);
1985 static int
1986 pr_read_auxv_32(prnode_t *pnp, uio_t *uiop)
1988 auxv32_t auxv[__KERN_NAUXV_IMPL];
1989 proc_t *p;
1990 user_t *up;
1991 int error;
1992 int i;
1994 ASSERT(pnp->pr_type == PR_AUXV);
1996 if ((error = prlock(pnp, ZNO)) != 0)
1997 return (error);
1998 p = pnp->pr_common->prc_proc;
2000 if (PROCESS_NOT_32BIT(p)) {
2001 prunlock(pnp);
2002 return (EOVERFLOW);
2005 if (uiop->uio_offset >= sizeof (auxv)) {
2006 prunlock(pnp);
2007 return (0);
2010 up = PTOU(p);
2011 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2012 auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
2013 auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
2015 prunlock(pnp);
2017 return (pr_uioread(auxv, sizeof (auxv), uiop));
2020 static int
2021 pr_read_usage_32(prnode_t *pnp, uio_t *uiop)
2023 prhusage_t *pup;
2024 prusage32_t *upup;
2025 proc_t *p;
2026 kthread_t *t;
2027 int error;
2029 ASSERT(pnp->pr_type == PR_USAGE);
2031 /* allocate now, before locking the process */
2032 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2033 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2036 * We don't want the full treatment of prlock(pnp) here.
2037 * This file is world-readable and never goes invalid.
2038 * It doesn't matter if we are in the middle of an exec().
2040 p = pr_p_lock(pnp);
2041 mutex_exit(&pr_pidlock);
2042 if (p == NULL) {
2043 error = ENOENT;
2044 goto out;
2046 ASSERT(p == pnp->pr_common->prc_proc);
2048 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2049 prunlock(pnp);
2050 error = 0;
2051 goto out;
2054 pup->pr_tstamp = gethrtime();
2056 pup->pr_count = p->p_defunct;
2057 pup->pr_create = p->p_mstart;
2058 pup->pr_term = p->p_mterm;
2060 pup->pr_rtime = p->p_mlreal;
2061 pup->pr_utime = p->p_acct[LMS_USER];
2062 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2063 pup->pr_ttime = p->p_acct[LMS_TRAP];
2064 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2065 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2066 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2067 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2068 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2069 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2070 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2072 pup->pr_minf = p->p_ru.minflt;
2073 pup->pr_majf = p->p_ru.majflt;
2074 pup->pr_nswap = p->p_ru.nswap;
2075 pup->pr_inblk = p->p_ru.inblock;
2076 pup->pr_oublk = p->p_ru.oublock;
2077 pup->pr_msnd = p->p_ru.msgsnd;
2078 pup->pr_mrcv = p->p_ru.msgrcv;
2079 pup->pr_sigs = p->p_ru.nsignals;
2080 pup->pr_vctx = p->p_ru.nvcsw;
2081 pup->pr_ictx = p->p_ru.nivcsw;
2082 pup->pr_sysc = p->p_ru.sysc;
2083 pup->pr_ioch = p->p_ru.ioch;
2086 * Add the usage information for each active lwp.
2088 if ((t = p->p_tlist) != NULL &&
2089 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
2090 do {
2091 if (t->t_proc_flag & TP_LWPEXIT)
2092 continue;
2093 pup->pr_count++;
2094 praddusage(t, pup);
2095 } while ((t = t->t_forw) != p->p_tlist);
2098 prunlock(pnp);
2100 prcvtusage32(pup, upup);
2102 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2103 out:
2104 kmem_free(pup, sizeof (*pup));
2105 kmem_free(upup, sizeof (*upup));
2106 return (error);
2109 static int
2110 pr_read_lusage_32(prnode_t *pnp, uio_t *uiop)
2112 int nlwp;
2113 prhusage_t *pup;
2114 prheader32_t *php;
2115 prusage32_t *upup;
2116 size_t size;
2117 hrtime_t curtime;
2118 proc_t *p;
2119 kthread_t *t;
2120 lwpdir_t *ldp;
2121 int error;
2122 int i;
2124 ASSERT(pnp->pr_type == PR_LUSAGE);
2127 * We don't want the full treatment of prlock(pnp) here.
2128 * This file is world-readable and never goes invalid.
2129 * It doesn't matter if we are in the middle of an exec().
2131 p = pr_p_lock(pnp);
2132 mutex_exit(&pr_pidlock);
2133 if (p == NULL)
2134 return (ENOENT);
2135 ASSERT(p == pnp->pr_common->prc_proc);
2136 if ((nlwp = p->p_lwpcnt) == 0) {
2137 prunlock(pnp);
2138 return (ENOENT);
2141 size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
2142 if (uiop->uio_offset >= size) {
2143 prunlock(pnp);
2144 return (0);
2147 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2148 mutex_exit(&p->p_lock);
2149 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
2150 mutex_enter(&p->p_lock);
2151 /* p->p_lwpcnt can't change while process is locked */
2152 ASSERT(nlwp == p->p_lwpcnt);
2154 php = (prheader32_t *)(pup + 1);
2155 upup = (prusage32_t *)(php + 1);
2157 php->pr_nent = nlwp + 1;
2158 php->pr_entsize = LSPAN32(prusage32_t);
2160 curtime = gethrtime();
2163 * First the summation over defunct lwps.
2165 pup->pr_count = p->p_defunct;
2166 pup->pr_tstamp = curtime;
2167 pup->pr_create = p->p_mstart;
2168 pup->pr_term = p->p_mterm;
2170 pup->pr_rtime = p->p_mlreal;
2171 pup->pr_utime = p->p_acct[LMS_USER];
2172 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2173 pup->pr_ttime = p->p_acct[LMS_TRAP];
2174 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2175 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2176 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2177 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2178 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2179 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2180 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2182 pup->pr_minf = p->p_ru.minflt;
2183 pup->pr_majf = p->p_ru.majflt;
2184 pup->pr_nswap = p->p_ru.nswap;
2185 pup->pr_inblk = p->p_ru.inblock;
2186 pup->pr_oublk = p->p_ru.oublock;
2187 pup->pr_msnd = p->p_ru.msgsnd;
2188 pup->pr_mrcv = p->p_ru.msgrcv;
2189 pup->pr_sigs = p->p_ru.nsignals;
2190 pup->pr_vctx = p->p_ru.nvcsw;
2191 pup->pr_ictx = p->p_ru.nivcsw;
2192 pup->pr_sysc = p->p_ru.sysc;
2193 pup->pr_ioch = p->p_ru.ioch;
2195 prcvtusage32(pup, upup);
2198 * Fill one prusage struct for each active lwp.
2200 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2201 if (ldp->ld_entry == NULL ||
2202 (t = ldp->ld_entry->le_thread) == NULL)
2203 continue;
2204 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2205 ASSERT(nlwp > 0);
2206 --nlwp;
2207 upup = (prusage32_t *)
2208 ((caddr_t)upup + LSPAN32(prusage32_t));
2209 prgetusage(t, pup);
2210 prcvtusage32(pup, upup);
2212 ASSERT(nlwp == 0);
2214 prunlock(pnp);
2216 error = pr_uioread(php, size, uiop);
2217 kmem_free(pup, size + sizeof (prhusage_t));
2218 return (error);
2221 static int
2222 pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop)
2224 proc_t *p;
2225 int error;
2227 ASSERT(pnp->pr_type == PR_PAGEDATA);
2229 if ((error = prlock(pnp, ZNO)) != 0)
2230 return (error);
2232 p = pnp->pr_common->prc_proc;
2233 if ((p->p_flag & SSYS) || p->p_as == &kas) {
2234 prunlock(pnp);
2235 return (0);
2238 if (PROCESS_NOT_32BIT(p)) {
2239 prunlock(pnp);
2240 return (EOVERFLOW);
2243 mutex_exit(&p->p_lock);
2244 error = prpdread32(p, pnp->pr_hatid, uiop);
2245 mutex_enter(&p->p_lock);
2247 prunlock(pnp);
2248 return (error);
2251 static int
2252 pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop)
2254 proc_t *p;
2255 struct as *as;
2256 int error;
2258 ASSERT(pnp->pr_type == PR_OPAGEDATA);
2260 if ((error = prlock(pnp, ZNO)) != 0)
2261 return (error);
2263 p = pnp->pr_common->prc_proc;
2264 as = p->p_as;
2266 if ((p->p_flag & SSYS) || as == &kas) {
2267 prunlock(pnp);
2268 return (0);
2271 if (PROCESS_NOT_32BIT(p)) {
2272 prunlock(pnp);
2273 return (EOVERFLOW);
2276 mutex_exit(&p->p_lock);
2277 error = oprpdread32(as, pnp->pr_hatid, uiop);
2278 mutex_enter(&p->p_lock);
2280 prunlock(pnp);
2281 return (error);
2284 static int
2285 pr_read_watch_32(prnode_t *pnp, uio_t *uiop)
2287 proc_t *p;
2288 int error;
2289 prwatch32_t *Bpwp;
2290 size_t size;
2291 prwatch32_t *pwp;
2292 int nwarea;
2293 struct watched_area *pwarea;
2295 ASSERT(pnp->pr_type == PR_WATCH);
2297 if ((error = prlock(pnp, ZNO)) != 0)
2298 return (error);
2300 p = pnp->pr_common->prc_proc;
2301 if (PROCESS_NOT_32BIT(p)) {
2302 prunlock(pnp);
2303 return (EOVERFLOW);
2305 nwarea = avl_numnodes(&p->p_warea);
2306 size = nwarea * sizeof (prwatch32_t);
2307 if (uiop->uio_offset >= size) {
2308 prunlock(pnp);
2309 return (0);
2312 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2313 mutex_exit(&p->p_lock);
2314 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
2315 mutex_enter(&p->p_lock);
2316 /* p->p_nwarea can't change while process is locked */
2317 ASSERT(nwarea == avl_numnodes(&p->p_warea));
2319 /* gather the watched areas */
2320 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
2321 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
2322 pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
2323 pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
2324 pwp->pr_wflags = (int)pwarea->wa_flags;
2327 prunlock(pnp);
2329 error = pr_uioread(Bpwp, size, uiop);
2330 kmem_free(Bpwp, size);
2331 return (error);
2334 static int
2335 pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop)
2337 lwpstatus32_t *sp;
2338 proc_t *p;
2339 int error;
2341 ASSERT(pnp->pr_type == PR_LWPSTATUS);
2344 * We kmem_alloc() the lwpstatus structure because
2345 * it is so big it might blow the kernel stack.
2347 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
2349 if ((error = prlock(pnp, ZNO)) != 0)
2350 goto out;
2353 * A 32-bit process cannot get the status of a 64-bit process.
2354 * The fields for the 64-bit quantities are not large enough.
2356 p = pnp->pr_common->prc_proc;
2357 if (PROCESS_NOT_32BIT(p)) {
2358 prunlock(pnp);
2359 error = EOVERFLOW;
2360 goto out;
2363 if (uiop->uio_offset >= sizeof (*sp)) {
2364 prunlock(pnp);
2365 goto out;
2368 prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
2369 prunlock(pnp);
2371 error = pr_uioread(sp, sizeof (*sp), uiop);
2372 out:
2373 kmem_free(sp, sizeof (*sp));
2374 return (error);
2377 static int
2378 pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop)
2380 lwpsinfo32_t lwpsinfo;
2381 proc_t *p;
2382 kthread_t *t;
2383 lwpent_t *lep;
2385 ASSERT(pnp->pr_type == PR_LWPSINFO);
2388 * We don't want the full treatment of prlock(pnp) here.
2389 * This file is world-readable and never goes invalid.
2390 * It doesn't matter if we are in the middle of an exec().
2392 p = pr_p_lock(pnp);
2393 mutex_exit(&pr_pidlock);
2394 if (p == NULL)
2395 return (ENOENT);
2396 ASSERT(p == pnp->pr_common->prc_proc);
2397 if (pnp->pr_common->prc_tslot == -1) {
2398 prunlock(pnp);
2399 return (ENOENT);
2402 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
2403 prunlock(pnp);
2404 return (0);
2407 if ((t = pnp->pr_common->prc_thread) != NULL)
2408 prgetlwpsinfo32(t, &lwpsinfo);
2409 else {
2410 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
2411 bzero(&lwpsinfo, sizeof (lwpsinfo));
2412 lwpsinfo.pr_lwpid = lep->le_lwpid;
2413 lwpsinfo.pr_state = SZOMB;
2414 lwpsinfo.pr_sname = 'Z';
2415 lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
2417 prunlock(pnp);
2419 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
2422 static int
2423 pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop)
2425 prhusage_t *pup;
2426 prusage32_t *upup;
2427 proc_t *p;
2428 int error;
2430 ASSERT(pnp->pr_type == PR_LWPUSAGE);
2432 /* allocate now, before locking the process */
2433 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2434 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2437 * We don't want the full treatment of prlock(pnp) here.
2438 * This file is world-readable and never goes invalid.
2439 * It doesn't matter if we are in the middle of an exec().
2441 p = pr_p_lock(pnp);
2442 mutex_exit(&pr_pidlock);
2443 if (p == NULL) {
2444 error = ENOENT;
2445 goto out;
2447 ASSERT(p == pnp->pr_common->prc_proc);
2448 if (pnp->pr_common->prc_thread == NULL) {
2449 prunlock(pnp);
2450 error = ENOENT;
2451 goto out;
2453 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2454 prunlock(pnp);
2455 error = 0;
2456 goto out;
2459 pup->pr_tstamp = gethrtime();
2460 prgetusage(pnp->pr_common->prc_thread, pup);
2462 prunlock(pnp);
2464 prcvtusage32(pup, upup);
2466 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2467 out:
2468 kmem_free(pup, sizeof (*pup));
2469 kmem_free(upup, sizeof (*upup));
2470 return (error);
2473 static int
2474 pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop)
2476 psinfo32_t psinfo;
2477 int error;
2478 klwp_t *lwp;
2480 ASSERT(pnp->pr_type == PR_SPYMASTER);
2482 if ((error = prlock(pnp, ZNO)) != 0)
2483 return (error);
2485 lwp = pnp->pr_common->prc_thread->t_lwp;
2487 if (lwp->lwp_spymaster == NULL) {
2488 prunlock(pnp);
2489 return (0);
2492 psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2493 prunlock(pnp);
2495 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2498 #if defined(__sparc)
2499 static int
2500 pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop)
2502 proc_t *p;
2503 kthread_t *t;
2504 gwindows32_t *gwp;
2505 int error;
2506 size_t size;
2508 ASSERT(pnp->pr_type == PR_GWINDOWS);
2510 gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
2512 if ((error = prlock(pnp, ZNO)) != 0)
2513 goto out;
2515 p = pnp->pr_common->prc_proc;
2516 t = pnp->pr_common->prc_thread;
2518 if (PROCESS_NOT_32BIT(p)) {
2519 prunlock(pnp);
2520 error = EOVERFLOW;
2521 goto out;
2525 * Drop p->p_lock while touching the stack.
2526 * The P_PR_LOCK flag prevents the lwp from
2527 * disappearing while we do this.
2529 mutex_exit(&p->p_lock);
2530 if ((size = prnwindows(ttolwp(t))) != 0)
2531 size = sizeof (gwindows32_t) -
2532 (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
2533 if (uiop->uio_offset >= size) {
2534 mutex_enter(&p->p_lock);
2535 prunlock(pnp);
2536 goto out;
2538 prgetwindows32(ttolwp(t), gwp);
2539 mutex_enter(&p->p_lock);
2540 prunlock(pnp);
2542 error = pr_uioread(gwp, size, uiop);
2543 out:
2544 kmem_free(gwp, sizeof (gwindows32_t));
2545 return (error);
2547 #endif /* __sparc */
2549 #endif /* _SYSCALL32_IMPL */
2551 /* ARGSUSED */
2552 static int
2553 prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2555 prnode_t *pnp = VTOP(vp);
2557 ASSERT(pnp->pr_type < PR_NFILES);
2559 #ifdef _SYSCALL32_IMPL
2561 * What is read from the /proc files depends on the data
2562 * model of the caller. An LP64 process will see LP64
2563 * data. An ILP32 process will see ILP32 data.
2565 if (curproc->p_model == DATAMODEL_LP64)
2566 return (pr_read_function[pnp->pr_type](pnp, uiop));
2567 else
2568 return (pr_read_function_32[pnp->pr_type](pnp, uiop));
2569 #else
2570 return (pr_read_function[pnp->pr_type](pnp, uiop));
2571 #endif
2574 /* ARGSUSED */
2575 static int
2576 prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2578 prnode_t *pnp = VTOP(vp);
2579 int old = 0;
2580 int error;
2581 ssize_t resid;
2583 ASSERT(pnp->pr_type < PR_NFILES);
2586 * Only a handful of /proc files are writable, enumerate them here.
2588 switch (pnp->pr_type) {
2589 case PR_PIDDIR: /* directory write()s: visceral revulsion. */
2590 ASSERT(pnp->pr_pidfile != NULL);
2591 /* use the underlying PR_PIDFILE to write the process */
2592 vp = pnp->pr_pidfile;
2593 pnp = VTOP(vp);
2594 ASSERT(pnp->pr_type == PR_PIDFILE);
2595 /* FALLTHROUGH */
2596 case PR_PIDFILE:
2597 case PR_LWPIDFILE:
2598 old = 1;
2599 /* FALLTHROUGH */
2600 case PR_AS:
2601 if ((error = prlock(pnp, ZNO)) == 0) {
2602 proc_t *p = pnp->pr_common->prc_proc;
2603 struct as *as = p->p_as;
2605 if ((p->p_flag & SSYS) || as == &kas) {
2607 * /proc I/O cannot be done to a system process.
2609 error = EIO;
2610 #ifdef _SYSCALL32_IMPL
2611 } else if (curproc->p_model == DATAMODEL_ILP32 &&
2612 PROCESS_NOT_32BIT(p)) {
2613 error = EOVERFLOW;
2614 #endif
2615 } else {
2617 * See comments above (pr_read_pidfile)
2618 * about this locking dance.
2620 mutex_exit(&p->p_lock);
2621 error = prusrio(p, UIO_WRITE, uiop, old);
2622 mutex_enter(&p->p_lock);
2624 prunlock(pnp);
2626 return (error);
2628 case PR_CTL:
2629 case PR_LWPCTL:
2630 resid = uiop->uio_resid;
2632 * Perform the action on the control file
2633 * by passing curthreads credentials
2634 * and not target process's credentials.
2636 #ifdef _SYSCALL32_IMPL
2637 if (curproc->p_model == DATAMODEL_ILP32)
2638 error = prwritectl32(vp, uiop, CRED());
2639 else
2640 error = prwritectl(vp, uiop, CRED());
2641 #else
2642 error = prwritectl(vp, uiop, CRED());
2643 #endif
2645 * This hack makes sure that the EINTR is passed
2646 * all the way back to the caller's write() call.
2648 if (error == EINTR)
2649 uiop->uio_resid = resid;
2650 return (error);
2652 default:
2653 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2655 /* NOTREACHED */
2658 static int
2659 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2660 caller_context_t *ct)
2662 prnode_t *pnp = VTOP(vp);
2663 prnodetype_t type = pnp->pr_type;
2664 prcommon_t *pcp;
2665 proc_t *p;
2666 struct as *as;
2667 int error;
2668 vnode_t *rvp;
2669 timestruc_t now;
2670 extern uint_t nproc;
2671 int ngroups;
2672 int nsig;
2675 * This ugly bit of code allows us to keep both versions of this
2676 * function from the same source.
2678 #ifdef _LP64
2679 int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
2680 #define PR_OBJSIZE(obj32, obj64) \
2681 (iam32bit ? sizeof (obj32) : sizeof (obj64))
2682 #define PR_OBJSPAN(obj32, obj64) \
2683 (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
2684 #else
2685 #define PR_OBJSIZE(obj32, obj64) \
2686 (sizeof (obj64))
2687 #define PR_OBJSPAN(obj32, obj64) \
2688 (LSPAN(obj64))
2689 #endif
2692 * Return all the attributes. Should be refined
2693 * so that it returns only those asked for.
2694 * Most of this is complete fakery anyway.
2698 * For files in the /proc/<pid>/object directory,
2699 * return the attributes of the underlying object.
2700 * For files in the /proc/<pid>/fd directory,
2701 * return the attributes of the underlying file, but
2702 * make it look inaccessible if it is not a regular file.
2703 * Make directories look like symlinks.
2705 switch (type) {
2706 case PR_CURDIR:
2707 case PR_ROOTDIR:
2708 if (!(flags & ATTR_REAL))
2709 break;
2710 /* restrict full knowledge of the attributes to owner or root */
2711 if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
2712 return (error);
2713 /* FALLTHROUGH */
2714 case PR_OBJECT:
2715 case PR_FD:
2716 rvp = pnp->pr_realvp;
2717 error = fop_getattr(rvp, vap, flags, cr, ct);
2718 if (error)
2719 return (error);
2720 if (type == PR_FD) {
2721 if (rvp->v_type != VREG && rvp->v_type != VDIR)
2722 vap->va_mode = 0;
2723 else
2724 vap->va_mode &= pnp->pr_mode;
2726 if (type == PR_OBJECT)
2727 vap->va_mode &= 07555;
2728 if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
2729 vap->va_type = VLNK;
2730 vap->va_size = 0;
2731 vap->va_nlink = 1;
2733 return (0);
2734 default:
2735 break;
2738 bzero(vap, sizeof (*vap));
2740 * Large Files: Internally proc now uses VPROC to indicate
2741 * a proc file. Since we have been returning VREG through
2742 * fop_getattr() until now, we continue to do this so as
2743 * not to break apps depending on this return value.
2745 vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
2746 vap->va_mode = pnp->pr_mode;
2747 vap->va_fsid = vp->v_vfsp->vfs_dev;
2748 vap->va_blksize = DEV_BSIZE;
2749 vap->va_rdev = 0;
2750 vap->va_seq = 0;
2752 if (type == PR_PROCDIR) {
2753 vap->va_uid = 0;
2754 vap->va_gid = 0;
2755 vap->va_nlink = nproc + 2;
2756 vap->va_nodeid = (ino64_t)PRROOTINO;
2757 gethrestime(&now);
2758 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
2759 vap->va_size = (v.v_proc + 2) * PRSDSIZE;
2760 vap->va_nblocks = btod(vap->va_size);
2761 return (0);
2765 * /proc/<pid>/self is a symbolic link, and has no prcommon member
2767 if (type == PR_SELF) {
2768 vap->va_uid = crgetruid(CRED());
2769 vap->va_gid = crgetrgid(CRED());
2770 vap->va_nodeid = (ino64_t)PR_SELF;
2771 gethrestime(&now);
2772 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
2773 vap->va_nlink = 1;
2774 vap->va_type = VLNK;
2775 vap->va_size = 0;
2776 return (0);
2779 p = pr_p_lock(pnp);
2780 mutex_exit(&pr_pidlock);
2781 if (p == NULL)
2782 return (ENOENT);
2783 pcp = pnp->pr_common;
2785 mutex_enter(&p->p_crlock);
2786 vap->va_uid = crgetruid(p->p_cred);
2787 vap->va_gid = crgetrgid(p->p_cred);
2788 mutex_exit(&p->p_crlock);
2790 vap->va_nlink = 1;
2791 vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
2792 pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
2793 if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
2794 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
2795 vap->va_ctime.tv_sec =
2796 p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
2797 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
2798 vap->va_ctime.tv_nsec = 0;
2799 } else {
2800 user_t *up = PTOU(p);
2801 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
2802 vap->va_ctime.tv_sec = up->u_start.tv_sec;
2803 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
2804 vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
2807 switch (type) {
2808 case PR_PIDDIR:
2809 /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
2810 vap->va_nlink = 5;
2811 vap->va_size = sizeof (piddir);
2812 break;
2813 case PR_OBJECTDIR:
2814 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2815 vap->va_size = 2 * PRSDSIZE;
2816 else {
2817 mutex_exit(&p->p_lock);
2818 AS_LOCK_ENTER(as, RW_WRITER);
2819 if (as->a_updatedir)
2820 rebuild_objdir(as);
2821 vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
2822 AS_LOCK_EXIT(as);
2823 mutex_enter(&p->p_lock);
2825 vap->va_nlink = 2;
2826 break;
2827 case PR_PATHDIR:
2828 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2829 vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
2830 else {
2831 mutex_exit(&p->p_lock);
2832 AS_LOCK_ENTER(as, RW_WRITER);
2833 if (as->a_updatedir)
2834 rebuild_objdir(as);
2835 vap->va_size = (as->a_sizedir + 4 +
2836 P_FINFO(p)->fi_nfiles) * PRSDSIZE;
2837 AS_LOCK_EXIT(as);
2838 mutex_enter(&p->p_lock);
2840 vap->va_nlink = 2;
2841 break;
2842 case PR_PATH:
2843 case PR_CURDIR:
2844 case PR_ROOTDIR:
2845 case PR_CT:
2846 vap->va_type = VLNK;
2847 vap->va_size = 0;
2848 break;
2849 case PR_FDDIR:
2850 vap->va_nlink = 2;
2851 vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
2852 break;
2853 case PR_LWPDIR:
2855 * va_nlink: count each lwp as a directory link.
2856 * va_size: size of p_lwpdir + 2
2858 vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
2859 vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
2860 break;
2861 case PR_LWPIDDIR:
2862 vap->va_nlink = 2;
2863 vap->va_size = sizeof (lwpiddir);
2864 break;
2865 case PR_CTDIR:
2866 vap->va_nlink = 2;
2867 vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
2868 break;
2869 case PR_TMPLDIR:
2870 vap->va_nlink = 2;
2871 vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
2872 break;
2873 case PR_AS:
2874 case PR_PIDFILE:
2875 case PR_LWPIDFILE:
2876 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2877 vap->va_size = 0;
2878 else
2879 vap->va_size = as->a_resvsize;
2880 break;
2881 case PR_STATUS:
2882 vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
2883 break;
2884 case PR_LSTATUS:
2885 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
2886 p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
2887 break;
2888 case PR_PSINFO:
2889 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
2890 break;
2891 case PR_LPSINFO:
2892 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
2893 (p->p_lwpcnt + p->p_zombcnt) *
2894 PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
2895 break;
2896 case PR_MAP:
2897 case PR_RMAP:
2898 case PR_XMAP:
2899 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2900 vap->va_size = 0;
2901 else {
2902 mutex_exit(&p->p_lock);
2903 AS_LOCK_ENTER(as, RW_WRITER);
2904 if (type == PR_MAP)
2905 vap->va_mtime = as->a_updatetime;
2906 if (type == PR_XMAP)
2907 vap->va_size = prnsegs(as, 0) *
2908 PR_OBJSIZE(prxmap32_t, prxmap_t);
2909 else
2910 vap->va_size = prnsegs(as, type == PR_RMAP) *
2911 PR_OBJSIZE(prmap32_t, prmap_t);
2912 AS_LOCK_EXIT(as);
2913 mutex_enter(&p->p_lock);
2915 break;
2916 case PR_CRED:
2917 mutex_enter(&p->p_crlock);
2918 vap->va_size = sizeof (prcred_t);
2919 ngroups = crgetngroups(p->p_cred);
2920 if (ngroups > 1)
2921 vap->va_size += (ngroups - 1) * sizeof (gid_t);
2922 mutex_exit(&p->p_crlock);
2923 break;
2924 case PR_PRIV:
2925 vap->va_size = prgetprivsize();
2926 break;
2927 case PR_SECFLAGS:
2928 vap->va_size = sizeof (prsecflags_t);
2929 break;
2930 case PR_SIGACT:
2931 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
2932 vap->va_size = (nsig-1) *
2933 PR_OBJSIZE(struct sigaction32, struct sigaction);
2934 break;
2935 case PR_AUXV:
2936 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
2937 break;
2938 #if defined(__x86)
2939 case PR_LDT:
2940 mutex_exit(&p->p_lock);
2941 mutex_enter(&p->p_ldtlock);
2942 vap->va_size = prnldt(p) * sizeof (struct ssd);
2943 mutex_exit(&p->p_ldtlock);
2944 mutex_enter(&p->p_lock);
2945 break;
2946 #endif
2947 case PR_USAGE:
2948 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
2949 break;
2950 case PR_LUSAGE:
2951 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
2952 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
2953 break;
2954 case PR_PAGEDATA:
2955 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2956 vap->va_size = 0;
2957 else {
2959 * We can drop p->p_lock before grabbing the
2960 * address space lock because p->p_as will not
2961 * change while the process is marked P_PR_LOCK.
2963 mutex_exit(&p->p_lock);
2964 AS_LOCK_ENTER(as, RW_WRITER);
2965 #ifdef _LP64
2966 vap->va_size = iam32bit?
2967 prpdsize32(as) : prpdsize(as);
2968 #else
2969 vap->va_size = prpdsize(as);
2970 #endif
2971 AS_LOCK_EXIT(as);
2972 mutex_enter(&p->p_lock);
2974 break;
2975 case PR_OPAGEDATA:
2976 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
2977 vap->va_size = 0;
2978 else {
2979 mutex_exit(&p->p_lock);
2980 AS_LOCK_ENTER(as, RW_WRITER);
2981 #ifdef _LP64
2982 vap->va_size = iam32bit?
2983 oprpdsize32(as) : oprpdsize(as);
2984 #else
2985 vap->va_size = oprpdsize(as);
2986 #endif
2987 AS_LOCK_EXIT(as);
2988 mutex_enter(&p->p_lock);
2990 break;
2991 case PR_WATCH:
2992 vap->va_size = avl_numnodes(&p->p_warea) *
2993 PR_OBJSIZE(prwatch32_t, prwatch_t);
2994 break;
2995 case PR_LWPSTATUS:
2996 vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
2997 break;
2998 case PR_LWPSINFO:
2999 vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
3000 break;
3001 case PR_LWPUSAGE:
3002 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3003 break;
3004 case PR_XREGS:
3005 if (prhasx(p))
3006 vap->va_size = prgetprxregsize(p);
3007 else
3008 vap->va_size = 0;
3009 break;
3010 case PR_SPYMASTER:
3011 if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3012 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3013 } else {
3014 vap->va_size = 0;
3016 break;
3017 case PR_CTL:
3018 case PR_LWPCTL:
3019 default:
3020 vap->va_size = 0;
3021 break;
3024 prunlock(pnp);
3025 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3026 return (0);
3029 static int
3030 praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3032 prnode_t *pnp = VTOP(vp);
3033 prnodetype_t type = pnp->pr_type;
3034 int vmode;
3035 vtype_t vtype;
3036 proc_t *p;
3037 int error = 0;
3038 vnode_t *rvp;
3039 vnode_t *xvp;
3041 if ((mode & VWRITE) && vn_is_readonly(vp))
3042 return (EROFS);
3044 switch (type) {
3045 case PR_PROCDIR:
3046 break;
3048 case PR_OBJECT:
3049 case PR_FD:
3051 * Disallow write access to the underlying objects.
3052 * Disallow access to underlying non-regular-file fds.
3053 * Disallow access to fds with other than existing open modes.
3055 rvp = pnp->pr_realvp;
3056 vtype = rvp->v_type;
3057 vmode = pnp->pr_mode;
3058 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3059 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3060 (type == PR_FD && (vmode & mode) != mode &&
3061 secpolicy_proc_access(cr) != 0))
3062 return (EACCES);
3063 return (fop_access(rvp, mode, flags, cr, ct));
3065 case PR_PSINFO: /* these files can be read by anyone */
3066 case PR_LPSINFO:
3067 case PR_LWPSINFO:
3068 case PR_LWPDIR:
3069 case PR_LWPIDDIR:
3070 case PR_USAGE:
3071 case PR_LUSAGE:
3072 case PR_LWPUSAGE:
3073 p = pr_p_lock(pnp);
3074 mutex_exit(&pr_pidlock);
3075 if (p == NULL)
3076 return (ENOENT);
3077 prunlock(pnp);
3078 break;
3080 default:
3082 * Except for the world-readable files above,
3083 * only /proc/pid exists if the process is a zombie.
3085 if ((error = prlock(pnp,
3086 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3087 return (error);
3088 p = pnp->pr_common->prc_proc;
3089 if (p != curproc)
3090 error = priv_proc_cred_perm(cr, p, NULL, mode);
3092 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3093 p->p_as == &kas || (xvp = p->p_exec) == NULL) {
3094 prunlock(pnp);
3095 } else {
3097 * Determine if the process's executable is readable.
3098 * We have to drop p->p_lock before the secpolicy
3099 * and VOP operation.
3101 VN_HOLD(xvp);
3102 prunlock(pnp);
3103 if (secpolicy_proc_access(cr) != 0)
3104 error = fop_access(xvp, VREAD, 0, cr, ct);
3105 VN_RELE(xvp);
3107 if (error)
3108 return (error);
3109 break;
3112 if (type == PR_CURDIR || type == PR_ROOTDIR) {
3114 * Final access check on the underlying directory vnode.
3116 return (fop_access(pnp->pr_realvp, mode, flags, cr, ct));
3120 * Visceral revulsion: For compatibility with old /proc,
3121 * allow the /proc/<pid> directory to be opened for writing.
3123 vmode = pnp->pr_mode;
3124 if (type == PR_PIDDIR)
3125 vmode |= VWRITE;
3126 if ((vmode & mode) != mode)
3127 error = secpolicy_proc_access(cr);
3128 return (error);
3132 * Array of lookup functions, indexed by /proc file type.
3134 static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3135 *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3136 *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
3137 *pr_lookup_ctdir();
3139 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3140 pr_lookup_procdir, /* /proc */
3141 pr_lookup_notdir, /* /proc/self */
3142 pr_lookup_piddir, /* /proc/<pid> */
3143 pr_lookup_notdir, /* /proc/<pid>/as */
3144 pr_lookup_notdir, /* /proc/<pid>/ctl */
3145 pr_lookup_notdir, /* /proc/<pid>/status */
3146 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3147 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3148 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3149 pr_lookup_notdir, /* /proc/<pid>/map */
3150 pr_lookup_notdir, /* /proc/<pid>/rmap */
3151 pr_lookup_notdir, /* /proc/<pid>/xmap */
3152 pr_lookup_notdir, /* /proc/<pid>/cred */
3153 pr_lookup_notdir, /* /proc/<pid>/sigact */
3154 pr_lookup_notdir, /* /proc/<pid>/auxv */
3155 #if defined(__x86)
3156 pr_lookup_notdir, /* /proc/<pid>/ldt */
3157 #endif
3158 pr_lookup_notdir, /* /proc/<pid>/usage */
3159 pr_lookup_notdir, /* /proc/<pid>/lusage */
3160 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3161 pr_lookup_notdir, /* /proc/<pid>/watch */
3162 pr_lookup_notdir, /* /proc/<pid>/cwd */
3163 pr_lookup_notdir, /* /proc/<pid>/root */
3164 pr_lookup_fddir, /* /proc/<pid>/fd */
3165 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3166 pr_lookup_objectdir, /* /proc/<pid>/object */
3167 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3168 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3169 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3170 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3171 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3172 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3173 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3174 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3175 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3176 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3177 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
3178 pr_lookup_notdir, /* /proc/<pid>/priv */
3179 pr_lookup_pathdir, /* /proc/<pid>/path */
3180 pr_lookup_notdir, /* /proc/<pid>/path/xxx */
3181 pr_lookup_ctdir, /* /proc/<pid>/contracts */
3182 pr_lookup_notdir, /* /proc/<pid>/contracts/<ctid> */
3183 pr_lookup_notdir, /* /proc/<pid>/secflags */
3184 pr_lookup_notdir, /* old process file */
3185 pr_lookup_notdir, /* old lwp file */
3186 pr_lookup_notdir, /* old pagedata file */
3189 static int
3190 prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3191 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3192 int *direntflags, pathname_t *realpnp)
3194 prnode_t *pnp = VTOP(dp);
3195 prnodetype_t type = pnp->pr_type;
3196 int error;
3198 ASSERT(dp->v_type == VDIR);
3199 ASSERT(type < PR_NFILES);
3201 if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
3202 VN_HOLD(pnp->pr_parent);
3203 *vpp = pnp->pr_parent;
3204 return (0);
3207 if (*comp == '\0' ||
3208 strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
3209 VN_HOLD(dp);
3210 *vpp = dp;
3211 return (0);
3214 switch (type) {
3215 case PR_CURDIR:
3216 case PR_ROOTDIR:
3217 /* restrict lookup permission to owner or root */
3218 if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3219 return (error);
3220 /* FALLTHROUGH */
3221 case PR_FD:
3223 * Performing a VOP_LOOKUP on the underlying vnode and emitting
3224 * the resulting vnode, without encapsulation, as our own is a
3225 * very special case when it comes to the assumptions built
3226 * into VFS.
3228 * Since the resulting vnode is highly likely to be at some
3229 * abitrary position in another filesystem, we insist that the
3230 * VTRAVERSE flag is set on the parent. This prevents things
3231 * such as the v_path freshness logic from mistaking the
3232 * resulting vnode as a "real" child of the parent, rather than
3233 * a consequence of this "procfs wormhole".
3235 * Failure to establish such protections can lead to
3236 * incorrectly calculated v_paths being set on nodes reached
3237 * through these lookups.
3239 ASSERT((dp->v_flag & VTRAVERSE) != 0);
3241 dp = pnp->pr_realvp;
3242 return (fop_lookup(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3243 direntflags, realpnp));
3244 default:
3245 break;
3248 if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
3249 (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3250 return (error);
3252 /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3253 *vpp = (pr_lookup_function[type](dp, comp));
3255 return ((*vpp == NULL) ? ENOENT : 0);
3258 /* ARGSUSED */
3259 static int
3260 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3261 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3262 vsecattr_t *vsecp)
3264 int error;
3266 if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3267 ct, NULL, NULL)) != 0) {
3268 if (error == ENOENT) {
3269 /* One can't O_CREAT nonexistent files in /proc. */
3270 error = EACCES;
3272 return (error);
3275 if (excl == EXCL) {
3276 /* Disallow the O_EXCL case */
3277 error = EEXIST;
3278 } else if ((error = praccess(*vpp, mode, 0, cr, ct)) == 0) {
3279 /* Before proceeding, handle O_TRUNC if necessary. */
3280 if (vap->va_mask & AT_SIZE) {
3281 vnode_t *vp = *vpp;
3283 if (vp->v_type == VDIR) {
3284 /* Only allow O_TRUNC on files */
3285 error = EISDIR;
3286 } else if (vp->v_type != VPROC ||
3287 VTOP(vp)->pr_type != PR_FD) {
3289 * Disallow for files outside of the
3290 * /proc/<pid>/fd/<n> entries
3292 error = EACCES;
3293 } else {
3294 uint_t mask;
3296 vp = VTOP(vp)->pr_realvp;
3297 mask = vap->va_mask;
3298 vap->va_mask = AT_SIZE;
3299 error = fop_setattr(vp, vap, 0, cr, ct);
3300 vap->va_mask = mask;
3305 if (error) {
3306 VN_RELE(*vpp);
3307 *vpp = NULL;
3309 return (error);
3312 /* ARGSUSED */
3313 static vnode_t *
3314 pr_lookup_notdir(vnode_t *dp, char *comp)
3316 return (NULL);
3320 * Find or construct a process vnode for the given pid.
3322 static vnode_t *
3323 pr_lookup_procdir(vnode_t *dp, char *comp)
3325 pid_t pid;
3326 prnode_t *pnp;
3327 prcommon_t *pcp;
3328 vnode_t *vp;
3329 proc_t *p;
3330 int c;
3332 ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
3334 if (strcmp(comp, "self") == 0) {
3335 pnp = prgetnode(dp, PR_SELF);
3336 return (PTOV(pnp));
3337 } else {
3338 pid = 0;
3339 while ((c = *comp++) != '\0') {
3340 if (c < '0' || c > '9')
3341 return (NULL);
3342 pid = 10*pid + c - '0';
3343 if (pid > maxpid)
3344 return (NULL);
3348 pnp = prgetnode(dp, PR_PIDDIR);
3350 mutex_enter(&pidlock);
3351 if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
3352 mutex_exit(&pidlock);
3353 prfreenode(pnp);
3354 return (NULL);
3356 ASSERT(p->p_stat != 0);
3358 /* NOTE: we're holding pidlock across the policy call. */
3359 if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3360 mutex_exit(&pidlock);
3361 prfreenode(pnp);
3362 return (NULL);
3365 mutex_enter(&p->p_lock);
3366 mutex_exit(&pidlock);
3369 * If a process vnode already exists and it is not invalid
3370 * and it was created by the current process and it belongs
3371 * to the same /proc mount point as our parent vnode, then
3372 * just use it and discard the newly-allocated prnode.
3374 for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3375 if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
3376 VTOP(vp)->pr_owner == curproc &&
3377 vp->v_vfsp == dp->v_vfsp) {
3378 ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
3379 VN_HOLD(vp);
3380 prfreenode(pnp);
3381 mutex_exit(&p->p_lock);
3382 return (vp);
3385 pnp->pr_owner = curproc;
3388 * prgetnode() initialized most of the prnode.
3389 * Finish the job.
3391 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
3392 if ((vp = p->p_trace) != NULL) {
3393 /* discard the new prcommon and use the existing prcommon */
3394 prfreecommon(pcp);
3395 pcp = VTOP(vp)->pr_common;
3396 mutex_enter(&pcp->prc_mutex);
3397 ASSERT(pcp->prc_refcnt > 0);
3398 pcp->prc_refcnt++;
3399 mutex_exit(&pcp->prc_mutex);
3400 pnp->pr_common = pcp;
3401 } else {
3402 /* initialize the new prcommon struct */
3403 if ((p->p_flag & SSYS) || p->p_as == &kas)
3404 pcp->prc_flags |= PRC_SYS;
3405 if (p->p_stat == SZOMB)
3406 pcp->prc_flags |= PRC_DESTROY;
3407 pcp->prc_proc = p;
3408 pcp->prc_datamodel = p->p_model;
3409 pcp->prc_pid = p->p_pid;
3410 pcp->prc_slot = p->p_slot;
3412 pnp->pr_pcommon = pcp;
3413 pnp->pr_parent = dp;
3414 VN_HOLD(dp);
3416 * Link in the old, invalid directory vnode so we
3417 * can later determine the last close of the file.
3419 pnp->pr_next = p->p_trace;
3420 p->p_trace = dp = PTOV(pnp);
3423 * Kludge for old /proc: initialize the PR_PIDFILE as well.
3425 vp = pnp->pr_pidfile;
3426 pnp = VTOP(vp);
3427 pnp->pr_ino = ptoi(pcp->prc_pid);
3428 pnp->pr_common = pcp;
3429 pnp->pr_pcommon = pcp;
3430 pnp->pr_parent = dp;
3431 pnp->pr_next = p->p_plist;
3432 p->p_plist = vp;
3434 mutex_exit(&p->p_lock);
3435 return (dp);
3438 static vnode_t *
3439 pr_lookup_piddir(vnode_t *dp, char *comp)
3441 prnode_t *dpnp = VTOP(dp);
3442 vnode_t *vp;
3443 prnode_t *pnp;
3444 proc_t *p;
3445 user_t *up;
3446 prdirent_t *dirp;
3447 int i;
3448 enum prnodetype type;
3450 ASSERT(dpnp->pr_type == PR_PIDDIR);
3452 for (i = 0; i < NPIDDIRFILES; i++) {
3453 /* Skip "." and ".." */
3454 dirp = &piddir[i+2];
3455 if (strcmp(comp, dirp->d_name) == 0)
3456 break;
3459 if (i >= NPIDDIRFILES)
3460 return (NULL);
3462 type = (int)dirp->d_ino;
3463 pnp = prgetnode(dp, type);
3465 p = pr_p_lock(dpnp);
3466 mutex_exit(&pr_pidlock);
3467 if (p == NULL) {
3468 prfreenode(pnp);
3469 return (NULL);
3471 if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
3472 switch (type) {
3473 case PR_PSINFO:
3474 case PR_USAGE:
3475 break;
3476 default:
3477 prunlock(dpnp);
3478 prfreenode(pnp);
3479 return (NULL);
3483 switch (type) {
3484 case PR_CURDIR:
3485 case PR_ROOTDIR:
3486 up = PTOU(p);
3487 vp = (type == PR_CURDIR)? up->u_cdir :
3488 (up->u_rdir? up->u_rdir : rootdir);
3490 if (vp == NULL) {
3491 /* can't happen(?) */
3492 prunlock(dpnp);
3493 prfreenode(pnp);
3494 return (NULL);
3497 * Fill in the prnode so future references will
3498 * be able to find the underlying object's vnode.
3500 VN_HOLD(vp);
3501 pnp->pr_realvp = vp;
3502 PTOV(pnp)->v_flag |= VTRAVERSE;
3503 break;
3504 default:
3505 break;
3508 mutex_enter(&dpnp->pr_mutex);
3510 if ((vp = dpnp->pr_files[i]) != NULL &&
3511 !(VTOP(vp)->pr_flags & PR_INVAL)) {
3512 VN_HOLD(vp);
3513 mutex_exit(&dpnp->pr_mutex);
3514 prunlock(dpnp);
3515 prfreenode(pnp);
3516 return (vp);
3520 * prgetnode() initialized most of the prnode.
3521 * Finish the job.
3523 pnp->pr_common = dpnp->pr_common;
3524 pnp->pr_pcommon = dpnp->pr_pcommon;
3525 pnp->pr_parent = dp;
3526 VN_HOLD(dp);
3527 pnp->pr_index = i;
3529 dpnp->pr_files[i] = vp = PTOV(pnp);
3532 * Link new vnode into list of all /proc vnodes for the process.
3534 if (vp->v_type == VPROC) {
3535 pnp->pr_next = p->p_plist;
3536 p->p_plist = vp;
3538 mutex_exit(&dpnp->pr_mutex);
3539 prunlock(dpnp);
3540 return (vp);
3543 static vnode_t *
3544 pr_lookup_objectdir(vnode_t *dp, char *comp)
3546 prnode_t *dpnp = VTOP(dp);
3547 prnode_t *pnp;
3548 proc_t *p;
3549 struct seg *seg;
3550 struct as *as;
3551 vnode_t *vp;
3552 vattr_t vattr;
3554 ASSERT(dpnp->pr_type == PR_OBJECTDIR);
3556 pnp = prgetnode(dp, PR_OBJECT);
3558 if (prlock(dpnp, ZNO) != 0) {
3559 prfreenode(pnp);
3560 return (NULL);
3562 p = dpnp->pr_common->prc_proc;
3563 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3564 prunlock(dpnp);
3565 prfreenode(pnp);
3566 return (NULL);
3570 * We drop p_lock before grabbing the address space lock
3571 * in order to avoid a deadlock with the clock thread.
3572 * The process will not disappear and its address space
3573 * will not change because it is marked P_PR_LOCK.
3575 mutex_exit(&p->p_lock);
3576 AS_LOCK_ENTER(as, RW_READER);
3577 if ((seg = AS_SEGFIRST(as)) == NULL) {
3578 vp = NULL;
3579 goto out;
3581 if (strcmp(comp, "a.out") == 0) {
3582 vp = p->p_exec;
3583 goto out;
3585 do {
3587 * Manufacture a filename for the "object" directory.
3589 vattr.va_mask = AT_FSID|AT_NODEID;
3590 if (seg->s_ops == &segvn_ops &&
3591 segop_getvp(seg, seg->s_base, &vp) == 0 &&
3592 vp != NULL && vp->v_type == VREG &&
3593 fop_getattr(vp, &vattr, 0, CRED(), NULL) == 0) {
3594 char name[64];
3596 if (vp == p->p_exec) /* "a.out" */
3597 continue;
3598 pr_object_name(name, vp, &vattr);
3599 if (strcmp(name, comp) == 0)
3600 goto out;
3602 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3604 vp = NULL;
3605 out:
3606 if (vp != NULL) {
3607 VN_HOLD(vp);
3609 AS_LOCK_EXIT(as);
3610 mutex_enter(&p->p_lock);
3611 prunlock(dpnp);
3613 if (vp == NULL)
3614 prfreenode(pnp);
3615 else {
3617 * Fill in the prnode so future references will
3618 * be able to find the underlying object's vnode.
3619 * Don't link this prnode into the list of all
3620 * prnodes for the process; this is a one-use node.
3621 * Its use is entirely to catch and fail opens for writing.
3623 pnp->pr_realvp = vp;
3624 vp = PTOV(pnp);
3627 return (vp);
3631 * Find or construct an lwp vnode for the given lwpid.
3633 static vnode_t *
3634 pr_lookup_lwpdir(vnode_t *dp, char *comp)
3636 id_t tid; /* same type as t->t_tid */
3637 int want_agent;
3638 prnode_t *dpnp = VTOP(dp);
3639 prnode_t *pnp;
3640 prcommon_t *pcp;
3641 vnode_t *vp;
3642 proc_t *p;
3643 kthread_t *t;
3644 lwpdir_t *ldp;
3645 lwpent_t *lep;
3646 int tslot;
3647 int c;
3649 ASSERT(dpnp->pr_type == PR_LWPDIR);
3651 tid = 0;
3652 if (strcmp(comp, "agent") == 0)
3653 want_agent = 1;
3654 else {
3655 want_agent = 0;
3656 while ((c = *comp++) != '\0') {
3657 id_t otid;
3659 if (c < '0' || c > '9')
3660 return (NULL);
3661 otid = tid;
3662 tid = 10*tid + c - '0';
3663 if (tid/10 != otid) /* integer overflow */
3664 return (NULL);
3668 pnp = prgetnode(dp, PR_LWPIDDIR);
3670 p = pr_p_lock(dpnp);
3671 mutex_exit(&pr_pidlock);
3672 if (p == NULL) {
3673 prfreenode(pnp);
3674 return (NULL);
3677 if (want_agent) {
3678 if ((t = p->p_agenttp) == NULL)
3679 lep = NULL;
3680 else {
3681 tid = t->t_tid;
3682 tslot = t->t_dslot;
3683 lep = p->p_lwpdir[tslot].ld_entry;
3685 } else {
3686 if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
3687 lep = NULL;
3688 else {
3689 tslot = (int)(ldp - p->p_lwpdir);
3690 lep = ldp->ld_entry;
3694 if (lep == NULL) {
3695 prunlock(dpnp);
3696 prfreenode(pnp);
3697 return (NULL);
3701 * If an lwp vnode already exists and it is not invalid
3702 * and it was created by the current process and it belongs
3703 * to the same /proc mount point as our parent vnode, then
3704 * just use it and discard the newly-allocated prnode.
3706 for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3707 if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
3708 VTOP(vp)->pr_owner == curproc &&
3709 vp->v_vfsp == dp->v_vfsp) {
3710 VN_HOLD(vp);
3711 prunlock(dpnp);
3712 prfreenode(pnp);
3713 return (vp);
3716 pnp->pr_owner = curproc;
3719 * prgetnode() initialized most of the prnode.
3720 * Finish the job.
3722 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
3723 if ((vp = lep->le_trace) != NULL) {
3724 /* discard the new prcommon and use the existing prcommon */
3725 prfreecommon(pcp);
3726 pcp = VTOP(vp)->pr_common;
3727 mutex_enter(&pcp->prc_mutex);
3728 ASSERT(pcp->prc_refcnt > 0);
3729 pcp->prc_refcnt++;
3730 mutex_exit(&pcp->prc_mutex);
3731 pnp->pr_common = pcp;
3732 } else {
3733 /* initialize the new prcommon struct */
3734 pcp->prc_flags |= PRC_LWP;
3735 if ((p->p_flag & SSYS) || p->p_as == &kas)
3736 pcp->prc_flags |= PRC_SYS;
3737 if ((t = lep->le_thread) == NULL)
3738 pcp->prc_flags |= PRC_DESTROY;
3739 pcp->prc_proc = p;
3740 pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
3741 pcp->prc_pid = p->p_pid;
3742 pcp->prc_slot = p->p_slot;
3743 pcp->prc_thread = t;
3744 pcp->prc_tid = tid;
3745 pcp->prc_tslot = tslot;
3747 pnp->pr_pcommon = dpnp->pr_pcommon;
3748 pnp->pr_parent = dp;
3749 VN_HOLD(dp);
3751 * Link in the old, invalid directory vnode so we
3752 * can later determine the last close of the file.
3754 pnp->pr_next = lep->le_trace;
3755 lep->le_trace = vp = PTOV(pnp);
3756 prunlock(dpnp);
3757 return (vp);
3760 static vnode_t *
3761 pr_lookup_lwpiddir(vnode_t *dp, char *comp)
3763 prnode_t *dpnp = VTOP(dp);
3764 vnode_t *vp;
3765 prnode_t *pnp;
3766 proc_t *p;
3767 prdirent_t *dirp;
3768 int i;
3769 enum prnodetype type;
3771 ASSERT(dpnp->pr_type == PR_LWPIDDIR);
3773 for (i = 0; i < NLWPIDDIRFILES; i++) {
3774 /* Skip "." and ".." */
3775 dirp = &lwpiddir[i+2];
3776 if (strcmp(comp, dirp->d_name) == 0)
3777 break;
3780 if (i >= NLWPIDDIRFILES)
3781 return (NULL);
3783 type = (int)dirp->d_ino;
3784 pnp = prgetnode(dp, type);
3786 p = pr_p_lock(dpnp);
3787 mutex_exit(&pr_pidlock);
3788 if (p == NULL) {
3789 prfreenode(pnp);
3790 return (NULL);
3792 if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
3794 * Only the lwpsinfo file is present for zombie lwps.
3795 * Nothing is present if the lwp has been reaped.
3797 if (dpnp->pr_common->prc_tslot == -1 ||
3798 type != PR_LWPSINFO) {
3799 prunlock(dpnp);
3800 prfreenode(pnp);
3801 return (NULL);
3806 mutex_enter(&dpnp->pr_mutex);
3808 if ((vp = dpnp->pr_files[i]) != NULL &&
3809 !(VTOP(vp)->pr_flags & PR_INVAL)) {
3810 VN_HOLD(vp);
3811 mutex_exit(&dpnp->pr_mutex);
3812 prunlock(dpnp);
3813 prfreenode(pnp);
3814 return (vp);
3818 * prgetnode() initialized most of the prnode.
3819 * Finish the job.
3821 pnp->pr_common = dpnp->pr_common;
3822 pnp->pr_pcommon = dpnp->pr_pcommon;
3823 pnp->pr_parent = dp;
3824 VN_HOLD(dp);
3825 pnp->pr_index = i;
3827 dpnp->pr_files[i] = vp = PTOV(pnp);
3830 * Link new vnode into list of all /proc vnodes for the process.
3832 if (vp->v_type == VPROC) {
3833 pnp->pr_next = p->p_plist;
3834 p->p_plist = vp;
3836 mutex_exit(&dpnp->pr_mutex);
3837 prunlock(dpnp);
3838 return (vp);
3842 * Lookup one of the process's open files.
3844 static vnode_t *
3845 pr_lookup_fddir(vnode_t *dp, char *comp)
3847 prnode_t *dpnp = VTOP(dp);
3848 prnode_t *pnp;
3849 vnode_t *vp = NULL;
3850 proc_t *p;
3851 file_t *fp;
3852 uint_t fd;
3853 int c;
3854 uf_entry_t *ufp;
3855 uf_info_t *fip;
3857 ASSERT(dpnp->pr_type == PR_FDDIR);
3859 fd = 0;
3860 while ((c = *comp++) != '\0') {
3861 int ofd;
3862 if (c < '0' || c > '9')
3863 return (NULL);
3864 ofd = fd;
3865 fd = 10*fd + c - '0';
3866 if (fd/10 != ofd) /* integer overflow */
3867 return (NULL);
3870 pnp = prgetnode(dp, PR_FD);
3872 if (prlock(dpnp, ZNO) != 0) {
3873 prfreenode(pnp);
3874 return (NULL);
3876 p = dpnp->pr_common->prc_proc;
3877 if ((p->p_flag & SSYS) || p->p_as == &kas) {
3878 prunlock(dpnp);
3879 prfreenode(pnp);
3880 return (NULL);
3883 fip = P_FINFO(p);
3884 mutex_exit(&p->p_lock);
3885 mutex_enter(&fip->fi_lock);
3886 if (fd < fip->fi_nfiles) {
3887 UF_ENTER(ufp, fip, fd);
3888 if ((fp = ufp->uf_file) != NULL) {
3889 pnp->pr_mode = 07111;
3890 if (fp->f_flag & FREAD)
3891 pnp->pr_mode |= 0444;
3892 if (fp->f_flag & FWRITE)
3893 pnp->pr_mode |= 0222;
3894 vp = fp->f_vnode;
3895 VN_HOLD(vp);
3897 UF_EXIT(ufp);
3899 mutex_exit(&fip->fi_lock);
3900 mutex_enter(&p->p_lock);
3901 prunlock(dpnp);
3903 if (vp == NULL)
3904 prfreenode(pnp);
3905 else {
3907 * Fill in the prnode so future references will
3908 * be able to find the underlying object's vnode.
3909 * Don't link this prnode into the list of all
3910 * prnodes for the process; this is a one-use node.
3912 pnp->pr_realvp = vp;
3913 pnp->pr_parent = dp; /* needed for prlookup */
3914 VN_HOLD(dp);
3915 vp = PTOV(pnp);
3916 if (pnp->pr_realvp->v_type == VDIR) {
3917 vp->v_type = VDIR;
3918 vp->v_flag |= VTRAVERSE;
3922 return (vp);
3925 static vnode_t *
3926 pr_lookup_pathdir(vnode_t *dp, char *comp)
3928 prnode_t *dpnp = VTOP(dp);
3929 prnode_t *pnp;
3930 vnode_t *vp = NULL;
3931 proc_t *p;
3932 uint_t fd, flags = 0;
3933 int c;
3934 uf_entry_t *ufp;
3935 uf_info_t *fip;
3936 enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
3937 char *tmp;
3938 int idx;
3939 struct seg *seg;
3940 struct as *as = NULL;
3941 vattr_t vattr;
3943 ASSERT(dpnp->pr_type == PR_PATHDIR);
3946 * First, check if this is a numeric entry, in which case we have a
3947 * file descriptor.
3949 fd = 0;
3950 type = NAME_FD;
3951 tmp = comp;
3952 while ((c = *tmp++) != '\0') {
3953 int ofd;
3954 if (c < '0' || c > '9') {
3955 type = NAME_UNKNOWN;
3956 break;
3958 ofd = fd;
3959 fd = 10*fd + c - '0';
3960 if (fd/10 != ofd) { /* integer overflow */
3961 type = NAME_UNKNOWN;
3962 break;
3967 * Next, see if it is one of the special values {root, cwd}.
3969 if (type == NAME_UNKNOWN) {
3970 if (strcmp(comp, "root") == 0)
3971 type = NAME_ROOT;
3972 else if (strcmp(comp, "cwd") == 0)
3973 type = NAME_CWD;
3977 * Grab the necessary data from the process
3979 if (prlock(dpnp, ZNO) != 0)
3980 return (NULL);
3981 p = dpnp->pr_common->prc_proc;
3983 fip = P_FINFO(p);
3985 switch (type) {
3986 case NAME_ROOT:
3987 if ((vp = PTOU(p)->u_rdir) == NULL)
3988 vp = p->p_zone->zone_rootvp;
3989 VN_HOLD(vp);
3990 break;
3991 case NAME_CWD:
3992 vp = PTOU(p)->u_cdir;
3993 VN_HOLD(vp);
3994 break;
3995 default:
3996 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3997 prunlock(dpnp);
3998 return (NULL);
4001 mutex_exit(&p->p_lock);
4004 * Determine if this is an object entry
4006 if (type == NAME_UNKNOWN) {
4008 * Start with the inode index immediately after the number of
4009 * files.
4011 mutex_enter(&fip->fi_lock);
4012 idx = fip->fi_nfiles + 4;
4013 mutex_exit(&fip->fi_lock);
4015 if (strcmp(comp, "a.out") == 0) {
4016 if (p->p_execdir != NULL) {
4017 vp = p->p_execdir;
4018 VN_HOLD(vp);
4019 type = NAME_OBJECT;
4020 flags |= PR_AOUT;
4021 } else {
4022 vp = p->p_exec;
4023 VN_HOLD(vp);
4024 type = NAME_OBJECT;
4026 } else {
4027 AS_LOCK_ENTER(as, RW_READER);
4028 if ((seg = AS_SEGFIRST(as)) != NULL) {
4029 do {
4031 * Manufacture a filename for the
4032 * "object" directory.
4034 vattr.va_mask = AT_FSID|AT_NODEID;
4035 if (seg->s_ops == &segvn_ops &&
4036 segop_getvp(seg, seg->s_base, &vp)
4037 == 0 &&
4038 vp != NULL && vp->v_type == VREG &&
4039 fop_getattr(vp, &vattr, 0, CRED(),
4040 NULL) == 0) {
4041 char name[64];
4043 if (vp == p->p_exec)
4044 continue;
4045 idx++;
4046 pr_object_name(name, vp,
4047 &vattr);
4048 if (strcmp(name, comp) == 0)
4049 break;
4051 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4054 if (seg == NULL) {
4055 vp = NULL;
4056 } else {
4057 VN_HOLD(vp);
4058 type = NAME_OBJECT;
4061 AS_LOCK_EXIT(as);
4066 switch (type) {
4067 case NAME_FD:
4068 mutex_enter(&fip->fi_lock);
4069 if (fd < fip->fi_nfiles) {
4070 UF_ENTER(ufp, fip, fd);
4071 if (ufp->uf_file != NULL) {
4072 vp = ufp->uf_file->f_vnode;
4073 VN_HOLD(vp);
4075 UF_EXIT(ufp);
4077 mutex_exit(&fip->fi_lock);
4078 idx = fd + 4;
4079 break;
4080 case NAME_ROOT:
4081 idx = 2;
4082 break;
4083 case NAME_CWD:
4084 idx = 3;
4085 break;
4086 case NAME_OBJECT:
4087 case NAME_UNKNOWN:
4088 /* Nothing to do */
4089 break;
4092 mutex_enter(&p->p_lock);
4093 prunlock(dpnp);
4095 if (vp != NULL) {
4096 pnp = prgetnode(dp, PR_PATH);
4098 pnp->pr_flags |= flags;
4099 pnp->pr_common = dpnp->pr_common;
4100 pnp->pr_pcommon = dpnp->pr_pcommon;
4101 pnp->pr_realvp = vp;
4102 pnp->pr_parent = dp; /* needed for prlookup */
4103 pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
4104 VN_HOLD(dp);
4105 vp = PTOV(pnp);
4106 vp->v_type = VLNK;
4109 return (vp);
4113 * Look up one of the process's active templates.
4115 static vnode_t *
4116 pr_lookup_tmpldir(vnode_t *dp, char *comp)
4118 prnode_t *dpnp = VTOP(dp);
4119 prnode_t *pnp;
4120 vnode_t *vp = NULL;
4121 proc_t *p;
4122 int i;
4124 ASSERT(dpnp->pr_type == PR_TMPLDIR);
4126 for (i = 0; i < ct_ntypes; i++)
4127 if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
4128 break;
4129 if (i == ct_ntypes)
4130 return (NULL);
4132 pnp = prgetnode(dp, PR_TMPL);
4134 if (prlock(dpnp, ZNO) != 0) {
4135 prfreenode(pnp);
4136 return (NULL);
4138 p = dpnp->pr_common->prc_proc;
4139 if ((p->p_flag & SSYS) || p->p_as == &kas ||
4140 (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
4141 prunlock(dpnp);
4142 prfreenode(pnp);
4143 return (NULL);
4145 if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
4146 pnp->pr_common = dpnp->pr_common;
4147 pnp->pr_pcommon = dpnp->pr_pcommon;
4148 pnp->pr_parent = dp;
4149 pnp->pr_cttype = i;
4150 VN_HOLD(dp);
4151 vp = PTOV(pnp);
4152 } else {
4153 prfreenode(pnp);
4155 prunlock(dpnp);
4157 return (vp);
4161 * Look up one of the contracts owned by the process.
4163 static vnode_t *
4164 pr_lookup_ctdir(vnode_t *dp, char *comp)
4166 prnode_t *dpnp = VTOP(dp);
4167 prnode_t *pnp;
4168 vnode_t *vp = NULL;
4169 proc_t *p;
4170 id_t id = 0;
4171 contract_t *ct;
4172 int c;
4174 ASSERT(dpnp->pr_type == PR_CTDIR);
4176 while ((c = *comp++) != '\0') {
4177 id_t oid;
4178 if (c < '0' || c > '9')
4179 return (NULL);
4180 oid = id;
4181 id = 10 * id + c - '0';
4182 if (id / 10 != oid) /* integer overflow */
4183 return (NULL);
4187 * Search all contracts; we'll filter below.
4189 ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
4190 if (ct == NULL)
4191 return (NULL);
4193 pnp = prgetnode(dp, PR_CT);
4195 if (prlock(dpnp, ZNO) != 0) {
4196 prfreenode(pnp);
4197 contract_rele(ct);
4198 return (NULL);
4200 p = dpnp->pr_common->prc_proc;
4202 * We only allow lookups of contracts owned by this process, or,
4203 * if we are zsched and this is a zone's procfs, contracts on
4204 * stuff in the zone which are held by processes or contracts
4205 * outside the zone. (see logic in contract_status_common)
4207 if ((ct->ct_owner != p) &&
4208 !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4209 VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4210 VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
4211 ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
4212 prunlock(dpnp);
4213 prfreenode(pnp);
4214 contract_rele(ct);
4215 return (NULL);
4217 pnp->pr_common = dpnp->pr_common;
4218 pnp->pr_pcommon = dpnp->pr_pcommon;
4219 pnp->pr_contract = ct;
4220 pnp->pr_parent = dp;
4221 pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
4222 VN_HOLD(dp);
4223 prunlock(dpnp);
4224 vp = PTOV(pnp);
4226 return (vp);
4230 * Construct an lwp vnode for the old /proc interface.
4231 * We stand on our head to make the /proc plumbing correct.
4233 vnode_t *
4234 prlwpnode(prnode_t *pnp, uint_t tid)
4236 char comp[12];
4237 vnode_t *dp;
4238 vnode_t *vp;
4239 prcommon_t *pcp;
4240 proc_t *p;
4243 * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
4245 if (pnp->pr_type == PR_PIDFILE) {
4246 dp = pnp->pr_parent; /* /proc/<pid> */
4247 VN_HOLD(dp);
4248 vp = pr_lookup_piddir(dp, "lwp");
4249 VN_RELE(dp);
4250 if ((dp = vp) == NULL) /* /proc/<pid>/lwp */
4251 return (NULL);
4252 } else if (pnp->pr_type == PR_LWPIDFILE) {
4253 dp = pnp->pr_parent; /* /proc/<pid>/lwp/<lwpid> */
4254 dp = VTOP(dp)->pr_parent; /* /proc/<pid>/lwp */
4255 VN_HOLD(dp);
4256 } else {
4257 return (NULL);
4260 (void) pr_u32tos(tid, comp, sizeof (comp));
4261 vp = pr_lookup_lwpdir(dp, comp);
4262 VN_RELE(dp);
4263 if ((dp = vp) == NULL)
4264 return (NULL);
4266 pnp = prgetnode(dp, PR_LWPIDFILE);
4267 vp = PTOV(pnp);
4270 * prgetnode() initialized most of the prnode.
4271 * Finish the job.
4273 pcp = VTOP(dp)->pr_common;
4274 pnp->pr_ino = ptoi(pcp->prc_pid);
4275 pnp->pr_common = pcp;
4276 pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
4277 pnp->pr_parent = dp;
4279 * Link new vnode into list of all /proc vnodes for the process.
4281 p = pr_p_lock(pnp);
4282 mutex_exit(&pr_pidlock);
4283 if (p == NULL) {
4284 VN_RELE(dp);
4285 prfreenode(pnp);
4286 vp = NULL;
4287 } else if (pcp->prc_thread == NULL) {
4288 prunlock(pnp);
4289 VN_RELE(dp);
4290 prfreenode(pnp);
4291 vp = NULL;
4292 } else {
4293 pnp->pr_next = p->p_plist;
4294 p->p_plist = vp;
4295 prunlock(pnp);
4298 return (vp);
4301 #if defined(DEBUG)
4303 static uint32_t nprnode;
4304 static uint32_t nprcommon;
4306 #define INCREMENT(x) atomic_inc_32(&x);
4307 #define DECREMENT(x) atomic_dec_32(&x);
4309 #else
4311 #define INCREMENT(x)
4312 #define DECREMENT(x)
4314 #endif /* DEBUG */
4317 * New /proc vnode required; allocate it and fill in most of the fields.
4319 prnode_t *
4320 prgetnode(vnode_t *dp, prnodetype_t type)
4322 prnode_t *pnp;
4323 prcommon_t *pcp;
4324 vnode_t *vp;
4325 ulong_t nfiles;
4327 INCREMENT(nprnode);
4328 pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
4330 mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
4331 pnp->pr_type = type;
4333 pnp->pr_vnode = vn_alloc(KM_SLEEP);
4335 vp = PTOV(pnp);
4336 vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
4337 vn_setops(vp, &prvnodeops);
4338 vp->v_vfsp = dp->v_vfsp;
4339 vp->v_type = VPROC;
4340 vp->v_data = (caddr_t)pnp;
4342 switch (type) {
4343 case PR_PIDDIR:
4344 case PR_LWPIDDIR:
4346 * We need a prcommon and a files array for each of these.
4348 INCREMENT(nprcommon);
4350 pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
4351 pcp->prc_refcnt = 1;
4352 pnp->pr_common = pcp;
4353 mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
4354 cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
4356 nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
4357 pnp->pr_files =
4358 kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
4360 vp->v_type = VDIR;
4362 * Mode should be read-search by all, but we cannot so long
4363 * as we must support compatibility mode with old /proc.
4364 * Make /proc/<pid> be read by owner only, search by all.
4365 * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
4366 * set VDIROPEN on /proc/<pid> so it can be opened for writing.
4368 if (type == PR_PIDDIR) {
4369 /* kludge for old /proc interface */
4370 prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
4371 pnp->pr_pidfile = PTOV(xpnp);
4372 pnp->pr_mode = 0511;
4373 vp->v_flag |= VDIROPEN;
4374 } else {
4375 pnp->pr_mode = 0555;
4378 break;
4380 case PR_CURDIR:
4381 case PR_ROOTDIR:
4382 case PR_FDDIR:
4383 case PR_OBJECTDIR:
4384 case PR_PATHDIR:
4385 case PR_CTDIR:
4386 case PR_TMPLDIR:
4387 vp->v_type = VDIR;
4388 pnp->pr_mode = 0500; /* read-search by owner only */
4389 break;
4391 case PR_CT:
4392 vp->v_type = VLNK;
4393 pnp->pr_mode = 0500; /* read-search by owner only */
4394 break;
4396 case PR_PATH:
4397 case PR_SELF:
4398 vp->v_type = VLNK;
4399 pnp->pr_mode = 0777;
4400 break;
4402 case PR_LWPDIR:
4403 vp->v_type = VDIR;
4404 pnp->pr_mode = 0555; /* read-search by all */
4405 break;
4407 case PR_AS:
4408 case PR_TMPL:
4409 pnp->pr_mode = 0600; /* read-write by owner only */
4410 break;
4412 case PR_CTL:
4413 case PR_LWPCTL:
4414 pnp->pr_mode = 0200; /* write-only by owner only */
4415 break;
4417 case PR_PIDFILE:
4418 case PR_LWPIDFILE:
4419 pnp->pr_mode = 0600; /* read-write by owner only */
4420 break;
4422 case PR_PSINFO:
4423 case PR_LPSINFO:
4424 case PR_LWPSINFO:
4425 case PR_USAGE:
4426 case PR_LUSAGE:
4427 case PR_LWPUSAGE:
4428 pnp->pr_mode = 0444; /* read-only by all */
4429 break;
4431 default:
4432 pnp->pr_mode = 0400; /* read-only by owner only */
4433 break;
4435 vn_exists(vp);
4436 return (pnp);
4440 * Free the storage obtained from prgetnode().
4442 void
4443 prfreenode(prnode_t *pnp)
4445 vnode_t *vp;
4446 ulong_t nfiles;
4448 vn_invalid(PTOV(pnp));
4449 vn_free(PTOV(pnp));
4450 mutex_destroy(&pnp->pr_mutex);
4452 switch (pnp->pr_type) {
4453 case PR_PIDDIR:
4454 /* kludge for old /proc interface */
4455 if (pnp->pr_pidfile != NULL) {
4456 prfreenode(VTOP(pnp->pr_pidfile));
4457 pnp->pr_pidfile = NULL;
4459 /* FALLTHROUGH */
4460 case PR_LWPIDDIR:
4462 * We allocated a prcommon and a files array for each of these.
4464 prfreecommon(pnp->pr_common);
4465 nfiles = (pnp->pr_type == PR_PIDDIR)?
4466 NPIDDIRFILES : NLWPIDDIRFILES;
4467 kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
4468 break;
4469 default:
4470 break;
4473 * If there is an underlying vnode, be sure
4474 * to release it after freeing the prnode.
4476 vp = pnp->pr_realvp;
4477 kmem_free(pnp, sizeof (*pnp));
4478 DECREMENT(nprnode);
4479 if (vp != NULL) {
4480 VN_RELE(vp);
4485 * Free a prcommon structure, if the reference count reaches zero.
4487 static void
4488 prfreecommon(prcommon_t *pcp)
4490 mutex_enter(&pcp->prc_mutex);
4491 ASSERT(pcp->prc_refcnt > 0);
4492 if (--pcp->prc_refcnt != 0)
4493 mutex_exit(&pcp->prc_mutex);
4494 else {
4495 mutex_exit(&pcp->prc_mutex);
4496 ASSERT(pcp->prc_pollhead.ph_list == NULL);
4497 ASSERT(pcp->prc_refcnt == 0);
4498 ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
4499 mutex_destroy(&pcp->prc_mutex);
4500 cv_destroy(&pcp->prc_wait);
4501 kmem_free(pcp, sizeof (prcommon_t));
4502 DECREMENT(nprcommon);
4507 * Array of readdir functions, indexed by /proc file type.
4509 static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4510 pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4511 pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
4512 pr_readdir_ctdir();
4514 static int (*pr_readdir_function[PR_NFILES])() = {
4515 pr_readdir_procdir, /* /proc */
4516 pr_readdir_notdir, /* /proc/self */
4517 pr_readdir_piddir, /* /proc/<pid> */
4518 pr_readdir_notdir, /* /proc/<pid>/as */
4519 pr_readdir_notdir, /* /proc/<pid>/ctl */
4520 pr_readdir_notdir, /* /proc/<pid>/status */
4521 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4522 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4523 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4524 pr_readdir_notdir, /* /proc/<pid>/map */
4525 pr_readdir_notdir, /* /proc/<pid>/rmap */
4526 pr_readdir_notdir, /* /proc/<pid>/xmap */
4527 pr_readdir_notdir, /* /proc/<pid>/cred */
4528 pr_readdir_notdir, /* /proc/<pid>/sigact */
4529 pr_readdir_notdir, /* /proc/<pid>/auxv */
4530 #if defined(__x86)
4531 pr_readdir_notdir, /* /proc/<pid>/ldt */
4532 #endif
4533 pr_readdir_notdir, /* /proc/<pid>/usage */
4534 pr_readdir_notdir, /* /proc/<pid>/lusage */
4535 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4536 pr_readdir_notdir, /* /proc/<pid>/watch */
4537 pr_readdir_notdir, /* /proc/<pid>/cwd */
4538 pr_readdir_notdir, /* /proc/<pid>/root */
4539 pr_readdir_fddir, /* /proc/<pid>/fd */
4540 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4541 pr_readdir_objectdir, /* /proc/<pid>/object */
4542 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4543 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4544 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4545 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4546 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4547 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4548 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4549 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4550 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4551 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4552 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4553 pr_readdir_notdir, /* /proc/<pid>/priv */
4554 pr_readdir_pathdir, /* /proc/<pid>/path */
4555 pr_readdir_notdir, /* /proc/<pid>/path/xxx */
4556 pr_readdir_ctdir, /* /proc/<pid>/contracts */
4557 pr_readdir_notdir, /* /proc/<pid>/contracts/<ctid> */
4558 pr_readdir_notdir, /* /proc/<pid>/secflags */
4559 pr_readdir_notdir, /* old process file */
4560 pr_readdir_notdir, /* old lwp file */
4561 pr_readdir_notdir, /* old pagedata file */
4564 /* ARGSUSED */
4565 static int
4566 prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
4567 caller_context_t *ct, int flags)
4569 prnode_t *pnp = VTOP(vp);
4571 ASSERT(pnp->pr_type < PR_NFILES);
4573 /* XXX - Do we need to pass ct and flags? */
4574 return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
4577 /* ARGSUSED */
4578 static int
4579 pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4581 return (ENOTDIR);
4584 /* ARGSUSED */
4585 static int
4586 pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4588 zoneid_t zoneid;
4589 gfs_readdir_state_t gstate;
4590 int error, eof = 0;
4591 offset_t n;
4593 ASSERT(pnp->pr_type == PR_PROCDIR);
4595 zoneid = VTOZONE(PTOV(pnp))->zone_id;
4597 if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
4598 PRROOTINO, PRROOTINO, 0)) != 0)
4599 return (error);
4602 * Loop until user's request is satisfied or until all processes
4603 * have been examined.
4605 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
4606 uint_t pid;
4607 int pslot;
4608 proc_t *p;
4611 * Find next entry. Skip processes not visible where
4612 * this /proc was mounted.
4614 mutex_enter(&pidlock);
4615 while (n < v.v_proc &&
4616 ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
4617 (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
4618 secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
4619 n++;
4622 * Stop when entire proc table has been examined.
4624 if (n >= v.v_proc) {
4625 mutex_exit(&pidlock);
4626 eof = 1;
4627 break;
4630 ASSERT(p->p_stat != 0);
4631 pid = p->p_pid;
4632 pslot = p->p_slot;
4633 mutex_exit(&pidlock);
4634 error = gfs_readdir_emitn(&gstate, uiop, n,
4635 pmkino(0, pslot, PR_PIDDIR), pid);
4636 if (error)
4637 break;
4640 return (gfs_readdir_fini(&gstate, error, eofp, eof));
4643 /* ARGSUSED */
4644 static int
4645 pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
4647 int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
4648 prdirent_t dirent;
4649 prdirent_t *dirp;
4650 offset_t off;
4651 int error;
4653 ASSERT(pnp->pr_type == PR_PIDDIR);
4655 if (uiop->uio_offset < 0 ||
4656 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
4657 uiop->uio_resid < sizeof (prdirent_t))
4658 return (EINVAL);
4659 if (pnp->pr_pcommon->prc_proc == NULL)
4660 return (ENOENT);
4661 if (uiop->uio_offset >= sizeof (piddir))
4662 goto out;
4665 * Loop until user's request is satisfied, omitting some
4666 * files along the way if the process is a zombie.
4668 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
4669 uiop->uio_resid >= sizeof (prdirent_t) &&
4670 dirp < &piddir[NPIDDIRFILES+2];
4671 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
4672 off = uiop->uio_offset;
4673 if (zombie) {
4674 switch (dirp->d_ino) {
4675 case PR_PIDDIR:
4676 case PR_PROCDIR:
4677 case PR_PSINFO:
4678 case PR_USAGE:
4679 break;
4680 default:
4681 continue;
4684 bcopy(dirp, &dirent, sizeof (prdirent_t));
4685 if (dirent.d_ino == PR_PROCDIR)
4686 dirent.d_ino = PRROOTINO;
4687 else
4688 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
4689 dirent.d_ino);
4690 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
4691 UIO_READ, uiop)) != 0)
4692 return (error);
4694 out:
4695 if (eofp)
4696 *eofp = (uiop->uio_offset >= sizeof (piddir));
4697 return (0);
4700 static void
4701 rebuild_objdir(struct as *as)
4703 struct seg *seg;
4704 vnode_t *vp;
4705 vattr_t vattr;
4706 vnode_t **dir;
4707 ulong_t nalloc;
4708 ulong_t nentries;
4709 int i, j;
4710 ulong_t nold, nnew;
4712 ASSERT(AS_WRITE_HELD(as));
4714 if (as->a_updatedir == 0 && as->a_objectdir != NULL)
4715 return;
4716 as->a_updatedir = 0;
4718 if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
4719 (seg = AS_SEGFIRST(as)) == NULL) /* can't happen? */
4720 return;
4723 * Allocate space for the new object directory.
4724 * (This is usually about two times too many entries.)
4726 nalloc = (nalloc + 0xf) & ~0xf; /* multiple of 16 */
4727 dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
4729 /* fill in the new directory with desired entries */
4730 nentries = 0;
4731 do {
4732 vattr.va_mask = AT_FSID|AT_NODEID;
4733 if (seg->s_ops == &segvn_ops &&
4734 segop_getvp(seg, seg->s_base, &vp) == 0 &&
4735 vp != NULL && vp->v_type == VREG &&
4736 fop_getattr(vp, &vattr, 0, CRED(), NULL) == 0) {
4737 for (i = 0; i < nentries; i++)
4738 if (vp == dir[i])
4739 break;
4740 if (i == nentries) {
4741 ASSERT(nentries < nalloc);
4742 dir[nentries++] = vp;
4745 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4747 if (as->a_objectdir == NULL) { /* first time */
4748 as->a_objectdir = dir;
4749 as->a_sizedir = nalloc;
4750 return;
4754 * Null out all of the defunct entries in the old directory.
4756 nold = 0;
4757 nnew = nentries;
4758 for (i = 0; i < as->a_sizedir; i++) {
4759 if ((vp = as->a_objectdir[i]) != NULL) {
4760 for (j = 0; j < nentries; j++) {
4761 if (vp == dir[j]) {
4762 dir[j] = NULL;
4763 nnew--;
4764 break;
4767 if (j == nentries)
4768 as->a_objectdir[i] = NULL;
4769 else
4770 nold++;
4774 if (nold + nnew > as->a_sizedir) {
4776 * Reallocate the old directory to have enough
4777 * space for the old and new entries combined.
4778 * Round up to the next multiple of 16.
4780 ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
4781 vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
4782 KM_SLEEP);
4783 bcopy(as->a_objectdir, newdir,
4784 as->a_sizedir * sizeof (vnode_t *));
4785 kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
4786 as->a_objectdir = newdir;
4787 as->a_sizedir = newsize;
4791 * Move all new entries to the old directory and
4792 * deallocate the space used by the new directory.
4794 if (nnew) {
4795 for (i = 0, j = 0; i < nentries; i++) {
4796 if ((vp = dir[i]) == NULL)
4797 continue;
4798 for (; j < as->a_sizedir; j++) {
4799 if (as->a_objectdir[j] != NULL)
4800 continue;
4801 as->a_objectdir[j++] = vp;
4802 break;
4806 kmem_free(dir, nalloc * sizeof (vnode_t *));
4810 * Return the vnode from a slot in the process's object directory.
4811 * The caller must have locked the process's address space.
4812 * The only caller is below, in pr_readdir_objectdir().
4814 static vnode_t *
4815 obj_entry(struct as *as, int slot)
4817 ASSERT(AS_LOCK_HELD(as));
4818 if (as->a_objectdir == NULL)
4819 return (NULL);
4820 ASSERT(slot < as->a_sizedir);
4821 return (as->a_objectdir[slot]);
4824 /* ARGSUSED */
4825 static int
4826 pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4828 gfs_readdir_state_t gstate;
4829 int error, eof = 0;
4830 offset_t n;
4831 int pslot;
4832 size_t objdirsize;
4833 proc_t *p;
4834 struct as *as;
4835 vnode_t *vp;
4837 ASSERT(pnp->pr_type == PR_OBJECTDIR);
4839 if ((error = prlock(pnp, ZNO)) != 0)
4840 return (error);
4841 p = pnp->pr_common->prc_proc;
4842 pslot = p->p_slot;
4845 * We drop p_lock before grabbing the address space lock
4846 * in order to avoid a deadlock with the clock thread.
4847 * The process will not disappear and its address space
4848 * will not change because it is marked P_PR_LOCK.
4850 mutex_exit(&p->p_lock);
4852 if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
4853 pmkino(0, pslot, PR_PIDDIR),
4854 pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
4855 mutex_enter(&p->p_lock);
4856 prunlock(pnp);
4857 return (error);
4860 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4861 as = NULL;
4862 objdirsize = 0;
4866 * Loop until user's request is satisfied or until
4867 * all mapped objects have been examined. Cannot hold
4868 * the address space lock for the following call as
4869 * gfs_readdir_pred() utimately causes a call to uiomove().
4871 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
4872 vattr_t vattr;
4873 char str[64];
4876 * Set the correct size of the directory just
4877 * in case the process has changed it's address
4878 * space via mmap/munmap calls.
4880 if (as != NULL) {
4881 AS_LOCK_ENTER(as, RW_WRITER);
4882 if (as->a_updatedir)
4883 rebuild_objdir(as);
4884 objdirsize = as->a_sizedir;
4888 * Find next object.
4890 vattr.va_mask = AT_FSID | AT_NODEID;
4891 while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
4892 (fop_getattr(vp, &vattr, 0, CRED(), NULL)
4893 != 0))) {
4894 vattr.va_mask = AT_FSID | AT_NODEID;
4895 n++;
4898 if (as != NULL)
4899 AS_LOCK_EXIT(as);
4902 * Stop when all objects have been reported.
4904 if (n >= objdirsize) {
4905 eof = 1;
4906 break;
4909 if (vp == p->p_exec)
4910 (void) strcpy(str, "a.out");
4911 else
4912 pr_object_name(str, vp, &vattr);
4914 error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
4915 str, 0);
4917 if (error)
4918 break;
4921 mutex_enter(&p->p_lock);
4922 prunlock(pnp);
4924 return (gfs_readdir_fini(&gstate, error, eofp, eof));
4927 /* ARGSUSED */
4928 static int
4929 pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4931 gfs_readdir_state_t gstate;
4932 int error, eof = 0;
4933 offset_t tslot;
4934 proc_t *p;
4935 int pslot;
4936 lwpdir_t *lwpdir;
4937 int lwpdirsize;
4939 ASSERT(pnp->pr_type == PR_LWPDIR);
4941 p = pr_p_lock(pnp);
4942 mutex_exit(&pr_pidlock);
4943 if (p == NULL)
4944 return (ENOENT);
4945 ASSERT(p == pnp->pr_common->prc_proc);
4946 pslot = p->p_slot;
4947 lwpdir = p->p_lwpdir;
4948 lwpdirsize = p->p_lwpdir_sz;
4951 * Drop p->p_lock so we can safely do uiomove().
4952 * The lwp directory will not change because
4953 * we have the process locked with P_PR_LOCK.
4955 mutex_exit(&p->p_lock);
4958 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
4959 pmkino(0, pslot, PR_PIDDIR),
4960 pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
4961 mutex_enter(&p->p_lock);
4962 prunlock(pnp);
4963 return (error);
4967 * Loop until user's request is satisfied or until all lwps
4968 * have been examined.
4970 while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
4971 lwpent_t *lep;
4972 uint_t tid;
4975 * Find next LWP.
4977 while (tslot < lwpdirsize &&
4978 ((lep = lwpdir[tslot].ld_entry) == NULL))
4979 tslot++;
4981 * Stop when all lwps have been reported.
4983 if (tslot >= lwpdirsize) {
4984 eof = 1;
4985 break;
4988 tid = lep->le_lwpid;
4989 error = gfs_readdir_emitn(&gstate, uiop, tslot,
4990 pmkino(tslot, pslot, PR_LWPIDDIR), tid);
4991 if (error)
4992 break;
4995 mutex_enter(&p->p_lock);
4996 prunlock(pnp);
4998 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5001 /* ARGSUSED */
5002 static int
5003 pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5005 prcommon_t *pcp = pnp->pr_common;
5006 int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
5007 prdirent_t dirent;
5008 prdirent_t *dirp;
5009 offset_t off;
5010 int error;
5011 int pslot;
5012 int tslot;
5014 ASSERT(pnp->pr_type == PR_LWPIDDIR);
5016 if (uiop->uio_offset < 0 ||
5017 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
5018 uiop->uio_resid < sizeof (prdirent_t))
5019 return (EINVAL);
5020 if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
5021 return (ENOENT);
5022 if (uiop->uio_offset >= sizeof (lwpiddir))
5023 goto out;
5026 * Loop until user's request is satisfied, omitting some files
5027 * along the way if the lwp is a zombie and also depending
5028 * on the data model of the process.
5030 pslot = pcp->prc_slot;
5031 tslot = pcp->prc_tslot;
5032 for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
5033 uiop->uio_resid >= sizeof (prdirent_t) &&
5034 dirp < &lwpiddir[NLWPIDDIRFILES+2];
5035 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5036 off = uiop->uio_offset;
5037 if (zombie) {
5038 switch (dirp->d_ino) {
5039 case PR_LWPIDDIR:
5040 case PR_LWPDIR:
5041 case PR_LWPSINFO:
5042 break;
5043 default:
5044 continue;
5047 bcopy(dirp, &dirent, sizeof (prdirent_t));
5048 if (dirent.d_ino == PR_LWPDIR)
5049 dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5050 else
5051 dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5052 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5053 UIO_READ, uiop)) != 0)
5054 return (error);
5056 out:
5057 if (eofp)
5058 *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5059 return (0);
5062 /* ARGSUSED */
5063 static int
5064 pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5066 gfs_readdir_state_t gstate;
5067 int error, eof = 0;
5068 offset_t n;
5069 proc_t *p;
5070 int pslot;
5071 int fddirsize;
5072 uf_info_t *fip;
5074 ASSERT(pnp->pr_type == PR_FDDIR);
5076 if ((error = prlock(pnp, ZNO)) != 0)
5077 return (error);
5078 p = pnp->pr_common->prc_proc;
5079 pslot = p->p_slot;
5080 fip = P_FINFO(p);
5081 mutex_exit(&p->p_lock);
5083 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5084 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
5085 mutex_enter(&p->p_lock);
5086 prunlock(pnp);
5087 return (error);
5090 mutex_enter(&fip->fi_lock);
5091 if ((p->p_flag & SSYS) || p->p_as == &kas)
5092 fddirsize = 0;
5093 else
5094 fddirsize = fip->fi_nfiles;
5097 * Loop until user's request is satisfied or until
5098 * all file descriptors have been examined.
5100 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5102 * Find next fd.
5104 while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5105 n++;
5107 * Stop when all fds have been reported.
5109 if (n >= fddirsize) {
5110 eof = 1;
5111 break;
5114 error = gfs_readdir_emitn(&gstate, uiop, n,
5115 pmkino(n, pslot, PR_FD), n);
5116 if (error)
5117 break;
5120 mutex_exit(&fip->fi_lock);
5121 mutex_enter(&p->p_lock);
5122 prunlock(pnp);
5124 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5127 /* ARGSUSED */
5128 static int
5129 pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5131 longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5132 dirent64_t *dirent = (dirent64_t *)bp;
5133 int reclen;
5134 ssize_t oresid;
5135 offset_t off, idx;
5136 int error = 0;
5137 proc_t *p;
5138 int fd, obj;
5139 int pslot;
5140 int fddirsize;
5141 uf_info_t *fip;
5142 struct as *as = NULL;
5143 size_t objdirsize;
5144 vattr_t vattr;
5145 vnode_t *vp;
5147 ASSERT(pnp->pr_type == PR_PATHDIR);
5149 if (uiop->uio_offset < 0 ||
5150 uiop->uio_resid <= 0 ||
5151 (uiop->uio_offset % PRSDSIZE) != 0)
5152 return (EINVAL);
5153 oresid = uiop->uio_resid;
5154 bzero(bp, sizeof (bp));
5156 if ((error = prlock(pnp, ZNO)) != 0)
5157 return (error);
5158 p = pnp->pr_common->prc_proc;
5159 fip = P_FINFO(p);
5160 pslot = p->p_slot;
5161 mutex_exit(&p->p_lock);
5163 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5164 as = NULL;
5165 objdirsize = 0;
5166 } else {
5167 AS_LOCK_ENTER(as, RW_WRITER);
5168 if (as->a_updatedir)
5169 rebuild_objdir(as);
5170 objdirsize = as->a_sizedir;
5171 AS_LOCK_EXIT(as);
5172 as = NULL;
5175 mutex_enter(&fip->fi_lock);
5176 if ((p->p_flag & SSYS) || p->p_as == &kas)
5177 fddirsize = 0;
5178 else
5179 fddirsize = fip->fi_nfiles;
5181 for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
5183 * There are 4 special files in the path directory: ".", "..",
5184 * "root", and "cwd". We handle those specially here.
5186 off = uiop->uio_offset;
5187 idx = off / PRSDSIZE;
5188 if (off == 0) { /* "." */
5189 dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
5190 dirent->d_name[0] = '.';
5191 dirent->d_name[1] = '\0';
5192 reclen = DIRENT64_RECLEN(1);
5193 } else if (idx == 1) { /* ".." */
5194 dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
5195 dirent->d_name[0] = '.';
5196 dirent->d_name[1] = '.';
5197 dirent->d_name[2] = '\0';
5198 reclen = DIRENT64_RECLEN(2);
5199 } else if (idx == 2) { /* "root" */
5200 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5201 (void) strcpy(dirent->d_name, "root");
5202 reclen = DIRENT64_RECLEN(4);
5203 } else if (idx == 3) { /* "cwd" */
5204 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5205 (void) strcpy(dirent->d_name, "cwd");
5206 reclen = DIRENT64_RECLEN(3);
5207 } else if (idx < 4 + fddirsize) {
5209 * In this case, we have one of the file descriptors.
5211 fd = idx - 4;
5212 if (fip->fi_list[fd].uf_file == NULL)
5213 continue;
5214 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5215 (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
5216 reclen = DIRENT64_RECLEN(PLNSIZ);
5217 } else if (idx < 4 + fddirsize + objdirsize) {
5218 if (fip != NULL) {
5219 mutex_exit(&fip->fi_lock);
5220 fip = NULL;
5224 * We drop p_lock before grabbing the address space lock
5225 * in order to avoid a deadlock with the clock thread.
5226 * The process will not disappear and its address space
5227 * will not change because it is marked P_PR_LOCK.
5229 if (as == NULL) {
5230 as = p->p_as;
5231 AS_LOCK_ENTER(as, RW_WRITER);
5234 if (as->a_updatedir) {
5235 rebuild_objdir(as);
5236 objdirsize = as->a_sizedir;
5239 obj = idx - 4 - fddirsize;
5240 if ((vp = obj_entry(as, obj)) == NULL)
5241 continue;
5242 vattr.va_mask = AT_FSID|AT_NODEID;
5243 if (fop_getattr(vp, &vattr, 0, CRED(), NULL) != 0)
5244 continue;
5245 if (vp == p->p_exec)
5246 (void) strcpy(dirent->d_name, "a.out");
5247 else
5248 pr_object_name(dirent->d_name, vp, &vattr);
5249 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5250 reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
5251 } else {
5252 break;
5255 dirent->d_off = uiop->uio_offset + PRSDSIZE;
5256 dirent->d_reclen = (ushort_t)reclen;
5257 if (reclen > uiop->uio_resid) {
5259 * Error if no entries have been returned yet.
5261 if (uiop->uio_resid == oresid)
5262 error = EINVAL;
5263 break;
5266 * Drop the address space lock to do the uiomove().
5268 if (as != NULL)
5269 AS_LOCK_EXIT(as);
5271 error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
5272 if (as != NULL)
5273 AS_LOCK_ENTER(as, RW_WRITER);
5275 if (error)
5276 break;
5279 if (error == 0 && eofp)
5280 *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
5282 if (fip != NULL)
5283 mutex_exit(&fip->fi_lock);
5284 if (as != NULL)
5285 AS_LOCK_EXIT(as);
5286 mutex_enter(&p->p_lock);
5287 prunlock(pnp);
5288 return (error);
5291 static int
5292 pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
5294 proc_t *p;
5295 int pslot, tslot;
5296 gfs_readdir_state_t gstate;
5297 int error, eof = 0;
5298 offset_t n;
5300 ASSERT(pnp->pr_type == PR_TMPLDIR);
5302 if ((error = prlock(pnp, ZNO)) != 0)
5303 return (error);
5304 p = pnp->pr_common->prc_proc;
5305 pslot = pnp->pr_common->prc_slot;
5306 tslot = pnp->pr_common->prc_tslot;
5307 mutex_exit(&p->p_lock);
5309 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5310 pmkino(tslot, pslot, PR_LWPDIR),
5311 pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
5312 mutex_enter(&p->p_lock);
5313 prunlock(pnp);
5314 return (error);
5317 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5319 * Check for an active template. Reading a directory's
5320 * contents is already racy, so we don't bother taking
5321 * any locks.
5323 while (n < ct_ntypes &&
5324 pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
5325 n++;
5327 * Stop when all types have been reported.
5329 if (n >= ct_ntypes) {
5330 eof = 1;
5331 break;
5334 * The pmkino invocation below will need to be updated
5335 * when we create our fifth contract type.
5337 ASSERT(ct_ntypes <= 4);
5338 error = gfs_readdir_emit(&gstate, uiop, n,
5339 pmkino((tslot << 2) | n, pslot, PR_TMPL),
5340 ct_types[n]->ct_type_name, 0);
5341 if (error)
5342 break;
5345 mutex_enter(&p->p_lock);
5346 prunlock(pnp);
5348 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5351 static int
5352 pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5354 proc_t *p;
5355 int pslot;
5356 gfs_readdir_state_t gstate;
5357 int error, eof = 0;
5358 offset_t n;
5359 uint64_t zid;
5361 ASSERT(pnp->pr_type == PR_CTDIR);
5363 if ((error = prlock(pnp, ZNO)) != 0)
5364 return (error);
5365 p = pnp->pr_common->prc_proc;
5366 pslot = p->p_slot;
5367 mutex_exit(&p->p_lock);
5369 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5370 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
5371 mutex_enter(&p->p_lock);
5372 prunlock(pnp);
5373 return (error);
5376 zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
5377 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5378 id_t next = contract_plookup(p, n, zid);
5379 if (next == -1) {
5380 eof = 1;
5381 break;
5383 error = gfs_readdir_emitn(&gstate, uiop, next,
5384 pmkino(next, pslot, PR_CT), next);
5385 if (error)
5386 break;
5389 mutex_enter(&p->p_lock);
5390 prunlock(pnp);
5392 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5395 /* ARGSUSED */
5396 static int
5397 prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
5399 return (0);
5403 * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
5405 static void
5406 pr_list_unlink(vnode_t *pvp, vnode_t **listp)
5408 vnode_t *vp;
5409 prnode_t *pnp;
5411 while ((vp = *listp) != NULL) {
5412 pnp = VTOP(vp);
5413 if (vp == pvp) {
5414 *listp = pnp->pr_next;
5415 pnp->pr_next = NULL;
5416 break;
5418 listp = &pnp->pr_next;
5422 /* ARGSUSED */
5423 static void
5424 prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5426 prnode_t *pnp = VTOP(vp);
5427 prnodetype_t type = pnp->pr_type;
5428 proc_t *p;
5429 vnode_t *dp;
5430 vnode_t *ovp = NULL;
5431 prnode_t *opnp = NULL;
5433 switch (type) {
5434 case PR_OBJECT:
5435 case PR_FD:
5436 case PR_SELF:
5437 case PR_PATH:
5438 /* These are not linked into the usual lists */
5439 ASSERT(vp->v_count == 1);
5440 if ((dp = pnp->pr_parent) != NULL)
5441 VN_RELE(dp);
5442 prfreenode(pnp);
5443 return;
5444 default:
5445 break;
5448 mutex_enter(&pr_pidlock);
5449 if (pnp->pr_pcommon == NULL)
5450 p = NULL;
5451 else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
5452 mutex_enter(&p->p_lock);
5453 mutex_enter(&vp->v_lock);
5455 if (type == PR_PROCDIR || vp->v_count > 1) {
5456 VN_RELE_LOCKED(vp);
5457 mutex_exit(&vp->v_lock);
5458 if (p != NULL)
5459 mutex_exit(&p->p_lock);
5460 mutex_exit(&pr_pidlock);
5461 return;
5464 if ((dp = pnp->pr_parent) != NULL) {
5465 prnode_t *dpnp;
5467 switch (type) {
5468 case PR_PIDFILE:
5469 case PR_LWPIDFILE:
5470 case PR_OPAGEDATA:
5471 break;
5472 default:
5473 dpnp = VTOP(dp);
5474 mutex_enter(&dpnp->pr_mutex);
5475 if (dpnp->pr_files != NULL &&
5476 dpnp->pr_files[pnp->pr_index] == vp)
5477 dpnp->pr_files[pnp->pr_index] = NULL;
5478 mutex_exit(&dpnp->pr_mutex);
5479 break;
5481 pnp->pr_parent = NULL;
5484 ASSERT(vp->v_count == 1);
5487 * If we allocated an old /proc/pid node, free it too.
5489 if (pnp->pr_pidfile != NULL) {
5490 ASSERT(type == PR_PIDDIR);
5491 ovp = pnp->pr_pidfile;
5492 opnp = VTOP(ovp);
5493 ASSERT(opnp->pr_type == PR_PIDFILE);
5494 pnp->pr_pidfile = NULL;
5497 mutex_exit(&pr_pidlock);
5499 if (p != NULL) {
5501 * Remove the vnodes from the lists of
5502 * /proc vnodes for the process.
5504 int slot;
5506 switch (type) {
5507 case PR_PIDDIR:
5508 pr_list_unlink(vp, &p->p_trace);
5509 break;
5510 case PR_LWPIDDIR:
5511 if ((slot = pnp->pr_common->prc_tslot) != -1) {
5512 lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
5513 pr_list_unlink(vp, &lep->le_trace);
5515 break;
5516 default:
5517 pr_list_unlink(vp, &p->p_plist);
5518 break;
5520 if (ovp != NULL)
5521 pr_list_unlink(ovp, &p->p_plist);
5522 mutex_exit(&p->p_lock);
5525 mutex_exit(&vp->v_lock);
5527 if (type == PR_CT && pnp->pr_contract != NULL) {
5528 contract_rele(pnp->pr_contract);
5529 pnp->pr_contract = NULL;
5532 if (opnp != NULL)
5533 prfreenode(opnp);
5534 prfreenode(pnp);
5535 if (dp != NULL) {
5536 VN_RELE(dp);
5540 /* ARGSUSED */
5541 static int
5542 prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
5544 return (0);
5548 * We use the p_execdir member of proc_t to expand the %d token in core file
5549 * paths (the directory path for the executable that dumped core; see
5550 * coreadm(8) for details). We'd like gcore(1) to be able to expand %d in
5551 * the same way as core dumping from the kernel, but there's no convenient
5552 * and comprehensible way to export the path name for p_execdir. To solve
5553 * this, we try to find the actual path to the executable that was used. In
5554 * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
5555 * flag, and use that here to indicate that more work is needed beyond the
5556 * call to vnodetopath().
5558 static int
5559 prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
5561 proc_t *p;
5562 vnode_t *vp, *execvp, *vrootp;
5563 int ret;
5564 size_t len;
5565 dirent64_t *dp;
5566 size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
5567 char *dbuf;
5569 p = curproc;
5570 mutex_enter(&p->p_lock);
5571 if ((vrootp = PTOU(p)->u_rdir) == NULL)
5572 vrootp = rootdir;
5573 VN_HOLD(vrootp);
5574 mutex_exit(&p->p_lock);
5576 ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
5579 * If PR_AOUT isn't set, then we looked up the path for the vnode;
5580 * otherwise, we looked up the path for (what we believe to be) the
5581 * containing directory.
5583 if ((pnp->pr_flags & PR_AOUT) == 0) {
5584 VN_RELE(vrootp);
5585 return (ret);
5589 * Fail if there's a problem locking the process. This will only
5590 * occur if the process is changing so the information we would
5591 * report would already be invalid.
5593 if (prlock(pnp, ZNO) != 0) {
5594 VN_RELE(vrootp);
5595 return (EIO);
5598 p = pnp->pr_common->prc_proc;
5599 mutex_exit(&p->p_lock);
5601 execvp = p->p_exec;
5602 VN_HOLD(execvp);
5605 * If our initial lookup of the directory failed, fall back to
5606 * the path name information for p_exec.
5608 if (ret != 0) {
5609 mutex_enter(&p->p_lock);
5610 prunlock(pnp);
5611 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5612 VN_RELE(execvp);
5613 VN_RELE(vrootp);
5614 return (ret);
5617 len = strlen(buf);
5620 * We use u_comm as a guess for the last component of the full
5621 * executable path name. If there isn't going to be enough space
5622 * we fall back to using the p_exec so that we can have _an_
5623 * answer even if it's not perfect.
5625 if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
5626 buf[len] = '/';
5627 (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
5628 mutex_enter(&p->p_lock);
5629 prunlock(pnp);
5632 * Do a forward lookup of our u_comm guess.
5634 if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
5635 &vp, pnp->pr_realvp) == 0) {
5636 if (vn_compare(vp, execvp)) {
5637 VN_RELE(vp);
5638 VN_RELE(execvp);
5639 VN_RELE(vrootp);
5640 return (0);
5643 VN_RELE(vp);
5645 } else {
5646 mutex_enter(&p->p_lock);
5647 prunlock(pnp);
5650 dbuf = kmem_alloc(dlen, KM_SLEEP);
5653 * Try to find a matching vnode by iterating through the directory's
5654 * entries. If that fails, fall back to the path information for
5655 * p_exec.
5657 if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
5658 dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
5659 buf[len] = '/';
5660 (void) strcpy(buf + len + 1, dp->d_name);
5661 } else {
5662 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5665 kmem_free(dbuf, dlen);
5666 VN_RELE(execvp);
5667 VN_RELE(vrootp);
5669 return (ret);
5672 /* ARGSUSED */
5673 static int
5674 prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
5676 prnode_t *pnp = VTOP(vp);
5677 char *buf;
5678 int ret = EINVAL;
5679 char idbuf[16];
5680 int length, rlength;
5681 contract_t *ct;
5683 switch (pnp->pr_type) {
5684 case PR_SELF:
5685 (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
5686 ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
5687 break;
5688 case PR_OBJECT:
5689 case PR_FD:
5690 case PR_CURDIR:
5691 case PR_ROOTDIR:
5692 if (pnp->pr_realvp->v_type == VDIR)
5693 ret = 0;
5694 break;
5695 case PR_PATH:
5696 buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
5698 if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
5699 ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
5701 kmem_free(buf, MAXPATHLEN);
5702 break;
5703 case PR_CT:
5704 ASSERT(pnp->pr_contract != NULL);
5705 ct = pnp->pr_contract;
5706 length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
5707 strlen(ct->ct_type->ct_type_name);
5708 buf = kmem_alloc(length, KM_SLEEP);
5709 rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
5710 ct->ct_type->ct_type_name, ct->ct_id);
5711 ASSERT(rlength < length);
5712 ret = uiomove(buf, rlength, UIO_READ, uiop);
5713 kmem_free(buf, length);
5714 break;
5715 default:
5716 break;
5719 return (ret);
5722 /*ARGSUSED2*/
5723 static int
5724 prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
5726 prnode_t *pp1, *pp2;
5728 if (vp1 == vp2)
5729 return (1);
5731 if (!vn_matchops(vp1, &prvnodeops) || !vn_matchops(vp2, &prvnodeops))
5732 return (0);
5734 pp1 = VTOP(vp1);
5735 pp2 = VTOP(vp2);
5737 if (pp1->pr_type != pp2->pr_type)
5738 return (0);
5739 if (pp1->pr_type == PR_PROCDIR)
5740 return (1);
5741 if (pp1->pr_ino || pp2->pr_ino)
5742 return (pp2->pr_ino == pp1->pr_ino);
5744 if (pp1->pr_common == NULL || pp2->pr_common == NULL)
5745 return (0);
5747 return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
5748 pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
5751 static int
5752 prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
5754 vnode_t *rvp;
5756 if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
5757 vp = rvp;
5758 if (fop_realvp(vp, &rvp, ct) == 0)
5759 vp = rvp;
5762 *vpp = vp;
5763 return (0);
5767 * Return the answer requested to poll().
5768 * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
5769 * In addition, these have special meaning for /proc files:
5770 * POLLPRI process or lwp stopped on an event of interest
5771 * POLLERR /proc file descriptor is invalid
5772 * POLLHUP process or lwp has terminated
5774 /*ARGSUSED5*/
5775 static int
5776 prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
5777 pollhead_t **phpp, caller_context_t *ct)
5779 prnode_t *pnp = VTOP(vp);
5780 prcommon_t *pcp = pnp->pr_common;
5781 pollhead_t *php = &pcp->prc_pollhead;
5782 proc_t *p;
5783 short revents;
5784 int error;
5785 int lockstate;
5787 ASSERT(pnp->pr_type < PR_NFILES);
5790 * Support for old /proc interface.
5792 if (pnp->pr_pidfile != NULL) {
5793 vp = pnp->pr_pidfile;
5794 pnp = VTOP(vp);
5795 ASSERT(pnp->pr_type == PR_PIDFILE);
5796 ASSERT(pnp->pr_common == pcp);
5799 *reventsp = revents = 0;
5800 *phpp = (pollhead_t *)NULL;
5802 if (vp->v_type == VDIR) {
5803 *reventsp |= POLLNVAL;
5804 return (0);
5807 /* avoid deadlock with prnotify() */
5808 if (pollunlock(&lockstate) != 0) {
5809 *reventsp = POLLNVAL;
5810 return (0);
5813 if ((error = prlock(pnp, ZNO)) != 0) {
5814 pollrelock(lockstate);
5815 switch (error) {
5816 case ENOENT: /* process or lwp died */
5817 *reventsp = POLLHUP;
5818 error = 0;
5819 break;
5820 case EAGAIN: /* invalidated */
5821 *reventsp = POLLERR;
5822 error = 0;
5823 break;
5825 return (error);
5829 * We have the process marked locked (P_PR_LOCK) and we are holding
5830 * its p->p_lock. We want to unmark the process but retain
5831 * exclusive control w.r.t. other /proc controlling processes
5832 * before reacquiring the polling locks.
5834 * prunmark() does this for us. It unmarks the process
5835 * but retains p->p_lock so we still have exclusive control.
5836 * We will drop p->p_lock at the end to relinquish control.
5838 * We cannot call prunlock() at the end to relinquish control
5839 * because prunlock(), like prunmark(), may drop and reacquire
5840 * p->p_lock and that would lead to a lock order violation
5841 * w.r.t. the polling locks we are about to reacquire.
5843 p = pcp->prc_proc;
5844 ASSERT(p != NULL);
5845 prunmark(p);
5847 pollrelock(lockstate); /* reacquire dropped poll locks */
5849 if ((p->p_flag & SSYS) || p->p_as == &kas)
5850 revents = POLLNVAL;
5851 else {
5852 short ev;
5854 if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
5855 revents |= ev;
5857 * POLLWRNORM (same as POLLOUT) really should not be
5858 * used to indicate that the process or lwp stopped.
5859 * However, USL chose to use POLLWRNORM rather than
5860 * POLLPRI to indicate this, so we just accept either
5861 * requested event to indicate stopped. (grr...)
5863 if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
5864 kthread_t *t;
5866 if (pcp->prc_flags & PRC_LWP) {
5867 t = pcp->prc_thread;
5868 ASSERT(t != NULL);
5869 thread_lock(t);
5870 } else {
5871 t = prchoose(p); /* returns locked t */
5872 ASSERT(t != NULL);
5875 if (ISTOPPED(t) || VSTOPPED(t))
5876 revents |= ev;
5877 thread_unlock(t);
5881 *reventsp = revents;
5882 if ((!anyyet && revents == 0) || (events & POLLET)) {
5884 * Arrange to wake up the polling lwp when
5885 * the target process/lwp stops or terminates
5886 * or when the file descriptor becomes invalid.
5888 pcp->prc_flags |= PRC_POLL;
5889 *phpp = php;
5891 mutex_exit(&p->p_lock);
5892 return (0);
5895 /* in prioctl.c */
5896 extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
5897 caller_context_t *);
5900 * /proc vnode operations vector
5902 const struct vnodeops prvnodeops = {
5903 .vnop_name = "procfs",
5904 .vop_open = propen,
5905 .vop_close = prclose,
5906 .vop_read = prread,
5907 .vop_write = prwrite,
5908 .vop_ioctl = prioctl,
5909 .vop_getattr = prgetattr,
5910 .vop_access = praccess,
5911 .vop_lookup = prlookup,
5912 .vop_create = prcreate,
5913 .vop_readdir = prreaddir,
5914 .vop_readlink = prreadlink,
5915 .vop_fsync = prfsync,
5916 .vop_inactive = prinactive,
5917 .vop_seek = prseek,
5918 .vop_cmp = prcmp,
5919 .vop_frlock = fs_nosys,
5920 .vop_realvp = prrealvp,
5921 .vop_poll = prpoll,
5922 .vop_dispose = fs_nodispose,
5923 .vop_shrlock = fs_nosys,