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