Annotation of kernel/bsd/kern/cmu_syscalls.c, revision 1.1.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.