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