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