Annotation of coherent/b/STREAMS/io.386/shm1.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * File: shm1.c
        !             3:  *
        !             4:  * Purpose: System V Compatible Shared Memory Device Driver
        !             5:  *
        !             6:  * $Log:       shm1.c,v $
        !             7:  * Revision 2.3  93/08/09  13:46:24  bin
        !             8:  * Kernel 82 changes
        !             9:  * 
        !            10:  * Revision 2.2  93/07/26  15:32:18  nigel
        !            11:  * Nigel's R80
        !            12:  * 
        !            13:  * Revision 1.3  93/04/14  10:23:10  root
        !            14:  * r75
        !            15:  * 
        !            16:  */
        !            17: 
        !            18: /*
        !            19:  * ----------------------------------------------------------------------
        !            20:  * Includes.
        !            21:  */
        !            22: #include <sys/coherent.h>
        !            23: #include <sys/types.h>
        !            24: #include <sys/proc.h>
        !            25: #include <sys/ipc.h>
        !            26: #include <sys/shm.h>
        !            27: #include <sys/errno.h>
        !            28: 
        !            29: /*
        !            30:  * ----------------------------------------------------------------------
        !            31:  * Definitions.
        !            32:  *     Constants.
        !            33:  *     Macros with argument lists.
        !            34:  *     Typedefs.
        !            35:  *     Enums.
        !            36:  */
        !            37: #define SHMBASE        0x80000000      /* Base shared memory address */
        !            38: /* These macros should be somewhere in the headers ???*/
        !            39: #define        DATAST  0x400000        /* Start of the data virtual address */
        !            40: #define DATAEND        0x7FFFFF        /* End of the data virtual address */
        !            41: #define STACKST        0x7C000000      /* Start of the stack */
        !            42: #define        STACKEN 0x7FFFFFFF      /* End of the stack virtual address */
        !            43: 
        !            44: /*
        !            45:  * ----------------------------------------------------------------------
        !            46:  * Functions.
        !            47:  *     Import Functions.
        !            48:  *     Export Functions.
        !            49:  *     Local Functions.
        !            50:  */
        !            51: extern SEG     *shmAlloc();    /* shm0.c */
        !            52: char           *ushmat();
        !            53: int            ushmdt();
        !            54: int            ushmctl();
        !            55: int            ushmget();
        !            56: int            iShmPerm();     /* Check permissions */
        !            57: caddr_t                vCheckReqAdd(); /* Check attach address for shmat */
        !            58: /*
        !            59:  * ----------------------------------------------------------------------
        !            60:  * Global Data.
        !            61:  *     Import Variables.
        !            62:  *     Export Variables.
        !            63:  *     Local Variables.
        !            64:  */
        !            65: 
        !            66: /* Configurable variables - see /etc/conf/mtune. */
        !            67: extern int     SHMMNI;
        !            68: extern int     SHMMAX;
        !            69: 
        !            70: struct shmid_ds        *shmids = NULL;         /* Array of shared memory segments */
        !            71: SEG            **shmsegs;              /* Array of pointers to segments */
        !            72: /*
        !            73:  * ----------------------------------------------------------------------
        !            74:  * Code.
        !            75:  */
        !            76: 
        !            77: /*
        !            78:  * Shmctl - Shared Memory Control Operations.
        !            79:  */
        !            80: int
        !            81: ushmctl(iShmId, iCmd, pstShmId)
        !            82: int            iShmId,         /* Shared memory id */
        !            83:                iCmd;           /* Command */
        !            84: struct shmid_ds        *pstShmId;      /* User shmid_ds buffer */
        !            85: {
        !            86:        register struct shmid_ds *rstIdp;       
        !            87:        int iRet = 0;
        !            88: 
        !            89:        /* Check if id is in proper range. */
        !            90:        if (iShmId >= SHMMNI || iShmId < 0) {
        !            91:                u.u_error = EINVAL;
        !            92:                return;
        !            93:        }
        !            94:        /* Check we did alloc. All allocatable arrays are alloced after
        !            95:         * the first ~correct usage of shmget.
        !            96:         */
        !            97:        if (shmids == NULL) {
        !            98:                u.u_error = EINVAL;
        !            99:                return;
        !           100:        }
        !           101:        rstIdp = &shmids[iShmId];       /* Requested segment */
        !           102: 
        !           103:        /* Check if segment is in used */
        !           104:        if ((rstIdp->shm_perm.mode & IPC_ALLOC) == 0) {
        !           105:                u.u_error = EINVAL;
        !           106:                return;
        !           107:        }
        !           108: 
        !           109:        switch (iCmd) {
        !           110:        case IPC_STAT:
        !           111:                /* Check read permission for stat. */
        !           112:                if (iShmPerm((rstIdp), SHM_R)) {
        !           113:                        u.u_error = EACCES;
        !           114:                        return;
        !           115:                }
        !           116:                /* Check if user gives a valid buffer */
        !           117:                if (!useracc(pstShmId, sizeof(struct shmid_ds), 1)) {
        !           118:                        u.u_error = EFAULT;
        !           119:                        return;
        !           120:                }
        !           121:                /* kucopy will set u_error if error occurs */
        !           122:                kucopy(rstIdp, pstShmId, sizeof(struct shmid_ds));
        !           123:                break;
        !           124: 
        !           125:        case IPC_SET:
        !           126:                if ((u.u_uid != 0) && (u.u_uid != rstIdp->shm_perm.uid) &&
        !           127:                                (u.u_uid != rstIdp->shm_perm.cuid)) {
        !           128:                        u.u_error = EPERM;
        !           129:                        iRet = -1;
        !           130:                        break;
        !           131:                }
        !           132:                rstIdp->shm_perm.uid   = getuwd(&(pstShmId->shm_perm.uid));
        !           133:                rstIdp->shm_perm.gid   = getuwd(&(pstShmId->shm_perm.gid));
        !           134:                rstIdp->shm_perm.mode &= ~0777;
        !           135:                rstIdp->shm_perm.mode |= getuwd(&(pstShmId->shm_perm.mode)) 
        !           136:                                                                        & 0777;
        !           137:                break;
        !           138: 
        !           139:        case IPC_RMID:
        !           140:                if ((u.u_uid != 0) && (u.u_uid != rstIdp->shm_perm.uid) &&
        !           141:                                (u.u_uid != rstIdp->shm_perm.cuid)) {
        !           142:                        u.u_error = EPERM;
        !           143:                        iRet = -1;
        !           144:                        break;
        !           145:                }
        !           146:                
        !           147:                /* SVR3 allows removing an attached segment. Even worse, the
        !           148:                 * process that has the segment attached can keep using it. 
        !           149:                 * Some buggy third party software uses this "feature". 
        !           150:                 * So, we have to make it available too;-(
        !           151:                 */
        !           152:                rstIdp->shm_perm.seq = 0;
        !           153:                rstIdp->shm_perm.mode = 0;
        !           154: 
        !           155:                /* If segment is attached, set flag to be removed */
        !           156:                if (rstIdp->shm_nattch > 0)
        !           157:                        shmsegs[iShmId]->s_flags |= SRFBERM;
        !           158:                else    /* remove it otherwise */
        !           159:                        shmFree(shmsegs[iShmId]);
        !           160:                shmsegs[iShmId] = NULL;
        !           161:                break;
        !           162: 
        !           163:        /* SHM_LOCK and SHM_UNLOCK: lock/unlock shared memory segement 
        !           164:         * in core. Is not a part of iBCS2.
        !           165:         * Has no meaning for current 4.0.* release of COHERENT.
        !           166:         * Have been done for binary portability.
        !           167:         */
        !           168:        case SHM_LOCK:  
        !           169:                if (!u.u_uid) {
        !           170:                        u.u_error = EPERM;
        !           171:                        return;
        !           172:                }
        !           173:                break;
        !           174:        case SHM_UNLOCK:        
        !           175:                if (!u.u_uid) {
        !           176:                        u.u_error = EPERM;
        !           177:                        return;
        !           178:                }
        !           179:                break;
        !           180:        
        !           181:        default:
        !           182:                u.u_error = EINVAL;
        !           183:                iRet = -1;
        !           184:        }
        !           185: 
        !           186:        return iRet;
        !           187: }
        !           188: 
        !           189: /*
        !           190:  * Shmget - Get Shared Memory Segment
        !           191:  * Return shared memory id if succed, -1 and set u_error otheriwse.
        !           192:  */
        !           193: int
        !           194: ushmget(kShmKey, iShmSize, iShmFlg)
        !           195: key_t  kShmKey;        /* Shared memory key */
        !           196: int    iShmSize;       /* Shared memory segment size */
        !           197: int    iShmFlg;        /* Flags */
        !           198: {
        !           199:        register struct shmid_ds *rstShmId;     /* Work pointer */
        !           200:        register struct shmid_ds *rstOldest = 0;/* Oldest free segment */
        !           201:        register int             i;             /* Loop index */
        !           202:        SEG                      *pstSeg;
        !           203: 
        !           204:        /* Check the requested segment size */
        !           205:        if (iShmSize < 0 || iShmSize > SHMMAX) {
        !           206:                u.u_error = EINVAL;
        !           207:                return;
        !           208:        }
        !           209:        /* Init the shared memory on the first shmget. */
        !           210:        if (shmids == NULL) 
        !           211:                if (shminit()) {
        !           212:                        u.u_error = ENOSPC;
        !           213:                        return;
        !           214:                }
        !           215: 
        !           216:        /* Search for desire shared memory segment. */
        !           217:        for (rstShmId = shmids, i = 0; i < SHMMNI; i++, rstShmId++) {
        !           218:                /* If segment is not alloced, we will look for the oldest
        !           219:                 * free segment. We will use it to create a new one.
        !           220:                 * The "oldest" will increase (a little) system reliability.
        !           221:                 */
        !           222:                if ((rstShmId->shm_perm.mode & IPC_ALLOC) == 0) {
        !           223:                        if ((rstOldest == NULL) || 
        !           224:                           (rstOldest->shm_ctime > rstShmId->shm_ctime))
        !           225:                                rstOldest = rstShmId;
        !           226:                        continue;
        !           227:                }
        !           228:                /* Do we need a new segment? */
        !           229:                if (kShmKey == IPC_PRIVATE)
        !           230:                        continue;
        !           231:                /* Keep going if key is different. The key is an element
        !           232:                 * number of shmids
        !           233:                 */
        !           234:                if (kShmKey != rstShmId->shm_perm.key)
        !           235:                        continue;
        !           236: 
        !           237:                /* We found the segment with requested key. */
        !           238:                
        !           239:                /* Request was for the exclusive segment should fail. */
        !           240:                if ((iShmFlg & IPC_CREAT) && (iShmFlg & IPC_EXCL)) {
        !           241:                        u.u_error = EEXIST;
        !           242:                        return;
        !           243:                }
        !           244: 
        !           245:                /* Check the requested size */
        !           246:                if (rstShmId->shm_segsz < iShmSize) {
        !           247:                        u.u_error = EINVAL;
        !           248:                        return;
        !           249:                }
        !           250: 
        !           251:                /* Check permissions */
        !           252:                if (iShmPerm(rstShmId, iShmFlg))
        !           253:                        return;
        !           254:                return i;
        !           255:        }
        !           256: 
        !           257:        /* We need to create a new segment */
        !           258:        if (rstOldest == 0) { /* Check system limits */
        !           259:                u.u_error = ENOSPC;
        !           260:                return;
        !           261:        }
        !           262:        if (!(iShmFlg & IPC_CREAT)) {
        !           263:                u.u_error = ENOENT;
        !           264:                return;
        !           265:        }
        !           266:        rstShmId = rstOldest;
        !           267:        /* Allocate a new shared memory segment */
        !           268:        pstSeg = shmAlloc(iShmSize);
        !           269:        if (pstSeg == NULL) {
        !           270:                u.u_error = ENOSPC;
        !           271:                return;
        !           272:        }
        !           273:        /* Save it in shmsegs */
        !           274:        shmsegs[rstShmId - shmids] = pstSeg;
        !           275: 
        !           276:        rstShmId->shm_perm.seq = (unsigned short) (rstShmId - shmids);
        !           277:        rstShmId->shm_segsz = iShmSize;
        !           278:        rstShmId->shm_atime = 0;
        !           279:        rstShmId->shm_dtime = 0;
        !           280:        rstShmId->shm_ctime = timer.t_time;
        !           281:        rstShmId->shm_cpid  = SELF->p_pid;
        !           282:        rstShmId->shm_perm.cuid = rstShmId->shm_perm.uid = u.u_uid;
        !           283:        rstShmId->shm_perm.cgid = rstShmId->shm_perm.gid = u.u_gid;
        !           284:        rstShmId->shm_perm.mode = (iShmFlg & 0777) | IPC_ALLOC;
        !           285:        rstShmId->shm_perm.key  = kShmKey;
        !           286: 
        !           287:        if (kShmKey == IPC_PRIVATE)
        !           288:                rstShmId->shm_perm.mode |= SHM_DEST;
        !           289: 
        !           290:        return rstShmId - shmids;
        !           291: }
        !           292: 
        !           293: /*
        !           294:  * Allocate space for shared memory data structures.
        !           295:  */
        !           296: int
        !           297: shminit()
        !           298: {
        !           299:        shmids = (struct shmid_ds *) kalloc(sizeof(struct shmid_ds) * SHMMNI);
        !           300:        if (shmids == NULL)
        !           301:                return -1;
        !           302: 
        !           303:        /* Allocate array of shared memory segments. We do not have to
        !           304:         * initalise it
        !           305:         */
        !           306:        shmsegs = (SEG *) kalloc(sizeof(SEG *) * SHMMNI);
        !           307:        if (shmsegs == NULL)
        !           308:                return -1;
        !           309:        return 0;
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * Attach shared memory segment.
        !           314:  */
        !           315: char *
        !           316: ushmat(iSysId, pcShmAddr, iShmFlg)
        !           317: int    iSysId;         /* System segment id */
        !           318: char   *pcShmAddr;     /* Address to attach */
        !           319: int    iShmFlg;        /* Flags */
        !           320: {
        !           321:        register PROC           *rpstProc;      /* Current process */
        !           322:        register struct sr      *rpstSr;        /* Shared memory segments */
        !           323:        struct sr               *pstSrTmp;
        !           324:        SEG                     *pstSegSh;      /* Segment to attach */
        !           325:        struct shmid_ds         *pstShmId;      /* Pointer to a system segment*/
        !           326:        unsigned int            uSegId;         /* Segment id */
        !           327:        caddr_t                 vAttAddr;       /* Address to attach */
        !           328:        int                     i;              /* Loop index */
        !           329:        int                     iReadOnly = 0;  /* 1 - read only, 0 - rw */
        !           330:                
        !           331:        /* Check if iSysId is a valid shared memory id. */
        !           332:        if (iSysId < 0 || iSysId > SHMMNI) {
        !           333:                u.u_error = EINVAL;
        !           334:                return;
        !           335:        }
        !           336:        /* Do we really have this segment? */
        !           337:        pstShmId = shmids + iSysId;
        !           338:        if (pstShmId->shm_perm.seq != iSysId) {
        !           339:                u.u_error = EINVAL;
        !           340:                return;
        !           341:        }
        !           342:        /* Check permissions. */
        !           343:        if (iShmFlg & SHM_RDONLY)
        !           344:                iReadOnly = 1;
        !           345:        if (iReadOnly) {
        !           346:                if (iShmPerm(pstShmId, 0444)) {
        !           347:                        u.u_error = EACCES;
        !           348:                        return;
        !           349:                }
        !           350:        } else {
        !           351:                if (iShmPerm(pstShmId, 0666)) {
        !           352:                        u.u_error = EACCES;
        !           353:                        return;
        !           354:                }
        !           355:        }
        !           356:        /* Check if process has free shm index. */
        !           357:        rpstProc = SELF;
        !           358:        /* We will go through all NSHMSEG segments to see if any is free. */
        !           359:        for (rpstSr = rpstProc->p_shmsr; rpstSr < rpstProc->p_shmsr + NSHMSEG; 
        !           360:                                                                rpstSr++)
        !           361:                if (rpstSr->sr_segp == NULL)
        !           362:                        break;
        !           363:        /* The segment id is just an element number. */
        !           364:        uSegId = rpstSr - rpstProc->p_shmsr;
        !           365:        /* If segment id is >= NSHMSEG we cannot attach any new segment. */
        !           366:        if (uSegId >= NSHMSEG) {
        !           367:                u.u_error = EMFILE;
        !           368:                return;
        !           369:        }
        !           370:        /* Get the pointer to the shared memory segment */
        !           371:        pstSegSh = shmsegs[iSysId];
        !           372: 
        !           373:        /* Find an address to attach.
        !           374:         * There are two cases: process does not request the address,
        !           375:         * process requests the address.
        !           376:         * In the first case we have to take the first available free address.
        !           377:         * We will try to put a free page between the segments.
        !           378:         * In the second case we have to check if address is an available and
        !           379:         * attach to this address.
        !           380:         */
        !           381:        /* First case. We have to find a free address. */
        !           382:        if (pcShmAddr == NULL) {
        !           383:                /* Find a free space to attach.  */
        !           384:                for (pstSrTmp = rpstProc->p_shmsr, i = 0; i < NSHMSEG; 
        !           385:                                                        i++, pstSrTmp++) 
        !           386:                        if (pstSrTmp->sr_base == NULL)
        !           387:                                break;
        !           388:                /* Check limit of attaches per process */
        !           389:                if (i >= NSHMSEG) {
        !           390:                        u.u_error = EINVAL;
        !           391:                        return;
        !           392:                }
        !           393:                /* We will use the addresses starting from SHMBASE. 
        !           394:                 * Each new address can be SHMMAX + NBPC appart.
        !           395:                 */
        !           396:                vAttAddr = (caddr_t) (SHMBASE + i * (SHMMAX + NBPC));
        !           397:        } else {
        !           398:                /* Requst attach to a specific address. This is none portable 
        !           399:                 * way to use a shared memory. 
        !           400:                 */
        !           401:                if ((vAttAddr = vCheckReqAdd(pcShmAddr, iReadOnly)) < 0) {
        !           402:                        printf("%s: attempt attach to 0x%x\n", 
        !           403:                        u.u_comm, pcShmAddr);
        !           404:                        u.u_error = EINVAL;
        !           405:                        return;
        !           406:                } 
        !           407:        }
        !           408: 
        !           409:        if (!shmAtt(uSegId, vAttAddr, pstSegSh, iReadOnly)) {
        !           410:                u.u_error = EINVAL;
        !           411:                return;
        !           412:        }
        !           413:        pstShmId->shm_lpid = SELF->p_pid;
        !           414:        pstShmId->shm_atime = timer.t_time;
        !           415:        pstShmId->shm_dtime = 0;
        !           416:        pstShmId->shm_nattch = pstSegSh->s_urefc - 1;
        !           417:        /* Keep all attached addresses. We will need them for detach */
        !           418:        return (char *) vAttAddr;
        !           419: }
        !           420: 
        !           421: /*
        !           422:  * Check requested address for attach.
        !           423:  * Just fail for the first release.
        !           424:  */
        !           425: caddr_t
        !           426: vCheckReqAdd(pcAdd, iFlg)
        !           427: char   *pcAdd; /* Address to atatch */
        !           428: int    iFlg;   /* Mode flag */
        !           429: {
        !           430:        return (caddr_t) -1;
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * Check permissions of the shared memory segment.
        !           435:  * Return 0 on success, -1 and set errno on error.
        !           436:  */
        !           437: int
        !           438: iShmPerm(pstShmId, iShmFlg)
        !           439: struct shmid_ds        *pstShmId;
        !           440: int            iShmFlg;
        !           441: {
        !           442:        int     iShmMode;
        !           443: 
        !           444:        /* We need 9 lower order bits. There is a question what we have to do
        !           445:         * if someone sets an execute bits on. At this point we just ignore 
        !           446:         * them.
        !           447:         */
        !           448:        iShmMode = iShmFlg & 0666;
        !           449: 
        !           450:        /* For superuser or if mode is 0 */
        !           451:        if (u.u_uid == 0 || !iShmMode) 
        !           452:                return 0;
        !           453:        /* For owner or creator */
        !           454:        if (u.u_uid == pstShmId->shm_perm.uid || u.u_uid 
        !           455:                                                == pstShmId->shm_perm.cuid) {
        !           456:                if ((iShmMode & pstShmId->shm_perm.mode) & 0600)
        !           457:                        return 0;
        !           458:                else {
        !           459:                        u.u_error = EACCES;
        !           460:                        return -1;
        !           461:                }
        !           462:        }
        !           463:        /* For group */         
        !           464:        if (u.u_gid == pstShmId->shm_perm.gid 
        !           465:                                        || u.u_gid == pstShmId->shm_perm.cgid) {
        !           466:                if ((iShmMode & pstShmId->shm_perm.mode) & 060)
        !           467:                        return 0;
        !           468:                else {
        !           469:                        u.u_error = EACCES;
        !           470:                        return -1;
        !           471:                }
        !           472:        }
        !           473:        /* For the rest of the world */
        !           474:        if ((iShmMode & pstShmId->shm_perm.mode) & 06) 
        !           475:                return 0;
        !           476:        else {
        !           477:                u.u_error = EACCES;
        !           478:                return -1;
        !           479:        }
        !           480:        /* We should never come here */
        !           481:        u.u_error = EACCES;
        !           482:        return -1;
        !           483: }
        !           484: 
        !           485: /*
        !           486:  * ushmdt() - Detach shared memory segment.
        !           487:  * Find segment number and call shmDetach() (shm0.c).
        !           488:  */
        !           489: int
        !           490: ushmdt(cpShmAddr)
        !           491: char   *cpShmAddr;     /* Pointer to a segment */
        !           492: {
        !           493:        register PROC           *rpstProc;      /* Current process */
        !           494:        register struct sr      *rpstSr;        /* Shared memory segments */
        !           495:        int                     i;              /* Loop indexe */
        !           496: 
        !           497:        rpstProc = SELF;        /* Get pointer to our process */
        !           498: 
        !           499:        /* Go through all segments. */
        !           500:        for (rpstSr = rpstProc->p_shmsr, i = 0; i < NSHMSEG; i++, rpstSr++) {
        !           501:                if (rpstSr->sr_base == (caddr_t) cpShmAddr) {
        !           502:                        shmDetach(i);
        !           503:                         return 0;
        !           504:                }
        !           505:        }
        !           506: 
        !           507:        /* We can come here only if we have invalid address */
        !           508:        u.u_error = EINVAL;
        !           509:        return;
        !           510: }
        !           511: 
        !           512: /*
        !           513:  * shmSetDs(). Called from shm0.c.
        !           514:  *
        !           515:  * Given a pointer to shared memory segment, set shmid_ds.
        !           516:  */
        !           517: void
        !           518: shmSetDs(rpstSeg)
        !           519: register SEG   *rpstSeg;
        !           520: {
        !           521:        struct shmid_ds         *pstShmId;      /* Shared memory structure */
        !           522:        int                     iShmId;         /* Shared memory id */
        !           523:        int                     j;              /* Loop indexe */
        !           524: 
        !           525:        for (j = 0; j < SHMMNI; j++)
        !           526:                if (shmsegs[j] == rpstSeg)
        !           527:                        break;
        !           528: 
        !           529:        /* We should have this segment. */
        !           530:        if (j >= SHMMNI) {
        !           531:                u.u_error = EINVAL;
        !           532:                return;
        !           533:        }
        !           534: 
        !           535:        iShmId = j;
        !           536:        pstShmId = shmids + iShmId;
        !           537: 
        !           538:        /* Set proper values */
        !           539:        pstShmId->shm_lpid = SELF->p_pid;
        !           540:        pstShmId->shm_dtime = timer.t_time;
        !           541:        pstShmId->shm_nattch = rpstSeg->s_urefc - 1;
        !           542:        return;
        !           543: }

unix.superglobalmegacorp.com

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