Annotation of Net2/kern/kern_prot.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
        !             3:  * of California.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)kern_prot.c 7.21 (Berkeley) 5/3/91
        !            34:  */
        !            35: 
        !            36: /*
        !            37:  * System calls related to processes and protection
        !            38:  */
        !            39: 
        !            40: #include "param.h"
        !            41: #include "acct.h"
        !            42: #include "systm.h"
        !            43: #include "ucred.h"
        !            44: #include "proc.h"
        !            45: #include "timeb.h"
        !            46: #include "times.h"
        !            47: #include "malloc.h"
        !            48: 
        !            49: /* ARGSUSED */
        !            50: getpid(p, uap, retval)
        !            51:        struct proc *p;
        !            52:        void *uap;
        !            53:        int *retval;
        !            54: {
        !            55: 
        !            56:        *retval = p->p_pid;
        !            57: #ifdef COMPAT_43
        !            58:        retval[1] = p->p_pptr->p_pid;
        !            59: #endif
        !            60:        return (0);
        !            61: }
        !            62: 
        !            63: /* ARGSUSED */
        !            64: getppid(p, uap, retval)
        !            65:        struct proc *p;
        !            66:        void *uap;
        !            67:        int *retval;
        !            68: {
        !            69: 
        !            70:        *retval = p->p_pptr->p_pid;
        !            71:        return (0);
        !            72: }
        !            73: 
        !            74: /* Get process group ID; note that POSIX getpgrp takes no parameter */
        !            75: getpgrp(p, uap, retval)
        !            76:        struct proc *p;
        !            77:        void *uap;
        !            78:        int *retval;
        !            79: {
        !            80: 
        !            81:        *retval = p->p_pgrp->pg_id;
        !            82:        return (0);
        !            83: }
        !            84: 
        !            85: /* ARGSUSED */
        !            86: getuid(p, uap, retval)
        !            87:        struct proc *p;
        !            88:        void *uap;
        !            89:        int *retval;
        !            90: {
        !            91: 
        !            92:        *retval = p->p_cred->p_ruid;
        !            93: #ifdef COMPAT_43
        !            94:        retval[1] = p->p_ucred->cr_uid;
        !            95: #endif
        !            96:        return (0);
        !            97: }
        !            98: 
        !            99: /* ARGSUSED */
        !           100: geteuid(p, uap, retval)
        !           101:        struct proc *p;
        !           102:        void *uap;
        !           103:        int *retval;
        !           104: {
        !           105: 
        !           106:        *retval = p->p_ucred->cr_uid;
        !           107:        return (0);
        !           108: }
        !           109: 
        !           110: /* ARGSUSED */
        !           111: getgid(p, uap, retval)
        !           112:        struct proc *p;
        !           113:        void *uap;
        !           114:        int *retval;
        !           115: {
        !           116: 
        !           117:        *retval = p->p_cred->p_rgid;
        !           118: #ifdef COMPAT_43
        !           119:        retval[1] = p->p_ucred->cr_groups[0];
        !           120: #endif
        !           121:        return (0);
        !           122: }
        !           123: 
        !           124: /*
        !           125:  * Get effective group ID.  The "egid" is groups[0], and could be obtained
        !           126:  * via getgroups.  This syscall exists because it is somewhat painful to do
        !           127:  * correctly in a library function.
        !           128:  */
        !           129: /* ARGSUSED */
        !           130: getegid(p, uap, retval)
        !           131:        struct proc *p;
        !           132:        void *uap;
        !           133:        int *retval;
        !           134: {
        !           135: 
        !           136:        *retval = p->p_ucred->cr_groups[0];
        !           137:        return (0);
        !           138: }
        !           139: 
        !           140: getgroups(p, uap, retval)
        !           141:        struct proc *p;
        !           142:        register struct arg {
        !           143:                u_int   gidsetsize;
        !           144:                int     *gidset;                /* XXX not yet POSIX */
        !           145:        } *uap;
        !           146:        int *retval;
        !           147: {
        !           148:        register struct pcred *pc = p->p_cred;
        !           149:        register gid_t *gp;
        !           150:        register int *lp;
        !           151:        register u_int ngrp;
        !           152:        int groups[NGROUPS];
        !           153:        int error;
        !           154: 
        !           155:        if ((ngrp = uap->gidsetsize) == 0) {
        !           156:                *retval = pc->pc_ucred->cr_ngroups;
        !           157:                return (0);
        !           158:        }
        !           159:        if (ngrp < pc->pc_ucred->cr_ngroups)
        !           160:                return (EINVAL);
        !           161:        ngrp = pc->pc_ucred->cr_ngroups;
        !           162:        for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
        !           163:                *lp++ = *gp++;
        !           164:        if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
        !           165:            ngrp * sizeof (groups[0])))
        !           166:                return (error);
        !           167:        *retval = ngrp;
        !           168:        return (0);
        !           169: }
        !           170: 
        !           171: /* ARGSUSED */
        !           172: setsid(p, uap, retval)
        !           173:        register struct proc *p;
        !           174:        void *uap;
        !           175:        int *retval;
        !           176: {
        !           177: 
        !           178:        if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
        !           179:                return (EPERM);
        !           180:        } else {
        !           181:                enterpgrp(p, p->p_pid, 1);
        !           182:                *retval = p->p_pid;
        !           183:                return (0);
        !           184:        }
        !           185: }
        !           186: 
        !           187: /*
        !           188:  * set process group (setpgid/old setpgrp)
        !           189:  *
        !           190:  * caller does setpgid(targpid, targpgid)
        !           191:  *
        !           192:  * pid must be caller or child of caller (ESRCH)
        !           193:  * if a child
        !           194:  *     pid must be in same session (EPERM)
        !           195:  *     pid can't have done an exec (EACCES)
        !           196:  * if pgid != pid
        !           197:  *     there must exist some pid in same session having pgid (EPERM)
        !           198:  * pid must not be session leader (EPERM)
        !           199:  */
        !           200: /* ARGSUSED */
        !           201: setpgid(curp, uap, retval)
        !           202:        struct proc *curp;
        !           203:        register struct args {
        !           204:                int     pid;    /* target process id */
        !           205:                int     pgid;   /* target pgrp id */
        !           206:        } *uap;
        !           207:        int *retval;
        !           208: {
        !           209:        register struct proc *targp;            /* target process */
        !           210:        register struct pgrp *pgrp;             /* target pgrp */
        !           211: 
        !           212:        if (uap->pid != 0 && uap->pid != curp->p_pid) {
        !           213:                if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
        !           214:                        return (ESRCH);
        !           215:                if (targp->p_session != curp->p_session)
        !           216:                        return (EPERM);
        !           217:                if (targp->p_flag&SEXEC)
        !           218:                        return (EACCES);
        !           219:        } else
        !           220:                targp = curp;
        !           221:        if (SESS_LEADER(targp))
        !           222:                return (EPERM);
        !           223:        if (uap->pgid == 0)
        !           224:                uap->pgid = targp->p_pid;
        !           225:        else if (uap->pgid != targp->p_pid)
        !           226:                if ((pgrp = pgfind(uap->pgid)) == 0 ||
        !           227:                    pgrp->pg_session != curp->p_session)
        !           228:                        return (EPERM);
        !           229:        enterpgrp(targp, uap->pgid, 0);
        !           230:        return (0);
        !           231: }
        !           232: 
        !           233: /* ARGSUSED */
        !           234: setuid(p, uap, retval)
        !           235:        struct proc *p;
        !           236:        struct args {
        !           237:                int     uid;
        !           238:        } *uap;
        !           239:        int *retval;
        !           240: {
        !           241:        register struct pcred *pc = p->p_cred;
        !           242:        register uid_t uid;
        !           243:        int error;
        !           244: 
        !           245:        uid = uap->uid;
        !           246:        if (uid != pc->p_ruid &&
        !           247:            (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           248:                return (error);
        !           249:        /*
        !           250:         * Everything's okay, do it.  Copy credentials so other references do
        !           251:         * not see our changes.
        !           252:         */
        !           253:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           254:        pc->pc_ucred->cr_uid = uid;
        !           255:        pc->p_ruid = uid;
        !           256:        pc->p_svuid = uid;
        !           257:        return (0);
        !           258: }
        !           259: 
        !           260: /* ARGSUSED */
        !           261: seteuid(p, uap, retval)
        !           262:        struct proc *p;
        !           263:        struct args {
        !           264:                int     euid;
        !           265:        } *uap;
        !           266:        int *retval;
        !           267: {
        !           268:        register struct pcred *pc = p->p_cred;
        !           269:        register uid_t euid;
        !           270:        int error;
        !           271: 
        !           272:        euid = uap->euid;
        !           273:        if (euid != pc->p_ruid && euid != pc->p_svuid &&
        !           274:            (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           275:                return (error);
        !           276:        /*
        !           277:         * Everything's okay, do it.  Copy credentials so other references do
        !           278:         * not see our changes.
        !           279:         */
        !           280:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           281:        pc->pc_ucred->cr_uid = euid;
        !           282:        return (0);
        !           283: }
        !           284: 
        !           285: /* ARGSUSED */
        !           286: setgid(p, uap, retval)
        !           287:        struct proc *p;
        !           288:        struct args {
        !           289:                int     gid;
        !           290:        } *uap;
        !           291:        int *retval;
        !           292: {
        !           293:        register struct pcred *pc = p->p_cred;
        !           294:        register gid_t gid;
        !           295:        int error;
        !           296: 
        !           297:        gid = uap->gid;
        !           298:        if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           299:                return (error);
        !           300:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           301:        pc->pc_ucred->cr_groups[0] = gid;
        !           302:        pc->p_rgid = gid;
        !           303:        pc->p_svgid = gid;              /* ??? */
        !           304:        return (0);
        !           305: }
        !           306: 
        !           307: /* ARGSUSED */
        !           308: setegid(p, uap, retval)
        !           309:        struct proc *p;
        !           310:        struct args {
        !           311:                int     egid;
        !           312:        } *uap;
        !           313:        int *retval;
        !           314: {
        !           315:        register struct pcred *pc = p->p_cred;
        !           316:        register gid_t egid;
        !           317:        int error;
        !           318: 
        !           319:        egid = uap->egid;
        !           320:        if (egid != pc->p_rgid && egid != pc->p_svgid &&
        !           321:            (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           322:                return (error);
        !           323:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           324:        pc->pc_ucred->cr_groups[0] = egid;
        !           325:        return (0);
        !           326: }
        !           327: 
        !           328: #ifdef COMPAT_43
        !           329: /* ARGSUSED */
        !           330: osetreuid(p, uap, retval)
        !           331:        register struct proc *p;
        !           332:        struct args {
        !           333:                int     ruid;
        !           334:                int     euid;
        !           335:        } *uap;
        !           336:        int *retval;
        !           337: {
        !           338:        register struct pcred *pc = p->p_cred;
        !           339:        register uid_t ruid, euid;
        !           340:        int error;
        !           341: 
        !           342:        if (uap->ruid == -1)
        !           343:                ruid = pc->p_ruid;
        !           344:        else
        !           345:                ruid = uap->ruid;
        !           346:        /*
        !           347:         * Allow setting real uid to previous effective, for swapping real and
        !           348:         * effective.  This should be:
        !           349:         *
        !           350:         * if (ruid != pc->p_ruid &&
        !           351:         *     (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           352:         */
        !           353:        if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
        !           354:            (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           355:                return (error);
        !           356:        if (uap->euid == -1)
        !           357:                euid = pc->pc_ucred->cr_uid;
        !           358:        else
        !           359:                euid = uap->euid;
        !           360:        if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
        !           361:            euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           362:                return (error);
        !           363:        /*
        !           364:         * Everything's okay, do it.  Copy credentials so other references do
        !           365:         * not see our changes.
        !           366:         */
        !           367:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           368:        pc->pc_ucred->cr_uid = euid;
        !           369:        pc->p_ruid = ruid;
        !           370:        return (0);
        !           371: }
        !           372: 
        !           373: /* ARGSUSED */
        !           374: osetregid(p, uap, retval)
        !           375:        register struct proc *p;
        !           376:        struct args {
        !           377:                int     rgid;
        !           378:                int     egid;
        !           379:        } *uap;
        !           380:        int *retval;
        !           381: {
        !           382:        register struct pcred *pc = p->p_cred;
        !           383:        register gid_t rgid, egid;
        !           384:        int error;
        !           385: 
        !           386:        if (uap->rgid == -1)
        !           387:                rgid = pc->p_rgid;
        !           388:        else
        !           389:                rgid = uap->rgid;
        !           390:        /*
        !           391:         * Allow setting real gid to previous effective, for swapping real and
        !           392:         * effective.  This didn't really work correctly in 4.[23], but is
        !           393:         * preserved so old stuff doesn't fail.  This should be:
        !           394:         *
        !           395:         * if (rgid != pc->p_rgid &&
        !           396:         *     (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           397:         */
        !           398:        if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
        !           399:            (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           400:                return (error);
        !           401:        if (uap->egid == -1)
        !           402:                egid = pc->pc_ucred->cr_groups[0];
        !           403:        else
        !           404:                egid = uap->egid;
        !           405:        if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
        !           406:            egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
        !           407:                return (error);
        !           408:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           409:        pc->pc_ucred->cr_groups[0] = egid;
        !           410:        pc->p_rgid = rgid;
        !           411:        return (0);
        !           412: }
        !           413: #endif
        !           414: 
        !           415: /* ARGSUSED */
        !           416: setgroups(p, uap, retval)
        !           417:        struct proc *p;
        !           418:        struct args {
        !           419:                u_int   gidsetsize;
        !           420:                int     *gidset;
        !           421:        } *uap;
        !           422:        int *retval;
        !           423: {
        !           424:        register struct pcred *pc = p->p_cred;
        !           425:        register gid_t *gp;
        !           426:        register u_int ngrp;
        !           427:        register int *lp;
        !           428:        int error, groups[NGROUPS];
        !           429: 
        !           430:        if (error = suser(pc->pc_ucred, &p->p_acflag))
        !           431:                return (error);
        !           432:        if ((ngrp = uap->gidsetsize) > NGROUPS)
        !           433:                return (EINVAL);
        !           434:        if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
        !           435:            ngrp * sizeof (groups[0])))
        !           436:                return (error);
        !           437:        pc->pc_ucred = crcopy(pc->pc_ucred);
        !           438:        pc->pc_ucred->cr_ngroups = ngrp;
        !           439:        /* convert from int's to gid_t's */
        !           440:        for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
        !           441:                *gp++ = *lp++;
        !           442:        return (0);
        !           443: }
        !           444: 
        !           445: /*
        !           446:  * Check if gid is a member of the group set.
        !           447:  */
        !           448: groupmember(gid, cred)
        !           449:        gid_t gid;
        !           450:        register struct ucred *cred;
        !           451: {
        !           452:        register gid_t *gp;
        !           453:        gid_t *egp;
        !           454: 
        !           455:        egp = &(cred->cr_groups[cred->cr_ngroups]);
        !           456:        for (gp = cred->cr_groups; gp < egp; gp++)
        !           457:                if (*gp == gid)
        !           458:                        return (1);
        !           459:        return (0);
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Test whether the specified credentials imply "super-user"
        !           464:  * privilege; if so, and we have accounting info, set the flag
        !           465:  * indicating use of super-powers.
        !           466:  * Returns 0 or error.
        !           467:  */
        !           468: suser(cred, acflag)
        !           469:        struct ucred *cred;
        !           470:        short *acflag;
        !           471: {
        !           472:        if (cred->cr_uid == 0) {
        !           473:                if (acflag)
        !           474:                        *acflag |= ASU;
        !           475:                return (0);
        !           476:        }
        !           477:        return (EPERM);
        !           478: }
        !           479: 
        !           480: /*
        !           481:  * Allocate a zeroed cred structure.
        !           482:  */
        !           483: struct ucred *
        !           484: crget()
        !           485: {
        !           486:        register struct ucred *cr;
        !           487: 
        !           488:        MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
        !           489:        bzero((caddr_t)cr, sizeof(*cr));
        !           490:        cr->cr_ref = 1;
        !           491:        return (cr);
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * Free a cred structure.
        !           496:  * Throws away space when ref count gets to 0.
        !           497:  */
        !           498: crfree(cr)
        !           499:        struct ucred *cr;
        !           500: {
        !           501:        int s = splimp();                       /* ??? */
        !           502: 
        !           503:        if (--cr->cr_ref != 0) {
        !           504:                (void) splx(s);
        !           505:                return;
        !           506:        }
        !           507:        FREE((caddr_t)cr, M_CRED);
        !           508:        (void) splx(s);
        !           509: }
        !           510: 
        !           511: /*
        !           512:  * Copy cred structure to a new one and free the old one.
        !           513:  */
        !           514: struct ucred *
        !           515: crcopy(cr)
        !           516:        struct ucred *cr;
        !           517: {
        !           518:        struct ucred *newcr;
        !           519: 
        !           520:        if (cr->cr_ref == 1)
        !           521:                return (cr);
        !           522:        newcr = crget();
        !           523:        *newcr = *cr;
        !           524:        crfree(cr);
        !           525:        newcr->cr_ref = 1;
        !           526:        return (newcr);
        !           527: }
        !           528: 
        !           529: /*
        !           530:  * Dup cred struct to a new held one.
        !           531:  */
        !           532: struct ucred *
        !           533: crdup(cr)
        !           534:        struct ucred *cr;
        !           535: {
        !           536:        struct ucred *newcr;
        !           537: 
        !           538:        newcr = crget();
        !           539:        *newcr = *cr;
        !           540:        newcr->cr_ref = 1;
        !           541:        return (newcr);
        !           542: }
        !           543: 
        !           544: /*
        !           545:  * Get login name, if available.
        !           546:  */
        !           547: /* ARGSUSED */
        !           548: getlogin(p, uap, retval)
        !           549:        struct proc *p;
        !           550:        struct args {
        !           551:                char    *namebuf;
        !           552:                u_int   namelen;
        !           553:        } *uap;
        !           554:        int *retval;
        !           555: {
        !           556: 
        !           557:        if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
        !           558:                uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
        !           559:        return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
        !           560:            (caddr_t) uap->namebuf, uap->namelen));
        !           561: }
        !           562: 
        !           563: /*
        !           564:  * Set login name.
        !           565:  */
        !           566: /* ARGSUSED */
        !           567: setlogin(p, uap, retval)
        !           568:        struct proc *p;
        !           569:        struct args {
        !           570:                char    *namebuf;
        !           571:        } *uap;
        !           572:        int *retval;
        !           573: {
        !           574:        int error;
        !           575: 
        !           576:        if (error = suser(p->p_ucred, &p->p_acflag))
        !           577:                return (error);
        !           578:        error = copyinstr((caddr_t) uap->namebuf,
        !           579:            (caddr_t) p->p_pgrp->pg_session->s_login,
        !           580:            sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
        !           581:        if (error == ENAMETOOLONG)
        !           582:                error = EINVAL;
        !           583:        return (error);
        !           584: }

unix.superglobalmegacorp.com

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