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

unix.superglobalmegacorp.com

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