]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_sysctl.c
58551e20ffd1a044adc8dfe2afb7620aa0b73a01
[apple/xnu.git] / bsd / kern / kern_sysctl.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26 /*-
27 * Copyright (c) 1982, 1986, 1989, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * This code is derived from software contributed to Berkeley by
31 * Mike Karels at Berkeley Software Design, Inc.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
62 */
63
64 /*
65 * sysctl system call.
66 */
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/kernel.h>
71 #include <sys/malloc.h>
72 #include <sys/proc.h>
73 #include <sys/file.h>
74 #include <sys/vnode.h>
75 #include <sys/unistd.h>
76 #include <sys/buf.h>
77 #include <sys/ioctl.h>
78 #include <sys/tty.h>
79 #include <sys/disklabel.h>
80 #include <sys/vm.h>
81 #include <sys/sysctl.h>
82 #include <sys/user.h>
83 #include <mach/machine.h>
84 #include <mach/mach_types.h>
85 #include <mach/vm_param.h>
86 #include <kern/task.h>
87 #include <vm/vm_kern.h>
88 #include <mach/host_info.h>
89
90 extern vm_map_t bsd_pageable_map;
91
92 #include <sys/mount.h>
93 #include <sys/kdebug.h>
94
95 #include <IOKit/IOPlatformExpert.h>
96 #include <pexpert/pexpert.h>
97
98 #if __ppc__
99 #include <ppc/machine_routines.h>
100 #endif
101
102 sysctlfn kern_sysctl;
103 #ifdef DEBUG
104 sysctlfn debug_sysctl;
105 #endif
106 extern sysctlfn vm_sysctl;
107 extern sysctlfn vfs_sysctl;
108 extern sysctlfn net_sysctl;
109 extern sysctlfn cpu_sysctl;
110
111
112 int
113 userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t
114 *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
115
116 void
117 fill_proc(struct proc *p,struct kinfo_proc *kp, int doingzomb);
118
119 void
120 fill_externproc(struct proc *p, struct extern_proc *exp);
121
122
123
124 /*
125 * temporary location for vm_sysctl. This should be machine independant
126 */
127 int
128 vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
129 int *name;
130 u_int namelen;
131 void *oldp;
132 size_t *oldlenp;
133 void *newp;
134 size_t newlen;
135 struct proc *p;
136 {
137 extern uint32_t mach_factor[3];
138 struct loadavg loadinfo;
139
140 switch (name[0]) {
141 case VM_LOADAVG:
142 return (sysctl_struct(oldp, oldlenp, newp, newlen,
143 &averunnable, sizeof(struct loadavg)));
144 case VM_MACHFACTOR:
145 loadinfo.ldavg[0] = mach_factor[0];
146 loadinfo.ldavg[1] = mach_factor[1];
147 loadinfo.ldavg[2] = mach_factor[2];
148 loadinfo.fscale = LSCALE;
149 return (sysctl_struct(oldp, oldlenp, newp, newlen,
150 &loadinfo, sizeof(struct loadavg)));
151 case VM_METER:
152 return (EOPNOTSUPP);
153 case VM_MAXID:
154 return (EOPNOTSUPP);
155 default:
156 return (EOPNOTSUPP);
157 }
158 /* NOTREACHED */
159 return (EOPNOTSUPP);
160 }
161
162 /*
163 * Locking and stats
164 */
165 static struct sysctl_lock {
166 int sl_lock;
167 int sl_want;
168 int sl_locked;
169 } memlock;
170
171 struct __sysctl_args {
172 int *name;
173 u_int namelen;
174 void *old;
175 size_t *oldlenp;
176 void *new;
177 size_t newlen;
178 };
179 int
180 __sysctl(p, uap, retval)
181 struct proc *p;
182 register struct __sysctl_args *uap;
183 register_t *retval;
184 {
185 int error, dolock = 1;
186 size_t savelen, oldlen = 0;
187 sysctlfn *fn;
188 int name[CTL_MAXNAME];
189 int i;
190 int error1;
191
192 /*
193 * all top-level sysctl names are non-terminal
194 */
195 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
196 return (EINVAL);
197 if (error =
198 copyin(uap->name, &name, uap->namelen * sizeof(int)))
199 return (error);
200
201 /* CTL_UNSPEC is used to get oid to AUTO_OID */
202 if (uap->new != NULL
203 && ((name[0] == CTL_KERN
204 && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO))
205 || (name[0] == CTL_HW)
206 || (name[0] == CTL_VM)
207 || (name[0] == CTL_VFS))
208 && (error = suser(p->p_ucred, &p->p_acflag)))
209 return (error);
210
211 switch (name[0]) {
212 case CTL_KERN:
213 fn = kern_sysctl;
214 if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE)
215 && (name[1] != KERN_PROC))
216 dolock = 0;
217 break;
218 case CTL_VM:
219 fn = vm_sysctl;
220 break;
221
222 case CTL_VFS:
223 fn = vfs_sysctl;
224 break;
225 #ifdef DEBUG
226 case CTL_DEBUG:
227 fn = debug_sysctl;
228 break;
229 #endif
230 default:
231 fn = 0;
232 }
233
234 if (uap->oldlenp &&
235 (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
236 return (error);
237
238 if (uap->old != NULL) {
239 if (!useracc(uap->old, oldlen, B_WRITE))
240 return (EFAULT);
241
242 /* The pc sampling mechanism does not need to take this lock */
243 if ((name[1] != KERN_PCSAMPLES) &&
244 (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
245 while (memlock.sl_lock) {
246 memlock.sl_want = 1;
247 sleep((caddr_t)&memlock, PRIBIO+1);
248 memlock.sl_locked++;
249 }
250 memlock.sl_lock = 1;
251 }
252
253 if (dolock && oldlen && (error = vslock(uap->old, oldlen))) {
254 if ((name[1] != KERN_PCSAMPLES) &&
255 (! ((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
256 memlock.sl_lock = 0;
257 if (memlock.sl_want) {
258 memlock.sl_want = 0;
259 wakeup((caddr_t)&memlock);
260 }
261 }
262 return(error);
263 }
264 savelen = oldlen;
265 }
266
267 if (fn)
268 error = (*fn)(name + 1, uap->namelen - 1, uap->old,
269 &oldlen, uap->new, uap->newlen, p);
270 else
271 error = EOPNOTSUPP;
272
273 if ( (name[0] != CTL_VFS) && (error == EOPNOTSUPP))
274 error = userland_sysctl(p, name, uap->namelen,
275 uap->old, uap->oldlenp, 0,
276 uap->new, uap->newlen, &oldlen);
277
278 if (uap->old != NULL) {
279 if (dolock && savelen) {
280 error1 = vsunlock(uap->old, savelen, B_WRITE);
281 if (!error && error1)
282 error = error1;
283 }
284 if (name[1] != KERN_PCSAMPLES) {
285 memlock.sl_lock = 0;
286 if (memlock.sl_want) {
287 memlock.sl_want = 0;
288 wakeup((caddr_t)&memlock);
289 }
290 }
291 }
292 if ((error) && (error != ENOMEM))
293 return (error);
294
295 if (uap->oldlenp) {
296 i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
297 if (i)
298 return i;
299 }
300
301 return (error);
302 }
303
304 /*
305 * Attributes stored in the kernel.
306 */
307 extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
308 extern int hostnamelen;
309 extern char domainname[MAXHOSTNAMELEN];
310 extern int domainnamelen;
311 extern long hostid;
312 #ifdef INSECURE
313 int securelevel = -1;
314 #else
315 int securelevel;
316 #endif
317
318 extern int get_kernel_symfile( struct proc *, char **);
319 extern int sysctl_dopanicinfo(int *, u_int, void *, size_t *,
320 void *, size_t, struct proc *);
321
322 /*
323 * kernel related system variables.
324 */
325 int
326 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
327 int *name;
328 u_int namelen;
329 void *oldp;
330 size_t *oldlenp;
331 void *newp;
332 size_t newlen;
333 struct proc *p;
334 {
335 int error, level, inthostid;
336 unsigned int oldval=0;
337 char *str;
338 extern char ostype[], osrelease[], version[];
339 extern int netboot_root();
340
341 /* all sysctl names not listed below are terminal at this level */
342 if (namelen != 1
343 && !(name[0] == KERN_PROC
344 || name[0] == KERN_PROF
345 || name[0] == KERN_KDEBUG
346 || name[0] == KERN_PROCARGS
347 || name[0] == KERN_PCSAMPLES
348 || name[0] == KERN_IPC
349 || name[0] == KERN_SYSV
350 || name[0] == KERN_PANICINFO)
351 )
352 return (ENOTDIR); /* overloaded */
353
354 switch (name[0]) {
355 case KERN_OSTYPE:
356 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
357 case KERN_OSRELEASE:
358 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
359 case KERN_OSREV:
360 return (sysctl_rdint(oldp, oldlenp, newp, BSD));
361 case KERN_VERSION:
362 return (sysctl_rdstring(oldp, oldlenp, newp, version));
363 case KERN_MAXVNODES:
364 oldval = desiredvnodes;
365 error = sysctl_int(oldp, oldlenp, newp,
366 newlen, &desiredvnodes);
367 reset_vmobjectcache(oldval, desiredvnodes);
368 return(error);
369 case KERN_MAXPROC:
370 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
371 case KERN_MAXFILES:
372 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
373 case KERN_ARGMAX:
374 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
375 case KERN_SECURELVL:
376 level = securelevel;
377 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
378 newp == NULL)
379 return (error);
380 if (level < securelevel && p->p_pid != 1)
381 return (EPERM);
382 securelevel = level;
383 return (0);
384 case KERN_HOSTNAME:
385 error = sysctl_string(oldp, oldlenp, newp, newlen,
386 hostname, sizeof(hostname));
387 if (newp && !error)
388 hostnamelen = newlen;
389 return (error);
390 case KERN_DOMAINNAME:
391 error = sysctl_string(oldp, oldlenp, newp, newlen,
392 domainname, sizeof(domainname));
393 if (newp && !error)
394 domainnamelen = newlen;
395 return (error);
396 case KERN_HOSTID:
397 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
398 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
399 hostid = inthostid;
400 return (error);
401 case KERN_CLOCKRATE:
402 return (sysctl_clockrate(oldp, oldlenp));
403 case KERN_BOOTTIME:
404 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
405 sizeof(struct timeval)));
406 case KERN_VNODE:
407 return (sysctl_vnode(oldp, oldlenp));
408 case KERN_PROC:
409 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
410 case KERN_FILE:
411 return (sysctl_file(oldp, oldlenp));
412 #ifdef GPROF
413 case KERN_PROF:
414 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
415 newp, newlen));
416 #endif
417 case KERN_POSIX1:
418 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
419 case KERN_NGROUPS:
420 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
421 case KERN_JOB_CONTROL:
422 return (sysctl_rdint(oldp, oldlenp, newp, 1));
423 case KERN_SAVED_IDS:
424 #ifdef _POSIX_SAVED_IDS
425 return (sysctl_rdint(oldp, oldlenp, newp, 1));
426 #else
427 return (sysctl_rdint(oldp, oldlenp, newp, 0));
428 #endif
429 case KERN_KDEBUG:
430 return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
431 case KERN_PCSAMPLES:
432 return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
433 case KERN_PROCARGS:
434 /* new one as it does not use kinfo_proc */
435 return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
436 case KERN_SYMFILE:
437 error = get_kernel_symfile( p, &str );
438 if ( error )
439 return error;
440 return (sysctl_rdstring(oldp, oldlenp, newp, str));
441 case KERN_NETBOOT:
442 return (sysctl_rdint(oldp, oldlenp, newp, netboot_root()));
443 case KERN_PANICINFO:
444 return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
445 newp, newlen, p));
446 default:
447 return (EOPNOTSUPP);
448 }
449 /* NOTREACHED */
450 }
451
452 #ifdef DEBUG
453 /*
454 * Debugging related system variables.
455 */
456 #if DIAGNOSTIC
457 extern
458 #endif /* DIAGNOSTIC */
459 struct ctldebug debug0, debug1;
460 struct ctldebug debug2, debug3, debug4;
461 struct ctldebug debug5, debug6, debug7, debug8, debug9;
462 struct ctldebug debug10, debug11, debug12, debug13, debug14;
463 struct ctldebug debug15, debug16, debug17, debug18, debug19;
464 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
465 &debug0, &debug1, &debug2, &debug3, &debug4,
466 &debug5, &debug6, &debug7, &debug8, &debug9,
467 &debug10, &debug11, &debug12, &debug13, &debug14,
468 &debug15, &debug16, &debug17, &debug18, &debug19,
469 };
470 int
471 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
472 int *name;
473 u_int namelen;
474 void *oldp;
475 size_t *oldlenp;
476 void *newp;
477 size_t newlen;
478 struct proc *p;
479 {
480 struct ctldebug *cdp;
481
482 /* all sysctl names at this level are name and field */
483 if (namelen != 2)
484 return (ENOTDIR); /* overloaded */
485 cdp = debugvars[name[0]];
486 if (cdp->debugname == 0)
487 return (EOPNOTSUPP);
488 switch (name[1]) {
489 case CTL_DEBUG_NAME:
490 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
491 case CTL_DEBUG_VALUE:
492 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
493 default:
494 return (EOPNOTSUPP);
495 }
496 /* NOTREACHED */
497 }
498 #endif /* DEBUG */
499
500 /*
501 * Validate parameters and get old / set new parameters
502 * for an integer-valued sysctl function.
503 */
504 int
505 sysctl_int(oldp, oldlenp, newp, newlen, valp)
506 void *oldp;
507 size_t *oldlenp;
508 void *newp;
509 size_t newlen;
510 int *valp;
511 {
512 int error = 0;
513
514 if (oldp && *oldlenp < sizeof(int))
515 return (ENOMEM);
516 if (newp && newlen != sizeof(int))
517 return (EINVAL);
518 *oldlenp = sizeof(int);
519 if (oldp)
520 error = copyout(valp, oldp, sizeof(int));
521 if (error == 0 && newp)
522 error = copyin(newp, valp, sizeof(int));
523 return (error);
524 }
525
526 /*
527 * As above, but read-only.
528 */
529 int
530 sysctl_rdint(oldp, oldlenp, newp, val)
531 void *oldp;
532 size_t *oldlenp;
533 void *newp;
534 int val;
535 {
536 int error = 0;
537
538 if (oldp && *oldlenp < sizeof(int))
539 return (ENOMEM);
540 if (newp)
541 return (EPERM);
542 *oldlenp = sizeof(int);
543 if (oldp)
544 error = copyout((caddr_t)&val, oldp, sizeof(int));
545 return (error);
546 }
547
548 /*
549 * Validate parameters and get old / set new parameters
550 * for an quad(64bit)-valued sysctl function.
551 */
552 int
553 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
554 void *oldp;
555 size_t *oldlenp;
556 void *newp;
557 size_t newlen;
558 quad_t *valp;
559 {
560 int error = 0;
561
562 if (oldp && *oldlenp < sizeof(quad_t))
563 return (ENOMEM);
564 if (newp && newlen != sizeof(quad_t))
565 return (EINVAL);
566 *oldlenp = sizeof(quad_t);
567 if (oldp)
568 error = copyout(valp, oldp, sizeof(quad_t));
569 if (error == 0 && newp)
570 error = copyin(newp, valp, sizeof(quad_t));
571 return (error);
572 }
573
574 /*
575 * As above, but read-only.
576 */
577 int
578 sysctl_rdquad(oldp, oldlenp, newp, val)
579 void *oldp;
580 size_t *oldlenp;
581 void *newp;
582 quad_t val;
583 {
584 int error = 0;
585
586 if (oldp && *oldlenp < sizeof(quad_t))
587 return (ENOMEM);
588 if (newp)
589 return (EPERM);
590 *oldlenp = sizeof(quad_t);
591 if (oldp)
592 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
593 return (error);
594 }
595
596 /*
597 * Validate parameters and get old / set new parameters
598 * for a string-valued sysctl function.
599 */
600 int
601 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
602 void *oldp;
603 size_t *oldlenp;
604 void *newp;
605 size_t newlen;
606 char *str;
607 int maxlen;
608 {
609 int len, error = 0;
610
611 len = strlen(str) + 1;
612 if (oldp && *oldlenp < len)
613 return (ENOMEM);
614 if (newp && newlen >= maxlen)
615 return (EINVAL);
616 *oldlenp = len -1; /* deal with NULL strings correctly */
617 if (oldp) {
618 error = copyout(str, oldp, len);
619 }
620 if (error == 0 && newp) {
621 error = copyin(newp, str, newlen);
622 str[newlen] = 0;
623 }
624 return (error);
625 }
626
627 /*
628 * As above, but read-only.
629 */
630 int
631 sysctl_rdstring(oldp, oldlenp, newp, str)
632 void *oldp;
633 size_t *oldlenp;
634 void *newp;
635 char *str;
636 {
637 int len, error = 0;
638
639 len = strlen(str) + 1;
640 if (oldp && *oldlenp < len)
641 return (ENOMEM);
642 if (newp)
643 return (EPERM);
644 *oldlenp = len;
645 if (oldp)
646 error = copyout(str, oldp, len);
647 return (error);
648 }
649
650 /*
651 * Validate parameters and get old / set new parameters
652 * for a structure oriented sysctl function.
653 */
654 int
655 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
656 void *oldp;
657 size_t *oldlenp;
658 void *newp;
659 size_t newlen;
660 void *sp;
661 int len;
662 {
663 int error = 0;
664
665 if (oldp && *oldlenp < len)
666 return (ENOMEM);
667 if (newp && newlen > len)
668 return (EINVAL);
669 if (oldp) {
670 *oldlenp = len;
671 error = copyout(sp, oldp, len);
672 }
673 if (error == 0 && newp)
674 error = copyin(newp, sp, len);
675 return (error);
676 }
677
678 /*
679 * Validate parameters and get old parameters
680 * for a structure oriented sysctl function.
681 */
682 int
683 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
684 void *oldp;
685 size_t *oldlenp;
686 void *newp, *sp;
687 int len;
688 {
689 int error = 0;
690
691 if (oldp && *oldlenp < len)
692 return (ENOMEM);
693 if (newp)
694 return (EPERM);
695 *oldlenp = len;
696 if (oldp)
697 error = copyout(sp, oldp, len);
698 return (error);
699 }
700
701 /*
702 * Get file structures.
703 */
704 int
705 sysctl_file(where, sizep)
706 char *where;
707 size_t *sizep;
708 {
709 int buflen, error;
710 struct file *fp;
711 char *start = where;
712
713 buflen = *sizep;
714 if (where == NULL) {
715 /*
716 * overestimate by 10 files
717 */
718 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
719 return (0);
720 }
721
722 /*
723 * first copyout filehead
724 */
725 if (buflen < sizeof(filehead)) {
726 *sizep = 0;
727 return (0);
728 }
729 if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
730 return (error);
731 buflen -= sizeof(filehead);
732 where += sizeof(filehead);
733
734 /*
735 * followed by an array of file structures
736 */
737 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
738 if (buflen < sizeof(struct file)) {
739 *sizep = where - start;
740 return (ENOMEM);
741 }
742 if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
743 return (error);
744 buflen -= sizeof(struct file);
745 where += sizeof(struct file);
746 }
747 *sizep = where - start;
748 return (0);
749 }
750
751 /*
752 * try over estimating by 5 procs
753 */
754 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
755
756 int
757 sysctl_doproc(name, namelen, where, sizep)
758 int *name;
759 u_int namelen;
760 char *where;
761 size_t *sizep;
762 {
763 register struct proc *p;
764 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
765 register int needed = 0;
766 int buflen = where != NULL ? *sizep : 0;
767 int doingzomb;
768 struct kinfo_proc kproc;
769 int error = 0;
770
771 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
772 return (EINVAL);
773 p = allproc.lh_first;
774 doingzomb = 0;
775 again:
776 for (; p != 0; p = p->p_list.le_next) {
777 /*
778 * Skip embryonic processes.
779 */
780 if (p->p_stat == SIDL)
781 continue;
782 /*
783 * TODO - make more efficient (see notes below).
784 * do by session.
785 */
786 switch (name[0]) {
787
788 case KERN_PROC_PID:
789 /* could do this with just a lookup */
790 if (p->p_pid != (pid_t)name[1])
791 continue;
792 break;
793
794 case KERN_PROC_PGRP:
795 /* could do this by traversing pgrp */
796 if (p->p_pgrp->pg_id != (pid_t)name[1])
797 continue;
798 break;
799
800 case KERN_PROC_TTY:
801 if ( doingzomb || (p->p_flag & P_CONTROLT) == 0 ||
802 p->p_session->s_ttyp == NULL ||
803 p->p_session->s_ttyp->t_dev != (dev_t)name[1])
804 continue;
805 break;
806
807 case KERN_PROC_UID:
808 if (doingzomb || (p->p_ucred->cr_uid != (uid_t)name[1]))
809 continue;
810 break;
811
812 case KERN_PROC_RUID:
813 if ( doingzomb || (p->p_cred->p_ruid != (uid_t)name[1]))
814 continue;
815 break;
816 }
817 if (buflen >= sizeof(struct kinfo_proc)) {
818 bzero(&kproc, sizeof(struct kinfo_proc));
819 fill_proc(p, &kproc, doingzomb);
820 if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
821 sizeof(struct kinfo_proc)))
822 return (error);
823 dp++;
824 buflen -= sizeof(struct kinfo_proc);
825 }
826 needed += sizeof(struct kinfo_proc);
827 }
828 if (doingzomb == 0) {
829 p = zombproc.lh_first;
830 doingzomb++;
831 goto again;
832 }
833 if (where != NULL) {
834 *sizep = (caddr_t)dp - where;
835 if (needed > *sizep)
836 return (ENOMEM);
837 } else {
838 needed += KERN_PROCSLOP;
839 *sizep = needed;
840 }
841 return (0);
842 }
843
844 void
845 fill_proc(p,kp, doingzomb)
846 register struct proc *p;
847 register struct kinfo_proc *kp;
848 int doingzomb;
849 {
850 fill_externproc(p, &kp->kp_proc);
851 if (!doingzomb)
852 fill_eproc(p, &kp->kp_eproc);
853 }
854 /*
855 * Fill in an eproc structure for the specified process.
856 */
857 void
858 fill_eproc(p, ep)
859 register struct proc *p;
860 register struct eproc *ep;
861 {
862 register struct tty *tp;
863
864 /*
865 * Skip zombie processes.
866 */
867 if (p->p_stat == SZOMB)
868 return;
869
870 ep->e_paddr = p;
871 ep->e_sess = p->p_pgrp->pg_session;
872 ep->e_pcred = *p->p_cred;
873 ep->e_ucred = *p->p_ucred;
874 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
875 ep->e_vm.vm_tsize = 0;
876 ep->e_vm.vm_dsize = 0;
877 ep->e_vm.vm_ssize = 0;
878 }
879 ep->e_vm.vm_rssize = 0;
880 if (p->p_pptr)
881 ep->e_ppid = p->p_pptr->p_pid;
882 else
883 ep->e_ppid = 0;
884 ep->e_pgid = p->p_pgrp->pg_id;
885 ep->e_jobc = p->p_pgrp->pg_jobc;
886 if ((p->p_flag & P_CONTROLT) &&
887 (tp = ep->e_sess->s_ttyp)) {
888 ep->e_tdev = tp->t_dev;
889 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
890 ep->e_tsess = tp->t_session;
891 } else
892 ep->e_tdev = NODEV;
893 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
894 if (SESS_LEADER(p))
895 ep->e_flag |= EPROC_SLEADER;
896 if (p->p_wmesg)
897 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
898 ep->e_xsize = ep->e_xrssize = 0;
899 ep->e_xccount = ep->e_xswrss = 0;
900 }
901 /*
902 * Fill in an eproc structure for the specified process.
903 */
904 void
905 fill_externproc(p, exp)
906 register struct proc *p;
907 register struct extern_proc *exp;
908 {
909 exp->p_forw = exp->p_back = NULL;
910 if (p->p_stats)
911 exp->p_starttime = p->p_stats->p_start;
912 exp->p_vmspace = NULL;
913 exp->p_sigacts = p->p_sigacts;
914 exp->p_flag = p->p_flag;
915 exp->p_stat = p->p_stat ;
916 exp->p_pid = p->p_pid ;
917 exp->p_oppid = p->p_oppid ;
918 exp->p_dupfd = p->p_dupfd ;
919 /* Mach related */
920 exp->user_stack = p->user_stack ;
921 exp->exit_thread = p->exit_thread ;
922 exp->p_debugger = p->p_debugger ;
923 exp->sigwait = p->sigwait ;
924 /* scheduling */
925 exp->p_estcpu = p->p_estcpu ;
926 exp->p_cpticks = p->p_cpticks ;
927 exp->p_pctcpu = p->p_pctcpu ;
928 exp->p_wchan = p->p_wchan ;
929 exp->p_wmesg = p->p_wmesg ;
930 exp->p_swtime = p->p_swtime ;
931 exp->p_slptime = p->p_slptime ;
932 bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
933 bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
934 exp->p_uticks = p->p_uticks ;
935 exp->p_sticks = p->p_sticks ;
936 exp->p_iticks = p->p_iticks ;
937 exp->p_traceflag = p->p_traceflag ;
938 exp->p_tracep = p->p_tracep ;
939 exp->p_siglist = 0 ; /* No longer relevant */
940 exp->p_textvp = p->p_textvp ;
941 exp->p_holdcnt = 0 ;
942 exp->p_sigmask = 0 ; /* no longer avaialable */
943 exp->p_sigignore = p->p_sigignore ;
944 exp->p_sigcatch = p->p_sigcatch ;
945 exp->p_priority = p->p_priority ;
946 exp->p_usrpri = p->p_usrpri ;
947 exp->p_nice = p->p_nice ;
948 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
949 exp->p_comm[MAXCOMLEN] = '\0';
950 exp->p_pgrp = p->p_pgrp ;
951 exp->p_addr = NULL;
952 exp->p_xstat = p->p_xstat ;
953 exp->p_acflag = p->p_acflag ;
954 exp->p_ru = p->p_ru ;
955 }
956
957 int
958 kdebug_ops(name, namelen, where, sizep, p)
959 int *name;
960 u_int namelen;
961 char *where;
962 size_t *sizep;
963 struct proc *p;
964 {
965 int size=*sizep;
966 int ret=0;
967 extern int kdbg_control(int *name, u_int namelen,
968 char * where,size_t * sizep);
969
970 if (ret = suser(p->p_ucred, &p->p_acflag))
971 return(ret);
972
973 switch(name[0]) {
974 case KERN_KDEFLAGS:
975 case KERN_KDDFLAGS:
976 case KERN_KDENABLE:
977 case KERN_KDGETBUF:
978 case KERN_KDSETUP:
979 case KERN_KDREMOVE:
980 case KERN_KDSETREG:
981 case KERN_KDGETREG:
982 case KERN_KDREADTR:
983 case KERN_KDPIDTR:
984 case KERN_KDTHRMAP:
985 case KERN_KDPIDEX:
986 case KERN_KDSETRTCDEC:
987 case KERN_KDSETBUF:
988 case KERN_KDGETENTROPY:
989 ret = kdbg_control(name, namelen, where, sizep);
990 break;
991 default:
992 ret= EOPNOTSUPP;
993 break;
994 }
995 return(ret);
996 }
997
998 int
999 pcsamples_ops(name, namelen, where, sizep, p)
1000 int *name;
1001 u_int namelen;
1002 char *where;
1003 size_t *sizep;
1004 struct proc *p;
1005 {
1006 int ret=0;
1007 extern int pcsamples_control(int *name, u_int namelen,
1008 char * where,size_t * sizep);
1009
1010 if (ret = suser(p->p_ucred, &p->p_acflag))
1011 return(ret);
1012
1013 switch(name[0]) {
1014 case KERN_PCDISABLE:
1015 case KERN_PCGETBUF:
1016 case KERN_PCSETUP:
1017 case KERN_PCREMOVE:
1018 case KERN_PCREADBUF:
1019 case KERN_PCSETREG:
1020 case KERN_PCSETBUF:
1021 case KERN_PCCOMM:
1022 ret = pcsamples_control(name, namelen, where, sizep);
1023 break;
1024 default:
1025 ret= EOPNOTSUPP;
1026 break;
1027 }
1028 return(ret);
1029 }
1030
1031 /*
1032 * Returns the top N bytes of the user stack, with
1033 * everything below the first argument character
1034 * zeroed for security reasons.
1035 * Odd data structure is for compatibility.
1036 */
1037 int
1038 sysctl_procargs(name, namelen, where, sizep, cur_proc)
1039 int *name;
1040 u_int namelen;
1041 char *where;
1042 size_t *sizep;
1043 struct proc *cur_proc;
1044 {
1045 register struct proc *p;
1046 register int needed = 0;
1047 int buflen = where != NULL ? *sizep : 0;
1048 int error = 0;
1049 struct vm_map *proc_map;
1050 struct task * task;
1051 vm_map_copy_t tmp;
1052 vm_offset_t arg_addr;
1053 vm_size_t arg_size;
1054 caddr_t data;
1055 unsigned size;
1056 vm_offset_t copy_start, copy_end;
1057 vm_offset_t dealloc_start; /* area to remove from kernel map */
1058 vm_offset_t dealloc_end;
1059 int *ip;
1060 kern_return_t ret;
1061 int pid;
1062
1063
1064 if ((buflen <= 0) || (buflen > (PAGE_SIZE << 1))) {
1065 return(EINVAL);
1066 }
1067 arg_size = buflen;
1068
1069 /*
1070 * Lookup process by pid
1071 */
1072 pid = name[0];
1073
1074 restart:
1075 p = pfind(pid);
1076 if (p == NULL) {
1077 return(EINVAL);
1078 }
1079
1080 /*
1081 * Copy the top N bytes of the stack.
1082 * On all machines we have so far, the stack grows
1083 * downwards.
1084 *
1085 * If the user expects no more than N bytes of
1086 * argument list, use that as a guess for the
1087 * size.
1088 */
1089
1090 if (!p->user_stack)
1091 return(EINVAL);
1092
1093 if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid)
1094 && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
1095 return (EINVAL);
1096 arg_addr = (vm_offset_t)(p->user_stack - arg_size);
1097
1098
1099 /*
1100 * Before we can block (any VM code), make another
1101 * reference to the map to keep it alive. We do
1102 * that by getting a reference on the task itself.
1103 */
1104 task = p->task;
1105 if (task == NULL)
1106 return(EINVAL);
1107
1108 /*
1109 * A regular task_reference call can block, causing the funnel
1110 * to be dropped and allowing the proc/task to get freed.
1111 * Instead, we issue a non-blocking attempt at the task reference,
1112 * and look up the proc/task all over again if that fails.
1113 */
1114 if (!task_reference_try(task)) {
1115 mutex_pause();
1116 goto restart;
1117 }
1118
1119 ret = kmem_alloc(kernel_map, &copy_start, round_page_32(arg_size));
1120 if (ret != KERN_SUCCESS) {
1121 task_deallocate(task);
1122 return(ENOMEM);
1123 }
1124
1125 proc_map = get_task_map(task);
1126 copy_end = round_page_32(copy_start + arg_size);
1127
1128 if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page_32(arg_size),
1129 FALSE, &tmp) != KERN_SUCCESS) {
1130 task_deallocate(task);
1131 kmem_free(kernel_map, copy_start,
1132 round_page_32(arg_size));
1133 return (EIO);
1134 }
1135
1136 /*
1137 * Now that we've done the copyin from the process'
1138 * map, we can release the reference to it.
1139 */
1140 task_deallocate(task);
1141
1142 if( vm_map_copy_overwrite(kernel_map, copy_start,
1143 tmp, FALSE) != KERN_SUCCESS) {
1144 kmem_free(kernel_map, copy_start,
1145 round_page_32(arg_size));
1146 return (EIO);
1147 }
1148
1149 data = (caddr_t) (copy_end - arg_size);
1150 ip = (int *) copy_end;
1151 size = arg_size;
1152
1153 /*
1154 * Now look down the stack for the bottom of the
1155 * argument list. Since this call is otherwise
1156 * unprotected, we can't let the nosy user see
1157 * anything else on the stack.
1158 *
1159 * The arguments are pushed on the stack by
1160 * execve() as:
1161 *
1162 * .long 0
1163 * arg 0 (null-terminated)
1164 * arg 1
1165 * ...
1166 * arg N
1167 * .long 0
1168 *
1169 */
1170
1171 ip -= 2; /*skip trailing 0 word and assume at least one
1172 argument. The last word of argN may be just
1173 the trailing 0, in which case we'd stop
1174 there */
1175 while (*--ip)
1176 if (ip == (int *)data)
1177 break;
1178 /*
1179 * To account for saved path name and not having a null after that
1180 * Run the sweep again. If we have already sweeped entire range skip this
1181 */
1182 if (ip != (int *)data) {
1183 while (*--ip)
1184 if (ip == (int *)data)
1185 break;
1186 }
1187
1188 bzero(data, (unsigned) ((int)ip - (int)data));
1189
1190 dealloc_start = copy_start;
1191 dealloc_end = copy_end;
1192
1193
1194 size = MIN(size, buflen);
1195 error = copyout(data, where, size);
1196
1197 if (dealloc_start != (vm_offset_t) 0) {
1198 kmem_free(kernel_map, dealloc_start,
1199 dealloc_end - dealloc_start);
1200 }
1201 if (error) {
1202 return(error);
1203 }
1204
1205 if (where != NULL)
1206 *sizep = size;
1207 return (0);
1208 }