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