Annotation of coherent/b/STREAMS/io.386/shm1.c, revision 1.1.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.