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