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