2 * Copyright (c) 2000-2002 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>
76 #include <sys/disklabel.h>
78 #include <sys/sysctl.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>
87 extern vm_map_t bsd_pageable_map
;
89 #include <sys/mount.h>
90 #include <sys/kdebug.h>
92 #include <IOKit/IOPlatformExpert.h>
93 #include <pexpert/pexpert.h>
96 #include <ppc/machine_routines.h>
102 sysctlfn debug_sysctl
;
104 extern sysctlfn vm_sysctl
;
105 extern sysctlfn vfs_sysctl
;
106 extern sysctlfn net_sysctl
;
107 extern sysctlfn cpu_sysctl
;
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
);
115 fill_proc(struct proc
*p
,struct kinfo_proc
*kp
, int doingzomb
);
118 fill_externproc(struct proc
*p
, struct extern_proc
*exp
);
123 * temporary location for vm_sysctl. This should be machine independant
126 vm_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
135 extern uint32_t mach_factor
[3];
136 struct loadavg loadinfo
;
140 return (sysctl_struct(oldp
, oldlenp
, newp
, newlen
,
141 &averunnable
, sizeof(struct loadavg
)));
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
)));
163 static struct sysctl_lock
{
169 struct __sysctl_args
{
178 __sysctl(p
, uap
, retval
)
180 register struct __sysctl_args
*uap
;
183 int error
, dolock
= 1;
184 size_t savelen
, oldlen
= 0;
186 int name
[CTL_MAXNAME
];
191 * all top-level sysctl names are non-terminal
193 if (uap
->namelen
> CTL_MAXNAME
|| uap
->namelen
< 2)
196 copyin(uap
->name
, &name
, uap
->namelen
* sizeof(int)))
199 /* CTL_UNSPEC is used to get oid to AUTO_OID */
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
)))
212 if ((name
[1] != KERN_VNODE
) && (name
[1] != KERN_FILE
)
213 && (name
[1] != KERN_PROC
))
236 (error
= copyin(uap
->oldlenp
, &oldlen
, sizeof(oldlen
))))
239 if (uap
->old
!= NULL
) {
240 if (!useracc(uap
->old
, oldlen
, B_WRITE
))
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
) {
248 sleep((caddr_t
)&memlock
, PRIBIO
+1);
254 if (dolock
&& oldlen
&& (error
= vslock(uap
->old
, oldlen
))) {
255 if ((name
[1] != KERN_PCSAMPLES
) &&
256 (! ((name
[1] == KERN_KDEBUG
) && (name
[2] == KERN_KDGETENTROPY
)))) {
258 if (memlock
.sl_want
) {
260 wakeup((caddr_t
)&memlock
);
269 error
= (*fn
)(name
+ 1, uap
->namelen
- 1, uap
->old
,
270 &oldlen
, uap
->new, uap
->newlen
, p
);
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
);
279 if (uap
->old
!= NULL
) {
280 if (dolock
&& savelen
) {
281 error1
= vsunlock(uap
->old
, savelen
, B_WRITE
);
282 if (!error
&& error1
)
285 if (name
[1] != KERN_PCSAMPLES
) {
287 if (memlock
.sl_want
) {
289 wakeup((caddr_t
)&memlock
);
293 if ((error
) && (error
!= ENOMEM
))
297 i
= copyout(&oldlen
, uap
->oldlenp
, sizeof(oldlen
));
306 * Attributes stored in the kernel.
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
;
314 int securelevel
= -1;
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
*);
324 * kernel related system variables.
327 kern_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
336 int error
, level
, inthostid
;
337 unsigned int oldval
=0;
339 extern char ostype
[], osrelease
[], version
[];
340 extern int netboot_root();
342 /* all sysctl names not listed below are terminal at this level */
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
)
353 return (ENOTDIR
); /* overloaded */
357 return (sysctl_rdstring(oldp
, oldlenp
, newp
, ostype
));
359 return (sysctl_rdstring(oldp
, oldlenp
, newp
, osrelease
));
361 return (sysctl_rdint(oldp
, oldlenp
, newp
, BSD
));
363 return (sysctl_rdstring(oldp
, oldlenp
, newp
, version
));
365 oldval
= desiredvnodes
;
366 error
= sysctl_int(oldp
, oldlenp
, newp
,
367 newlen
, &desiredvnodes
);
368 reset_vmobjectcache(oldval
, desiredvnodes
);
371 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxproc
));
373 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, &maxfiles
));
375 return (sysctl_rdint(oldp
, oldlenp
, newp
, ARG_MAX
));
378 if ((error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &level
)) ||
381 if (level
< securelevel
&& p
->p_pid
!= 1)
386 error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
387 hostname
, sizeof(hostname
));
389 hostnamelen
= newlen
;
391 case KERN_DOMAINNAME
:
392 error
= sysctl_string(oldp
, oldlenp
, newp
, newlen
,
393 domainname
, sizeof(domainname
));
395 domainnamelen
= newlen
;
398 inthostid
= hostid
; /* XXX assumes sizeof long <= sizeof int */
399 error
= sysctl_int(oldp
, oldlenp
, newp
, newlen
, &inthostid
);
403 return (sysctl_clockrate(oldp
, oldlenp
));
405 return (sysctl_rdstruct(oldp
, oldlenp
, newp
, &boottime
,
406 sizeof(struct timeval
)));
408 return (sysctl_vnode(oldp
, oldlenp
));
410 return (sysctl_doproc(name
+ 1, namelen
- 1, oldp
, oldlenp
));
412 return (sysctl_file(oldp
, oldlenp
));
415 return (sysctl_doprof(name
+ 1, namelen
- 1, oldp
, oldlenp
,
419 return (sysctl_rdint(oldp
, oldlenp
, newp
, _POSIX_VERSION
));
421 return (sysctl_rdint(oldp
, oldlenp
, newp
, NGROUPS_MAX
));
422 case KERN_JOB_CONTROL
:
423 return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
425 #ifdef _POSIX_SAVED_IDS
426 return (sysctl_rdint(oldp
, oldlenp
, newp
, 1));
428 return (sysctl_rdint(oldp
, oldlenp
, newp
, 0));
431 return (kdebug_ops(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
433 return (pcsamples_ops(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
435 /* new one as it does not use kinfo_proc */
436 return (sysctl_procargs(name
+ 1, namelen
- 1, oldp
, oldlenp
, p
));
438 error
= get_kernel_symfile( p
, &str
);
441 return (sysctl_rdstring(oldp
, oldlenp
, newp
, str
));
443 return (sysctl_rdint(oldp
, oldlenp
, newp
, netboot_root()));
445 return(sysctl_dopanicinfo(name
+ 1, namelen
- 1, oldp
, oldlenp
,
454 * hardware related system variables.
456 hw_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
467 extern int vm_page_wire_count
;
469 ml_ppc_cpu_info_t cpu_info
;
471 ml_ppc_get_info(&cpu_info
);
474 /* all sysctl names at this level are terminal */
476 return (ENOTDIR
); /* overloaded */
480 if(!PEGetMachineName(dummy
,64))
482 return (sysctl_rdstring(oldp
, oldlenp
, newp
, dummy
));
484 if(!PEGetModelName(dummy
,64))
486 return (sysctl_rdstring(oldp
, oldlenp
, newp
, dummy
));
490 host_basic_info_data_t hinfo
;
492 int count
= HOST_BASIC_INFO_COUNT
;
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
));
504 return (sysctl_rdint(oldp
, oldlenp
, newp
, BYTE_ORDER
));
506 return (sysctl_rdint(oldp
, oldlenp
, newp
, mem_size
));
508 return (sysctl_rdint(oldp
, oldlenp
, newp
,
509 (mem_size
- vm_page_wire_count
* page_size
)));
511 return (sysctl_rdint(oldp
, oldlenp
, newp
, page_size
));
513 epochTemp
= PEGetPlatformEpoch();
514 if (epochTemp
== -1) return(EINVAL
);
515 return (sysctl_rdint(oldp
, oldlenp
, newp
, epochTemp
));
517 return (sysctl_rdint(oldp
, oldlenp
, newp
, gPEClockFrequencyInfo
.bus_clock_rate_hz
));
519 return (sysctl_rdint(oldp
, oldlenp
, newp
, gPEClockFrequencyInfo
.cpu_clock_rate_hz
));
522 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.vector_unit
));
524 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.cache_line_size
));
525 case HW_L1ICACHESIZE
:
526 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l1_icache_size
));
527 case HW_L1DCACHESIZE
:
528 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l1_dcache_size
));
530 if (cpu_info
.l2_cache_size
== 0xFFFFFFFF) return(EINVAL
);
531 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l2_settings
));
533 if (cpu_info
.l2_cache_size
== 0xFFFFFFFF) return(EINVAL
);
534 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l2_cache_size
));
536 if (cpu_info
.l3_cache_size
== 0xFFFFFFFF) return(EINVAL
);
537 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l3_settings
));
539 if (cpu_info
.l3_cache_size
== 0xFFFFFFFF) return(EINVAL
);
540 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l3_cache_size
));
549 * Debugging related system variables.
553 #endif /* DIAGNOSTIC */
554 struct ctldebug debug0
, debug1
;
555 struct ctldebug debug2
, debug3
, debug4
;
556 struct ctldebug debug5
, debug6
, debug7
, debug8
, debug9
;
557 struct ctldebug debug10
, debug11
, debug12
, debug13
, debug14
;
558 struct ctldebug debug15
, debug16
, debug17
, debug18
, debug19
;
559 static struct ctldebug
*debugvars
[CTL_DEBUG_MAXID
] = {
560 &debug0
, &debug1
, &debug2
, &debug3
, &debug4
,
561 &debug5
, &debug6
, &debug7
, &debug8
, &debug9
,
562 &debug10
, &debug11
, &debug12
, &debug13
, &debug14
,
563 &debug15
, &debug16
, &debug17
, &debug18
, &debug19
,
566 debug_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
)
575 struct ctldebug
*cdp
;
577 /* all sysctl names at this level are name and field */
579 return (ENOTDIR
); /* overloaded */
580 cdp
= debugvars
[name
[0]];
581 if (cdp
->debugname
== 0)
585 return (sysctl_rdstring(oldp
, oldlenp
, newp
, cdp
->debugname
));
586 case CTL_DEBUG_VALUE
:
587 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, cdp
->debugvar
));
596 * Validate parameters and get old / set new parameters
597 * for an integer-valued sysctl function.
600 sysctl_int(oldp
, oldlenp
, newp
, newlen
, valp
)
609 if (oldp
&& *oldlenp
< sizeof(int))
611 if (newp
&& newlen
!= sizeof(int))
613 *oldlenp
= sizeof(int);
615 error
= copyout(valp
, oldp
, sizeof(int));
616 if (error
== 0 && newp
)
617 error
= copyin(newp
, valp
, sizeof(int));
622 * As above, but read-only.
625 sysctl_rdint(oldp
, oldlenp
, newp
, val
)
633 if (oldp
&& *oldlenp
< sizeof(int))
637 *oldlenp
= sizeof(int);
639 error
= copyout((caddr_t
)&val
, oldp
, sizeof(int));
644 * Validate parameters and get old / set new parameters
645 * for an quad(64bit)-valued sysctl function.
648 sysctl_quad(oldp
, oldlenp
, newp
, newlen
, valp
)
657 if (oldp
&& *oldlenp
< sizeof(quad_t
))
659 if (newp
&& newlen
!= sizeof(quad_t
))
661 *oldlenp
= sizeof(quad_t
);
663 error
= copyout(valp
, oldp
, sizeof(quad_t
));
664 if (error
== 0 && newp
)
665 error
= copyin(newp
, valp
, sizeof(quad_t
));
670 * As above, but read-only.
673 sysctl_rdquad(oldp
, oldlenp
, newp
, val
)
681 if (oldp
&& *oldlenp
< sizeof(quad_t
))
685 *oldlenp
= sizeof(quad_t
);
687 error
= copyout((caddr_t
)&val
, oldp
, sizeof(quad_t
));
692 * Validate parameters and get old / set new parameters
693 * for a string-valued sysctl function.
696 sysctl_string(oldp
, oldlenp
, newp
, newlen
, str
, maxlen
)
706 len
= strlen(str
) + 1;
707 if (oldp
&& *oldlenp
< len
)
709 if (newp
&& newlen
>= maxlen
)
711 *oldlenp
= len
-1; /* deal with NULL strings correctly */
713 error
= copyout(str
, oldp
, len
);
715 if (error
== 0 && newp
) {
716 error
= copyin(newp
, str
, newlen
);
723 * As above, but read-only.
726 sysctl_rdstring(oldp
, oldlenp
, newp
, str
)
734 len
= strlen(str
) + 1;
735 if (oldp
&& *oldlenp
< len
)
741 error
= copyout(str
, oldp
, len
);
746 * Validate parameters and get old / set new parameters
747 * for a structure oriented sysctl function.
750 sysctl_struct(oldp
, oldlenp
, newp
, newlen
, sp
, len
)
760 if (oldp
&& *oldlenp
< len
)
762 if (newp
&& newlen
> len
)
766 error
= copyout(sp
, oldp
, len
);
768 if (error
== 0 && newp
)
769 error
= copyin(newp
, sp
, len
);
774 * Validate parameters and get old parameters
775 * for a structure oriented sysctl function.
778 sysctl_rdstruct(oldp
, oldlenp
, newp
, sp
, len
)
786 if (oldp
&& *oldlenp
< len
)
792 error
= copyout(sp
, oldp
, len
);
797 * Get file structures.
800 sysctl_file(where
, sizep
)
811 * overestimate by 10 files
813 *sizep
= sizeof(filehead
) + (nfiles
+ 10) * sizeof(struct file
);
818 * first copyout filehead
820 if (buflen
< sizeof(filehead
)) {
824 if (error
= copyout((caddr_t
)&filehead
, where
, sizeof(filehead
)))
826 buflen
-= sizeof(filehead
);
827 where
+= sizeof(filehead
);
830 * followed by an array of file structures
832 for (fp
= filehead
.lh_first
; fp
!= 0; fp
= fp
->f_list
.le_next
) {
833 if (buflen
< sizeof(struct file
)) {
834 *sizep
= where
- start
;
837 if (error
= copyout((caddr_t
)fp
, where
, sizeof (struct file
)))
839 buflen
-= sizeof(struct file
);
840 where
+= sizeof(struct file
);
842 *sizep
= where
- start
;
847 * try over estimating by 5 procs
849 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
852 sysctl_doproc(name
, namelen
, where
, sizep
)
858 register struct proc
*p
;
859 register struct kinfo_proc
*dp
= (struct kinfo_proc
*)where
;
860 register int needed
= 0;
861 int buflen
= where
!= NULL
? *sizep
: 0;
863 struct kinfo_proc kproc
;
866 if (namelen
!= 2 && !(namelen
== 1 && name
[0] == KERN_PROC_ALL
))
868 p
= allproc
.lh_first
;
871 for (; p
!= 0; p
= p
->p_list
.le_next
) {
873 * Skip embryonic processes.
875 if (p
->p_stat
== SIDL
)
878 * TODO - make more efficient (see notes below).
884 /* could do this with just a lookup */
885 if (p
->p_pid
!= (pid_t
)name
[1])
890 /* could do this by traversing pgrp */
891 if (p
->p_pgrp
->pg_id
!= (pid_t
)name
[1])
896 if ( doingzomb
|| (p
->p_flag
& P_CONTROLT
) == 0 ||
897 p
->p_session
->s_ttyp
== NULL
||
898 p
->p_session
->s_ttyp
->t_dev
!= (dev_t
)name
[1])
903 if (doingzomb
|| (p
->p_ucred
->cr_uid
!= (uid_t
)name
[1]))
908 if ( doingzomb
|| (p
->p_cred
->p_ruid
!= (uid_t
)name
[1]))
912 if (buflen
>= sizeof(struct kinfo_proc
)) {
913 bzero(&kproc
, sizeof(struct kinfo_proc
));
914 fill_proc(p
, &kproc
, doingzomb
);
915 if (error
= copyout((caddr_t
)&kproc
, &dp
->kp_proc
,
916 sizeof(struct kinfo_proc
)))
919 buflen
-= sizeof(struct kinfo_proc
);
921 needed
+= sizeof(struct kinfo_proc
);
923 if (doingzomb
== 0) {
924 p
= zombproc
.lh_first
;
929 *sizep
= (caddr_t
)dp
- where
;
933 needed
+= KERN_PROCSLOP
;
940 fill_proc(p
,kp
, doingzomb
)
941 register struct proc
*p
;
942 register struct kinfo_proc
*kp
;
945 fill_externproc(p
, &kp
->kp_proc
);
947 fill_eproc(p
, &kp
->kp_eproc
);
950 * Fill in an eproc structure for the specified process.
954 register struct proc
*p
;
955 register struct eproc
*ep
;
957 register struct tty
*tp
;
960 * Skip zombie processes.
962 if (p
->p_stat
== SZOMB
)
966 ep
->e_sess
= p
->p_pgrp
->pg_session
;
967 ep
->e_pcred
= *p
->p_cred
;
968 ep
->e_ucred
= *p
->p_ucred
;
969 if (p
->p_stat
== SIDL
|| p
->p_stat
== SZOMB
) {
970 ep
->e_vm
.vm_tsize
= 0;
971 ep
->e_vm
.vm_dsize
= 0;
972 ep
->e_vm
.vm_ssize
= 0;
974 ep
->e_vm
.vm_rssize
= 0;
976 ep
->e_ppid
= p
->p_pptr
->p_pid
;
979 ep
->e_pgid
= p
->p_pgrp
->pg_id
;
980 ep
->e_jobc
= p
->p_pgrp
->pg_jobc
;
981 if ((p
->p_flag
& P_CONTROLT
) &&
982 (tp
= ep
->e_sess
->s_ttyp
)) {
983 ep
->e_tdev
= tp
->t_dev
;
984 ep
->e_tpgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: NO_PID
;
985 ep
->e_tsess
= tp
->t_session
;
988 ep
->e_flag
= ep
->e_sess
->s_ttyvp
? EPROC_CTTY
: 0;
990 ep
->e_flag
|= EPROC_SLEADER
;
992 strncpy(ep
->e_wmesg
, p
->p_wmesg
, WMESGLEN
);
993 ep
->e_xsize
= ep
->e_xrssize
= 0;
994 ep
->e_xccount
= ep
->e_xswrss
= 0;
997 * Fill in an eproc structure for the specified process.
1000 fill_externproc(p
, exp
)
1001 register struct proc
*p
;
1002 register struct extern_proc
*exp
;
1004 exp
->p_forw
= exp
->p_back
= NULL
;
1006 exp
->p_starttime
= p
->p_stats
->p_start
;
1007 exp
->p_vmspace
= NULL
;
1008 exp
->p_sigacts
= p
->p_sigacts
;
1009 exp
->p_flag
= p
->p_flag
;
1010 exp
->p_stat
= p
->p_stat
;
1011 exp
->p_pid
= p
->p_pid
;
1012 exp
->p_oppid
= p
->p_oppid
;
1013 exp
->p_dupfd
= p
->p_dupfd
;
1015 exp
->user_stack
= p
->user_stack
;
1016 exp
->exit_thread
= p
->exit_thread
;
1017 exp
->p_debugger
= p
->p_debugger
;
1018 exp
->sigwait
= p
->sigwait
;
1020 exp
->p_estcpu
= p
->p_estcpu
;
1021 exp
->p_cpticks
= p
->p_cpticks
;
1022 exp
->p_pctcpu
= p
->p_pctcpu
;
1023 exp
->p_wchan
= p
->p_wchan
;
1024 exp
->p_wmesg
= p
->p_wmesg
;
1025 exp
->p_swtime
= p
->p_swtime
;
1026 exp
->p_slptime
= p
->p_slptime
;
1027 bcopy(&p
->p_realtimer
, &exp
->p_realtimer
,sizeof(struct itimerval
));
1028 bcopy(&p
->p_rtime
, &exp
->p_rtime
,sizeof(struct timeval
));
1029 exp
->p_uticks
= p
->p_uticks
;
1030 exp
->p_sticks
= p
->p_sticks
;
1031 exp
->p_iticks
= p
->p_iticks
;
1032 exp
->p_traceflag
= p
->p_traceflag
;
1033 exp
->p_tracep
= p
->p_tracep
;
1034 exp
->p_siglist
= 0 ; /* No longer relevant */
1035 exp
->p_textvp
= p
->p_textvp
;
1036 exp
->p_holdcnt
= 0 ;
1037 exp
->p_sigmask
= 0 ; /* no longer avaialable */
1038 exp
->p_sigignore
= p
->p_sigignore
;
1039 exp
->p_sigcatch
= p
->p_sigcatch
;
1040 exp
->p_priority
= p
->p_priority
;
1041 exp
->p_usrpri
= p
->p_usrpri
;
1042 exp
->p_nice
= p
->p_nice
;
1043 bcopy(&p
->p_comm
, &exp
->p_comm
,MAXCOMLEN
);
1044 exp
->p_comm
[MAXCOMLEN
] = '\0';
1045 exp
->p_pgrp
= p
->p_pgrp
;
1047 exp
->p_xstat
= p
->p_xstat
;
1048 exp
->p_acflag
= p
->p_acflag
;
1049 exp
->p_ru
= p
->p_ru
;
1053 kdebug_ops(name
, namelen
, where
, sizep
, p
)
1062 extern int kdbg_control(int *name
, u_int namelen
,
1063 char * where
,size_t * sizep
);
1065 if (ret
= suser(p
->p_ucred
, &p
->p_acflag
))
1081 case KERN_KDSETRTCDEC
:
1083 case KERN_KDGETENTROPY
:
1084 ret
= kdbg_control(name
, namelen
, where
, sizep
);
1094 pcsamples_ops(name
, namelen
, where
, sizep
, p
)
1102 extern int pcsamples_control(int *name
, u_int namelen
,
1103 char * where
,size_t * sizep
);
1105 if (ret
= suser(p
->p_ucred
, &p
->p_acflag
))
1109 case KERN_PCDISABLE
:
1113 case KERN_PCREADBUF
:
1117 ret
= pcsamples_control(name
, namelen
, where
, sizep
);
1127 * Returns the top N bytes of the user stack, with
1128 * everything below the first argument character
1129 * zeroed for security reasons.
1130 * Odd data structure is for compatibility.
1133 sysctl_procargs(name
, namelen
, where
, sizep
, cur_proc
)
1138 struct proc
*cur_proc
;
1140 register struct proc
*p
;
1141 register int needed
= 0;
1142 int buflen
= where
!= NULL
? *sizep
: 0;
1144 struct vm_map
*proc_map
;
1147 vm_offset_t arg_addr
;
1151 vm_offset_t copy_start
, copy_end
;
1152 vm_offset_t dealloc_start
; /* area to remove from kernel map */
1153 vm_offset_t dealloc_end
;
1159 if ((buflen
<= 0) || (buflen
> (PAGE_SIZE
<< 1))) {
1165 * Lookup process by pid
1176 * Copy the top N bytes of the stack.
1177 * On all machines we have so far, the stack grows
1180 * If the user expects no more than N bytes of
1181 * argument list, use that as a guess for the
1188 if ((p
->p_ucred
->cr_uid
!= cur_proc
->p_ucred
->cr_uid
)
1189 && suser(cur_proc
->p_ucred
, &cur_proc
->p_acflag
))
1191 arg_addr
= (vm_offset_t
)(p
->user_stack
- arg_size
);
1195 * Before we can block (any VM code), make another
1196 * reference to the map to keep it alive. We do
1197 * that by getting a reference on the task itself.
1204 * A regular task_reference call can block, causing the funnel
1205 * to be dropped and allowing the proc/task to get freed.
1206 * Instead, we issue a non-blocking attempt at the task reference,
1207 * and look up the proc/task all over again if that fails.
1209 if (!task_reference_try(task
)) {
1214 ret
= kmem_alloc(kernel_map
, ©_start
, round_page(arg_size
));
1215 if (ret
!= KERN_SUCCESS
) {
1216 task_deallocate(task
);
1220 proc_map
= get_task_map(task
);
1221 copy_end
= round_page(copy_start
+ arg_size
);
1223 if( vm_map_copyin(proc_map
, trunc_page(arg_addr
), round_page(arg_size
),
1224 FALSE
, &tmp
) != KERN_SUCCESS
) {
1225 task_deallocate(task
);
1226 kmem_free(kernel_map
, copy_start
,
1227 round_page(arg_size
));
1232 * Now that we've done the copyin from the process'
1233 * map, we can release the reference to it.
1235 task_deallocate(task
);
1237 if( vm_map_copy_overwrite(kernel_map
, copy_start
,
1238 tmp
, FALSE
) != KERN_SUCCESS
) {
1239 kmem_free(kernel_map
, copy_start
,
1240 round_page(arg_size
));
1244 data
= (caddr_t
) (copy_end
- arg_size
);
1245 ip
= (int *) copy_end
;
1249 * Now look down the stack for the bottom of the
1250 * argument list. Since this call is otherwise
1251 * unprotected, we can't let the nosy user see
1252 * anything else on the stack.
1254 * The arguments are pushed on the stack by
1258 * arg 0 (null-terminated)
1266 ip
-= 2; /*skip trailing 0 word and assume at least one
1267 argument. The last word of argN may be just
1268 the trailing 0, in which case we'd stop
1271 if (ip
== (int *)data
)
1274 * To account for saved path name and not having a null after that
1275 * Run the sweep again. If we have already sweeped entire range skip this
1277 if (ip
!= (int *)data
) {
1279 if (ip
== (int *)data
)
1283 bzero(data
, (unsigned) ((int)ip
- (int)data
));
1285 dealloc_start
= copy_start
;
1286 dealloc_end
= copy_end
;
1289 size
= MIN(size
, buflen
);
1290 error
= copyout(data
, where
, size
);
1292 if (dealloc_start
!= (vm_offset_t
) 0) {
1293 kmem_free(kernel_map
, dealloc_start
,
1294 dealloc_end
- dealloc_start
);