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
)); 
 521                 return (sysctl_rdint(oldp
, oldlenp
, newp
, gPEClockFrequencyInfo
.timebase_frequency_hz
)); 
 524                 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.vector_unit
)); 
 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
)); 
 532                 if (cpu_info
.l2_cache_size 
== 0xFFFFFFFF) return(EINVAL
); 
 533                 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l2_settings
)); 
 535                 if (cpu_info
.l2_cache_size 
== 0xFFFFFFFF) return(EINVAL
); 
 536                 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l2_cache_size
)); 
 538                 if (cpu_info
.l3_cache_size 
== 0xFFFFFFFF) return(EINVAL
); 
 539                 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l3_settings
)); 
 541                 if (cpu_info
.l3_cache_size 
== 0xFFFFFFFF) return(EINVAL
); 
 542                 return (sysctl_rdint(oldp
, oldlenp
, newp
, cpu_info
.l3_cache_size
)); 
 551  * Debugging related system variables. 
 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
, 
 568 debug_sysctl(name
, namelen
, oldp
, oldlenp
, newp
, newlen
, p
) 
 577         struct ctldebug 
*cdp
; 
 579         /* all sysctl names at this level are name and field */ 
 581                 return (ENOTDIR
);               /* overloaded */ 
 582         cdp 
= debugvars
[name
[0]]; 
 583         if (cdp
->debugname 
== 0) 
 587                 return (sysctl_rdstring(oldp
, oldlenp
, newp
, cdp
->debugname
)); 
 588         case CTL_DEBUG_VALUE
: 
 589                 return (sysctl_int(oldp
, oldlenp
, newp
, newlen
, cdp
->debugvar
)); 
 598  * Validate parameters and get old / set new parameters 
 599  * for an integer-valued sysctl function. 
 602 sysctl_int(oldp
, oldlenp
, newp
, newlen
, valp
) 
 611         if (oldp 
&& *oldlenp 
< sizeof(int)) 
 613         if (newp 
&& newlen 
!= sizeof(int)) 
 615         *oldlenp 
= sizeof(int); 
 617                 error 
= copyout(valp
, oldp
, sizeof(int)); 
 618         if (error 
== 0 && newp
) 
 619                 error 
= copyin(newp
, valp
, sizeof(int)); 
 624  * As above, but read-only. 
 627 sysctl_rdint(oldp
, oldlenp
, newp
, val
) 
 635         if (oldp 
&& *oldlenp 
< sizeof(int)) 
 639         *oldlenp 
= sizeof(int); 
 641                 error 
= copyout((caddr_t
)&val
, oldp
, sizeof(int)); 
 646  * Validate parameters and get old / set new parameters 
 647  * for an quad(64bit)-valued sysctl function. 
 650 sysctl_quad(oldp
, oldlenp
, newp
, newlen
, valp
) 
 659         if (oldp 
&& *oldlenp 
< sizeof(quad_t
)) 
 661         if (newp 
&& newlen 
!= sizeof(quad_t
)) 
 663         *oldlenp 
= sizeof(quad_t
); 
 665                 error 
= copyout(valp
, oldp
, sizeof(quad_t
)); 
 666         if (error 
== 0 && newp
) 
 667                 error 
= copyin(newp
, valp
, sizeof(quad_t
)); 
 672  * As above, but read-only. 
 675 sysctl_rdquad(oldp
, oldlenp
, newp
, val
) 
 683         if (oldp 
&& *oldlenp 
< sizeof(quad_t
)) 
 687         *oldlenp 
= sizeof(quad_t
); 
 689                 error 
= copyout((caddr_t
)&val
, oldp
, sizeof(quad_t
)); 
 694  * Validate parameters and get old / set new parameters 
 695  * for a string-valued sysctl function. 
 698 sysctl_string(oldp
, oldlenp
, newp
, newlen
, str
, maxlen
) 
 708         len 
= strlen(str
) + 1; 
 709         if (oldp 
&& *oldlenp 
< len
) 
 711         if (newp 
&& newlen 
>= maxlen
) 
 713         *oldlenp 
= len 
-1; /* deal with NULL strings correctly */ 
 715                 error 
