Print this page
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
usr/src/uts/common/fs/proc/prcontrol.c
usr/src/uts/intel/os/archdep.c
usr/src/uts/intel/sys/ucontext.h
usr/src/uts/intel/syscall/getcontext.c
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/proc/prioctl.c
+++ new/usr/src/uts/common/fs/proc/prioctl.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 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 * Copyright 2019 Joyent, Inc.
26 + * Copyright 2023 Oxide Computer Company
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/vmparam.h>
34 35 #include <sys/var.h>
35 36 #include <sys/cmn_err.h>
36 37 #include <sys/cred.h>
37 38 #include <sys/debug.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/proc.h>
43 44 #include <sys/brand.h>
44 45 #include <sys/sysmacros.h>
45 46 #include <sys/systm.h>
46 47 #include <sys/vfs.h>
47 48 #include <sys/vnode.h>
48 49 #include <sys/cpuvar.h>
49 50 #include <sys/session.h>
50 51 #include <sys/signal.h>
51 52 #include <sys/auxv.h>
52 53 #include <sys/user.h>
53 54 #include <sys/disp.h>
54 55 #include <sys/class.h>
55 56 #include <sys/ts.h>
56 57 #include <sys/mman.h>
57 58 #include <sys/fault.h>
58 59 #include <sys/syscall.h>
59 60 #include <sys/schedctl.h>
60 61 #include <sys/pset.h>
61 62 #include <sys/old_procfs.h>
62 63 #include <sys/zone.h>
63 64 #include <sys/time.h>
64 65 #include <sys/msacct.h>
65 66 #include <vm/rm.h>
66 67 #include <vm/as.h>
67 68 #include <vm/rm.h>
68 69 #include <vm/seg.h>
69 70 #include <vm/seg_vn.h>
70 71 #include <sys/contract_impl.h>
71 72 #include <sys/ctfs_impl.h>
72 73 #include <sys/ctfs.h>
73 74
74 75 #if defined(__i386_COMPAT)
75 76 #include <sys/sysi86.h>
76 77 #endif
77 78
78 79 #include <fs/proc/prdata.h>
79 80
80 81 static int isprwrioctl(int);
81 82 static ulong_t prmaprunflags(long);
82 83 static long prmapsetflags(long);
83 84 static void prsetrun(kthread_t *, prrun_t *);
84 85 static int propenm(prnode_t *, caddr_t, caddr_t, int *, cred_t *);
85 86 extern void oprgetstatus(kthread_t *, prstatus_t *, zone_t *);
86 87 extern void oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *);
87 88 static int oprgetmap(proc_t *, list_t *);
88 89
89 90 static int
90 91 prctioctl(prnode_t *pnp, int cmd, intptr_t arg, int flag, cred_t *cr)
91 92 {
92 93 int error = 0;
93 94 ct_kparam_t kparam;
94 95 ct_param_t *param = &kparam.param;
95 96 ct_template_t *tmpl;
96 97
97 98 if (cmd != CT_TSET && cmd != CT_TGET)
98 99 return (EINVAL);
99 100
100 101 error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
101 102 if (error != 0)
102 103 return (error);
103 104
104 105 if ((error = prlock(pnp, ZNO)) != 0) {
105 106 kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
106 107 return (error);
107 108 }
108 109
109 110 tmpl = pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[pnp->pr_cttype];
110 111 if (tmpl == NULL) {
111 112 prunlock(pnp);
112 113 kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
113 114 return (ESTALE);
114 115 }
115 116
116 117 if (cmd == CT_TSET)
117 118 error = ctmpl_set(tmpl, &kparam, cr);
118 119 else
119 120 error = ctmpl_get(tmpl, &kparam);
120 121
121 122 prunlock(pnp);
122 123
123 124 if (cmd == CT_TGET && error == 0) {
124 125 error = ctparam_copyout(&kparam, (void *)arg, flag);
125 126 } else {
126 127 kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
127 128 }
128 129
129 130 return (error);
130 131 }
131 132
132 133
133 134 /*
134 135 * Control operations (lots).
135 136 */
136 137 /* BEGIN CSTYLED */
137 138 /*ARGSUSED*/
138 139 #ifdef _SYSCALL32_IMPL
139 140 static int
140 141 prioctl64(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
141 142 int *rvalp, caller_context_t *ct)
142 143 #else
143 144 int
144 145 prioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
145 146 int *rvalp, caller_context_t *ct)
146 147 #endif /* _SYSCALL32_IMPL */
147 148 {
148 149 /* END CSTYLED */
149 150 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
150 151 caddr_t cmaddr = (caddr_t)arg;
151 152 proc_t *p;
152 153 user_t *up;
153 154 kthread_t *t;
154 155 klwp_t *lwp;
155 156 prnode_t *pnp = VTOP(vp);
156 157 prcommon_t *pcp;
157 158 prnode_t *xpnp = NULL;
158 159 int error;
159 160 int zdisp;
160 161 void *thing = NULL;
161 162 size_t thingsize = 0;
162 163
163 164 /*
164 165 * For copyin()/copyout().
165 166 */
166 167 union {
167 168 caddr_t va;
168 169 int signo;
169 170 int nice;
170 171 uint_t lwpid;
171 172 long flags;
172 173 prstatus_t prstat;
173 174 prrun_t prrun;
174 175 sigset_t smask;
175 176 siginfo_t info;
176 177 sysset_t prmask;
177 178 prgregset_t regs;
178 179 prfpregset_t fpregs;
179 180 prpsinfo_t prps;
180 181 sigset_t holdmask;
181 182 fltset_t fltmask;
182 183 prcred_t prcred;
183 184 prhusage_t prhusage;
184 185 prmap_t prmap;
185 186 auxv_t auxv[__KERN_NAUXV_IMPL];
186 187 } un;
187 188
188 189 if (pnp->pr_type == PR_TMPL)
189 190 return (prctioctl(pnp, cmd, arg, flag, cr));
190 191
191 192 /*
192 193 * Support for old /proc interface.
193 194 */
194 195 if (pnp->pr_pidfile != NULL) {
195 196 ASSERT(pnp->pr_type == PR_PIDDIR);
196 197 vp = pnp->pr_pidfile;
197 198 pnp = VTOP(vp);
198 199 ASSERT(pnp->pr_type == PR_PIDFILE);
199 200 }
200 201
201 202 if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
|
↓ open down ↓ |
166 lines elided |
↑ open up ↑ |
202 203 return (ENOTTY);
203 204
204 205 /*
205 206 * Fail ioctls which are logically "write" requests unless
206 207 * the user has write permission.
207 208 */
208 209 if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
209 210 return (EBADF);
210 211
211 212 /*
213 + * The following commands are no longer supported. They were present on
214 + * SPARC and were always errors on other platforms. We now explicitly
215 + * return ENOTSUP to indicate that this is no longer done.
216 + */
217 + switch (cmd) {
218 + case PIOCSXREG:
219 + return (ENOTSUP);
220 + default:
221 + break;
222 + }
223 +
224 + /*
212 225 * Perform any necessary copyin() operations before
213 226 * locking the process. Helps avoid deadlocks and
214 227 * improves performance.
215 228 *
216 229 * Also, detect invalid ioctl codes here to avoid
217 - * locking a process unnnecessarily.
230 + * locking a process unnecessarily.
218 231 *
219 232 * Also, prepare to allocate space that will be needed below,
220 233 * case by case.
221 234 */
222 235 error = 0;
223 236 switch (cmd) {
224 237 case PIOCGETPR:
225 238 thingsize = sizeof (proc_t);
226 239 break;
227 240 case PIOCGETU:
228 241 thingsize = sizeof (user_t);
229 242 break;
230 243 case PIOCSTOP:
231 244 case PIOCWSTOP:
232 245 case PIOCLWPIDS:
233 246 case PIOCGTRACE:
234 247 case PIOCGENTRY:
235 248 case PIOCGEXIT:
236 249 case PIOCSRLC:
237 250 case PIOCRRLC:
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
238 251 case PIOCSFORK:
239 252 case PIOCRFORK:
240 253 case PIOCGREG:
241 254 case PIOCGFPREG:
242 255 case PIOCSTATUS:
243 256 case PIOCLSTATUS:
244 257 case PIOCPSINFO:
245 258 case PIOCMAXSIG:
246 259 case PIOCGXREGSIZE:
247 260 break;
248 - case PIOCSXREG: /* set extra registers */
249 261 case PIOCGXREG: /* get extra registers */
250 -#if defined(__sparc)
251 - thingsize = sizeof (prxregset_t);
252 -#else
253 - thingsize = 0;
254 -#endif
262 + thingsize = prgetprxregsize(p);
255 263 break;
256 264 case PIOCACTION:
257 265 thingsize = (nsig-1) * sizeof (struct sigaction);
258 266 break;
259 267 case PIOCGHOLD:
260 268 case PIOCNMAP:
261 269 case PIOCMAP:
262 270 case PIOCGFAULT:
263 271 case PIOCCFAULT:
264 272 case PIOCCRED:
265 273 case PIOCGROUPS:
266 274 case PIOCUSAGE:
267 275 case PIOCLUSAGE:
268 276 break;
269 277 case PIOCOPENPD:
270 278 /*
271 279 * We will need this below.
272 280 * Allocate it now, before locking the process.
273 281 */
274 282 xpnp = prgetnode(vp, PR_OPAGEDATA);
275 283 break;
276 284 case PIOCNAUXV:
277 285 case PIOCAUXV:
278 286 break;
279 287
280 288 #if defined(__x86)
281 289 case PIOCNLDT:
282 290 case PIOCLDT:
283 291 break;
284 292 #endif /* __x86 */
285 293
286 294 #if defined(__sparc)
287 295 case PIOCGWIN:
288 296 thingsize = sizeof (gwindows_t);
289 297 break;
290 298 #endif /* __sparc */
291 299
292 300 case PIOCOPENM: /* open mapped object for reading */
293 301 if (cmaddr == NULL)
294 302 un.va = NULL;
295 303 else if (copyin(cmaddr, &un.va, sizeof (un.va)))
296 304 error = EFAULT;
297 305 break;
298 306
299 307 case PIOCRUN: /* make lwp or process runnable */
300 308 if (cmaddr == NULL)
301 309 un.prrun.pr_flags = 0;
302 310 else if (copyin(cmaddr, &un.prrun, sizeof (un.prrun)))
303 311 error = EFAULT;
304 312 break;
305 313
306 314 case PIOCOPENLWP: /* return /proc lwp file descriptor */
307 315 if (copyin(cmaddr, &un.lwpid, sizeof (un.lwpid)))
308 316 error = EFAULT;
309 317 break;
310 318
311 319 case PIOCSTRACE: /* set signal trace mask */
312 320 if (copyin(cmaddr, &un.smask, sizeof (un.smask)))
313 321 error = EFAULT;
314 322 break;
315 323
316 324 case PIOCSSIG: /* set current signal */
317 325 if (cmaddr == NULL)
318 326 un.info.si_signo = 0;
319 327 else if (copyin(cmaddr, &un.info, sizeof (un.info)))
320 328 error = EFAULT;
321 329 break;
322 330
323 331 case PIOCKILL: /* send signal */
324 332 case PIOCUNKILL: /* delete a signal */
325 333 if (copyin(cmaddr, &un.signo, sizeof (un.signo)))
326 334 error = EFAULT;
327 335 break;
328 336
329 337 case PIOCNICE: /* set nice priority */
330 338 if (copyin(cmaddr, &un.nice, sizeof (un.nice)))
331 339 error = EFAULT;
332 340 break;
333 341
334 342 case PIOCSENTRY: /* set syscall entry bit mask */
335 343 case PIOCSEXIT: /* set syscall exit bit mask */
336 344 if (copyin(cmaddr, &un.prmask, sizeof (un.prmask)))
337 345 error = EFAULT;
338 346 break;
339 347
340 348 case PIOCSET: /* set process flags */
341 349 case PIOCRESET: /* reset process flags */
342 350 if (copyin(cmaddr, &un.flags, sizeof (un.flags)))
343 351 error = EFAULT;
344 352 break;
345 353
346 354 case PIOCSREG: /* set general registers */
347 355 if (copyin(cmaddr, un.regs, sizeof (un.regs)))
348 356 error = EFAULT;
349 357 break;
350 358
351 359 case PIOCSFPREG: /* set floating-point registers */
352 360 if (copyin(cmaddr, &un.fpregs, sizeof (un.fpregs)))
353 361 error = EFAULT;
354 362 break;
355 363
356 364 case PIOCSHOLD: /* set signal-hold mask */
357 365 if (copyin(cmaddr, &un.holdmask, sizeof (un.holdmask)))
358 366 error = EFAULT;
359 367 break;
360 368
361 369 case PIOCSFAULT: /* set mask of traced faults */
362 370 if (copyin(cmaddr, &un.fltmask, sizeof (un.fltmask)))
363 371 error = EFAULT;
364 372 break;
365 373
366 374 default:
367 375 error = EINVAL;
368 376 break;
369 377 }
370 378
371 379 if (error)
372 380 return (error);
373 381
374 382 startover:
375 383 /*
376 384 * If we need kmem_alloc()d space then we allocate it now, before
377 385 * grabbing the process lock. Using kmem_alloc(KM_SLEEP) while
378 386 * holding the process lock leads to deadlock with the clock thread.
379 387 * (The clock thread wakes up the pageout daemon to free up space.
380 388 * If the clock thread blocks behind us and we are sleeping waiting
381 389 * for space, then space may never become available.)
382 390 */
383 391 if (thingsize) {
384 392 ASSERT(thing == NULL);
|
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
385 393 thing = kmem_alloc(thingsize, KM_SLEEP);
386 394 }
387 395
388 396 switch (cmd) {
389 397 case PIOCPSINFO:
390 398 case PIOCGETPR:
391 399 case PIOCUSAGE:
392 400 case PIOCLUSAGE:
393 401 zdisp = ZYES;
394 402 break;
395 - case PIOCSXREG: /* set extra registers */
396 - /*
397 - * perform copyin before grabbing the process lock
398 - */
399 - if (thing) {
400 - if (copyin(cmaddr, thing, thingsize)) {
401 - kmem_free(thing, thingsize);
402 - return (EFAULT);
403 - }
404 - }
405 - /* fall through... */
406 403 default:
407 404 zdisp = ZNO;
408 405 break;
409 406 }
410 407
411 408 if ((error = prlock(pnp, zdisp)) != 0) {
412 409 if (thing != NULL)
413 410 kmem_free(thing, thingsize);
414 411 if (xpnp)
415 412 prfreenode(xpnp);
416 413 return (error);
417 414 }
418 415
419 416 pcp = pnp->pr_common;
420 417 p = pcp->prc_proc;
421 418 ASSERT(p != NULL);
422 419
423 420 /*
424 421 * Choose a thread/lwp for the operation.
425 422 */
426 423 if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
427 424 if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
428 425 t = pcp->prc_thread;
429 426 ASSERT(t != NULL);
430 427 } else {
431 428 t = prchoose(p); /* returns locked thread */
432 429 ASSERT(t != NULL);
433 430 thread_unlock(t);
434 431 }
435 432 lwp = ttolwp(t);
436 433 }
437 434
438 435 error = 0;
439 436 switch (cmd) {
440 437
441 438 case PIOCGETPR: /* read struct proc */
442 439 {
443 440 proc_t *prp = thing;
444 441
445 442 *prp = *p;
446 443 prunlock(pnp);
447 444 if (copyout(prp, cmaddr, sizeof (proc_t)))
448 445 error = EFAULT;
449 446 kmem_free(prp, sizeof (proc_t));
450 447 thing = NULL;
451 448 break;
452 449 }
453 450
454 451 case PIOCGETU: /* read u-area */
455 452 {
456 453 user_t *userp = thing;
457 454
458 455 up = PTOU(p);
459 456 *userp = *up;
460 457 prunlock(pnp);
461 458 if (copyout(userp, cmaddr, sizeof (user_t)))
462 459 error = EFAULT;
463 460 kmem_free(userp, sizeof (user_t));
464 461 thing = NULL;
465 462 break;
466 463 }
467 464
468 465 case PIOCOPENM: /* open mapped object for reading */
469 466 error = propenm(pnp, cmaddr, un.va, rvalp, cr);
470 467 /* propenm() called prunlock(pnp) */
471 468 break;
472 469
473 470 case PIOCSTOP: /* stop process or lwp from running */
474 471 case PIOCWSTOP: /* wait for process or lwp to stop */
475 472 /*
476 473 * Can't apply to a system process.
477 474 */
478 475 if ((p->p_flag & SSYS) || p->p_as == &kas) {
479 476 prunlock(pnp);
480 477 error = EBUSY;
481 478 break;
482 479 }
483 480
484 481 if (cmd == PIOCSTOP)
485 482 pr_stop(pnp);
486 483
487 484 /*
488 485 * If an lwp is waiting for itself or its process, don't wait.
489 486 * The stopped lwp would never see the fact that it is stopped.
490 487 */
491 488 if ((pnp->pr_type == PR_LWPIDFILE)?
492 489 (pcp->prc_thread == curthread) : (p == curproc)) {
493 490 if (cmd == PIOCWSTOP)
494 491 error = EBUSY;
495 492 prunlock(pnp);
496 493 break;
497 494 }
498 495
499 496 if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
500 497 break; /* pr_wait_stop() unlocked the process */
501 498
502 499 if (cmaddr == NULL)
503 500 prunlock(pnp);
504 501 else {
505 502 /*
506 503 * Return process/lwp status information.
507 504 */
508 505 t = pr_thread(pnp); /* returns locked thread */
509 506 thread_unlock(t);
510 507 oprgetstatus(t, &un.prstat, VTOZONE(vp));
511 508 prunlock(pnp);
512 509 if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
513 510 error = EFAULT;
514 511 }
515 512 break;
516 513
517 514 case PIOCRUN: /* make lwp or process runnable */
518 515 {
519 516 long flags = un.prrun.pr_flags;
520 517
521 518 /*
522 519 * Cannot set an lwp running is it is not stopped.
523 520 * Also, no lwp other than the /proc agent lwp can
524 521 * be set running so long as the /proc agent lwp exists.
525 522 */
526 523 if ((!ISTOPPED(t) && !VSTOPPED(t) &&
527 524 !(t->t_proc_flag & TP_PRSTOP)) ||
528 525 (p->p_agenttp != NULL &&
529 526 (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
530 527 prunlock(pnp);
531 528 error = EBUSY;
532 529 break;
533 530 }
534 531
535 532 if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR))
536 533 prsetrun(t, &un.prrun);
537 534
538 535 error = pr_setrun(pnp, prmaprunflags(flags));
539 536
540 537 prunlock(pnp);
541 538 break;
542 539 }
543 540
544 541 case PIOCLWPIDS: /* get array of lwp identifiers */
545 542 {
546 543 int nlwp;
547 544 int Nlwp;
548 545 id_t *idp;
549 546 id_t *Bidp;
550 547
551 548 Nlwp = nlwp = p->p_lwpcnt;
552 549
553 550 if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
554 551 kmem_free(thing, thingsize);
555 552 thing = NULL;
556 553 }
557 554 if (thing == NULL) {
558 555 thingsize = (Nlwp+1) * sizeof (id_t);
559 556 thing = kmem_alloc(thingsize, KM_NOSLEEP);
560 557 }
561 558 if (thing == NULL) {
562 559 prunlock(pnp);
563 560 goto startover;
564 561 }
565 562
566 563 idp = thing;
567 564 thing = NULL;
568 565 Bidp = idp;
569 566 if ((t = p->p_tlist) != NULL) {
570 567 do {
571 568 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
572 569 ASSERT(nlwp > 0);
573 570 --nlwp;
574 571 *idp++ = t->t_tid;
575 572 } while ((t = t->t_forw) != p->p_tlist);
576 573 }
577 574 *idp = 0;
578 575 ASSERT(nlwp == 0);
579 576 prunlock(pnp);
580 577 if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
581 578 error = EFAULT;
582 579 kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
583 580 break;
584 581 }
585 582
586 583 case PIOCOPENLWP: /* return /proc lwp file descriptor */
587 584 {
588 585 vnode_t *xvp;
589 586 int n;
590 587
591 588 prunlock(pnp);
592 589 if ((xvp = prlwpnode(pnp, un.lwpid)) == NULL)
593 590 error = ENOENT;
594 591 else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
595 592 VN_RELE(xvp);
596 593 } else
597 594 *rvalp = n;
598 595 break;
599 596 }
600 597
601 598 case PIOCOPENPD: /* return /proc page data file descriptor */
602 599 {
603 600 vnode_t *xvp = PTOV(xpnp);
604 601 vnode_t *dp = pnp->pr_parent;
605 602 int n;
606 603
607 604 if (pnp->pr_type == PR_LWPIDFILE) {
608 605 dp = VTOP(dp)->pr_parent;
609 606 dp = VTOP(dp)->pr_parent;
610 607 }
611 608 ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
612 609
613 610 VN_HOLD(dp);
614 611 pcp = pnp->pr_pcommon;
615 612 xpnp->pr_ino = ptoi(pcp->prc_pid);
616 613 xpnp->pr_common = pcp;
617 614 xpnp->pr_pcommon = pcp;
618 615 xpnp->pr_parent = dp;
619 616
620 617 xpnp->pr_next = p->p_plist;
621 618 p->p_plist = xvp;
622 619
623 620 prunlock(pnp);
624 621 if (error = fassign(&xvp, FREAD, &n)) {
625 622 VN_RELE(xvp);
626 623 } else
627 624 *rvalp = n;
628 625
629 626 xpnp = NULL;
630 627 break;
631 628 }
632 629
633 630 case PIOCGTRACE: /* get signal trace mask */
634 631 prassignset(&un.smask, &p->p_sigmask);
635 632 prunlock(pnp);
636 633 if (copyout(&un.smask, cmaddr, sizeof (un.smask)))
637 634 error = EFAULT;
638 635 break;
639 636
640 637 case PIOCSTRACE: /* set signal trace mask */
641 638 prdelset(&un.smask, SIGKILL);
642 639 prassignset(&p->p_sigmask, &un.smask);
643 640 if (!sigisempty(&p->p_sigmask))
644 641 p->p_proc_flag |= P_PR_TRACE;
645 642 else if (prisempty(&p->p_fltmask)) {
646 643 up = PTOU(p);
647 644 if (up->u_systrap == 0)
648 645 p->p_proc_flag &= ~P_PR_TRACE;
649 646 }
650 647 prunlock(pnp);
651 648 break;
652 649
653 650 case PIOCSSIG: /* set current signal */
654 651 error = pr_setsig(pnp, &un.info);
655 652 prunlock(pnp);
656 653 if (un.info.si_signo == SIGKILL && error == 0)
657 654 pr_wait_die(pnp);
658 655 break;
659 656
660 657 case PIOCKILL: /* send signal */
661 658 {
662 659 int sig = (int)un.signo;
663 660
664 661 error = pr_kill(pnp, sig, cr);
665 662 prunlock(pnp);
666 663 if (sig == SIGKILL && error == 0)
667 664 pr_wait_die(pnp);
668 665 break;
669 666 }
670 667
671 668 case PIOCUNKILL: /* delete a signal */
672 669 error = pr_unkill(pnp, (int)un.signo);
673 670 prunlock(pnp);
674 671 break;
675 672
676 673 case PIOCNICE: /* set nice priority */
677 674 error = pr_nice(p, (int)un.nice, cr);
678 675 prunlock(pnp);
679 676 break;
680 677
681 678 case PIOCGENTRY: /* get syscall entry bit mask */
682 679 case PIOCGEXIT: /* get syscall exit bit mask */
683 680 up = PTOU(p);
684 681 if (cmd == PIOCGENTRY) {
685 682 prassignset(&un.prmask, &up->u_entrymask);
686 683 } else {
687 684 prassignset(&un.prmask, &up->u_exitmask);
688 685 }
689 686 prunlock(pnp);
690 687 if (copyout(&un.prmask, cmaddr, sizeof (un.prmask)))
691 688 error = EFAULT;
692 689 break;
693 690
694 691 case PIOCSENTRY: /* set syscall entry bit mask */
695 692 case PIOCSEXIT: /* set syscall exit bit mask */
696 693 pr_setentryexit(p, &un.prmask, cmd == PIOCSENTRY);
697 694 prunlock(pnp);
698 695 break;
699 696
700 697 case PIOCSRLC: /* obsolete: set running on last /proc close */
701 698 error = pr_set(p, prmapsetflags(PR_RLC));
702 699 prunlock(pnp);
703 700 break;
704 701
705 702 case PIOCRRLC: /* obsolete: reset run-on-last-close flag */
706 703 error = pr_unset(p, prmapsetflags(PR_RLC));
707 704 prunlock(pnp);
708 705 break;
709 706
710 707 case PIOCSFORK: /* obsolete: set inherit-on-fork flag */
711 708 error = pr_set(p, prmapsetflags(PR_FORK));
712 709 prunlock(pnp);
713 710 break;
714 711
715 712 case PIOCRFORK: /* obsolete: reset inherit-on-fork flag */
716 713 error = pr_unset(p, prmapsetflags(PR_FORK));
717 714 prunlock(pnp);
718 715 break;
719 716
720 717 case PIOCSET: /* set process flags */
721 718 error = pr_set(p, prmapsetflags(un.flags));
722 719 prunlock(pnp);
723 720 break;
724 721
725 722 case PIOCRESET: /* reset process flags */
726 723 error = pr_unset(p, prmapsetflags(un.flags));
727 724 prunlock(pnp);
728 725 break;
729 726
730 727 case PIOCGREG: /* get general registers */
731 728 if (t->t_state != TS_STOPPED && !VSTOPPED(t))
732 729 bzero(un.regs, sizeof (un.regs));
733 730 else {
734 731 /* drop p_lock while touching the lwp's stack */
735 732 mutex_exit(&p->p_lock);
736 733 prgetprregs(lwp, un.regs);
737 734 mutex_enter(&p->p_lock);
738 735 }
739 736 prunlock(pnp);
740 737 if (copyout(un.regs, cmaddr, sizeof (un.regs)))
741 738 error = EFAULT;
742 739 break;
743 740
744 741 case PIOCSREG: /* set general registers */
745 742 if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
746 743 error = EBUSY;
747 744 else {
748 745 /* drop p_lock while touching the lwp's stack */
749 746 mutex_exit(&p->p_lock);
750 747 prsetprregs(lwp, un.regs, 0);
751 748 mutex_enter(&p->p_lock);
752 749 }
753 750 prunlock(pnp);
754 751 break;
755 752
756 753 case PIOCGFPREG: /* get floating-point registers */
757 754 if (!prhasfp()) {
758 755 prunlock(pnp);
759 756 error = EINVAL; /* No FP support */
760 757 break;
761 758 }
762 759
763 760 if (t->t_state != TS_STOPPED && !VSTOPPED(t))
764 761 bzero(&un.fpregs, sizeof (un.fpregs));
765 762 else {
766 763 /* drop p_lock while touching the lwp's stack */
767 764 mutex_exit(&p->p_lock);
768 765 prgetprfpregs(lwp, &un.fpregs);
769 766 mutex_enter(&p->p_lock);
770 767 }
771 768 prunlock(pnp);
772 769 if (copyout(&un.fpregs, cmaddr, sizeof (un.fpregs)))
773 770 error = EFAULT;
774 771 break;
775 772
776 773 case PIOCSFPREG: /* set floating-point registers */
777 774 if (!prhasfp())
778 775 error = EINVAL; /* No FP support */
779 776 else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
780 777 error = EBUSY;
781 778 else {
|
↓ open down ↓ |
366 lines elided |
↑ open up ↑ |
782 779 /* drop p_lock while touching the lwp's stack */
783 780 mutex_exit(&p->p_lock);
784 781 prsetprfpregs(lwp, &un.fpregs);
785 782 mutex_enter(&p->p_lock);
786 783 }
787 784 prunlock(pnp);
788 785 break;
789 786
790 787 case PIOCGXREGSIZE: /* get the size of the extra registers */
791 788 {
792 - int xregsize;
793 -
794 789 if (prhasx(p)) {
790 + size_t xregsize;
791 + int abisize;
792 +
795 793 xregsize = prgetprxregsize(p);
796 794 prunlock(pnp);
797 - if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
795 + if (xregsize > INT_MAX) {
796 + error = EOVERFLOW;
797 + break;
798 + }
799 +
800 + abisize = (int)xregsize;
801 + if (copyout(&abisize, cmaddr, sizeof (abisize)))
798 802 error = EFAULT;
799 803 } else {
800 804 prunlock(pnp);
801 805 error = EINVAL; /* No extra register support */
802 806 }
803 807 break;
804 808 }
805 809
806 810 case PIOCGXREG: /* get extra registers */
807 811 if (prhasx(p)) {
808 812 bzero(thing, thingsize);
809 813 if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
810 814 /* drop p_lock to touch the stack */
811 815 mutex_exit(&p->p_lock);
812 816 prgetprxregs(lwp, thing);
813 817 mutex_enter(&p->p_lock);
814 818 }
815 819 prunlock(pnp);
816 820 if (copyout(thing, cmaddr, thingsize))
817 821 error = EFAULT;
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
818 822 } else {
819 823 prunlock(pnp);
820 824 error = EINVAL; /* No extra register support */
821 825 }
822 826 if (thing) {
823 827 kmem_free(thing, thingsize);
824 828 thing = NULL;
825 829 }
826 830 break;
827 831
828 - case PIOCSXREG: /* set extra registers */
829 - if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
830 - error = EBUSY;
831 - else if (!prhasx(p))
832 - error = EINVAL; /* No extra register support */
833 - else if (thing) {
834 - /* drop p_lock while touching the lwp's stack */
835 - mutex_exit(&p->p_lock);
836 - prsetprxregs(lwp, thing);
837 - mutex_enter(&p->p_lock);
838 - }
839 - prunlock(pnp);
840 - if (thing) {
841 - kmem_free(thing, thingsize);
842 - thing = NULL;
843 - }
844 - break;
845 -
846 832 case PIOCSTATUS: /* get process/lwp status */
847 833 oprgetstatus(t, &un.prstat, VTOZONE(vp));
848 834 prunlock(pnp);
849 835 if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
850 836 error = EFAULT;
851 837 break;
852 838
853 839 case PIOCLSTATUS: /* get status for process & all lwps */
854 840 {
855 841 int Nlwp;
856 842 int nlwp;
857 843 prstatus_t *Bprsp;
858 844 prstatus_t *prsp;
859 845
860 846 nlwp = Nlwp = p->p_lwpcnt;
861 847
862 848 if (thing && thingsize != (Nlwp+1) * sizeof (prstatus_t)) {
863 849 kmem_free(thing, thingsize);
864 850 thing = NULL;
865 851 }
866 852 if (thing == NULL) {
867 853 thingsize = (Nlwp+1) * sizeof (prstatus_t);
868 854 thing = kmem_alloc(thingsize, KM_NOSLEEP);
869 855 }
870 856 if (thing == NULL) {
871 857 prunlock(pnp);
872 858 goto startover;
873 859 }
874 860
875 861 Bprsp = thing;
876 862 thing = NULL;
877 863 prsp = Bprsp;
878 864 oprgetstatus(t, prsp, VTOZONE(vp));
879 865 t = p->p_tlist;
880 866 do {
881 867 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
882 868 ASSERT(nlwp > 0);
883 869 --nlwp;
884 870 oprgetstatus(t, ++prsp, VTOZONE(vp));
885 871 } while ((t = t->t_forw) != p->p_tlist);
886 872 ASSERT(nlwp == 0);
887 873 prunlock(pnp);
888 874 if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus_t)))
889 875 error = EFAULT;
890 876
891 877 kmem_free(Bprsp, (Nlwp+1) * sizeof (prstatus_t));
892 878 break;
893 879 }
894 880
895 881 case PIOCPSINFO: /* get ps(1) information */
896 882 {
897 883 prpsinfo_t *psp = &un.prps;
898 884
899 885 oprgetpsinfo(p, psp,
900 886 (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
901 887
902 888 prunlock(pnp);
903 889 if (copyout(&un.prps, cmaddr, sizeof (un.prps)))
904 890 error = EFAULT;
905 891 break;
906 892 }
907 893
908 894 case PIOCMAXSIG: /* get maximum signal number */
909 895 {
910 896 int n = nsig-1;
911 897
912 898 prunlock(pnp);
913 899 if (copyout(&n, cmaddr, sizeof (n)))
914 900 error = EFAULT;
915 901 break;
916 902 }
917 903
918 904 case PIOCACTION: /* get signal action structures */
919 905 {
920 906 uint_t sig;
921 907 struct sigaction *sap = thing;
922 908
923 909 up = PTOU(p);
924 910 for (sig = 1; sig < nsig; sig++)
925 911 prgetaction(p, up, sig, &sap[sig-1]);
926 912 prunlock(pnp);
927 913 if (copyout(sap, cmaddr, (nsig-1) * sizeof (struct sigaction)))
928 914 error = EFAULT;
929 915 kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
930 916 thing = NULL;
931 917 break;
932 918 }
933 919
934 920 case PIOCGHOLD: /* get signal-hold mask */
935 921 prgethold(t, &un.holdmask);
936 922 prunlock(pnp);
937 923 if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask)))
938 924 error = EFAULT;
939 925 break;
940 926
941 927 case PIOCSHOLD: /* set signal-hold mask */
942 928 pr_sethold(pnp, &un.holdmask);
943 929 prunlock(pnp);
944 930 break;
945 931
946 932 case PIOCNMAP: /* get number of memory mappings */
947 933 {
948 934 uint_t n;
949 935 struct as *as = p->p_as;
950 936
951 937 if ((p->p_flag & SSYS) || as == &kas)
952 938 n = 0;
953 939 else {
954 940 mutex_exit(&p->p_lock);
955 941 AS_LOCK_ENTER(as, RW_WRITER);
956 942 n = prnsegs(as, 0);
957 943 AS_LOCK_EXIT(as);
958 944 mutex_enter(&p->p_lock);
959 945 }
960 946 prunlock(pnp);
961 947 if (copyout(&n, cmaddr, sizeof (uint_t)))
962 948 error = EFAULT;
963 949 break;
964 950 }
965 951
966 952 case PIOCMAP: /* get memory map information */
967 953 {
968 954 list_t iolhead;
969 955 struct as *as = p->p_as;
970 956
971 957 if ((p->p_flag & SSYS) || as == &kas) {
972 958 error = 0;
973 959 prunlock(pnp);
974 960 } else {
975 961 mutex_exit(&p->p_lock);
976 962 AS_LOCK_ENTER(as, RW_WRITER);
977 963 error = oprgetmap(p, &iolhead);
978 964 AS_LOCK_EXIT(as);
979 965 mutex_enter(&p->p_lock);
980 966 prunlock(pnp);
981 967
982 968 error = pr_iol_copyout_and_free(&iolhead,
983 969 &cmaddr, error);
984 970 }
985 971 /*
986 972 * The procfs PIOCMAP ioctl returns an all-zero buffer
987 973 * to indicate the end of the prmap[] array.
988 974 * Append it to whatever has already been copied out.
989 975 */
990 976 bzero(&un.prmap, sizeof (un.prmap));
991 977 if (!error && copyout(&un.prmap, cmaddr, sizeof (un.prmap)))
992 978 error = EFAULT;
993 979
994 980 break;
995 981 }
996 982
997 983 case PIOCGFAULT: /* get mask of traced faults */
998 984 prassignset(&un.fltmask, &p->p_fltmask);
999 985 prunlock(pnp);
1000 986 if (copyout(&un.fltmask, cmaddr, sizeof (un.fltmask)))
1001 987 error = EFAULT;
1002 988 break;
1003 989
1004 990 case PIOCSFAULT: /* set mask of traced faults */
1005 991 pr_setfault(p, &un.fltmask);
1006 992 prunlock(pnp);
1007 993 break;
1008 994
1009 995 case PIOCCFAULT: /* clear current fault */
1010 996 lwp->lwp_curflt = 0;
1011 997 prunlock(pnp);
1012 998 break;
1013 999
1014 1000 case PIOCCRED: /* get process credentials */
1015 1001 {
1016 1002 cred_t *cp;
1017 1003
1018 1004 mutex_enter(&p->p_crlock);
1019 1005 cp = p->p_cred;
1020 1006 un.prcred.pr_euid = crgetuid(cp);
1021 1007 un.prcred.pr_ruid = crgetruid(cp);
1022 1008 un.prcred.pr_suid = crgetsuid(cp);
1023 1009 un.prcred.pr_egid = crgetgid(cp);
1024 1010 un.prcred.pr_rgid = crgetrgid(cp);
1025 1011 un.prcred.pr_sgid = crgetsgid(cp);
1026 1012 un.prcred.pr_ngroups = crgetngroups(cp);
1027 1013 mutex_exit(&p->p_crlock);
1028 1014
1029 1015 prunlock(pnp);
1030 1016 if (copyout(&un.prcred, cmaddr, sizeof (un.prcred)))
1031 1017 error = EFAULT;
1032 1018 break;
1033 1019 }
1034 1020
1035 1021 case PIOCGROUPS: /* get supplementary groups */
1036 1022 {
1037 1023 cred_t *cp;
1038 1024
1039 1025 mutex_enter(&p->p_crlock);
1040 1026 cp = p->p_cred;
1041 1027 crhold(cp);
1042 1028 mutex_exit(&p->p_crlock);
1043 1029
1044 1030 prunlock(pnp);
1045 1031 if (copyout(crgetgroups(cp), cmaddr,
1046 1032 MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
1047 1033 error = EFAULT;
1048 1034 crfree(cp);
1049 1035 break;
1050 1036 }
1051 1037
1052 1038 case PIOCUSAGE: /* get usage info */
1053 1039 {
1054 1040 /*
1055 1041 * For an lwp file descriptor, return just the lwp usage.
1056 1042 * For a process file descriptor, return total usage,
1057 1043 * all current lwps plus all defunct lwps.
1058 1044 */
1059 1045 prhusage_t *pup = &un.prhusage;
1060 1046 prusage_t *upup;
1061 1047
1062 1048 bzero(pup, sizeof (*pup));
1063 1049 pup->pr_tstamp = gethrtime();
1064 1050
1065 1051 if (pnp->pr_type == PR_LWPIDFILE) {
1066 1052 t = pcp->prc_thread;
1067 1053 if (t != NULL)
1068 1054 prgetusage(t, pup);
1069 1055 else
1070 1056 error = ENOENT;
1071 1057 } else {
1072 1058 pup->pr_count = p->p_defunct;
1073 1059 pup->pr_create = p->p_mstart;
1074 1060 pup->pr_term = p->p_mterm;
1075 1061
1076 1062 pup->pr_rtime = p->p_mlreal;
1077 1063 pup->pr_utime = p->p_acct[LMS_USER];
1078 1064 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1079 1065 pup->pr_ttime = p->p_acct[LMS_TRAP];
1080 1066 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1081 1067 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1082 1068 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1083 1069 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1084 1070 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1085 1071 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1086 1072 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1087 1073
1088 1074 pup->pr_minf = p->p_ru.minflt;
1089 1075 pup->pr_majf = p->p_ru.majflt;
1090 1076 pup->pr_nswap = p->p_ru.nswap;
1091 1077 pup->pr_inblk = p->p_ru.inblock;
1092 1078 pup->pr_oublk = p->p_ru.oublock;
1093 1079 pup->pr_msnd = p->p_ru.msgsnd;
1094 1080 pup->pr_mrcv = p->p_ru.msgrcv;
1095 1081 pup->pr_sigs = p->p_ru.nsignals;
1096 1082 pup->pr_vctx = p->p_ru.nvcsw;
1097 1083 pup->pr_ictx = p->p_ru.nivcsw;
1098 1084 pup->pr_sysc = p->p_ru.sysc;
1099 1085 pup->pr_ioch = p->p_ru.ioch;
1100 1086
1101 1087 /*
1102 1088 * Add the usage information for each active lwp.
1103 1089 */
1104 1090 if ((t = p->p_tlist) != NULL &&
1105 1091 !(pcp->prc_flags & PRC_DESTROY)) {
1106 1092 do {
1107 1093 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1108 1094 pup->pr_count++;
1109 1095 praddusage(t, pup);
1110 1096 } while ((t = t->t_forw) != p->p_tlist);
1111 1097 }
1112 1098 }
1113 1099
1114 1100 prunlock(pnp);
1115 1101
1116 1102 upup = kmem_zalloc(sizeof (*upup), KM_SLEEP);
1117 1103 prcvtusage(&un.prhusage, upup);
1118 1104 if (copyout(upup, cmaddr, sizeof (*upup)))
1119 1105 error = EFAULT;
1120 1106 kmem_free(upup, sizeof (*upup));
1121 1107
1122 1108 break;
1123 1109 }
1124 1110
1125 1111 case PIOCLUSAGE: /* get detailed usage info */
1126 1112 {
1127 1113 int Nlwp;
1128 1114 int nlwp;
1129 1115 prusage_t *upup;
1130 1116 prusage_t *Bupup;
1131 1117 prhusage_t *pup;
1132 1118 hrtime_t curtime;
1133 1119
1134 1120 nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
1135 1121
1136 1122 if (thing && thingsize !=
1137 1123 sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage_t)) {
1138 1124 kmem_free(thing, thingsize);
1139 1125 thing = NULL;
1140 1126 }
1141 1127 if (thing == NULL) {
1142 1128 thingsize = sizeof (prhusage_t) +
1143 1129 (Nlwp+1) * sizeof (prusage_t);
1144 1130 thing = kmem_alloc(thingsize, KM_NOSLEEP);
1145 1131 }
1146 1132 if (thing == NULL) {
1147 1133 prunlock(pnp);
1148 1134 goto startover;
1149 1135 }
1150 1136
1151 1137 pup = thing;
1152 1138 upup = Bupup = (prusage_t *)(pup + 1);
1153 1139
1154 1140 ASSERT(p == pcp->prc_proc);
1155 1141
1156 1142 curtime = gethrtime();
1157 1143
1158 1144 /*
1159 1145 * First the summation over defunct lwps.
1160 1146 */
1161 1147 bzero(pup, sizeof (*pup));
1162 1148 pup->pr_count = p->p_defunct;
1163 1149 pup->pr_tstamp = curtime;
1164 1150 pup->pr_create = p->p_mstart;
1165 1151 pup->pr_term = p->p_mterm;
1166 1152
1167 1153 pup->pr_rtime = p->p_mlreal;
1168 1154 pup->pr_utime = p->p_acct[LMS_USER];
1169 1155 pup->pr_stime = p->p_acct[LMS_SYSTEM];
1170 1156 pup->pr_ttime = p->p_acct[LMS_TRAP];
1171 1157 pup->pr_tftime = p->p_acct[LMS_TFAULT];
1172 1158 pup->pr_dftime = p->p_acct[LMS_DFAULT];
1173 1159 pup->pr_kftime = p->p_acct[LMS_KFAULT];
1174 1160 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
1175 1161 pup->pr_slptime = p->p_acct[LMS_SLEEP];
1176 1162 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
1177 1163 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1178 1164
1179 1165 pup->pr_minf = p->p_ru.minflt;
1180 1166 pup->pr_majf = p->p_ru.majflt;
1181 1167 pup->pr_nswap = p->p_ru.nswap;
1182 1168 pup->pr_inblk = p->p_ru.inblock;
1183 1169 pup->pr_oublk = p->p_ru.oublock;
1184 1170 pup->pr_msnd = p->p_ru.msgsnd;
1185 1171 pup->pr_mrcv = p->p_ru.msgrcv;
1186 1172 pup->pr_sigs = p->p_ru.nsignals;
1187 1173 pup->pr_vctx = p->p_ru.nvcsw;
1188 1174 pup->pr_ictx = p->p_ru.nivcsw;
1189 1175 pup->pr_sysc = p->p_ru.sysc;
1190 1176 pup->pr_ioch = p->p_ru.ioch;
1191 1177
1192 1178 prcvtusage(pup, upup);
1193 1179
1194 1180 /*
1195 1181 * Fill one prusage struct for each active lwp.
1196 1182 */
1197 1183 if ((t = p->p_tlist) != NULL &&
1198 1184 !(pcp->prc_flags & PRC_DESTROY)) {
1199 1185 do {
1200 1186 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1201 1187 ASSERT(nlwp > 0);
1202 1188 --nlwp;
1203 1189 upup++;
1204 1190 prgetusage(t, pup);
1205 1191 prcvtusage(pup, upup);
1206 1192 } while ((t = t->t_forw) != p->p_tlist);
1207 1193 }
1208 1194 ASSERT(nlwp == 0);
1209 1195
1210 1196 prunlock(pnp);
1211 1197 if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage_t)))
1212 1198 error = EFAULT;
1213 1199 kmem_free(thing, thingsize);
1214 1200 thing = NULL;
1215 1201 break;
1216 1202 }
1217 1203
1218 1204 case PIOCNAUXV: /* get number of aux vector entries */
1219 1205 {
1220 1206 int n = __KERN_NAUXV_IMPL;
1221 1207
1222 1208 prunlock(pnp);
1223 1209 if (copyout(&n, cmaddr, sizeof (int)))
1224 1210 error = EFAULT;
1225 1211 break;
1226 1212 }
1227 1213
1228 1214 case PIOCAUXV: /* get aux vector (see sys/auxv.h) */
1229 1215 {
1230 1216 up = PTOU(p);
1231 1217 bcopy(up->u_auxv, un.auxv,
1232 1218 __KERN_NAUXV_IMPL * sizeof (auxv_t));
1233 1219 prunlock(pnp);
1234 1220 if (copyout(un.auxv, cmaddr,
1235 1221 __KERN_NAUXV_IMPL * sizeof (auxv_t)))
1236 1222 error = EFAULT;
1237 1223 break;
1238 1224 }
1239 1225
1240 1226 #if defined(__x86)
1241 1227 case PIOCNLDT: /* get number of LDT entries */
1242 1228 {
1243 1229 int n;
1244 1230
1245 1231 mutex_exit(&p->p_lock);
1246 1232 mutex_enter(&p->p_ldtlock);
1247 1233 n = prnldt(p);
1248 1234 mutex_exit(&p->p_ldtlock);
1249 1235 mutex_enter(&p->p_lock);
1250 1236 prunlock(pnp);
1251 1237 if (copyout(&n, cmaddr, sizeof (n)))
1252 1238 error = EFAULT;
1253 1239 break;
1254 1240 }
1255 1241
1256 1242 case PIOCLDT: /* get LDT entries */
1257 1243 {
1258 1244 struct ssd *ssd;
1259 1245 int n;
1260 1246
1261 1247 mutex_exit(&p->p_lock);
1262 1248 mutex_enter(&p->p_ldtlock);
1263 1249 n = prnldt(p);
1264 1250
1265 1251 if (thing && thingsize != (n+1) * sizeof (*ssd)) {
1266 1252 kmem_free(thing, thingsize);
1267 1253 thing = NULL;
1268 1254 }
1269 1255 if (thing == NULL) {
1270 1256 thingsize = (n+1) * sizeof (*ssd);
1271 1257 thing = kmem_alloc(thingsize, KM_NOSLEEP);
1272 1258 }
1273 1259 if (thing == NULL) {
1274 1260 mutex_exit(&p->p_ldtlock);
1275 1261 mutex_enter(&p->p_lock);
1276 1262 prunlock(pnp);
1277 1263 goto startover;
1278 1264 }
1279 1265
1280 1266 ssd = thing;
1281 1267 thing = NULL;
1282 1268 if (n != 0)
1283 1269 prgetldt(p, ssd);
1284 1270 mutex_exit(&p->p_ldtlock);
1285 1271 mutex_enter(&p->p_lock);
1286 1272 prunlock(pnp);
1287 1273
1288 1274 /* mark the end of the list with a null entry */
1289 1275 bzero(&ssd[n], sizeof (*ssd));
1290 1276 if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
1291 1277 error = EFAULT;
1292 1278 kmem_free(ssd, (n+1) * sizeof (*ssd));
1293 1279 break;
1294 1280 }
1295 1281 #endif /* __x86 */
1296 1282
1297 1283 #if defined(__sparc)
1298 1284 case PIOCGWIN: /* get gwindows_t (see sys/reg.h) */
1299 1285 {
1300 1286 gwindows_t *gwp = thing;
1301 1287
1302 1288 /* drop p->p_lock while touching the stack */
1303 1289 mutex_exit(&p->p_lock);
1304 1290 bzero(gwp, sizeof (*gwp));
1305 1291 prgetwindows(lwp, gwp);
1306 1292 mutex_enter(&p->p_lock);
1307 1293 prunlock(pnp);
1308 1294 if (copyout(gwp, cmaddr, sizeof (*gwp)))
1309 1295 error = EFAULT;
1310 1296 kmem_free(gwp, sizeof (gwindows_t));
1311 1297 thing = NULL;
1312 1298 break;
1313 1299 }
1314 1300 #endif /* __sparc */
1315 1301
1316 1302 default:
1317 1303 prunlock(pnp);
1318 1304 error = EINVAL;
1319 1305 break;
1320 1306
1321 1307 }
1322 1308
1323 1309 ASSERT(thing == NULL);
1324 1310 ASSERT(xpnp == NULL);
1325 1311 return (error);
1326 1312 }
1327 1313
1328 1314 #ifdef _SYSCALL32_IMPL
1329 1315
1330 1316 static int oprgetmap32(proc_t *, list_t *);
1331 1317
1332 1318 void
1333 1319 oprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp)
1334 1320 {
1335 1321 proc_t *p = ttoproc(t);
1336 1322 klwp_t *lwp = ttolwp(t);
1337 1323 int32_t flags;
1338 1324 user_t *up;
1339 1325 ulong_t instr;
1340 1326
1341 1327 ASSERT(MUTEX_HELD(&p->p_lock));
1342 1328
1343 1329 up = PTOU(p);
1344 1330 bzero(sp, sizeof (*sp));
1345 1331 flags = 0L;
1346 1332 if (t->t_state == TS_STOPPED) {
1347 1333 flags |= PR_STOPPED;
1348 1334 if ((t->t_schedflag & TS_PSTART) == 0)
1349 1335 flags |= PR_ISTOP;
1350 1336 } else if (VSTOPPED(t)) {
1351 1337 flags |= PR_STOPPED|PR_ISTOP;
1352 1338 }
1353 1339 if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
1354 1340 flags |= PR_DSTOP;
1355 1341 if (lwp->lwp_asleep)
1356 1342 flags |= PR_ASLEEP;
1357 1343 if (p->p_proc_flag & P_PR_FORK)
1358 1344 flags |= PR_FORK;
1359 1345 if (p->p_proc_flag & P_PR_RUNLCL)
1360 1346 flags |= PR_RLC;
1361 1347 if (p->p_proc_flag & P_PR_KILLCL)
1362 1348 flags |= PR_KLC;
1363 1349 if (p->p_proc_flag & P_PR_ASYNC)
1364 1350 flags |= PR_ASYNC;
1365 1351 if (p->p_proc_flag & P_PR_BPTADJ)
1366 1352 flags |= PR_BPTADJ;
1367 1353 if (p->p_proc_flag & P_PR_PTRACE)
1368 1354 flags |= PR_PCOMPAT;
1369 1355 if (t->t_proc_flag & TP_MSACCT)
1370 1356 flags |= PR_MSACCT;
1371 1357 sp->pr_flags = flags;
1372 1358 if (VSTOPPED(t)) {
1373 1359 sp->pr_why = PR_REQUESTED;
1374 1360 sp->pr_what = 0;
1375 1361 } else {
1376 1362 sp->pr_why = t->t_whystop;
1377 1363 sp->pr_what = t->t_whatstop;
1378 1364 }
1379 1365
1380 1366 if (t->t_whystop == PR_FAULTED) {
1381 1367 siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
1382 1368 if (t->t_whatstop == FLTPAGE)
1383 1369 sp->pr_info.si_addr =
1384 1370 (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
1385 1371 } else if (lwp->lwp_curinfo)
1386 1372 siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
1387 1373
1388 1374 if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
1389 1375 sp->pr_info.si_zoneid != zp->zone_id) {
1390 1376 sp->pr_info.si_pid = zp->zone_zsched->p_pid;
1391 1377 sp->pr_info.si_uid = 0;
1392 1378 sp->pr_info.si_ctid = -1;
1393 1379 sp->pr_info.si_zoneid = zp->zone_id;
1394 1380 }
1395 1381
1396 1382 sp->pr_cursig = lwp->lwp_cursig;
1397 1383 prassignset(&sp->pr_sigpend, &p->p_sig);
1398 1384 prassignset(&sp->pr_lwppend, &t->t_sig);
1399 1385 prgethold(t, &sp->pr_sighold);
1400 1386 sp->pr_altstack.ss_sp =
1401 1387 (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
1402 1388 sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
1403 1389 sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
1404 1390 prgetaction32(p, up, lwp->lwp_cursig, &sp->pr_action);
1405 1391 sp->pr_pid = p->p_pid;
1406 1392 if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
1407 1393 (p->p_flag & SZONETOP)) {
1408 1394 ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
1409 1395 /*
1410 1396 * Inside local zones, fake zsched's pid as parent pids for
1411 1397 * processes which reference processes outside of the zone.
1412 1398 */
1413 1399 sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
1414 1400 } else {
1415 1401 sp->pr_ppid = p->p_ppid;
1416 1402 }
1417 1403 sp->pr_pgrp = p->p_pgrp;
1418 1404 sp->pr_sid = p->p_sessp->s_sid;
1419 1405 hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
1420 1406 hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
1421 1407 TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
1422 1408 TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
1423 1409 (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
1424 1410 sizeof (sp->pr_clname) - 1);
1425 1411 sp->pr_who = t->t_tid;
1426 1412 sp->pr_nlwp = p->p_lwpcnt;
1427 1413 sp->pr_brkbase = (caddr32_t)(uintptr_t)p->p_brkbase;
1428 1414 sp->pr_brksize = (size32_t)p->p_brksize;
1429 1415 sp->pr_stkbase = (caddr32_t)(uintptr_t)prgetstackbase(p);
1430 1416 sp->pr_stksize = (size32_t)p->p_stksize;
1431 1417 sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
1432 1418 sp->pr_processor = t->t_cpu->cpu_id;
1433 1419 sp->pr_bind = t->t_bind_cpu;
1434 1420
1435 1421 /*
1436 1422 * Fetch the current instruction, if not a system process.
1437 1423 * We don't attempt this unless the lwp is stopped.
1438 1424 */
1439 1425 if ((p->p_flag & SSYS) || p->p_as == &kas)
1440 1426 sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
1441 1427 else if (!(flags & PR_STOPPED))
1442 1428 sp->pr_flags |= PR_PCINVAL;
1443 1429 else if (!prfetchinstr(lwp, &instr))
1444 1430 sp->pr_flags |= PR_PCINVAL;
1445 1431 else
1446 1432 sp->pr_instr = (uint32_t)instr;
1447 1433
1448 1434 /*
1449 1435 * Drop p_lock while touching the lwp's stack.
1450 1436 */
1451 1437 mutex_exit(&p->p_lock);
1452 1438 if (prisstep(lwp))
1453 1439 sp->pr_flags |= PR_STEP;
1454 1440 if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
1455 1441 int i;
1456 1442 auxv_t *auxp;
1457 1443
1458 1444 sp->pr_syscall = get_syscall32_args(lwp,
1459 1445 (int *)sp->pr_sysarg, &i);
1460 1446 sp->pr_nsysarg = (short)i;
1461 1447 if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
1462 1448 sp->pr_sysarg[0] = 0;
1463 1449 sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
1464 1450 sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
1465 1451 for (i = 0, auxp = up->u_auxv;
1466 1452 i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
1467 1453 i++, auxp++) {
1468 1454 if (auxp->a_type == AT_SUN_EXECNAME) {
1469 1455 sp->pr_sysarg[0] =
1470 1456 (caddr32_t)
1471 1457 (uintptr_t)auxp->a_un.a_ptr;
1472 1458 break;
1473 1459 }
1474 1460 }
1475 1461 }
1476 1462 }
1477 1463 if ((flags & PR_STOPPED) || t == curthread)
1478 1464 prgetprregs32(lwp, sp->pr_reg);
1479 1465 mutex_enter(&p->p_lock);
1480 1466 }
1481 1467
1482 1468 void
1483 1469 oprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp)
1484 1470 {
1485 1471 kthread_t *t;
1486 1472 char c, state;
1487 1473 user_t *up;
1488 1474 dev_t d;
1489 1475 uint64_t pct;
1490 1476 int retval, niceval;
1491 1477 cred_t *cred;
1492 1478 struct as *as;
1493 1479 hrtime_t hrutime, hrstime, cur_time;
1494 1480
1495 1481 ASSERT(MUTEX_HELD(&p->p_lock));
1496 1482
1497 1483 bzero(psp, sizeof (*psp));
1498 1484
1499 1485 if ((t = tp) == NULL)
1500 1486 t = prchoose(p); /* returns locked thread */
1501 1487 else
1502 1488 thread_lock(t);
1503 1489
1504 1490 /* kludge: map thread state enum into process state enum */
1505 1491
1506 1492 if (t == NULL) {
1507 1493 state = TS_ZOMB;
1508 1494 } else {
1509 1495 state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
1510 1496 thread_unlock(t);
1511 1497 }
1512 1498
1513 1499 switch (state) {
1514 1500 case TS_SLEEP: state = SSLEEP; break;
1515 1501 case TS_RUN: state = SRUN; break;
1516 1502 case TS_ONPROC: state = SONPROC; break;
1517 1503 case TS_ZOMB: state = SZOMB; break;
1518 1504 case TS_STOPPED: state = SSTOP; break;
1519 1505 default: state = 0; break;
1520 1506 }
1521 1507 switch (state) {
1522 1508 case SSLEEP: c = 'S'; break;
1523 1509 case SRUN: c = 'R'; break;
1524 1510 case SZOMB: c = 'Z'; break;
1525 1511 case SSTOP: c = 'T'; break;
1526 1512 case SIDL: c = 'I'; break;
1527 1513 case SONPROC: c = 'O'; break;
1528 1514 #ifdef SXBRK
1529 1515 case SXBRK: c = 'X'; break;
1530 1516 #endif
1531 1517 default: c = '?'; break;
1532 1518 }
1533 1519 psp->pr_state = state;
1534 1520 psp->pr_sname = c;
1535 1521 psp->pr_zomb = (state == SZOMB);
1536 1522 /*
1537 1523 * only export SSYS and SMSACCT; everything else is off-limits to
1538 1524 * userland apps.
1539 1525 */
1540 1526 psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
1541 1527
1542 1528 mutex_enter(&p->p_crlock);
1543 1529 cred = p->p_cred;
1544 1530 psp->pr_uid = crgetruid(cred);
1545 1531 psp->pr_gid = crgetrgid(cred);
1546 1532 psp->pr_euid = crgetuid(cred);
1547 1533 psp->pr_egid = crgetgid(cred);
1548 1534 mutex_exit(&p->p_crlock);
1549 1535
1550 1536 psp->pr_pid = p->p_pid;
1551 1537 if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
1552 1538 (p->p_flag & SZONETOP)) {
1553 1539 ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
1554 1540 /*
1555 1541 * Inside local zones, fake zsched's pid as parent pids for
1556 1542 * processes which reference processes outside of the zone.
1557 1543 */
1558 1544 psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
1559 1545 } else {
1560 1546 psp->pr_ppid = p->p_ppid;
1561 1547 }
1562 1548 psp->pr_pgrp = p->p_pgrp;
1563 1549 psp->pr_sid = p->p_sessp->s_sid;
1564 1550 psp->pr_addr = 0; /* cannot represent 64-bit addr in 32 bits */
1565 1551 hrutime = mstate_aggr_state(p, LMS_USER);
1566 1552 hrstime = mstate_aggr_state(p, LMS_SYSTEM);
1567 1553 hrt2ts32(hrutime + hrstime, &psp->pr_time);
1568 1554 TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
1569 1555 switch (p->p_model) {
1570 1556 case DATAMODEL_ILP32:
1571 1557 psp->pr_dmodel = PR_MODEL_ILP32;
1572 1558 break;
1573 1559 case DATAMODEL_LP64:
1574 1560 psp->pr_dmodel = PR_MODEL_LP64;
1575 1561 break;
1576 1562 }
1577 1563 if (state == SZOMB || t == NULL) {
1578 1564 int wcode = p->p_wcode; /* must be atomic read */
1579 1565
1580 1566 if (wcode)
1581 1567 psp->pr_wstat = wstat(wcode, p->p_wdata);
1582 1568 psp->pr_lttydev = PRNODEV32;
1583 1569 psp->pr_ottydev = (o_dev_t)PRNODEV32;
1584 1570 psp->pr_size = 0;
1585 1571 psp->pr_rssize = 0;
1586 1572 psp->pr_pctmem = 0;
1587 1573 } else {
1588 1574 up = PTOU(p);
1589 1575 psp->pr_wchan = 0; /* cannot represent in 32 bits */
1590 1576 psp->pr_pri = t->t_pri;
1591 1577 (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
1592 1578 sizeof (psp->pr_clname) - 1);
1593 1579 retval = CL_DONICE(t, NULL, 0, &niceval);
1594 1580 if (retval == 0) {
1595 1581 psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
1596 1582 psp->pr_nice = niceval + NZERO;
1597 1583 } else {
1598 1584 psp->pr_oldpri = 0;
1599 1585 psp->pr_nice = 0;
1600 1586 }
1601 1587 d = cttydev(p);
1602 1588 #ifdef sun
1603 1589 {
1604 1590 extern dev_t rwsconsdev, rconsdev, uconsdev;
1605 1591 /*
1606 1592 * If the controlling terminal is the real
1607 1593 * or workstation console device, map to what the
1608 1594 * user thinks is the console device. Handle case when
1609 1595 * rwsconsdev or rconsdev is set to NODEV for Starfire.
1610 1596 */
1611 1597 if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
1612 1598 d = uconsdev;
1613 1599 }
1614 1600 #endif
1615 1601 (void) cmpldev(&psp->pr_lttydev, d);
1616 1602 psp->pr_ottydev = cmpdev(d);
1617 1603 TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
1618 1604 bcopy(up->u_comm, psp->pr_fname,
1619 1605 MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
1620 1606 bcopy(up->u_psargs, psp->pr_psargs,
1621 1607 MIN(PRARGSZ-1, PSARGSZ));
1622 1608 psp->pr_syscall = t->t_sysnum;
1623 1609 psp->pr_argc = up->u_argc;
1624 1610 psp->pr_argv = (caddr32_t)up->u_argv;
1625 1611 psp->pr_envp = (caddr32_t)up->u_envp;
1626 1612
1627 1613 /* compute %cpu for the lwp or process */
1628 1614 pct = 0;
1629 1615 if ((t = tp) == NULL)
1630 1616 t = p->p_tlist;
1631 1617 cur_time = gethrtime_unscaled();
1632 1618 do {
1633 1619 pct += cpu_update_pct(t, cur_time);
1634 1620 if (tp != NULL) /* just do the one lwp */
1635 1621 break;
1636 1622 } while ((t = t->t_forw) != p->p_tlist);
1637 1623
1638 1624 psp->pr_pctcpu = prgetpctcpu(pct);
1639 1625 psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
1640 1626 if (psp->pr_cpu > 99)
1641 1627 psp->pr_cpu = 99;
1642 1628
1643 1629 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
1644 1630 psp->pr_size = 0;
1645 1631 psp->pr_rssize = 0;
1646 1632 psp->pr_pctmem = 0;
1647 1633 } else {
1648 1634 mutex_exit(&p->p_lock);
1649 1635 AS_LOCK_ENTER(as, RW_READER);
1650 1636 psp->pr_size = (size32_t)btopr(as->a_resvsize);
1651 1637 psp->pr_rssize = (size32_t)rm_asrss(as);
1652 1638 psp->pr_pctmem = rm_pctmemory(as);
1653 1639 AS_LOCK_EXIT(as);
1654 1640 mutex_enter(&p->p_lock);
1655 1641 }
1656 1642 }
1657 1643 psp->pr_bysize = (size32_t)ptob(psp->pr_size);
1658 1644 psp->pr_byrssize = (size32_t)ptob(psp->pr_rssize);
1659 1645
1660 1646 /*
1661 1647 * If we are looking at an LP64 process, zero out
1662 1648 * the fields that cannot be represented in ILP32.
1663 1649 */
1664 1650 if (p->p_model != DATAMODEL_ILP32) {
1665 1651 psp->pr_size = 0;
1666 1652 psp->pr_rssize = 0;
1667 1653 psp->pr_bysize = 0;
1668 1654 psp->pr_byrssize = 0;
1669 1655 psp->pr_argv = 0;
1670 1656 psp->pr_envp = 0;
1671 1657 }
1672 1658 }
1673 1659
1674 1660 /*ARGSUSED*/
1675 1661 static int
1676 1662 prioctl32(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
1677 1663 int *rvalp, caller_context_t *ct)
1678 1664 {
1679 1665 int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1680 1666 caddr_t cmaddr = (caddr_t)arg;
1681 1667 proc_t *p;
1682 1668 user_t *up;
1683 1669 kthread_t *t;
1684 1670 klwp_t *lwp;
1685 1671 prnode_t *pnp = VTOP(vp);
1686 1672 prcommon_t *pcp;
1687 1673 prnode_t *xpnp = NULL;
1688 1674 int error;
1689 1675 int zdisp;
1690 1676 void *thing = NULL;
1691 1677 size_t thingsize = 0;
1692 1678
1693 1679 /*
1694 1680 * For copyin()/copyout().
1695 1681 */
1696 1682 union {
1697 1683 caddr32_t va;
1698 1684 int signo;
1699 1685 int nice;
1700 1686 uint_t lwpid;
1701 1687 int32_t flags;
1702 1688 prstatus32_t prstat;
1703 1689 prrun32_t prrun;
1704 1690 sigset_t smask;
1705 1691 siginfo32_t info;
1706 1692 sysset_t prmask;
1707 1693 prgregset32_t regs;
1708 1694 prfpregset32_t fpregs;
1709 1695 prpsinfo32_t prps;
1710 1696 sigset_t holdmask;
1711 1697 fltset_t fltmask;
1712 1698 prcred_t prcred;
1713 1699 prusage32_t prusage;
1714 1700 prhusage_t prhusage;
1715 1701 ioc_prmap32_t prmap;
1716 1702 auxv32_t auxv[__KERN_NAUXV_IMPL];
1717 1703 } un32;
1718 1704
1719 1705 /*
1720 1706 * Native objects for internal use.
1721 1707 */
1722 1708 union {
1723 1709 caddr_t va;
1724 1710 int signo;
1725 1711 int nice;
1726 1712 uint_t lwpid;
1727 1713 long flags;
1728 1714 prstatus_t prstat;
1729 1715 prrun_t prrun;
1730 1716 sigset_t smask;
1731 1717 siginfo_t info;
1732 1718 sysset_t prmask;
1733 1719 prgregset_t regs;
1734 1720 prpsinfo_t prps;
1735 1721 sigset_t holdmask;
1736 1722 fltset_t fltmask;
1737 1723 prcred_t prcred;
1738 1724 prusage_t prusage;
1739 1725 prhusage_t prhusage;
1740 1726 auxv_t auxv[__KERN_NAUXV_IMPL];
1741 1727 } un;
1742 1728
1743 1729 if (pnp->pr_type == PR_TMPL)
1744 1730 return (prctioctl(pnp, cmd, arg, flag, cr));
1745 1731
1746 1732 /*
1747 1733 * Support for old /proc interface.
1748 1734 */
1749 1735 if (pnp->pr_pidfile != NULL) {
1750 1736 ASSERT(pnp->pr_type == PR_PIDDIR);
1751 1737 vp = pnp->pr_pidfile;
1752 1738 pnp = VTOP(vp);
1753 1739 ASSERT(pnp->pr_type == PR_PIDFILE);
1754 1740 }
1755 1741
1756 1742 if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
|
↓ open down ↓ |
901 lines elided |
↑ open up ↑ |
1757 1743 return (ENOTTY);
1758 1744
1759 1745 /*
1760 1746 * Fail ioctls which are logically "write" requests unless
1761 1747 * the user has write permission.
1762 1748 */
1763 1749 if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
1764 1750 return (EBADF);
1765 1751
1766 1752 /*
1753 + * The following commands are no longer supported. They were present on
1754 + * SPARC and were always errors on other platforms. We now explicitly
1755 + * return ENOTSUP to indicate that this is no longer done.
1756 + */
1757 + switch (cmd) {
1758 + case PIOCSXREG:
1759 + return (ENOTSUP);
1760 + default:
1761 + break;
1762 + }
1763 +
1764 + /*
1767 1765 * Perform any necessary copyin() operations before
1768 1766 * locking the process. Helps avoid deadlocks and
1769 1767 * improves performance.
1770 1768 *
1771 1769 * Also, detect invalid ioctl codes here to avoid
1772 - * locking a process unnnecessarily.
1770 + * locking a process unnecessarily.
1773 1771 *
1774 1772 * Also, prepare to allocate space that will be needed below,
1775 1773 * case by case.
1776 1774 */
1777 1775 error = 0;
1778 1776 switch (cmd) {
1779 1777 case PIOCGETPR:
1780 1778 thingsize = sizeof (proc_t);
1781 1779 break;
1782 1780 case PIOCGETU:
1783 1781 thingsize = sizeof (user_t);
1784 1782 break;
1785 1783 case PIOCSTOP:
1786 1784 case PIOCWSTOP:
1787 1785 case PIOCLWPIDS:
1788 1786 case PIOCGTRACE:
1789 1787 case PIOCGENTRY:
1790 1788 case PIOCGEXIT:
1791 1789 case PIOCSRLC:
1792 1790 case PIOCRRLC:
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1793 1791 case PIOCSFORK:
1794 1792 case PIOCRFORK:
1795 1793 case PIOCGREG:
1796 1794 case PIOCGFPREG:
1797 1795 case PIOCSTATUS:
1798 1796 case PIOCLSTATUS:
1799 1797 case PIOCPSINFO:
1800 1798 case PIOCMAXSIG:
1801 1799 case PIOCGXREGSIZE:
1802 1800 break;
1803 - case PIOCSXREG: /* set extra registers */
1804 1801 case PIOCGXREG: /* get extra registers */
1805 -#if defined(__sparc)
1806 - thingsize = sizeof (prxregset_t);
1807 -#else
1808 - thingsize = 0;
1809 -#endif
1802 + thingsize = prgetprxregsize(p);
1810 1803 break;
1811 1804 case PIOCACTION:
1812 1805 thingsize = (nsig-1) * sizeof (struct sigaction32);
1813 1806 break;
1814 1807 case PIOCGHOLD:
1815 1808 case PIOCNMAP:
1816 1809 case PIOCMAP:
1817 1810 case PIOCGFAULT:
1818 1811 case PIOCCFAULT:
1819 1812 case PIOCCRED:
1820 1813 case PIOCGROUPS:
1821 1814 case PIOCUSAGE:
1822 1815 case PIOCLUSAGE:
1823 1816 break;
1824 1817 case PIOCOPENPD:
1825 1818 /*
1826 1819 * We will need this below.
1827 1820 * Allocate it now, before locking the process.
1828 1821 */
1829 1822 xpnp = prgetnode(vp, PR_OPAGEDATA);
1830 1823 break;
1831 1824 case PIOCNAUXV:
1832 1825 case PIOCAUXV:
1833 1826 break;
1834 1827
1835 1828 #if defined(__i386_COMPAT)
1836 1829 case PIOCNLDT:
1837 1830 case PIOCLDT:
1838 1831 break;
1839 1832 #endif /* __i386_COMPAT */
1840 1833
1841 1834 #if defined(__sparc)
1842 1835 case PIOCGWIN:
1843 1836 thingsize = sizeof (gwindows32_t);
1844 1837 break;
1845 1838 #endif /* __sparc */
1846 1839
1847 1840 case PIOCOPENM: /* open mapped object for reading */
1848 1841 if (cmaddr == NULL)
1849 1842 un32.va = (caddr32_t)(uintptr_t)NULL;
1850 1843 else if (copyin(cmaddr, &un32.va, sizeof (un32.va)))
1851 1844 error = EFAULT;
1852 1845 break;
1853 1846
1854 1847 case PIOCRUN: /* make lwp or process runnable */
1855 1848 if (cmaddr == NULL)
1856 1849 un32.prrun.pr_flags = 0;
1857 1850 else if (copyin(cmaddr, &un32.prrun, sizeof (un32.prrun)))
1858 1851 error = EFAULT;
1859 1852 break;
1860 1853
1861 1854 case PIOCOPENLWP: /* return /proc lwp file descriptor */
1862 1855 if (copyin(cmaddr, &un32.lwpid, sizeof (un32.lwpid)))
1863 1856 error = EFAULT;
1864 1857 break;
1865 1858
1866 1859 case PIOCSTRACE: /* set signal trace mask */
1867 1860 if (copyin(cmaddr, &un32.smask, sizeof (un32.smask)))
1868 1861 error = EFAULT;
1869 1862 break;
1870 1863
1871 1864 case PIOCSSIG: /* set current signal */
1872 1865 if (cmaddr == NULL)
1873 1866 un32.info.si_signo = 0;
1874 1867 else if (copyin(cmaddr, &un32.info, sizeof (un32.info)))
1875 1868 error = EFAULT;
1876 1869 break;
1877 1870
1878 1871 case PIOCKILL: /* send signal */
1879 1872 case PIOCUNKILL: /* delete a signal */
1880 1873 if (copyin(cmaddr, &un32.signo, sizeof (un32.signo)))
1881 1874 error = EFAULT;
1882 1875 break;
1883 1876
1884 1877 case PIOCNICE: /* set nice priority */
1885 1878 if (copyin(cmaddr, &un32.nice, sizeof (un32.nice)))
1886 1879 error = EFAULT;
1887 1880 break;
1888 1881
1889 1882 case PIOCSENTRY: /* set syscall entry bit mask */
1890 1883 case PIOCSEXIT: /* set syscall exit bit mask */
1891 1884 if (copyin(cmaddr, &un32.prmask, sizeof (un32.prmask)))
1892 1885 error = EFAULT;
1893 1886 break;
1894 1887
1895 1888 case PIOCSET: /* set process flags */
1896 1889 case PIOCRESET: /* reset process flags */
1897 1890 if (copyin(cmaddr, &un32.flags, sizeof (un32.flags)))
1898 1891 error = EFAULT;
1899 1892 break;
1900 1893
1901 1894 case PIOCSREG: /* set general registers */
1902 1895 if (copyin(cmaddr, un32.regs, sizeof (un32.regs)))
1903 1896 error = EFAULT;
1904 1897 break;
1905 1898
1906 1899 case PIOCSFPREG: /* set floating-point registers */
1907 1900 if (copyin(cmaddr, &un32.fpregs, sizeof (un32.fpregs)))
1908 1901 error = EFAULT;
1909 1902 break;
1910 1903
1911 1904 case PIOCSHOLD: /* set signal-hold mask */
1912 1905 if (copyin(cmaddr, &un32.holdmask, sizeof (un32.holdmask)))
1913 1906 error = EFAULT;
1914 1907 break;
1915 1908
1916 1909 case PIOCSFAULT: /* set mask of traced faults */
1917 1910 if (copyin(cmaddr, &un32.fltmask, sizeof (un32.fltmask)))
1918 1911 error = EFAULT;
1919 1912 break;
1920 1913
1921 1914 default:
1922 1915 error = EINVAL;
1923 1916 break;
1924 1917 }
1925 1918
1926 1919 if (error)
1927 1920 return (error);
1928 1921
1929 1922 startover:
1930 1923 /*
1931 1924 * If we need kmem_alloc()d space then we allocate it now, before
1932 1925 * grabbing the process lock. Using kmem_alloc(KM_SLEEP) while
1933 1926 * holding the process lock leads to deadlock with the clock thread.
1934 1927 * (The clock thread wakes up the pageout daemon to free up space.
1935 1928 * If the clock thread blocks behind us and we are sleeping waiting
1936 1929 * for space, then space may never become available.)
1937 1930 */
1938 1931 if (thingsize) {
1939 1932 ASSERT(thing == NULL);
|
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
1940 1933 thing = kmem_alloc(thingsize, KM_SLEEP);
1941 1934 }
1942 1935
1943 1936 switch (cmd) {
1944 1937 case PIOCPSINFO:
1945 1938 case PIOCGETPR:
1946 1939 case PIOCUSAGE:
1947 1940 case PIOCLUSAGE:
1948 1941 zdisp = ZYES;
1949 1942 break;
1950 - case PIOCSXREG: /* set extra registers */
1951 - /*
1952 - * perform copyin before grabbing the process lock
1953 - */
1954 - if (thing) {
1955 - if (copyin(cmaddr, thing, thingsize)) {
1956 - kmem_free(thing, thingsize);
1957 - return (EFAULT);
1958 - }
1959 - }
1960 - /* fall through... */
1961 1943 default:
1962 1944 zdisp = ZNO;
1963 1945 break;
1964 1946 }
1965 1947
1966 1948 if ((error = prlock(pnp, zdisp)) != 0) {
1967 1949 if (thing != NULL)
1968 1950 kmem_free(thing, thingsize);
1969 1951 if (xpnp)
1970 1952 prfreenode(xpnp);
1971 1953 return (error);
1972 1954 }
1973 1955
1974 1956 pcp = pnp->pr_common;
1975 1957 p = pcp->prc_proc;
1976 1958 ASSERT(p != NULL);
1977 1959
1978 1960 /*
1979 1961 * Choose a thread/lwp for the operation.
1980 1962 */
1981 1963 if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
1982 1964 if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
1983 1965 t = pcp->prc_thread;
1984 1966 ASSERT(t != NULL);
1985 1967 } else {
1986 1968 t = prchoose(p); /* returns locked thread */
1987 1969 ASSERT(t != NULL);
1988 1970 thread_unlock(t);
1989 1971 }
1990 1972 lwp = ttolwp(t);
1991 1973 }
1992 1974
1993 1975 error = 0;
1994 1976 switch (cmd) {
1995 1977
1996 1978 case PIOCGETPR: /* read struct proc */
1997 1979 {
1998 1980 proc_t *prp = thing;
1999 1981
2000 1982 *prp = *p;
2001 1983 prunlock(pnp);
2002 1984 if (copyout(prp, cmaddr, sizeof (proc_t)))
2003 1985 error = EFAULT;
2004 1986 kmem_free(prp, sizeof (proc_t));
2005 1987 thing = NULL;
2006 1988 break;
2007 1989 }
2008 1990
2009 1991 case PIOCGETU: /* read u-area */
2010 1992 {
2011 1993 user_t *userp = thing;
2012 1994
2013 1995 up = PTOU(p);
2014 1996 *userp = *up;
2015 1997 prunlock(pnp);
2016 1998 if (copyout(userp, cmaddr, sizeof (user_t)))
2017 1999 error = EFAULT;
2018 2000 kmem_free(userp, sizeof (user_t));
2019 2001 thing = NULL;
2020 2002 break;
2021 2003 }
2022 2004
2023 2005 case PIOCOPENM: /* open mapped object for reading */
2024 2006 if (PROCESS_NOT_32BIT(p) && cmaddr != NULL) {
2025 2007 prunlock(pnp);
2026 2008 error = EOVERFLOW;
2027 2009 break;
2028 2010 }
2029 2011 error = propenm(pnp, cmaddr,
2030 2012 (caddr_t)(uintptr_t)un32.va, rvalp, cr);
2031 2013 /* propenm() called prunlock(pnp) */
2032 2014 break;
2033 2015
2034 2016 case PIOCSTOP: /* stop process or lwp from running */
2035 2017 case PIOCWSTOP: /* wait for process or lwp to stop */
2036 2018 /*
2037 2019 * Can't apply to a system process.
2038 2020 */
2039 2021 if ((p->p_flag & SSYS) || p->p_as == &kas) {
2040 2022 prunlock(pnp);
2041 2023 error = EBUSY;
2042 2024 break;
2043 2025 }
2044 2026
2045 2027 if (cmd == PIOCSTOP)
2046 2028 pr_stop(pnp);
2047 2029
2048 2030 /*
2049 2031 * If an lwp is waiting for itself or its process, don't wait.
2050 2032 * The lwp will never see the fact that itself is stopped.
2051 2033 */
2052 2034 if ((pnp->pr_type == PR_LWPIDFILE)?
2053 2035 (pcp->prc_thread == curthread) : (p == curproc)) {
2054 2036 if (cmd == PIOCWSTOP)
2055 2037 error = EBUSY;
2056 2038 prunlock(pnp);
2057 2039 break;
2058 2040 }
2059 2041
2060 2042 if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
2061 2043 break; /* pr_wait_stop() unlocked the process */
2062 2044
2063 2045 if (cmaddr == NULL)
2064 2046 prunlock(pnp);
2065 2047 else if (PROCESS_NOT_32BIT(p)) {
2066 2048 prunlock(pnp);
2067 2049 error = EOVERFLOW;
2068 2050 } else {
2069 2051 /*
2070 2052 * Return process/lwp status information.
2071 2053 */
2072 2054 t = pr_thread(pnp); /* returns locked thread */
2073 2055 thread_unlock(t);
2074 2056 oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
2075 2057 prunlock(pnp);
2076 2058 if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
2077 2059 error = EFAULT;
2078 2060 }
2079 2061 break;
2080 2062
2081 2063 case PIOCRUN: /* make lwp or process runnable */
2082 2064 {
2083 2065 long flags = un32.prrun.pr_flags;
2084 2066
2085 2067 /*
2086 2068 * Cannot set an lwp running is it is not stopped.
2087 2069 * Also, no lwp other than the /proc agent lwp can
2088 2070 * be set running so long as the /proc agent lwp exists.
2089 2071 */
2090 2072 if ((!ISTOPPED(t) && !VSTOPPED(t) &&
2091 2073 !(t->t_proc_flag & TP_PRSTOP)) ||
2092 2074 (p->p_agenttp != NULL &&
2093 2075 (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
2094 2076 prunlock(pnp);
2095 2077 error = EBUSY;
2096 2078 break;
2097 2079 }
2098 2080
2099 2081 if ((flags & PRSVADDR) && PROCESS_NOT_32BIT(p)) {
2100 2082 prunlock(pnp);
2101 2083 error = EOVERFLOW;
2102 2084 break;
2103 2085 }
2104 2086
2105 2087 if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR)) {
2106 2088 un.prrun.pr_flags = (int)flags;
2107 2089 un.prrun.pr_trace = un32.prrun.pr_trace;
2108 2090 un.prrun.pr_sighold = un32.prrun.pr_sighold;
2109 2091 un.prrun.pr_fault = un32.prrun.pr_fault;
2110 2092 un.prrun.pr_vaddr =
2111 2093 (caddr_t)(uintptr_t)un32.prrun.pr_vaddr;
2112 2094 prsetrun(t, &un.prrun);
2113 2095 }
2114 2096
2115 2097 error = pr_setrun(pnp, prmaprunflags(flags));
2116 2098
2117 2099 prunlock(pnp);
2118 2100 break;
2119 2101 }
2120 2102
2121 2103 case PIOCLWPIDS: /* get array of lwp identifiers */
2122 2104 {
2123 2105 int nlwp;
2124 2106 int Nlwp;
2125 2107 id_t *idp;
2126 2108 id_t *Bidp;
2127 2109
2128 2110 Nlwp = nlwp = p->p_lwpcnt;
2129 2111
2130 2112 if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
2131 2113 kmem_free(thing, thingsize);
2132 2114 thing = NULL;
2133 2115 }
2134 2116 if (thing == NULL) {
2135 2117 thingsize = (Nlwp+1) * sizeof (id_t);
2136 2118 thing = kmem_alloc(thingsize, KM_NOSLEEP);
2137 2119 }
2138 2120 if (thing == NULL) {
2139 2121 prunlock(pnp);
2140 2122 goto startover;
2141 2123 }
2142 2124
2143 2125 idp = thing;
2144 2126 thing = NULL;
2145 2127 Bidp = idp;
2146 2128 if ((t = p->p_tlist) != NULL) {
2147 2129 do {
2148 2130 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2149 2131 ASSERT(nlwp > 0);
2150 2132 --nlwp;
2151 2133 *idp++ = t->t_tid;
2152 2134 } while ((t = t->t_forw) != p->p_tlist);
2153 2135 }
2154 2136 *idp = 0;
2155 2137 ASSERT(nlwp == 0);
2156 2138 prunlock(pnp);
2157 2139 if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
2158 2140 error = EFAULT;
2159 2141 kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
2160 2142 break;
2161 2143 }
2162 2144
2163 2145 case PIOCOPENLWP: /* return /proc lwp file descriptor */
2164 2146 {
2165 2147 vnode_t *xvp;
2166 2148 int n;
2167 2149
2168 2150 prunlock(pnp);
2169 2151 if ((xvp = prlwpnode(pnp, un32.lwpid)) == NULL)
2170 2152 error = ENOENT;
2171 2153 else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
2172 2154 VN_RELE(xvp);
2173 2155 } else
2174 2156 *rvalp = n;
2175 2157 break;
2176 2158 }
2177 2159
2178 2160 case PIOCOPENPD: /* return /proc page data file descriptor */
2179 2161 {
2180 2162 vnode_t *xvp = PTOV(xpnp);
2181 2163 vnode_t *dp = pnp->pr_parent;
2182 2164 int n;
2183 2165
2184 2166 if (PROCESS_NOT_32BIT(p)) {
2185 2167 prunlock(pnp);
2186 2168 prfreenode(xpnp);
2187 2169 xpnp = NULL;
2188 2170 error = EOVERFLOW;
2189 2171 break;
2190 2172 }
2191 2173
2192 2174 if (pnp->pr_type == PR_LWPIDFILE) {
2193 2175 dp = VTOP(dp)->pr_parent;
2194 2176 dp = VTOP(dp)->pr_parent;
2195 2177 }
2196 2178 ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
2197 2179
2198 2180 VN_HOLD(dp);
2199 2181 pcp = pnp->pr_pcommon;
2200 2182 xpnp->pr_ino = ptoi(pcp->prc_pid);
2201 2183 xpnp->pr_common = pcp;
2202 2184 xpnp->pr_pcommon = pcp;
2203 2185 xpnp->pr_parent = dp;
2204 2186
2205 2187 xpnp->pr_next = p->p_plist;
2206 2188 p->p_plist = xvp;
2207 2189
2208 2190 prunlock(pnp);
2209 2191 if (error = fassign(&xvp, FREAD, &n)) {
2210 2192 VN_RELE(xvp);
2211 2193 } else
2212 2194 *rvalp = n;
2213 2195
2214 2196 xpnp = NULL;
2215 2197 break;
2216 2198 }
2217 2199
2218 2200 case PIOCGTRACE: /* get signal trace mask */
2219 2201 prassignset(&un32.smask, &p->p_sigmask);
2220 2202 prunlock(pnp);
2221 2203 if (copyout(&un32.smask, cmaddr, sizeof (un32.smask)))
2222 2204 error = EFAULT;
2223 2205 break;
2224 2206
2225 2207 case PIOCSTRACE: /* set signal trace mask */
2226 2208 prdelset(&un32.smask, SIGKILL);
2227 2209 prassignset(&p->p_sigmask, &un32.smask);
2228 2210 if (!sigisempty(&p->p_sigmask))
2229 2211 p->p_proc_flag |= P_PR_TRACE;
2230 2212 else if (prisempty(&p->p_fltmask)) {
2231 2213 up = PTOU(p);
2232 2214 if (up->u_systrap == 0)
2233 2215 p->p_proc_flag &= ~P_PR_TRACE;
2234 2216 }
2235 2217 prunlock(pnp);
2236 2218 break;
2237 2219
2238 2220 case PIOCSSIG: /* set current signal */
2239 2221 if (un32.info.si_signo != 0 && PROCESS_NOT_32BIT(p)) {
2240 2222 prunlock(pnp);
2241 2223 error = EOVERFLOW;
2242 2224 } else {
2243 2225 bzero(&un.info, sizeof (un.info));
2244 2226 siginfo_32tok(&un32.info, (k_siginfo_t *)&un.info);
2245 2227 error = pr_setsig(pnp, &un.info);
2246 2228 prunlock(pnp);
2247 2229 if (un32.info.si_signo == SIGKILL && error == 0)
2248 2230 pr_wait_die(pnp);
2249 2231 }
2250 2232 break;
2251 2233
2252 2234 case PIOCKILL: /* send signal */
2253 2235 error = pr_kill(pnp, un32.signo, cr);
2254 2236 prunlock(pnp);
2255 2237 if (un32.signo == SIGKILL && error == 0)
2256 2238 pr_wait_die(pnp);
2257 2239 break;
2258 2240
2259 2241 case PIOCUNKILL: /* delete a signal */
2260 2242 error = pr_unkill(pnp, un32.signo);
2261 2243 prunlock(pnp);
2262 2244 break;
2263 2245
2264 2246 case PIOCNICE: /* set nice priority */
2265 2247 error = pr_nice(p, un32.nice, cr);
2266 2248 prunlock(pnp);
2267 2249 break;
2268 2250
2269 2251 case PIOCGENTRY: /* get syscall entry bit mask */
2270 2252 case PIOCGEXIT: /* get syscall exit bit mask */
2271 2253 up = PTOU(p);
2272 2254 if (cmd == PIOCGENTRY) {
2273 2255 prassignset(&un32.prmask, &up->u_entrymask);
2274 2256 } else {
2275 2257 prassignset(&un32.prmask, &up->u_exitmask);
2276 2258 }
2277 2259 prunlock(pnp);
2278 2260 if (copyout(&un32.prmask, cmaddr, sizeof (un32.prmask)))
2279 2261 error = EFAULT;
2280 2262 break;
2281 2263
2282 2264 case PIOCSENTRY: /* set syscall entry bit mask */
2283 2265 case PIOCSEXIT: /* set syscall exit bit mask */
2284 2266 pr_setentryexit(p, &un32.prmask, cmd == PIOCSENTRY);
2285 2267 prunlock(pnp);
2286 2268 break;
2287 2269
2288 2270 case PIOCSRLC: /* obsolete: set running on last /proc close */
2289 2271 error = pr_set(p, prmapsetflags(PR_RLC));
2290 2272 prunlock(pnp);
2291 2273 break;
2292 2274
2293 2275 case PIOCRRLC: /* obsolete: reset run-on-last-close flag */
2294 2276 error = pr_unset(p, prmapsetflags(PR_RLC));
2295 2277 prunlock(pnp);
2296 2278 break;
2297 2279
2298 2280 case PIOCSFORK: /* obsolete: set inherit-on-fork flag */
2299 2281 error = pr_set(p, prmapsetflags(PR_FORK));
2300 2282 prunlock(pnp);
2301 2283 break;
2302 2284
2303 2285 case PIOCRFORK: /* obsolete: reset inherit-on-fork flag */
2304 2286 error = pr_unset(p, prmapsetflags(PR_FORK));
2305 2287 prunlock(pnp);
2306 2288 break;
2307 2289
2308 2290 case PIOCSET: /* set process flags */
2309 2291 error = pr_set(p, prmapsetflags((long)un32.flags));
2310 2292 prunlock(pnp);
2311 2293 break;
2312 2294
2313 2295 case PIOCRESET: /* reset process flags */
2314 2296 error = pr_unset(p, prmapsetflags((long)un32.flags));
2315 2297 prunlock(pnp);
2316 2298 break;
2317 2299
2318 2300 case PIOCGREG: /* get general registers */
2319 2301 if (PROCESS_NOT_32BIT(p))
2320 2302 error = EOVERFLOW;
2321 2303 else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
2322 2304 bzero(un32.regs, sizeof (un32.regs));
2323 2305 else {
2324 2306 /* drop p_lock while touching the lwp's stack */
2325 2307 mutex_exit(&p->p_lock);
2326 2308 prgetprregs32(lwp, un32.regs);
2327 2309 mutex_enter(&p->p_lock);
2328 2310 }
2329 2311 prunlock(pnp);
2330 2312 if (error == 0 &&
2331 2313 copyout(un32.regs, cmaddr, sizeof (un32.regs)))
2332 2314 error = EFAULT;
2333 2315 break;
2334 2316
2335 2317 case PIOCSREG: /* set general registers */
2336 2318 if (PROCESS_NOT_32BIT(p))
2337 2319 error = EOVERFLOW;
2338 2320 else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2339 2321 error = EBUSY;
2340 2322 else {
2341 2323 /* drop p_lock while touching the lwp's stack */
2342 2324 mutex_exit(&p->p_lock);
2343 2325 prgregset_32ton(lwp, un32.regs, un.regs);
2344 2326 prsetprregs(lwp, un.regs, 0);
2345 2327 mutex_enter(&p->p_lock);
2346 2328 }
2347 2329 prunlock(pnp);
2348 2330 break;
2349 2331
2350 2332 case PIOCGFPREG: /* get floating-point registers */
2351 2333 if (!prhasfp())
2352 2334 error = EINVAL; /* No FP support */
2353 2335 else if (PROCESS_NOT_32BIT(p))
2354 2336 error = EOVERFLOW;
2355 2337 else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
2356 2338 bzero(&un32.fpregs, sizeof (un32.fpregs));
2357 2339 else {
2358 2340 /* drop p_lock while touching the lwp's stack */
2359 2341 mutex_exit(&p->p_lock);
2360 2342 prgetprfpregs32(lwp, &un32.fpregs);
2361 2343 mutex_enter(&p->p_lock);
2362 2344 }
2363 2345 prunlock(pnp);
2364 2346 if (error == 0 &&
2365 2347 copyout(&un32.fpregs, cmaddr, sizeof (un32.fpregs)))
2366 2348 error = EFAULT;
2367 2349 break;
2368 2350
2369 2351 case PIOCSFPREG: /* set floating-point registers */
2370 2352 if (!prhasfp())
2371 2353 error = EINVAL; /* No FP support */
2372 2354 else if (PROCESS_NOT_32BIT(p))
2373 2355 error = EOVERFLOW;
2374 2356 else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2375 2357 error = EBUSY;
2376 2358 else {
|
↓ open down ↓ |
406 lines elided |
↑ open up ↑ |
2377 2359 /* drop p_lock while touching the lwp's stack */
2378 2360 mutex_exit(&p->p_lock);
2379 2361 prsetprfpregs32(lwp, &un32.fpregs);
2380 2362 mutex_enter(&p->p_lock);
2381 2363 }
2382 2364 prunlock(pnp);
2383 2365 break;
2384 2366
2385 2367 case PIOCGXREGSIZE: /* get the size of the extra registers */
2386 2368 {
2387 - int xregsize;
2388 -
2389 2369 if (prhasx(p)) {
2370 + size_t xregsize;
2371 + int abisize;
2372 +
2390 2373 xregsize = prgetprxregsize(p);
2391 2374 prunlock(pnp);
2392 - if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
2375 + if (xregsize > INT_MAX) {
2376 + error = EOVERFLOW;
2377 + break;
2378 + }
2379 +
2380 + abisize = (int)xregsize;
2381 + if (copyout(&abisize, cmaddr, sizeof (abisize)))
2393 2382 error = EFAULT;
2394 2383 } else {
2395 2384 prunlock(pnp);
2396 2385 error = EINVAL; /* No extra register support */
2397 2386 }
2398 2387 break;
2399 2388 }
2400 2389
2401 2390 case PIOCGXREG: /* get extra registers */
2402 2391 if (PROCESS_NOT_32BIT(p))
2403 2392 error = EOVERFLOW;
2404 2393 else if (!prhasx(p))
2405 2394 error = EINVAL; /* No extra register support */
2406 2395 else {
2407 2396 bzero(thing, thingsize);
2408 2397 if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
2409 2398 /* drop p_lock to touch the stack */
2410 2399 mutex_exit(&p->p_lock);
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
2411 2400 prgetprxregs(lwp, thing);
2412 2401 mutex_enter(&p->p_lock);
2413 2402 }
2414 2403 }
2415 2404 prunlock(pnp);
2416 2405 if (error == 0 &&
2417 2406 copyout(thing, cmaddr, thingsize))
2418 2407 error = EFAULT;
2419 2408 if (thing) {
2420 2409 kmem_free(thing, thingsize);
2421 - thing = NULL;
2422 - }
2423 - break;
2424 -
2425 - case PIOCSXREG: /* set extra registers */
2426 - if (PROCESS_NOT_32BIT(p))
2427 - error = EOVERFLOW;
2428 - else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2429 - error = EBUSY;
2430 - else if (!prhasx(p))
2431 - error = EINVAL; /* No extra register support */
2432 - else if (thing) {
2433 - /* drop p_lock while touching the lwp's stack */
2434 - mutex_exit(&p->p_lock);
2435 - prsetprxregs(lwp, thing);
2436 - mutex_enter(&p->p_lock);
2437 - }
2438 - prunlock(pnp);
2439 - if (thing) {
2440 - kmem_free(thing, thingsize);
2441 2410 thing = NULL;
2442 2411 }
2443 2412 break;
2444 2413
2445 2414 case PIOCSTATUS: /* get process/lwp status */
2446 2415 if (PROCESS_NOT_32BIT(p)) {
2447 2416 prunlock(pnp);
2448 2417 error = EOVERFLOW;
2449 2418 break;
2450 2419 }
2451 2420 oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
2452 2421 prunlock(pnp);
2453 2422 if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
2454 2423 error = EFAULT;
2455 2424 break;
2456 2425
2457 2426 case PIOCLSTATUS: /* get status for process & all lwps */
2458 2427 {
2459 2428 int Nlwp;
2460 2429 int nlwp;
2461 2430 prstatus32_t *Bprsp;
2462 2431 prstatus32_t *prsp;
2463 2432
2464 2433 if (PROCESS_NOT_32BIT(p)) {
2465 2434 prunlock(pnp);
2466 2435 if (thing) {
2467 2436 kmem_free(thing, thingsize);
2468 2437 thing = NULL;
2469 2438 }
2470 2439 error = EOVERFLOW;
2471 2440 break;
2472 2441 }
2473 2442
2474 2443 nlwp = Nlwp = p->p_lwpcnt;
2475 2444
2476 2445 if (thing && thingsize != (Nlwp+1) * sizeof (prstatus32_t)) {
2477 2446 kmem_free(thing, thingsize);
2478 2447 thing = NULL;
2479 2448 }
2480 2449 if (thing == NULL) {
2481 2450 thingsize = (Nlwp+1) * sizeof (prstatus32_t);
2482 2451 thing = kmem_alloc(thingsize, KM_NOSLEEP);
2483 2452 }
2484 2453 if (thing == NULL) {
2485 2454 prunlock(pnp);
2486 2455 goto startover;
2487 2456 }
2488 2457
2489 2458 Bprsp = (prstatus32_t *)thing;
2490 2459 thing = NULL;
2491 2460 prsp = Bprsp;
2492 2461 oprgetstatus32(t, prsp, VTOZONE(vp));
2493 2462 t = p->p_tlist;
2494 2463 do {
2495 2464 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2496 2465 ASSERT(nlwp > 0);
2497 2466 --nlwp;
2498 2467 oprgetstatus32(t, ++prsp, VTOZONE(vp));
2499 2468 } while ((t = t->t_forw) != p->p_tlist);
2500 2469 ASSERT(nlwp == 0);
2501 2470 prunlock(pnp);
2502 2471 if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus32_t)))
2503 2472 error = EFAULT;
2504 2473
2505 2474 kmem_free(Bprsp, (Nlwp + 1) * sizeof (prstatus32_t));
2506 2475 break;
2507 2476 }
2508 2477
2509 2478 case PIOCPSINFO: /* get ps(1) information */
2510 2479 {
2511 2480 prpsinfo32_t *psp = &un32.prps;
2512 2481
2513 2482 oprgetpsinfo32(p, psp,
2514 2483 (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
2515 2484
2516 2485 prunlock(pnp);
2517 2486 if (copyout(&un32.prps, cmaddr, sizeof (un32.prps)))
2518 2487 error = EFAULT;
2519 2488 break;
2520 2489 }
2521 2490
2522 2491 case PIOCMAXSIG: /* get maximum signal number */
2523 2492 {
2524 2493 int n = nsig-1;
2525 2494
2526 2495 prunlock(pnp);
2527 2496 if (copyout(&n, cmaddr, sizeof (int)))
2528 2497 error = EFAULT;
2529 2498 break;
2530 2499 }
2531 2500
2532 2501 case PIOCACTION: /* get signal action structures */
2533 2502 {
2534 2503 uint_t sig;
2535 2504 struct sigaction32 *sap = thing;
2536 2505
2537 2506 if (PROCESS_NOT_32BIT(p))
2538 2507 error = EOVERFLOW;
2539 2508 else {
2540 2509 up = PTOU(p);
2541 2510 for (sig = 1; sig < nsig; sig++)
2542 2511 prgetaction32(p, up, sig, &sap[sig-1]);
2543 2512 }
2544 2513 prunlock(pnp);
2545 2514 if (error == 0 &&
2546 2515 copyout(sap, cmaddr, (nsig-1)*sizeof (struct sigaction32)))
2547 2516 error = EFAULT;
2548 2517 kmem_free(sap, (nsig-1)*sizeof (struct sigaction32));
2549 2518 thing = NULL;
2550 2519 break;
2551 2520 }
2552 2521
2553 2522 case PIOCGHOLD: /* get signal-hold mask */
2554 2523 prgethold(t, &un32.holdmask);
2555 2524 prunlock(pnp);
2556 2525 if (copyout(&un32.holdmask, cmaddr, sizeof (un32.holdmask)))
2557 2526 error = EFAULT;
2558 2527 break;
2559 2528
2560 2529 case PIOCSHOLD: /* set signal-hold mask */
2561 2530 pr_sethold(pnp, &un32.holdmask);
2562 2531 prunlock(pnp);
2563 2532 break;
2564 2533
2565 2534 case PIOCNMAP: /* get number of memory mappings */
2566 2535 {
2567 2536 uint_t n;
2568 2537 struct as *as = p->p_as;
2569 2538
2570 2539 if ((p->p_flag & SSYS) || as == &kas)
2571 2540 n = 0;
2572 2541 else {
2573 2542 mutex_exit(&p->p_lock);
2574 2543 AS_LOCK_ENTER(as, RW_WRITER);
2575 2544 n = prnsegs(as, 0);
2576 2545 AS_LOCK_EXIT(as);
2577 2546 mutex_enter(&p->p_lock);
2578 2547 }
2579 2548 prunlock(pnp);
2580 2549 if (copyout(&n, cmaddr, sizeof (uint_t)))
2581 2550 error = EFAULT;
2582 2551 break;
2583 2552 }
2584 2553
2585 2554 case PIOCMAP: /* get memory map information */
2586 2555 {
2587 2556 list_t iolhead;
2588 2557 struct as *as = p->p_as;
2589 2558
2590 2559 if ((p->p_flag & SSYS) || as == &kas) {
2591 2560 error = 0;
2592 2561 prunlock(pnp);
2593 2562 } else if (PROCESS_NOT_32BIT(p)) {
2594 2563 error = EOVERFLOW;
2595 2564 prunlock(pnp);
2596 2565 } else {
2597 2566 mutex_exit(&p->p_lock);
2598 2567 AS_LOCK_ENTER(as, RW_WRITER);
2599 2568 error = oprgetmap32(p, &iolhead);
2600 2569 AS_LOCK_EXIT(as);
2601 2570 mutex_enter(&p->p_lock);
2602 2571 prunlock(pnp);
2603 2572
2604 2573 error = pr_iol_copyout_and_free(&iolhead,
2605 2574 &cmaddr, error);
2606 2575 }
2607 2576 /*
2608 2577 * The procfs PIOCMAP ioctl returns an all-zero buffer
2609 2578 * to indicate the end of the prmap[] array.
2610 2579 * Append it to whatever has already been copied out.
2611 2580 */
2612 2581 bzero(&un32.prmap, sizeof (un32.prmap));
2613 2582 if (!error &&
2614 2583 copyout(&un32.prmap, cmaddr, sizeof (un32.prmap)))
2615 2584 error = EFAULT;
2616 2585 break;
2617 2586 }
2618 2587
2619 2588 case PIOCGFAULT: /* get mask of traced faults */
2620 2589 prassignset(&un32.fltmask, &p->p_fltmask);
2621 2590 prunlock(pnp);
2622 2591 if (copyout(&un32.fltmask, cmaddr, sizeof (un32.fltmask)))
2623 2592 error = EFAULT;
2624 2593 break;
2625 2594
2626 2595 case PIOCSFAULT: /* set mask of traced faults */
2627 2596 pr_setfault(p, &un32.fltmask);
2628 2597 prunlock(pnp);
2629 2598 break;
2630 2599
2631 2600 case PIOCCFAULT: /* clear current fault */
2632 2601 lwp->lwp_curflt = 0;
2633 2602 prunlock(pnp);
2634 2603 break;
2635 2604
2636 2605 case PIOCCRED: /* get process credentials */
2637 2606 {
2638 2607 cred_t *cp;
2639 2608
2640 2609 mutex_enter(&p->p_crlock);
2641 2610 cp = p->p_cred;
2642 2611 un32.prcred.pr_euid = crgetuid(cp);
2643 2612 un32.prcred.pr_ruid = crgetruid(cp);
2644 2613 un32.prcred.pr_suid = crgetsuid(cp);
2645 2614 un32.prcred.pr_egid = crgetgid(cp);
2646 2615 un32.prcred.pr_rgid = crgetrgid(cp);
2647 2616 un32.prcred.pr_sgid = crgetsgid(cp);
2648 2617 un32.prcred.pr_ngroups = crgetngroups(cp);
2649 2618 mutex_exit(&p->p_crlock);
2650 2619
2651 2620 prunlock(pnp);
2652 2621 if (copyout(&un32.prcred, cmaddr, sizeof (un32.prcred)))
2653 2622 error = EFAULT;
2654 2623 break;
2655 2624 }
2656 2625
2657 2626 case PIOCGROUPS: /* get supplementary groups */
2658 2627 {
2659 2628 cred_t *cp;
2660 2629
2661 2630 mutex_enter(&p->p_crlock);
2662 2631 cp = p->p_cred;
2663 2632 crhold(cp);
2664 2633 mutex_exit(&p->p_crlock);
2665 2634
2666 2635 prunlock(pnp);
2667 2636 if (copyout(crgetgroups(cp), cmaddr,
2668 2637 MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
2669 2638 error = EFAULT;
2670 2639 crfree(cp);
2671 2640 break;
2672 2641 }
2673 2642
2674 2643 case PIOCUSAGE: /* get usage info */
2675 2644 {
2676 2645 /*
2677 2646 * For an lwp file descriptor, return just the lwp usage.
2678 2647 * For a process file descriptor, return total usage,
2679 2648 * all current lwps plus all defunct lwps.
2680 2649 */
2681 2650 prhusage_t *pup = &un32.prhusage;
2682 2651 prusage32_t *upup;
2683 2652
2684 2653 bzero(pup, sizeof (*pup));
2685 2654 pup->pr_tstamp = gethrtime();
2686 2655
2687 2656 if (pnp->pr_type == PR_LWPIDFILE) {
2688 2657 t = pcp->prc_thread;
2689 2658 if (t != NULL)
2690 2659 prgetusage(t, pup);
2691 2660 else
2692 2661 error = ENOENT;
2693 2662 } else {
2694 2663 pup->pr_count = p->p_defunct;
2695 2664 pup->pr_create = p->p_mstart;
2696 2665 pup->pr_term = p->p_mterm;
2697 2666
2698 2667 pup->pr_rtime = p->p_mlreal;
2699 2668 pup->pr_utime = p->p_acct[LMS_USER];
2700 2669 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2701 2670 pup->pr_ttime = p->p_acct[LMS_TRAP];
2702 2671 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2703 2672 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2704 2673 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2705 2674 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2706 2675 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2707 2676 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2708 2677 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2709 2678
2710 2679 pup->pr_minf = p->p_ru.minflt;
2711 2680 pup->pr_majf = p->p_ru.majflt;
2712 2681 pup->pr_nswap = p->p_ru.nswap;
2713 2682 pup->pr_inblk = p->p_ru.inblock;
2714 2683 pup->pr_oublk = p->p_ru.oublock;
2715 2684 pup->pr_msnd = p->p_ru.msgsnd;
2716 2685 pup->pr_mrcv = p->p_ru.msgrcv;
2717 2686 pup->pr_sigs = p->p_ru.nsignals;
2718 2687 pup->pr_vctx = p->p_ru.nvcsw;
2719 2688 pup->pr_ictx = p->p_ru.nivcsw;
2720 2689 pup->pr_sysc = p->p_ru.sysc;
2721 2690 pup->pr_ioch = p->p_ru.ioch;
2722 2691
2723 2692 /*
2724 2693 * Add the usage information for each active lwp.
2725 2694 */
2726 2695 if ((t = p->p_tlist) != NULL &&
2727 2696 !(pcp->prc_flags & PRC_DESTROY)) {
2728 2697 do {
2729 2698 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2730 2699 pup->pr_count++;
2731 2700 praddusage(t, pup);
2732 2701 } while ((t = t->t_forw) != p->p_tlist);
2733 2702 }
2734 2703 }
2735 2704
2736 2705 prunlock(pnp);
2737 2706
2738 2707 upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2739 2708 prcvtusage32(pup, upup);
2740 2709 if (copyout(upup, cmaddr, sizeof (*upup)))
2741 2710 error = EFAULT;
2742 2711 kmem_free(upup, sizeof (*upup));
2743 2712
2744 2713 break;
2745 2714 }
2746 2715
2747 2716 case PIOCLUSAGE: /* get detailed usage info */
2748 2717 {
2749 2718 int Nlwp;
2750 2719 int nlwp;
2751 2720 prusage32_t *upup;
2752 2721 prusage32_t *Bupup;
2753 2722 prhusage_t *pup;
2754 2723 hrtime_t curtime;
2755 2724
2756 2725 nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
2757 2726
2758 2727 if (thing && thingsize !=
2759 2728 sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage32_t)) {
2760 2729 kmem_free(thing, thingsize);
2761 2730 thing = NULL;
2762 2731 }
2763 2732 if (thing == NULL) {
2764 2733 thingsize = sizeof (prhusage_t) +
2765 2734 (Nlwp+1) * sizeof (prusage32_t);
2766 2735 thing = kmem_alloc(thingsize, KM_NOSLEEP);
2767 2736 }
2768 2737 if (thing == NULL) {
2769 2738 prunlock(pnp);
2770 2739 goto startover;
2771 2740 }
2772 2741
2773 2742 pup = (prhusage_t *)thing;
2774 2743 upup = Bupup = (prusage32_t *)(pup + 1);
2775 2744
2776 2745 ASSERT(p == pcp->prc_proc);
2777 2746
2778 2747 curtime = gethrtime();
2779 2748
2780 2749 /*
2781 2750 * First the summation over defunct lwps.
2782 2751 */
2783 2752 bzero(pup, sizeof (*pup));
2784 2753 pup->pr_count = p->p_defunct;
2785 2754 pup->pr_tstamp = curtime;
2786 2755 pup->pr_create = p->p_mstart;
2787 2756 pup->pr_term = p->p_mterm;
2788 2757
2789 2758 pup->pr_rtime = p->p_mlreal;
2790 2759 pup->pr_utime = p->p_acct[LMS_USER];
2791 2760 pup->pr_stime = p->p_acct[LMS_SYSTEM];
2792 2761 pup->pr_ttime = p->p_acct[LMS_TRAP];
2793 2762 pup->pr_tftime = p->p_acct[LMS_TFAULT];
2794 2763 pup->pr_dftime = p->p_acct[LMS_DFAULT];
2795 2764 pup->pr_kftime = p->p_acct[LMS_KFAULT];
2796 2765 pup->pr_ltime = p->p_acct[LMS_USER_LOCK];
2797 2766 pup->pr_slptime = p->p_acct[LMS_SLEEP];
2798 2767 pup->pr_wtime = p->p_acct[LMS_WAIT_CPU];
2799 2768 pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2800 2769
2801 2770 pup->pr_minf = p->p_ru.minflt;
2802 2771 pup->pr_majf = p->p_ru.majflt;
2803 2772 pup->pr_nswap = p->p_ru.nswap;
2804 2773 pup->pr_inblk = p->p_ru.inblock;
2805 2774 pup->pr_oublk = p->p_ru.oublock;
2806 2775 pup->pr_msnd = p->p_ru.msgsnd;
2807 2776 pup->pr_mrcv = p->p_ru.msgrcv;
2808 2777 pup->pr_sigs = p->p_ru.nsignals;
2809 2778 pup->pr_vctx = p->p_ru.nvcsw;
2810 2779 pup->pr_ictx = p->p_ru.nivcsw;
2811 2780 pup->pr_sysc = p->p_ru.sysc;
2812 2781 pup->pr_ioch = p->p_ru.ioch;
2813 2782
2814 2783 prcvtusage32(pup, upup);
2815 2784
2816 2785 /*
2817 2786 * Fill one prusage struct for each active lwp.
2818 2787 */
2819 2788 if ((t = p->p_tlist) != NULL &&
2820 2789 !(pcp->prc_flags & PRC_DESTROY)) {
2821 2790 do {
2822 2791 ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2823 2792 ASSERT(nlwp > 0);
2824 2793 --nlwp;
2825 2794 upup++;
2826 2795 prgetusage(t, pup);
2827 2796 prcvtusage32(pup, upup);
2828 2797 } while ((t = t->t_forw) != p->p_tlist);
2829 2798 }
2830 2799 ASSERT(nlwp == 0);
2831 2800
2832 2801 prunlock(pnp);
2833 2802 if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage32_t)))
2834 2803 error = EFAULT;
2835 2804 kmem_free(thing, thingsize);
2836 2805 thing = NULL;
2837 2806 break;
2838 2807 }
2839 2808
2840 2809 case PIOCNAUXV: /* get number of aux vector entries */
2841 2810 {
2842 2811 int n = __KERN_NAUXV_IMPL;
2843 2812
2844 2813 prunlock(pnp);
2845 2814 if (copyout(&n, cmaddr, sizeof (int)))
2846 2815 error = EFAULT;
2847 2816 break;
2848 2817 }
2849 2818
2850 2819 case PIOCAUXV: /* get aux vector (see sys/auxv.h) */
2851 2820 {
2852 2821 int i;
2853 2822
2854 2823 if (PROCESS_NOT_32BIT(p)) {
2855 2824 prunlock(pnp);
2856 2825 error = EOVERFLOW;
2857 2826 } else {
2858 2827 up = PTOU(p);
2859 2828 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2860 2829 un32.auxv[i].a_type = up->u_auxv[i].a_type;
2861 2830 un32.auxv[i].a_un.a_val =
2862 2831 (int32_t)up->u_auxv[i].a_un.a_val;
2863 2832 }
2864 2833 prunlock(pnp);
2865 2834 if (copyout(un32.auxv, cmaddr,
2866 2835 __KERN_NAUXV_IMPL * sizeof (auxv32_t)))
2867 2836 error = EFAULT;
2868 2837 }
2869 2838 break;
2870 2839 }
2871 2840
2872 2841 #if defined(__i386_COMPAT)
2873 2842 case PIOCNLDT: /* get number of LDT entries */
2874 2843 {
2875 2844 int n;
2876 2845
2877 2846 mutex_exit(&p->p_lock);
2878 2847 mutex_enter(&p->p_ldtlock);
2879 2848 n = prnldt(p);
2880 2849 mutex_exit(&p->p_ldtlock);
2881 2850 mutex_enter(&p->p_lock);
2882 2851 prunlock(pnp);
2883 2852 if (copyout(&n, cmaddr, sizeof (n)))
2884 2853 error = EFAULT;
2885 2854 break;
2886 2855 }
2887 2856
2888 2857 case PIOCLDT: /* get LDT entries */
2889 2858 {
2890 2859 struct ssd *ssd;
2891 2860 int n;
2892 2861
2893 2862 mutex_exit(&p->p_lock);
2894 2863 mutex_enter(&p->p_ldtlock);
2895 2864 n = prnldt(p);
2896 2865
2897 2866 if (thing && thingsize != (n+1) * sizeof (*ssd)) {
2898 2867 kmem_free(thing, thingsize);
2899 2868 thing = NULL;
2900 2869 }
2901 2870 if (thing == NULL) {
2902 2871 thingsize = (n+1) * sizeof (*ssd);
2903 2872 thing = kmem_alloc(thingsize, KM_NOSLEEP);
2904 2873 }
2905 2874 if (thing == NULL) {
2906 2875 mutex_exit(&p->p_ldtlock);
2907 2876 mutex_enter(&p->p_lock);
2908 2877 prunlock(pnp);
2909 2878 goto startover;
2910 2879 }
2911 2880
2912 2881 ssd = thing;
2913 2882 thing = NULL;
2914 2883 if (n != 0)
2915 2884 prgetldt(p, ssd);
2916 2885 mutex_exit(&p->p_ldtlock);
2917 2886 mutex_enter(&p->p_lock);
2918 2887 prunlock(pnp);
2919 2888
2920 2889 /* mark the end of the list with a null entry */
2921 2890 bzero(&ssd[n], sizeof (*ssd));
2922 2891 if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
2923 2892 error = EFAULT;
2924 2893 kmem_free(ssd, (n+1) * sizeof (*ssd));
2925 2894 break;
2926 2895 }
2927 2896 #endif /* __i386_COMPAT */
2928 2897
2929 2898 #if defined(__sparc)
2930 2899 case PIOCGWIN: /* get gwindows_t (see sys/reg.h) */
2931 2900 {
2932 2901 gwindows32_t *gwp = thing;
2933 2902
2934 2903 if (PROCESS_NOT_32BIT(p)) {
2935 2904 prunlock(pnp);
2936 2905 error = EOVERFLOW;
2937 2906 } else {
2938 2907 /* drop p->p_lock while touching the stack */
2939 2908 mutex_exit(&p->p_lock);
2940 2909 bzero(gwp, sizeof (*gwp));
2941 2910 prgetwindows32(lwp, gwp);
2942 2911 mutex_enter(&p->p_lock);
2943 2912 prunlock(pnp);
2944 2913 if (copyout(gwp, cmaddr, sizeof (*gwp)))
2945 2914 error = EFAULT;
2946 2915 }
2947 2916 kmem_free(gwp, sizeof (*gwp));
2948 2917 thing = NULL;
2949 2918 break;
2950 2919 }
2951 2920 #endif /* __sparc */
2952 2921
2953 2922 default:
2954 2923 prunlock(pnp);
2955 2924 error = EINVAL;
2956 2925 break;
2957 2926
2958 2927 }
2959 2928
2960 2929 ASSERT(thing == NULL);
2961 2930 ASSERT(xpnp == NULL);
2962 2931 return (error);
2963 2932 }
2964 2933 #endif /* _SYSCALL32_IMPL */
2965 2934
2966 2935 /*
2967 2936 * Distinguish "writeable" ioctl requests from others.
2968 2937 */
2969 2938 static int
2970 2939 isprwrioctl(int cmd)
2971 2940 {
2972 2941 switch (cmd) {
2973 2942 case PIOCSTOP:
2974 2943 case PIOCRUN:
2975 2944 case PIOCSTRACE:
2976 2945 case PIOCSSIG:
2977 2946 case PIOCKILL:
2978 2947 case PIOCUNKILL:
2979 2948 case PIOCNICE:
2980 2949 case PIOCSENTRY:
2981 2950 case PIOCSEXIT:
2982 2951 case PIOCSRLC:
2983 2952 case PIOCRRLC:
2984 2953 case PIOCSREG:
2985 2954 case PIOCSFPREG:
2986 2955 case PIOCSXREG:
2987 2956 case PIOCSHOLD:
2988 2957 case PIOCSFAULT:
2989 2958 case PIOCCFAULT:
2990 2959 case PIOCSFORK:
2991 2960 case PIOCRFORK:
2992 2961 case PIOCSET:
2993 2962 case PIOCRESET:
2994 2963 return (1);
2995 2964 }
2996 2965 return (0);
2997 2966 }
2998 2967
2999 2968 /*
3000 2969 * Map the ioctl() interface run flags to the new interface run flags.
3001 2970 */
3002 2971 static ulong_t
3003 2972 prmaprunflags(long flags)
3004 2973 {
3005 2974 ulong_t newflags = 0;
3006 2975
3007 2976 if (flags & PRCSIG)
3008 2977 newflags |= 0x01;
3009 2978 if (flags & PRCFAULT)
3010 2979 newflags |= 0x02;
3011 2980 if (flags & PRSTEP)
3012 2981 newflags |= 0x04;
3013 2982 if (flags & PRSABORT)
3014 2983 newflags |= 0x08;
3015 2984 if (flags & PRSTOP)
3016 2985 newflags |= 0x10;
3017 2986 return (newflags);
3018 2987 }
3019 2988
3020 2989 /*
3021 2990 * Map the ioctl() interface settable mode flags to the new interface flags.
3022 2991 */
3023 2992 static long
3024 2993 prmapsetflags(long flags)
3025 2994 {
3026 2995 long newflags = 0;
3027 2996
3028 2997 #define ALLFLAGS \
3029 2998 (PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_PCOMPAT)
3030 2999
3031 3000 if (flags & ~ALLFLAGS)
3032 3001 newflags = 0xffff; /* forces EINVAL */
3033 3002 if (flags & PR_FORK)
3034 3003 newflags |= (0x00100000 | 0x08000000);
3035 3004 if (flags & PR_RLC)
3036 3005 newflags |= 0x00200000;
3037 3006 if (flags & PR_KLC)
3038 3007 newflags |= 0x00400000;
3039 3008 if (flags & PR_ASYNC)
3040 3009 newflags |= 0x00800000;
3041 3010 if (flags & PR_MSACCT)
3042 3011 newflags |= 0x01000000;
3043 3012 if (flags & PR_BPTADJ)
3044 3013 newflags |= 0x02000000;
3045 3014 if (flags & PR_PCOMPAT)
3046 3015 newflags |= 0x04000000;
3047 3016 return (newflags);
3048 3017 }
3049 3018
3050 3019 /*
3051 3020 * Apply PIOCRUN options specific to the ioctl() interface.
3052 3021 */
3053 3022 static void
3054 3023 prsetrun(kthread_t *t, prrun_t *prp)
3055 3024 {
3056 3025 proc_t *p = ttoproc(t);
3057 3026 klwp_t *lwp = ttolwp(t);
3058 3027 long flags = prp->pr_flags;
3059 3028 user_t *up = PTOU(p);
3060 3029
3061 3030 ASSERT(MUTEX_HELD(&p->p_lock));
3062 3031
3063 3032 if (flags & PRSHOLD) {
3064 3033 schedctl_finish_sigblock(t);
3065 3034 sigutok(&prp->pr_sighold, &t->t_hold);
3066 3035 t->t_sig_check = 1; /* so ISSIG will be done */
3067 3036 }
3068 3037 if (flags & PRSTRACE) {
3069 3038 prdelset(&prp->pr_trace, SIGKILL);
3070 3039 prassignset(&p->p_sigmask, &prp->pr_trace);
3071 3040 if (!sigisempty(&p->p_sigmask))
3072 3041 p->p_proc_flag |= P_PR_TRACE;
3073 3042 else if (prisempty(&p->p_fltmask)) {
3074 3043 if (up->u_systrap == 0)
3075 3044 p->p_proc_flag &= ~P_PR_TRACE;
3076 3045 }
3077 3046 }
3078 3047 if (flags & PRSFAULT) {
3079 3048 prassignset(&p->p_fltmask, &prp->pr_fault);
3080 3049 if (!prisempty(&p->p_fltmask))
3081 3050 p->p_proc_flag |= P_PR_TRACE;
3082 3051 else if (sigisempty(&p->p_sigmask)) {
3083 3052 if (up->u_systrap == 0)
3084 3053 p->p_proc_flag &= ~P_PR_TRACE;
3085 3054 }
3086 3055 }
3087 3056 /*
3088 3057 * prsvaddr() must be called before prstep() because
3089 3058 * stepping can depend on the current value of the PC.
3090 3059 * We drop p_lock while touching the lwp's registers (on stack).
3091 3060 */
3092 3061 if (flags & PRSVADDR) {
3093 3062 mutex_exit(&p->p_lock);
3094 3063 prsvaddr(lwp, prp->pr_vaddr);
3095 3064 mutex_enter(&p->p_lock);
3096 3065 }
3097 3066 }
3098 3067
3099 3068 /*
3100 3069 * Common code for PIOCOPENM
3101 3070 * Returns with the process unlocked.
3102 3071 */
3103 3072 static int
3104 3073 propenm(prnode_t *pnp, caddr_t cmaddr, caddr_t va, int *rvalp, cred_t *cr)
3105 3074 {
3106 3075 proc_t *p = pnp->pr_common->prc_proc;
3107 3076 struct as *as = p->p_as;
3108 3077 int error = 0;
3109 3078 struct seg *seg;
3110 3079 struct vnode *xvp;
3111 3080 int n;
3112 3081
3113 3082 /*
3114 3083 * By fiat, a system process has no address space.
3115 3084 */
3116 3085 if ((p->p_flag & SSYS) || as == &kas) {
3117 3086 error = EINVAL;
3118 3087 } else if (cmaddr) {
3119 3088 /*
3120 3089 * We drop p_lock before grabbing the address
3121 3090 * space lock in order to avoid a deadlock with
3122 3091 * the clock thread. The process will not
3123 3092 * disappear and its address space will not
3124 3093 * change because it is marked P_PR_LOCK.
3125 3094 */
3126 3095 mutex_exit(&p->p_lock);
3127 3096 AS_LOCK_ENTER(as, RW_READER);
3128 3097 seg = as_segat(as, va);
3129 3098 if (seg != NULL &&
3130 3099 seg->s_ops == &segvn_ops &&
3131 3100 SEGOP_GETVP(seg, va, &xvp) == 0 &&
3132 3101 xvp != NULL &&
3133 3102 xvp->v_type == VREG) {
3134 3103 VN_HOLD(xvp);
3135 3104 } else {
3136 3105 error = EINVAL;
3137 3106 }
3138 3107 AS_LOCK_EXIT(as);
3139 3108 mutex_enter(&p->p_lock);
3140 3109 } else if ((xvp = p->p_exec) == NULL) {
3141 3110 error = EINVAL;
3142 3111 } else {
3143 3112 VN_HOLD(xvp);
3144 3113 }
3145 3114
3146 3115 prunlock(pnp);
3147 3116
3148 3117 if (error == 0) {
3149 3118 if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
3150 3119 error = fassign(&xvp, FREAD, &n);
3151 3120 if (error) {
3152 3121 VN_RELE(xvp);
3153 3122 } else {
3154 3123 *rvalp = n;
3155 3124 }
3156 3125 }
3157 3126
3158 3127 return (error);
3159 3128 }
3160 3129
3161 3130 /*
3162 3131 * Return old version of process/lwp status.
3163 3132 * The u-block is mapped in by this routine and unmapped at the end.
3164 3133 */
3165 3134 void
3166 3135 oprgetstatus(kthread_t *t, prstatus_t *sp, zone_t *zp)
3167 3136 {
3168 3137 proc_t *p = ttoproc(t);
3169 3138 klwp_t *lwp = ttolwp(t);
3170 3139 int flags;
3171 3140 user_t *up;
3172 3141 ulong_t instr;
3173 3142
3174 3143 ASSERT(MUTEX_HELD(&p->p_lock));
3175 3144
3176 3145 up = PTOU(p);
3177 3146 bzero(sp, sizeof (*sp));
3178 3147 flags = 0;
3179 3148 if (t->t_state == TS_STOPPED) {
3180 3149 flags |= PR_STOPPED;
3181 3150 if ((t->t_schedflag & TS_PSTART) == 0)
3182 3151 flags |= PR_ISTOP;
3183 3152 } else if (VSTOPPED(t)) {
3184 3153 flags |= PR_STOPPED|PR_ISTOP;
3185 3154 }
3186 3155 if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
3187 3156 flags |= PR_DSTOP;
3188 3157 if (lwp->lwp_asleep)
3189 3158 flags |= PR_ASLEEP;
3190 3159 if (p->p_proc_flag & P_PR_FORK)
3191 3160 flags |= PR_FORK;
3192 3161 if (p->p_proc_flag & P_PR_RUNLCL)
3193 3162 flags |= PR_RLC;
3194 3163 if (p->p_proc_flag & P_PR_KILLCL)
3195 3164 flags |= PR_KLC;
3196 3165 if (p->p_proc_flag & P_PR_ASYNC)
3197 3166 flags |= PR_ASYNC;
3198 3167 if (p->p_proc_flag & P_PR_BPTADJ)
3199 3168 flags |= PR_BPTADJ;
3200 3169 if (p->p_proc_flag & P_PR_PTRACE)
3201 3170 flags |= PR_PCOMPAT;
3202 3171 if (t->t_proc_flag & TP_MSACCT)
3203 3172 flags |= PR_MSACCT;
3204 3173 sp->pr_flags = flags;
3205 3174 if (VSTOPPED(t)) {
3206 3175 sp->pr_why = PR_REQUESTED;
3207 3176 sp->pr_what = 0;
3208 3177 } else {
3209 3178 sp->pr_why = t->t_whystop;
3210 3179 sp->pr_what = t->t_whatstop;
3211 3180 }
3212 3181
3213 3182 if (t->t_whystop == PR_FAULTED)
3214 3183 bcopy(&lwp->lwp_siginfo,
3215 3184 &sp->pr_info, sizeof (k_siginfo_t));
3216 3185 else if (lwp->lwp_curinfo)
3217 3186 bcopy(&lwp->lwp_curinfo->sq_info,
3218 3187 &sp->pr_info, sizeof (k_siginfo_t));
3219 3188
3220 3189 if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
3221 3190 sp->pr_info.si_zoneid != zp->zone_id) {
3222 3191 sp->pr_info.si_pid = zp->zone_zsched->p_pid;
3223 3192 sp->pr_info.si_uid = 0;
3224 3193 sp->pr_info.si_ctid = -1;
3225 3194 sp->pr_info.si_zoneid = zp->zone_id;
3226 3195 }
3227 3196
3228 3197 sp->pr_cursig = lwp->lwp_cursig;
3229 3198 prassignset(&sp->pr_sigpend, &p->p_sig);
3230 3199 prassignset(&sp->pr_lwppend, &t->t_sig);
3231 3200 prgethold(t, &sp->pr_sighold);
3232 3201 sp->pr_altstack = lwp->lwp_sigaltstack;
3233 3202 prgetaction(p, up, lwp->lwp_cursig, &sp->pr_action);
3234 3203 sp->pr_pid = p->p_pid;
3235 3204 if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
3236 3205 (p->p_flag & SZONETOP)) {
3237 3206 ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
3238 3207 /*
3239 3208 * Inside local zones, fake zsched's pid as parent pids for
3240 3209 * processes which reference processes outside of the zone.
3241 3210 */
3242 3211 sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
3243 3212 } else {
3244 3213 sp->pr_ppid = p->p_ppid;
3245 3214 }
3246 3215 sp->pr_pgrp = p->p_pgrp;
3247 3216 sp->pr_sid = p->p_sessp->s_sid;
3248 3217 hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
3249 3218 hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
3250 3219 TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
3251 3220 TICK_TO_TIMESTRUC(p->p_cstime, &sp->pr_cstime);
3252 3221 (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
3253 3222 sizeof (sp->pr_clname) - 1);
3254 3223 sp->pr_who = t->t_tid;
3255 3224 sp->pr_nlwp = p->p_lwpcnt;
3256 3225 sp->pr_brkbase = p->p_brkbase;
3257 3226 sp->pr_brksize = p->p_brksize;
3258 3227 sp->pr_stkbase = prgetstackbase(p);
3259 3228 sp->pr_stksize = p->p_stksize;
3260 3229 sp->pr_oldcontext = (struct ucontext *)lwp->lwp_oldcontext;
3261 3230 sp->pr_processor = t->t_cpu->cpu_id;
3262 3231 sp->pr_bind = t->t_bind_cpu;
3263 3232
3264 3233 /*
3265 3234 * Fetch the current instruction, if not a system process.
3266 3235 * We don't attempt this unless the lwp is stopped.
3267 3236 */
3268 3237 if ((p->p_flag & SSYS) || p->p_as == &kas)
3269 3238 sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
3270 3239 else if (!(flags & PR_STOPPED))
3271 3240 sp->pr_flags |= PR_PCINVAL;
3272 3241 else if (!prfetchinstr(lwp, &instr))
3273 3242 sp->pr_flags |= PR_PCINVAL;
3274 3243 else
3275 3244 sp->pr_instr = instr;
3276 3245
3277 3246 /*
3278 3247 * Drop p_lock while touching the lwp's stack.
3279 3248 */
3280 3249 mutex_exit(&p->p_lock);
3281 3250 if (prisstep(lwp))
3282 3251 sp->pr_flags |= PR_STEP;
3283 3252 if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
3284 3253 int i;
3285 3254 auxv_t *auxp;
3286 3255
3287 3256 sp->pr_syscall = get_syscall_args(lwp,
3288 3257 (long *)sp->pr_sysarg, &i);
3289 3258 sp->pr_nsysarg = (short)i;
3290 3259 if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
3291 3260 sp->pr_sysarg[0] = 0;
3292 3261 sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
3293 3262 sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
3294 3263 for (i = 0, auxp = up->u_auxv;
3295 3264 i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
3296 3265 i++, auxp++) {
3297 3266 if (auxp->a_type == AT_SUN_EXECNAME) {
3298 3267 sp->pr_sysarg[0] =
3299 3268 (uintptr_t)auxp->a_un.a_ptr;
3300 3269 break;
3301 3270 }
3302 3271 }
3303 3272 }
3304 3273 }
3305 3274 if ((flags & PR_STOPPED) || t == curthread)
3306 3275 prgetprregs(lwp, sp->pr_reg);
3307 3276 mutex_enter(&p->p_lock);
3308 3277 }
3309 3278
3310 3279 /*
3311 3280 * Return old version of information used by ps(1).
3312 3281 */
3313 3282 void
3314 3283 oprgetpsinfo(proc_t *p, prpsinfo_t *psp, kthread_t *tp)
3315 3284 {
3316 3285 kthread_t *t;
3317 3286 char c, state;
3318 3287 user_t *up;
3319 3288 dev_t d;
3320 3289 uint64_t pct;
3321 3290 int retval, niceval;
3322 3291 cred_t *cred;
3323 3292 struct as *as;
3324 3293 hrtime_t hrutime, hrstime, cur_time;
3325 3294
3326 3295 ASSERT(MUTEX_HELD(&p->p_lock));
3327 3296
3328 3297 bzero(psp, sizeof (*psp));
3329 3298
3330 3299 if ((t = tp) == NULL)
3331 3300 t = prchoose(p); /* returns locked thread */
3332 3301 else
3333 3302 thread_lock(t);
3334 3303
3335 3304 /* kludge: map thread state enum into process state enum */
3336 3305
3337 3306 if (t == NULL) {
3338 3307 state = TS_ZOMB;
3339 3308 } else {
3340 3309 state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
3341 3310 thread_unlock(t);
3342 3311 }
3343 3312
3344 3313 switch (state) {
3345 3314 case TS_SLEEP: state = SSLEEP; break;
3346 3315 case TS_RUN: state = SRUN; break;
3347 3316 case TS_ONPROC: state = SONPROC; break;
3348 3317 case TS_ZOMB: state = SZOMB; break;
3349 3318 case TS_STOPPED: state = SSTOP; break;
3350 3319 default: state = 0; break;
3351 3320 }
3352 3321 switch (state) {
3353 3322 case SSLEEP: c = 'S'; break;
3354 3323 case SRUN: c = 'R'; break;
3355 3324 case SZOMB: c = 'Z'; break;
3356 3325 case SSTOP: c = 'T'; break;
3357 3326 case SIDL: c = 'I'; break;
3358 3327 case SONPROC: c = 'O'; break;
3359 3328 #ifdef SXBRK
3360 3329 case SXBRK: c = 'X'; break;
3361 3330 #endif
3362 3331 default: c = '?'; break;
3363 3332 }
3364 3333 psp->pr_state = state;
3365 3334 psp->pr_sname = c;
3366 3335 psp->pr_zomb = (state == SZOMB);
3367 3336 /*
3368 3337 * only export SSYS and SMSACCT; everything else is off-limits to
3369 3338 * userland apps.
3370 3339 */
3371 3340 psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
3372 3341
3373 3342 mutex_enter(&p->p_crlock);
3374 3343 cred = p->p_cred;
3375 3344 psp->pr_uid = crgetruid(cred);
3376 3345 psp->pr_gid = crgetrgid(cred);
3377 3346 psp->pr_euid = crgetuid(cred);
3378 3347 psp->pr_egid = crgetgid(cred);
3379 3348 mutex_exit(&p->p_crlock);
3380 3349
3381 3350 psp->pr_pid = p->p_pid;
3382 3351 if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
3383 3352 (p->p_flag & SZONETOP)) {
3384 3353 ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
3385 3354 /*
3386 3355 * Inside local zones, fake zsched's pid as parent pids for
3387 3356 * processes which reference processes outside of the zone.
3388 3357 */
3389 3358 psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
3390 3359 } else {
3391 3360 psp->pr_ppid = p->p_ppid;
3392 3361 }
3393 3362 psp->pr_pgrp = p->p_pgrp;
3394 3363 psp->pr_sid = p->p_sessp->s_sid;
3395 3364 psp->pr_addr = prgetpsaddr(p);
3396 3365 hrutime = mstate_aggr_state(p, LMS_USER);
3397 3366 hrstime = mstate_aggr_state(p, LMS_SYSTEM);
3398 3367 hrt2ts(hrutime + hrstime, &psp->pr_time);
3399 3368 TICK_TO_TIMESTRUC(p->p_cutime + p->p_cstime, &psp->pr_ctime);
3400 3369 switch (p->p_model) {
3401 3370 case DATAMODEL_ILP32:
3402 3371 psp->pr_dmodel = PR_MODEL_ILP32;
3403 3372 break;
3404 3373 case DATAMODEL_LP64:
3405 3374 psp->pr_dmodel = PR_MODEL_LP64;
3406 3375 break;
3407 3376 }
3408 3377 if (state == SZOMB || t == NULL) {
3409 3378 int wcode = p->p_wcode; /* must be atomic read */
3410 3379
3411 3380 if (wcode)
3412 3381 psp->pr_wstat = wstat(wcode, p->p_wdata);
3413 3382 psp->pr_lttydev = PRNODEV;
3414 3383 psp->pr_ottydev = (o_dev_t)PRNODEV;
3415 3384 psp->pr_size = 0;
3416 3385 psp->pr_rssize = 0;
3417 3386 psp->pr_pctmem = 0;
3418 3387 } else {
3419 3388 up = PTOU(p);
3420 3389 psp->pr_wchan = t->t_wchan;
3421 3390 psp->pr_pri = t->t_pri;
3422 3391 (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
3423 3392 sizeof (psp->pr_clname) - 1);
3424 3393 retval = CL_DONICE(t, NULL, 0, &niceval);
3425 3394 if (retval == 0) {
3426 3395 psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
3427 3396 psp->pr_nice = niceval + NZERO;
3428 3397 } else {
3429 3398 psp->pr_oldpri = 0;
3430 3399 psp->pr_nice = 0;
3431 3400 }
3432 3401 d = cttydev(p);
3433 3402 #ifdef sun
3434 3403 {
3435 3404 extern dev_t rwsconsdev, rconsdev, uconsdev;
3436 3405 /*
3437 3406 * If the controlling terminal is the real
3438 3407 * or workstation console device, map to what the
3439 3408 * user thinks is the console device. Handle case when
3440 3409 * rwsconsdev or rconsdev is set to NODEV for Starfire.
3441 3410 */
3442 3411 if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
3443 3412 d = uconsdev;
3444 3413 }
3445 3414 #endif
3446 3415 psp->pr_lttydev = (d == NODEV) ? PRNODEV : d;
3447 3416 psp->pr_ottydev = cmpdev(d);
3448 3417 psp->pr_start = up->u_start;
3449 3418 bcopy(up->u_comm, psp->pr_fname,
3450 3419 MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
3451 3420 bcopy(up->u_psargs, psp->pr_psargs,
3452 3421 MIN(PRARGSZ-1, PSARGSZ));
3453 3422 psp->pr_syscall = t->t_sysnum;
3454 3423 psp->pr_argc = up->u_argc;
3455 3424 psp->pr_argv = (char **)up->u_argv;
3456 3425 psp->pr_envp = (char **)up->u_envp;
3457 3426
3458 3427 /* compute %cpu for the lwp or process */
3459 3428 pct = 0;
3460 3429 if ((t = tp) == NULL)
3461 3430 t = p->p_tlist;
3462 3431 cur_time = gethrtime_unscaled();
3463 3432 do {
3464 3433 pct += cpu_update_pct(t, cur_time);
3465 3434 if (tp != NULL) /* just do the one lwp */
3466 3435 break;
3467 3436 } while ((t = t->t_forw) != p->p_tlist);
3468 3437
3469 3438 psp->pr_pctcpu = prgetpctcpu(pct);
3470 3439 psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
3471 3440 if (psp->pr_cpu > 99)
3472 3441 psp->pr_cpu = 99;
3473 3442
3474 3443 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3475 3444 psp->pr_size = 0;
3476 3445 psp->pr_rssize = 0;
3477 3446 psp->pr_pctmem = 0;
3478 3447 } else {
3479 3448 mutex_exit(&p->p_lock);
3480 3449 AS_LOCK_ENTER(as, RW_READER);
3481 3450 psp->pr_size = btopr(as->a_resvsize);
3482 3451 psp->pr_rssize = rm_asrss(as);
3483 3452 psp->pr_pctmem = rm_pctmemory(as);
3484 3453 AS_LOCK_EXIT(as);
3485 3454 mutex_enter(&p->p_lock);
3486 3455 }
3487 3456 }
3488 3457 psp->pr_bysize = ptob(psp->pr_size);
3489 3458 psp->pr_byrssize = ptob(psp->pr_rssize);
3490 3459 }
3491 3460
3492 3461 /*
3493 3462 * Return an array of structures with memory map information.
3494 3463 * We allocate here; the caller must deallocate.
3495 3464 * The caller is also responsible to append the zero-filled entry
3496 3465 * that terminates the PIOCMAP output buffer.
3497 3466 */
3498 3467 static int
3499 3468 oprgetmap(proc_t *p, list_t *iolhead)
3500 3469 {
3501 3470 struct as *as = p->p_as;
3502 3471 prmap_t *mp;
3503 3472 struct seg *seg;
3504 3473 struct seg *brkseg, *stkseg;
3505 3474 uint_t prot;
3506 3475
3507 3476 ASSERT(as != &kas && AS_WRITE_HELD(as));
3508 3477
3509 3478 /*
3510 3479 * Request an initial buffer size that doesn't waste memory
3511 3480 * if the address space has only a small number of segments.
3512 3481 */
3513 3482 pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
3514 3483
3515 3484 if ((seg = AS_SEGFIRST(as)) == NULL)
3516 3485 return (0);
3517 3486
3518 3487 brkseg = break_seg(p);
3519 3488 stkseg = as_segat(as, prgetstackbase(p));
3520 3489
3521 3490 do {
3522 3491 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3523 3492 caddr_t saddr, naddr;
3524 3493 void *tmp = NULL;
3525 3494
3526 3495 if ((seg->s_flags & S_HOLE) != 0) {
3527 3496 continue;
3528 3497 }
3529 3498
3530 3499 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3531 3500 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3532 3501 if (saddr == naddr)
3533 3502 continue;
3534 3503
3535 3504 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3536 3505
3537 3506 mp->pr_vaddr = saddr;
3538 3507 mp->pr_size = naddr - saddr;
3539 3508 mp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3540 3509 mp->pr_mflags = 0;
3541 3510 if (prot & PROT_READ)
3542 3511 mp->pr_mflags |= MA_READ;
3543 3512 if (prot & PROT_WRITE)
3544 3513 mp->pr_mflags |= MA_WRITE;
3545 3514 if (prot & PROT_EXEC)
3546 3515 mp->pr_mflags |= MA_EXEC;
3547 3516 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3548 3517 mp->pr_mflags |= MA_SHARED;
3549 3518 if (seg == brkseg)
3550 3519 mp->pr_mflags |= MA_BREAK;
3551 3520 else if (seg == stkseg)
3552 3521 mp->pr_mflags |= MA_STACK;
3553 3522 mp->pr_pagesize = PAGESIZE;
3554 3523 }
3555 3524 ASSERT(tmp == NULL);
3556 3525 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3557 3526
3558 3527 return (0);
3559 3528 }
3560 3529
3561 3530 #ifdef _SYSCALL32_IMPL
3562 3531 static int
3563 3532 oprgetmap32(proc_t *p, list_t *iolhead)
3564 3533 {
3565 3534 struct as *as = p->p_as;
3566 3535 ioc_prmap32_t *mp;
3567 3536 struct seg *seg;
3568 3537 struct seg *brkseg, *stkseg;
3569 3538 uint_t prot;
3570 3539
3571 3540 ASSERT(as != &kas && AS_WRITE_HELD(as));
3572 3541
3573 3542 /*
3574 3543 * Request an initial buffer size that doesn't waste memory
3575 3544 * if the address space has only a small number of segments.
3576 3545 */
3577 3546 pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
3578 3547
3579 3548 if ((seg = AS_SEGFIRST(as)) == NULL)
3580 3549 return (0);
3581 3550
3582 3551 brkseg = break_seg(p);
3583 3552 stkseg = as_segat(as, prgetstackbase(p));
3584 3553
3585 3554 do {
3586 3555 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3587 3556 caddr_t saddr, naddr;
3588 3557 void *tmp = NULL;
3589 3558
3590 3559 if ((seg->s_flags & S_HOLE) != 0) {
3591 3560 continue;
3592 3561 }
3593 3562
3594 3563 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3595 3564 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3596 3565 if (saddr == naddr)
3597 3566 continue;
3598 3567
3599 3568 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3600 3569
3601 3570 mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
3602 3571 mp->pr_size = (size32_t)(naddr - saddr);
3603 3572 mp->pr_off = (off32_t)SEGOP_GETOFFSET(seg, saddr);
3604 3573 mp->pr_mflags = 0;
3605 3574 if (prot & PROT_READ)
3606 3575 mp->pr_mflags |= MA_READ;
3607 3576 if (prot & PROT_WRITE)
3608 3577 mp->pr_mflags |= MA_WRITE;
3609 3578 if (prot & PROT_EXEC)
3610 3579 mp->pr_mflags |= MA_EXEC;
3611 3580 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3612 3581 mp->pr_mflags |= MA_SHARED;
3613 3582 if (seg == brkseg)
3614 3583 mp->pr_mflags |= MA_BREAK;
3615 3584 else if (seg == stkseg)
3616 3585 mp->pr_mflags |= MA_STACK;
3617 3586 mp->pr_pagesize = PAGESIZE;
3618 3587 }
3619 3588 ASSERT(tmp == NULL);
3620 3589 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3621 3590
3622 3591 return (0);
3623 3592 }
3624 3593 #endif /* _SYSCALL32_IMPL */
3625 3594
3626 3595 /*
3627 3596 * Return the size of the old /proc page data file.
3628 3597 */
3629 3598 size_t
3630 3599 oprpdsize(struct as *as)
3631 3600 {
3632 3601 struct seg *seg;
3633 3602 size_t size;
3634 3603
3635 3604 ASSERT(as != &kas && AS_WRITE_HELD(as));
3636 3605
3637 3606 if ((seg = AS_SEGFIRST(as)) == NULL)
3638 3607 return (0);
3639 3608
3640 3609 size = sizeof (prpageheader_t);
3641 3610 do {
3642 3611 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3643 3612 caddr_t saddr, naddr;
3644 3613 void *tmp = NULL;
3645 3614 size_t npage;
3646 3615
3647 3616 if ((seg->s_flags & S_HOLE) != 0) {
3648 3617 continue;
3649 3618 }
3650 3619
3651 3620 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3652 3621 (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3653 3622 if ((npage = (naddr - saddr) / PAGESIZE) != 0)
3654 3623 size += sizeof (prasmap_t) + roundlong(npage);
3655 3624 }
3656 3625 ASSERT(tmp == NULL);
3657 3626 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3658 3627
3659 3628 return (size);
3660 3629 }
3661 3630
3662 3631 #ifdef _SYSCALL32_IMPL
3663 3632 size_t
3664 3633 oprpdsize32(struct as *as)
3665 3634 {
3666 3635 struct seg *seg;
3667 3636 size_t size;
3668 3637
3669 3638 ASSERT(as != &kas && AS_WRITE_HELD(as));
3670 3639
3671 3640 if ((seg = AS_SEGFIRST(as)) == NULL)
3672 3641 return (0);
3673 3642
3674 3643 size = sizeof (ioc_prpageheader32_t);
3675 3644 do {
3676 3645 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3677 3646 caddr_t saddr, naddr;
3678 3647 void *tmp = NULL;
3679 3648 size_t npage;
3680 3649
3681 3650 if ((seg->s_flags & S_HOLE) != 0) {
3682 3651 continue;
3683 3652 }
3684 3653
3685 3654 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3686 3655 (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3687 3656 if ((npage = (naddr - saddr) / PAGESIZE) != 0)
3688 3657 size += sizeof (ioc_prmap32_t) + round4(npage);
3689 3658 }
3690 3659 ASSERT(tmp == NULL);
3691 3660 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3692 3661
3693 3662 return (size);
3694 3663 }
3695 3664 #endif /* _SYSCALL32_IMPL */
3696 3665
3697 3666 /*
3698 3667 * Read old /proc page data information.
3699 3668 */
3700 3669 int
3701 3670 oprpdread(struct as *as, uint_t hatid, struct uio *uiop)
3702 3671 {
3703 3672 caddr_t buf;
3704 3673 size_t size;
3705 3674 prpageheader_t *php;
3706 3675 prasmap_t *pmp;
3707 3676 struct seg *seg;
3708 3677 int error;
3709 3678
3710 3679 again:
3711 3680 AS_LOCK_ENTER(as, RW_WRITER);
3712 3681
3713 3682 if ((seg = AS_SEGFIRST(as)) == NULL) {
3714 3683 AS_LOCK_EXIT(as);
3715 3684 return (0);
3716 3685 }
3717 3686 size = oprpdsize(as);
3718 3687 if (uiop->uio_resid < size) {
3719 3688 AS_LOCK_EXIT(as);
3720 3689 return (E2BIG);
3721 3690 }
3722 3691
3723 3692 buf = kmem_zalloc(size, KM_SLEEP);
3724 3693 php = (prpageheader_t *)buf;
3725 3694 pmp = (prasmap_t *)(buf + sizeof (prpageheader_t));
3726 3695
3727 3696 hrt2ts(gethrtime(), &php->pr_tstamp);
3728 3697 php->pr_nmap = 0;
3729 3698 php->pr_npage = 0;
3730 3699 do {
3731 3700 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3732 3701 caddr_t saddr, naddr;
3733 3702 void *tmp = NULL;
3734 3703
3735 3704 if ((seg->s_flags & S_HOLE) != 0) {
3736 3705 continue;
3737 3706 }
3738 3707
3739 3708 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3740 3709 size_t len;
3741 3710 size_t npage;
3742 3711 uint_t prot;
3743 3712 uintptr_t next;
3744 3713
3745 3714 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3746 3715 if ((len = naddr - saddr) == 0)
3747 3716 continue;
3748 3717 npage = len / PAGESIZE;
3749 3718 next = (uintptr_t)(pmp + 1) + roundlong(npage);
3750 3719 /*
3751 3720 * It's possible that the address space can change
3752 3721 * subtlely even though we're holding as->a_lock
3753 3722 * due to the nondeterminism of page_exists() in
3754 3723 * the presence of asychronously flushed pages or
3755 3724 * mapped files whose sizes are changing.
3756 3725 * page_exists() may be called indirectly from
3757 3726 * pr_getprot() by a SEGOP_INCORE() routine.
3758 3727 * If this happens we need to make sure we don't
3759 3728 * overrun the buffer whose size we computed based
3760 3729 * on the initial iteration through the segments.
3761 3730 * Once we've detected an overflow, we need to clean
3762 3731 * up the temporary memory allocated in pr_getprot()
3763 3732 * and retry. If there's a pending signal, we return
3764 3733 * EINTR so that this thread can be dislodged if
3765 3734 * a latent bug causes us to spin indefinitely.
3766 3735 */
3767 3736 if (next > (uintptr_t)buf + size) {
3768 3737 pr_getprot_done(&tmp);
3769 3738 AS_LOCK_EXIT(as);
3770 3739
3771 3740 kmem_free(buf, size);
3772 3741
3773 3742 if (ISSIG(curthread, JUSTLOOKING))
3774 3743 return (EINTR);
3775 3744
3776 3745 goto again;
3777 3746 }
3778 3747
3779 3748 php->pr_nmap++;
3780 3749 php->pr_npage += npage;
3781 3750 pmp->pr_vaddr = saddr;
3782 3751 pmp->pr_npage = npage;
3783 3752 pmp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3784 3753 pmp->pr_mflags = 0;
3785 3754 if (prot & PROT_READ)
3786 3755 pmp->pr_mflags |= MA_READ;
3787 3756 if (prot & PROT_WRITE)
3788 3757 pmp->pr_mflags |= MA_WRITE;
3789 3758 if (prot & PROT_EXEC)
3790 3759 pmp->pr_mflags |= MA_EXEC;
3791 3760 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3792 3761 pmp->pr_mflags |= MA_SHARED;
3793 3762 pmp->pr_pagesize = PAGESIZE;
3794 3763 hat_getstat(as, saddr, len, hatid,
3795 3764 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3796 3765 pmp = (prasmap_t *)next;
3797 3766 }
3798 3767 ASSERT(tmp == NULL);
3799 3768 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3800 3769
3801 3770 AS_LOCK_EXIT(as);
3802 3771
3803 3772 ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
3804 3773 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3805 3774 kmem_free(buf, size);
3806 3775
3807 3776 return (error);
3808 3777 }
3809 3778
3810 3779 #ifdef _SYSCALL32_IMPL
3811 3780 int
3812 3781 oprpdread32(struct as *as, uint_t hatid, struct uio *uiop)
3813 3782 {
3814 3783 caddr_t buf;
3815 3784 size_t size;
3816 3785 ioc_prpageheader32_t *php;
3817 3786 ioc_prasmap32_t *pmp;
3818 3787 struct seg *seg;
3819 3788 int error;
3820 3789
3821 3790 again:
3822 3791 AS_LOCK_ENTER(as, RW_WRITER);
3823 3792
3824 3793 if ((seg = AS_SEGFIRST(as)) == NULL) {
3825 3794 AS_LOCK_EXIT(as);
3826 3795 return (0);
3827 3796 }
3828 3797 size = oprpdsize32(as);
3829 3798 if (uiop->uio_resid < size) {
3830 3799 AS_LOCK_EXIT(as);
3831 3800 return (E2BIG);
3832 3801 }
3833 3802
3834 3803 buf = kmem_zalloc(size, KM_SLEEP);
3835 3804 php = (ioc_prpageheader32_t *)buf;
3836 3805 pmp = (ioc_prasmap32_t *)(buf + sizeof (ioc_prpageheader32_t));
3837 3806
3838 3807 hrt2ts32(gethrtime(), &php->pr_tstamp);
3839 3808 php->pr_nmap = 0;
3840 3809 php->pr_npage = 0;
3841 3810 do {
3842 3811 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3843 3812 caddr_t saddr, naddr;
3844 3813 void *tmp = NULL;
3845 3814
3846 3815 if ((seg->s_flags & S_HOLE) != 0) {
3847 3816 continue;
3848 3817 }
3849 3818
3850 3819 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3851 3820 size_t len;
3852 3821 size_t npage;
3853 3822 uint_t prot;
3854 3823 uintptr_t next;
3855 3824
3856 3825 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3857 3826 if ((len = naddr - saddr) == 0)
3858 3827 continue;
3859 3828 npage = len / PAGESIZE;
3860 3829 next = (uintptr_t)(pmp + 1) + round4(npage);
3861 3830 /*
3862 3831 * It's possible that the address space can change
3863 3832 * subtlely even though we're holding as->a_lock
3864 3833 * due to the nondeterminism of page_exists() in
3865 3834 * the presence of asychronously flushed pages or
3866 3835 * mapped files whose sizes are changing.
3867 3836 * page_exists() may be called indirectly from
3868 3837 * pr_getprot() by a SEGOP_INCORE() routine.
3869 3838 * If this happens we need to make sure we don't
3870 3839 * overrun the buffer whose size we computed based
3871 3840 * on the initial iteration through the segments.
3872 3841 * Once we've detected an overflow, we need to clean
3873 3842 * up the temporary memory allocated in pr_getprot()
3874 3843 * and retry. If there's a pending signal, we return
3875 3844 * EINTR so that this thread can be dislodged if
3876 3845 * a latent bug causes us to spin indefinitely.
3877 3846 */
3878 3847 if (next > (uintptr_t)buf + size) {
3879 3848 pr_getprot_done(&tmp);
3880 3849 AS_LOCK_EXIT(as);
3881 3850
3882 3851 kmem_free(buf, size);
3883 3852
3884 3853 if (ISSIG(curthread, JUSTLOOKING))
3885 3854 return (EINTR);
3886 3855
3887 3856 goto again;
3888 3857 }
3889 3858
3890 3859 php->pr_nmap++;
3891 3860 php->pr_npage += npage;
3892 3861 pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
3893 3862 pmp->pr_npage = (uint32_t)npage;
3894 3863 pmp->pr_off = (int32_t)SEGOP_GETOFFSET(seg, saddr);
3895 3864 pmp->pr_mflags = 0;
3896 3865 if (prot & PROT_READ)
3897 3866 pmp->pr_mflags |= MA_READ;
3898 3867 if (prot & PROT_WRITE)
3899 3868 pmp->pr_mflags |= MA_WRITE;
3900 3869 if (prot & PROT_EXEC)
3901 3870 pmp->pr_mflags |= MA_EXEC;
3902 3871 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3903 3872 pmp->pr_mflags |= MA_SHARED;
3904 3873 pmp->pr_pagesize = PAGESIZE;
3905 3874 hat_getstat(as, saddr, len, hatid,
3906 3875 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3907 3876 pmp = (ioc_prasmap32_t *)next;
3908 3877 }
3909 3878 ASSERT(tmp == NULL);
3910 3879 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3911 3880
3912 3881 AS_LOCK_EXIT(as);
3913 3882
3914 3883 ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
3915 3884 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3916 3885 kmem_free(buf, size);
3917 3886
3918 3887 return (error);
3919 3888 }
3920 3889 #endif /* _SYSCALL32_IMPL */
3921 3890
3922 3891 /*ARGSUSED*/
3923 3892 #ifdef _SYSCALL32_IMPL
3924 3893 int
3925 3894 prioctl(
3926 3895 struct vnode *vp,
3927 3896 int cmd,
3928 3897 intptr_t arg,
3929 3898 int flag,
3930 3899 cred_t *cr,
3931 3900 int *rvalp,
3932 3901 caller_context_t *ct)
3933 3902 {
3934 3903 switch (curproc->p_model) {
3935 3904 case DATAMODEL_ILP32:
3936 3905 return (prioctl32(vp, cmd, arg, flag, cr, rvalp, ct));
3937 3906 case DATAMODEL_LP64:
3938 3907 return (prioctl64(vp, cmd, arg, flag, cr, rvalp, ct));
3939 3908 default:
3940 3909 return (ENOSYS);
3941 3910 }
3942 3911 }
3943 3912 #endif /* _SYSCALL32_IMPL */
|
↓ open down ↓ |
1493 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX