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