Annotation of XNU/bsd/kern/kern_mman.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: /*
                     23:  * Copyright (c) 1988 University of Utah.
                     24:  * Copyright (c) 1991, 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:  * the Systems Programming Group of the University of Utah Computer
                     29:  * Science Department.
                     30:  *
                     31:  * Redistribution and use in source and binary forms, with or without
                     32:  * modification, are permitted provided that the following conditions
                     33:  * are met:
                     34:  * 1. Redistributions of source code must retain the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer.
                     36:  * 2. Redistributions in binary form must reproduce the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer in the
                     38:  *    documentation and/or other materials provided with the distribution.
                     39:  * 3. All advertising materials mentioning features or use of this software
                     40:  *    must display the following acknowledgement:
                     41:  *     This product includes software developed by the University of
                     42:  *     California, Berkeley and its contributors.
                     43:  * 4. Neither the name of the University nor the names of its contributors
                     44:  *    may be used to endorse or promote products derived from this software
                     45:  *    without specific prior written permission.
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     48:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     49:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     50:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     51:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     52:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     53:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     54:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     55:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     56:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     57:  * SUCH DAMAGE.
                     58:  *
                     59:  * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
                     60:  *
                     61:  *     @(#)vm_mmap.c   8.10 (Berkeley) 2/19/95
                     62:  */
                     63: 
                     64: /*
                     65:  * Mapped file (mmap) interface to VM
                     66:  */
                     67: 
                     68: #include <sys/param.h>
                     69: #include <sys/systm.h>
                     70: #include <sys/filedesc.h>
                     71: #include <sys/proc.h>
                     72: #include <sys/resourcevar.h>
                     73: #include <sys/buf.h>
                     74: #include <sys/vnode.h>
                     75: #include <sys/acct.h>
                     76: #include <sys/wait.h>
                     77: #include <sys/file.h>
                     78: #include <sys/vadvise.h>
                     79: #include <sys/trace.h>
                     80: #include <sys/mman.h>
                     81: #include <sys/conf.h>
                     82: #include <sys/stat.h>
                     83: 
                     84: #include <mach/mach_types.h>
                     85: 
                     86: #include <kern/cpu_number.h>
                     87: 
                     88: #include <vm/vm_map.h>
                     89: #include <vm/vm_kern.h>
                     90: #include <vm/vm_pager.h>
                     91: #include <vm/vnode_pager.h>
                     92: #include <kern/mapfs.h>
                     93: 
                     94: #include <mach/vm_sync.h>
                     95: #include <mach/vm_behavior.h>
                     96: #include <mach/vm_inherit.h>
                     97: #include <mach/vm_statistics.h>
                     98: 
                     99: struct sbrk_args {
                    100:                int     incr;
                    101: };
                    102: 
                    103: /* ARGSUSED */
                    104: int
                    105: sbrk(p, uap, retval)
                    106:        struct proc *p;
                    107:        struct sbrk_args *uap;
                    108:        register_t *retval;
                    109: {
                    110:        /* Not yet implemented */
                    111:        return (EOPNOTSUPP);
                    112: }
                    113: 
                    114: struct sstk_args {
                    115:        int     incr;
                    116: } *uap;
                    117: 
                    118: /* ARGSUSED */
                    119: int
                    120: sstk(p, uap, retval)
                    121:        struct proc *p;
                    122:        struct sstk_args *uap;
                    123:        register_t *retval;
                    124: {
                    125:        /* Not yet implemented */
                    126:        return (EOPNOTSUPP);
                    127: }
                    128: 
                    129: #if COMPAT_43
                    130: /* ARGSUSED */
                    131: int
                    132: ogetpagesize(p, uap, retval)
                    133:        struct proc *p;
                    134:        void *uap;
                    135:        register_t *retval;
                    136: {
                    137: 
                    138:        *retval = PAGE_SIZE;
                    139:        return (0);
                    140: }
                    141: #endif /* COMPAT_43 */
                    142: 
                    143: struct osmmap_args {
                    144:                caddr_t addr;
                    145:                int     len;
                    146:                int     prot;
                    147:                int     share;
                    148:                int     fd;
                    149:                long    pos;
                    150: };
                    151: 
                    152: osmmap(curp, uap, retval)
                    153:        struct proc *curp;
                    154:        register struct osmmap_args *uap;
                    155:        register_t *retval;
                    156: {
                    157: struct mmap_args {
                    158:                caddr_t addr;
                    159:                size_t len;
                    160:                int prot;
                    161:                int flags;
                    162:                int fd;
                    163: #ifdef DOUBLE_ALIGN_PARAMS
                    164:                long pad;
                    165: #endif
                    166:                off_t pos;
                    167: } newargs;
                    168: 
                    169:        if ((uap->share ==  MAP_SHARED )|| (uap->share ==  MAP_PRIVATE )) {
                    170:                newargs.addr = uap->addr;
                    171:                newargs.len = (size_t)uap->len;
                    172:                newargs.prot = uap->prot;
                    173:                newargs.flags = uap->share;
                    174:                newargs.fd = uap->fd;
                    175:                newargs.pos = (off_t)uap->pos;
                    176:                return(mmap(curp,&newargs, retval));
                    177:        } else
                    178:                return(EINVAL); 
                    179: }
                    180: 
                    181: struct mmap_args {
                    182:                caddr_t addr;
                    183:                size_t len;
                    184:                int prot;
                    185:                int flags;
                    186:                int fd;
                    187: #ifdef DOUBLE_ALIGN_PARAMS
                    188:                long pad;
                    189: #endif
                    190:                off_t pos;
                    191: };
                    192: int
                    193: mmap(p, uap, retval)
                    194:        struct proc *p;
                    195:        struct mmap_args *uap;
                    196:        register_t *retval;
                    197: {
                    198:        /*
                    199:         *      Map in special device (must be SHARED) or file
                    200:         */
                    201:        struct file *fp;
                    202:        register struct vnode *vp;
                    203:        int             flags;
                    204:        int             prot;
                    205:        int             err=0;
                    206:        vm_map_t        user_map;
                    207:        kern_return_t   result;
                    208:        vm_offset_t     user_addr;
                    209:        vm_size_t       user_size, pageoff;
                    210:        vm_offset_t     file_pos;
                    211:        boolean_t       find_space, docow;
                    212:        vm_prot_t       maxprot;
                    213:        void *handle;
                    214:        vm_pager_t      pager;
                    215:        struct vm_info  *vmp;
                    216:        int mapanon=0;
                    217: 
                    218:        user_addr = (vm_offset_t)uap->addr;
                    219:        user_size = (vm_size_t) uap->len;
                    220:        prot = (uap->prot & VM_PROT_ALL);
                    221:        flags = uap->flags;
                    222: 
                    223:        /*
                    224:         * The vm code does not have prototypes & compiler doesn't do the'
                    225:         * the right thing when you cast 64bit value and pass it in function 
                    226:         * call. So here it is.
                    227:         */
                    228:        file_pos = (vm_offset_t)uap->pos;
                    229: 
                    230: 
                    231:        /* make sure mapping fits into numeric range etc */
                    232:        if ((file_pos + user_size > (vm_offset_t)-PAGE_SIZE) ||
                    233:            ((ssize_t) uap->len < 0 )||
                    234:            ((flags & MAP_ANON) && uap->fd != -1))
                    235:                return (EINVAL);
                    236: 
                    237:        /*
                    238:         * Align the file position to a page boundary,
                    239:         * and save its page offset component.
                    240:         */
                    241:        pageoff = (file_pos & PAGE_MASK);
                    242:        file_pos -= pageoff;
                    243: 
                    244: 
                    245:        /* Adjust size for rounding (on both ends). */
                    246:        user_size += pageoff;                   /* low end... */
                    247:        user_size = (vm_size_t) round_page(user_size);  /* hi end */
                    248: 
                    249: 
                    250:        /*
                    251:         * Check for illegal addresses.  Watch out for address wrap... Note
                    252:         * that VM_*_ADDRESS are not constants due to casts (argh).
                    253:         */
                    254:        if (flags & MAP_FIXED) {
                    255:                /*
                    256:                 * The specified address must have the same remainder
                    257:                 * as the file offset taken modulo PAGE_SIZE, so it
                    258:                 * should be aligned after adjustment by pageoff.
                    259:                 */
                    260:                user_addr -= pageoff;
                    261:                if (user_addr & PAGE_MASK)
                    262:                        return (EINVAL);
                    263:                /* Address range must be all in user VM space. */
                    264:                if (VM_MAX_ADDRESS > 0 && (user_addr + user_size > VM_MAX_ADDRESS))
                    265:                        return (EINVAL);
                    266:                if (VM_MIN_ADDRESS > 0 && user_addr < VM_MIN_ADDRESS)
                    267:                        return (EINVAL);
                    268:                if (user_addr + user_size < user_addr)
                    269:                        return (EINVAL);
                    270:        }
                    271: #ifdef notyet
                    272:        /* DO not have apis to get this info, need to wait till then*/
                    273:        /*
                    274:         * XXX for non-fixed mappings where no hint is provided or
                    275:         * the hint would fall in the potential heap space,
                    276:         * place it after the end of the largest possible heap.
                    277:         *
                    278:         * There should really be a pmap call to determine a reasonable
                    279:         * location.
                    280:         */
                    281:        else if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ))
                    282:                addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
                    283: 
                    284: #endif
                    285: 
                    286: 
                    287:        if (flags & MAP_ANON) {
                    288:                /*
                    289:                 * Mapping blank space is trivial.
                    290:                 */
                    291:                handle = NULL;
                    292:                maxprot = VM_PROT_ALL;
                    293:                file_pos = 0;
                    294:                mapanon = 1;
                    295:        } else {
                    296:                /*
                    297:                 * Mapping file, get fp for validation. Obtain vnode and make
                    298:                 * sure it is of appropriate type.
                    299:                 */
                    300:                err = fdgetf(p, uap->fd, &fp);
                    301:                if (err)
                    302:                        return(err);
                    303:                if(fp->f_type == DTYPE_PSXSHM) {
                    304:                        uap->addr = user_addr;
                    305:                        uap->len = user_size;
                    306:                        uap->prot = prot;
                    307:                        uap->flags = flags;
                    308:                        uap->pos = file_pos;
                    309:                        return(pshm_mmap(p, uap, retval, fp , pageoff));
                    310:                }
                    311: 
                    312:                if (fp->f_type != DTYPE_VNODE)
                    313:                        return(EINVAL);
                    314:                vp = (struct vnode *)fp->f_data;
                    315: 
                    316:                if (vp->v_type != VREG && vp->v_type != VCHR)
                    317:                        return (EINVAL);
                    318:                /*
                    319:                 * XXX hack to handle use of /dev/zero to map anon memory (ala
                    320:                 * SunOS).
                    321:                 */
                    322:                if (vp->v_type == VCHR || vp->v_type == VSTR) {
                    323:                        return(EOPNOTSUPP);
                    324:                } else {
                    325:                        /*
                    326:                         * Ensure that file and memory protections are
                    327:                         * compatible.  Note that we only worry about
                    328:                         * writability if mapping is shared; in this case,
                    329:                         * current and max prot are dictated by the open file.
                    330:                         * XXX use the vnode instead?  Problem is: what
                    331:                         * credentials do we use for determination? What if
                    332:                         * proc does a setuid?
                    333:                         */
                    334:                        maxprot = VM_PROT_EXECUTE;      /* ??? */
                    335:                        if (fp->f_flag & FREAD)
                    336:                                maxprot |= VM_PROT_READ;
                    337:                        else if (prot & PROT_READ)
                    338:                                return (EACCES);
                    339:                        /*
                    340:                         * If we are sharing potential changes (either via
                    341:                         * MAP_SHARED or via the implicit sharing of character
                    342:                         * device mappings), and we are trying to get write
                    343:                         * permission although we opened it without asking
                    344:                         * for it, bail out. 
                    345:                         */
                    346: 
                    347:                        if ((flags & MAP_SHARED) != 0) {
                    348:                                if ((fp->f_flag & FWRITE) != 0) {
                    349:                                        struct vattr va;
                    350:                                        if ((err =
                    351:                                            VOP_GETATTR(vp, &va,
                    352:                                                        p->p_ucred, p)))
                    353:                                                return (err);
                    354:                                        if ((va.va_flags &
                    355:                                            (IMMUTABLE|APPEND)) == 0)
                    356:                                                maxprot |= VM_PROT_WRITE;
                    357:                                        else if (prot & PROT_WRITE)
                    358:                                                return (EPERM);
                    359:                                } else if ((prot & PROT_WRITE) != 0)
                    360:                                        return (EACCES);
                    361:                        } else
                    362:                                maxprot |= VM_PROT_WRITE;
                    363: 
                    364:                        handle = (void *)vp;
                    365:                }
                    366:        }
                    367: 
                    368:        if (user_size == 0) 
                    369:                return(0);
                    370: 
                    371:        /*
                    372:         *      We bend a little - round the start and end addresses
                    373:         *      to the nearest page boundary.
                    374:         */
                    375:        user_size = round_page(user_size);
                    376: 
                    377:        if (file_pos & PAGE_MASK)
                    378:                return (EINVAL);
                    379: 
                    380:        user_map = current_map();
                    381: 
                    382:        if ((flags & MAP_FIXED) == 0) {
                    383:                find_space = TRUE;
                    384:                user_addr = round_page(user_addr); 
                    385:        } else {
                    386:                if (user_addr != trunc_page(user_addr))
                    387:                        return (EINVAL);
                    388:                find_space = FALSE;
                    389:                (void) vm_deallocate(user_map, user_addr, user_size);
                    390:        }
                    391: 
                    392: 
                    393:        /*
                    394:         * Lookup/allocate object.
                    395:         */
                    396:        if (flags & MAP_ANON) {
                    397:                /*
                    398:                 * Unnamed anonymous regions always start at 0.
                    399:                 */
                    400:                if (handle == 0)
                    401:                        file_pos = 0;
                    402:        }
                    403: 
                    404:        if (handle == NULL) {
                    405:                pager = NULL;
                    406: #ifdef notyet
                    407: /* Hmm .. */
                    408: #if defined(VM_PROT_READ_IS_EXEC)
                    409:                if (prot & VM_PROT_READ)
                    410:                        prot |= VM_PROT_EXECUTE;
                    411: 
                    412:                if (maxprot & VM_PROT_READ)
                    413:                        maxprot |= VM_PROT_EXECUTE;
                    414: #endif
                    415: #endif
                    416:                result = vm_allocate(user_map, &user_addr, user_size, find_space);
                    417:                if (result != KERN_SUCCESS) 
                    418:                                goto out;
                    419:                
                    420:        } else {
                    421:                if (!vp->v_vm_info) {
                    422:                        vm_info_init(vp);
                    423:                }
                    424:                pager = vnode_pager_setup(vp,
                    425:                        vp->v_vm_info->pager, FALSE, FALSE);
                    426:                
                    427:                if (pager == NULL)
                    428:                        return (ENOMEM);
                    429:                /*
                    430:                 *  Set credentials:
                    431:                 *      FIXME: if we're writing the file we need a way to
                    432:                 *      ensure that someone doesn't replace our R/W creds
                    433:                 *      with ones that only work for read.
                    434:                 */
                    435:                vmp = vp->v_vm_info;
                    436:                if (vmp->cred == NULL) {                        
                    437:                        crhold(p->p_ucred);
                    438:                        vmp->cred = p->p_ucred;
                    439:                }
                    440:                docow = FALSE;
                    441:                if ((flags & (MAP_ANON|MAP_SHARED)) == 0) {
                    442:                        docow = TRUE;
                    443:                }
                    444: 
                    445: #ifdef notyet
                    446: /* Hmm .. */
                    447: #if defined(VM_PROT_READ_IS_EXEC)
                    448:                if (prot & VM_PROT_READ)
                    449:                        prot |= VM_PROT_EXECUTE;
                    450: 
                    451:                if (maxprot & VM_PROT_READ)
                    452:                        maxprot |= VM_PROT_EXECUTE;
                    453: #endif
                    454: #endif /* notyet */
                    455: 
                    456:                result = vm_map(user_map, &user_addr, user_size,
                    457:                                0, find_space, pager, file_pos, docow,
                    458:                          prot, maxprot, 
                    459:                                VM_INHERIT_DEFAULT);
                    460: 
                    461:                if (result != KERN_SUCCESS) 
                    462:                                goto out;
                    463: 
                    464:        }
                    465: 
                    466:        if (flags & (MAP_SHARED|MAP_INHERIT)) {
                    467:                result = vm_inherit(user_map, user_addr, user_size,
                    468:                                VM_INHERIT_SHARE);
                    469:                if (result != KERN_SUCCESS) {
                    470:                        (void) vm_deallocate(user_map, user_addr, user_size);
                    471:                        goto out;
                    472:                }
                    473:        }
                    474: 
                    475: out:
                    476:        switch (result) {
                    477:        case KERN_SUCCESS:
                    478:                if(!mapanon) {
                    479:                        *fdflags(p, uap->fd) |= UF_MAPPED;
                    480:                        if (ISMAPPABLEFILE(vp))
                    481:                                vp->v_vm_info->mapped = 1;
                    482:                }
                    483:                *retval = (register_t)(user_addr + pageoff);
                    484:                return (0);
                    485:        case KERN_INVALID_ADDRESS:
                    486:        case KERN_NO_SPACE:
                    487:                return (ENOMEM);
                    488:        case KERN_PROTECTION_FAILURE:
                    489:                return (EACCES);
                    490:        default:
                    491:                return (EINVAL);
                    492:        }
                    493:        /*NOTREACHED*/
                    494: }
                    495: 
                    496: struct msync_args {
                    497:                caddr_t addr;
                    498:                int len;
                    499:                int flags;
                    500: };
                    501: int
                    502: msync(p, uap, retval)
                    503:        struct proc *p;
                    504:        struct msync_args *uap;
                    505:        register_t *retval;
                    506: {
                    507:        vm_offset_t addr;
                    508:        vm_size_t size, pageoff;
                    509:        int flags;
                    510:        vm_map_t user_map;
                    511:        int rv;
                    512:        vm_sync_t sync_flags=0;
                    513: 
                    514:        addr = (vm_offset_t) uap->addr;
                    515:        pageoff = (addr & PAGE_MASK);
                    516:        addr -= pageoff;
                    517:        size = uap->len;
                    518:        size = (vm_size_t) round_page(size);
                    519:        flags = uap->flags;
                    520: 
                    521:        if (addr + size < addr)
                    522:                return(EINVAL);
                    523: 
                    524:        user_map = current_map();
                    525: 
                    526:        if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
                    527:                return (EINVAL);
                    528: 
                    529: #ifdef notyet
                    530:         /* XXX Gak!  If size is zero we are supposed to sync "all modified
                    531:         * pages with the region containing addr".  Unfortunately, we don't
                    532:         * really keep track of individual mmaps so we approximate by flushing
                    533:         * the range of the map entry containing addr. This can be incorrect
                    534:         * if the region splits or is coalesced with a neighbor.
                    535:         */
                    536:        if (size == 0) {
                    537:                vm_map_entry_t entry;
                    538: 
                    539:                vm_map_lock_read(map);
                    540:                rv = vm_map_lookup_entry(map, addr, &entry);
                    541:                vm_map_unlock_read(map);
                    542:                if (rv == FALSE)
                    543:                        return (EINVAL);
                    544:                addr = entry->start;
                    545:                size = entry->end - entry->start;
                    546:        }
                    547: #endif /* notyet */
                    548: 
                    549:        if (flags & MS_ASYNC) 
                    550:                sync_flags |= VM_SYNC_ASYNCHRONOUS;
                    551:        else 
                    552:                sync_flags |= VM_SYNC_SYNCHRONOUS;
                    553:                
                    554:        if (flags & MS_INVALIDATE)
                    555:                        sync_flags |= VM_SYNC_INVALIDATE;
                    556: 
                    557:        rv = vm_msync(user_map, addr, size, sync_flags);
                    558: 
                    559:        switch (rv) {
                    560:        case KERN_SUCCESS:
                    561:                break;
                    562:        case KERN_INVALID_ADDRESS:
                    563:                return (EINVAL);        /* Sun returns ENOMEM? */
                    564:        case KERN_FAILURE:
                    565:                return (EIO);
                    566:        default:
                    567:                return (EINVAL);
                    568:        }
                    569: 
                    570:        return (0);
                    571: 
                    572: }
                    573: 
                    574: 
                    575: mremap()
                    576: {
                    577:        /* Not yet implemented */
                    578:        return (EOPNOTSUPP);
                    579: }
                    580: 
                    581: struct munmap_args {
                    582:                caddr_t addr;
                    583:                int     len;
                    584: };
                    585: munmap(p, uap, retval)
                    586:        struct proc *p;
                    587:        struct munmap_args *uap;
                    588:        register_t *retval;
                    589: 
                    590: {
                    591:        vm_offset_t     user_addr;
                    592:        vm_size_t       user_size, pageoff;
                    593:        kern_return_t   result;
                    594: 
                    595:        user_addr = (vm_offset_t) uap->addr;
                    596:        user_size = (vm_size_t) uap->len;
                    597: 
                    598:        pageoff = (user_addr & PAGE_MASK);
                    599: 
                    600:        user_addr -= pageoff;
                    601:        user_size += pageoff;
                    602:        user_size = round_page(user_size);
                    603:        if (user_addr + user_size < user_addr)
                    604:                return(EINVAL);
                    605: 
                    606:        if (user_size == 0)
                    607:                return (0);
                    608: 
                    609:        /* Address range must be all in user VM space. */
                    610:        if (VM_MAX_ADDRESS > 0 && (user_addr + user_size > VM_MAX_ADDRESS))
                    611:                return (EINVAL);
                    612:        if (VM_MIN_ADDRESS > 0 && user_addr < VM_MIN_ADDRESS)
                    613:                return (EINVAL);
                    614: 
                    615: 
                    616:        result = vm_deallocate(current_map(), user_addr, user_size);
                    617:        if (result != KERN_SUCCESS) {
                    618:                return(EINVAL);
                    619:        }
                    620:        return(0);
                    621: }
                    622: 
                    623: void
                    624: munmapfd(p, fd)
                    625:        struct proc *p;
                    626:        int fd;
                    627: {
                    628:        /*
                    629:         * XXX should vm_deallocate any regions mapped to this file
                    630:         */
                    631:        *fdflags(p, fd) &= ~UF_MAPPED;
                    632: }
                    633: 
                    634: struct mprotect_args {
                    635:                caddr_t addr;
                    636:                int len;
                    637:                int prot;
                    638: };
                    639: int
                    640: mprotect(p, uap, retval)
                    641:        struct proc *p;
                    642:        struct mprotect_args *uap;
                    643:        register_t *retval;
                    644: {
                    645:        register vm_prot_t prot;
                    646:        vm_offset_t     user_addr;
                    647:        vm_size_t       user_size, pageoff;
                    648:        kern_return_t   result;
                    649:        vm_map_t        user_map;
                    650: 
                    651:        user_addr = (vm_offset_t) uap->addr;
                    652:        user_size = (vm_size_t) uap->len;
                    653:        prot = (vm_prot_t)(uap->prot & VM_PROT_ALL);
                    654: 
                    655: #ifdef notyet
                    656: /* Hmm .. */
                    657: #if defined(VM_PROT_READ_IS_EXEC)
                    658:        if (prot & VM_PROT_READ)
                    659:                prot |= VM_PROT_EXECUTE;
                    660: #endif
                    661: #endif /* notyet */
                    662: 
                    663:        pageoff = (user_addr & PAGE_MASK);
                    664:        user_addr -= pageoff;
                    665:        user_size += pageoff;
                    666:        user_size = round_page(user_size);
                    667:        if (user_addr + user_size < user_addr)
                    668:                return(EINVAL);
                    669: 
                    670:        user_map = current_map();
                    671: 
                    672:        result = vm_map_protect(user_map, user_addr, user_addr+user_size, prot,
                    673:                                         FALSE);
                    674:        switch (result) {
                    675:        case KERN_SUCCESS:
                    676:                return (0);
                    677:        case KERN_PROTECTION_FAILURE:
                    678:                return (EACCES);
                    679:        }
                    680:        return (EINVAL);
                    681: }
                    682: 
                    683: 
                    684: struct minherit_args {
                    685:        void *addr;
                    686:        size_t len;
                    687:        int inherit;
                    688: };
                    689: 
                    690: int
                    691: minherit(p, uap, retval)
                    692:        struct proc *p;
                    693:        struct minherit_args *uap;
                    694:        register_t *retval;
                    695: {
                    696:        vm_offset_t addr;
                    697:        vm_size_t size, pageoff;
                    698:        register vm_inherit_t inherit;
                    699:        vm_map_t        user_map;
                    700:        kern_return_t   result;
                    701: 
                    702:        addr = (vm_offset_t)uap->addr;
                    703:        size = uap->len;
                    704:        inherit = uap->inherit;
                    705: 
                    706:        pageoff = (addr & PAGE_MASK);
                    707:        addr -= pageoff;
                    708:        size += pageoff;
                    709:        size = (vm_size_t) round_page(size);
                    710:        if (addr + size < addr)
                    711:                return(EINVAL);
                    712: 
                    713:        user_map = current_map();
                    714:        result = vm_inherit(user_map, addr, size,
                    715:                                inherit);
                    716:        switch (result) {
                    717:        case KERN_SUCCESS:
                    718:                return (0);
                    719:        case KERN_PROTECTION_FAILURE:
                    720:                return (EACCES);
                    721:        }
                    722:        return (EINVAL);
                    723: }
                    724: 
                    725: struct madvise_args {
                    726:                caddr_t addr;
                    727:                int len;
                    728:                int behav;
                    729: };
                    730: /* ARGSUSED */
                    731: int
                    732: madvise(p, uap, retval)
                    733:        struct proc *p;
                    734:        struct madvise_args *uap;
                    735:        register_t *retval;
                    736: {
                    737:        vm_map_t user_map;
                    738:        vm_offset_t start, end;
                    739:        vm_behavior_t new_behavior;
                    740:        kern_return_t   result;
                    741: 
                    742:        /*
                    743:         * Check for illegal addresses.  Watch out for address wrap... Note
                    744:         * that VM_*_ADDRESS are not constants due to casts (argh).
                    745:         */
                    746:        if (VM_MAX_ADDRESS > 0 &&
                    747:                ((vm_offset_t) uap->addr + uap->len) > VM_MAX_ADDRESS)
                    748:                return (EINVAL);
                    749:        if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS)
                    750:                return (EINVAL);
                    751: 
                    752:        if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
                    753:                return (EINVAL);
                    754: 
                    755:        /*
                    756:         * Since this routine is only advisory, we default to conservative
                    757:         * behavior.
                    758:         */
                    759:        start = trunc_page((vm_offset_t) uap->addr);
                    760:        end = round_page((vm_offset_t) uap->addr + uap->len);
                    761:        
                    762:        user_map = current_map();
                    763: 
                    764:        switch (uap->behav) {
                    765:                case MADV_RANDOM:
                    766:                        new_behavior = VM_BEHAVIOR_RANDOM;
                    767:                case MADV_SEQUENTIAL: 
                    768:                        new_behavior = VM_BEHAVIOR_SEQUENTIAL;
                    769:                case MADV_NORMAL:
                    770:                default:
                    771:                        new_behavior = VM_BEHAVIOR_DEFAULT;
                    772:        }
                    773: 
                    774:        result = vm_behavior_set(user_map, start, end, uap->behav);
                    775:        switch (result) {
                    776:                case KERN_SUCCESS:
                    777:                        return (0);
                    778:                case KERN_INVALID_ADDRESS:
                    779:                        return (EINVAL);
                    780:        }
                    781: 
                    782:        return (EINVAL);
                    783: }
                    784: 
                    785: struct mincore_args {
                    786:        const void *addr;
                    787:        size_t len;
                    788:        char *vec;
                    789: };
                    790: /* ARGSUSED */
                    791: int
                    792: mincore(p, uap, retval)
                    793:        struct proc *p;
                    794:        struct mincore_args *uap;
                    795:        register_t *retval;
                    796: {
                    797:        vm_offset_t addr, first_addr;
                    798:        vm_offset_t end;
                    799:        vm_map_t map;
                    800:        char *vec;
                    801:        int error;
                    802:        int vecindex, lastvecindex;
                    803:        int mincoreinfo=0;
                    804:        int pqueryinfo;
                    805:        kern_return_t   ret;
                    806:        int numref;
                    807: 
                    808:        map = current_map();
                    809: 
                    810:        /*
                    811:         * Make sure that the addresses presented are valid for user
                    812:         * mode.
                    813:         */
                    814:        first_addr = addr = trunc_page((vm_offset_t) uap->addr);
                    815:        end = addr + (vm_size_t)round_page(uap->len);
                    816: 
                    817:        if (VM_MAX_ADDRESS > 0 && end > VM_MAX_ADDRESS)
                    818:                return (EINVAL);
                    819:        if (end < addr)
                    820:                return (EINVAL);
                    821: 
                    822:        /*
                    823:         * Address of byte vector
                    824:         */
                    825:        vec = uap->vec;
                    826: 
                    827:        map = current_map();
                    828: 
                    829:        /*
                    830:         * Do this on a map entry basis so that if the pages are not
                    831:         * in the current processes address space, we can easily look
                    832:         * up the pages elsewhere.
                    833:         */
                    834:        lastvecindex = -1;
                    835:        for(addr; addr < end; addr += PAGE_SIZE) {
                    836:                pqueryinfo = 0;
                    837:                ret = vm_map_page_query(map, addr, &pqueryinfo, &numref);
                    838:                if (ret != KERN_SUCCESS) 
                    839:                        pqueryinfo = 0;
                    840:                mincoreinfo = 0;
                    841:                if (pqueryinfo & VM_PAGE_QUERY_PAGE_PRESENT)
                    842:                        mincoreinfo |= MINCORE_INCORE;
                    843:                if (pqueryinfo & VM_PAGE_QUERY_PAGE_REF)
                    844:                        mincoreinfo |= MINCORE_REFERENCED;
                    845:                if (pqueryinfo & VM_PAGE_QUERY_PAGE_DIRTY)
                    846:                        mincoreinfo |= MINCORE_MODIFIED;
                    847:                
                    848:                
                    849:                /*
                    850:                 * calculate index into user supplied byte vector
                    851:                 */
                    852:                vecindex = (addr - first_addr)>> PAGE_SHIFT;
                    853: 
                    854:                /*
                    855:                 * If we have skipped map entries, we need to make sure that
                    856:                 * the byte vector is zeroed for those skipped entries.
                    857:                 */
                    858:                while((lastvecindex + 1) < vecindex) {
                    859:                        error = subyte( vec + lastvecindex, 0);
                    860:                        if (error) {
                    861:                                return (EFAULT);
                    862:                        }
                    863:                        ++lastvecindex;
                    864:                }
                    865: 
                    866:                /*
                    867:                 * Pass the page information to the user
                    868:                 */
                    869:                error = subyte( vec + vecindex, mincoreinfo);
                    870:                if (error) {
                    871:                        return (EFAULT);
                    872:                }
                    873:                lastvecindex = vecindex;
                    874:        }
                    875: 
                    876: 
                    877:        /*
                    878:         * Zero the last entries in the byte vector.
                    879:         */
                    880:        vecindex = (end - first_addr) >> PAGE_SHIFT;
                    881:        while((lastvecindex + 1) < vecindex) {
                    882:                error = subyte( vec + lastvecindex, 0);
                    883:                if (error) {
                    884:                        return (EFAULT);
                    885:                }
                    886:                ++lastvecindex;
                    887:        }
                    888:        
                    889:        return (0);
                    890: }
                    891: 
                    892: struct mlock_args {
                    893:                caddr_t addr;
                    894:                size_t len;
                    895: };
                    896: 
                    897: #define BSD_DUMMY_HOST 1
                    898: 
                    899: int
                    900: mlock(p, uap, retval)
                    901:        struct proc *p;
                    902:        struct mlock_args *uap;
                    903:        register_t *retval;
                    904: {
                    905:        vm_map_t user_map;
                    906:        vm_offset_t addr;
                    907:        vm_size_t size, pageoff;
                    908:        int error;
                    909:        kern_return_t   result;
                    910: 
                    911:        addr = (vm_offset_t) uap->addr;
                    912:        size = uap->len;
                    913: 
                    914:        pageoff = (addr & PAGE_MASK);
                    915:        addr -= pageoff;
                    916:        size += pageoff;
                    917:        size = (vm_size_t) round_page(size);
                    918: 
                    919:        /* disable wrap around */
                    920:        if (addr + size < addr)
                    921:                return (EINVAL);
                    922: #ifdef notyet 
                    923: /* Hmm.. What am I going to do with this? */
                    924:        if (atop(size) + cnt.v_wire_count > vm_page_max_wired)
                    925:                return (EAGAIN);
                    926: #ifdef pmap_wired_count
                    927:        if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
                    928:            p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
                    929:                return (ENOMEM);
                    930: #else
                    931:        error = suser(p->p_ucred, &p->p_acflag);
                    932:        if (error)
                    933:                return (error);
                    934: #endif
                    935: #endif /* notyet */
                    936: 
                    937:        user_map = current_map();
                    938: 
                    939:        /* vm_wire */
                    940:        result = vm_wire(BSD_DUMMY_HOST, user_map, addr, size, VM_PROT_ALL);
                    941:        return (result == KERN_SUCCESS ? 0 : ENOMEM);
                    942: }
                    943: 
                    944: struct munlock_args {
                    945:                caddr_t addr;
                    946:                size_t len;
                    947: };
                    948: int
                    949: munlock(p, uap, retval)
                    950:        struct proc *p;
                    951:        struct munlock_args *uap;
                    952:        register_t *retval;
                    953: {
                    954:        vm_offset_t addr;
                    955:        vm_size_t size, pageoff;
                    956:        int error;
                    957:        vm_map_t user_map;
                    958:        kern_return_t   result;
                    959: 
                    960:        addr = (vm_offset_t) uap->addr;
                    961:        size = uap->len;
                    962: 
                    963:        pageoff = (addr & PAGE_MASK);
                    964:        addr -= pageoff;
                    965:        size += pageoff;
                    966:        size = (vm_size_t) round_page(size);
                    967: 
                    968:        /* disable wrap around */
                    969:        if (addr + size < addr)
                    970:                return (EINVAL);
                    971: 
                    972: #ifdef notyet 
                    973: /* Hmm.. What am I going to do with this? */
                    974: #ifndef pmap_wired_count
                    975:        error = suser(p->p_ucred, &p->p_acflag);
                    976:        if (error)
                    977:                return (error);
                    978: #endif
                    979: #endif /* notyet */
                    980: 
                    981:        user_map = current_map();
                    982: 
                    983:        /* vm_wire */
                    984:        result = vm_wire(BSD_DUMMY_HOST, user_map, addr, size, VM_PROT_NONE);
                    985:        return (result == KERN_SUCCESS ? 0 : ENOMEM);
                    986: }
                    987: 
                    988: 
                    989: struct mlockall_args {
                    990:        int     how;
                    991: };
                    992: 
                    993: int
                    994: mlockall(p, uap)
                    995:        struct proc *p;
                    996:        struct mlockall_args *uap;
                    997: {
                    998:        return 0;
                    999: }
                   1000: 
                   1001: struct munlockall_args {
                   1002:        int     how;
                   1003: };
                   1004: 
                   1005: int
                   1006: munlockall(p, uap)
                   1007:        struct proc *p;
                   1008:        struct munlockall_args *uap;
                   1009: {
                   1010:        return 0;
                   1011: }
                   1012: 
                   1013: 
                   1014: /* BEGIN DEFUNCT */
                   1015: struct obreak_args {
                   1016:        char *nsiz;
                   1017: };
                   1018: obreak(p, uap, retval)
                   1019:        struct proc *p;
                   1020:        struct obreak_args *uap;
                   1021:        register_t *retval;
                   1022: {
                   1023:        /* Not implemented, obsolete */
                   1024:        return (ENOMEM);
                   1025: }
                   1026: 
                   1027: int    both;
                   1028: 
                   1029: ovadvise()
                   1030: {
                   1031: 
                   1032: #ifdef lint
                   1033:        both = 0;
                   1034: #endif
                   1035: }
                   1036: /* END DEFUNCT */
                   1037: #if 1
                   1038: int print_map_addr=0;
                   1039: #endif /* 1 */
                   1040: 
                   1041: kern_return_t map_fd(
                   1042:        int             fd,
                   1043:        vm_offset_t     offset,
                   1044:        vm_offset_t     *va,
                   1045:        boolean_t       findspace,
                   1046:        vm_size_t       size)
                   1047: {
                   1048:        kern_return_t ret;
                   1049:        boolean_t funnel_state;
                   1050: 
                   1051:        funnel_state = thread_set_funneled(TRUE);
                   1052: 
                   1053:        ret = map_fd_funneled( fd, offset, va, findspace, size);
                   1054: 
                   1055:        (void) thread_set_funneled(funnel_state);
                   1056: 
                   1057:        return ret;
                   1058: }
                   1059: 
                   1060: kern_return_t map_fd_funneled(
                   1061:        int             fd,
                   1062:        vm_offset_t     offset,
                   1063:        vm_offset_t     *va,
                   1064:        boolean_t       findspace,
                   1065:        vm_size_t       size)
                   1066: {
                   1067:        kern_return_t   result;
                   1068:        struct file     *fp;
                   1069:        struct vnode    *vp;
                   1070:        void *  pager;
                   1071:        vm_offset_t     map_addr=0;
                   1072:        vm_size_t       map_size;
                   1073:        vm_map_copy_t   tmp;
                   1074:        int             err=0;
                   1075:        vm_map_t        my_map;
                   1076:        struct proc     *p =(struct proc *)(get_bsdtask_info(current_task()));
                   1077: #if 0
                   1078:        extern int print_map_addr;
                   1079: #endif /* 0 */
                   1080: 
                   1081:        /*
                   1082:         *      Find the inode; verify that it's a regular file.
                   1083:         */
                   1084: 
                   1085:        err = fdgetf(p, fd, &fp);
                   1086:        if (err)
                   1087:                return(err);
                   1088:        
                   1089:        if (fp->f_type != DTYPE_VNODE)
                   1090:                return(KERN_INVALID_ARGUMENT);
                   1091:        vp = (struct vnode *)fp->f_data;
                   1092: 
                   1093:        if (vp->v_type != VREG)
                   1094:                return (KERN_INVALID_ARGUMENT);
                   1095: 
                   1096:        map_size = round_page(size);
                   1097: 
                   1098:        /*
                   1099:         * Allow user to map in a zero length file.
                   1100:         */
                   1101:        if (size == 0)
                   1102:                return (KERN_SUCCESS);
                   1103:        /*
                   1104:         *      Map in the file.
                   1105:         */
                   1106:        if (!vp->v_vm_info) {
                   1107:                vm_info_init(vp);
                   1108:        }
                   1109: 
                   1110:        pager = (void *) vnode_pager_setup(vp, vp->v_vm_info->pager, FALSE, TRUE);
                   1111:        if (pager == NULL)
                   1112:                return (KERN_FAILURE);
                   1113: 
                   1114: 
                   1115:        my_map = current_map();
                   1116: 
                   1117:        result = vm_map(
                   1118:                        my_map,
                   1119:                        &map_addr, map_size, (vm_offset_t)0, TRUE,
                   1120:                        pager, offset, TRUE,
                   1121:                        VM_PROT_DEFAULT, VM_PROT_ALL,
                   1122:                        VM_INHERIT_DEFAULT);
                   1123:        if (result != KERN_SUCCESS)
                   1124:                return (result);
                   1125: 
                   1126: 
                   1127:        if (!findspace) {
                   1128:                vm_offset_t     dst_addr;
                   1129:                vm_map_copy_t   tmp;
                   1130: 
                   1131:                if (copyin(va, &dst_addr, sizeof (dst_addr))    ||
                   1132:                                        trunc_page(dst_addr) != dst_addr) {
                   1133:                        (void) vm_map_remove(
                   1134:                                        my_map,
                   1135:                                        map_addr, map_addr + map_size,
                   1136:                                        VM_MAP_NO_FLAGS);
                   1137:                        return (KERN_INVALID_ADDRESS);
                   1138:                }
                   1139: 
                   1140:                result = vm_map_copyin(
                   1141:                                my_map,
                   1142:                                map_addr, map_size, TRUE,
                   1143:                                &tmp);
                   1144:                if (result != KERN_SUCCESS) {
                   1145:                        
                   1146:                        (void) vm_map_remove(
                   1147:                                        my_map,
                   1148:                                        map_addr, map_addr + map_size,
                   1149:                                        VM_MAP_NO_FLAGS);
                   1150:                        return (result);
                   1151:                }
                   1152: 
                   1153:                result = vm_map_copy_overwrite(
                   1154:                                        my_map,
                   1155:                                        dst_addr, tmp, FALSE);
                   1156:                if (result != KERN_SUCCESS) {
                   1157:                        vm_map_copy_discard(tmp);
                   1158:                        return (result);
                   1159:                }
                   1160:        }
                   1161:        else {
                   1162:                if (copyout(&map_addr, va, sizeof (map_addr))) {
                   1163:                        (void) vm_map_remove(
                   1164:                                        my_map,
                   1165:                                        map_addr, map_addr + map_size,
                   1166:                                        VM_MAP_NO_FLAGS);
                   1167:                        return (KERN_INVALID_ADDRESS);
                   1168:                }
                   1169:        }
                   1170:        if (ISMAPPABLEFILE(vp))
                   1171:              vp->v_vm_info->mapped = 1;
                   1172: 
                   1173:        /*
                   1174:         * Set credentials.
                   1175:         */
                   1176:        if (vp->v_vm_info->cred == NULL) {
                   1177:                crhold(current_proc()->p_ucred);
                   1178:                vp->v_vm_info->cred = current_proc()->p_ucred;
                   1179:        }
                   1180: 
                   1181:        return (KERN_SUCCESS);
                   1182: }

unix.superglobalmegacorp.com

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