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