Annotation of coherent/b/kernel/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 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.