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