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