= copyout(str
, oldp
, len
); 
 717         if (error 
== 0 && newp
) { 
 718                 error 
= copyin(newp
, str
, newlen
); 
 725  * As above, but read-only. 
 728 sysctl_rdstring(oldp
, oldlenp
, newp
, str
) 
 736         len 
= strlen(str
) + 1; 
 737         if (oldp 
&& *oldlenp 
< len
) 
 743                 error 
= copyout(str
, oldp
, len
); 
 748  * Validate parameters and get old / set new parameters 
 749  * for a structure oriented sysctl function. 
 752 sysctl_struct(oldp
, oldlenp
, newp
, newlen
, sp
, len
) 
 762         if (oldp 
&& *oldlenp 
< len
) 
 764         if (newp 
&& newlen 
> len
) 
 768                 error 
= copyout(sp
, oldp
, len
); 
 770         if (error 
== 0 && newp
) 
 771                 error 
= copyin(newp
, sp
, len
); 
 776  * Validate parameters and get old parameters 
 777  * for a structure oriented sysctl function. 
 780 sysctl_rdstruct(oldp
, oldlenp
, newp
, sp
, len
) 
 788         if (oldp 
&& *oldlenp 
< len
) 
 794                 error 
= copyout(sp
, oldp
, len
); 
 799  * Get file structures. 
 802 sysctl_file(where
, sizep
) 
 813                  * overestimate by 10 files 
 815                 *sizep 
= sizeof(filehead
) + (nfiles 
+ 10) * sizeof(struct file
); 
 820          * first copyout filehead 
 822         if (buflen 
< sizeof(filehead
)) { 
 826         if (error 
= copyout((caddr_t
)&filehead
, where
, sizeof(filehead
))) 
 828         buflen 
-= sizeof(filehead
); 
 829         where 
+= sizeof(filehead
); 
 832          * followed by an array of file structures 
 834         for (fp 
= filehead
.lh_first
; fp 
!= 0; fp 
= fp
->f_list
.le_next
) { 
 835                 if (buflen 
< sizeof(struct file
)) { 
 836                         *sizep 
= where 
- start
; 
 839                 if (error 
= copyout((caddr_t
)fp
, where
, sizeof (struct file
))) 
 841                 buflen 
-= sizeof(struct file
); 
 842                 where 
+= sizeof(struct file
); 
 844         *sizep 
= where 
- start
; 
 849  * try over estimating by 5 procs 
 851 #define KERN_PROCSLOP   (5 * sizeof (struct kinfo_proc)) 
 854 sysctl_doproc(name
, namelen
, where
, sizep
) 
 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; 
 865         struct kinfo_proc kproc
; 
 868         if (namelen 
!= 2 && !(namelen 
== 1 && name
[0] == KERN_PROC_ALL
)) 
 870         p 
= allproc
.lh_first
; 
 873         for (; p 
!= 0; p 
= p
->p_list
.le_next
) { 
 875                  * Skip embryonic processes. 
 877                 if (p
->p_stat 
== SIDL
) 
 880                  * TODO - make more efficient (see notes below). 
 886                         /* could do this with just a lookup */ 
 887                         if (p
->p_pid 
!= (pid_t
)name
[1]) 
 892                         /* could do this by traversing pgrp */ 
 893                         if (p
->p_pgrp
->pg_id 
!= (pid_t
)name
[1]) 
 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]) 
 905                         if (doingzomb 
|| (p
->p_ucred
->cr_uid 
!= (uid_t
)name
[1])) 
 910                         if ( doingzomb 
|| (p
->p_cred
->p_ruid 
!= (uid_t
)name
[1])) 
 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
))) 
 921                         buflen 
-= sizeof(struct kinfo_proc
); 
 923                 needed 
