2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software contributed to Berkeley by
28 * Mike Karels at Berkeley Software Design, Inc.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
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.
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
58 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/malloc.h>
71 #include <sys/vnode.h>
72 #include <sys/unistd.h>
74 #include <sys/ioctl.h>
75 #include <sys/namei.h>
77 #include <sys/disklabel.h>
79 #include <sys/sysctl.h>
81 #include <sys/aio_kern.h>
83 #include <bsm/audit_kernel.h>
85 #include <mach/machine.h>
86 #include <mach/mach_types.h>
87 #include <mach/vm_param.h>
88 #include <kern/task.h>
89 #include <vm/vm_kern.h>
90 #include <mach/host_info.h>
92 extern vm_map_t bsd_pageable_map
;
94 #include <sys/mount.h>
95 #include <sys/kdebug.h>
97 #include <IOKit/IOPlatformExpert.h>
98 #include <pexpert/pexpert.h>
100 #include <machine/machine_routines.h>
102 sysctlfn kern_sysctl
;
104 sysctlfn debug_sysctl
;
106 extern sysctlfn vm_sysctl
;
107 extern sysctlfn vfs_sysctl
;
108 extern sysctlfn net_sysctl
;
109 extern sysctlfn cpu_sysctl
;
110 extern int aio_max_requests
;
111 extern int aio_max_requests_per_process
;
112 extern int aio_worker_threads
;
113 extern int maxprocperuid
;
114 extern int maxfilesperproc
;
118 userland_sysctl(struct proc
*p
, int *name
, u_int namelen
, void *old
, size_t
119 *oldlenp
, int inkernel
, void *new, size_t newlen
, size_t *retval
);
122 sysctl_aiomax( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
124 sysctl_aioprocmax( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
126 sysctl_aiothreads( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
128 fill_proc(struct proc
*p
, struct kinfo_proc
*kp
);
130 sysctl_maxfilesperproc( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
132 sysctl_maxprocperuid( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
134 sysctl_maxproc( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
);
136 sysctl_procargs2( int *name
, u_int namelen
, char *where
, size_t *sizep
, struct proc
*cur_proc
);
138 sysctl_procargsx( int *name
, u_int namelen
, char *where
, size_t *sizep
, struct proc
*cur_proc
, int argc_yes
);
142 * temporary location for vm_sysctl. This should be machine independant
145 vm_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
154 extern uint32_t mach_factor
[3];
155 struct loadavg loadinfo
;
159 return (sysctl_struct(oldp
, oldlenp
, newp
, newlen
,
160 &averunnable
, sizeof(struct loadavg
)));
162 loadinfo
.ldavg
[0] = mach_factor
[0];
163 loadinfo
.ldavg
[1] = mach_factor
[1];
164 loadinfo
.ldavg
[2] = mach_factor
[2];
165 loadinfo
.fscale
= LSCALE
;
166 return (sysctl_struct(oldp
, oldlenp
, newp
, newlen
,
167 &loadinfo
, sizeof(struct loadavg
)));
182 static struct sysctl_lock
{
188 struct __sysctl_args
{
197 __sysctl(p
, uap
, retval
)
199 register struct __sysctl_args
*uap
;
202 int error
, dolock
= 1;
203 size_t savelen
, oldlen
= 0;
205 int name
[CTL_MAXNAME
];
210 * all top-level sysctl names are non-terminal
212 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
215 copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int)))
218 AUDIT_ARG(ctlname
, name
, uap
->namelen
);
220 /* CTL_UNSPEC is used to get oid to AUTO_OID */
222 && ((name
[0] == CTL_KERN
223 && !(name
[1] == KERN_IPC
|| name
[1] == KERN_PANICINFO
))
224 || (name
[0] == CTL_HW
)
225 || (name
[0] == CTL_VM
)
226 || (name
[0] == CTL_VFS
))
227 && (error
= suser(p
->p_ucred
, &p
->p_acflag
)))
233 if ((name
[1] != KERN_VNODE
) && (name
[1] != KERN_FILE
)
234 && (name
[1] != KERN_PROC
))
254 (error
= copyin(uap
->oldlenp
, &oldlen
, sizeof(oldlen
))))
257 if (uap
->old
!= NULL
) {
258 if (!useracc(uap
->old
, oldlen
, B_WRITE
))
261 /* The pc sampling mechanism does not need to take this lock */
262 if ((name
[1] != KERN_PCSAMPLES
) &&
263 (!((name
[1] == KERN_KDEBUG
) && (name
[2] == KERN_KDGETENTROPY
)))) {
264 while (memlock
.sl_lock
) {
266 sleep((caddr_t
)&memlock
, PRIBIO
+1);
272 if (dolock
&& oldlen
&& (error
= vslock(uap
->old
, oldlen
))) {
273 if ((name
[1] != KERN_PCSAMPLES
) &&
274 (! ((name
[1] == KERN_KDEBUG
) && (name
[2] == KERN_KDGETENTROPY
)))) {
276 if (memlock
.sl_want
) {
278 wakeup((caddr_t
)&memlock
);
287 error
= (*fn
)(name
+ 1, uap
->namelen
- 1, uap
->old
,
288 &oldlen
, uap
->new, uap
->newlen
, p
);
292 if ( (name
[0] != CTL_VFS
) && (error
== EOPNOTSUPP
))
293 error
= userland_sysctl(p
, name
, uap
->namelen
,
294 uap
->old
, uap
->oldlenp
, 0,
295 uap
->new, uap
->newlen
, &oldlen
);
297 if (uap
->old
!= NULL
) {
298 if (dolock
&& savelen
) {
299 error1
= vsunlock(uap
->old
, savelen
, B_WRITE
);
300 if (!error
&& error1
)
303 if (name
[1] != KERN_PCSAMPLES
) {
305 if (memlock
.sl_want
) {
307 wakeup((caddr_t
)&memlock
);
311 if ((error
) && (error
!= ENOMEM
))
315 i
= copyout(&oldlen
, uap
->oldlenp
, sizeof(oldlen
));
324 * Attributes stored in the kernel.
326 extern char hostname
[MAXHOSTNAMELEN
]; /* defined in bsd/kern/init_main.c */
327 extern int hostnamelen
;
328 extern char domainname
[MAXHOSTNAMELEN
];
329 extern int domainnamelen
;
330 extern char classichandler
[32];
331 extern long classichandler_fsid
;
332 extern long classichandler_fileid
;
333 __private_extern__
char corefilename
[MAXPATHLEN
+1];
334 __private_extern__ do_coredump
;
335 __private_extern__ sugid_coredump
;
340 int securelevel
= -1;
346 sysctl_affinity(name
, namelen
, oldBuf
, oldSize
, newBuf
, newSize
, cur_proc
)
353 struct proc
*cur_proc
;
358 if (name
[0] == 0 && 1 == namelen
) {
359 return sysctl_rdint(oldBuf
, oldSize
, newBuf
,
360 (cur_proc
->p_flag
& P_AFFINITY
) ? 1 : 0);
361 } else if (name
[0] == 1 && 2 == namelen
) {
363 cur_proc
->p_flag
&= ~P_AFFINITY
;
365 cur_proc
->p_flag
|= P_AFFINITY
;
373 sysctl_classic(name
, namelen
, oldBuf
, oldSize
, newBuf
, newSize
, cur_proc
)
380 struct proc
*cur_proc
;
393 if ((p
->p_ucred
->cr_uid
!= cur_proc
->p_ucred
->cr_uid
)
394 && suser(cur_proc
->p_ucred
, &cur_proc
->p_acflag
))
397 return sysctl_rdint(oldBuf
, oldSize
, newBuf
,
398 (p
->p_flag
& P_CLASSIC
) ? 1 : 0);
402 sysctl_classichandler(name
, namelen
, oldBuf
, oldSize
, newBuf
, newSize
, p
)
415 char handler
[sizeof(classichandler
)];
417 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)))
419 len
= strlen(classichandler
) + 1;
420 if (oldBuf
&& *oldSize
< len
)
422 if (newBuf
&& newSize
>= sizeof(classichandler
))
423 return (ENAMETOOLONG
);
426 error
= copyin(newBuf
, handler
, newSize
);
429 handler
[newSize
] = 0;
431 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_SYSSPACE
,
436 /* Check mount point */
437 if ((nd
.ni_vp
->v_mount
->mnt_flag
& MNT_NOEXEC
) ||
438 (nd
.ni_vp
->v_type
!= VREG
)) {
442 error
= VOP_GETATTR(nd
.ni_vp
, &vattr
, p
->p_ucred
, p
);
447 classichandler_fsid
= vattr
.va_fsid
;
448 classichandler_fileid
= vattr
.va_fileid
;
452 error
= copyout(classichandler
, oldBuf
, len
);
457 strcpy(classichandler
, handler
);
463 extern int get_kernel_symfile( struct proc
*, char **);
464 extern int sysctl_dopanicinfo(int *, u_int
, void *, size_t *,
465 void *, size_t, struct proc
*);
468 * kernel related system variables.
471 kern_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
480 int error
, level
, inthostid
, tmp
;
481 unsigned int oldval
=0;
483 extern char ostype
[], osrelease
[], version
[];
484 extern int netboot_root();
486 /* all sysctl names not listed below are terminal at this level */
488 && !(name
[0] == KERN_PROC
489 || name
[0] == KERN_PROF
490 || name
[0] == KERN_KDEBUG
491 || name
[0] == KERN_PROCARGS
492 || name
[0] == KERN_PROCARGS2
493 || name
[0] == KERN_PCSAMPLES
494 || name
[0] == KERN_IPC
495 || name
[0] == KERN_SYSV
496 || name
[0] == KERN_AFFINITY
497 || name
[0] == KERN_CLASSIC
498 || name
[0] == KERN_PANICINFO
)
500 return (ENOTDIR
); /* overloaded */
504 return (sysctl_rdstring(oldp
, oldlenp
, newp
, ostype
));
506 return (sysctl_rdstring(oldp
, oldlenp
, newp
, osrelease
));
508 return (sysctl_rdint(oldp
, oldlenp
, newp
, BSD
));
510 return (sysctl_rdstring(oldp
, oldlenp
, newp
, version
));
512 oldval
= desiredvnodes
;
513 error
= sysctl_int(oldp
, oldlenp
, newp
,
514 newlen
, &desiredvnodes
);
515 reset_vmobjectcache(oldval
, desiredvnodes
);
516 resize_namecache(desiredvnodes
);
519 return (sysctl_maxproc(oldp
, oldlenp
, newp
, newlen
));
521 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxfiles
));
522 case KERN_MAXPROCPERUID
:
523 return( sysctl_maxprocperuid( oldp
, oldlenp
, newp
, newlen
) );
524 case KERN_MAXFILESPERPROC
:
525 return( sysctl_maxfilesperproc( oldp
, oldlenp
, newp
, newlen
) );
527 return (sysctl_rdint(oldp
, oldlenp
, newp
, ARG_MAX
));
530 if ((error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &level
)) ||
533 if (level
< securelevel
&& p
->p_pid
!= 1)
538 error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
539 hostname
, sizeof(hostname
));
541 hostnamelen
= newlen
;
543 case KERN_DOMAINNAME
:
544 error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
545 domainname
, sizeof(domainname
));
547 domainnamelen
= newlen
;
550 inthostid
= hostid
; /* XXX assumes sizeof long <= sizeof int */
551 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &inthostid
);
555 return (sysctl_clockrate(oldp
, oldlenp
));
557 return (sysctl_rdstruct(oldp
, oldlenp
, newp
, &boottime
,
558 sizeof(struct timeval
)));
560 return (sysctl_vnode(oldp
, oldlenp
));
562 return (sysctl_doproc(name
+ 1, namelen
- 1, oldp
, oldlenp
));
564 return (sysctl_file(oldp
, oldlenp
));
567 return (sysctl_doprof(name
+ 1, namelen
- 1, oldp
, oldlenp
,
571 return (sysctl_rdint(oldp
, oldlenp
, newp
, _POSIX_VERSION
));
573 return (sysctl_rdint(oldp
, oldlenp
, newp
, NGROUPS_MAX
));
574 case KERN_JOB_CONTROL
:
575 return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
577 #ifdef _POSIX_SAVED_IDS
578 return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
580 return (sysctl_rdint(oldp
, oldlenp
, newp
, 0));
583 return (kdebug_ops(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
585 return (pcsamples_ops(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
587 /* new one as it does not use kinfo_proc */
588 return (sysctl_procargs(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
590 /* new one as it does not use kinfo_proc */
591 return (sysctl_procargs2(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
593 error
= get_kernel_symfile( p
, &str
);
596 return (sysctl_rdstring(oldp
, oldlenp
, newp
, str
));
598 return (sysctl_rdint(oldp
, oldlenp
, newp
, netboot_root()));
600 return(sysctl_dopanicinfo(name
+ 1, namelen
- 1, oldp
, oldlenp
,
603 return sysctl_affinity(name
+1, namelen
-1, oldp
, oldlenp
,
606 return sysctl_classic(name
+1, namelen
-1, oldp
, oldlenp
,
608 case KERN_CLASSICHANDLER
:
609 return sysctl_classichandler(name
+1, namelen
-1, oldp
, oldlenp
,
612 return( sysctl_aiomax( oldp
, oldlenp
, newp
, newlen
) );
613 case KERN_AIOPROCMAX
:
614 return( sysctl_aioprocmax( oldp
, oldlenp
, newp
, newlen
) );
615 case KERN_AIOTHREADS
:
616 return( sysctl_aiothreads( oldp
, oldlenp
, newp
, newlen
) );
618 error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
619 corefilename
, sizeof(corefilename
));
623 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &do_coredump
);
624 if (!error
&& (do_coredump
< 0) || (do_coredump
> 1)) {
629 case KERN_SUGID_COREDUMP
:
630 tmp
= sugid_coredump
;
631 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &sugid_coredump
);
632 if (!error
&& (sugid_coredump
< 0) || (sugid_coredump
> 1)) {
633 sugid_coredump
= tmp
;
645 * Debugging related system variables.
649 #endif /* DIAGNOSTIC */
650 struct ctldebug debug0
, debug1
;
651 struct ctldebug debug2
, debug3
, debug4
;
652 struct ctldebug debug5
, debug6
, debug7
, debug8
, debug9
;
653 struct ctldebug debug10
, debug11
, debug12
, debug13
, debug14
;
654 struct ctldebug debug15
, debug16
, debug17
, debug18
, debug19
;
655 static struct ctldebug
*debugvars
[CTL_DEBUG_MAXID
] = {
656 &debug0
, &debug1
, &debug2
, &debug3
, &debug4
,
657 &debug5
, &debug6
, &debug7
, &debug8
, &debug9
,
658 &debug10
, &debug11
, &debug12
, &debug13
, &debug14
,
659 &debug15
, &debug16
, &debug17
, &debug18
, &debug19
,
662 debug_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
671 struct ctldebug
*cdp
;
673 /* all sysctl names at this level are name and field */
675 return (ENOTDIR
); /* overloaded */
676 cdp
= debugvars
[name
[0]];
677 if (cdp
->debugname
== 0)
681 return (sysctl_rdstring(oldp
, oldlenp
, newp
, cdp
->debugname
));
682 case CTL_DEBUG_VALUE
:
683 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, cdp
->debugvar
));
692 * Validate parameters and get old / set new parameters
693 * for an integer-valued sysctl function.
696 sysctl_int(oldp
, oldlenp
, newp
, newlen
, valp
)
705 if (oldp
&& *oldlenp
< sizeof(int))
707 if (newp
&& newlen
!= sizeof(int))
709 *oldlenp
= sizeof(int);
711 error
= copyout(valp
, oldp
, sizeof(int));
712 if (error
== 0 && newp
) {
713 error
= copyin(newp
, valp
, sizeof(int));
714 AUDIT_ARG(value
, *valp
);
720 * As above, but read-only.
723 sysctl_rdint(oldp
, oldlenp
, newp
, val
)
731 if (oldp
&& *oldlenp
< sizeof(int))
735 *oldlenp
= sizeof(int);
737 error
= copyout((caddr_t
)&val
, oldp
, sizeof(int));
742 * Validate parameters and get old / set new parameters
743 * for an quad(64bit)-valued sysctl function.
746 sysctl_quad(oldp
, oldlenp
, newp
, newlen
, valp
)
755 if (oldp
&& *oldlenp
< sizeof(quad_t
))
757 if (newp
&& newlen
!= sizeof(quad_t
))
759 *oldlenp
= sizeof(quad_t
);
761 error
= copyout(valp
, oldp
, sizeof(quad_t
));
762 if (error
== 0 && newp
)
763 error
= copyin(newp
, valp
, sizeof(quad_t
));
768 * As above, but read-only.
771 sysctl_rdquad(oldp
, oldlenp
, newp
, val
)
779 if (oldp
&& *oldlenp
< sizeof(quad_t
))
783 *oldlenp
= sizeof(quad_t
);
785 error
= copyout((caddr_t
)&val
, oldp
, sizeof(quad_t
));
790 * Validate parameters and get old / set new parameters
791 * for a string-valued sysctl function.
794 sysctl_string(oldp
, oldlenp
, newp
, newlen
, str
, maxlen
)
804 len
= strlen(str
) + 1;
805 if (oldp
&& *oldlenp
< len
)
807 if (newp
&& newlen
>= maxlen
)
809 *oldlenp
= len
-1; /* deal with NULL strings correctly */
811 error
= copyout(str
, oldp
, len
);
813 if (error
== 0 && newp
) {
814 error
= copyin(newp
, str
, newlen
);
816 AUDIT_ARG(text
, (char *)str
);
822 * As above, but read-only.
825 sysctl_rdstring(oldp
, oldlenp
, newp
, str
)
833 len
= strlen(str
) + 1;
834 if (oldp
&& *oldlenp
< len
)
840 error
= copyout(str
, oldp
, len
);
845 * Validate parameters and get old / set new parameters
846 * for a structure oriented sysctl function.
849 sysctl_struct(oldp
, oldlenp
, newp
, newlen
, sp
, len
)
859 if (oldp
&& *oldlenp
< len
)
861 if (newp
&& newlen
> len
)
865 error
= copyout(sp
, oldp
, len
);
867 if (error
== 0 && newp
)
868 error
= copyin(newp
, sp
, len
);
873 * Validate parameters and get old parameters
874 * for a structure oriented sysctl function.
877 sysctl_rdstruct(oldp
, oldlenp
, newp
, sp
, len
)
885 if (oldp
&& *oldlenp
< len
)
891 error
= copyout(sp
, oldp
, len
);
896 * Get file structures.
899 sysctl_file(where
, sizep
)
910 * overestimate by 10 files
912 *sizep
= sizeof(filehead
) + (nfiles
+ 10) * sizeof(struct file
);
917 * first copyout filehead
919 if (buflen
< sizeof(filehead
)) {
923 if (error
= copyout((caddr_t
)&filehead
, where
, sizeof(filehead
)))
925 buflen
-= sizeof(filehead
);
926 where
+= sizeof(filehead
);
929 * followed by an array of file structures
931 for (fp
= filehead
.lh_first
; fp
!= 0; fp
= fp
->f_list
.le_next
) {
932 if (buflen
< sizeof(struct file
)) {
933 *sizep
= where
- start
;
936 if (error
= copyout((caddr_t
)fp
, where
, sizeof (struct file
)))
938 buflen
-= sizeof(struct file
);
939 where
+= sizeof(struct file
);
941 *sizep
= where
- start
;
946 * try over estimating by 5 procs
948 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
951 sysctl_doproc(name
, namelen
, where
, sizep
)
957 register struct proc
*p
;
958 register struct kinfo_proc
*dp
= (struct kinfo_proc
*)where
;
959 register int needed
= 0;
960 int buflen
= where
!= NULL
? *sizep
: 0;
962 struct kinfo_proc kproc
;
965 if (namelen
!= 2 && !(namelen
== 1 && name
[0] == KERN_PROC_ALL
))
967 p
= allproc
.lh_first
;
970 for (; p
!= 0; p
= p
->p_list
.le_next
) {
972 * Skip embryonic processes.
974 if (p
->p_stat
== SIDL
)
977 * TODO - make more efficient (see notes below).
983 /* could do this with just a lookup */
984 if (p
->p_pid
!= (pid_t
)name
[1])
989 /* could do this by traversing pgrp */
990 if (p
->p_pgrp
->pg_id
!= (pid_t
)name
[1])
995 if ((p
->p_flag
& P_CONTROLT
) == 0 ||
996 (p
->p_session
== NULL
) ||
997 p
->p_session
->s_ttyp
== NULL
||
998 p
->p_session
->s_ttyp
->t_dev
!= (dev_t
)name
[1])
1003 if ((p
->p_ucred
== NULL
) ||
1004 (p
->p_ucred
->cr_uid
!= (uid_t
)name
[1]))
1008 case KERN_PROC_RUID
:
1009 if ((p
->p_ucred
== NULL
) ||
1010 (p
->p_cred
->p_ruid
!= (uid_t
)name
[1]))
1014 if (buflen
>= sizeof(struct kinfo_proc
)) {
1015 bzero(&kproc
, sizeof(struct kinfo_proc
));
1016 fill_proc(p
, &kproc
);
1017 if (error
= copyout((caddr_t
)&kproc
, &dp
->kp_proc
,
1018 sizeof(struct kinfo_proc
)))
1021 buflen
-= sizeof(struct kinfo_proc
);
1023 needed
+= sizeof(struct kinfo_proc
);
1025 if (doingzomb
== 0) {
1026 p
= zombproc
.lh_first
;
1030 if (where
!= NULL
) {
1031 *sizep
= (caddr_t
)dp
- where
;
1032 if (needed
> *sizep
)
1035 needed
+= KERN_PROCSLOP
;
1042 * Fill in an eproc structure for the specified process.
1046 register struct proc
*p
;
1047 register struct eproc
*ep
;
1049 register struct tty
*tp
;
1053 ep
->e_sess
= p
->p_pgrp
->pg_session
;
1054 ep
->e_pgid
= p
->p_pgrp
->pg_id
;
1055 ep
->e_jobc
= p
->p_pgrp
->pg_jobc
;
1056 if (ep
->e_sess
&& ep
->e_sess
->s_ttyvp
)
1057 ep
->e_flag
= EPROC_CTTY
;
1059 ep
->e_sess
= (struct session
*)0;
1063 ep
->e_ppid
= (p
->p_pptr
) ? p
->p_pptr
->p_pid
: 0;
1065 ep
->e_pcred
= *p
->p_cred
;
1067 ep
->e_ucred
= *p
->p_ucred
;
1069 if (p
->p_stat
== SIDL
|| p
->p_stat
== SZOMB
) {
1070 ep
->e_vm
.vm_tsize
= 0;
1071 ep
->e_vm
.vm_dsize
= 0;
1072 ep
->e_vm
.vm_ssize
= 0;
1074 ep
->e_vm
.vm_rssize
= 0;
1076 if ((p
->p_flag
& P_CONTROLT
) && (ep
->e_sess
) &&
1077 (tp
= ep
->e_sess
->s_ttyp
)) {
1078 ep
->e_tdev
= tp
->t_dev
;
1079 ep
->e_tpgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: NO_PID
;
1080 ep
->e_tsess
= tp
->t_session
;
1085 ep
->e_flag
|= EPROC_SLEADER
;
1087 strncpy(ep
->e_wmesg
, p
->p_wmesg
, WMESGLEN
);
1088 ep
->e_xsize
= ep
->e_xrssize
= 0;
1089 ep
->e_xccount
= ep
->e_xswrss
= 0;
1093 * Fill in an eproc structure for the specified process.
1096 fill_externproc(p
, exp
)
1097 register struct proc
*p
;
1098 register struct extern_proc
*exp
;
1100 exp
->p_forw
= exp
->p_back
= NULL
;
1102 exp
->p_starttime
= p
->p_stats
->p_start
;
1103 exp
->p_vmspace
= NULL
;
1104 exp
->p_sigacts
= p
->p_sigacts
;
1105 exp
->p_flag
= p
->p_flag
;
1106 exp
->p_stat
= p
->p_stat
;
1107 exp
->p_pid
= p
->p_pid
;
1108 exp
->p_oppid
= p
->p_oppid
;
1109 exp
->p_dupfd
= p
->p_dupfd
;
1111 exp
->user_stack
= p
->user_stack
;
1112 exp
->exit_thread
= p
->exit_thread
;
1113 exp
->p_debugger
= p
->p_debugger
;
1114 exp
->sigwait
= p
->sigwait
;
1116 exp
->p_estcpu
= p
->p_estcpu
;
1117 exp
->p_cpticks
= p
->p_cpticks
;
1118 exp
->p_pctcpu
= p
->p_pctcpu
;
1119 exp
->p_wchan
= p
->p_wchan
;
1120 exp
->p_wmesg
= p
->p_wmesg
;
1121 exp
->p_swtime
= p
->p_swtime
;
1122 exp
->p_slptime
= p
->p_slptime
;
1123 bcopy(&p
->p_realtimer
, &exp
->p_realtimer
,sizeof(struct itimerval
));
1124 bcopy(&p
->p_rtime
, &exp
->p_rtime
,sizeof(struct timeval
));
1125 exp
->p_uticks
= p
->p_uticks
;
1126 exp
->p_sticks
= p
->p_sticks
;
1127 exp
->p_iticks
= p
->p_iticks
;
1128 exp
->p_traceflag
= p
->p_traceflag
;
1129 exp
->p_tracep
= p
->p_tracep
;
1130 exp
->p_siglist
= 0 ; /* No longer relevant */
1131 exp
->p_textvp
= p
->p_textvp
;
1132 exp
->p_holdcnt
= 0 ;
1133 exp
->p_sigmask
= 0 ; /* no longer avaialable */
1134 exp
->p_sigignore
= p
->p_sigignore
;
1135 exp
->p_sigcatch
= p
->p_sigcatch
;
1136 exp
->p_priority
= p
->p_priority
;
1137 exp
->p_usrpri
= p
->p_usrpri
;
1138 exp
->p_nice
= p
->p_nice
;
1139 bcopy(&p
->p_comm
, &exp
->p_comm
,MAXCOMLEN
);
1140 exp
->p_comm
[MAXCOMLEN
] = '\0';
1141 exp
->p_pgrp
= p
->p_pgrp
;
1143 exp
->p_xstat
= p
->p_xstat
;
1144 exp
->p_acflag
= p
->p_acflag
;
1145 exp
->p_ru
= p
->p_ru
;
1150 register struct proc
*p
;
1151 register struct kinfo_proc
*kp
;
1153 fill_externproc(p
, &kp
->kp_proc
);
1154 fill_eproc(p
, &kp
->kp_eproc
);
1158 kdebug_ops(name
, namelen
, where
, sizep
, p
)
1167 extern int kdbg_control(int *name
, u_int namelen
,
1168 char * where
,size_t * sizep
);
1170 if (ret
= suser(p
->p_ucred
, &p
->p_acflag
))
1186 case KERN_KDSETRTCDEC
:
1188 case KERN_KDGETENTROPY
:
1189 ret
= kdbg_control(name
, namelen
, where
, sizep
);
1199 pcsamples_ops(name
, namelen
, where
, sizep
, p
)
1207 extern int pcsamples_control(int *name
, u_int namelen
,
1208 char * where
,size_t * sizep
);
1210 if (ret
= suser(p
->p_ucred
, &p
->p_acflag
))
1214 case KERN_PCDISABLE
:
1218 case KERN_PCREADBUF
:
1222 ret
= pcsamples_control(name
, namelen
, where
, sizep
);
1232 * Return the top *sizep bytes of the user stack, or the entire area of the
1233 * user stack down through the saved exec_path, whichever is smaller.
1236 sysctl_procargs(name
, namelen
, where
, sizep
, cur_proc
)
1241 struct proc
*cur_proc
;
1243 return sysctl_procargsx( name
, namelen
, where
, sizep
, cur_proc
, 0);
1247 sysctl_procargs2(name
, namelen
, where
, sizep
, cur_proc
)
1252 struct proc
*cur_proc
;
1254 return sysctl_procargsx( name
, namelen
, where
, sizep
, cur_proc
, 1);
1258 sysctl_procargsx(name
, namelen
, where
, sizep
, cur_proc
, argc_yes
)
1263 struct proc
*cur_proc
;
1266 register struct proc
*p
;
1267 register int needed
= 0;
1268 int buflen
= where
!= NULL
? *sizep
: 0;
1270 struct vm_map
*proc_map
;
1273 vm_offset_t arg_addr
;
1277 vm_offset_t copy_start
, copy_end
;
1283 buflen
-= NBPW
; /* reserve first word to return argc */
1285 if ((buflen
<= 0) || (buflen
> ARG_MAX
)) {
1291 * Lookup process by pid
1302 * Copy the top N bytes of the stack.
1303 * On all machines we have so far, the stack grows
1306 * If the user expects no more than N bytes of
1307 * argument list, use that as a guess for the
1314 if ((p
->p_ucred
->cr_uid
!= cur_proc
->p_ucred
->cr_uid
)
1315 && suser(cur_proc
->p_ucred
, &cur_proc
->p_acflag
))
1317 arg_addr
= (vm_offset_t
)(p
->user_stack
- arg_size
);
1321 * Before we can block (any VM code), make another
1322 * reference to the map to keep it alive. We do
1323 * that by getting a reference on the task itself.
1330 * A regular task_reference call can block, causing the funnel
1331 * to be dropped and allowing the proc/task to get freed.
1332 * Instead, we issue a non-blocking attempt at the task reference,
1333 * and look up the proc/task all over again if that fails.
1335 if (!task_reference_try(task
)) {
1340 ret
= kmem_alloc(kernel_map
, ©_start
, round_page_32(arg_size
));
1341 if (ret
!= KERN_SUCCESS
) {
1342 task_deallocate(task
);
1346 proc_map
= get_task_map(task
);
1347 copy_end
= round_page_32(copy_start
+ arg_size
);
1349 if( vm_map_copyin(proc_map
, trunc_page(arg_addr
), round_page_32(arg_size
),
1350 FALSE
, &tmp
) != KERN_SUCCESS
) {
1351 task_deallocate(task
);
1352 kmem_free(kernel_map
, copy_start
,
1353 round_page_32(arg_size
));
1358 * Now that we've done the copyin from the process'
1359 * map, we can release the reference to it.
1361 task_deallocate(task
);
1363 if( vm_map_copy_overwrite(kernel_map
, copy_start
,
1364 tmp
, FALSE
) != KERN_SUCCESS
) {
1365 kmem_free(kernel_map
, copy_start
,
1366 round_page_32(arg_size
));
1370 data
= (caddr_t
) (copy_end
- arg_size
);
1372 if (buflen
> p
->p_argslen
) {
1373 data
= &data
[buflen
- p
->p_argslen
];
1374 size
= p
->p_argslen
;
1380 /* Put processes argc as the first word in the copyout buffer */
1381 suword(where
, p
->p_argc
);
1382 error
= copyout(data
, where
+ NBPW
, size
);
1384 error
= copyout(data
, where
, size
);
1387 * Make the old PROCARGS work to return the executable's path
1388 * But, only if there is enough space in the provided buffer
1390 * on entry: data [possibily] points to the beginning of the path
1392 * Note: we keep all pointers&sizes aligned to word boundries
1395 if ( (! error
) && (buflen
> p
->p_argslen
) )
1398 int extraSpaceNeeded
, addThis
;
1400 char * str
= (char *) data
;
1401 unsigned int max_len
= size
;
1403 /* Some apps are really bad about messing up their stacks
1404 So, we have to be extra careful about getting the length
1405 of the executing binary. If we encounter an error, we bail.
1408 /* Limit ourselves to PATH_MAX paths */
1409 if ( max_len
> PATH_MAX
) max_len
= PATH_MAX
;
1413 while ( (binPath_sz
< max_len
-1) && (*str
++ != 0) )
1416 if (binPath_sz
< max_len
-1) binPath_sz
+= 1;
1418 /* Pre-Flight the space requiremnts */
1420 /* Account for the padding that fills out binPath to the next word */
1421 binPath_sz
+= (binPath_sz
& (NBPW
-1)) ? (NBPW
-(binPath_sz
& (NBPW
-1))) : 0;
1423 placeHere
= where
+ size
;
1425 /* Account for the bytes needed to keep placeHere word aligned */
1426 addThis
= ((unsigned long)placeHere
& (NBPW
-1)) ? (NBPW
-((unsigned long)placeHere
& (NBPW
-1))) : 0;
1428 /* Add up all the space that is needed */
1429 extraSpaceNeeded
= binPath_sz
+ addThis
+ (4 * NBPW
);
1431 /* is there is room to tack on argv[0]? */
1432 if ( (buflen
& ~(NBPW
-1)) >= ( p
->p_argslen
+ extraSpaceNeeded
))
1434 placeHere
+= addThis
;
1435 suword(placeHere
, 0);
1437 suword(placeHere
, 0xBFFF0000);
1439 suword(placeHere
, 0);
1441 error
= copyout(data
, placeHere
, binPath_sz
);
1444 placeHere
+= binPath_sz
;
1445 suword(placeHere
, 0);
1446 size
+= extraSpaceNeeded
;
1452 if (copy_start
!= (vm_offset_t
) 0) {
1453 kmem_free(kernel_map
, copy_start
, copy_end
- copy_start
);
1466 * Validate parameters and get old / set new parameters
1467 * for max number of concurrent aio requests. Makes sure
1468 * the system wide limit is greater than the per process
1472 sysctl_aiomax( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1477 if ( oldp
&& *oldlenp
< sizeof(int) )
1479 if ( newp
&& newlen
!= sizeof(int) )
1482 *oldlenp
= sizeof(int);
1484 error
= copyout( &aio_max_requests
, oldp
, sizeof(int) );
1485 if ( error
== 0 && newp
)
1486 error
= copyin( newp
, &new_value
, sizeof(int) );
1487 if ( error
== 0 && newp
) {
1488 if ( new_value
>= aio_max_requests_per_process
)
1489 aio_max_requests
= new_value
;
1495 } /* sysctl_aiomax */
1499 * Validate parameters and get old / set new parameters
1500 * for max number of concurrent aio requests per process.
1501 * Makes sure per process limit is less than the system wide
1505 sysctl_aioprocmax( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1510 if ( oldp
&& *oldlenp
< sizeof(int) )
1512 if ( newp
&& newlen
!= sizeof(int) )
1515 *oldlenp
= sizeof(int);
1517 error
= copyout( &aio_max_requests_per_process
, oldp
, sizeof(int) );
1518 if ( error
== 0 && newp
)
1519 error
= copyin( newp
, &new_value
, sizeof(int) );
1520 if ( error
== 0 && newp
) {
1521 if ( new_value
<= aio_max_requests
&& new_value
>= AIO_LISTIO_MAX
)
1522 aio_max_requests_per_process
= new_value
;
1528 } /* sysctl_aioprocmax */
1532 * Validate parameters and get old / set new parameters
1533 * for max number of async IO worker threads.
1534 * We only allow an increase in the number of worker threads.
1537 sysctl_aiothreads( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1542 if ( oldp
&& *oldlenp
< sizeof(int) )
1544 if ( newp
&& newlen
!= sizeof(int) )
1547 *oldlenp
= sizeof(int);
1549 error
= copyout( &aio_worker_threads
, oldp
, sizeof(int) );
1550 if ( error
== 0 && newp
)
1551 error
= copyin( newp
, &new_value
, sizeof(int) );
1552 if ( error
== 0 && newp
) {
1553 if (new_value
> aio_worker_threads
) {
1554 _aio_create_worker_threads( (new_value
- aio_worker_threads
) );
1555 aio_worker_threads
= new_value
;
1562 } /* sysctl_aiothreads */
1566 * Validate parameters and get old / set new parameters
1567 * for max number of processes per UID.
1568 * Makes sure per UID limit is less than the system wide limit.
1571 sysctl_maxprocperuid( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1576 if ( oldp
!= NULL
&& *oldlenp
< sizeof(int) )
1578 if ( newp
!= NULL
&& newlen
!= sizeof(int) )
1581 *oldlenp
= sizeof(int);
1583 error
= copyout( &maxprocperuid
, oldp
, sizeof(int) );
1584 if ( error
== 0 && newp
!= NULL
) {
1585 error
= copyin( newp
, &new_value
, sizeof(int) );
1587 AUDIT_ARG(value
, new_value
);
1588 if ( new_value
<= maxproc
&& new_value
> 0 )
1589 maxprocperuid
= new_value
;
1598 } /* sysctl_maxprocperuid */
1602 * Validate parameters and get old / set new parameters
1603 * for max number of files per process.
1604 * Makes sure per process limit is less than the system-wide limit.
1607 sysctl_maxfilesperproc( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1612 if ( oldp
!= NULL
&& *oldlenp
< sizeof(int) )
1614 if ( newp
!= NULL
&& newlen
!= sizeof(int) )
1617 *oldlenp
= sizeof(int);
1619 error
= copyout( &maxfilesperproc
, oldp
, sizeof(int) );
1620 if ( error
== 0 && newp
!= NULL
) {
1621 error
= copyin( newp
, &new_value
, sizeof(int) );
1623 AUDIT_ARG(value
, new_value
);
1624 if ( new_value
< maxfiles
&& new_value
> 0 )
1625 maxfilesperproc
= new_value
;
1634 } /* sysctl_maxfilesperproc */
1638 * Validate parameters and get old / set new parameters
1639 * for the system-wide limit on the max number of processes.
1640 * Makes sure the system-wide limit is less than the configured hard
1641 * limit set at kernel compilation.
1644 sysctl_maxproc( void *oldp
, size_t *oldlenp
, void *newp
, size_t newlen
)
1649 if ( oldp
!= NULL
&& *oldlenp
< sizeof(int) )
1651 if ( newp
!= NULL
&& newlen
!= sizeof(int) )
1654 *oldlenp
= sizeof(int);
1656 error
= copyout( &maxproc
, oldp
, sizeof(int) );
1657 if ( error
== 0 && newp
!= NULL
) {
1658 error
= copyin( newp
, &new_value
, sizeof(int) );
1660 AUDIT_ARG(value
, new_value
);
1661 if ( new_value
<= hard_maxproc
&& new_value
> 0 )
1662 maxproc
= new_value
;
1671 } /* sysctl_maxproc */