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