+= sizeof(struct kinfo_proc
); 
 925         if (doingzomb 
== 0) { 
 926                 p 
= zombproc
.lh_first
; 
 931                 *sizep 
= (caddr_t
)dp 
- where
; 
 935                 needed 
+= KERN_PROCSLOP
; 
 942 fill_proc(p
,kp
, doingzomb
) 
 943         register struct proc 
*p
; 
 944         register struct kinfo_proc 
*kp
; 
 947         fill_externproc(p
, &kp
->kp_proc
); 
 949                 fill_eproc(p
, &kp
->kp_eproc
); 
 952  * Fill in an eproc structure for the specified process. 
 956         register struct proc 
*p
; 
 957         register struct eproc 
*ep
; 
 959         register struct tty 
*tp
; 
 962          * Skip zombie processes. 
 964         if (p
->p_stat 
== SZOMB
) 
 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; 
 976         ep
->e_vm
.vm_rssize 
= 0; 
 978                 ep
->e_ppid 
= p
->p_pptr
->p_pid
; 
 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
; 
 990         ep
->e_flag 
= ep
->e_sess
->s_ttyvp 
? EPROC_CTTY 
: 0; 
 992                 ep
->e_flag 
|= EPROC_SLEADER
; 
 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; 
 999  * Fill in an eproc structure for the specified process. 
1002 fill_externproc(p
, exp
) 
1003         register struct proc 
*p
; 
1004         register struct extern_proc 
*exp
; 
1006         exp
->p_forw 
= exp
->p_back 
= NULL
; 
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 
; 
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 
; 
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 
; 
1049         exp
->p_xstat  
= p
->p_xstat 
; 
1050         exp
->p_acflag  
= p
->p_acflag 
; 
1051         exp
->p_ru  
= p
->p_ru 
; 
1055 kdebug_ops(name
, namelen
, where
, sizep
, p
) 
1064         extern int kdbg_control(int *name
, u_int namelen
, 
1065                 char * where
,size_t * sizep
); 
1067         if (ret 
= suser(p
->p_ucred
, &p
->p_acflag
)) 
1083         case KERN_KDSETRTCDEC
: 
1085         case KERN_KDGETENTROPY
: 
1086                 ret 
= kdbg_control(name
, namelen
, where
, sizep
); 
1096 pcsamples_ops(name
, namelen
, where
, sizep
, p
) 
1104         extern int pcsamples_control(int *name
, u_int namelen
, 
1105                 char * where
,size_t * sizep
); 
1107         if (ret 
= suser(p
->p_ucred
, &p
->p_acflag
)) 
1111         case KERN_PCDISABLE
: 
1115         case KERN_PCREADBUF
: 
1119                 ret 
= pcsamples_control(name
, namelen
, where
, sizep
); 
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. 
1135 sysctl_procargs(name
, namelen
, where
, sizep
, cur_proc
) 
1140         struct proc 
*cur_proc
; 
1142         register struct proc 
*p
; 
1143         register int needed 
= 0; 
1144         int buflen 
= where 
!= NULL 
? *sizep 
: 0; 
1146         struct vm_map 
*proc_map
; 
1149         vm_offset_t     arg_addr
; 
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
; 
1161         if ((buflen 
<= 0) || (buflen 
> (PAGE_SIZE 
<< 1))) { 
1167          *      Lookup process by pid 
1178          *      Copy the top N bytes of the stack. 
1179          *      On all machines we have so far, the stack grows 
1182          *      If the user expects no more than N bytes of 
1183          *      argument list, use that as a guess for the 
1190         if ((p
->p_ucred
->cr_uid 
!= cur_proc
->p_ucred
->cr_uid
)  
1191                 && suser(cur_proc
->p_ucred
, &cur_proc
->p_acflag
)) 
1193         arg_addr 
= (vm_offset_t
)(p
->user_stack 
- arg_size
); 
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. 
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. 
1211         if (!task_reference_try(task
)) { 
1216         ret 
= kmem_alloc(kernel_map
, ©_start
, round_page(arg_size
)); 
1217         if (ret 
!= KERN_SUCCESS
) { 
1218                 task_deallocate(task
); 
1222         proc_map 
= get_task_map(task
); 
1223         copy_end 
= round_page(copy_start 
+ arg_size
); 
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
)); 
1234          *      Now that we've done the copyin from the process' 
1235          *      map, we can release the reference to it. 
1237         task_deallocate(task
); 
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
)); 
1246         data 
= (caddr_t
) (copy_end 
- arg_size
); 
1247         ip 
= (int *) copy_end
;           
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. 
1256          *      The arguments are pushed on the stack by 
1260          *              arg 0   (null-terminated) 
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 
1273                 if (ip 
== (int *)data
) 
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 
1279          if (ip 
!= (int *)data
) { 
1281                     if (ip 
== (int *)data
) 
1285         bzero(data
, (unsigned) ((int)ip 
- (int)data
)); 
1287         dealloc_start 
= copy_start
; 
1288         dealloc_end 
= copy_end
; 
1291         size 
= MIN(size
, buflen
); 
1292         error 
= copyout(data
, where
, size
); 
1294         if (dealloc_start 
!= (vm_offset_t
) 0) { 
1295                 kmem_free(kernel_map
, dealloc_start
, 
1296                         dealloc_end 
- dealloc_start
);