Annotation of kernel/bsd/kern/cmu_syscalls.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* 
        !            26:  * Mach Operating System
        !            27:  * Copyright (c) 1987 Carnegie-Mellon University
        !            28:  * All rights reserved.  The CMU software License Agreement specifies
        !            29:  * the terms and conditions for use and redistribution.
        !            30:  *
        !            31:  * HISTORY
        !            32:  *
        !            33:  * 27-Apr-97  A.Ramesh (aramesh) at Apple
        !            34:  *  Added limited set for Rhapsody
        !            35:  * 
        !            36:  */
        !            37: 
        !            38: #import <sys/param.h>
        !            39: #import <sys/systm.h>
        !            40: #import <sys/dir.h>
        !            41: #import <sys/buf.h>
        !            42: #import <sys/vnode.h>
        !            43: #import <sys/file.h>
        !            44: #import <sys/proc.h>
        !            45: #import <sys/conf.h>
        !            46: #import <sys/ioctl.h>
        !            47: #import <sys/tty.h>
        !            48: //#import <sys/vfs.h>
        !            49: //#import <ufs/mount.h>
        !            50: #import <sys/kernel.h>
        !            51: #import <sys/table.h>
        !            52: 
        !            53: #import <mach/mach_types.h>
        !            54: 
        !            55: #import <vm/vm_user.h>
        !            56: #import <vm/vm_map.h>
        !            57: #import <vm/vm_kern.h>
        !            58: #import <mach/vm_param.h>
        !            59: #import <machine/vmparam.h>    /* only way to find the user stack (argblock) */
        !            60: 
        !            61: #import <sys/vmmeter.h>
        !            62: #import <sys/socket.h>
        !            63: #import <net/if.h>
        !            64: 
        !            65: #import <sys/version.h>
        !            66: 
        !            67: struct vmmeter cnt;
        !            68: 
        !            69: /*
        !            70:  *  table - get/set element(s) from system table
        !            71:  *
        !            72:  *  This call is intended as a general purpose mechanism for retrieving or
        !            73:  *  updating individual or sequential elements of various system tables and
        !            74:  *  data structures.
        !            75:  *
        !            76:  *  One potential future use might be to make most of the standard system
        !            77:  *  tables available via this mechanism so as to permit non-privileged programs
        !            78:  *  to access these common SYSTAT types of data.
        !            79:  *
        !            80:  *  Parameters:
        !            81:  *
        !            82:  *  id         = an identifer indicating the table in question
        !            83:  *  index      = an index into this table specifying the starting
        !            84:  *               position at which to begin the data copy
        !            85:  *  addr       = address in user space to receive/supply the data
        !            86:  *  nel                = number of table elements to retrieve/update
        !            87:  *  lel                = expected size of a single element of the table.  If this
        !            88:  *               is smaller than the actual size, extra data will be
        !            89:  *               truncated from the end.  If it is larger, holes will be
        !            90:  *               left between elements copied to/from the user address space.
        !            91:  *
        !            92:  *               The intent of separately distinguishing these final two
        !            93:  *               arguments is to insulate user programs as much as possible
        !            94:  *               from the common change in the size of system data structures
        !            95:  *               when a new field is added.  This works so long as new fields
        !            96:  *               are added only to the end, none are removed, and all fields
        !            97:  *               remain a fixed size.
        !            98:  *
        !            99:  *  Returns:
        !           100:  *
        !           101:  *  val1       = number of elements retrieved/updated (this may be fewer than
        !           102:  *               requested if more elements are requested than exist in
        !           103:  *               the table from the specified index).
        !           104:  *
        !           105:  *  Note:
        !           106:  *
        !           107:  *  A call with lel == 0 and nel == MAXSHORT can be used to determine the
        !           108:  *  length of a table (in elements) before actually requesting any of the
        !           109:  *  data.
        !           110:  */
        !           111: 
        !           112: #define        MAXLEL  (sizeof(long))  /* maximum element length (for set) */
        !           113: 
        !           114: struct table_args {
        !           115:                int id;
        !           116:                int index;
        !           117:                caddr_t addr;
        !           118:                int nel;        /* >0 ==> get, <0 ==> set */
        !           119:                u_int lel;
        !           120: };
        !           121: 
        !           122: table(p, uap, retval)
        !           123:        struct proc *p;
        !           124:        register struct table_args *uap;
        !           125:        int *retval;
        !           126: {
        !           127:        caddr_t data;
        !           128:        unsigned size;
        !           129:        int error = 0;
        !           130:        int set;
        !           131:        vm_offset_t     arg_addr;
        !           132:        vm_size_t       arg_size;
        !           133:        int             *ip;
        !           134:        struct proc     *pp;
        !           135:        vm_offset_t     copy_start, copy_end;
        !           136:        vm_map_t        proc_map;
        !           137:        vm_offset_t     dealloc_start;  /* area to remove from kernel map */
        !           138:        vm_offset_t     dealloc_end;
        !           139:        struct tbl_procinfo     tp;
        !           140:        struct tbl_cpuinfo      tc;
        !           141:        struct tbl_loadavg      tl;
        !           142:        int val1=0;
        !           143:        extern long avenrun[3], mach_factor[3];
        !           144: 
        !           145:        /*
        !           146:         *  Verify that any set request is appropriate.
        !           147:         */
        !           148:        set = 0;
        !           149:        if (uap->nel < 0) {
        !           150:                /*
        !           151:                 * Give the machine dependent code a crack at this first
        !           152:                 */
        !           153:                switch (machine_table_setokay(uap->id)) {
        !           154:                case TBL_MACHDEP_OKAY:
        !           155:                        goto okay;
        !           156:                case TBL_MACHDEP_BAD:
        !           157:                        *retval = val1;
        !           158:                        return(EINVAL);
        !           159:                case TBL_MACHDEP_NONE:
        !           160:                default:
        !           161:                        break;
        !           162:                }
        !           163:                switch (uap->id) {
        !           164:                default:
        !           165:                        *retval = val1;
        !           166:                        return(EINVAL);
        !           167:                }
        !           168:            okay:
        !           169:                set++;
        !           170:                uap->nel = -(uap->nel);
        !           171:        }
        !           172: 
        !           173:        val1 = 0;
        !           174: 
        !           175:        /*
        !           176:         *  Main loop for each element.
        !           177:         */
        !           178: 
        !           179:        while (uap->nel > 0) {
        !           180: 
        !           181:                dealloc_start = (vm_offset_t) 0;
        !           182:                dealloc_end = (vm_offset_t) 0;
        !           183: 
        !           184:                /*
        !           185:                 * Give machine dependent code a chance
        !           186:                 */
        !           187:                switch (machine_table(uap->id, uap->index, uap->addr,
        !           188:                                      uap->nel, uap->lel, set))
        !           189:                {
        !           190:                case TBL_MACHDEP_OKAY:
        !           191:                        uap->addr += uap->lel;
        !           192:                        uap->nel -= 1;
        !           193:                        uap->index += 1;
        !           194:                        val1 += 1;
        !           195:                        continue;
        !           196:                case TBL_MACHDEP_NONE:
        !           197:                        break;
        !           198:                case TBL_MACHDEP_BAD:
        !           199:                default:
        !           200:                        goto bad;
        !           201:                }
        !           202: 
        !           203:                switch (uap->id) {
        !           204:                case TBL_ARGUMENTS:
        !           205:                        /*
        !           206:                         *      Returns the top N bytes of the user stack, with
        !           207:                         *      everything below the first argument character
        !           208:                         *      zeroed for security reasons.
        !           209:                         *      Odd data structure is for compatibility.
        !           210:                         */
        !           211:                        /*
        !           212:                         *      Lookup process by pid
        !           213:                         */
        !           214:                        p = pfind(uap->index);
        !           215:                        if (p == (struct proc *)0) {
        !           216:                                /*
        !           217:                                 *      No such process
        !           218:                                 */
        !           219:                                *retval = val1;
        !           220:                                return(ESRCH);
        !           221:                         }
        !           222:                        /*
        !           223:                         *      Get map for process
        !           224:                         */
        !           225:                        proc_map = ((task_t)p->task)->map;
        !           226: 
        !           227:                        /*
        !           228:                         *      Copy the top N bytes of the stack.
        !           229:                         *      On all machines we have so far, the stack grows
        !           230:                         *      downwards.
        !           231:                         *
        !           232:                         *      If the user expects no more than N bytes of
        !           233:                         *      argument list, use that as a guess for the
        !           234:                         *      size.
        !           235:                         */
        !           236:                        if ((arg_size = uap->lel) == 0) {
        !           237:                                error = EINVAL;
        !           238:                                goto bad;
        !           239:                        }
        !           240: 
        !           241:                        if (!p->user_stack)
        !           242:                                goto bad;       /* kernel only proc */
        !           243: #if    STACK_GROWTH_UP
        !           244:                        arg_addr = p->user_stack;
        !           245: #else  STACK_GROWTH_UP
        !           246:                        arg_addr = p->user_stack - arg_size;
        !           247: #endif /* STACK_GROWTH_UP */
        !           248: 
        !           249:                        /*
        !           250:                         *      Before we can block (any VM code), make another
        !           251:                         *      reference to the map to keep it alive.
        !           252:                         */
        !           253:                        vm_map_reference(proc_map);
        !           254: 
        !           255:                        copy_start = kmem_alloc_wait(kernel_pageable_map,
        !           256:                                                round_page(arg_size));
        !           257: 
        !           258:                        copy_end = round_page(copy_start + arg_size);
        !           259: 
        !           260:                        if (vm_map_copy(kernel_pageable_map, proc_map, copy_start,
        !           261:                            round_page(arg_size), trunc_page(arg_addr),
        !           262:                            FALSE, FALSE) != KERN_SUCCESS) {
        !           263:                                kmem_free_wakeup(kernel_pageable_map, copy_start,
        !           264:                                        round_page(arg_size));
        !           265:                                vm_map_deallocate(proc_map);
        !           266:                                goto bad;
        !           267:                        }
        !           268: 
        !           269:                        /*
        !           270:                         *      Now that we've done the copy, we can release
        !           271:                         *      the process' map.
        !           272:                         */
        !           273:                        vm_map_deallocate(proc_map);
        !           274:                        
        !           275: #if    STACK_GROWTH_UP
        !           276:                        data = (caddr_t)copy_start;
        !           277:                        ip = (int *) ((*(int *)copy_start) - arg_addr + data);
        !           278:                        /*
        !           279:                         * sanity check ip since it comes from user-accessible
        !           280:                         * stack area
        !           281:                         */
        !           282:                        if (((vm_offset_t)ip > copy_end) ||
        !           283:                                        ((vm_offset_t)ip < copy_start))
        !           284:                                ip = (int *)copy_end;
        !           285:                        /*
        !           286:                         * relocate so that end of string area is at end
        !           287:                         * of buffer.
        !           288:                         */
        !           289:                        size = (unsigned) ((int)ip - (int)copy_start);
        !           290:                        data = (caddr_t)(copy_end - size);
        !           291:                        bcopy(copy_start, data, size);
        !           292:                        /*
        !           293:                         * now find beginning of string area so we can
        !           294:                         * clear out data user should not see
        !           295:                         */
        !           296:                        ip = (int *)copy_end;   // start at new end
        !           297:                        ip -= 2; /*skip trailing 0 word and assume at least one
        !           298:                                  argument.  The last word of argN may be just
        !           299:                                  the trailing 0, in which case we'd stop
        !           300:                                  there */
        !           301:                        while (*--ip)
        !           302:                                if (ip == (int *)data)
        !           303:                                        break;                  
        !           304:                        bzero(copy_start,
        !           305:                                (unsigned) ((int)ip - (int)copy_start));
        !           306:                        /*
        !           307:                         * now prepare data/size for the copy's out of the
        !           308:                         * switch.  We copy the last arg_size bytes from
        !           309:                         * our data.
        !           310:                         */
        !           311:                        size = arg_size;
        !           312:                        data = (caddr_t)(copy_end - size);
        !           313: #else  STACK_GROWTH_UP
        !           314: #if    ( defined(vax) || defined(romp) )
        !           315:                        data = (caddr_t) (copy_end-arg_size-SIGCODE_SIZE);
        !           316:                        ip = (int *) (copy_end - SIGCODE_SIZE);
        !           317: #else  ( defined(vax) || defined(romp) )               
        !           318:                        data = (caddr_t) (copy_end - arg_size);
        !           319:                        ip = (int *) copy_end;          
        !           320: #endif /* ( defined(vax) || defined(romp) )             */
        !           321:                        size = arg_size;
        !           322: 
        !           323:                        /*
        !           324:                         *      Now look down the stack for the bottom of the
        !           325:                         *      argument list.  Since this call is otherwise
        !           326:                         *      unprotected, we can't let the nosy user see
        !           327:                         *      anything else on the stack.
        !           328:                         *
        !           329:                         *      The arguments are pushed on the stack by
        !           330:                         *      execve() as:
        !           331:                         *
        !           332:                         *              .long   0
        !           333:                         *              arg 0   (null-terminated)
        !           334:                         *              arg 1
        !           335:                         *              ...
        !           336:                         *              arg N
        !           337:                         *              .long   0
        !           338:                         *
        !           339:                         */
        !           340: 
        !           341:                        ip -= 2; /*skip trailing 0 word and assume at least one
        !           342:                                  argument.  The last word of argN may be just
        !           343:                                  the trailing 0, in which case we'd stop
        !           344:                                  there */
        !           345:                        while (*--ip)
        !           346:                                if (ip == (int *)data)
        !           347:                                        break;                  
        !           348:                        bzero(data, (unsigned) ((int)ip - (int)data));
        !           349: #endif /* STACK_GROWTH_UP */
        !           350: 
        !           351:                        dealloc_start = copy_start;
        !           352:                        dealloc_end = copy_end;
        !           353:                        break;
        !           354: 
        !           355:                case TBL_PROCINFO:
        !           356:                    {
        !           357:                        register struct proc    *p;
        !           358: 
        !           359:                        /*
        !           360:                         *      Index is entry number in proc table.
        !           361:                         */
        !           362:                        /* transition, take negative numbers as pid for now */
        !           363:                        if (uap->index < 0)
        !           364:                                uap->index = -uap->index;       /* compatibility */
        !           365:                        p = pfind(uap->index);
        !           366:                        if (p == (struct proc *)0) {
        !           367:                                /*
        !           368:                                 *      No such process
        !           369:                                 */
        !           370:                                return(ESRCH);
        !           371:                        }
        !           372:                        if (p->p_stat == 0) {
        !           373:                            bzero((caddr_t)&tp, sizeof(tp));
        !           374:                            tp.pi_status = PI_EMPTY;
        !           375:                        }
        !           376:                        else {
        !           377:                            tp.pi_uid   = p->p_ucred->cr_uid;
        !           378:                            tp.pi_pid   = p->p_pid;
        !           379: 
        !           380:                                if (p->p_pptr)
        !           381:                                 tp.pi_ppid     = p->p_pptr->p_pid;
        !           382:                                else
        !           383:                                 tp.pi_ppid     = 0;
        !           384:                                if (p->p_pgrp)
        !           385:                                  tp.pi_pgrp    = p->p_pgrp->pg_id;
        !           386:                                else
        !           387:                                  tp.pi_pgrp    = 0;
        !           388:                            tp.pi_flag  = p->p_flag;
        !           389: 
        !           390:                            if (p->task == TASK_NULL) {
        !           391:                                tp.pi_status = PI_ZOMBIE;
        !           392:                            }
        !           393:                            else {
        !           394: if (p->p_pgrp && p->p_pgrp->pg_session && p->p_pgrp->pg_session->s_ttyp )
        !           395:        tp.pi_ttyd = p->p_pgrp->pg_session->s_ttyp->t_dev;
        !           396: else
        !           397:        tp.pi_ttyd = -1;
        !           398:                                bcopy(&p->p_comm[0], tp.pi_comm,
        !           399:                                      MAXCOMLEN);
        !           400:                                tp.pi_comm[MAXCOMLEN] = '\0';
        !           401: 
        !           402:                                if (p->p_flag & P_WEXIT)
        !           403:                                    tp.pi_status = PI_EXITING;
        !           404:                                else
        !           405:                                    tp.pi_status = PI_ACTIVE;
        !           406:                            }
        !           407:                        }
        !           408: 
        !           409:                        data = (caddr_t)&tp;
        !           410:                        size = sizeof(tp);
        !           411:                        break;
        !           412:                    }
        !           413: 
        !           414:                case TBL_CPUINFO:
        !           415:                        if (uap->index != 0 || uap->nel != 1)
        !           416:                                goto bad;
        !           417:                        tc.ci_swtch = cnt.v_swtch;
        !           418:                        tc.ci_intr = cnt.v_intr;
        !           419:                        tc.ci_syscall = cnt.v_syscall;
        !           420:                        tc.ci_traps = cnt.v_trap;
        !           421:                        tc.ci_hz = hz;
        !           422:                        tc.ci_phz = 0;
        !           423:                        bcopy(cp_time, tc.ci_cptime, sizeof(cp_time));
        !           424:                        data = (caddr_t)&tc;
        !           425:                        size = sizeof (tc);
        !           426:                        break;
        !           427:                case TBL_LOADAVG:
        !           428:                        if (uap->index != 0 || uap->nel != 1)
        !           429:                                goto bad;
        !           430:                        bcopy((caddr_t)&avenrun[0], (caddr_t)&tl.tl_avenrun[0],
        !           431:                                        sizeof(tl.tl_avenrun));
        !           432:                        tl.tl_lscale = LSCALE;
        !           433:                        data = (caddr_t)&tl;
        !           434:                        size = sizeof (tl);
        !           435:                        break;
        !           436:                case TBL_MACHFACTOR:
        !           437:                        if (uap->index != 0 || uap->nel != 1)
        !           438:                                goto bad;
        !           439:                        bcopy((caddr_t)&mach_factor[0],
        !           440:                                        (caddr_t)&tl.tl_avenrun[0],
        !           441:                                        sizeof(tl.tl_avenrun));
        !           442:                        tl.tl_lscale = LSCALE;
        !           443:                        data = (caddr_t)&tl;
        !           444:                        size = sizeof (tl);
        !           445:                        break;
        !           446:                default:
        !           447:                bad:
        !           448:                        /*
        !           449:                         *      Return error only if all indices
        !           450:                         *      are invalid.
        !           451:                         */
        !           452:                        if (val1 == 0)
        !           453:                                error = EINVAL;
        !           454:                        *retval = val1;
        !           455:                        return(error);
        !           456:                }
        !           457:                /*
        !           458:                 * This code should be generalized if/when other tables
        !           459:                 * are added to handle single element copies where the
        !           460:                 * actual and expected sizes differ or the table entries
        !           461:                 * are not contiguous in kernel memory (as with TTYLOC)
        !           462:                 * and also efficiently copy multiple element
        !           463:                 * tables when contiguous and the sizes match.
        !           464:                 */
        !           465:                size = MIN(size, uap->lel);
        !           466:                if (size) {
        !           467:                        if (set) {
        !           468:                                char buff[MAXLEL];
        !           469: 
        !           470:                                error = copyin(uap->addr, buff, size);
        !           471:                                if (error == 0)
        !           472:                                        bcopy(buff, data, size);
        !           473:                        }
        !           474:                        else {
        !           475:                                error = copyout(data, uap->addr, size);
        !           476:                        }
        !           477:                }
        !           478:                if (dealloc_start != (vm_offset_t) 0) {
        !           479:                        kmem_free_wakeup(kernel_pageable_map, dealloc_start,
        !           480:                                dealloc_end - dealloc_start);
        !           481:                }
        !           482:                if (error) {
        !           483:                        *retval = val1;
        !           484:                        return(error);
        !           485:                }
        !           486:                uap->addr += uap->lel;
        !           487:                uap->nel -= 1;
        !           488:                uap->index += 1;
        !           489:                val1 += 1;
        !           490:        }
        !           491:        *retval = val1;
        !           492:        return(0);
        !           493: }
        !           494: 

unix.superglobalmegacorp.com

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