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