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