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