Annotation of XNU/bsd/kern/kern_sysctl.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.