8158 Want named threads API
[unleashed.git] / usr / src / uts / common / fs / proc / prvnops.c
blob2cf007c42ca391db655b80b418941f537bb54c1e
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) 2018, 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/vfs_opreg.h>
57 #include <sys/gfs.h>
58 #include <sys/vnode.h>
59 #include <sys/fault.h>
60 #include <sys/syscall.h>
61 #include <sys/procfs.h>
62 #include <sys/atomic.h>
63 #include <sys/cmn_err.h>
64 #include <sys/contract_impl.h>
65 #include <sys/ctfs.h>
66 #include <sys/avl.h>
67 #include <sys/ctype.h>
68 #include <fs/fs_subr.h>
69 #include <vm/rm.h>
70 #include <vm/as.h>
71 #include <vm/seg.h>
72 #include <vm/seg_vn.h>
73 #include <vm/hat.h>
74 #include <fs/proc/prdata.h>
75 #if defined(__sparc)
76 #include <sys/regset.h>
77 #endif
78 #if defined(__x86)
79 #include <sys/sysi86.h>
80 #endif
83 * Created by prinit.
85 vnodeops_t *prvnodeops;
88 * Directory characteristics (patterned after the s5 file system).
90 #define PRROOTINO 2
92 #define PRDIRSIZE 14
93 struct prdirect {
94 ushort_t d_ino;
95 char d_name[PRDIRSIZE];
98 #define PRSDSIZE (sizeof (struct prdirect))
101 * Directory characteristics.
103 typedef struct prdirent {
104 ino64_t d_ino; /* "inode number" of entry */
105 off64_t d_off; /* offset of disk directory entry */
106 unsigned short d_reclen; /* length of this record */
107 char d_name[14]; /* name of file */
108 } prdirent_t;
111 * Contents of a /proc/<pid> directory.
112 * Reuse d_ino field for the /proc file type.
114 static prdirent_t piddir[] = {
115 { PR_PIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
116 "." },
117 { PR_PROCDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
118 ".." },
119 { PR_AS, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
120 "as" },
121 { PR_CTL, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
122 "ctl" },
123 { PR_STATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
124 "status" },
125 { PR_LSTATUS, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
126 "lstatus" },
127 { PR_PSINFO, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
128 "psinfo" },
129 { PR_LPSINFO, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
130 "lpsinfo" },
131 { PR_MAP, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
132 "map" },
133 { PR_RMAP, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
134 "rmap" },
135 { PR_XMAP, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
136 "xmap" },
137 { PR_CRED, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
138 "cred" },
139 { PR_SIGACT, 13 * sizeof (prdirent_t), sizeof (prdirent_t),
140 "sigact" },
141 { PR_AUXV, 14 * sizeof (prdirent_t), sizeof (prdirent_t),
142 "auxv" },
143 { PR_USAGE, 15 * sizeof (prdirent_t), sizeof (prdirent_t),
144 "usage" },
145 { PR_LUSAGE, 16 * sizeof (prdirent_t), sizeof (prdirent_t),
146 "lusage" },
147 { PR_PAGEDATA, 17 * sizeof (prdirent_t), sizeof (prdirent_t),
148 "pagedata" },
149 { PR_WATCH, 18 * sizeof (prdirent_t), sizeof (prdirent_t),
150 "watch" },
151 { PR_CURDIR, 19 * sizeof (prdirent_t), sizeof (prdirent_t),
152 "cwd" },
153 { PR_ROOTDIR, 20 * sizeof (prdirent_t), sizeof (prdirent_t),
154 "root" },
155 { PR_FDDIR, 21 * sizeof (prdirent_t), sizeof (prdirent_t),
156 "fd" },
157 { PR_OBJECTDIR, 22 * sizeof (prdirent_t), sizeof (prdirent_t),
158 "object" },
159 { PR_LWPDIR, 23 * sizeof (prdirent_t), sizeof (prdirent_t),
160 "lwp" },
161 { PR_PRIV, 24 * sizeof (prdirent_t), sizeof (prdirent_t),
162 "priv" },
163 { PR_PATHDIR, 25 * sizeof (prdirent_t), sizeof (prdirent_t),
164 "path" },
165 { PR_CTDIR, 26 * sizeof (prdirent_t), sizeof (prdirent_t),
166 "contracts" },
167 { PR_SECFLAGS, 27 * sizeof (prdirent_t), sizeof (prdirent_t),
168 "secflags" },
169 #if defined(__x86)
170 { PR_LDT, 28 * sizeof (prdirent_t), sizeof (prdirent_t),
171 "ldt" },
172 #endif
175 #define NPIDDIRFILES (sizeof (piddir) / sizeof (piddir[0]) - 2)
178 * Contents of a /proc/<pid>/lwp/<lwpid> directory.
180 static prdirent_t lwpiddir[] = {
181 { PR_LWPIDDIR, 1 * sizeof (prdirent_t), sizeof (prdirent_t),
182 "." },
183 { PR_LWPDIR, 2 * sizeof (prdirent_t), sizeof (prdirent_t),
184 ".." },
185 { PR_LWPCTL, 3 * sizeof (prdirent_t), sizeof (prdirent_t),
186 "lwpctl" },
187 { PR_LWPNAME, 4 * sizeof (prdirent_t), sizeof (prdirent_t),
188 "lwpname" },
189 { PR_LWPSTATUS, 5 * sizeof (prdirent_t), sizeof (prdirent_t),
190 "lwpstatus" },
191 { PR_LWPSINFO, 6 * sizeof (prdirent_t), sizeof (prdirent_t),
192 "lwpsinfo" },
193 { PR_LWPUSAGE, 7 * sizeof (prdirent_t), sizeof (prdirent_t),
194 "lwpusage" },
195 { PR_XREGS, 8 * sizeof (prdirent_t), sizeof (prdirent_t),
196 "xregs" },
197 { PR_TMPLDIR, 9 * sizeof (prdirent_t), sizeof (prdirent_t),
198 "templates" },
199 { PR_SPYMASTER, 10 * sizeof (prdirent_t), sizeof (prdirent_t),
200 "spymaster" },
201 #if defined(__sparc)
202 { PR_GWINDOWS, 11 * sizeof (prdirent_t), sizeof (prdirent_t),
203 "gwindows" },
204 { PR_ASRS, 12 * sizeof (prdirent_t), sizeof (prdirent_t),
205 "asrs" },
206 #endif
209 #define NLWPIDDIRFILES (sizeof (lwpiddir) / sizeof (lwpiddir[0]) - 2)
212 * Span of entries in the array files (lstatus, lpsinfo, lusage).
213 * We make the span larger than the size of the structure on purpose,
214 * to make sure that programs cannot use the structure size by mistake.
215 * Align _ILP32 structures at 8 bytes, _LP64 structures at 16 bytes.
217 #ifdef _LP64
218 #define LSPAN(type) (round16(sizeof (type)) + 16)
219 #define LSPAN32(type) (round8(sizeof (type)) + 8)
220 #else
221 #define LSPAN(type) (round8(sizeof (type)) + 8)
222 #endif
224 static void rebuild_objdir(struct as *);
225 static void prfreecommon(prcommon_t *);
226 static int praccess(vnode_t *, int, int, cred_t *, caller_context_t *);
228 static int
229 propen(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
231 vnode_t *vp = *vpp;
232 prnode_t *pnp = VTOP(vp);
233 prcommon_t *pcp = pnp->pr_pcommon;
234 prnodetype_t type = pnp->pr_type;
235 vnode_t *rvp;
236 vtype_t vtype;
237 proc_t *p;
238 int error = 0;
239 prnode_t *npnp = NULL;
242 * Nothing to do for the /proc directory itself.
244 if (type == PR_PROCDIR)
245 return (0);
248 * If we are opening an underlying mapped object, reject opens
249 * for writing regardless of the objects's access modes.
250 * If we are opening a file in the /proc/pid/fd directory,
251 * reject the open for any but a regular file or directory.
252 * Just do it if we are opening the current or root directory.
254 switch (type) {
255 case PR_OBJECT:
256 case PR_FD:
257 case PR_CURDIR:
258 case PR_ROOTDIR:
259 rvp = pnp->pr_realvp;
260 vtype = rvp->v_type;
261 if ((type == PR_OBJECT && (flag & FWRITE)) ||
262 (type == PR_FD && vtype != VREG && vtype != VDIR))
263 error = EACCES;
264 else {
266 * Need to hold rvp since VOP_OPEN() may release it.
268 VN_HOLD(rvp);
269 error = VOP_OPEN(&rvp, flag, cr, ct);
270 if (error) {
271 VN_RELE(rvp);
272 } else {
273 *vpp = rvp;
274 VN_RELE(vp);
277 return (error);
278 default:
279 break;
283 * If we are opening the pagedata file, allocate a prnode now
284 * to avoid calling kmem_alloc() while holding p->p_lock.
286 if (type == PR_PAGEDATA || type == PR_OPAGEDATA)
287 npnp = prgetnode(vp, type);
290 * If the process exists, lock it now.
291 * Otherwise we have a race condition with prclose().
293 p = pr_p_lock(pnp);
294 mutex_exit(&pr_pidlock);
295 if (p == NULL) {
296 if (npnp != NULL)
297 prfreenode(npnp);
298 return (ENOENT);
300 ASSERT(p == pcp->prc_proc);
301 ASSERT(p->p_proc_flag & P_PR_LOCK);
304 * Maintain a count of opens for write. Allow exactly one
305 * O_WRITE|O_EXCL request and fail subsequent ones.
306 * Don't fail opens of old (bletch!) /proc lwp files.
307 * Special case for open by the process itself:
308 * Always allow the open by self and discount this
309 * open for other opens for writing.
311 if (flag & FWRITE) {
312 if (p == curproc) {
313 pcp->prc_selfopens++;
314 pnp->pr_flags |= PR_ISSELF;
315 } else if (type == PR_LWPIDFILE) {
316 /* EMPTY */;
317 } else if (flag & FEXCL) {
318 if (pcp->prc_writers > pcp->prc_selfopens) {
319 error = EBUSY;
320 goto out;
322 /* semantic for old /proc interface */
323 if (type == PR_PIDDIR)
324 pcp->prc_flags |= PRC_EXCL;
325 } else if (pcp->prc_flags & PRC_EXCL) {
326 ASSERT(pcp->prc_writers > pcp->prc_selfopens);
327 error = secpolicy_proc_excl_open(cr);
328 if (error)
329 goto out;
331 pcp->prc_writers++;
333 * The vnode may have become invalid between the
334 * VOP_LOOKUP() of the /proc vnode and the VOP_OPEN().
335 * If so, do now what prinvalidate() should have done.
337 if ((pnp->pr_flags & PR_INVAL) ||
338 (type == PR_PIDDIR &&
339 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
340 if (p != curproc)
341 pcp->prc_selfopens++;
342 ASSERT(pcp->prc_selfopens <= pcp->prc_writers);
343 if (pcp->prc_selfopens == pcp->prc_writers)
344 pcp->prc_flags &= ~PRC_EXCL;
349 * If this is a large file open, indicate that in our flags -- some
350 * procfs structures are not off_t-neutral (e.g., priovec_t), and
351 * the open will need to be differentiated where 32-bit processes
352 * pass these structures across the user/kernel boundary.
354 if (flag & FOFFMAX)
355 pnp->pr_flags |= PR_OFFMAX;
358 * Do file-specific things.
360 switch (type) {
361 default:
362 break;
363 case PR_PAGEDATA:
364 case PR_OPAGEDATA:
366 * Enable data collection for page data file;
367 * get unique id from the hat layer.
370 int id;
373 * Drop p->p_lock to call hat_startstat()
375 mutex_exit(&p->p_lock);
376 if ((p->p_flag & SSYS) || p->p_as == &kas ||
377 (id = hat_startstat(p->p_as)) == -1) {
378 mutex_enter(&p->p_lock);
379 error = ENOMEM;
380 } else if (pnp->pr_hatid == 0) {
381 mutex_enter(&p->p_lock);
382 pnp->pr_hatid = (uint_t)id;
383 } else {
384 mutex_enter(&p->p_lock);
386 * Use our newly allocated prnode.
388 npnp->pr_hatid = (uint_t)id;
390 * prgetnode() initialized most of the prnode.
391 * Duplicate the remainder.
393 npnp->pr_ino = pnp->pr_ino;
394 npnp->pr_common = pnp->pr_common;
395 npnp->pr_pcommon = pnp->pr_pcommon;
396 npnp->pr_parent = pnp->pr_parent;
397 VN_HOLD(npnp->pr_parent);
398 npnp->pr_index = pnp->pr_index;
400 npnp->pr_next = p->p_plist;
401 p->p_plist = PTOV(npnp);
403 VN_RELE(PTOV(pnp));
404 pnp = npnp;
405 npnp = NULL;
406 *vpp = PTOV(pnp);
409 break;
412 out:
413 prunlock(pnp);
415 if (npnp != NULL)
416 prfreenode(npnp);
417 return (error);
420 /* ARGSUSED */
421 static int
422 prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
423 caller_context_t *ct)
425 prnode_t *pnp = VTOP(vp);
426 prcommon_t *pcp = pnp->pr_pcommon;
427 prnodetype_t type = pnp->pr_type;
428 proc_t *p;
429 kthread_t *t;
430 user_t *up;
433 * Nothing to do for the /proc directory itself.
435 if (type == PR_PROCDIR)
436 return (0);
438 ASSERT(type != PR_OBJECT && type != PR_FD &&
439 type != PR_CURDIR && type != PR_ROOTDIR);
442 * If the process exists, lock it now.
443 * Otherwise we have a race condition with propen().
444 * Hold pr_pidlock across the reference to prc_selfopens,
445 * and prc_writers in case there is no process anymore,
446 * to cover the case of concurrent calls to prclose()
447 * after the process has been reaped by freeproc().
449 p = pr_p_lock(pnp);
452 * There is nothing more to do until the last close of
453 * the file table entry except to clear the pr_owner
454 * field of the prnode and notify any waiters
455 * (their file descriptor may have just been closed).
457 if (count > 1) {
458 mutex_exit(&pr_pidlock);
459 if (pnp->pr_owner == curproc && !fisopen(vp))
460 pnp->pr_owner = NULL;
461 if (p != NULL) {
462 prnotify(vp);
463 prunlock(pnp);
465 return (0);
469 * Decrement the count of self-opens for writing.
470 * Decrement the total count of opens for writing.
471 * Cancel exclusive opens when only self-opens remain.
473 if (flag & FWRITE) {
475 * prc_selfopens also contains the count of
476 * invalid writers. See prinvalidate().
478 if ((pnp->pr_flags & (PR_ISSELF|PR_INVAL)) ||
479 (type == PR_PIDDIR &&
480 (VTOP(pnp->pr_pidfile)->pr_flags & PR_INVAL))) {
481 ASSERT(pcp->prc_selfopens != 0);
482 --pcp->prc_selfopens;
484 ASSERT(pcp->prc_writers != 0);
485 if (--pcp->prc_writers == pcp->prc_selfopens)
486 pcp->prc_flags &= ~PRC_EXCL;
488 ASSERT(pcp->prc_writers >= pcp->prc_selfopens);
489 mutex_exit(&pr_pidlock);
490 if (pnp->pr_owner == curproc && !fisopen(vp))
491 pnp->pr_owner = NULL;
494 * If there is no process, there is nothing more to do.
496 if (p == NULL)
497 return (0);
499 ASSERT(p == pcp->prc_proc);
500 prnotify(vp); /* notify waiters */
503 * Do file-specific things.
505 switch (type) {
506 default:
507 break;
508 case PR_PAGEDATA:
509 case PR_OPAGEDATA:
511 * This is a page data file.
512 * Free the hat level statistics.
513 * Drop p->p_lock before calling hat_freestat().
515 mutex_exit(&p->p_lock);
516 if (p->p_as != &kas && pnp->pr_hatid != 0)
517 hat_freestat(p->p_as, pnp->pr_hatid);
518 mutex_enter(&p->p_lock);
519 pnp->pr_hatid = 0;
520 break;
524 * On last close of all writable file descriptors,
525 * perform run-on-last-close and/or kill-on-last-close logic.
526 * Can't do this is the /proc agent lwp still exists.
528 if (pcp->prc_writers == 0 &&
529 p->p_agenttp == NULL &&
530 !(pcp->prc_flags & PRC_DESTROY) &&
531 p->p_stat != SZOMB &&
532 (p->p_proc_flag & (P_PR_RUNLCL|P_PR_KILLCL))) {
533 int killproc;
536 * Cancel any watchpoints currently in effect.
537 * The process might disappear during this operation.
539 if (pr_cancel_watch(pnp) == NULL)
540 return (0);
542 * If any tracing flags are set, clear them.
544 if (p->p_proc_flag & P_PR_TRACE) {
545 up = PTOU(p);
546 premptyset(&up->u_entrymask);
547 premptyset(&up->u_exitmask);
548 up->u_systrap = 0;
550 premptyset(&p->p_sigmask);
551 premptyset(&p->p_fltmask);
552 killproc = (p->p_proc_flag & P_PR_KILLCL);
553 p->p_proc_flag &= ~(P_PR_RUNLCL|P_PR_KILLCL|P_PR_TRACE);
555 * Cancel any outstanding single-step requests.
557 if ((t = p->p_tlist) != NULL) {
559 * Drop p_lock because prnostep() touches the stack.
560 * The loop is safe because the process is P_PR_LOCK'd.
562 mutex_exit(&p->p_lock);
563 do {
564 prnostep(ttolwp(t));
565 } while ((t = t->t_forw) != p->p_tlist);
566 mutex_enter(&p->p_lock);
569 * Set runnable all lwps stopped by /proc.
571 if (killproc)
572 sigtoproc(p, NULL, SIGKILL);
573 else
574 allsetrun(p);
577 prunlock(pnp);
578 return (0);
582 * Array of read functions, indexed by /proc file type.
584 static int pr_read_inval(), pr_read_as(), pr_read_status(),
585 pr_read_lstatus(), pr_read_psinfo(), pr_read_lpsinfo(),
586 pr_read_map(), pr_read_rmap(), pr_read_xmap(),
587 pr_read_cred(), pr_read_sigact(), pr_read_auxv(),
588 #if defined(__x86)
589 pr_read_ldt(),
590 #endif
591 pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
592 pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
593 pr_read_lwpusage(), pr_read_lwpname(),
594 pr_read_xregs(), pr_read_priv(),
595 pr_read_spymaster(), pr_read_secflags(),
596 #if defined(__sparc)
597 pr_read_gwindows(), pr_read_asrs(),
598 #endif
599 pr_read_piddir(), pr_read_pidfile(), pr_read_opagedata();
601 static int (*pr_read_function[PR_NFILES])() = {
602 pr_read_inval, /* /proc */
603 pr_read_inval, /* /proc/self */
604 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
605 pr_read_as, /* /proc/<pid>/as */
606 pr_read_inval, /* /proc/<pid>/ctl */
607 pr_read_status, /* /proc/<pid>/status */
608 pr_read_lstatus, /* /proc/<pid>/lstatus */
609 pr_read_psinfo, /* /proc/<pid>/psinfo */
610 pr_read_lpsinfo, /* /proc/<pid>/lpsinfo */
611 pr_read_map, /* /proc/<pid>/map */
612 pr_read_rmap, /* /proc/<pid>/rmap */
613 pr_read_xmap, /* /proc/<pid>/xmap */
614 pr_read_cred, /* /proc/<pid>/cred */
615 pr_read_sigact, /* /proc/<pid>/sigact */
616 pr_read_auxv, /* /proc/<pid>/auxv */
617 #if defined(__x86)
618 pr_read_ldt, /* /proc/<pid>/ldt */
619 #endif
620 pr_read_usage, /* /proc/<pid>/usage */
621 pr_read_lusage, /* /proc/<pid>/lusage */
622 pr_read_pagedata, /* /proc/<pid>/pagedata */
623 pr_read_watch, /* /proc/<pid>/watch */
624 pr_read_inval, /* /proc/<pid>/cwd */
625 pr_read_inval, /* /proc/<pid>/root */
626 pr_read_inval, /* /proc/<pid>/fd */
627 pr_read_inval, /* /proc/<pid>/fd/nn */
628 pr_read_inval, /* /proc/<pid>/object */
629 pr_read_inval, /* /proc/<pid>/object/xxx */
630 pr_read_inval, /* /proc/<pid>/lwp */
631 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
632 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
633 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
634 pr_read_lwpstatus, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
635 pr_read_lwpsinfo, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
636 pr_read_lwpusage, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
637 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
638 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
639 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
640 pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */
641 #if defined(__sparc)
642 pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */
643 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
644 #endif
645 pr_read_priv, /* /proc/<pid>/priv */
646 pr_read_inval, /* /proc/<pid>/path */
647 pr_read_inval, /* /proc/<pid>/path/xxx */
648 pr_read_inval, /* /proc/<pid>/contracts */
649 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
650 pr_read_secflags, /* /proc/<pid>/secflags */
651 pr_read_pidfile, /* old process file */
652 pr_read_pidfile, /* old lwp file */
653 pr_read_opagedata, /* old pagedata file */
656 /* ARGSUSED */
657 static int
658 pr_read_inval(prnode_t *pnp, uio_t *uiop)
661 * No read() on any /proc directory, use getdents(2) instead.
662 * Cannot read a control file either.
663 * An underlying mapped object file cannot get here.
665 return (EINVAL);
668 static int
669 pr_uioread(void *base, long count, uio_t *uiop)
671 int error = 0;
673 ASSERT(count >= 0);
674 count -= uiop->uio_offset;
675 if (count > 0 && uiop->uio_offset >= 0) {
676 error = uiomove((char *)base + uiop->uio_offset,
677 count, UIO_READ, uiop);
680 return (error);
683 static int
684 pr_read_as(prnode_t *pnp, uio_t *uiop)
686 int error;
688 ASSERT(pnp->pr_type == PR_AS);
690 if ((error = prlock(pnp, ZNO)) == 0) {
691 proc_t *p = pnp->pr_common->prc_proc;
692 struct as *as = p->p_as;
695 * /proc I/O cannot be done to a system process.
696 * A 32-bit process cannot read a 64-bit process.
698 if ((p->p_flag & SSYS) || as == &kas) {
699 error = 0;
700 #ifdef _SYSCALL32_IMPL
701 } else if (curproc->p_model == DATAMODEL_ILP32 &&
702 PROCESS_NOT_32BIT(p)) {
703 error = EOVERFLOW;
704 #endif
705 } else {
707 * We don't hold p_lock over an i/o operation because
708 * that could lead to deadlock with the clock thread.
710 mutex_exit(&p->p_lock);
711 error = prusrio(p, UIO_READ, uiop, 0);
712 mutex_enter(&p->p_lock);
714 prunlock(pnp);
717 return (error);
720 static int
721 pr_read_status(prnode_t *pnp, uio_t *uiop)
723 pstatus_t *sp;
724 int error;
726 ASSERT(pnp->pr_type == PR_STATUS);
729 * We kmem_alloc() the pstatus structure because
730 * it is so big it might blow the kernel stack.
732 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
733 if ((error = prlock(pnp, ZNO)) == 0) {
734 prgetstatus(pnp->pr_common->prc_proc, sp, VTOZONE(PTOV(pnp)));
735 prunlock(pnp);
736 error = pr_uioread(sp, sizeof (*sp), uiop);
738 kmem_free(sp, sizeof (*sp));
739 return (error);
742 static int
743 pr_read_lstatus(prnode_t *pnp, uio_t *uiop)
745 proc_t *p;
746 kthread_t *t;
747 lwpdir_t *ldp;
748 size_t size;
749 prheader_t *php;
750 lwpstatus_t *sp;
751 int error;
752 int nlwp;
753 int i;
755 ASSERT(pnp->pr_type == PR_LSTATUS);
757 if ((error = prlock(pnp, ZNO)) != 0)
758 return (error);
759 p = pnp->pr_common->prc_proc;
760 nlwp = p->p_lwpcnt;
761 size = sizeof (prheader_t) + nlwp * LSPAN(lwpstatus_t);
763 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
764 mutex_exit(&p->p_lock);
765 php = kmem_zalloc(size, KM_SLEEP);
766 mutex_enter(&p->p_lock);
767 /* p->p_lwpcnt can't change while process is locked */
768 ASSERT(nlwp == p->p_lwpcnt);
770 php->pr_nent = nlwp;
771 php->pr_entsize = LSPAN(lwpstatus_t);
773 sp = (lwpstatus_t *)(php + 1);
774 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
775 if (ldp->ld_entry == NULL ||
776 (t = ldp->ld_entry->le_thread) == NULL)
777 continue;
778 prgetlwpstatus(t, sp, VTOZONE(PTOV(pnp)));
779 sp = (lwpstatus_t *)((caddr_t)sp + LSPAN(lwpstatus_t));
781 prunlock(pnp);
783 error = pr_uioread(php, size, uiop);
784 kmem_free(php, size);
785 return (error);
788 static int
789 pr_read_psinfo(prnode_t *pnp, uio_t *uiop)
791 psinfo_t psinfo;
792 proc_t *p;
793 int error = 0;
795 ASSERT(pnp->pr_type == PR_PSINFO);
798 * We don't want the full treatment of prlock(pnp) here.
799 * This file is world-readable and never goes invalid.
800 * It doesn't matter if we are in the middle of an exec().
802 p = pr_p_lock(pnp);
803 mutex_exit(&pr_pidlock);
804 if (p == NULL)
805 error = ENOENT;
806 else {
807 ASSERT(p == pnp->pr_common->prc_proc);
808 prgetpsinfo(p, &psinfo);
809 prunlock(pnp);
810 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
812 return (error);
815 static int
816 pr_read_lpsinfo(prnode_t *pnp, uio_t *uiop)
818 proc_t *p;
819 kthread_t *t;
820 lwpdir_t *ldp;
821 lwpent_t *lep;
822 size_t size;
823 prheader_t *php;
824 lwpsinfo_t *sp;
825 int error;
826 int nlwp;
827 int i;
829 ASSERT(pnp->pr_type == PR_LPSINFO);
832 * We don't want the full treatment of prlock(pnp) here.
833 * This file is world-readable and never goes invalid.
834 * It doesn't matter if we are in the middle of an exec().
836 p = pr_p_lock(pnp);
837 mutex_exit(&pr_pidlock);
838 if (p == NULL)
839 return (ENOENT);
840 ASSERT(p == pnp->pr_common->prc_proc);
841 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
842 prunlock(pnp);
843 return (ENOENT);
845 size = sizeof (prheader_t) + nlwp * LSPAN(lwpsinfo_t);
847 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
848 mutex_exit(&p->p_lock);
849 php = kmem_zalloc(size, KM_SLEEP);
850 mutex_enter(&p->p_lock);
851 /* p->p_lwpcnt can't change while process is locked */
852 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
854 php->pr_nent = nlwp;
855 php->pr_entsize = LSPAN(lwpsinfo_t);
857 sp = (lwpsinfo_t *)(php + 1);
858 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
859 if ((lep = ldp->ld_entry) == NULL)
860 continue;
861 if ((t = lep->le_thread) != NULL)
862 prgetlwpsinfo(t, sp);
863 else {
864 bzero(sp, sizeof (*sp));
865 sp->pr_lwpid = lep->le_lwpid;
866 sp->pr_state = SZOMB;
867 sp->pr_sname = 'Z';
868 sp->pr_start.tv_sec = lep->le_start;
869 sp->pr_bindpro = PBIND_NONE;
870 sp->pr_bindpset = PS_NONE;
872 sp = (lwpsinfo_t *)((caddr_t)sp + LSPAN(lwpsinfo_t));
874 prunlock(pnp);
876 error = pr_uioread(php, size, uiop);
877 kmem_free(php, size);
878 return (error);
881 static int
882 pr_read_map_common(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
884 proc_t *p;
885 struct as *as;
886 list_t iolhead;
887 int error;
889 readmap_common:
890 if ((error = prlock(pnp, ZNO)) != 0)
891 return (error);
893 p = pnp->pr_common->prc_proc;
894 as = p->p_as;
896 if ((p->p_flag & SSYS) || as == &kas) {
897 prunlock(pnp);
898 return (0);
901 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
902 prunlock(pnp);
903 delay(1);
904 goto readmap_common;
906 mutex_exit(&p->p_lock);
908 switch (type) {
909 case PR_XMAP:
910 error = prgetxmap(p, &iolhead);
911 break;
912 case PR_RMAP:
913 error = prgetmap(p, 1, &iolhead);
914 break;
915 case PR_MAP:
916 error = prgetmap(p, 0, &iolhead);
917 break;
920 AS_LOCK_EXIT(as);
921 mutex_enter(&p->p_lock);
922 prunlock(pnp);
924 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
926 return (error);
929 static int
930 pr_read_map(prnode_t *pnp, uio_t *uiop)
932 ASSERT(pnp->pr_type == PR_MAP);
933 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
936 static int
937 pr_read_rmap(prnode_t *pnp, uio_t *uiop)
939 ASSERT(pnp->pr_type == PR_RMAP);
940 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
943 static int
944 pr_read_xmap(prnode_t *pnp, uio_t *uiop)
946 ASSERT(pnp->pr_type == PR_XMAP);
947 return (pr_read_map_common(pnp, uiop, pnp->pr_type));
950 static int
951 pr_read_cred(prnode_t *pnp, uio_t *uiop)
953 proc_t *p;
954 prcred_t *pcrp;
955 int error;
956 size_t count;
958 ASSERT(pnp->pr_type == PR_CRED);
961 * We kmem_alloc() the prcred_t structure because
962 * the number of supplementary groups is variable.
964 pcrp =
965 kmem_alloc(sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1),
966 KM_SLEEP);
968 if ((error = prlock(pnp, ZNO)) != 0)
969 goto out;
970 p = pnp->pr_common->prc_proc;
971 ASSERT(p != NULL);
973 prgetcred(p, pcrp);
974 prunlock(pnp);
976 count = sizeof (prcred_t);
977 if (pcrp->pr_ngroups > 1)
978 count += sizeof (gid_t) * (pcrp->pr_ngroups - 1);
979 error = pr_uioread(pcrp, count, uiop);
980 out:
981 kmem_free(pcrp, sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1));
982 return (error);
985 static int
986 pr_read_priv(prnode_t *pnp, uio_t *uiop)
988 proc_t *p;
989 size_t psize = prgetprivsize();
990 prpriv_t *ppriv = kmem_alloc(psize, KM_SLEEP);
991 int error;
993 ASSERT(pnp->pr_type == PR_PRIV);
995 if ((error = prlock(pnp, ZNO)) != 0)
996 goto out;
997 p = pnp->pr_common->prc_proc;
998 ASSERT(p != NULL);
1000 prgetpriv(p, ppriv);
1001 prunlock(pnp);
1003 error = pr_uioread(ppriv, psize, uiop);
1004 out:
1005 kmem_free(ppriv, psize);
1006 return (error);
1009 static int
1010 pr_read_sigact(prnode_t *pnp, uio_t *uiop)
1012 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1013 proc_t *p;
1014 struct sigaction *sap;
1015 int sig;
1016 int error;
1017 user_t *up;
1019 ASSERT(pnp->pr_type == PR_SIGACT);
1022 * We kmem_alloc() the sigaction array because
1023 * it is so big it might blow the kernel stack.
1025 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction), KM_SLEEP);
1027 if ((error = prlock(pnp, ZNO)) != 0)
1028 goto out;
1029 p = pnp->pr_common->prc_proc;
1030 ASSERT(p != NULL);
1032 if (uiop->uio_offset >= (nsig-1)*sizeof (struct sigaction)) {
1033 prunlock(pnp);
1034 goto out;
1037 up = PTOU(p);
1038 for (sig = 1; sig < nsig; sig++)
1039 prgetaction(p, up, sig, &sap[sig-1]);
1040 prunlock(pnp);
1042 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction), uiop);
1043 out:
1044 kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
1045 return (error);
1048 static int
1049 pr_read_auxv(prnode_t *pnp, uio_t *uiop)
1051 auxv_t auxv[__KERN_NAUXV_IMPL];
1052 proc_t *p;
1053 user_t *up;
1054 int error;
1056 ASSERT(pnp->pr_type == PR_AUXV);
1058 if ((error = prlock(pnp, ZNO)) != 0)
1059 return (error);
1061 if (uiop->uio_offset >= sizeof (auxv)) {
1062 prunlock(pnp);
1063 return (0);
1066 p = pnp->pr_common->prc_proc;
1067 up = PTOU(p);
1068 bcopy(up->u_auxv, auxv, sizeof (auxv));
1069 prunlock(pnp);
1071 return (pr_uioread(auxv, sizeof (auxv), uiop));
1074 #if defined(__x86)
1076 * XX64
1077 * This is almost certainly broken for the amd64 kernel, because
1078 * we have two kinds of LDT structures to export -- one for compatibility
1079 * mode, and one for long mode, sigh.
1081 * For now let's just have a ldt of size 0 for 64-bit processes.
1083 static int
1084 pr_read_ldt(prnode_t *pnp, uio_t *uiop)
1086 proc_t *p;
1087 struct ssd *ssd;
1088 size_t size;
1089 int error;
1091 ASSERT(pnp->pr_type == PR_LDT);
1093 if ((error = prlock(pnp, ZNO)) != 0)
1094 return (error);
1095 p = pnp->pr_common->prc_proc;
1097 mutex_exit(&p->p_lock);
1098 mutex_enter(&p->p_ldtlock);
1099 size = prnldt(p) * sizeof (struct ssd);
1100 if (uiop->uio_offset >= size) {
1101 mutex_exit(&p->p_ldtlock);
1102 mutex_enter(&p->p_lock);
1103 prunlock(pnp);
1104 return (0);
1107 ssd = kmem_alloc(size, KM_SLEEP);
1108 prgetldt(p, ssd);
1109 mutex_exit(&p->p_ldtlock);
1110 mutex_enter(&p->p_lock);
1111 prunlock(pnp);
1113 error = pr_uioread(ssd, size, uiop);
1114 kmem_free(ssd, size);
1115 return (error);
1117 #endif /* __x86 */
1119 static int
1120 pr_read_usage(prnode_t *pnp, uio_t *uiop)
1122 prhusage_t *pup;
1123 prusage_t *upup;
1124 proc_t *p;
1125 kthread_t *t;
1126 int error;
1128 ASSERT(pnp->pr_type == PR_USAGE);
1130 /* allocate now, before locking the process */
1131 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1132 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1135 * We don't want the full treatment of prlock(pnp) here.
1136 * This file is world-readable and never goes invalid.
1137 * It doesn't matter if we are in the middle of an exec().
1139 p = pr_p_lock(pnp);
1140 mutex_exit(&pr_pidlock);
1141 if (p == NULL) {
1142 error = ENOENT;
1143 goto out;
1145 ASSERT(p == pnp->pr_common->prc_proc);
1147 if (uiop->uio_offset >= sizeof (prusage_t)) {
1148 prunlock(pnp);
1149 error = 0;
1150 goto out;
1153 pup->pr_tstamp = gethrtime();
1155 pup->pr_count = p->p_defunct;
1156 pup->pr_create = p->p_mstart;
1157 pup->pr_term = p->p_mterm;
1159 pup->pr_rtime = p->p_mlreal;
1160 pup->pr_utime = p->p_acct[LMS_USER];
1161 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1162 pup->pr_ttime = p->p_acct[LMS_TRAP];
1163 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1164 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1165 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1166 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1167 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1168 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1169 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1171 pup->pr_minf = p->p_ru.minflt;
1172 pup->pr_majf = p->p_ru.majflt;
1173 pup->pr_nswap = p->p_ru.nswap;
1174 pup->pr_inblk = p->p_ru.inblock;
1175 pup->pr_oublk = p->p_ru.oublock;
1176 pup->pr_msnd = p->p_ru.msgsnd;
1177 pup->pr_mrcv = p->p_ru.msgrcv;
1178 pup->pr_sigs = p->p_ru.nsignals;
1179 pup->pr_vctx = p->p_ru.nvcsw;
1180 pup->pr_ictx = p->p_ru.nivcsw;
1181 pup->pr_sysc = p->p_ru.sysc;
1182 pup->pr_ioch = p->p_ru.ioch;
1185 * Add the usage information for each active lwp.
1187 if ((t = p->p_tlist) != NULL &&
1188 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
1189 do {
1190 if (t->t_proc_flag & TP_LWPEXIT)
1191 continue;
1192 pup->pr_count++;
1193 praddusage(t, pup);
1194 } while ((t = t->t_forw) != p->p_tlist);
1197 prunlock(pnp);
1199 prcvtusage(pup, upup);
1201 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1202 out:
1203 kmem_free(pup, sizeof (*pup));
1204 kmem_free(upup, sizeof (*upup));
1205 return (error);
1208 static int
1209 pr_read_lusage(prnode_t *pnp, uio_t *uiop)
1211 int nlwp;
1212 prhusage_t *pup;
1213 prheader_t *php;
1214 prusage_t *upup;
1215 size_t size;
1216 hrtime_t curtime;
1217 proc_t *p;
1218 kthread_t *t;
1219 lwpdir_t *ldp;
1220 int error;
1221 int i;
1223 ASSERT(pnp->pr_type == PR_LUSAGE);
1226 * We don't want the full treatment of prlock(pnp) here.
1227 * This file is world-readable and never goes invalid.
1228 * It doesn't matter if we are in the middle of an exec().
1230 p = pr_p_lock(pnp);
1231 mutex_exit(&pr_pidlock);
1232 if (p == NULL)
1233 return (ENOENT);
1234 ASSERT(p == pnp->pr_common->prc_proc);
1235 if ((nlwp = p->p_lwpcnt) == 0) {
1236 prunlock(pnp);
1237 return (ENOENT);
1240 size = sizeof (prheader_t) + (nlwp + 1) * LSPAN(prusage_t);
1241 if (uiop->uio_offset >= size) {
1242 prunlock(pnp);
1243 return (0);
1246 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1247 mutex_exit(&p->p_lock);
1248 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
1249 mutex_enter(&p->p_lock);
1250 /* p->p_lwpcnt can't change while process is locked */
1251 ASSERT(nlwp == p->p_lwpcnt);
1253 php = (prheader_t *)(pup + 1);
1254 upup = (prusage_t *)(php + 1);
1256 php->pr_nent = nlwp + 1;
1257 php->pr_entsize = LSPAN(prusage_t);
1259 curtime = gethrtime();
1262 * First the summation over defunct lwps.
1264 pup->pr_count = p->p_defunct;
1265 pup->pr_tstamp = curtime;
1266 pup->pr_create = p->p_mstart;
1267 pup->pr_term = p->p_mterm;
1269 pup->pr_rtime = p->p_mlreal;
1270 pup->pr_utime = p->p_acct[LMS_USER];
1271 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1272 pup->pr_ttime = p->p_acct[LMS_TRAP];
1273 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1274 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1275 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1276 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1277 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1278 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1279 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1281 pup->pr_minf = p->p_ru.minflt;
1282 pup->pr_majf = p->p_ru.majflt;
1283 pup->pr_nswap = p->p_ru.nswap;
1284 pup->pr_inblk = p->p_ru.inblock;
1285 pup->pr_oublk = p->p_ru.oublock;
1286 pup->pr_msnd = p->p_ru.msgsnd;
1287 pup->pr_mrcv = p->p_ru.msgrcv;
1288 pup->pr_sigs = p->p_ru.nsignals;
1289 pup->pr_vctx = p->p_ru.nvcsw;
1290 pup->pr_ictx = p->p_ru.nivcsw;
1291 pup->pr_sysc = p->p_ru.sysc;
1292 pup->pr_ioch = p->p_ru.ioch;
1294 prcvtusage(pup, upup);
1297 * Fill one prusage struct for each active lwp.
1299 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1300 if (ldp->ld_entry == NULL ||
1301 (t = ldp->ld_entry->le_thread) == NULL)
1302 continue;
1303 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1304 ASSERT(nlwp > 0);
1305 --nlwp;
1306 upup = (prusage_t *)((caddr_t)upup + LSPAN(prusage_t));
1307 prgetusage(t, pup);
1308 prcvtusage(pup, upup);
1310 ASSERT(nlwp == 0);
1312 prunlock(pnp);
1314 error = pr_uioread(php, size, uiop);
1315 kmem_free(pup, size + sizeof (prhusage_t));
1316 return (error);
1319 static int
1320 pr_read_pagedata(prnode_t *pnp, uio_t *uiop)
1322 proc_t *p;
1323 int error;
1325 ASSERT(pnp->pr_type == PR_PAGEDATA);
1327 if ((error = prlock(pnp, ZNO)) != 0)
1328 return (error);
1330 p = pnp->pr_common->prc_proc;
1331 if ((p->p_flag & SSYS) || p->p_as == &kas) {
1332 prunlock(pnp);
1333 return (0);
1336 mutex_exit(&p->p_lock);
1337 error = prpdread(p, pnp->pr_hatid, uiop);
1338 mutex_enter(&p->p_lock);
1340 prunlock(pnp);
1341 return (error);
1344 static int
1345 pr_read_opagedata(prnode_t *pnp, uio_t *uiop)
1347 proc_t *p;
1348 struct as *as;
1349 int error;
1351 ASSERT(pnp->pr_type == PR_OPAGEDATA);
1353 if ((error = prlock(pnp, ZNO)) != 0)
1354 return (error);
1356 p = pnp->pr_common->prc_proc;
1357 as = p->p_as;
1358 if ((p->p_flag & SSYS) || as == &kas) {
1359 prunlock(pnp);
1360 return (0);
1363 mutex_exit(&p->p_lock);
1364 error = oprpdread(as, pnp->pr_hatid, uiop);
1365 mutex_enter(&p->p_lock);
1367 prunlock(pnp);
1368 return (error);
1371 static int
1372 pr_read_watch(prnode_t *pnp, uio_t *uiop)
1374 proc_t *p;
1375 int error;
1376 prwatch_t *Bpwp;
1377 size_t size;
1378 prwatch_t *pwp;
1379 int nwarea;
1380 struct watched_area *pwarea;
1382 ASSERT(pnp->pr_type == PR_WATCH);
1384 if ((error = prlock(pnp, ZNO)) != 0)
1385 return (error);
1387 p = pnp->pr_common->prc_proc;
1388 nwarea = avl_numnodes(&p->p_warea);
1389 size = nwarea * sizeof (prwatch_t);
1390 if (uiop->uio_offset >= size) {
1391 prunlock(pnp);
1392 return (0);
1395 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1396 mutex_exit(&p->p_lock);
1397 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
1398 mutex_enter(&p->p_lock);
1399 /* p->p_nwarea can't change while process is locked */
1400 ASSERT(nwarea == avl_numnodes(&p->p_warea));
1402 /* gather the watched areas */
1403 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
1404 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
1405 pwp->pr_vaddr = (uintptr_t)pwarea->wa_vaddr;
1406 pwp->pr_size = pwarea->wa_eaddr - pwarea->wa_vaddr;
1407 pwp->pr_wflags = (int)pwarea->wa_flags;
1410 prunlock(pnp);
1412 error = pr_uioread(Bpwp, size, uiop);
1413 kmem_free(Bpwp, size);
1414 return (error);
1417 static int
1418 pr_read_lwpstatus(prnode_t *pnp, uio_t *uiop)
1420 lwpstatus_t *sp;
1421 int error;
1423 ASSERT(pnp->pr_type == PR_LWPSTATUS);
1426 * We kmem_alloc() the lwpstatus structure because
1427 * it is so big it might blow the kernel stack.
1429 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1431 if ((error = prlock(pnp, ZNO)) != 0)
1432 goto out;
1434 if (uiop->uio_offset >= sizeof (*sp)) {
1435 prunlock(pnp);
1436 goto out;
1439 prgetlwpstatus(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
1440 prunlock(pnp);
1442 error = pr_uioread(sp, sizeof (*sp), uiop);
1443 out:
1444 kmem_free(sp, sizeof (*sp));
1445 return (error);
1448 static int
1449 pr_read_lwpsinfo(prnode_t *pnp, uio_t *uiop)
1451 lwpsinfo_t lwpsinfo;
1452 proc_t *p;
1453 kthread_t *t;
1454 lwpent_t *lep;
1456 ASSERT(pnp->pr_type == PR_LWPSINFO);
1459 * We don't want the full treatment of prlock(pnp) here.
1460 * This file is world-readable and never goes invalid.
1461 * It doesn't matter if we are in the middle of an exec().
1463 p = pr_p_lock(pnp);
1464 mutex_exit(&pr_pidlock);
1465 if (p == NULL)
1466 return (ENOENT);
1467 ASSERT(p == pnp->pr_common->prc_proc);
1468 if (pnp->pr_common->prc_tslot == -1) {
1469 prunlock(pnp);
1470 return (ENOENT);
1473 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
1474 prunlock(pnp);
1475 return (0);
1478 if ((t = pnp->pr_common->prc_thread) != NULL)
1479 prgetlwpsinfo(t, &lwpsinfo);
1480 else {
1481 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
1482 bzero(&lwpsinfo, sizeof (lwpsinfo));
1483 lwpsinfo.pr_lwpid = lep->le_lwpid;
1484 lwpsinfo.pr_state = SZOMB;
1485 lwpsinfo.pr_sname = 'Z';
1486 lwpsinfo.pr_start.tv_sec = lep->le_start;
1487 lwpsinfo.pr_bindpro = PBIND_NONE;
1488 lwpsinfo.pr_bindpset = PS_NONE;
1490 prunlock(pnp);
1492 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
1495 static int
1496 pr_read_lwpusage(prnode_t *pnp, uio_t *uiop)
1498 prhusage_t *pup;
1499 prusage_t *upup;
1500 proc_t *p;
1501 int error;
1503 ASSERT(pnp->pr_type == PR_LWPUSAGE);
1505 /* allocate now, before locking the process */
1506 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
1507 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
1510 * We don't want the full treatment of prlock(pnp) here.
1511 * This file is world-readable and never goes invalid.
1512 * It doesn't matter if we are in the middle of an exec().
1514 p = pr_p_lock(pnp);
1515 mutex_exit(&pr_pidlock);
1516 if (p == NULL) {
1517 error = ENOENT;
1518 goto out;
1520 ASSERT(p == pnp->pr_common->prc_proc);
1521 if (pnp->pr_common->prc_thread == NULL) {
1522 prunlock(pnp);
1523 error = ENOENT;
1524 goto out;
1526 if (uiop->uio_offset >= sizeof (prusage_t)) {
1527 prunlock(pnp);
1528 error = 0;
1529 goto out;
1532 pup->pr_tstamp = gethrtime();
1533 prgetusage(pnp->pr_common->prc_thread, pup);
1535 prunlock(pnp);
1537 prcvtusage(pup, upup);
1539 error = pr_uioread(upup, sizeof (prusage_t), uiop);
1540 out:
1541 kmem_free(pup, sizeof (*pup));
1542 kmem_free(upup, sizeof (*upup));
1543 return (error);
1546 static int
1547 pr_read_lwpname(prnode_t *pnp, uio_t *uiop)
1549 char lwpname[THREAD_NAME_MAX];
1550 kthread_t *t;
1551 int error;
1553 ASSERT(pnp->pr_type == PR_LWPNAME);
1555 if (uiop->uio_offset >= THREAD_NAME_MAX)
1556 return (0);
1558 if ((error = prlock(pnp, ZNO)) != 0)
1559 return (error);
1561 bzero(lwpname, sizeof (lwpname));
1563 t = pnp->pr_common->prc_thread;
1565 if (t->t_name != NULL)
1566 (void) strlcpy(lwpname, t->t_name, sizeof (lwpname));
1568 prunlock(pnp);
1570 return (pr_uioread(lwpname, sizeof (lwpname), uiop));
1573 /* ARGSUSED */
1574 static int
1575 pr_read_xregs(prnode_t *pnp, uio_t *uiop)
1577 #if defined(__sparc)
1578 proc_t *p;
1579 kthread_t *t;
1580 int error;
1581 char *xreg;
1582 size_t size;
1584 ASSERT(pnp->pr_type == PR_XREGS);
1586 xreg = kmem_zalloc(sizeof (prxregset_t), KM_SLEEP);
1588 if ((error = prlock(pnp, ZNO)) != 0)
1589 goto out;
1591 p = pnp->pr_common->prc_proc;
1592 t = pnp->pr_common->prc_thread;
1594 size = prhasx(p)? prgetprxregsize(p) : 0;
1595 if (uiop->uio_offset >= size) {
1596 prunlock(pnp);
1597 goto out;
1600 /* drop p->p_lock while (possibly) touching the stack */
1601 mutex_exit(&p->p_lock);
1602 prgetprxregs(ttolwp(t), xreg);
1603 mutex_enter(&p->p_lock);
1604 prunlock(pnp);
1606 error = pr_uioread(xreg, size, uiop);
1607 out:
1608 kmem_free(xreg, sizeof (prxregset_t));
1609 return (error);
1610 #else
1611 return (0);
1612 #endif
1615 static int
1616 pr_read_spymaster(prnode_t *pnp, uio_t *uiop)
1618 psinfo_t psinfo;
1619 int error;
1620 klwp_t *lwp;
1622 ASSERT(pnp->pr_type == PR_SPYMASTER);
1624 if ((error = prlock(pnp, ZNO)) != 0)
1625 return (error);
1627 if (pnp->pr_common->prc_thread == NULL) {
1628 prunlock(pnp);
1629 return (0);
1632 lwp = pnp->pr_common->prc_thread->t_lwp;
1634 if (lwp->lwp_spymaster == NULL) {
1635 prunlock(pnp);
1636 return (0);
1639 bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t));
1640 prunlock(pnp);
1642 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
1645 static int
1646 pr_read_secflags(prnode_t *pnp, uio_t *uiop)
1648 prsecflags_t ret;
1649 int error;
1650 proc_t *p;
1652 ASSERT(pnp->pr_type == PR_SECFLAGS);
1654 if ((error = prlock(pnp, ZNO)) != 0)
1655 return (error);
1657 p = pnp->pr_common->prc_proc;
1658 prgetsecflags(p, &ret);
1659 prunlock(pnp);
1661 return (pr_uioread(&ret, sizeof (ret), uiop));
1664 #if defined(__sparc)
1666 static int
1667 pr_read_gwindows(prnode_t *pnp, uio_t *uiop)
1669 proc_t *p;
1670 kthread_t *t;
1671 gwindows_t *gwp;
1672 int error;
1673 size_t size;
1675 ASSERT(pnp->pr_type == PR_GWINDOWS);
1677 gwp = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP);
1679 if ((error = prlock(pnp, ZNO)) != 0)
1680 goto out;
1682 p = pnp->pr_common->prc_proc;
1683 t = pnp->pr_common->prc_thread;
1686 * Drop p->p_lock while touching the stack.
1687 * The P_PR_LOCK flag prevents the lwp from
1688 * disappearing while we do this.
1690 mutex_exit(&p->p_lock);
1691 if ((size = prnwindows(ttolwp(t))) != 0)
1692 size = sizeof (gwindows_t) -
1693 (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow);
1694 if (uiop->uio_offset >= size) {
1695 mutex_enter(&p->p_lock);
1696 prunlock(pnp);
1697 goto out;
1699 prgetwindows(ttolwp(t), gwp);
1700 mutex_enter(&p->p_lock);
1701 prunlock(pnp);
1703 error = pr_uioread(gwp, size, uiop);
1704 out:
1705 kmem_free(gwp, sizeof (gwindows_t));
1706 return (error);
1709 /* ARGSUSED */
1710 static int
1711 pr_read_asrs(prnode_t *pnp, uio_t *uiop)
1713 int error;
1715 ASSERT(pnp->pr_type == PR_ASRS);
1717 /* the asrs file exists only for sparc v9 _LP64 processes */
1718 if ((error = prlock(pnp, ZNO)) == 0) {
1719 proc_t *p = pnp->pr_common->prc_proc;
1720 kthread_t *t = pnp->pr_common->prc_thread;
1721 asrset_t asrset;
1723 if (p->p_model != DATAMODEL_LP64 ||
1724 uiop->uio_offset >= sizeof (asrset_t)) {
1725 prunlock(pnp);
1726 return (0);
1730 * Drop p->p_lock while touching the stack.
1731 * The P_PR_LOCK flag prevents the lwp from
1732 * disappearing while we do this.
1734 mutex_exit(&p->p_lock);
1735 prgetasregs(ttolwp(t), asrset);
1736 mutex_enter(&p->p_lock);
1737 prunlock(pnp);
1739 error = pr_uioread(&asrset[0], sizeof (asrset_t), uiop);
1742 return (error);
1745 #endif /* __sparc */
1747 static int
1748 pr_read_piddir(prnode_t *pnp, uio_t *uiop)
1750 ASSERT(pnp->pr_type == PR_PIDDIR);
1751 ASSERT(pnp->pr_pidfile != NULL);
1753 /* use the underlying PR_PIDFILE to read the process */
1754 pnp = VTOP(pnp->pr_pidfile);
1755 ASSERT(pnp->pr_type == PR_PIDFILE);
1757 return (pr_read_pidfile(pnp, uiop));
1760 static int
1761 pr_read_pidfile(prnode_t *pnp, uio_t *uiop)
1763 int error;
1765 ASSERT(pnp->pr_type == PR_PIDFILE || pnp->pr_type == PR_LWPIDFILE);
1767 if ((error = prlock(pnp, ZNO)) == 0) {
1768 proc_t *p = pnp->pr_common->prc_proc;
1769 struct as *as = p->p_as;
1771 if ((p->p_flag & SSYS) || as == &kas) {
1773 * /proc I/O cannot be done to a system process.
1775 error = EIO; /* old /proc semantics */
1776 } else {
1778 * We drop p_lock because we don't want to hold
1779 * it over an I/O operation because that could
1780 * lead to deadlock with the clock thread.
1781 * The process will not disappear and its address
1782 * space will not change because it is marked P_PR_LOCK.
1784 mutex_exit(&p->p_lock);
1785 error = prusrio(p, UIO_READ, uiop, 1);
1786 mutex_enter(&p->p_lock);
1788 prunlock(pnp);
1791 return (error);
1794 #ifdef _SYSCALL32_IMPL
1797 * Array of ILP32 read functions, indexed by /proc file type.
1799 static int pr_read_status_32(),
1800 pr_read_lstatus_32(), pr_read_psinfo_32(), pr_read_lpsinfo_32(),
1801 pr_read_map_32(), pr_read_rmap_32(), pr_read_xmap_32(),
1802 pr_read_sigact_32(), pr_read_auxv_32(),
1803 pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(),
1804 pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(),
1805 pr_read_lwpusage_32(), pr_read_spymaster_32(),
1806 #if defined(__sparc)
1807 pr_read_gwindows_32(),
1808 #endif
1809 pr_read_opagedata_32();
1811 static int (*pr_read_function_32[PR_NFILES])() = {
1812 pr_read_inval, /* /proc */
1813 pr_read_inval, /* /proc/self */
1814 pr_read_piddir, /* /proc/<pid> (old /proc read()) */
1815 pr_read_as, /* /proc/<pid>/as */
1816 pr_read_inval, /* /proc/<pid>/ctl */
1817 pr_read_status_32, /* /proc/<pid>/status */
1818 pr_read_lstatus_32, /* /proc/<pid>/lstatus */
1819 pr_read_psinfo_32, /* /proc/<pid>/psinfo */
1820 pr_read_lpsinfo_32, /* /proc/<pid>/lpsinfo */
1821 pr_read_map_32, /* /proc/<pid>/map */
1822 pr_read_rmap_32, /* /proc/<pid>/rmap */
1823 pr_read_xmap_32, /* /proc/<pid>/xmap */
1824 pr_read_cred, /* /proc/<pid>/cred */
1825 pr_read_sigact_32, /* /proc/<pid>/sigact */
1826 pr_read_auxv_32, /* /proc/<pid>/auxv */
1827 #if defined(__x86)
1828 pr_read_ldt, /* /proc/<pid>/ldt */
1829 #endif
1830 pr_read_usage_32, /* /proc/<pid>/usage */
1831 pr_read_lusage_32, /* /proc/<pid>/lusage */
1832 pr_read_pagedata_32, /* /proc/<pid>/pagedata */
1833 pr_read_watch_32, /* /proc/<pid>/watch */
1834 pr_read_inval, /* /proc/<pid>/cwd */
1835 pr_read_inval, /* /proc/<pid>/root */
1836 pr_read_inval, /* /proc/<pid>/fd */
1837 pr_read_inval, /* /proc/<pid>/fd/nn */
1838 pr_read_inval, /* /proc/<pid>/object */
1839 pr_read_inval, /* /proc/<pid>/object/xxx */
1840 pr_read_inval, /* /proc/<pid>/lwp */
1841 pr_read_inval, /* /proc/<pid>/lwp/<lwpid> */
1842 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
1843 pr_read_lwpname, /* /proc/<pid>/lwp/<lwpid>/lwpname */
1844 pr_read_lwpstatus_32, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
1845 pr_read_lwpsinfo_32, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
1846 pr_read_lwpusage_32, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
1847 pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */
1848 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */
1849 pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
1850 pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */
1851 #if defined(__sparc)
1852 pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */
1853 pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */
1854 #endif
1855 pr_read_priv, /* /proc/<pid>/priv */
1856 pr_read_inval, /* /proc/<pid>/path */
1857 pr_read_inval, /* /proc/<pid>/path/xxx */
1858 pr_read_inval, /* /proc/<pid>/contracts */
1859 pr_read_inval, /* /proc/<pid>/contracts/<ctid> */
1860 pr_read_secflags, /* /proc/<pid>/secflags */
1861 pr_read_pidfile, /* old process file */
1862 pr_read_pidfile, /* old lwp file */
1863 pr_read_opagedata_32, /* old pagedata file */
1866 static int
1867 pr_read_status_32(prnode_t *pnp, uio_t *uiop)
1869 pstatus32_t *sp;
1870 proc_t *p;
1871 int error;
1873 ASSERT(pnp->pr_type == PR_STATUS);
1876 * We kmem_alloc() the pstatus structure because
1877 * it is so big it might blow the kernel stack.
1879 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
1880 if ((error = prlock(pnp, ZNO)) == 0) {
1882 * A 32-bit process cannot get the status of a 64-bit process.
1883 * The fields for the 64-bit quantities are not large enough.
1885 p = pnp->pr_common->prc_proc;
1886 if (PROCESS_NOT_32BIT(p)) {
1887 prunlock(pnp);
1888 error = EOVERFLOW;
1889 } else {
1890 prgetstatus32(pnp->pr_common->prc_proc, sp,
1891 VTOZONE(PTOV(pnp)));
1892 prunlock(pnp);
1893 error = pr_uioread(sp, sizeof (*sp), uiop);
1896 kmem_free((caddr_t)sp, sizeof (*sp));
1897 return (error);
1900 static int
1901 pr_read_lstatus_32(prnode_t *pnp, uio_t *uiop)
1903 proc_t *p;
1904 kthread_t *t;
1905 lwpdir_t *ldp;
1906 size_t size;
1907 prheader32_t *php;
1908 lwpstatus32_t *sp;
1909 int error;
1910 int nlwp;
1911 int i;
1913 ASSERT(pnp->pr_type == PR_LSTATUS);
1915 if ((error = prlock(pnp, ZNO)) != 0)
1916 return (error);
1917 p = pnp->pr_common->prc_proc;
1919 * A 32-bit process cannot get the status of a 64-bit process.
1920 * The fields for the 64-bit quantities are not large enough.
1922 if (PROCESS_NOT_32BIT(p)) {
1923 prunlock(pnp);
1924 return (EOVERFLOW);
1926 nlwp = p->p_lwpcnt;
1927 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpstatus32_t);
1929 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
1930 mutex_exit(&p->p_lock);
1931 php = kmem_zalloc(size, KM_SLEEP);
1932 mutex_enter(&p->p_lock);
1933 /* p->p_lwpcnt can't change while process is locked */
1934 ASSERT(nlwp == p->p_lwpcnt);
1936 php->pr_nent = nlwp;
1937 php->pr_entsize = LSPAN32(lwpstatus32_t);
1939 sp = (lwpstatus32_t *)(php + 1);
1940 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
1941 if (ldp->ld_entry == NULL ||
1942 (t = ldp->ld_entry->le_thread) == NULL)
1943 continue;
1944 prgetlwpstatus32(t, sp, VTOZONE(PTOV(pnp)));
1945 sp = (lwpstatus32_t *)((caddr_t)sp + LSPAN32(lwpstatus32_t));
1947 prunlock(pnp);
1949 error = pr_uioread(php, size, uiop);
1950 kmem_free(php, size);
1951 return (error);
1954 static int
1955 pr_read_psinfo_32(prnode_t *pnp, uio_t *uiop)
1957 psinfo32_t psinfo;
1958 proc_t *p;
1959 int error = 0;
1961 ASSERT(pnp->pr_type == PR_PSINFO);
1964 * We don't want the full treatment of prlock(pnp) here.
1965 * This file is world-readable and never goes invalid.
1966 * It doesn't matter if we are in the middle of an exec().
1968 p = pr_p_lock(pnp);
1969 mutex_exit(&pr_pidlock);
1970 if (p == NULL)
1971 error = ENOENT;
1972 else {
1973 ASSERT(p == pnp->pr_common->prc_proc);
1974 prgetpsinfo32(p, &psinfo);
1975 prunlock(pnp);
1976 error = pr_uioread(&psinfo, sizeof (psinfo), uiop);
1978 return (error);
1981 static int
1982 pr_read_lpsinfo_32(prnode_t *pnp, uio_t *uiop)
1984 proc_t *p;
1985 kthread_t *t;
1986 lwpdir_t *ldp;
1987 lwpent_t *lep;
1988 size_t size;
1989 prheader32_t *php;
1990 lwpsinfo32_t *sp;
1991 int error;
1992 int nlwp;
1993 int i;
1995 ASSERT(pnp->pr_type == PR_LPSINFO);
1998 * We don't want the full treatment of prlock(pnp) here.
1999 * This file is world-readable and never goes invalid.
2000 * It doesn't matter if we are in the middle of an exec().
2002 p = pr_p_lock(pnp);
2003 mutex_exit(&pr_pidlock);
2004 if (p == NULL)
2005 return (ENOENT);
2006 ASSERT(p == pnp->pr_common->prc_proc);
2007 if ((nlwp = p->p_lwpcnt + p->p_zombcnt) == 0) {
2008 prunlock(pnp);
2009 return (ENOENT);
2011 size = sizeof (prheader32_t) + nlwp * LSPAN32(lwpsinfo32_t);
2013 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2014 mutex_exit(&p->p_lock);
2015 php = kmem_zalloc(size, KM_SLEEP);
2016 mutex_enter(&p->p_lock);
2017 /* p->p_lwpcnt can't change while process is locked */
2018 ASSERT(nlwp == p->p_lwpcnt + p->p_zombcnt);
2020 php->pr_nent = nlwp;
2021 php->pr_entsize = LSPAN32(lwpsinfo32_t);
2023 sp = (lwpsinfo32_t *)(php + 1);
2024 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2025 if ((lep = ldp->ld_entry) == NULL)
2026 continue;
2027 if ((t = lep->le_thread) != NULL)
2028 prgetlwpsinfo32(t, sp);
2029 else {
2030 bzero(sp, sizeof (*sp));
2031 sp->pr_lwpid = lep->le_lwpid;
2032 sp->pr_state = SZOMB;
2033 sp->pr_sname = 'Z';
2034 sp->pr_start.tv_sec = (time32_t)lep->le_start;
2036 sp = (lwpsinfo32_t *)((caddr_t)sp + LSPAN32(lwpsinfo32_t));
2038 prunlock(pnp);
2040 error = pr_uioread(php, size, uiop);
2041 kmem_free(php, size);
2042 return (error);
2045 static int
2046 pr_read_map_common_32(prnode_t *pnp, uio_t *uiop, prnodetype_t type)
2048 proc_t *p;
2049 struct as *as;
2050 list_t iolhead;
2051 int error;
2053 readmap32_common:
2054 if ((error = prlock(pnp, ZNO)) != 0)
2055 return (error);
2057 p = pnp->pr_common->prc_proc;
2058 as = p->p_as;
2060 if ((p->p_flag & SSYS) || as == &kas) {
2061 prunlock(pnp);
2062 return (0);
2065 if (PROCESS_NOT_32BIT(p)) {
2066 prunlock(pnp);
2067 return (EOVERFLOW);
2070 if (!AS_LOCK_TRYENTER(as, RW_WRITER)) {
2071 prunlock(pnp);
2072 delay(1);
2073 goto readmap32_common;
2075 mutex_exit(&p->p_lock);
2077 switch (type) {
2078 case PR_XMAP:
2079 error = prgetxmap32(p, &iolhead);
2080 break;
2081 case PR_RMAP:
2082 error = prgetmap32(p, 1, &iolhead);
2083 break;
2084 case PR_MAP:
2085 error = prgetmap32(p, 0, &iolhead);
2086 break;
2088 AS_LOCK_EXIT(as);
2089 mutex_enter(&p->p_lock);
2090 prunlock(pnp);
2092 error = pr_iol_uiomove_and_free(&iolhead, uiop, error);
2094 return (error);
2097 static int
2098 pr_read_map_32(prnode_t *pnp, uio_t *uiop)
2100 ASSERT(pnp->pr_type == PR_MAP);
2101 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2104 static int
2105 pr_read_rmap_32(prnode_t *pnp, uio_t *uiop)
2107 ASSERT(pnp->pr_type == PR_RMAP);
2108 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2111 static int
2112 pr_read_xmap_32(prnode_t *pnp, uio_t *uiop)
2114 ASSERT(pnp->pr_type == PR_XMAP);
2115 return (pr_read_map_common_32(pnp, uiop, pnp->pr_type));
2118 static int
2119 pr_read_sigact_32(prnode_t *pnp, uio_t *uiop)
2121 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
2122 proc_t *p;
2123 struct sigaction32 *sap;
2124 int sig;
2125 int error;
2126 user_t *up;
2128 ASSERT(pnp->pr_type == PR_SIGACT);
2131 * We kmem_alloc() the sigaction32 array because
2132 * it is so big it might blow the kernel stack.
2134 sap = kmem_alloc((nsig-1) * sizeof (struct sigaction32), KM_SLEEP);
2136 if ((error = prlock(pnp, ZNO)) != 0)
2137 goto out;
2138 p = pnp->pr_common->prc_proc;
2140 if (PROCESS_NOT_32BIT(p)) {
2141 prunlock(pnp);
2142 error = EOVERFLOW;
2143 goto out;
2146 if (uiop->uio_offset >= (nsig-1) * sizeof (struct sigaction32)) {
2147 prunlock(pnp);
2148 goto out;
2151 up = PTOU(p);
2152 for (sig = 1; sig < nsig; sig++)
2153 prgetaction32(p, up, sig, &sap[sig-1]);
2154 prunlock(pnp);
2156 error = pr_uioread(sap, (nsig - 1) * sizeof (struct sigaction32), uiop);
2157 out:
2158 kmem_free(sap, (nsig-1) * sizeof (struct sigaction32));
2159 return (error);
2162 static int
2163 pr_read_auxv_32(prnode_t *pnp, uio_t *uiop)
2165 auxv32_t auxv[__KERN_NAUXV_IMPL];
2166 proc_t *p;
2167 user_t *up;
2168 int error;
2169 int i;
2171 ASSERT(pnp->pr_type == PR_AUXV);
2173 if ((error = prlock(pnp, ZNO)) != 0)
2174 return (error);
2175 p = pnp->pr_common->prc_proc;
2177 if (PROCESS_NOT_32BIT(p)) {
2178 prunlock(pnp);
2179 return (EOVERFLOW);
2182 if (uiop->uio_offset >= sizeof (auxv)) {
2183 prunlock(pnp);
2184 return (0);
2187 up = PTOU(p);
2188 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2189 auxv[i].a_type = (int32_t)up->u_auxv[i].a_type;
2190 auxv[i].a_un.a_val = (int32_t)up->u_auxv[i].a_un.a_val;
2192 prunlock(pnp);
2194 return (pr_uioread(auxv, sizeof (auxv), uiop));
2197 static int
2198 pr_read_usage_32(prnode_t *pnp, uio_t *uiop)
2200 prhusage_t *pup;
2201 prusage32_t *upup;
2202 proc_t *p;
2203 kthread_t *t;
2204 int error;
2206 ASSERT(pnp->pr_type == PR_USAGE);
2208 /* allocate now, before locking the process */
2209 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2210 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2213 * We don't want the full treatment of prlock(pnp) here.
2214 * This file is world-readable and never goes invalid.
2215 * It doesn't matter if we are in the middle of an exec().
2217 p = pr_p_lock(pnp);
2218 mutex_exit(&pr_pidlock);
2219 if (p == NULL) {
2220 error = ENOENT;
2221 goto out;
2223 ASSERT(p == pnp->pr_common->prc_proc);
2225 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2226 prunlock(pnp);
2227 error = 0;
2228 goto out;
2231 pup->pr_tstamp = gethrtime();
2233 pup->pr_count = p->p_defunct;
2234 pup->pr_create = p->p_mstart;
2235 pup->pr_term = p->p_mterm;
2237 pup->pr_rtime = p->p_mlreal;
2238 pup->pr_utime = p->p_acct[LMS_USER];
2239 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2240 pup->pr_ttime = p->p_acct[LMS_TRAP];
2241 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2242 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2243 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2244 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2245 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2246 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2247 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2249 pup->pr_minf = p->p_ru.minflt;
2250 pup->pr_majf = p->p_ru.majflt;
2251 pup->pr_nswap = p->p_ru.nswap;
2252 pup->pr_inblk = p->p_ru.inblock;
2253 pup->pr_oublk = p->p_ru.oublock;
2254 pup->pr_msnd = p->p_ru.msgsnd;
2255 pup->pr_mrcv = p->p_ru.msgrcv;
2256 pup->pr_sigs = p->p_ru.nsignals;
2257 pup->pr_vctx = p->p_ru.nvcsw;
2258 pup->pr_ictx = p->p_ru.nivcsw;
2259 pup->pr_sysc = p->p_ru.sysc;
2260 pup->pr_ioch = p->p_ru.ioch;
2263 * Add the usage information for each active lwp.
2265 if ((t = p->p_tlist) != NULL &&
2266 !(pnp->pr_pcommon->prc_flags & PRC_DESTROY)) {
2267 do {
2268 if (t->t_proc_flag & TP_LWPEXIT)
2269 continue;
2270 pup->pr_count++;
2271 praddusage(t, pup);
2272 } while ((t = t->t_forw) != p->p_tlist);
2275 prunlock(pnp);
2277 prcvtusage32(pup, upup);
2279 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2280 out:
2281 kmem_free(pup, sizeof (*pup));
2282 kmem_free(upup, sizeof (*upup));
2283 return (error);
2286 static int
2287 pr_read_lusage_32(prnode_t *pnp, uio_t *uiop)
2289 int nlwp;
2290 prhusage_t *pup;
2291 prheader32_t *php;
2292 prusage32_t *upup;
2293 size_t size;
2294 hrtime_t curtime;
2295 proc_t *p;
2296 kthread_t *t;
2297 lwpdir_t *ldp;
2298 int error;
2299 int i;
2301 ASSERT(pnp->pr_type == PR_LUSAGE);
2304 * We don't want the full treatment of prlock(pnp) here.
2305 * This file is world-readable and never goes invalid.
2306 * It doesn't matter if we are in the middle of an exec().
2308 p = pr_p_lock(pnp);
2309 mutex_exit(&pr_pidlock);
2310 if (p == NULL)
2311 return (ENOENT);
2312 ASSERT(p == pnp->pr_common->prc_proc);
2313 if ((nlwp = p->p_lwpcnt) == 0) {
2314 prunlock(pnp);
2315 return (ENOENT);
2318 size = sizeof (prheader32_t) + (nlwp + 1) * LSPAN32(prusage32_t);
2319 if (uiop->uio_offset >= size) {
2320 prunlock(pnp);
2321 return (0);
2324 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2325 mutex_exit(&p->p_lock);
2326 pup = kmem_zalloc(size + sizeof (prhusage_t), KM_SLEEP);
2327 mutex_enter(&p->p_lock);
2328 /* p->p_lwpcnt can't change while process is locked */
2329 ASSERT(nlwp == p->p_lwpcnt);
2331 php = (prheader32_t *)(pup + 1);
2332 upup = (prusage32_t *)(php + 1);
2334 php->pr_nent = nlwp + 1;
2335 php->pr_entsize = LSPAN32(prusage32_t);
2337 curtime = gethrtime();
2340 * First the summation over defunct lwps.
2342 pup->pr_count = p->p_defunct;
2343 pup->pr_tstamp = curtime;
2344 pup->pr_create = p->p_mstart;
2345 pup->pr_term = p->p_mterm;
2347 pup->pr_rtime = p->p_mlreal;
2348 pup->pr_utime = p->p_acct[LMS_USER];
2349 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2350 pup->pr_ttime = p->p_acct[LMS_TRAP];
2351 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2352 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2353 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2354 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2355 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2356 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2357 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2359 pup->pr_minf = p->p_ru.minflt;
2360 pup->pr_majf = p->p_ru.majflt;
2361 pup->pr_nswap = p->p_ru.nswap;
2362 pup->pr_inblk = p->p_ru.inblock;
2363 pup->pr_oublk = p->p_ru.oublock;
2364 pup->pr_msnd = p->p_ru.msgsnd;
2365 pup->pr_mrcv = p->p_ru.msgrcv;
2366 pup->pr_sigs = p->p_ru.nsignals;
2367 pup->pr_vctx = p->p_ru.nvcsw;
2368 pup->pr_ictx = p->p_ru.nivcsw;
2369 pup->pr_sysc = p->p_ru.sysc;
2370 pup->pr_ioch = p->p_ru.ioch;
2372 prcvtusage32(pup, upup);
2375 * Fill one prusage struct for each active lwp.
2377 for (ldp = p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
2378 if (ldp->ld_entry == NULL ||
2379 (t = ldp->ld_entry->le_thread) == NULL)
2380 continue;
2381 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2382 ASSERT(nlwp > 0);
2383 --nlwp;
2384 upup = (prusage32_t *)
2385 ((caddr_t)upup + LSPAN32(prusage32_t));
2386 prgetusage(t, pup);
2387 prcvtusage32(pup, upup);
2389 ASSERT(nlwp == 0);
2391 prunlock(pnp);
2393 error = pr_uioread(php, size, uiop);
2394 kmem_free(pup, size + sizeof (prhusage_t));
2395 return (error);
2398 static int
2399 pr_read_pagedata_32(prnode_t *pnp, uio_t *uiop)
2401 proc_t *p;
2402 int error;
2404 ASSERT(pnp->pr_type == PR_PAGEDATA);
2406 if ((error = prlock(pnp, ZNO)) != 0)
2407 return (error);
2409 p = pnp->pr_common->prc_proc;
2410 if ((p->p_flag & SSYS) || p->p_as == &kas) {
2411 prunlock(pnp);
2412 return (0);
2415 if (PROCESS_NOT_32BIT(p)) {
2416 prunlock(pnp);
2417 return (EOVERFLOW);
2420 mutex_exit(&p->p_lock);
2421 error = prpdread32(p, pnp->pr_hatid, uiop);
2422 mutex_enter(&p->p_lock);
2424 prunlock(pnp);
2425 return (error);
2428 static int
2429 pr_read_opagedata_32(prnode_t *pnp, uio_t *uiop)
2431 proc_t *p;
2432 struct as *as;
2433 int error;
2435 ASSERT(pnp->pr_type == PR_OPAGEDATA);
2437 if ((error = prlock(pnp, ZNO)) != 0)
2438 return (error);
2440 p = pnp->pr_common->prc_proc;
2441 as = p->p_as;
2443 if ((p->p_flag & SSYS) || as == &kas) {
2444 prunlock(pnp);
2445 return (0);
2448 if (PROCESS_NOT_32BIT(p)) {
2449 prunlock(pnp);
2450 return (EOVERFLOW);
2453 mutex_exit(&p->p_lock);
2454 error = oprpdread32(as, pnp->pr_hatid, uiop);
2455 mutex_enter(&p->p_lock);
2457 prunlock(pnp);
2458 return (error);
2461 static int
2462 pr_read_watch_32(prnode_t *pnp, uio_t *uiop)
2464 proc_t *p;
2465 int error;
2466 prwatch32_t *Bpwp;
2467 size_t size;
2468 prwatch32_t *pwp;
2469 int nwarea;
2470 struct watched_area *pwarea;
2472 ASSERT(pnp->pr_type == PR_WATCH);
2474 if ((error = prlock(pnp, ZNO)) != 0)
2475 return (error);
2477 p = pnp->pr_common->prc_proc;
2478 if (PROCESS_NOT_32BIT(p)) {
2479 prunlock(pnp);
2480 return (EOVERFLOW);
2482 nwarea = avl_numnodes(&p->p_warea);
2483 size = nwarea * sizeof (prwatch32_t);
2484 if (uiop->uio_offset >= size) {
2485 prunlock(pnp);
2486 return (0);
2489 /* drop p->p_lock to do kmem_alloc(KM_SLEEP) */
2490 mutex_exit(&p->p_lock);
2491 Bpwp = pwp = kmem_zalloc(size, KM_SLEEP);
2492 mutex_enter(&p->p_lock);
2493 /* p->p_nwarea can't change while process is locked */
2494 ASSERT(nwarea == avl_numnodes(&p->p_warea));
2496 /* gather the watched areas */
2497 for (pwarea = avl_first(&p->p_warea); pwarea != NULL;
2498 pwarea = AVL_NEXT(&p->p_warea, pwarea), pwp++) {
2499 pwp->pr_vaddr = (caddr32_t)(uintptr_t)pwarea->wa_vaddr;
2500 pwp->pr_size = (size32_t)(pwarea->wa_eaddr - pwarea->wa_vaddr);
2501 pwp->pr_wflags = (int)pwarea->wa_flags;
2504 prunlock(pnp);
2506 error = pr_uioread(Bpwp, size, uiop);
2507 kmem_free(Bpwp, size);
2508 return (error);
2511 static int
2512 pr_read_lwpstatus_32(prnode_t *pnp, uio_t *uiop)
2514 lwpstatus32_t *sp;
2515 proc_t *p;
2516 int error;
2518 ASSERT(pnp->pr_type == PR_LWPSTATUS);
2521 * We kmem_alloc() the lwpstatus structure because
2522 * it is so big it might blow the kernel stack.
2524 sp = kmem_alloc(sizeof (*sp), KM_SLEEP);
2526 if ((error = prlock(pnp, ZNO)) != 0)
2527 goto out;
2530 * A 32-bit process cannot get the status of a 64-bit process.
2531 * The fields for the 64-bit quantities are not large enough.
2533 p = pnp->pr_common->prc_proc;
2534 if (PROCESS_NOT_32BIT(p)) {
2535 prunlock(pnp);
2536 error = EOVERFLOW;
2537 goto out;
2540 if (uiop->uio_offset >= sizeof (*sp)) {
2541 prunlock(pnp);
2542 goto out;
2545 prgetlwpstatus32(pnp->pr_common->prc_thread, sp, VTOZONE(PTOV(pnp)));
2546 prunlock(pnp);
2548 error = pr_uioread(sp, sizeof (*sp), uiop);
2549 out:
2550 kmem_free(sp, sizeof (*sp));
2551 return (error);
2554 static int
2555 pr_read_lwpsinfo_32(prnode_t *pnp, uio_t *uiop)
2557 lwpsinfo32_t lwpsinfo;
2558 proc_t *p;
2559 kthread_t *t;
2560 lwpent_t *lep;
2562 ASSERT(pnp->pr_type == PR_LWPSINFO);
2565 * We don't want the full treatment of prlock(pnp) here.
2566 * This file is world-readable and never goes invalid.
2567 * It doesn't matter if we are in the middle of an exec().
2569 p = pr_p_lock(pnp);
2570 mutex_exit(&pr_pidlock);
2571 if (p == NULL)
2572 return (ENOENT);
2573 ASSERT(p == pnp->pr_common->prc_proc);
2574 if (pnp->pr_common->prc_tslot == -1) {
2575 prunlock(pnp);
2576 return (ENOENT);
2579 if (uiop->uio_offset >= sizeof (lwpsinfo)) {
2580 prunlock(pnp);
2581 return (0);
2584 if ((t = pnp->pr_common->prc_thread) != NULL)
2585 prgetlwpsinfo32(t, &lwpsinfo);
2586 else {
2587 lep = p->p_lwpdir[pnp->pr_common->prc_tslot].ld_entry;
2588 bzero(&lwpsinfo, sizeof (lwpsinfo));
2589 lwpsinfo.pr_lwpid = lep->le_lwpid;
2590 lwpsinfo.pr_state = SZOMB;
2591 lwpsinfo.pr_sname = 'Z';
2592 lwpsinfo.pr_start.tv_sec = (time32_t)lep->le_start;
2594 prunlock(pnp);
2596 return (pr_uioread(&lwpsinfo, sizeof (lwpsinfo), uiop));
2599 static int
2600 pr_read_lwpusage_32(prnode_t *pnp, uio_t *uiop)
2602 prhusage_t *pup;
2603 prusage32_t *upup;
2604 proc_t *p;
2605 int error;
2607 ASSERT(pnp->pr_type == PR_LWPUSAGE);
2609 /* allocate now, before locking the process */
2610 pup = kmem_zalloc(sizeof (*pup), KM_SLEEP);
2611 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2614 * We don't want the full treatment of prlock(pnp) here.
2615 * This file is world-readable and never goes invalid.
2616 * It doesn't matter if we are in the middle of an exec().
2618 p = pr_p_lock(pnp);
2619 mutex_exit(&pr_pidlock);
2620 if (p == NULL) {
2621 error = ENOENT;
2622 goto out;
2624 ASSERT(p == pnp->pr_common->prc_proc);
2625 if (pnp->pr_common->prc_thread == NULL) {
2626 prunlock(pnp);
2627 error = ENOENT;
2628 goto out;
2630 if (uiop->uio_offset >= sizeof (prusage32_t)) {
2631 prunlock(pnp);
2632 error = 0;
2633 goto out;
2636 pup->pr_tstamp = gethrtime();
2637 prgetusage(pnp->pr_common->prc_thread, pup);
2639 prunlock(pnp);
2641 prcvtusage32(pup, upup);
2643 error = pr_uioread(upup, sizeof (prusage32_t), uiop);
2644 out:
2645 kmem_free(pup, sizeof (*pup));
2646 kmem_free(upup, sizeof (*upup));
2647 return (error);
2650 static int
2651 pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop)
2653 psinfo32_t psinfo;
2654 int error;
2655 klwp_t *lwp;
2657 ASSERT(pnp->pr_type == PR_SPYMASTER);
2659 if ((error = prlock(pnp, ZNO)) != 0)
2660 return (error);
2662 if (pnp->pr_common->prc_thread == NULL) {
2663 prunlock(pnp);
2664 return (0);
2667 lwp = pnp->pr_common->prc_thread->t_lwp;
2669 if (lwp->lwp_spymaster == NULL) {
2670 prunlock(pnp);
2671 return (0);
2674 psinfo_kto32(lwp->lwp_spymaster, &psinfo);
2675 prunlock(pnp);
2677 return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
2680 #if defined(__sparc)
2681 static int
2682 pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop)
2684 proc_t *p;
2685 kthread_t *t;
2686 gwindows32_t *gwp;
2687 int error;
2688 size_t size;
2690 ASSERT(pnp->pr_type == PR_GWINDOWS);
2692 gwp = kmem_zalloc(sizeof (gwindows32_t), KM_SLEEP);
2694 if ((error = prlock(pnp, ZNO)) != 0)
2695 goto out;
2697 p = pnp->pr_common->prc_proc;
2698 t = pnp->pr_common->prc_thread;
2700 if (PROCESS_NOT_32BIT(p)) {
2701 prunlock(pnp);
2702 error = EOVERFLOW;
2703 goto out;
2707 * Drop p->p_lock while touching the stack.
2708 * The P_PR_LOCK flag prevents the lwp from
2709 * disappearing while we do this.
2711 mutex_exit(&p->p_lock);
2712 if ((size = prnwindows(ttolwp(t))) != 0)
2713 size = sizeof (gwindows32_t) -
2714 (SPARC_MAXREGWINDOW - size) * sizeof (struct rwindow32);
2715 if (uiop->uio_offset >= size) {
2716 mutex_enter(&p->p_lock);
2717 prunlock(pnp);
2718 goto out;
2720 prgetwindows32(ttolwp(t), gwp);
2721 mutex_enter(&p->p_lock);
2722 prunlock(pnp);
2724 error = pr_uioread(gwp, size, uiop);
2725 out:
2726 kmem_free(gwp, sizeof (gwindows32_t));
2727 return (error);
2729 #endif /* __sparc */
2731 #endif /* _SYSCALL32_IMPL */
2733 /* ARGSUSED */
2734 static int
2735 prread(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2737 prnode_t *pnp = VTOP(vp);
2739 ASSERT(pnp->pr_type < PR_NFILES);
2741 #ifdef _SYSCALL32_IMPL
2743 * What is read from the /proc files depends on the data
2744 * model of the caller. An LP64 process will see LP64
2745 * data. An ILP32 process will see ILP32 data.
2747 if (curproc->p_model == DATAMODEL_LP64)
2748 return (pr_read_function[pnp->pr_type](pnp, uiop));
2749 else
2750 return (pr_read_function_32[pnp->pr_type](pnp, uiop));
2751 #else
2752 return (pr_read_function[pnp->pr_type](pnp, uiop));
2753 #endif
2756 /* Note we intentionally don't handle partial writes/updates. */
2757 static int
2758 pr_write_lwpname(prnode_t *pnp, uio_t *uiop)
2760 kthread_t *t = NULL;
2761 char *lwpname;
2762 int error;
2764 lwpname = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
2766 if ((error = uiomove(lwpname, THREAD_NAME_MAX, UIO_WRITE, uiop)) != 0) {
2767 kmem_free(lwpname, THREAD_NAME_MAX);
2768 return (error);
2771 /* Somebody tried to write too long a thread name... */
2772 if (lwpname[THREAD_NAME_MAX - 1] != '\0' || uiop->uio_resid > 0) {
2773 kmem_free(lwpname, THREAD_NAME_MAX);
2774 return (EIO);
2777 VERIFY3U(lwpname[THREAD_NAME_MAX - 1], ==, '\0');
2779 for (size_t i = 0; lwpname[i] != '\0'; i++) {
2780 if (!ISPRINT(lwpname[i])) {
2781 kmem_free(lwpname, THREAD_NAME_MAX);
2782 return (EINVAL);
2786 /* Equivalent of thread_setname(), but with the ZNO magic. */
2787 if ((error = prlock(pnp, ZNO)) != 0) {
2788 kmem_free(lwpname, THREAD_NAME_MAX);
2789 return (error);
2792 t = pnp->pr_common->prc_thread;
2793 if (t->t_name == NULL) {
2794 t->t_name = lwpname;
2795 } else {
2796 (void) strlcpy(t->t_name, lwpname, THREAD_NAME_MAX);
2797 kmem_free(lwpname, THREAD_NAME_MAX);
2800 prunlock(pnp);
2801 return (0);
2804 /* ARGSUSED */
2805 static int
2806 prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
2808 prnode_t *pnp = VTOP(vp);
2809 int old = 0;
2810 int error;
2811 ssize_t resid;
2813 ASSERT(pnp->pr_type < PR_NFILES);
2816 * Only a handful of /proc files are writable, enumerate them here.
2818 switch (pnp->pr_type) {
2819 case PR_PIDDIR: /* directory write()s: visceral revulsion. */
2820 ASSERT(pnp->pr_pidfile != NULL);
2821 /* use the underlying PR_PIDFILE to write the process */
2822 vp = pnp->pr_pidfile;
2823 pnp = VTOP(vp);
2824 ASSERT(pnp->pr_type == PR_PIDFILE);
2825 /* FALLTHROUGH */
2826 case PR_PIDFILE:
2827 case PR_LWPIDFILE:
2828 old = 1;
2829 /* FALLTHROUGH */
2830 case PR_AS:
2831 if ((error = prlock(pnp, ZNO)) == 0) {
2832 proc_t *p = pnp->pr_common->prc_proc;
2833 struct as *as = p->p_as;
2835 if ((p->p_flag & SSYS) || as == &kas) {
2837 * /proc I/O cannot be done to a system process.
2839 error = EIO;
2840 #ifdef _SYSCALL32_IMPL
2841 } else if (curproc->p_model == DATAMODEL_ILP32 &&
2842 PROCESS_NOT_32BIT(p)) {
2843 error = EOVERFLOW;
2844 #endif
2845 } else {
2847 * See comments above (pr_read_pidfile)
2848 * about this locking dance.
2850 mutex_exit(&p->p_lock);
2851 error = prusrio(p, UIO_WRITE, uiop, old);
2852 mutex_enter(&p->p_lock);
2854 prunlock(pnp);
2856 return (error);
2858 case PR_CTL:
2859 case PR_LWPCTL:
2860 resid = uiop->uio_resid;
2862 * Perform the action on the control file
2863 * by passing curthreads credentials
2864 * and not target process's credentials.
2866 #ifdef _SYSCALL32_IMPL
2867 if (curproc->p_model == DATAMODEL_ILP32)
2868 error = prwritectl32(vp, uiop, CRED());
2869 else
2870 error = prwritectl(vp, uiop, CRED());
2871 #else
2872 error = prwritectl(vp, uiop, CRED());
2873 #endif
2875 * This hack makes sure that the EINTR is passed
2876 * all the way back to the caller's write() call.
2878 if (error == EINTR)
2879 uiop->uio_resid = resid;
2880 return (error);
2882 case PR_LWPNAME:
2883 return (pr_write_lwpname(pnp, uiop));
2885 default:
2886 return ((vp->v_type == VDIR)? EISDIR : EBADF);
2888 /* NOTREACHED */
2891 static int
2892 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
2893 caller_context_t *ct)
2895 prnode_t *pnp = VTOP(vp);
2896 prnodetype_t type = pnp->pr_type;
2897 prcommon_t *pcp;
2898 proc_t *p;
2899 struct as *as;
2900 int error;
2901 vnode_t *rvp;
2902 timestruc_t now;
2903 extern uint_t nproc;
2904 int ngroups;
2905 int nsig;
2908 * This ugly bit of code allows us to keep both versions of this
2909 * function from the same source.
2911 #ifdef _LP64
2912 int iam32bit = (curproc->p_model == DATAMODEL_ILP32);
2913 #define PR_OBJSIZE(obj32, obj64) \
2914 (iam32bit ? sizeof (obj32) : sizeof (obj64))
2915 #define PR_OBJSPAN(obj32, obj64) \
2916 (iam32bit ? LSPAN32(obj32) : LSPAN(obj64))
2917 #else
2918 #define PR_OBJSIZE(obj32, obj64) \
2919 (sizeof (obj64))
2920 #define PR_OBJSPAN(obj32, obj64) \
2921 (LSPAN(obj64))
2922 #endif
2925 * Return all the attributes. Should be refined
2926 * so that it returns only those asked for.
2927 * Most of this is complete fakery anyway.
2931 * For files in the /proc/<pid>/object directory,
2932 * return the attributes of the underlying object.
2933 * For files in the /proc/<pid>/fd directory,
2934 * return the attributes of the underlying file, but
2935 * make it look inaccessible if it is not a regular file.
2936 * Make directories look like symlinks.
2938 switch (type) {
2939 case PR_CURDIR:
2940 case PR_ROOTDIR:
2941 if (!(flags & ATTR_REAL))
2942 break;
2943 /* restrict full knowledge of the attributes to owner or root */
2944 if ((error = praccess(vp, 0, 0, cr, ct)) != 0)
2945 return (error);
2946 /* FALLTHROUGH */
2947 case PR_OBJECT:
2948 case PR_FD:
2949 rvp = pnp->pr_realvp;
2950 error = VOP_GETATTR(rvp, vap, flags, cr, ct);
2951 if (error)
2952 return (error);
2953 if (type == PR_FD) {
2954 if (rvp->v_type != VREG && rvp->v_type != VDIR)
2955 vap->va_mode = 0;
2956 else
2957 vap->va_mode &= pnp->pr_mode;
2959 if (type == PR_OBJECT)
2960 vap->va_mode &= 07555;
2961 if (rvp->v_type == VDIR && !(flags & ATTR_REAL)) {
2962 vap->va_type = VLNK;
2963 vap->va_size = 0;
2964 vap->va_nlink = 1;
2966 return (0);
2967 default:
2968 break;
2971 bzero(vap, sizeof (*vap));
2973 * Large Files: Internally proc now uses VPROC to indicate
2974 * a proc file. Since we have been returning VREG through
2975 * VOP_GETATTR() until now, we continue to do this so as
2976 * not to break apps depending on this return value.
2978 vap->va_type = (vp->v_type == VPROC) ? VREG : vp->v_type;
2979 vap->va_mode = pnp->pr_mode;
2980 vap->va_fsid = vp->v_vfsp->vfs_dev;
2981 vap->va_blksize = DEV_BSIZE;
2982 vap->va_rdev = 0;
2983 vap->va_seq = 0;
2985 if (type == PR_PROCDIR) {
2986 vap->va_uid = 0;
2987 vap->va_gid = 0;
2988 vap->va_nlink = nproc + 2;
2989 vap->va_nodeid = (ino64_t)PRROOTINO;
2990 gethrestime(&now);
2991 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
2992 vap->va_size = (v.v_proc + 2) * PRSDSIZE;
2993 vap->va_nblocks = btod(vap->va_size);
2994 return (0);
2998 * /proc/<pid>/self is a symbolic link, and has no prcommon member
3000 if (type == PR_SELF) {
3001 vap->va_uid = crgetruid(CRED());
3002 vap->va_gid = crgetrgid(CRED());
3003 vap->va_nodeid = (ino64_t)PR_SELF;
3004 gethrestime(&now);
3005 vap->va_atime = vap->va_mtime = vap->va_ctime = now;
3006 vap->va_nlink = 1;
3007 vap->va_type = VLNK;
3008 vap->va_size = 0;
3009 return (0);
3012 p = pr_p_lock(pnp);
3013 mutex_exit(&pr_pidlock);
3014 if (p == NULL)
3015 return (ENOENT);
3016 pcp = pnp->pr_common;
3018 mutex_enter(&p->p_crlock);
3019 vap->va_uid = crgetruid(p->p_cred);
3020 vap->va_gid = crgetrgid(p->p_cred);
3021 mutex_exit(&p->p_crlock);
3023 vap->va_nlink = 1;
3024 vap->va_nodeid = pnp->pr_ino? pnp->pr_ino :
3025 pmkino(pcp->prc_tslot, pcp->prc_slot, pnp->pr_type);
3026 if ((pcp->prc_flags & PRC_LWP) && pcp->prc_tslot != -1) {
3027 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
3028 vap->va_ctime.tv_sec =
3029 p->p_lwpdir[pcp->prc_tslot].ld_entry->le_start;
3030 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
3031 vap->va_ctime.tv_nsec = 0;
3032 } else {
3033 user_t *up = PTOU(p);
3034 vap->va_atime.tv_sec = vap->va_mtime.tv_sec =
3035 vap->va_ctime.tv_sec = up->u_start.tv_sec;
3036 vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec =
3037 vap->va_ctime.tv_nsec = up->u_start.tv_nsec;
3040 switch (type) {
3041 case PR_PIDDIR:
3042 /* va_nlink: count 'lwp', 'object' and 'fd' directory links */
3043 vap->va_nlink = 5;
3044 vap->va_size = sizeof (piddir);
3045 break;
3046 case PR_OBJECTDIR:
3047 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3048 vap->va_size = 2 * PRSDSIZE;
3049 else {
3050 mutex_exit(&p->p_lock);
3051 AS_LOCK_ENTER(as, RW_WRITER);
3052 if (as->a_updatedir)
3053 rebuild_objdir(as);
3054 vap->va_size = (as->a_sizedir + 2) * PRSDSIZE;
3055 AS_LOCK_EXIT(as);
3056 mutex_enter(&p->p_lock);
3058 vap->va_nlink = 2;
3059 break;
3060 case PR_PATHDIR:
3061 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3062 vap->va_size = (P_FINFO(p)->fi_nfiles + 4) * PRSDSIZE;
3063 else {
3064 mutex_exit(&p->p_lock);
3065 AS_LOCK_ENTER(as, RW_WRITER);
3066 if (as->a_updatedir)
3067 rebuild_objdir(as);
3068 vap->va_size = (as->a_sizedir + 4 +
3069 P_FINFO(p)->fi_nfiles) * PRSDSIZE;
3070 AS_LOCK_EXIT(as);
3071 mutex_enter(&p->p_lock);
3073 vap->va_nlink = 2;
3074 break;
3075 case PR_PATH:
3076 case PR_CURDIR:
3077 case PR_ROOTDIR:
3078 case PR_CT:
3079 vap->va_type = VLNK;
3080 vap->va_size = 0;
3081 break;
3082 case PR_FDDIR:
3083 vap->va_nlink = 2;
3084 vap->va_size = (P_FINFO(p)->fi_nfiles + 2) * PRSDSIZE;
3085 break;
3086 case PR_LWPDIR:
3088 * va_nlink: count each lwp as a directory link.
3089 * va_size: size of p_lwpdir + 2
3091 vap->va_nlink = p->p_lwpcnt + p->p_zombcnt + 2;
3092 vap->va_size = (p->p_lwpdir_sz + 2) * PRSDSIZE;
3093 break;
3094 case PR_LWPIDDIR:
3095 vap->va_nlink = 2;
3096 vap->va_size = sizeof (lwpiddir);
3097 break;
3098 case PR_CTDIR:
3099 vap->va_nlink = 2;
3100 vap->va_size = (avl_numnodes(&p->p_ct_held) + 2) * PRSDSIZE;
3101 break;
3102 case PR_TMPLDIR:
3103 vap->va_nlink = 2;
3104 vap->va_size = (ct_ntypes + 2) * PRSDSIZE;
3105 break;
3106 case PR_AS:
3107 case PR_PIDFILE:
3108 case PR_LWPIDFILE:
3109 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3110 vap->va_size = 0;
3111 else
3112 vap->va_size = as->a_resvsize;
3113 break;
3114 case PR_STATUS:
3115 vap->va_size = PR_OBJSIZE(pstatus32_t, pstatus_t);
3116 break;
3117 case PR_LSTATUS:
3118 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3119 p->p_lwpcnt * PR_OBJSPAN(lwpstatus32_t, lwpstatus_t);
3120 break;
3121 case PR_PSINFO:
3122 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3123 break;
3124 case PR_LPSINFO:
3125 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3126 (p->p_lwpcnt + p->p_zombcnt) *
3127 PR_OBJSPAN(lwpsinfo32_t, lwpsinfo_t);
3128 break;
3129 case PR_MAP:
3130 case PR_RMAP:
3131 case PR_XMAP:
3132 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3133 vap->va_size = 0;
3134 else {
3135 mutex_exit(&p->p_lock);
3136 AS_LOCK_ENTER(as, RW_WRITER);
3137 if (type == PR_MAP)
3138 vap->va_mtime = as->a_updatetime;
3139 if (type == PR_XMAP)
3140 vap->va_size = prnsegs(as, 0) *
3141 PR_OBJSIZE(prxmap32_t, prxmap_t);
3142 else
3143 vap->va_size = prnsegs(as, type == PR_RMAP) *
3144 PR_OBJSIZE(prmap32_t, prmap_t);
3145 AS_LOCK_EXIT(as);
3146 mutex_enter(&p->p_lock);
3148 break;
3149 case PR_CRED:
3150 mutex_enter(&p->p_crlock);
3151 vap->va_size = sizeof (prcred_t);
3152 ngroups = crgetngroups(p->p_cred);
3153 if (ngroups > 1)
3154 vap->va_size += (ngroups - 1) * sizeof (gid_t);
3155 mutex_exit(&p->p_crlock);
3156 break;
3157 case PR_PRIV:
3158 vap->va_size = prgetprivsize();
3159 break;
3160 case PR_SECFLAGS:
3161 vap->va_size = sizeof (prsecflags_t);
3162 break;
3163 case PR_SIGACT:
3164 nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
3165 vap->va_size = (nsig-1) *
3166 PR_OBJSIZE(struct sigaction32, struct sigaction);
3167 break;
3168 case PR_AUXV:
3169 vap->va_size = __KERN_NAUXV_IMPL * PR_OBJSIZE(auxv32_t, auxv_t);
3170 break;
3171 #if defined(__x86)
3172 case PR_LDT:
3173 mutex_exit(&p->p_lock);
3174 mutex_enter(&p->p_ldtlock);
3175 vap->va_size = prnldt(p) * sizeof (struct ssd);
3176 mutex_exit(&p->p_ldtlock);
3177 mutex_enter(&p->p_lock);
3178 break;
3179 #endif
3180 case PR_USAGE:
3181 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3182 break;
3183 case PR_LUSAGE:
3184 vap->va_size = PR_OBJSIZE(prheader32_t, prheader_t) +
3185 (p->p_lwpcnt + 1) * PR_OBJSPAN(prusage32_t, prusage_t);
3186 break;
3187 case PR_PAGEDATA:
3188 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3189 vap->va_size = 0;
3190 else {
3192 * We can drop p->p_lock before grabbing the
3193 * address space lock because p->p_as will not
3194 * change while the process is marked P_PR_LOCK.
3196 mutex_exit(&p->p_lock);
3197 AS_LOCK_ENTER(as, RW_WRITER);
3198 #ifdef _LP64
3199 vap->va_size = iam32bit?
3200 prpdsize32(as) : prpdsize(as);
3201 #else
3202 vap->va_size = prpdsize(as);
3203 #endif
3204 AS_LOCK_EXIT(as);
3205 mutex_enter(&p->p_lock);
3207 break;
3208 case PR_OPAGEDATA:
3209 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas)
3210 vap->va_size = 0;
3211 else {
3212 mutex_exit(&p->p_lock);
3213 AS_LOCK_ENTER(as, RW_WRITER);
3214 #ifdef _LP64
3215 vap->va_size = iam32bit?
3216 oprpdsize32(as) : oprpdsize(as);
3217 #else
3218 vap->va_size = oprpdsize(as);
3219 #endif
3220 AS_LOCK_EXIT(as);
3221 mutex_enter(&p->p_lock);
3223 break;
3224 case PR_WATCH:
3225 vap->va_size = avl_numnodes(&p->p_warea) *
3226 PR_OBJSIZE(prwatch32_t, prwatch_t);
3227 break;
3228 case PR_LWPSTATUS:
3229 vap->va_size = PR_OBJSIZE(lwpstatus32_t, lwpstatus_t);
3230 break;
3231 case PR_LWPSINFO:
3232 vap->va_size = PR_OBJSIZE(lwpsinfo32_t, lwpsinfo_t);
3233 break;
3234 case PR_LWPUSAGE:
3235 vap->va_size = PR_OBJSIZE(prusage32_t, prusage_t);
3236 break;
3237 case PR_XREGS:
3238 if (prhasx(p))
3239 vap->va_size = prgetprxregsize(p);
3240 else
3241 vap->va_size = 0;
3242 break;
3243 case PR_SPYMASTER:
3244 if (pnp->pr_common->prc_thread != NULL &&
3245 pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) {
3246 vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t);
3247 } else {
3248 vap->va_size = 0;
3250 break;
3251 #if defined(__sparc)
3252 case PR_GWINDOWS:
3254 kthread_t *t;
3255 int n;
3258 * If there is no lwp then just make the size zero.
3259 * This can happen if the lwp exits between the VOP_LOOKUP()
3260 * of the /proc/<pid>/lwp/<lwpid>/gwindows file and the
3261 * VOP_GETATTR() of the resulting vnode.
3263 if ((t = pcp->prc_thread) == NULL) {
3264 vap->va_size = 0;
3265 break;
3268 * Drop p->p_lock while touching the stack.
3269 * The P_PR_LOCK flag prevents the lwp from
3270 * disappearing while we do this.
3272 mutex_exit(&p->p_lock);
3273 if ((n = prnwindows(ttolwp(t))) == 0)
3274 vap->va_size = 0;
3275 else
3276 vap->va_size = PR_OBJSIZE(gwindows32_t, gwindows_t) -
3277 (SPARC_MAXREGWINDOW - n) *
3278 PR_OBJSIZE(struct rwindow32, struct rwindow);
3279 mutex_enter(&p->p_lock);
3280 break;
3282 case PR_ASRS:
3283 #ifdef _LP64
3284 if (p->p_model == DATAMODEL_LP64)
3285 vap->va_size = sizeof (asrset_t);
3286 else
3287 #endif
3288 vap->va_size = 0;
3289 break;
3290 #endif
3291 case PR_CTL:
3292 case PR_LWPCTL:
3293 default:
3294 vap->va_size = 0;
3295 break;
3298 prunlock(pnp);
3299 vap->va_nblocks = (fsblkcnt64_t)btod(vap->va_size);
3300 return (0);
3303 static int
3304 praccess(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
3306 prnode_t *pnp = VTOP(vp);
3307 prnodetype_t type = pnp->pr_type;
3308 int vmode;
3309 vtype_t vtype;
3310 proc_t *p;
3311 int error = 0;
3312 vnode_t *rvp;
3313 vnode_t *xvp;
3315 if ((mode & VWRITE) && vn_is_readonly(vp))
3316 return (EROFS);
3318 switch (type) {
3319 case PR_PROCDIR:
3320 break;
3322 case PR_OBJECT:
3323 case PR_FD:
3325 * Disallow write access to the underlying objects.
3326 * Disallow access to underlying non-regular-file fds.
3327 * Disallow access to fds with other than existing open modes.
3329 rvp = pnp->pr_realvp;
3330 vtype = rvp->v_type;
3331 vmode = pnp->pr_mode;
3332 if ((type == PR_OBJECT && (mode & VWRITE)) ||
3333 (type == PR_FD && vtype != VREG && vtype != VDIR) ||
3334 (type == PR_FD && (vmode & mode) != mode &&
3335 secpolicy_proc_access(cr) != 0))
3336 return (EACCES);
3337 return (VOP_ACCESS(rvp, mode, flags, cr, ct));
3339 case PR_PSINFO: /* these files can be read by anyone */
3340 case PR_LPSINFO:
3341 case PR_LWPSINFO:
3342 case PR_LWPDIR:
3343 case PR_LWPIDDIR:
3344 case PR_USAGE:
3345 case PR_LUSAGE:
3346 case PR_LWPUSAGE:
3347 p = pr_p_lock(pnp);
3348 mutex_exit(&pr_pidlock);
3349 if (p == NULL)
3350 return (ENOENT);
3351 prunlock(pnp);
3352 break;
3354 default:
3356 * Except for the world-readable files above,
3357 * only /proc/pid exists if the process is a zombie.
3359 if ((error = prlock(pnp,
3360 (type == PR_PIDDIR)? ZYES : ZNO)) != 0)
3361 return (error);
3362 p = pnp->pr_common->prc_proc;
3363 if (p != curproc)
3364 error = priv_proc_cred_perm(cr, p, NULL, mode);
3366 if (error != 0 || p == curproc || (p->p_flag & SSYS) ||
3367 p->p_as == &kas || (xvp = p->p_exec) == NULL) {
3368 prunlock(pnp);
3369 } else {
3371 * Determine if the process's executable is readable.
3372 * We have to drop p->p_lock before the secpolicy
3373 * and VOP operation.
3375 VN_HOLD(xvp);
3376 prunlock(pnp);
3377 if (secpolicy_proc_access(cr) != 0)
3378 error = VOP_ACCESS(xvp, VREAD, 0, cr, ct);
3379 VN_RELE(xvp);
3381 if (error)
3382 return (error);
3383 break;
3386 if (type == PR_CURDIR || type == PR_ROOTDIR) {
3388 * Final access check on the underlying directory vnode.
3390 return (VOP_ACCESS(pnp->pr_realvp, mode, flags, cr, ct));
3394 * Visceral revulsion: For compatibility with old /proc,
3395 * allow the /proc/<pid> directory to be opened for writing.
3397 vmode = pnp->pr_mode;
3398 if (type == PR_PIDDIR)
3399 vmode |= VWRITE;
3400 if ((vmode & mode) != mode)
3401 error = secpolicy_proc_access(cr);
3402 return (error);
3406 * Array of lookup functions, indexed by /proc file type.
3408 static vnode_t *pr_lookup_notdir(), *pr_lookup_procdir(), *pr_lookup_piddir(),
3409 *pr_lookup_objectdir(), *pr_lookup_lwpdir(), *pr_lookup_lwpiddir(),
3410 *pr_lookup_fddir(), *pr_lookup_pathdir(), *pr_lookup_tmpldir(),
3411 *pr_lookup_ctdir();
3413 static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
3414 pr_lookup_procdir, /* /proc */
3415 pr_lookup_notdir, /* /proc/self */
3416 pr_lookup_piddir, /* /proc/<pid> */
3417 pr_lookup_notdir, /* /proc/<pid>/as */
3418 pr_lookup_notdir, /* /proc/<pid>/ctl */
3419 pr_lookup_notdir, /* /proc/<pid>/status */
3420 pr_lookup_notdir, /* /proc/<pid>/lstatus */
3421 pr_lookup_notdir, /* /proc/<pid>/psinfo */
3422 pr_lookup_notdir, /* /proc/<pid>/lpsinfo */
3423 pr_lookup_notdir, /* /proc/<pid>/map */
3424 pr_lookup_notdir, /* /proc/<pid>/rmap */
3425 pr_lookup_notdir, /* /proc/<pid>/xmap */
3426 pr_lookup_notdir, /* /proc/<pid>/cred */
3427 pr_lookup_notdir, /* /proc/<pid>/sigact */
3428 pr_lookup_notdir, /* /proc/<pid>/auxv */
3429 #if defined(__x86)
3430 pr_lookup_notdir, /* /proc/<pid>/ldt */
3431 #endif
3432 pr_lookup_notdir, /* /proc/<pid>/usage */
3433 pr_lookup_notdir, /* /proc/<pid>/lusage */
3434 pr_lookup_notdir, /* /proc/<pid>/pagedata */
3435 pr_lookup_notdir, /* /proc/<pid>/watch */
3436 pr_lookup_notdir, /* /proc/<pid>/cwd */
3437 pr_lookup_notdir, /* /proc/<pid>/root */
3438 pr_lookup_fddir, /* /proc/<pid>/fd */
3439 pr_lookup_notdir, /* /proc/<pid>/fd/nn */
3440 pr_lookup_objectdir, /* /proc/<pid>/object */
3441 pr_lookup_notdir, /* /proc/<pid>/object/xxx */
3442 pr_lookup_lwpdir, /* /proc/<pid>/lwp */
3443 pr_lookup_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
3444 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
3445 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
3446 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
3447 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
3448 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
3449 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
3450 pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
3451 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
3452 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
3453 #if defined(__sparc)
3454 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
3455 pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
3456 #endif
3457 pr_lookup_notdir, /* /proc/<pid>/priv */
3458 pr_lookup_pathdir, /* /proc/<pid>/path */
3459 pr_lookup_notdir, /* /proc/<pid>/path/xxx */
3460 pr_lookup_ctdir, /* /proc/<pid>/contracts */
3461 pr_lookup_notdir, /* /proc/<pid>/contracts/<ctid> */
3462 pr_lookup_notdir, /* /proc/<pid>/secflags */
3463 pr_lookup_notdir, /* old process file */
3464 pr_lookup_notdir, /* old lwp file */
3465 pr_lookup_notdir, /* old pagedata file */
3468 static int
3469 prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
3470 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
3471 int *direntflags, pathname_t *realpnp)
3473 prnode_t *pnp = VTOP(dp);
3474 prnodetype_t type = pnp->pr_type;
3475 int error;
3477 ASSERT(dp->v_type == VDIR);
3478 ASSERT(type < PR_NFILES);
3480 if (type != PR_PROCDIR && strcmp(comp, "..") == 0) {
3481 VN_HOLD(pnp->pr_parent);
3482 *vpp = pnp->pr_parent;
3483 return (0);
3486 if (*comp == '\0' ||
3487 strcmp(comp, ".") == 0 || strcmp(comp, "..") == 0) {
3488 VN_HOLD(dp);
3489 *vpp = dp;
3490 return (0);
3493 switch (type) {
3494 case PR_CURDIR:
3495 case PR_ROOTDIR:
3496 /* restrict lookup permission to owner or root */
3497 if ((error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3498 return (error);
3499 /* FALLTHROUGH */
3500 case PR_FD:
3502 * Performing a VOP_LOOKUP on the underlying vnode and emitting
3503 * the resulting vnode, without encapsulation, as our own is a
3504 * very special case when it comes to the assumptions built
3505 * into VFS.
3507 * Since the resulting vnode is highly likely to be at some
3508 * abitrary position in another filesystem, we insist that the
3509 * VTRAVERSE flag is set on the parent. This prevents things
3510 * such as the v_path freshness logic from mistaking the
3511 * resulting vnode as a "real" child of the parent, rather than
3512 * a consequence of this "procfs wormhole".
3514 * Failure to establish such protections can lead to
3515 * incorrectly calculated v_paths being set on nodes reached
3516 * through these lookups.
3518 ASSERT((dp->v_flag & VTRAVERSE) != 0);
3520 dp = pnp->pr_realvp;
3521 return (VOP_LOOKUP(dp, comp, vpp, pathp, flags, rdir, cr, ct,
3522 direntflags, realpnp));
3523 default:
3524 break;
3527 if ((type == PR_OBJECTDIR || type == PR_FDDIR || type == PR_PATHDIR) &&
3528 (error = praccess(dp, VEXEC, 0, cr, ct)) != 0)
3529 return (error);
3531 /* XXX - Do we need to pass ct, direntflags, or realpnp? */
3532 *vpp = (pr_lookup_function[type](dp, comp));
3534 return ((*vpp == NULL) ? ENOENT : 0);
3537 /* ARGSUSED */
3538 static int
3539 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
3540 int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
3541 vsecattr_t *vsecp)
3543 int error;
3545 if ((error = prlookup(dp, comp, vpp, NULL, 0, NULL, cr,
3546 ct, NULL, NULL)) != 0) {
3547 if (error == ENOENT) {
3548 /* One can't O_CREAT nonexistent files in /proc. */
3549 error = EACCES;
3551 return (error);
3554 if (excl == EXCL) {
3555 /* Disallow the O_EXCL case */
3556 error = EEXIST;
3557 } else if ((error = praccess(*vpp, mode, 0, cr, ct)) == 0) {
3558 /* Before proceeding, handle O_TRUNC if necessary. */
3559 if (vap->va_mask & AT_SIZE) {
3560 vnode_t *vp = *vpp;
3562 if (vp->v_type == VDIR) {
3563 /* Only allow O_TRUNC on files */
3564 error = EISDIR;
3565 } else if (vp->v_type != VPROC ||
3566 VTOP(vp)->pr_type != PR_FD) {
3568 * Disallow for files outside of the
3569 * /proc/<pid>/fd/<n> entries
3571 error = EACCES;
3572 } else {
3573 uint_t mask;
3575 vp = VTOP(vp)->pr_realvp;
3576 mask = vap->va_mask;
3577 vap->va_mask = AT_SIZE;
3578 error = VOP_SETATTR(vp, vap, 0, cr, ct);
3579 vap->va_mask = mask;
3584 if (error) {
3585 VN_RELE(*vpp);
3586 *vpp = NULL;
3588 return (error);
3591 /* ARGSUSED */
3592 static vnode_t *
3593 pr_lookup_notdir(vnode_t *dp, char *comp)
3595 return (NULL);
3599 * Find or construct a process vnode for the given pid.
3601 static vnode_t *
3602 pr_lookup_procdir(vnode_t *dp, char *comp)
3604 pid_t pid;
3605 prnode_t *pnp;
3606 prcommon_t *pcp;
3607 vnode_t *vp;
3608 proc_t *p;
3609 int c;
3611 ASSERT(VTOP(dp)->pr_type == PR_PROCDIR);
3613 if (strcmp(comp, "self") == 0) {
3614 pnp = prgetnode(dp, PR_SELF);
3615 return (PTOV(pnp));
3616 } else {
3617 pid = 0;
3618 while ((c = *comp++) != '\0') {
3619 if (c < '0' || c > '9')
3620 return (NULL);
3621 pid = 10*pid + c - '0';
3622 if (pid > maxpid)
3623 return (NULL);
3627 pnp = prgetnode(dp, PR_PIDDIR);
3629 mutex_enter(&pidlock);
3630 if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
3631 mutex_exit(&pidlock);
3632 prfreenode(pnp);
3633 return (NULL);
3635 ASSERT(p->p_stat != 0);
3637 /* NOTE: we're holding pidlock across the policy call. */
3638 if (secpolicy_basic_procinfo(CRED(), p, curproc) != 0) {
3639 mutex_exit(&pidlock);
3640 prfreenode(pnp);
3641 return (NULL);
3644 mutex_enter(&p->p_lock);
3645 mutex_exit(&pidlock);
3648 * If a process vnode already exists and it is not invalid
3649 * and it was created by the current process and it belongs
3650 * to the same /proc mount point as our parent vnode, then
3651 * just use it and discard the newly-allocated prnode.
3653 for (vp = p->p_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3654 if (!(VTOP(VTOP(vp)->pr_pidfile)->pr_flags & PR_INVAL) &&
3655 VTOP(vp)->pr_owner == curproc &&
3656 vp->v_vfsp == dp->v_vfsp) {
3657 ASSERT(!(VTOP(vp)->pr_flags & PR_INVAL));
3658 VN_HOLD(vp);
3659 prfreenode(pnp);
3660 mutex_exit(&p->p_lock);
3661 return (vp);
3664 pnp->pr_owner = curproc;
3667 * prgetnode() initialized most of the prnode.
3668 * Finish the job.
3670 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
3671 if ((vp = p->p_trace) != NULL) {
3672 /* discard the new prcommon and use the existing prcommon */
3673 prfreecommon(pcp);
3674 pcp = VTOP(vp)->pr_common;
3675 mutex_enter(&pcp->prc_mutex);
3676 ASSERT(pcp->prc_refcnt > 0);
3677 pcp->prc_refcnt++;
3678 mutex_exit(&pcp->prc_mutex);
3679 pnp->pr_common = pcp;
3680 } else {
3681 /* initialize the new prcommon struct */
3682 if ((p->p_flag & SSYS) || p->p_as == &kas)
3683 pcp->prc_flags |= PRC_SYS;
3684 if (p->p_stat == SZOMB || (p->p_flag & SEXITING) != 0)
3685 pcp->prc_flags |= PRC_DESTROY;
3686 pcp->prc_proc = p;
3687 pcp->prc_datamodel = p->p_model;
3688 pcp->prc_pid = p->p_pid;
3689 pcp->prc_slot = p->p_slot;
3691 pnp->pr_pcommon = pcp;
3692 pnp->pr_parent = dp;
3693 VN_HOLD(dp);
3695 * Link in the old, invalid directory vnode so we
3696 * can later determine the last close of the file.
3698 pnp->pr_next = p->p_trace;
3699 p->p_trace = dp = PTOV(pnp);
3702 * Kludge for old /proc: initialize the PR_PIDFILE as well.
3704 vp = pnp->pr_pidfile;
3705 pnp = VTOP(vp);
3706 pnp->pr_ino = ptoi(pcp->prc_pid);
3707 pnp->pr_common = pcp;
3708 pnp->pr_pcommon = pcp;
3709 pnp->pr_parent = dp;
3710 pnp->pr_next = p->p_plist;
3711 p->p_plist = vp;
3713 mutex_exit(&p->p_lock);
3714 return (dp);
3717 static vnode_t *
3718 pr_lookup_piddir(vnode_t *dp, char *comp)
3720 prnode_t *dpnp = VTOP(dp);
3721 vnode_t *vp;
3722 prnode_t *pnp;
3723 proc_t *p;
3724 user_t *up;
3725 prdirent_t *dirp;
3726 int i;
3727 enum prnodetype type;
3729 ASSERT(dpnp->pr_type == PR_PIDDIR);
3731 for (i = 0; i < NPIDDIRFILES; i++) {
3732 /* Skip "." and ".." */
3733 dirp = &piddir[i+2];
3734 if (strcmp(comp, dirp->d_name) == 0)
3735 break;
3738 if (i >= NPIDDIRFILES)
3739 return (NULL);
3741 type = (int)dirp->d_ino;
3742 pnp = prgetnode(dp, type);
3744 p = pr_p_lock(dpnp);
3745 mutex_exit(&pr_pidlock);
3746 if (p == NULL) {
3747 prfreenode(pnp);
3748 return (NULL);
3750 if (dpnp->pr_pcommon->prc_flags & PRC_DESTROY) {
3751 switch (type) {
3752 case PR_PSINFO:
3753 case PR_USAGE:
3754 break;
3755 default:
3756 prunlock(dpnp);
3757 prfreenode(pnp);
3758 return (NULL);
3762 switch (type) {
3763 case PR_CURDIR:
3764 case PR_ROOTDIR:
3765 up = PTOU(p);
3766 vp = (type == PR_CURDIR)? up->u_cdir :
3767 (up->u_rdir? up->u_rdir : rootdir);
3769 if (vp == NULL) {
3770 /* can't happen(?) */
3771 prunlock(dpnp);
3772 prfreenode(pnp);
3773 return (NULL);
3776 * Fill in the prnode so future references will
3777 * be able to find the underlying object's vnode.
3779 VN_HOLD(vp);
3780 pnp->pr_realvp = vp;
3781 PTOV(pnp)->v_flag |= VTRAVERSE;
3782 break;
3783 default:
3784 break;
3787 mutex_enter(&dpnp->pr_mutex);
3789 if ((vp = dpnp->pr_files[i]) != NULL &&
3790 !(VTOP(vp)->pr_flags & PR_INVAL)) {
3791 VN_HOLD(vp);
3792 mutex_exit(&dpnp->pr_mutex);
3793 prunlock(dpnp);
3794 prfreenode(pnp);
3795 return (vp);
3799 * prgetnode() initialized most of the prnode.
3800 * Finish the job.
3802 pnp->pr_common = dpnp->pr_common;
3803 pnp->pr_pcommon = dpnp->pr_pcommon;
3804 pnp->pr_parent = dp;
3805 VN_HOLD(dp);
3806 pnp->pr_index = i;
3808 dpnp->pr_files[i] = vp = PTOV(pnp);
3811 * Link new vnode into list of all /proc vnodes for the process.
3813 if (vp->v_type == VPROC) {
3814 pnp->pr_next = p->p_plist;
3815 p->p_plist = vp;
3817 mutex_exit(&dpnp->pr_mutex);
3818 prunlock(dpnp);
3819 return (vp);
3822 static vnode_t *
3823 pr_lookup_objectdir(vnode_t *dp, char *comp)
3825 prnode_t *dpnp = VTOP(dp);
3826 prnode_t *pnp;
3827 proc_t *p;
3828 struct seg *seg;
3829 struct as *as;
3830 vnode_t *vp;
3831 vattr_t vattr;
3833 ASSERT(dpnp->pr_type == PR_OBJECTDIR);
3835 pnp = prgetnode(dp, PR_OBJECT);
3837 if (prlock(dpnp, ZNO) != 0) {
3838 prfreenode(pnp);
3839 return (NULL);
3841 p = dpnp->pr_common->prc_proc;
3842 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3843 prunlock(dpnp);
3844 prfreenode(pnp);
3845 return (NULL);
3849 * We drop p_lock before grabbing the address space lock
3850 * in order to avoid a deadlock with the clock thread.
3851 * The process will not disappear and its address space
3852 * will not change because it is marked P_PR_LOCK.
3854 mutex_exit(&p->p_lock);
3855 AS_LOCK_ENTER(as, RW_READER);
3856 if ((seg = AS_SEGFIRST(as)) == NULL) {
3857 vp = NULL;
3858 goto out;
3860 if (strcmp(comp, "a.out") == 0) {
3861 vp = p->p_exec;
3862 goto out;
3864 do {
3866 * Manufacture a filename for the "object" directory.
3868 vattr.va_mask = AT_FSID|AT_NODEID;
3869 if (seg->s_ops == &segvn_ops &&
3870 SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
3871 vp != NULL && vp->v_type == VREG &&
3872 VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
3873 char name[64];
3875 if (vp == p->p_exec) /* "a.out" */
3876 continue;
3877 pr_object_name(name, vp, &vattr);
3878 if (strcmp(name, comp) == 0)
3879 goto out;
3881 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3883 vp = NULL;
3884 out:
3885 if (vp != NULL) {
3886 VN_HOLD(vp);
3888 AS_LOCK_EXIT(as);
3889 mutex_enter(&p->p_lock);
3890 prunlock(dpnp);
3892 if (vp == NULL)
3893 prfreenode(pnp);
3894 else {
3896 * Fill in the prnode so future references will
3897 * be able to find the underlying object's vnode.
3898 * Don't link this prnode into the list of all
3899 * prnodes for the process; this is a one-use node.
3900 * Its use is entirely to catch and fail opens for writing.
3902 pnp->pr_realvp = vp;
3903 vp = PTOV(pnp);
3906 return (vp);
3910 * Find or construct an lwp vnode for the given lwpid.
3912 static vnode_t *
3913 pr_lookup_lwpdir(vnode_t *dp, char *comp)
3915 id_t tid; /* same type as t->t_tid */
3916 int want_agent;
3917 prnode_t *dpnp = VTOP(dp);
3918 prnode_t *pnp;
3919 prcommon_t *pcp;
3920 vnode_t *vp;
3921 proc_t *p;
3922 kthread_t *t;
3923 lwpdir_t *ldp;
3924 lwpent_t *lep;
3925 int tslot;
3926 int c;
3928 ASSERT(dpnp->pr_type == PR_LWPDIR);
3930 tid = 0;
3931 if (strcmp(comp, "agent") == 0)
3932 want_agent = 1;
3933 else {
3934 want_agent = 0;
3935 while ((c = *comp++) != '\0') {
3936 id_t otid;
3938 if (c < '0' || c > '9')
3939 return (NULL);
3940 otid = tid;
3941 tid = 10*tid + c - '0';
3942 if (tid/10 != otid) /* integer overflow */
3943 return (NULL);
3947 pnp = prgetnode(dp, PR_LWPIDDIR);
3949 p = pr_p_lock(dpnp);
3950 mutex_exit(&pr_pidlock);
3951 if (p == NULL) {
3952 prfreenode(pnp);
3953 return (NULL);
3956 if (want_agent) {
3957 if ((t = p->p_agenttp) == NULL)
3958 lep = NULL;
3959 else {
3960 tid = t->t_tid;
3961 tslot = t->t_dslot;
3962 lep = p->p_lwpdir[tslot].ld_entry;
3964 } else {
3965 if ((ldp = lwp_hash_lookup(p, tid)) == NULL)
3966 lep = NULL;
3967 else {
3968 tslot = (int)(ldp - p->p_lwpdir);
3969 lep = ldp->ld_entry;
3973 if (lep == NULL) {
3974 prunlock(dpnp);
3975 prfreenode(pnp);
3976 return (NULL);
3980 * If an lwp vnode already exists and it is not invalid
3981 * and it was created by the current process and it belongs
3982 * to the same /proc mount point as our parent vnode, then
3983 * just use it and discard the newly-allocated prnode.
3985 for (vp = lep->le_trace; vp != NULL; vp = VTOP(vp)->pr_next) {
3986 if (!(VTOP(vp)->pr_flags & PR_INVAL) &&
3987 VTOP(vp)->pr_owner == curproc &&
3988 vp->v_vfsp == dp->v_vfsp) {
3989 VN_HOLD(vp);
3990 prunlock(dpnp);
3991 prfreenode(pnp);
3992 return (vp);
3995 pnp->pr_owner = curproc;
3998 * prgetnode() initialized most of the prnode.
3999 * Finish the job.
4001 pcp = pnp->pr_common; /* the newly-allocated prcommon struct */
4002 if ((vp = lep->le_trace) != NULL) {
4003 /* discard the new prcommon and use the existing prcommon */
4004 prfreecommon(pcp);
4005 pcp = VTOP(vp)->pr_common;
4006 mutex_enter(&pcp->prc_mutex);
4007 ASSERT(pcp->prc_refcnt > 0);
4008 pcp->prc_refcnt++;
4009 mutex_exit(&pcp->prc_mutex);
4010 pnp->pr_common = pcp;
4011 } else {
4012 /* initialize the new prcommon struct */
4013 pcp->prc_flags |= PRC_LWP;
4014 if ((p->p_flag & SSYS) || p->p_as == &kas)
4015 pcp->prc_flags |= PRC_SYS;
4016 if ((t = lep->le_thread) == NULL)
4017 pcp->prc_flags |= PRC_DESTROY;
4018 pcp->prc_proc = p;
4019 pcp->prc_datamodel = dpnp->pr_pcommon->prc_datamodel;
4020 pcp->prc_pid = p->p_pid;
4021 pcp->prc_slot = p->p_slot;
4022 pcp->prc_thread = t;
4023 pcp->prc_tid = tid;
4024 pcp->prc_tslot = tslot;
4026 pnp->pr_pcommon = dpnp->pr_pcommon;
4027 pnp->pr_parent = dp;
4028 VN_HOLD(dp);
4030 * Link in the old, invalid directory vnode so we
4031 * can later determine the last close of the file.
4033 pnp->pr_next = lep->le_trace;
4034 lep->le_trace = vp = PTOV(pnp);
4035 prunlock(dpnp);
4036 return (vp);
4039 static vnode_t *
4040 pr_lookup_lwpiddir(vnode_t *dp, char *comp)
4042 prnode_t *dpnp = VTOP(dp);
4043 vnode_t *vp;
4044 prnode_t *pnp;
4045 proc_t *p;
4046 prdirent_t *dirp;
4047 int i;
4048 enum prnodetype type;
4050 ASSERT(dpnp->pr_type == PR_LWPIDDIR);
4052 for (i = 0; i < NLWPIDDIRFILES; i++) {
4053 /* Skip "." and ".." */
4054 dirp = &lwpiddir[i+2];
4055 if (strcmp(comp, dirp->d_name) == 0)
4056 break;
4059 if (i >= NLWPIDDIRFILES)
4060 return (NULL);
4062 type = (int)dirp->d_ino;
4063 pnp = prgetnode(dp, type);
4065 p = pr_p_lock(dpnp);
4066 mutex_exit(&pr_pidlock);
4067 if (p == NULL) {
4068 prfreenode(pnp);
4069 return (NULL);
4071 if (dpnp->pr_common->prc_flags & PRC_DESTROY) {
4073 * Only the lwpsinfo file is present for zombie lwps.
4074 * Nothing is present if the lwp has been reaped.
4076 if (dpnp->pr_common->prc_tslot == -1 ||
4077 type != PR_LWPSINFO) {
4078 prunlock(dpnp);
4079 prfreenode(pnp);
4080 return (NULL);
4084 #if defined(__sparc)
4085 /* the asrs file exists only for sparc v9 _LP64 processes */
4086 if (type == PR_ASRS && p->p_model != DATAMODEL_LP64) {
4087 prunlock(dpnp);
4088 prfreenode(pnp);
4089 return (NULL);
4091 #endif
4093 mutex_enter(&dpnp->pr_mutex);
4095 if ((vp = dpnp->pr_files[i]) != NULL &&
4096 !(VTOP(vp)->pr_flags & PR_INVAL)) {
4097 VN_HOLD(vp);
4098 mutex_exit(&dpnp->pr_mutex);
4099 prunlock(dpnp);
4100 prfreenode(pnp);
4101 return (vp);
4105 * prgetnode() initialized most of the prnode.
4106 * Finish the job.
4108 pnp->pr_common = dpnp->pr_common;
4109 pnp->pr_pcommon = dpnp->pr_pcommon;
4110 pnp->pr_parent = dp;
4111 VN_HOLD(dp);
4112 pnp->pr_index = i;
4114 dpnp->pr_files[i] = vp = PTOV(pnp);
4117 * Link new vnode into list of all /proc vnodes for the process.
4119 if (vp->v_type == VPROC) {
4120 pnp->pr_next = p->p_plist;
4121 p->p_plist = vp;
4123 mutex_exit(&dpnp->pr_mutex);
4124 prunlock(dpnp);
4125 return (vp);
4129 * Lookup one of the process's open files.
4131 static vnode_t *
4132 pr_lookup_fddir(vnode_t *dp, char *comp)
4134 prnode_t *dpnp = VTOP(dp);
4135 prnode_t *pnp;
4136 vnode_t *vp = NULL;
4137 proc_t *p;
4138 file_t *fp;
4139 uint_t fd;
4140 int c;
4141 uf_entry_t *ufp;
4142 uf_info_t *fip;
4144 ASSERT(dpnp->pr_type == PR_FDDIR);
4146 fd = 0;
4147 while ((c = *comp++) != '\0') {
4148 int ofd;
4149 if (c < '0' || c > '9')
4150 return (NULL);
4151 ofd = fd;
4152 fd = 10*fd + c - '0';
4153 if (fd/10 != ofd) /* integer overflow */
4154 return (NULL);
4157 pnp = prgetnode(dp, PR_FD);
4159 if (prlock(dpnp, ZNO) != 0) {
4160 prfreenode(pnp);
4161 return (NULL);
4163 p = dpnp->pr_common->prc_proc;
4164 if ((p->p_flag & SSYS) || p->p_as == &kas) {
4165 prunlock(dpnp);
4166 prfreenode(pnp);
4167 return (NULL);
4170 fip = P_FINFO(p);
4171 mutex_exit(&p->p_lock);
4172 mutex_enter(&fip->fi_lock);
4173 if (fd < fip->fi_nfiles) {
4174 UF_ENTER(ufp, fip, fd);
4175 if ((fp = ufp->uf_file) != NULL) {
4176 pnp->pr_mode = 07111;
4177 if (fp->f_flag & FREAD)
4178 pnp->pr_mode |= 0444;
4179 if (fp->f_flag & FWRITE)
4180 pnp->pr_mode |= 0222;
4181 vp = fp->f_vnode;
4182 VN_HOLD(vp);
4184 UF_EXIT(ufp);
4186 mutex_exit(&fip->fi_lock);
4187 mutex_enter(&p->p_lock);
4188 prunlock(dpnp);
4190 if (vp == NULL)
4191 prfreenode(pnp);
4192 else {
4194 * Fill in the prnode so future references will
4195 * be able to find the underlying object's vnode.
4196 * Don't link this prnode into the list of all
4197 * prnodes for the process; this is a one-use node.
4199 pnp->pr_realvp = vp;
4200 pnp->pr_parent = dp; /* needed for prlookup */
4201 VN_HOLD(dp);
4202 vp = PTOV(pnp);
4203 if (pnp->pr_realvp->v_type == VDIR) {
4204 vp->v_type = VDIR;
4205 vp->v_flag |= VTRAVERSE;
4209 return (vp);
4212 static vnode_t *
4213 pr_lookup_pathdir(vnode_t *dp, char *comp)
4215 prnode_t *dpnp = VTOP(dp);
4216 prnode_t *pnp;
4217 vnode_t *vp = NULL;
4218 proc_t *p;
4219 uint_t fd, flags = 0;
4220 int c;
4221 uf_entry_t *ufp;
4222 uf_info_t *fip;
4223 enum { NAME_FD, NAME_OBJECT, NAME_ROOT, NAME_CWD, NAME_UNKNOWN } type;
4224 char *tmp;
4225 int idx;
4226 struct seg *seg;
4227 struct as *as = NULL;
4228 vattr_t vattr;
4230 ASSERT(dpnp->pr_type == PR_PATHDIR);
4233 * First, check if this is a numeric entry, in which case we have a
4234 * file descriptor.
4236 fd = 0;
4237 type = NAME_FD;
4238 tmp = comp;
4239 while ((c = *tmp++) != '\0') {
4240 int ofd;
4241 if (c < '0' || c > '9') {
4242 type = NAME_UNKNOWN;
4243 break;
4245 ofd = fd;
4246 fd = 10*fd + c - '0';
4247 if (fd/10 != ofd) { /* integer overflow */
4248 type = NAME_UNKNOWN;
4249 break;
4254 * Next, see if it is one of the special values {root, cwd}.
4256 if (type == NAME_UNKNOWN) {
4257 if (strcmp(comp, "root") == 0)
4258 type = NAME_ROOT;
4259 else if (strcmp(comp, "cwd") == 0)
4260 type = NAME_CWD;
4264 * Grab the necessary data from the process
4266 if (prlock(dpnp, ZNO) != 0)
4267 return (NULL);
4268 p = dpnp->pr_common->prc_proc;
4270 fip = P_FINFO(p);
4272 switch (type) {
4273 case NAME_ROOT:
4274 if ((vp = PTOU(p)->u_rdir) == NULL)
4275 vp = p->p_zone->zone_rootvp;
4276 VN_HOLD(vp);
4277 break;
4278 case NAME_CWD:
4279 vp = PTOU(p)->u_cdir;
4280 VN_HOLD(vp);
4281 break;
4282 default:
4283 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
4284 prunlock(dpnp);
4285 return (NULL);
4288 mutex_exit(&p->p_lock);
4291 * Determine if this is an object entry
4293 if (type == NAME_UNKNOWN) {
4295 * Start with the inode index immediately after the number of
4296 * files.
4298 mutex_enter(&fip->fi_lock);
4299 idx = fip->fi_nfiles + 4;
4300 mutex_exit(&fip->fi_lock);
4302 if (strcmp(comp, "a.out") == 0) {
4303 if (p->p_execdir != NULL) {
4304 vp = p->p_execdir;
4305 VN_HOLD(vp);
4306 type = NAME_OBJECT;
4307 flags |= PR_AOUT;
4308 } else {
4309 vp = p->p_exec;
4310 VN_HOLD(vp);
4311 type = NAME_OBJECT;
4313 } else {
4314 AS_LOCK_ENTER(as, RW_READER);
4315 if ((seg = AS_SEGFIRST(as)) != NULL) {
4316 do {
4318 * Manufacture a filename for the
4319 * "object" directory.
4321 vattr.va_mask = AT_FSID|AT_NODEID;
4322 if (seg->s_ops == &segvn_ops &&
4323 SEGOP_GETVP(seg, seg->s_base, &vp)
4324 == 0 &&
4325 vp != NULL && vp->v_type == VREG &&
4326 VOP_GETATTR(vp, &vattr, 0, CRED(),
4327 NULL) == 0) {
4328 char name[64];
4330 if (vp == p->p_exec)
4331 continue;
4332 idx++;
4333 pr_object_name(name, vp,
4334 &vattr);
4335 if (strcmp(name, comp) == 0)
4336 break;
4338 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
4341 if (seg == NULL) {
4342 vp = NULL;
4343 } else {
4344 VN_HOLD(vp);
4345 type = NAME_OBJECT;
4348 AS_LOCK_EXIT(as);
4353 switch (type) {
4354 case NAME_FD:
4355 mutex_enter(&fip->fi_lock);
4356 if (fd < fip->fi_nfiles) {
4357 UF_ENTER(ufp, fip, fd);
4358 if (ufp->uf_file != NULL) {
4359 vp = ufp->uf_file->f_vnode;
4360 VN_HOLD(vp);
4362 UF_EXIT(ufp);
4364 mutex_exit(&fip->fi_lock);
4365 idx = fd + 4;
4366 break;
4367 case NAME_ROOT:
4368 idx = 2;
4369 break;
4370 case NAME_CWD:
4371 idx = 3;
4372 break;
4373 case NAME_OBJECT:
4374 case NAME_UNKNOWN:
4375 /* Nothing to do */
4376 break;
4379 mutex_enter(&p->p_lock);
4380 prunlock(dpnp);
4382 if (vp != NULL) {
4383 pnp = prgetnode(dp, PR_PATH);
4385 pnp->pr_flags |= flags;
4386 pnp->pr_common = dpnp->pr_common;
4387 pnp->pr_pcommon = dpnp->pr_pcommon;
4388 pnp->pr_realvp = vp;
4389 pnp->pr_parent = dp; /* needed for prlookup */
4390 pnp->pr_ino = pmkino(idx, dpnp->pr_common->prc_slot, PR_PATH);
4391 VN_HOLD(dp);
4392 vp = PTOV(pnp);
4393 vp->v_type = VLNK;
4396 return (vp);
4400 * Look up one of the process's active templates.
4402 static vnode_t *
4403 pr_lookup_tmpldir(vnode_t *dp, char *comp)
4405 prnode_t *dpnp = VTOP(dp);
4406 prnode_t *pnp;
4407 vnode_t *vp = NULL;
4408 proc_t *p;
4409 int i;
4411 ASSERT(dpnp->pr_type == PR_TMPLDIR);
4413 for (i = 0; i < ct_ntypes; i++)
4414 if (strcmp(comp, ct_types[i]->ct_type_name) == 0)
4415 break;
4416 if (i == ct_ntypes)
4417 return (NULL);
4419 pnp = prgetnode(dp, PR_TMPL);
4421 if (prlock(dpnp, ZNO) != 0) {
4422 prfreenode(pnp);
4423 return (NULL);
4425 p = dpnp->pr_common->prc_proc;
4426 if ((p->p_flag & SSYS) || p->p_as == &kas ||
4427 (dpnp->pr_common->prc_flags & (PRC_DESTROY | PRC_LWP)) != PRC_LWP) {
4428 prunlock(dpnp);
4429 prfreenode(pnp);
4430 return (NULL);
4432 if (ttolwp(dpnp->pr_common->prc_thread)->lwp_ct_active[i] != NULL) {
4433 pnp->pr_common = dpnp->pr_common;
4434 pnp->pr_pcommon = dpnp->pr_pcommon;
4435 pnp->pr_parent = dp;
4436 pnp->pr_cttype = i;
4437 VN_HOLD(dp);
4438 vp = PTOV(pnp);
4439 } else {
4440 prfreenode(pnp);
4442 prunlock(dpnp);
4444 return (vp);
4448 * Look up one of the contracts owned by the process.
4450 static vnode_t *
4451 pr_lookup_ctdir(vnode_t *dp, char *comp)
4453 prnode_t *dpnp = VTOP(dp);
4454 prnode_t *pnp;
4455 vnode_t *vp = NULL;
4456 proc_t *p;
4457 id_t id = 0;
4458 contract_t *ct;
4459 int c;
4461 ASSERT(dpnp->pr_type == PR_CTDIR);
4463 while ((c = *comp++) != '\0') {
4464 id_t oid;
4465 if (c < '0' || c > '9')
4466 return (NULL);
4467 oid = id;
4468 id = 10 * id + c - '0';
4469 if (id / 10 != oid) /* integer overflow */
4470 return (NULL);
4474 * Search all contracts; we'll filter below.
4476 ct = contract_ptr(id, GLOBAL_ZONEUNIQID);
4477 if (ct == NULL)
4478 return (NULL);
4480 pnp = prgetnode(dp, PR_CT);
4482 if (prlock(dpnp, ZNO) != 0) {
4483 prfreenode(pnp);
4484 contract_rele(ct);
4485 return (NULL);
4487 p = dpnp->pr_common->prc_proc;
4489 * We only allow lookups of contracts owned by this process, or,
4490 * if we are zsched and this is a zone's procfs, contracts on
4491 * stuff in the zone which are held by processes or contracts
4492 * outside the zone. (see logic in contract_status_common)
4494 if ((ct->ct_owner != p) &&
4495 !(p == VTOZONE(dp)->zone_zsched && ct->ct_state < CTS_ORPHAN &&
4496 VTOZONE(dp)->zone_uniqid == contract_getzuniqid(ct) &&
4497 VTOZONE(dp)->zone_uniqid != GLOBAL_ZONEUNIQID &&
4498 ct->ct_czuniqid == GLOBAL_ZONEUNIQID)) {
4499 prunlock(dpnp);
4500 prfreenode(pnp);
4501 contract_rele(ct);
4502 return (NULL);
4504 pnp->pr_common = dpnp->pr_common;
4505 pnp->pr_pcommon = dpnp->pr_pcommon;
4506 pnp->pr_contract = ct;
4507 pnp->pr_parent = dp;
4508 pnp->pr_ino = pmkino(id, pnp->pr_common->prc_slot, PR_CT);
4509 VN_HOLD(dp);
4510 prunlock(dpnp);
4511 vp = PTOV(pnp);
4513 return (vp);
4517 * Construct an lwp vnode for the old /proc interface.
4518 * We stand on our head to make the /proc plumbing correct.
4520 vnode_t *
4521 prlwpnode(prnode_t *pnp, uint_t tid)
4523 char comp[12];
4524 vnode_t *dp;
4525 vnode_t *vp;
4526 prcommon_t *pcp;
4527 proc_t *p;
4530 * Lookup the /proc/<pid>/lwp/<lwpid> directory vnode.
4532 if (pnp->pr_type == PR_PIDFILE) {
4533 dp = pnp->pr_parent; /* /proc/<pid> */
4534 VN_HOLD(dp);
4535 vp = pr_lookup_piddir(dp, "lwp");
4536 VN_RELE(dp);
4537 if ((dp = vp) == NULL) /* /proc/<pid>/lwp */
4538 return (NULL);
4539 } else if (pnp->pr_type == PR_LWPIDFILE) {
4540 dp = pnp->pr_parent; /* /proc/<pid>/lwp/<lwpid> */
4541 dp = VTOP(dp)->pr_parent; /* /proc/<pid>/lwp */
4542 VN_HOLD(dp);
4543 } else {
4544 return (NULL);
4547 (void) pr_u32tos(tid, comp, sizeof (comp));
4548 vp = pr_lookup_lwpdir(dp, comp);
4549 VN_RELE(dp);
4550 if ((dp = vp) == NULL)
4551 return (NULL);
4553 pnp = prgetnode(dp, PR_LWPIDFILE);
4554 vp = PTOV(pnp);
4557 * prgetnode() initialized most of the prnode.
4558 * Finish the job.
4560 pcp = VTOP(dp)->pr_common;
4561 pnp->pr_ino = ptoi(pcp->prc_pid);
4562 pnp->pr_common = pcp;
4563 pnp->pr_pcommon = VTOP(dp)->pr_pcommon;
4564 pnp->pr_parent = dp;
4566 * Link new vnode into list of all /proc vnodes for the process.
4568 p = pr_p_lock(pnp);
4569 mutex_exit(&pr_pidlock);
4570 if (p == NULL) {
4571 VN_RELE(dp);
4572 prfreenode(pnp);
4573 vp = NULL;
4574 } else if (pcp->prc_thread == NULL) {
4575 prunlock(pnp);
4576 VN_RELE(dp);
4577 prfreenode(pnp);
4578 vp = NULL;
4579 } else {
4580 pnp->pr_next = p->p_plist;
4581 p->p_plist = vp;
4582 prunlock(pnp);
4585 return (vp);
4588 #if defined(DEBUG)
4590 static uint32_t nprnode;
4591 static uint32_t nprcommon;
4593 #define INCREMENT(x) atomic_inc_32(&x);
4594 #define DECREMENT(x) atomic_dec_32(&x);
4596 #else
4598 #define INCREMENT(x)
4599 #define DECREMENT(x)
4601 #endif /* DEBUG */
4604 * New /proc vnode required; allocate it and fill in most of the fields.
4606 prnode_t *
4607 prgetnode(vnode_t *dp, prnodetype_t type)
4609 prnode_t *pnp;
4610 prcommon_t *pcp;
4611 vnode_t *vp;
4612 ulong_t nfiles;
4614 INCREMENT(nprnode);
4615 pnp = kmem_zalloc(sizeof (prnode_t), KM_SLEEP);
4617 mutex_init(&pnp->pr_mutex, NULL, MUTEX_DEFAULT, NULL);
4618 pnp->pr_type = type;
4620 pnp->pr_vnode = vn_alloc(KM_SLEEP);
4622 vp = PTOV(pnp);
4623 vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
4624 vn_setops(vp, prvnodeops);
4625 vp->v_vfsp = dp->v_vfsp;
4626 vp->v_type = VPROC;
4627 vp->v_data = (caddr_t)pnp;
4629 switch (type) {
4630 case PR_PIDDIR:
4631 case PR_LWPIDDIR:
4633 * We need a prcommon and a files array for each of these.
4635 INCREMENT(nprcommon);
4637 pcp = kmem_zalloc(sizeof (prcommon_t), KM_SLEEP);
4638 pcp->prc_refcnt = 1;
4639 pnp->pr_common = pcp;
4640 mutex_init(&pcp->prc_mutex, NULL, MUTEX_DEFAULT, NULL);
4641 cv_init(&pcp->prc_wait, NULL, CV_DEFAULT, NULL);
4643 nfiles = (type == PR_PIDDIR)? NPIDDIRFILES : NLWPIDDIRFILES;
4644 pnp->pr_files =
4645 kmem_zalloc(nfiles * sizeof (vnode_t *), KM_SLEEP);
4647 vp->v_type = VDIR;
4649 * Mode should be read-search by all, but we cannot so long
4650 * as we must support compatibility mode with old /proc.
4651 * Make /proc/<pid> be read by owner only, search by all.
4652 * Make /proc/<pid>/lwp/<lwpid> read-search by all. Also,
4653 * set VDIROPEN on /proc/<pid> so it can be opened for writing.
4655 if (type == PR_PIDDIR) {
4656 /* kludge for old /proc interface */
4657 prnode_t *xpnp = prgetnode(dp, PR_PIDFILE);
4658 pnp->pr_pidfile = PTOV(xpnp);
4659 pnp->pr_mode = 0511;
4660 vp->v_flag |= VDIROPEN;
4661 } else {
4662 pnp->pr_mode = 0555;
4665 break;
4667 case PR_CURDIR:
4668 case PR_ROOTDIR:
4669 case PR_FDDIR:
4670 case PR_OBJECTDIR:
4671 case PR_PATHDIR:
4672 case PR_CTDIR:
4673 case PR_TMPLDIR:
4674 vp->v_type = VDIR;
4675 pnp->pr_mode = 0500; /* read-search by owner only */
4676 break;
4678 case PR_CT:
4679 vp->v_type = VLNK;
4680 pnp->pr_mode = 0500; /* read-search by owner only */
4681 break;
4683 case PR_PATH:
4684 case PR_SELF:
4685 vp->v_type = VLNK;
4686 pnp->pr_mode = 0777;
4687 break;
4689 case PR_LWPDIR:
4690 vp->v_type = VDIR;
4691 pnp->pr_mode = 0555; /* read-search by all */
4692 break;
4694 case PR_AS:
4695 case PR_TMPL:
4696 pnp->pr_mode = 0600; /* read-write by owner only */
4697 break;
4699 case PR_CTL:
4700 case PR_LWPCTL:
4701 pnp->pr_mode = 0200; /* write-only by owner only */
4702 break;
4704 case PR_PIDFILE:
4705 case PR_LWPIDFILE:
4706 pnp->pr_mode = 0600; /* read-write by owner only */
4707 break;
4709 case PR_LWPNAME:
4710 pnp->pr_mode = 0644; /* readable by all + owner can write */
4711 break;
4713 case PR_PSINFO:
4714 case PR_LPSINFO:
4715 case PR_LWPSINFO:
4716 case PR_USAGE:
4717 case PR_LUSAGE:
4718 case PR_LWPUSAGE:
4719 pnp->pr_mode = 0444; /* read-only by all */
4720 break;
4722 default:
4723 pnp->pr_mode = 0400; /* read-only by owner only */
4724 break;
4726 vn_exists(vp);
4727 return (pnp);
4731 * Free the storage obtained from prgetnode().
4733 void
4734 prfreenode(prnode_t *pnp)
4736 vnode_t *vp;
4737 ulong_t nfiles;
4739 vn_invalid(PTOV(pnp));
4740 vn_free(PTOV(pnp));
4741 mutex_destroy(&pnp->pr_mutex);
4743 switch (pnp->pr_type) {
4744 case PR_PIDDIR:
4745 /* kludge for old /proc interface */
4746 if (pnp->pr_pidfile != NULL) {
4747 prfreenode(VTOP(pnp->pr_pidfile));
4748 pnp->pr_pidfile = NULL;
4750 /* FALLTHROUGH */
4751 case PR_LWPIDDIR:
4753 * We allocated a prcommon and a files array for each of these.
4755 prfreecommon(pnp->pr_common);
4756 nfiles = (pnp->pr_type == PR_PIDDIR)?
4757 NPIDDIRFILES : NLWPIDDIRFILES;
4758 kmem_free(pnp->pr_files, nfiles * sizeof (vnode_t *));
4759 break;
4760 default:
4761 break;
4764 * If there is an underlying vnode, be sure
4765 * to release it after freeing the prnode.
4767 vp = pnp->pr_realvp;
4768 kmem_free(pnp, sizeof (*pnp));
4769 DECREMENT(nprnode);
4770 if (vp != NULL) {
4771 VN_RELE(vp);
4776 * Free a prcommon structure, if the reference count reaches zero.
4778 static void
4779 prfreecommon(prcommon_t *pcp)
4781 mutex_enter(&pcp->prc_mutex);
4782 ASSERT(pcp->prc_refcnt > 0);
4783 if (--pcp->prc_refcnt != 0)
4784 mutex_exit(&pcp->prc_mutex);
4785 else {
4786 mutex_exit(&pcp->prc_mutex);
4787 ASSERT(pcp->prc_pollhead.ph_list == NULL);
4788 ASSERT(pcp->prc_refcnt == 0);
4789 ASSERT(pcp->prc_selfopens == 0 && pcp->prc_writers == 0);
4790 mutex_destroy(&pcp->prc_mutex);
4791 cv_destroy(&pcp->prc_wait);
4792 kmem_free(pcp, sizeof (prcommon_t));
4793 DECREMENT(nprcommon);
4798 * Array of readdir functions, indexed by /proc file type.
4800 static int pr_readdir_notdir(), pr_readdir_procdir(), pr_readdir_piddir(),
4801 pr_readdir_objectdir(), pr_readdir_lwpdir(), pr_readdir_lwpiddir(),
4802 pr_readdir_fddir(), pr_readdir_pathdir(), pr_readdir_tmpldir(),
4803 pr_readdir_ctdir();
4805 static int (*pr_readdir_function[PR_NFILES])() = {
4806 pr_readdir_procdir, /* /proc */
4807 pr_readdir_notdir, /* /proc/self */
4808 pr_readdir_piddir, /* /proc/<pid> */
4809 pr_readdir_notdir, /* /proc/<pid>/as */
4810 pr_readdir_notdir, /* /proc/<pid>/ctl */
4811 pr_readdir_notdir, /* /proc/<pid>/status */
4812 pr_readdir_notdir, /* /proc/<pid>/lstatus */
4813 pr_readdir_notdir, /* /proc/<pid>/psinfo */
4814 pr_readdir_notdir, /* /proc/<pid>/lpsinfo */
4815 pr_readdir_notdir, /* /proc/<pid>/map */
4816 pr_readdir_notdir, /* /proc/<pid>/rmap */
4817 pr_readdir_notdir, /* /proc/<pid>/xmap */
4818 pr_readdir_notdir, /* /proc/<pid>/cred */
4819 pr_readdir_notdir, /* /proc/<pid>/sigact */
4820 pr_readdir_notdir, /* /proc/<pid>/auxv */
4821 #if defined(__x86)
4822 pr_readdir_notdir, /* /proc/<pid>/ldt */
4823 #endif
4824 pr_readdir_notdir, /* /proc/<pid>/usage */
4825 pr_readdir_notdir, /* /proc/<pid>/lusage */
4826 pr_readdir_notdir, /* /proc/<pid>/pagedata */
4827 pr_readdir_notdir, /* /proc/<pid>/watch */
4828 pr_readdir_notdir, /* /proc/<pid>/cwd */
4829 pr_readdir_notdir, /* /proc/<pid>/root */
4830 pr_readdir_fddir, /* /proc/<pid>/fd */
4831 pr_readdir_notdir, /* /proc/<pid>/fd/nn */
4832 pr_readdir_objectdir, /* /proc/<pid>/object */
4833 pr_readdir_notdir, /* /proc/<pid>/object/xxx */
4834 pr_readdir_lwpdir, /* /proc/<pid>/lwp */
4835 pr_readdir_lwpiddir, /* /proc/<pid>/lwp/<lwpid> */
4836 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpctl */
4837 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpname */
4838 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpstatus */
4839 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpsinfo */
4840 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/lwpusage */
4841 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */
4842 pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */
4843 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */
4844 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */
4845 #if defined(__sparc)
4846 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */
4847 pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */
4848 #endif
4849 pr_readdir_notdir, /* /proc/<pid>/priv */
4850 pr_readdir_pathdir, /* /proc/<pid>/path */
4851 pr_readdir_notdir, /* /proc/<pid>/path/xxx */
4852 pr_readdir_ctdir, /* /proc/<pid>/contracts */
4853 pr_readdir_notdir, /* /proc/<pid>/contracts/<ctid> */
4854 pr_readdir_notdir, /* /proc/<pid>/secflags */
4855 pr_readdir_notdir, /* old process file */
4856 pr_readdir_notdir, /* old lwp file */
4857 pr_readdir_notdir, /* old pagedata file */
4860 /* ARGSUSED */
4861 static int
4862 prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
4863 caller_context_t *ct, int flags)
4865 prnode_t *pnp = VTOP(vp);
4867 ASSERT(pnp->pr_type < PR_NFILES);
4869 /* XXX - Do we need to pass ct and flags? */
4870 return (pr_readdir_function[pnp->pr_type](pnp, uiop, eofp));
4873 /* ARGSUSED */
4874 static int
4875 pr_readdir_notdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4877 return (ENOTDIR);
4880 /* ARGSUSED */
4881 static int
4882 pr_readdir_procdir(prnode_t *pnp, uio_t *uiop, int *eofp)
4884 zoneid_t zoneid;
4885 gfs_readdir_state_t gstate;
4886 int error, eof = 0;
4887 offset_t n;
4889 ASSERT(pnp->pr_type == PR_PROCDIR);
4891 zoneid = VTOZONE(PTOV(pnp))->zone_id;
4893 if ((error = gfs_readdir_init(&gstate, PNSIZ, PRSDSIZE, uiop,
4894 PRROOTINO, PRROOTINO, 0)) != 0)
4895 return (error);
4898 * Loop until user's request is satisfied or until all processes
4899 * have been examined.
4901 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
4902 uint_t pid;
4903 int pslot;
4904 proc_t *p;
4907 * Find next entry. Skip processes not visible where
4908 * this /proc was mounted.
4910 mutex_enter(&pidlock);
4911 while (n < v.v_proc &&
4912 ((p = pid_entry(n)) == NULL || p->p_stat == SIDL ||
4913 (zoneid != GLOBAL_ZONEID && p->p_zone->zone_id != zoneid) ||
4914 secpolicy_basic_procinfo(CRED(), p, curproc) != 0))
4915 n++;
4918 * Stop when entire proc table has been examined.
4920 if (n >= v.v_proc) {
4921 mutex_exit(&pidlock);
4922 eof = 1;
4923 break;
4926 ASSERT(p->p_stat != 0);
4927 pid = p->p_pid;
4928 pslot = p->p_slot;
4929 mutex_exit(&pidlock);
4930 error = gfs_readdir_emitn(&gstate, uiop, n,
4931 pmkino(0, pslot, PR_PIDDIR), pid);
4932 if (error)
4933 break;
4936 return (gfs_readdir_fini(&gstate, error, eofp, eof));
4939 /* ARGSUSED */
4940 static int
4941 pr_readdir_piddir(prnode_t *pnp, uio_t *uiop, int *eofp)
4943 int zombie = ((pnp->pr_pcommon->prc_flags & PRC_DESTROY) != 0);
4944 prdirent_t dirent;
4945 prdirent_t *dirp;
4946 offset_t off;
4947 int error;
4949 ASSERT(pnp->pr_type == PR_PIDDIR);
4951 if (uiop->uio_offset < 0 ||
4952 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
4953 uiop->uio_resid < sizeof (prdirent_t))
4954 return (EINVAL);
4955 if (pnp->pr_pcommon->prc_proc == NULL)
4956 return (ENOENT);
4957 if (uiop->uio_offset >= sizeof (piddir))
4958 goto out;
4961 * Loop until user's request is satisfied, omitting some
4962 * files along the way if the process is a zombie.
4964 for (dirp = &piddir[uiop->uio_offset / sizeof (prdirent_t)];
4965 uiop->uio_resid >= sizeof (prdirent_t) &&
4966 dirp < &piddir[NPIDDIRFILES+2];
4967 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
4968 off = uiop->uio_offset;
4969 if (zombie) {
4970 switch (dirp->d_ino) {
4971 case PR_PIDDIR:
4972 case PR_PROCDIR:
4973 case PR_PSINFO:
4974 case PR_USAGE:
4975 break;
4976 default:
4977 continue;
4980 bcopy(dirp, &dirent, sizeof (prdirent_t));
4981 if (dirent.d_ino == PR_PROCDIR)
4982 dirent.d_ino = PRROOTINO;
4983 else
4984 dirent.d_ino = pmkino(0, pnp->pr_pcommon->prc_slot,
4985 dirent.d_ino);
4986 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
4987 UIO_READ, uiop)) != 0)
4988 return (error);
4990 out:
4991 if (eofp)
4992 *eofp = (uiop->uio_offset >= sizeof (piddir));
4993 return (0);
4996 static void
4997 rebuild_objdir(struct as *as)
4999 struct seg *seg;
5000 vnode_t *vp;
5001 vattr_t vattr;
5002 vnode_t **dir;
5003 ulong_t nalloc;
5004 ulong_t nentries;
5005 int i, j;
5006 ulong_t nold, nnew;
5008 ASSERT(AS_WRITE_HELD(as));
5010 if (as->a_updatedir == 0 && as->a_objectdir != NULL)
5011 return;
5012 as->a_updatedir = 0;
5014 if ((nalloc = avl_numnodes(&as->a_segtree)) == 0 ||
5015 (seg = AS_SEGFIRST(as)) == NULL) /* can't happen? */
5016 return;
5019 * Allocate space for the new object directory.
5020 * (This is usually about two times too many entries.)
5022 nalloc = (nalloc + 0xf) & ~0xf; /* multiple of 16 */
5023 dir = kmem_zalloc(nalloc * sizeof (vnode_t *), KM_SLEEP);
5025 /* fill in the new directory with desired entries */
5026 nentries = 0;
5027 do {
5028 vattr.va_mask = AT_FSID|AT_NODEID;
5029 if (seg->s_ops == &segvn_ops &&
5030 SEGOP_GETVP(seg, seg->s_base, &vp) == 0 &&
5031 vp != NULL && vp->v_type == VREG &&
5032 VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) == 0) {
5033 for (i = 0; i < nentries; i++)
5034 if (vp == dir[i])
5035 break;
5036 if (i == nentries) {
5037 ASSERT(nentries < nalloc);
5038 dir[nentries++] = vp;
5041 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
5043 if (as->a_objectdir == NULL) { /* first time */
5044 as->a_objectdir = dir;
5045 as->a_sizedir = nalloc;
5046 return;
5050 * Null out all of the defunct entries in the old directory.
5052 nold = 0;
5053 nnew = nentries;
5054 for (i = 0; i < as->a_sizedir; i++) {
5055 if ((vp = as->a_objectdir[i]) != NULL) {
5056 for (j = 0; j < nentries; j++) {
5057 if (vp == dir[j]) {
5058 dir[j] = NULL;
5059 nnew--;
5060 break;
5063 if (j == nentries)
5064 as->a_objectdir[i] = NULL;
5065 else
5066 nold++;
5070 if (nold + nnew > as->a_sizedir) {
5072 * Reallocate the old directory to have enough
5073 * space for the old and new entries combined.
5074 * Round up to the next multiple of 16.
5076 ulong_t newsize = (nold + nnew + 0xf) & ~0xf;
5077 vnode_t **newdir = kmem_zalloc(newsize * sizeof (vnode_t *),
5078 KM_SLEEP);
5079 bcopy(as->a_objectdir, newdir,
5080 as->a_sizedir * sizeof (vnode_t *));
5081 kmem_free(as->a_objectdir, as->a_sizedir * sizeof (vnode_t *));
5082 as->a_objectdir = newdir;
5083 as->a_sizedir = newsize;
5087 * Move all new entries to the old directory and
5088 * deallocate the space used by the new directory.
5090 if (nnew) {
5091 for (i = 0, j = 0; i < nentries; i++) {
5092 if ((vp = dir[i]) == NULL)
5093 continue;
5094 for (; j < as->a_sizedir; j++) {
5095 if (as->a_objectdir[j] != NULL)
5096 continue;
5097 as->a_objectdir[j++] = vp;
5098 break;
5102 kmem_free(dir, nalloc * sizeof (vnode_t *));
5106 * Return the vnode from a slot in the process's object directory.
5107 * The caller must have locked the process's address space.
5108 * The only caller is below, in pr_readdir_objectdir().
5110 static vnode_t *
5111 obj_entry(struct as *as, int slot)
5113 ASSERT(AS_LOCK_HELD(as));
5114 if (as->a_objectdir == NULL)
5115 return (NULL);
5116 ASSERT(slot < as->a_sizedir);
5117 return (as->a_objectdir[slot]);
5120 /* ARGSUSED */
5121 static int
5122 pr_readdir_objectdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5124 gfs_readdir_state_t gstate;
5125 int error, eof = 0;
5126 offset_t n;
5127 int pslot;
5128 size_t objdirsize;
5129 proc_t *p;
5130 struct as *as;
5131 vnode_t *vp;
5133 ASSERT(pnp->pr_type == PR_OBJECTDIR);
5135 if ((error = prlock(pnp, ZNO)) != 0)
5136 return (error);
5137 p = pnp->pr_common->prc_proc;
5138 pslot = p->p_slot;
5141 * We drop p_lock before grabbing the address space lock
5142 * in order to avoid a deadlock with the clock thread.
5143 * The process will not disappear and its address space
5144 * will not change because it is marked P_PR_LOCK.
5146 mutex_exit(&p->p_lock);
5148 if ((error = gfs_readdir_init(&gstate, 64, PRSDSIZE, uiop,
5149 pmkino(0, pslot, PR_PIDDIR),
5150 pmkino(0, pslot, PR_OBJECTDIR), 0)) != 0) {
5151 mutex_enter(&p->p_lock);
5152 prunlock(pnp);
5153 return (error);
5156 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5157 as = NULL;
5158 objdirsize = 0;
5162 * Loop until user's request is satisfied or until
5163 * all mapped objects have been examined. Cannot hold
5164 * the address space lock for the following call as
5165 * gfs_readdir_pred() utimately causes a call to uiomove().
5167 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5168 vattr_t vattr;
5169 char str[64];
5172 * Set the correct size of the directory just
5173 * in case the process has changed it's address
5174 * space via mmap/munmap calls.
5176 if (as != NULL) {
5177 AS_LOCK_ENTER(as, RW_WRITER);
5178 if (as->a_updatedir)
5179 rebuild_objdir(as);
5180 objdirsize = as->a_sizedir;
5184 * Find next object.
5186 vattr.va_mask = AT_FSID | AT_NODEID;
5187 while (n < objdirsize && (((vp = obj_entry(as, n)) == NULL) ||
5188 (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)
5189 != 0))) {
5190 vattr.va_mask = AT_FSID | AT_NODEID;
5191 n++;
5194 if (as != NULL)
5195 AS_LOCK_EXIT(as);
5198 * Stop when all objects have been reported.
5200 if (n >= objdirsize) {
5201 eof = 1;
5202 break;
5205 if (vp == p->p_exec)
5206 (void) strcpy(str, "a.out");
5207 else
5208 pr_object_name(str, vp, &vattr);
5210 error = gfs_readdir_emit(&gstate, uiop, n, vattr.va_nodeid,
5211 str, 0);
5213 if (error)
5214 break;
5217 mutex_enter(&p->p_lock);
5218 prunlock(pnp);
5220 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5223 /* ARGSUSED */
5224 static int
5225 pr_readdir_lwpdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5227 gfs_readdir_state_t gstate;
5228 int error, eof = 0;
5229 offset_t tslot;
5230 proc_t *p;
5231 int pslot;
5232 lwpdir_t *lwpdir;
5233 int lwpdirsize;
5235 ASSERT(pnp->pr_type == PR_LWPDIR);
5237 p = pr_p_lock(pnp);
5238 mutex_exit(&pr_pidlock);
5239 if (p == NULL)
5240 return (ENOENT);
5241 ASSERT(p == pnp->pr_common->prc_proc);
5242 pslot = p->p_slot;
5243 lwpdir = p->p_lwpdir;
5244 lwpdirsize = p->p_lwpdir_sz;
5247 * Drop p->p_lock so we can safely do uiomove().
5248 * The lwp directory will not change because
5249 * we have the process locked with P_PR_LOCK.
5251 mutex_exit(&p->p_lock);
5254 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5255 pmkino(0, pslot, PR_PIDDIR),
5256 pmkino(0, pslot, PR_LWPDIR), 0)) != 0) {
5257 mutex_enter(&p->p_lock);
5258 prunlock(pnp);
5259 return (error);
5263 * Loop until user's request is satisfied or until all lwps
5264 * have been examined.
5266 while ((error = gfs_readdir_pred(&gstate, uiop, &tslot)) == 0) {
5267 lwpent_t *lep;
5268 uint_t tid;
5271 * Find next LWP.
5273 while (tslot < lwpdirsize &&
5274 ((lep = lwpdir[tslot].ld_entry) == NULL))
5275 tslot++;
5277 * Stop when all lwps have been reported.
5279 if (tslot >= lwpdirsize) {
5280 eof = 1;
5281 break;
5284 tid = lep->le_lwpid;
5285 error = gfs_readdir_emitn(&gstate, uiop, tslot,
5286 pmkino(tslot, pslot, PR_LWPIDDIR), tid);
5287 if (error)
5288 break;
5291 mutex_enter(&p->p_lock);
5292 prunlock(pnp);
5294 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5297 /* ARGSUSED */
5298 static int
5299 pr_readdir_lwpiddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5301 prcommon_t *pcp = pnp->pr_common;
5302 int zombie = ((pcp->prc_flags & PRC_DESTROY) != 0);
5303 prdirent_t dirent;
5304 prdirent_t *dirp;
5305 offset_t off;
5306 int error;
5307 int pslot;
5308 int tslot;
5310 ASSERT(pnp->pr_type == PR_LWPIDDIR);
5312 if (uiop->uio_offset < 0 ||
5313 uiop->uio_offset % sizeof (prdirent_t) != 0 ||
5314 uiop->uio_resid < sizeof (prdirent_t))
5315 return (EINVAL);
5316 if (pcp->prc_proc == NULL || pcp->prc_tslot == -1)
5317 return (ENOENT);
5318 if (uiop->uio_offset >= sizeof (lwpiddir))
5319 goto out;
5322 * Loop until user's request is satisfied, omitting some files
5323 * along the way if the lwp is a zombie and also depending
5324 * on the data model of the process.
5326 pslot = pcp->prc_slot;
5327 tslot = pcp->prc_tslot;
5328 for (dirp = &lwpiddir[uiop->uio_offset / sizeof (prdirent_t)];
5329 uiop->uio_resid >= sizeof (prdirent_t) &&
5330 dirp < &lwpiddir[NLWPIDDIRFILES+2];
5331 uiop->uio_offset = off + sizeof (prdirent_t), dirp++) {
5332 off = uiop->uio_offset;
5333 if (zombie) {
5334 switch (dirp->d_ino) {
5335 case PR_LWPIDDIR:
5336 case PR_LWPDIR:
5337 case PR_LWPSINFO:
5338 break;
5339 default:
5340 continue;
5343 #if defined(__sparc)
5344 /* the asrs file exists only for sparc v9 _LP64 processes */
5345 if (dirp->d_ino == PR_ASRS &&
5346 pcp->prc_datamodel != DATAMODEL_LP64)
5347 continue;
5348 #endif
5349 bcopy(dirp, &dirent, sizeof (prdirent_t));
5350 if (dirent.d_ino == PR_LWPDIR)
5351 dirent.d_ino = pmkino(0, pslot, dirp->d_ino);
5352 else
5353 dirent.d_ino = pmkino(tslot, pslot, dirp->d_ino);
5354 if ((error = uiomove((caddr_t)&dirent, sizeof (prdirent_t),
5355 UIO_READ, uiop)) != 0)
5356 return (error);
5358 out:
5359 if (eofp)
5360 *eofp = (uiop->uio_offset >= sizeof (lwpiddir));
5361 return (0);
5364 /* ARGSUSED */
5365 static int
5366 pr_readdir_fddir(prnode_t *pnp, uio_t *uiop, int *eofp)
5368 gfs_readdir_state_t gstate;
5369 int error, eof = 0;
5370 offset_t n;
5371 proc_t *p;
5372 int pslot;
5373 int fddirsize;
5374 uf_info_t *fip;
5376 ASSERT(pnp->pr_type == PR_FDDIR);
5378 if ((error = prlock(pnp, ZNO)) != 0)
5379 return (error);
5380 p = pnp->pr_common->prc_proc;
5381 pslot = p->p_slot;
5382 fip = P_FINFO(p);
5383 mutex_exit(&p->p_lock);
5385 if ((error = gfs_readdir_init(&gstate, PLNSIZ, PRSDSIZE, uiop,
5386 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_FDDIR), 0)) != 0) {
5387 mutex_enter(&p->p_lock);
5388 prunlock(pnp);
5389 return (error);
5392 mutex_enter(&fip->fi_lock);
5393 if ((p->p_flag & SSYS) || p->p_as == &kas)
5394 fddirsize = 0;
5395 else
5396 fddirsize = fip->fi_nfiles;
5399 * Loop until user's request is satisfied or until
5400 * all file descriptors have been examined.
5402 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5404 * Find next fd.
5406 while (n < fddirsize && fip->fi_list[n].uf_file == NULL)
5407 n++;
5409 * Stop when all fds have been reported.
5411 if (n >= fddirsize) {
5412 eof = 1;
5413 break;
5416 error = gfs_readdir_emitn(&gstate, uiop, n,
5417 pmkino(n, pslot, PR_FD), n);
5418 if (error)
5419 break;
5422 mutex_exit(&fip->fi_lock);
5423 mutex_enter(&p->p_lock);
5424 prunlock(pnp);
5426 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5429 /* ARGSUSED */
5430 static int
5431 pr_readdir_pathdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5433 longlong_t bp[DIRENT64_RECLEN(64) / sizeof (longlong_t)];
5434 dirent64_t *dirent = (dirent64_t *)bp;
5435 int reclen;
5436 ssize_t oresid;
5437 offset_t off, idx;
5438 int error = 0;
5439 proc_t *p;
5440 int fd, obj;
5441 int pslot;
5442 int fddirsize;
5443 uf_info_t *fip;
5444 struct as *as = NULL;
5445 size_t objdirsize;
5446 vattr_t vattr;
5447 vnode_t *vp;
5449 ASSERT(pnp->pr_type == PR_PATHDIR);
5451 if (uiop->uio_offset < 0 ||
5452 uiop->uio_resid <= 0 ||
5453 (uiop->uio_offset % PRSDSIZE) != 0)
5454 return (EINVAL);
5455 oresid = uiop->uio_resid;
5456 bzero(bp, sizeof (bp));
5458 if ((error = prlock(pnp, ZNO)) != 0)
5459 return (error);
5460 p = pnp->pr_common->prc_proc;
5461 fip = P_FINFO(p);
5462 pslot = p->p_slot;
5463 mutex_exit(&p->p_lock);
5465 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
5466 as = NULL;
5467 objdirsize = 0;
5468 } else {
5469 AS_LOCK_ENTER(as, RW_WRITER);
5470 if (as->a_updatedir)
5471 rebuild_objdir(as);
5472 objdirsize = as->a_sizedir;
5473 AS_LOCK_EXIT(as);
5474 as = NULL;
5477 mutex_enter(&fip->fi_lock);
5478 if ((p->p_flag & SSYS) || p->p_as == &kas)
5479 fddirsize = 0;
5480 else
5481 fddirsize = fip->fi_nfiles;
5483 for (; uiop->uio_resid > 0; uiop->uio_offset = off + PRSDSIZE) {
5485 * There are 4 special files in the path directory: ".", "..",
5486 * "root", and "cwd". We handle those specially here.
5488 off = uiop->uio_offset;
5489 idx = off / PRSDSIZE;
5490 if (off == 0) { /* "." */
5491 dirent->d_ino = pmkino(0, pslot, PR_PATHDIR);
5492 dirent->d_name[0] = '.';
5493 dirent->d_name[1] = '\0';
5494 reclen = DIRENT64_RECLEN(1);
5495 } else if (idx == 1) { /* ".." */
5496 dirent->d_ino = pmkino(0, pslot, PR_PIDDIR);
5497 dirent->d_name[0] = '.';
5498 dirent->d_name[1] = '.';
5499 dirent->d_name[2] = '\0';
5500 reclen = DIRENT64_RECLEN(2);
5501 } else if (idx == 2) { /* "root" */
5502 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5503 (void) strcpy(dirent->d_name, "root");
5504 reclen = DIRENT64_RECLEN(4);
5505 } else if (idx == 3) { /* "cwd" */
5506 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5507 (void) strcpy(dirent->d_name, "cwd");
5508 reclen = DIRENT64_RECLEN(3);
5509 } else if (idx < 4 + fddirsize) {
5511 * In this case, we have one of the file descriptors.
5513 fd = idx - 4;
5514 if (fip->fi_list[fd].uf_file == NULL)
5515 continue;
5516 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5517 (void) pr_u32tos(fd, dirent->d_name, PLNSIZ+1);
5518 reclen = DIRENT64_RECLEN(PLNSIZ);
5519 } else if (idx < 4 + fddirsize + objdirsize) {
5520 if (fip != NULL) {
5521 mutex_exit(&fip->fi_lock);
5522 fip = NULL;
5526 * We drop p_lock before grabbing the address space lock
5527 * in order to avoid a deadlock with the clock thread.
5528 * The process will not disappear and its address space
5529 * will not change because it is marked P_PR_LOCK.
5531 if (as == NULL) {
5532 as = p->p_as;
5533 AS_LOCK_ENTER(as, RW_WRITER);
5536 if (as->a_updatedir) {
5537 rebuild_objdir(as);
5538 objdirsize = as->a_sizedir;
5541 obj = idx - 4 - fddirsize;
5542 if ((vp = obj_entry(as, obj)) == NULL)
5543 continue;
5544 vattr.va_mask = AT_FSID|AT_NODEID;
5545 if (VOP_GETATTR(vp, &vattr, 0, CRED(), NULL) != 0)
5546 continue;
5547 if (vp == p->p_exec)
5548 (void) strcpy(dirent->d_name, "a.out");
5549 else
5550 pr_object_name(dirent->d_name, vp, &vattr);
5551 dirent->d_ino = pmkino(idx, pslot, PR_PATH);
5552 reclen = DIRENT64_RECLEN(strlen(dirent->d_name));
5553 } else {
5554 break;
5557 dirent->d_off = uiop->uio_offset + PRSDSIZE;
5558 dirent->d_reclen = (ushort_t)reclen;
5559 if (reclen > uiop->uio_resid) {
5561 * Error if no entries have been returned yet.
5563 if (uiop->uio_resid == oresid)
5564 error = EINVAL;
5565 break;
5568 * Drop the address space lock to do the uiomove().
5570 if (as != NULL)
5571 AS_LOCK_EXIT(as);
5573 error = uiomove((caddr_t)dirent, reclen, UIO_READ, uiop);
5574 if (as != NULL)
5575 AS_LOCK_ENTER(as, RW_WRITER);
5577 if (error)
5578 break;
5581 if (error == 0 && eofp)
5582 *eofp = (uiop->uio_offset >= (fddirsize + 2) * PRSDSIZE);
5584 if (fip != NULL)
5585 mutex_exit(&fip->fi_lock);
5586 if (as != NULL)
5587 AS_LOCK_EXIT(as);
5588 mutex_enter(&p->p_lock);
5589 prunlock(pnp);
5590 return (error);
5593 static int
5594 pr_readdir_tmpldir(prnode_t *pnp, uio_t *uiop, int *eofp)
5596 proc_t *p;
5597 int pslot, tslot;
5598 gfs_readdir_state_t gstate;
5599 int error, eof = 0;
5600 offset_t n;
5602 ASSERT(pnp->pr_type == PR_TMPLDIR);
5604 if ((error = prlock(pnp, ZNO)) != 0)
5605 return (error);
5606 p = pnp->pr_common->prc_proc;
5607 pslot = pnp->pr_common->prc_slot;
5608 tslot = pnp->pr_common->prc_tslot;
5609 mutex_exit(&p->p_lock);
5611 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5612 pmkino(tslot, pslot, PR_LWPDIR),
5613 pmkino(tslot, pslot, PR_TMPLDIR), 0)) != 0) {
5614 mutex_enter(&p->p_lock);
5615 prunlock(pnp);
5616 return (error);
5619 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5621 * Check for an active template. Reading a directory's
5622 * contents is already racy, so we don't bother taking
5623 * any locks.
5625 while (n < ct_ntypes &&
5626 pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[n] == NULL)
5627 n++;
5629 * Stop when all types have been reported.
5631 if (n >= ct_ntypes) {
5632 eof = 1;
5633 break;
5636 * The pmkino invocation below will need to be updated
5637 * when we create our fifth contract type.
5639 ASSERT(ct_ntypes <= 4);
5640 error = gfs_readdir_emit(&gstate, uiop, n,
5641 pmkino((tslot << 2) | n, pslot, PR_TMPL),
5642 ct_types[n]->ct_type_name, 0);
5643 if (error)
5644 break;
5647 mutex_enter(&p->p_lock);
5648 prunlock(pnp);
5650 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5653 static int
5654 pr_readdir_ctdir(prnode_t *pnp, uio_t *uiop, int *eofp)
5656 proc_t *p;
5657 int pslot;
5658 gfs_readdir_state_t gstate;
5659 int error, eof = 0;
5660 offset_t n;
5661 uint64_t zid;
5663 ASSERT(pnp->pr_type == PR_CTDIR);
5665 if ((error = prlock(pnp, ZNO)) != 0)
5666 return (error);
5667 p = pnp->pr_common->prc_proc;
5668 pslot = p->p_slot;
5669 mutex_exit(&p->p_lock);
5671 if ((error = gfs_readdir_init(&gstate, PRDIRSIZE, PRSDSIZE, uiop,
5672 pmkino(0, pslot, PR_PIDDIR), pmkino(0, pslot, PR_CTDIR), 0)) != 0) {
5673 mutex_enter(&p->p_lock);
5674 prunlock(pnp);
5675 return (error);
5678 zid = VTOZONE(pnp->pr_vnode)->zone_uniqid;
5679 while ((error = gfs_readdir_pred(&gstate, uiop, &n)) == 0) {
5680 id_t next = contract_plookup(p, n, zid);
5681 if (next == -1) {
5682 eof = 1;
5683 break;
5685 error = gfs_readdir_emitn(&gstate, uiop, next,
5686 pmkino(next, pslot, PR_CT), next);
5687 if (error)
5688 break;
5691 mutex_enter(&p->p_lock);
5692 prunlock(pnp);
5694 return (gfs_readdir_fini(&gstate, error, eofp, eof));
5697 /* ARGSUSED */
5698 static int
5699 prfsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
5701 return (0);
5705 * Utility: remove a /proc vnode from a linked list, threaded through pr_next.
5707 static void
5708 pr_list_unlink(vnode_t *pvp, vnode_t **listp)
5710 vnode_t *vp;
5711 prnode_t *pnp;
5713 while ((vp = *listp) != NULL) {
5714 pnp = VTOP(vp);
5715 if (vp == pvp) {
5716 *listp = pnp->pr_next;
5717 pnp->pr_next = NULL;
5718 break;
5720 listp = &pnp->pr_next;
5724 /* ARGSUSED */
5725 static void
5726 prinactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5728 prnode_t *pnp = VTOP(vp);
5729 prnodetype_t type = pnp->pr_type;
5730 proc_t *p;
5731 vnode_t *dp;
5732 vnode_t *ovp = NULL;
5733 prnode_t *opnp = NULL;
5735 switch (type) {
5736 case PR_OBJECT:
5737 case PR_FD:
5738 case PR_SELF:
5739 case PR_PATH:
5740 /* These are not linked into the usual lists */
5741 ASSERT(vp->v_count == 1);
5742 if ((dp = pnp->pr_parent) != NULL)
5743 VN_RELE(dp);
5744 prfreenode(pnp);
5745 return;
5746 default:
5747 break;
5750 mutex_enter(&pr_pidlock);
5751 if (pnp->pr_pcommon == NULL)
5752 p = NULL;
5753 else if ((p = pnp->pr_pcommon->prc_proc) != NULL)
5754 mutex_enter(&p->p_lock);
5755 mutex_enter(&vp->v_lock);
5757 if (type == PR_PROCDIR || vp->v_count > 1) {
5758 VN_RELE_LOCKED(vp);
5759 mutex_exit(&vp->v_lock);
5760 if (p != NULL)
5761 mutex_exit(&p->p_lock);
5762 mutex_exit(&pr_pidlock);
5763 return;
5766 if ((dp = pnp->pr_parent) != NULL) {
5767 prnode_t *dpnp;
5769 switch (type) {
5770 case PR_PIDFILE:
5771 case PR_LWPIDFILE:
5772 case PR_OPAGEDATA:
5773 break;
5774 default:
5775 dpnp = VTOP(dp);
5776 mutex_enter(&dpnp->pr_mutex);
5777 if (dpnp->pr_files != NULL &&
5778 dpnp->pr_files[pnp->pr_index] == vp)
5779 dpnp->pr_files[pnp->pr_index] = NULL;
5780 mutex_exit(&dpnp->pr_mutex);
5781 break;
5783 pnp->pr_parent = NULL;
5786 ASSERT(vp->v_count == 1);
5789 * If we allocated an old /proc/pid node, free it too.
5791 if (pnp->pr_pidfile != NULL) {
5792 ASSERT(type == PR_PIDDIR);
5793 ovp = pnp->pr_pidfile;
5794 opnp = VTOP(ovp);
5795 ASSERT(opnp->pr_type == PR_PIDFILE);
5796 pnp->pr_pidfile = NULL;
5799 mutex_exit(&pr_pidlock);
5801 if (p != NULL) {
5803 * Remove the vnodes from the lists of
5804 * /proc vnodes for the process.
5806 int slot;
5808 switch (type) {
5809 case PR_PIDDIR:
5810 pr_list_unlink(vp, &p->p_trace);
5811 break;
5812 case PR_LWPIDDIR:
5813 if ((slot = pnp->pr_common->prc_tslot) != -1) {
5814 lwpent_t *lep = p->p_lwpdir[slot].ld_entry;
5815 pr_list_unlink(vp, &lep->le_trace);
5817 break;
5818 default:
5819 pr_list_unlink(vp, &p->p_plist);
5820 break;
5822 if (ovp != NULL)
5823 pr_list_unlink(ovp, &p->p_plist);
5824 mutex_exit(&p->p_lock);
5827 mutex_exit(&vp->v_lock);
5829 if (type == PR_CT && pnp->pr_contract != NULL) {
5830 contract_rele(pnp->pr_contract);
5831 pnp->pr_contract = NULL;
5834 if (opnp != NULL)
5835 prfreenode(opnp);
5836 prfreenode(pnp);
5837 if (dp != NULL) {
5838 VN_RELE(dp);
5842 /* ARGSUSED */
5843 static int
5844 prseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
5846 return (0);
5850 * We use the p_execdir member of proc_t to expand the %d token in core file
5851 * paths (the directory path for the executable that dumped core; see
5852 * coreadm(1M) for details). We'd like gcore(1) to be able to expand %d in
5853 * the same way as core dumping from the kernel, but there's no convenient
5854 * and comprehensible way to export the path name for p_execdir. To solve
5855 * this, we try to find the actual path to the executable that was used. In
5856 * pr_lookup_pathdir(), we mark the a.out path name vnode with the PR_AOUT
5857 * flag, and use that here to indicate that more work is needed beyond the
5858 * call to vnodetopath().
5860 static int
5861 prreadlink_lookup(prnode_t *pnp, char *buf, size_t size, cred_t *cr)
5863 proc_t *p;
5864 vnode_t *vp, *execvp, *vrootp;
5865 int ret;
5866 size_t len;
5867 dirent64_t *dp;
5868 size_t dlen = DIRENT64_RECLEN(MAXPATHLEN);
5869 char *dbuf;
5871 p = curproc;
5872 mutex_enter(&p->p_lock);
5873 if ((vrootp = PTOU(p)->u_rdir) == NULL)
5874 vrootp = rootdir;
5875 VN_HOLD(vrootp);
5876 mutex_exit(&p->p_lock);
5878 ret = vnodetopath(vrootp, pnp->pr_realvp, buf, size, cr);
5881 * If PR_AOUT isn't set, then we looked up the path for the vnode;
5882 * otherwise, we looked up the path for (what we believe to be) the
5883 * containing directory.
5885 if ((pnp->pr_flags & PR_AOUT) == 0) {
5886 VN_RELE(vrootp);
5887 return (ret);
5891 * Fail if there's a problem locking the process. This will only
5892 * occur if the process is changing so the information we would
5893 * report would already be invalid.
5895 if (prlock(pnp, ZNO) != 0) {
5896 VN_RELE(vrootp);
5897 return (EIO);
5900 p = pnp->pr_common->prc_proc;
5901 mutex_exit(&p->p_lock);
5903 execvp = p->p_exec;
5904 VN_HOLD(execvp);
5907 * If our initial lookup of the directory failed, fall back to
5908 * the path name information for p_exec.
5910 if (ret != 0) {
5911 mutex_enter(&p->p_lock);
5912 prunlock(pnp);
5913 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5914 VN_RELE(execvp);
5915 VN_RELE(vrootp);
5916 return (ret);
5919 len = strlen(buf);
5922 * We use u_comm as a guess for the last component of the full
5923 * executable path name. If there isn't going to be enough space
5924 * we fall back to using the p_exec so that we can have _an_
5925 * answer even if it's not perfect.
5927 if (strlen(PTOU(p)->u_comm) + len + 1 < size) {
5928 buf[len] = '/';
5929 (void) strcpy(buf + len + 1, PTOU(p)->u_comm);
5930 mutex_enter(&p->p_lock);
5931 prunlock(pnp);
5934 * Do a forward lookup of our u_comm guess.
5936 if (lookupnameat(buf + len + 1, UIO_SYSSPACE, FOLLOW, NULLVPP,
5937 &vp, pnp->pr_realvp) == 0) {
5938 if (vn_compare(vp, execvp)) {
5939 VN_RELE(vp);
5940 VN_RELE(execvp);
5941 VN_RELE(vrootp);
5942 return (0);
5945 VN_RELE(vp);
5947 } else {
5948 mutex_enter(&p->p_lock);
5949 prunlock(pnp);
5952 dbuf = kmem_alloc(dlen, KM_SLEEP);
5955 * Try to find a matching vnode by iterating through the directory's
5956 * entries. If that fails, fall back to the path information for
5957 * p_exec.
5959 if ((ret = dirfindvp(vrootp, pnp->pr_realvp, execvp, cr, dbuf,
5960 dlen, &dp)) == 0 && strlen(dp->d_name) + len + 1 < size) {
5961 buf[len] = '/';
5962 (void) strcpy(buf + len + 1, dp->d_name);
5963 } else {
5964 ret = vnodetopath(vrootp, execvp, buf, size, cr);
5967 kmem_free(dbuf, dlen);
5968 VN_RELE(execvp);
5969 VN_RELE(vrootp);
5971 return (ret);
5974 /* ARGSUSED */
5975 static int
5976 prreadlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ctp)
5978 prnode_t *pnp = VTOP(vp);
5979 char *buf;
5980 int ret = EINVAL;
5981 char idbuf[16];
5982 int length, rlength;
5983 contract_t *ct;
5985 switch (pnp->pr_type) {
5986 case PR_SELF:
5987 (void) snprintf(idbuf, sizeof (idbuf), "%d", curproc->p_pid);
5988 ret = uiomove(idbuf, strlen(idbuf), UIO_READ, uiop);
5989 break;
5990 case PR_OBJECT:
5991 case PR_FD:
5992 case PR_CURDIR:
5993 case PR_ROOTDIR:
5994 if (pnp->pr_realvp->v_type == VDIR)
5995 ret = 0;
5996 break;
5997 case PR_PATH:
5998 buf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6000 if ((ret = prreadlink_lookup(pnp, buf, MAXPATHLEN, cr)) == 0)
6001 ret = uiomove(buf, strlen(buf), UIO_READ, uiop);
6003 kmem_free(buf, MAXPATHLEN);
6004 break;
6005 case PR_CT:
6006 ASSERT(pnp->pr_contract != NULL);
6007 ct = pnp->pr_contract;
6008 length = sizeof (CTFS_ROOT "//") + sizeof (idbuf) +
6009 strlen(ct->ct_type->ct_type_name);
6010 buf = kmem_alloc(length, KM_SLEEP);
6011 rlength = snprintf(buf, length, CTFS_ROOT "/%s/%d",
6012 ct->ct_type->ct_type_name, ct->ct_id);
6013 ASSERT(rlength < length);
6014 ret = uiomove(buf, rlength, UIO_READ, uiop);
6015 kmem_free(buf, length);
6016 break;
6017 default:
6018 break;
6021 return (ret);
6024 /*ARGSUSED2*/
6025 static int
6026 prcmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
6028 prnode_t *pp1, *pp2;
6030 if (vp1 == vp2)
6031 return (1);
6033 if (!vn_matchops(vp1, prvnodeops) || !vn_matchops(vp2, prvnodeops))
6034 return (0);
6036 pp1 = VTOP(vp1);
6037 pp2 = VTOP(vp2);
6039 if (pp1->pr_type != pp2->pr_type)
6040 return (0);
6041 if (pp1->pr_type == PR_PROCDIR)
6042 return (1);
6043 if (pp1->pr_ino || pp2->pr_ino)
6044 return (pp2->pr_ino == pp1->pr_ino);
6046 if (pp1->pr_common == NULL || pp2->pr_common == NULL)
6047 return (0);
6049 return (pp1->pr_common->prc_slot == pp2->pr_common->prc_slot &&
6050 pp1->pr_common->prc_tslot == pp2->pr_common->prc_tslot);
6053 static int
6054 prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
6056 vnode_t *rvp;
6058 if ((rvp = VTOP(vp)->pr_realvp) != NULL) {
6059 vp = rvp;
6060 if (VOP_REALVP(vp, &rvp, ct) == 0)
6061 vp = rvp;
6064 *vpp = vp;
6065 return (0);
6069 * Return the answer requested to poll().
6070 * POLLIN, POLLRDNORM, and POLLOUT are recognized as in fs_poll().
6071 * In addition, these have special meaning for /proc files:
6072 * POLLPRI process or lwp stopped on an event of interest
6073 * POLLERR /proc file descriptor is invalid
6074 * POLLHUP process or lwp has terminated
6076 /*ARGSUSED5*/
6077 static int
6078 prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
6079 pollhead_t **phpp, caller_context_t *ct)
6081 prnode_t *pnp = VTOP(vp);
6082 prcommon_t *pcp = pnp->pr_common;
6083 pollhead_t *php = &pcp->prc_pollhead;
6084 proc_t *p;
6085 short revents;
6086 int error;
6087 int lockstate;
6089 ASSERT(pnp->pr_type < PR_NFILES);
6092 * Support for old /proc interface.
6094 if (pnp->pr_pidfile != NULL) {
6095 vp = pnp->pr_pidfile;
6096 pnp = VTOP(vp);
6097 ASSERT(pnp->pr_type == PR_PIDFILE);
6098 ASSERT(pnp->pr_common == pcp);
6101 *reventsp = revents = 0;
6102 *phpp = (pollhead_t *)NULL;
6104 if (vp->v_type == VDIR) {
6105 *reventsp |= POLLNVAL;
6106 return (0);
6109 /* avoid deadlock with prnotify() */
6110 if (pollunlock(&lockstate) != 0) {
6111 *reventsp = POLLNVAL;
6112 return (0);
6115 if ((error = prlock(pnp, ZNO)) != 0) {
6116 pollrelock(lockstate);
6117 switch (error) {
6118 case ENOENT: /* process or lwp died */
6119 *reventsp = POLLHUP;
6120 error = 0;
6121 break;
6122 case EAGAIN: /* invalidated */
6123 *reventsp = POLLERR;
6124 error = 0;
6125 break;
6127 return (error);
6131 * We have the process marked locked (P_PR_LOCK) and we are holding
6132 * its p->p_lock. We want to unmark the process but retain
6133 * exclusive control w.r.t. other /proc controlling processes
6134 * before reacquiring the polling locks.
6136 * prunmark() does this for us. It unmarks the process
6137 * but retains p->p_lock so we still have exclusive control.
6138 * We will drop p->p_lock at the end to relinquish control.
6140 * We cannot call prunlock() at the end to relinquish control
6141 * because prunlock(), like prunmark(), may drop and reacquire
6142 * p->p_lock and that would lead to a lock order violation
6143 * w.r.t. the polling locks we are about to reacquire.
6145 p = pcp->prc_proc;
6146 ASSERT(p != NULL);
6147 prunmark(p);
6149 pollrelock(lockstate); /* reacquire dropped poll locks */
6151 if ((p->p_flag & SSYS) || p->p_as == &kas)
6152 revents = POLLNVAL;
6153 else {
6154 short ev;
6156 if ((ev = (events & (POLLIN|POLLRDNORM))) != 0)
6157 revents |= ev;
6159 * POLLWRNORM (same as POLLOUT) really should not be
6160 * used to indicate that the process or lwp stopped.
6161 * However, USL chose to use POLLWRNORM rather than
6162 * POLLPRI to indicate this, so we just accept either
6163 * requested event to indicate stopped. (grr...)
6165 if ((ev = (events & (POLLPRI|POLLOUT|POLLWRNORM))) != 0) {
6166 kthread_t *t;
6168 if (pcp->prc_flags & PRC_LWP) {
6169 t = pcp->prc_thread;
6170 ASSERT(t != NULL);
6171 thread_lock(t);
6172 } else {
6173 t = prchoose(p); /* returns locked t */
6174 ASSERT(t != NULL);
6177 if (ISTOPPED(t) || VSTOPPED(t))
6178 revents |= ev;
6179 thread_unlock(t);
6183 *reventsp = revents;
6184 if ((!anyyet && revents == 0) || (events & POLLET)) {
6186 * Arrange to wake up the polling lwp when
6187 * the target process/lwp stops or terminates
6188 * or when the file descriptor becomes invalid.
6190 pcp->prc_flags |= PRC_POLL;
6191 *phpp = php;
6193 mutex_exit(&p->p_lock);
6194 return (0);
6197 /* in prioctl.c */
6198 extern int prioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
6199 caller_context_t *);
6202 * /proc vnode operations vector
6204 const fs_operation_def_t pr_vnodeops_template[] = {
6205 VOPNAME_OPEN, { .vop_open = propen },
6206 VOPNAME_CLOSE, { .vop_close = prclose },
6207 VOPNAME_READ, { .vop_read = prread },
6208 VOPNAME_WRITE, { .vop_write = prwrite },
6209 VOPNAME_IOCTL, { .vop_ioctl = prioctl },
6210 VOPNAME_GETATTR, { .vop_getattr = prgetattr },
6211 VOPNAME_ACCESS, { .vop_access = praccess },
6212 VOPNAME_LOOKUP, { .vop_lookup = prlookup },
6213 VOPNAME_CREATE, { .vop_create = prcreate },
6214 VOPNAME_READDIR, { .vop_readdir = prreaddir },
6215 VOPNAME_READLINK, { .vop_readlink = prreadlink },
6216 VOPNAME_FSYNC, { .vop_fsync = prfsync },
6217 VOPNAME_INACTIVE, { .vop_inactive = prinactive },
6218 VOPNAME_SEEK, { .vop_seek = prseek },
6219 VOPNAME_CMP, { .vop_cmp = prcmp },
6220 VOPNAME_FRLOCK, { .error = fs_error },
6221 VOPNAME_REALVP, { .vop_realvp = prrealvp },
6222 VOPNAME_POLL, { .vop_poll = prpoll },
6223 VOPNAME_DISPOSE, { .error = fs_error },
6224 VOPNAME_SHRLOCK, { .error = fs_error },
6225 NULL, NULL