Annotation of XNU/bsd/kern/posix_shm.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) 1990, 1996-1998 Apple Computer, Inc.
                     24:  *     All Rights Reserved.
                     25:  */
                     26: /*
                     27:  * posix_shm.c : Support for POSIX shared memory apis
                     28:  *
                     29:  *     File:   posix_shm.c
                     30:  *     Author: Ananthakrishna Ramesh
                     31:  *
                     32:  * HISTORY
                     33:  * 2-Sep-1999  A.Ramesh
                     34:  *     Created for MacOSX
                     35:  *
                     36:  */
                     37: 
                     38: #include <sys/cdefs.h>
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41: #include <sys/kernel.h>
                     42: #include <sys/file.h>
                     43: #include <sys/filedesc.h>
                     44: #include <sys/stat.h>
                     45: #include <sys/buf.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/mount.h>
                     48: #include <sys/namei.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/ioctl.h>
                     51: #include <sys/tty.h>
                     52: #include <sys/malloc.h>
                     53: #include <sys/mman.h>
                     54: #include <sys/stat.h>
                     55: #include <mach/mach_types.h>
                     56: #include <mach/vm_prot.h>
                     57: #include <mach/vm_inherit.h>
                     58: #include <mach/kern_return.h>
                     59: #include <mach/memory_object_control.h>
                     60: 
                     61: 
                     62: #define        PSHMNAMLEN      31      /* maximum name segment length we bother with */
                     63: 
                     64: struct pshminfo {
                     65:        unsigned int    pshm_flags;
                     66:        unsigned int    pshm_usecount;
                     67:        off_t           pshm_length;
                     68:        mode_t          pshm_mode;
                     69:        uid_t           pshm_uid;
                     70:        gid_t           pshm_gid;
                     71:        char            pshm_name[PSHMNAMLEN + 1];      /* segment name */
                     72:        void *          pshm_memobject;
                     73: #if DIAGNOSTIC
                     74:        unsigned int    pshm_readcount;
                     75:        unsigned int    pshm_writecount;
                     76:        struct proc *   pshm_proc;
                     77: #endif /* DIAGNOSTIC */
                     78: };
                     79: #define PSHMINFO_NULL (struct pshminfo *)0
                     80: 
                     81: #define        PSHM_NONE       1
                     82: #define        PSHM_DEFINED    2
                     83: #define        PSHM_ALLOCATED  4
                     84: #define        PSHM_MAPPED     8
                     85: #define        PSHM_INUSE      0x10
                     86: #define        PSHM_REMOVED    0x20
                     87: #define        PSHM_INCREATE   0x40
                     88: #define        PSHM_INDELETE   0x80
                     89: 
                     90: struct pshmcache {
                     91:        LIST_ENTRY(pshmcache) pshm_hash;        /* hash chain */
                     92:        struct  pshminfo *pshminfo;             /* vnode the name refers to */
                     93:        int     pshm_nlen;              /* length of name */
                     94:        char    pshm_name[PSHMNAMLEN + 1];      /* segment name */
                     95: };
                     96: #define PSHMCACHE_NULL (struct pshmcache *)0
                     97: 
                     98: struct pshmstats {
                     99:        long    goodhits;               /* hits that we can really use */
                    100:        long    neghits;                /* negative hits that we can use */
                    101:        long    badhits;                /* hits we must drop */
                    102:        long    falsehits;              /* hits with id mismatch */
                    103:        long    miss;           /* misses */
                    104:        long    longnames;              /* long names that ignore cache */
                    105: };
                    106: 
                    107: struct pshmname {
                    108:        char    *pshm_nameptr;  /* pointer to looked up name */
                    109:        long    pshm_namelen;   /* length of looked up component */
                    110:        u_long  pshm_hash;      /* hash value of looked up name */
                    111: };
                    112: 
                    113: struct pshmnode {
                    114:        off_t  mapp_addr;
                    115:        size_t  map_size;
                    116:        struct pshminfo *pinfo;
                    117:        unsigned int    pshm_usecount;
                    118: #if DIAGNOSTIC
                    119:        unsigned int readcnt;
                    120:        unsigned int writecnt;
                    121: #endif
                    122: };
                    123: #define PSHMNODE_NULL (struct pshmnode *)0
                    124: 
                    125: 
                    126: #define PSHMHASH(pnp) \
                    127:        (&pshmhashtbl[(pnp)->pshm_hash & pshmhash])
                    128: LIST_HEAD(pshmhashhead, pshmcache) *pshmhashtbl;       /* Hash Table */
                    129: u_long pshmhash;                               /* size of hash table - 1 */
                    130: long   pshmnument;                     /* number of cache entries allocated */
                    131: struct pshmstats pshmstats;            /* cache effectiveness statistics */
                    132: static pshm_init =0; 
                    133: 
                    134: int pshm_read  __P((struct file *fp, struct uio *uio,
                    135:                                            struct ucred *cred));
                    136: int pshm_write  __P((struct file *fp, struct uio *uio,
                    137:                                            struct ucred *cred));
                    138: int pshm_ioctl  __P((struct file *fp, u_long com,
                    139:                                            caddr_t data, struct proc *p));
                    140: int pshm_select  __P((struct file *fp, int which,
                    141:                                            struct proc *p));
                    142: int pshm_closefile  __P((struct file *fp, struct proc *p));
                    143: 
                    144: struct         fileops pshmops =
                    145:        { pshm_read, pshm_write, pshm_ioctl, pshm_select, pshm_closefile };
                    146: 
                    147: 
                    148: 
                    149: /*
                    150:  * Lookup an entry in the cache 
                    151:  * 
                    152:  * 
                    153:  * status of -1 is returned if matches
                    154:  * If the lookup determines that the name does not exist
                    155:  * (negative cacheing), a status of ENOENT is returned. If the lookup
                    156:  * fails, a status of zero is returned.
                    157:  */
                    158: 
                    159: int
                    160: pshm_cache_search(pshmp, pnp, pcache)
                    161:        struct pshminfo **pshmp;
                    162:        struct pshmname *pnp;
                    163:        struct pshmcache **pcache;
                    164: {
                    165:        register struct pshmcache *pcp, *nnp;
                    166:        register struct pshmhashhead *pcpp;
                    167: 
                    168:        if (pnp->pshm_namelen > PSHMNAMLEN) {
                    169:                pshmstats.longnames++;
                    170:                return (0);
                    171:        }
                    172: 
                    173:        pcpp = PSHMHASH(pnp);
                    174:        for (pcp = pcpp->lh_first; pcp != 0; pcp = nnp) {
                    175:                nnp = pcp->pshm_hash.le_next;
                    176:                if (pcp->pshm_nlen == pnp->pshm_namelen &&
                    177:                    !bcmp(pcp->pshm_name, pnp->pshm_nameptr,                                            (u_int)pcp-> pshm_nlen))
                    178:                        break;
                    179:        }
                    180: 
                    181:        if (pcp == 0) {
                    182:                pshmstats.miss++;
                    183:                return (0);
                    184:        }
                    185: 
                    186:        /* We found a "positive" match, return the vnode */
                    187:         if (pcp->pshminfo) {
                    188:                pshmstats.goodhits++;
                    189:                /* TOUCH(ncp); */
                    190:                *pshmp = pcp->pshminfo;
                    191:                *pcache = pcp;
                    192:                return (-1);
                    193:        }
                    194: 
                    195:        /*
                    196:         * We found a "negative" match, ENOENT notifies client of this match.
                    197:         * The nc_vpid field records whether this is a whiteout.
                    198:         */
                    199:        pshmstats.neghits++;
                    200:        return (ENOENT);
                    201: }
                    202: 
                    203: /*
                    204:  * Add an entry to the cache.
                    205:  */
                    206: int
                    207: pshm_cache_add(pshmp, pnp)
                    208:        struct pshminfo *pshmp;
                    209:        struct pshmname *pnp;
                    210: {
                    211:        register struct pshmcache *pcp;
                    212:        register struct pshmhashhead *pcpp;
                    213:        register struct pshminfo *dpinfo;
                    214:        register struct pshmcache *dpcp;
                    215: 
                    216: #if DIAGNOSTIC
                    217:        if (pnp->pshm_namelen > NCHNAMLEN)
                    218:                panic("cache_enter: name too long");
                    219: #endif
                    220: 
                    221:        /*
                    222:         * We allocate a new entry if we are less than the maximum
                    223:         * allowed and the one at the front of the LRU list is in use.
                    224:         * Otherwise we use the one at the front of the LRU list.
                    225:         */
                    226:        pcp = (struct pshmcache *)_MALLOC(sizeof(struct pshmcache), M_SHM, M_WAITOK);
                    227:        /*  if the entry has already been added by some one else return */
                    228:        if (pshm_cache_search(&dpinfo, pnp, &dpcp) == -1) {
                    229:                _FREE(pcp, M_SHM);
                    230:                return(EEXIST);
                    231:        }
                    232:        pshmnument++;
                    233: 
                    234:        bzero(pcp, sizeof(struct pshmcache));
                    235:        /*
                    236:         * Fill in cache info, if vp is NULL this is a "negative" cache entry.
                    237:         * For negative entries, we have to record whether it is a whiteout.
                    238:         * the whiteout flag is stored in the nc_vpid field which is
                    239:         * otherwise unused.
                    240:         */
                    241:        pcp->pshminfo = pshmp;
                    242:        pcp->pshm_nlen = pnp->pshm_namelen;
                    243:        bcopy(pnp->pshm_nameptr, pcp->pshm_name, (unsigned)pcp->pshm_nlen);
                    244:        pcpp = PSHMHASH(pnp);
                    245: #if DIAGNOSTIC
                    246:        {
                    247:                register struct pshmcache *p;
                    248: 
                    249:                for (p = pcpp->lh_first; p != 0; p = p->pshm_hash.le_next)
                    250:                        if (p == pcp)
                    251:                                panic("cache_enter: duplicate");
                    252:        }
                    253: #endif
                    254:        LIST_INSERT_HEAD(pcpp, pcp, pshm_hash);
                    255:        return(0);
                    256: }
                    257: 
                    258: /*
                    259:  * Name cache initialization, from vfs_init() when we are booting
                    260:  */
                    261: void
                    262: pshm_cache_init()
                    263: {
                    264:        pshmhashtbl = hashinit(desiredvnodes, M_SHM, &pshmhash);
                    265:        pshm_init = 1;
                    266: }
                    267: 
                    268: /*
                    269:  * Invalidate a all entries to particular vnode.
                    270:  * 
                    271:  * We actually just increment the v_id, that will do it. The entries will
                    272:  * be purged by lookup as they get found. If the v_id wraps around, we
                    273:  * need to ditch the entire cache, to avoid confusion. No valid vnode will
                    274:  * ever have (v_id == 0).
                    275:  */
                    276: void
                    277: pshm_cache_purge(void)
                    278: {
                    279:        struct pshmcache *pcp;
                    280:        struct pshmhashhead *pcpp;
                    281: 
                    282:        for (pcpp = &pshmhashtbl[pshmhash]; pcpp >= pshmhashtbl; pcpp--) {
                    283:                while (pcp = pcpp->lh_first)
                    284:                        pshm_cache_delete(pcp);
                    285:        }
                    286: }
                    287: 
                    288: pshm_cache_delete(pcp)
                    289:        struct pshmcache *pcp;
                    290: {
                    291: #if DIAGNOSTIC
                    292:        if (pcp->pshm_hash.le_prev == 0)
                    293:                panic("namecache purge le_prev");
                    294:        if (pcp->pshm_hash.le_next == pcp)
                    295:                panic("namecache purge le_next");
                    296: #endif /* DIAGNOSTIC */
                    297:        LIST_REMOVE(pcp, pshm_hash);
                    298:        pcp->pshm_hash.le_prev = 0;     
                    299:        pshmnument--;
                    300: }
                    301: 
                    302: 
                    303: struct shm_open_args {
                    304: const char *name;
                    305: int oflag;
                    306: int mode;
                    307: };
                    308: 
                    309: int
                    310: shm_open(p, uap, retval)
                    311: struct proc *p;
                    312: register struct shm_open_args *uap;
                    313: register_t *retval;
                    314: {
                    315:        register struct filedesc *fdp = p->p_fd;
                    316:        register struct file *fp;
                    317:        register struct vnode *vp;
                    318:        int flags, i;
                    319:        struct file *nfp;
                    320:        int type, indx, error;
                    321:        struct pshmname nd;
                    322:        struct pshminfo *pinfo;
                    323:        extern struct fileops pshmops;
                    324:        char * pnbuf;
                    325:        char * nameptr;
                    326:        char * cp;
                    327:        size_t pathlen, plen;
                    328:        int fmode ;
                    329:        int cmode = uap->mode;
                    330:        int incache = 0;
                    331:        struct pshmnode * pnode = PSHMNODE_NULL;
                    332:        struct pshmcache * pcache = PSHMCACHE_NULL;
                    333: 
                    334:        if(!pshm_init)
                    335:                pshm_cache_init();
                    336: 
                    337:        pinfo = PSHMINFO_NULL;
                    338: 
                    339:        MALLOC_ZONE(pnbuf, caddr_t,
                    340:                        MAXPATHLEN, M_NAMEI, M_WAITOK);
                    341:        pathlen = MAXPATHLEN;
                    342:        error = copyinstr(uap->name, pnbuf,
                    343:                MAXPATHLEN, &pathlen);
                    344:        if (error) {
                    345:                goto bad;
                    346:        }
                    347:        if (pathlen > PSHMNAMLEN) {
                    348:                error = ENAMETOOLONG;
                    349:                goto bad;
                    350:        }
                    351: 
                    352: 
                    353: #ifdef PSXSHM_NAME_RESTRICT
                    354:        nameptr = pnbuf;
                    355:        if (*nameptr == '/') {
                    356:                while (*(nameptr++) == '/') {
                    357:                        plen--;
                    358:                        error = EINVAL;
                    359:                        goto bad;
                    360:                }
                    361:         } else {
                    362:                error = EINVAL;
                    363:                goto bad;
                    364:        }
                    365: #endif /* PSXSHM_NAME_RESTRICT */
                    366: 
                    367:        plen = pathlen;
                    368:        nameptr = pnbuf;
                    369:        nd.pshm_nameptr = nameptr;
                    370:        nd.pshm_namelen = plen;
                    371:        nd. pshm_hash =0;
                    372: 
                    373:         for (cp = nameptr, i=1; *cp != 0 && i <= plen; i++, cp++) {
                    374:                nd.pshm_hash += (unsigned char)*cp * i;
                    375:        }
                    376: 
                    377:        error = pshm_cache_search(&pinfo, &nd, &pcache);
                    378: 
                    379:        if (error == ENOENT) {
                    380:                error = EINVAL;
                    381:                goto bad;
                    382: 
                    383:        }
                    384:        if (!error) {
                    385:                incache = 0;
                    386:        } else
                    387:                incache = 1;
                    388:        fmode = FFLAGS(uap->oflag);
                    389:        if ((fmode & (FREAD | FWRITE))==0)
                    390:                return(EINVAL);
                    391: 
                    392:        if (error = falloc(p, &nfp, &indx))
                    393:                return (error);
                    394:        fp = nfp;
                    395: 
                    396:        cmode &=  ALLPERMS;
                    397: 
                    398:        if (fmode & O_CREAT) {
                    399:                /* shm obj exists and opened O_EXCL */
                    400:                if ((fmode & O_EXCL) && incache) {
                    401: #if notyet
                    402:                        if (pinfo->pshm_flags & PSHM_INDELETE) {
                    403:                        }
                    404: #endif 
                    405:                        error = EEXIST;
                    406:                        goto bad;
                    407:                }
                    408:                pinfo = (struct pshminfo *)_MALLOC(sizeof(struct pshminfo), M_SHM, M_WAITOK);
                    409:                bzero(pinfo, sizeof(struct pshminfo));
                    410:                pinfo->pshm_flags = PSHM_DEFINED | PSHM_INCREATE;
                    411:                pinfo->pshm_usecount = 1;
                    412:                pinfo->pshm_mode = cmode;
                    413:                pinfo->pshm_uid = p->p_ucred->cr_uid;
                    414:                pinfo->pshm_gid = p->p_ucred->cr_gid;
                    415: 
                    416:        } else {
                    417:        /* O_CREAT  is not set and the shm obecj does not exist */
                    418:                if (!incache) {
                    419:                        error = ENOENT;
                    420:                        goto bad;
                    421:                }
                    422:                if( pinfo->pshm_flags & PSHM_INDELETE) {
                    423:                        error = ENOENT;
                    424:                        goto bad;
                    425:                }       
                    426:                if (error = pshm_access(pinfo, fmode, p->p_ucred, p))
                    427:                        goto bad;
                    428:        }
                    429:        if (fmode & O_TRUNC) {
                    430:                error = EINVAL;
                    431:                goto bad1;
                    432:        }
                    433: #if DIAGNOSTIC 
                    434:        if (fmode & FWRITE)
                    435:                pinfo->pshm_writecount++;
                    436:        if (fmode & FREAD)
                    437:                pinfo->pshm_readcount++;
                    438: #endif
                    439:        pnode = (struct pshmnode *)_MALLOC(sizeof(struct pshmnode), M_SHM, M_WAITOK);
                    440:        bzero(pnode, sizeof(struct pshmnode));
                    441: 
                    442:        if (!incache) {
                    443:                if (error = pshm_cache_add(pinfo, &nd)) {
                    444:                goto bad2;
                    445:                }
                    446:        }
                    447:        pinfo->pshm_flags &= ~PSHM_INCREATE;
                    448:        pinfo->pshm_usecount++;
                    449:        pnode->pinfo = pinfo;
                    450:        fp->f_flag = flags & FMASK;
                    451:        fp->f_type = DTYPE_PSXSHM;
                    452:        fp->f_ops = &pshmops;
                    453:        fp->f_data = (caddr_t)pnode;
                    454:        *fdflags(p, indx) &= ~UF_RESERVED;
                    455:        *retval = indx;
                    456:        return (0);
                    457: bad2:
                    458:        _FREE(pnode, M_SHM);
                    459:                
                    460: bad1:
                    461:        _FREE(pinfo, M_SHM);
                    462:                
                    463: bad:
                    464:        _FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
                    465:        return (error);
                    466: }
                    467: 
                    468: 
                    469: /* ARGSUSED */
                    470: int
                    471: pshm_truncate(p, fp, fd, length, retval)
                    472:        struct proc *p;
                    473:        struct file *fp;
                    474:        int fd;
                    475:        off_t length;
                    476:        register_t *retval;
                    477: {
                    478:        struct pshminfo * pinfo;
                    479:        struct pshmnode * pnode ;
                    480:        kern_return_t kret;
                    481:        vm_offset_t user_addr;
                    482:        void * mem_object;
                    483:        vm_size_t size;
                    484: 
                    485:        if (fp->f_type != DTYPE_PSXSHM) {
                    486:                return(EINVAL);
                    487:        }
                    488:        
                    489: 
                    490:        if (((pnode = (struct pshmnode *)fp->f_data)) == PSHMNODE_NULL )
                    491:                return(EINVAL);
                    492: 
                    493:        if ((pinfo = pnode->pinfo) == PSHMINFO_NULL)
                    494:                return(EINVAL);
                    495:        if ((pinfo->pshm_flags & (PSHM_DEFINED | PSHM_ALLOCATED)) 
                    496:                        != PSHM_DEFINED) {
                    497:                return(EINVAL);
                    498:        }
                    499: 
                    500:        size = round_page (length);
                    501:        kret = vm_allocate(current_map(), &user_addr, size, TRUE);
                    502:        if (kret != KERN_SUCCESS) 
                    503:                goto out;
                    504: 
                    505:        kret = mach_make_memory_entry (current_map(), &size,
                    506:                        user_addr, VM_PROT_DEFAULT, &mem_object, 0);
                    507: 
                    508:        if (kret != KERN_SUCCESS) 
                    509:                goto out;
                    510:        
                    511:        vm_deallocate(current_map(), user_addr, size);
                    512: 
                    513:        pinfo->pshm_flags &= ~PSHM_DEFINED;
                    514:        pinfo->pshm_flags = PSHM_ALLOCATED;
                    515:        pinfo->pshm_memobject = mem_object;
                    516:        pinfo->pshm_length = size;
                    517:        return(0);
                    518: 
                    519: out:
                    520:        switch (kret) {
                    521:        case KERN_INVALID_ADDRESS:
                    522:        case KERN_NO_SPACE:
                    523:                return (ENOMEM);
                    524:        case KERN_PROTECTION_FAILURE:
                    525:                return (EACCES);
                    526:        default:
                    527:                return (EINVAL);
                    528:        
                    529:        }
                    530: }
                    531: 
                    532: int
                    533: pshm_stat(pnode, sb)
                    534: struct pshmnode *pnode;
                    535: struct stat *sb;
                    536: {
                    537:        struct pshminfo *pinfo;
                    538:        
                    539:        if ((pinfo = pnode->pinfo) == PSHMINFO_NULL)
                    540:                return(EINVAL);
                    541: 
                    542:        bzero(sb, sizeof(struct stat)); 
                    543:        sb->st_mode = pinfo->pshm_mode;
                    544:        sb->st_uid = pinfo->pshm_uid;
                    545:        sb->st_gid = pinfo->pshm_gid;
                    546:        sb->st_size = pinfo->pshm_length;
                    547: 
                    548:        return(0);
                    549: }
                    550: 
                    551: int
                    552: pshm_access(struct pshminfo *pinfo, int mode, struct ucred *cred, struct proc *p)
                    553: {
                    554:        mode_t mask;
                    555:        register gid_t *gp;
                    556:        int i, error;
                    557: 
                    558:        /* Otherwise, user id 0 always gets access. */
                    559:        if (cred->cr_uid == 0)
                    560:                return (0);
                    561: 
                    562:        mask = 0;
                    563: 
                    564:        /* Otherwise, check the owner. */
                    565:        if (cred->cr_uid == pinfo->pshm_uid) {
                    566:                if (mode & FREAD)
                    567:                        mask |= S_IRUSR;
                    568:                if (mode & FWRITE)
                    569:                        mask |= S_IWUSR;
                    570:                return ((pinfo->pshm_mode & mask) == mask ? 0 : EACCES);
                    571:        }
                    572: 
                    573:        /* Otherwise, check the groups. */
                    574:        for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
                    575:                if (pinfo->pshm_gid == *gp) {
                    576:                        if (mode & FREAD)
                    577:                                mask |= S_IRGRP;
                    578:                        if (mode & FWRITE)
                    579:                                mask |= S_IWGRP;
                    580:                        return ((pinfo->pshm_mode & mask) == mask ? 0 : EACCES);
                    581:                }
                    582: 
                    583:        /* Otherwise, check everyone else. */
                    584:        if (mode & FREAD)
                    585:                mask |= S_IROTH;
                    586:        if (mode & FWRITE)
                    587:                mask |= S_IWOTH;
                    588:        return ((pinfo->pshm_mode & mask) == mask ? 0 : EACCES);
                    589: }
                    590: struct mmap_args {
                    591:                caddr_t addr;
                    592:                size_t len;
                    593:                int prot;
                    594:                int flags;
                    595:                int fd;
                    596: #ifdef DOUBLE_ALIGN_PARAMS
                    597:                long pad;
                    598: #endif
                    599:                off_t pos;
                    600: };
                    601: 
                    602: int
                    603: pshm_mmap(struct proc *p, struct mmap_args *uap, register_t *retval, struct file *fp, vm_size_t pageoff) 
                    604: {
                    605:        vm_offset_t     user_addr = uap->addr;
                    606:        vm_size_t       user_size = uap->len ;
                    607:        int prot = uap->prot;
                    608:        int flags = uap->flags;
                    609:        vm_offset_t     file_pos = (vm_offset_t)uap->pos;
                    610:        int fd = uap->fd;
                    611:        vm_map_t        user_map;
                    612:        boolean_t       find_space,docow;
                    613:        kern_return_t   kret;
                    614:        struct pshminfo * pinfo;
                    615:        struct pshmnode * pnode;
                    616:        void * mem_object;
                    617: 
                    618:        if (user_size == 0) 
                    619:                return(0);
                    620: 
                    621:        if ((flags & MAP_SHARED) == 0)
                    622:                return(EINVAL);
                    623: 
                    624: 
                    625:        if ((prot & PROT_WRITE) && ((fp->f_flag & FWRITE) == 0)) {
                    626:                return(EPERM);
                    627:        }
                    628: 
                    629:        if (((pnode = (struct pshmnode *)fp->f_data)) == PSHMNODE_NULL )
                    630:                return(EINVAL);
                    631: 
                    632:        if ((pinfo = pnode->pinfo) == PSHMINFO_NULL)
                    633:                return(EINVAL);
                    634: 
                    635:        if ((pinfo->pshm_flags & PSHM_ALLOCATED) != PSHM_ALLOCATED) {
                    636:                return(EINVAL);
                    637:        }
                    638:        if (user_size > pinfo->pshm_length) {
                    639:                return(EINVAL);
                    640:        }
                    641:        if (user_size  + file_pos > pinfo->pshm_length) {
                    642:                return(EINVAL);
                    643:        }
                    644:        if ((mem_object =  pinfo->pshm_memobject) == NULL) {
                    645:                return(EINVAL);
                    646:        }
                    647: 
                    648:        
                    649:        user_map = current_map();
                    650: 
                    651:        if ((flags & MAP_FIXED) == 0) {
                    652:                find_space = TRUE;
                    653:                user_addr = round_page(user_addr); 
                    654:        } else {
                    655:                if (user_addr != trunc_page(user_addr))
                    656:                        return (EINVAL);
                    657:                find_space = FALSE;
                    658:                (void) vm_deallocate(user_map, user_addr, user_size);
                    659:        }
                    660:        kret = vm_allocate(user_map, &user_addr, user_size, find_space);
                    661:        if (kret != KERN_SUCCESS) 
                    662:                goto out;
                    663:        docow = FALSE;  
                    664: 
                    665:        kret = vm_map(user_map, &user_addr, user_size,
                    666:                                0, find_space, pinfo->pshm_memobject, file_pos, docow,
                    667:                          prot, VM_PROT_DEFAULT, 
                    668:                                VM_INHERIT_DEFAULT);
                    669: 
                    670:        if (kret != KERN_SUCCESS) 
                    671:                        goto out;
                    672:        kret = vm_inherit(user_map, user_addr, user_size,
                    673:                                VM_INHERIT_SHARE);
                    674:        if (kret != KERN_SUCCESS) {
                    675:                (void) vm_deallocate(user_map, user_addr, user_size);
                    676:                goto out;
                    677:        }
                    678:        pnode->mapp_addr = user_addr;
                    679:        pnode->map_size = user_size;
                    680:        pinfo->pshm_flags |= (PSHM_MAPPED | PSHM_INUSE);
                    681: out:
                    682:        switch (kret) {
                    683:        case KERN_SUCCESS:
                    684:                *fdflags(p, fd) |= UF_MAPPED;
                    685:                *retval = (register_t)(user_addr + pageoff);
                    686:                return (0);
                    687:        case KERN_INVALID_ADDRESS:
                    688:        case KERN_NO_SPACE:
                    689:                return (ENOMEM);
                    690:        case KERN_PROTECTION_FAILURE:
                    691:                return (EACCES);
                    692:        default:
                    693:                return (EINVAL);
                    694:        }
                    695: 
                    696: }
                    697: 
                    698: struct shm_unlink_args {
                    699: const char *name;
                    700: };
                    701: 
                    702: int
                    703: shm_unlink(p, uap, retval)
                    704: struct proc *p;
                    705: register struct shm_unlink_args *uap;
                    706: register_t *retval;
                    707: {
                    708:        register struct filedesc *fdp = p->p_fd;
                    709:        register struct file *fp;
                    710:        int flags, i;
                    711:        int error=0;
                    712:        struct pshmname nd;
                    713:        struct pshminfo *pinfo;
                    714:        extern struct fileops pshmops;
                    715:        char * pnbuf;
                    716:        char * nameptr;
                    717:        char * cp;
                    718:        size_t pathlen, plen;
                    719:        int fmode, cmode ;
                    720:        int incache = 0;
                    721:        struct pshmnode * pnode = PSHMNODE_NULL;
                    722:        struct pshmcache *pcache = PSHMCACHE_NULL;
                    723:        kern_return_t kret;
                    724: 
                    725:        pinfo = PSHMINFO_NULL;
                    726: 
                    727:        MALLOC_ZONE(pnbuf, caddr_t,
                    728:                        MAXPATHLEN, M_NAMEI, M_WAITOK);
                    729:        pathlen = MAXPATHLEN;
                    730:        error = copyinstr(uap->name, pnbuf,
                    731:                MAXPATHLEN, &pathlen);
                    732:        if (error) {
                    733:                goto bad;
                    734:        }
                    735:        if (pathlen > PSHMNAMLEN) {
                    736:                error = ENAMETOOLONG;
                    737:                goto bad;
                    738:        }
                    739: 
                    740: 
                    741: #ifdef PSXSHM_NAME_RESTRICT
                    742:        nameptr = pnbuf;
                    743:        if (*nameptr == '/') {
                    744:                while (*(nameptr++) == '/') {
                    745:                        plen--;
                    746:                        error = EINVAL;
                    747:                        goto bad;
                    748:                }
                    749:         } else {
                    750:                error = EINVAL;
                    751:                goto bad;
                    752:        }
                    753: #endif /* PSXSHM_NAME_RESTRICT */
                    754: 
                    755:        plen = pathlen;
                    756:        nameptr = pnbuf;
                    757:        nd.pshm_nameptr = nameptr;
                    758:        nd.pshm_namelen = plen;
                    759:        nd. pshm_hash =0;
                    760: 
                    761:         for (cp = nameptr, i=1; *cp != 0 && i <= plen; i++, cp++) {
                    762:                nd.pshm_hash += (unsigned char)*cp * i;
                    763:        }
                    764: 
                    765:        error = pshm_cache_search(&pinfo, &nd, &pcache);
                    766: 
                    767:        if (error == ENOENT) {
                    768:                error = EINVAL;
                    769:                goto bad;
                    770: 
                    771:        }
                    772:        if (!error) {
                    773:                error = EINVAL;
                    774:                goto bad;
                    775:        } else
                    776:                incache = 1;
                    777: 
                    778:        if ((pinfo->pshm_flags & (PSHM_DEFINED | PSHM_ALLOCATED))==0) {
                    779:                return (EINVAL);
                    780:        }
                    781: 
                    782:        if (pinfo->pshm_flags & PSHM_INDELETE) {
                    783:                error = 0;
                    784:                goto bad;
                    785:        }
                    786:        pinfo->pshm_flags |= PSHM_INDELETE;
                    787:        pinfo->pshm_usecount--;
                    788:        kret = mach_destroy_memory_entry(pinfo->pshm_memobject);
                    789:        pshm_cache_delete(pcache);
                    790:        _FREE(pcache, M_SHM);
                    791:        pinfo->pshm_flags |= PSHM_REMOVED;
                    792:        error = 0;
                    793: bad:
                    794:        _FREE_ZONE(pnbuf, MAXPATHLEN, M_NAMEI);
                    795:        return (error);
                    796: out:
                    797:        switch (kret) {
                    798:        case KERN_INVALID_ADDRESS:
                    799:        case KERN_PROTECTION_FAILURE:
                    800:                return (EACCES);
                    801:        default:
                    802:                return (EINVAL);
                    803:        }
                    804: }
                    805: int
                    806: pshm_closefile(fp, p)
                    807:        struct file *fp;
                    808:        struct proc *p;
                    809: {
                    810: 
                    811:        return (pshm_close(((struct pshmnode *)fp->f_data), fp->f_flag,
                    812:                fp->f_cred, p));
                    813: }
                    814: 
                    815: int
                    816: pshm_close(pnode, flags, cred, p)
                    817:        register struct pshmnode *pnode;
                    818:        int flags;
                    819:        struct ucred *cred;
                    820:        struct proc *p;
                    821: {
                    822:        int error=0;
                    823:        kern_return_t kret;
                    824:        register struct pshminfo *pinfo;
                    825: 
                    826:        if ((pinfo = pnode->pinfo) == PSHMINFO_NULL)
                    827:                return(EINVAL);
                    828: 
                    829:        if ((pinfo->pshm_flags & PSHM_ALLOCATED) != PSHM_ALLOCATED) {
                    830:                return(EINVAL);
                    831:        }
                    832: #if DIAGNOSTIC
                    833:        if(!pinfo->pshm_usecount) {
                    834:                kprintf("negative usecount in pshm_close\n");
                    835:        }
                    836: #endif /* DIAGNOSTIC */
                    837:        pinfo->pshm_usecount--;
                    838: 
                    839:        if ((pinfo->pshm_flags & PSHM_REMOVED) && !pinfo->pshm_usecount) {
                    840:                _FREE(pinfo,M_SHM);
                    841:        }
                    842:        _FREE(pnode, M_SHM);
                    843:        return (error);
                    844: }
                    845: int
                    846: pshm_read(struct file *fp, struct uio *uio, struct ucred *cred) 
                    847: {
                    848:        return(EOPNOTSUPP);
                    849: }
                    850: int
                    851: pshm_write(struct file *fp, struct uio *uio, struct ucred *cred)
                    852: {
                    853:        return(EOPNOTSUPP);
                    854: }
                    855: int
                    856: pshm_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
                    857: {
                    858:        return(EOPNOTSUPP);
                    859: }
                    860: int
                    861: pshm_select(struct file *fp, int which, struct proc *p)
                    862: {
                    863:        return(EOPNOTSUPP);
                    864: }

unix.superglobalmegacorp.com

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