[BACK]Return to kern_resource.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_resource.c, Revision 1.134

1.134   ! rmind       1: /*     $NetBSD: kern_resource.c,v 1.133 2008/02/24 21:44:51 christos Exp $     */
1.20      cgd         2:
1.17      cgd         3: /*-
1.19      cgd         4:  * Copyright (c) 1982, 1986, 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.17      cgd         6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
1.72      agc        20:  * 3. Neither the name of the University nor the names of its contributors
1.17      cgd        21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
1.45      fvdl       36:  *     @(#)kern_resource.c     8.8 (Berkeley) 2/14/95
1.17      cgd        37:  */
1.61      lukem      38:
                     39: #include <sys/cdefs.h>
1.134   ! rmind      40: __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.133 2008/02/24 21:44:51 christos Exp $");
1.44      mrg        41:
1.17      cgd        42: #include <sys/param.h>
1.22      cgd        43: #include <sys/systm.h>
1.17      cgd        44: #include <sys/kernel.h>
1.19      cgd        45: #include <sys/file.h>
1.17      cgd        46: #include <sys/resourcevar.h>
                     47: #include <sys/malloc.h>
1.132     yamt       48: #include <sys/kmem.h>
1.100     yamt       49: #include <sys/namei.h>
1.49      thorpej    50: #include <sys/pool.h>
1.17      cgd        51: #include <sys/proc.h>
1.74      atatat     52: #include <sys/sysctl.h>
1.129     yamt       53: #include <sys/timevar.h>
1.101     elad       54: #include <sys/kauth.h>
1.125     ad         55: #include <sys/atomic.h>
1.22      cgd        56: #include <sys/mount.h>
                     57: #include <sys/syscallargs.h>
1.17      cgd        58:
1.43      mrg        59: #include <uvm/uvm_extern.h>
                     60:
1.17      cgd        61: /*
1.60      eeh        62:  * Maximum process data and stack limits.
                     63:  * They are variables so they are patchable.
                     64:  */
                     65: rlim_t maxdmap = MAXDSIZ;
                     66: rlim_t maxsmap = MAXSSIZ;
                     67:
1.134   ! rmind      68: static kmutex_t                uihashtbl_lock;
        !            69: static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
        !            70: static u_long          uihash;
1.79      christos   71:
1.134   ! rmind      72: #define        UIHASH(uid)     (&uihashtbl[(uid) & uihash])
        !            73:
        !            74: static pool_cache_t    plimit_cache;
        !            75: static pool_cache_t    pstats_cache;
1.130     ad         76:
                     77: void
                     78: resource_init(void)
                     79: {
                     80:
                     81:        plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0,
                     82:            "plimitpl", NULL, IPL_NONE, NULL, NULL, NULL);
                     83:        pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0,
                     84:            "pstatspl", NULL, IPL_NONE, NULL, NULL, NULL);
1.134   ! rmind      85:        uihashtbl = hashinit(maxproc / 16, HASH_LIST, M_PROC,
        !            86:            M_WAITOK, &uihash);
1.130     ad         87: }
                     88:
1.60      eeh        89: /*
1.17      cgd        90:  * Resource controls and accounting.
                     91:  */
                     92:
1.25      cgd        93: int
1.134   ! rmind      94: sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap,
        !            95:     register_t *retval)
1.30      thorpej    96: {
1.128     dsl        97:        /* {
1.22      cgd        98:                syscallarg(int) which;
1.81      kleink     99:                syscallarg(id_t) who;
1.128     dsl       100:        } */
1.68      thorpej   101:        struct proc *curp = l->l_proc, *p;
1.54      augustss  102:        int low = NZERO + PRIO_MAX + 1;
1.113     ad        103:        int who = SCARG(uap, who);
1.17      cgd       104:
1.116     ad        105:        mutex_enter(&proclist_lock);
1.22      cgd       106:        switch (SCARG(uap, which)) {
1.17      cgd       107:        case PRIO_PROCESS:
1.113     ad        108:                if (who == 0)
1.17      cgd       109:                        p = curp;
                    110:                else
1.113     ad        111:                        p = p_find(who, PFIND_LOCKED);
                    112:                if (p != NULL)
                    113:                        low = p->p_nice;
1.17      cgd       114:                break;
                    115:
                    116:        case PRIO_PGRP: {
1.54      augustss  117:                struct pgrp *pg;
1.17      cgd       118:
1.113     ad        119:                if (who == 0)
1.17      cgd       120:                        pg = curp->p_pgrp;
1.113     ad        121:                else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
1.17      cgd       122:                        break;
1.64      matt      123:                LIST_FOREACH(p, &pg->pg_members, p_pglist) {
1.17      cgd       124:                        if (p->p_nice < low)
                    125:                                low = p->p_nice;
                    126:                }
                    127:                break;
                    128:        }
                    129:
                    130:        case PRIO_USER:
1.113     ad        131:                if (who == 0)
                    132:                        who = (int)kauth_cred_geteuid(l->l_cred);
1.86      yamt      133:                PROCLIST_FOREACH(p, &allproc) {
1.113     ad        134:                        mutex_enter(&p->p_mutex);
1.102     ad        135:                        if (kauth_cred_geteuid(p->p_cred) ==
1.113     ad        136:                            (uid_t)who && p->p_nice < low)
1.17      cgd       137:                                low = p->p_nice;
1.113     ad        138:                        mutex_exit(&p->p_mutex);
1.64      matt      139:                }
1.17      cgd       140:                break;
                    141:
                    142:        default:
1.116     ad        143:                mutex_exit(&proclist_lock);
1.17      cgd       144:                return (EINVAL);
                    145:        }
1.116     ad        146:        mutex_exit(&proclist_lock);
1.113     ad        147:
1.37      ws        148:        if (low == NZERO + PRIO_MAX + 1)
1.17      cgd       149:                return (ESRCH);
1.37      ws        150:        *retval = low - NZERO;
1.17      cgd       151:        return (0);
                    152: }
                    153:
                    154: /* ARGSUSED */
1.25      cgd       155: int
1.134   ! rmind     156: sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap,
        !           157:     register_t *retval)
1.30      thorpej   158: {
1.128     dsl       159:        /* {
1.22      cgd       160:                syscallarg(int) which;
1.81      kleink    161:                syscallarg(id_t) who;
1.22      cgd       162:                syscallarg(int) prio;
1.128     dsl       163:        } */
1.68      thorpej   164:        struct proc *curp = l->l_proc, *p;
1.17      cgd       165:        int found = 0, error = 0;
1.113     ad        166:        int who = SCARG(uap, who);
1.17      cgd       167:
1.116     ad        168:        mutex_enter(&proclist_lock);
1.22      cgd       169:        switch (SCARG(uap, which)) {
1.17      cgd       170:        case PRIO_PROCESS:
1.113     ad        171:                if (who == 0)
1.17      cgd       172:                        p = curp;
                    173:                else
1.113     ad        174:                        p = p_find(who, PFIND_LOCKED);
                    175:                if (p != 0) {
                    176:                        mutex_enter(&p->p_mutex);
                    177:                        error = donice(l, p, SCARG(uap, prio));
                    178:                        mutex_exit(&p->p_mutex);
                    179:                }
1.17      cgd       180:                found++;
                    181:                break;
                    182:
                    183:        case PRIO_PGRP: {
1.54      augustss  184:                struct pgrp *pg;
1.87      perry     185:
1.113     ad        186:                if (who == 0)
1.17      cgd       187:                        pg = curp->p_pgrp;
1.113     ad        188:                else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
1.17      cgd       189:                        break;
1.64      matt      190:                LIST_FOREACH(p, &pg->pg_members, p_pglist) {
1.113     ad        191:                        mutex_enter(&p->p_mutex);
1.102     ad        192:                        error = donice(l, p, SCARG(uap, prio));
1.113     ad        193:                        mutex_exit(&p->p_mutex);
1.17      cgd       194:                        found++;
                    195:                }
                    196:                break;
                    197:        }
                    198:
                    199:        case PRIO_USER:
1.113     ad        200:                if (who == 0)
                    201:                        who = (int)kauth_cred_geteuid(l->l_cred);
1.86      yamt      202:                PROCLIST_FOREACH(p, &allproc) {
1.113     ad        203:                        mutex_enter(&p->p_mutex);
1.102     ad        204:                        if (kauth_cred_geteuid(p->p_cred) ==
                    205:                            (uid_t)SCARG(uap, who)) {
                    206:                                error = donice(l, p, SCARG(uap, prio));
1.17      cgd       207:                                found++;
                    208:                        }
1.113     ad        209:                        mutex_exit(&p->p_mutex);
1.64      matt      210:                }
1.17      cgd       211:                break;
                    212:
                    213:        default:
1.113     ad        214:                error = EINVAL;
                    215:                break;
1.17      cgd       216:        }
1.116     ad        217:        mutex_exit(&proclist_lock);
1.17      cgd       218:        if (found == 0)
                    219:                return (ESRCH);
                    220:        return (error);
                    221: }
                    222:
1.113     ad        223: /*
                    224:  * Renice a process.
                    225:  *
                    226:  * Call with the target process' credentials locked.
                    227:  */
1.25      cgd       228: int
1.102     ad        229: donice(struct lwp *l, struct proc *chgp, int n)
1.17      cgd       230: {
1.102     ad        231:        kauth_cred_t cred = l->l_cred;
1.113     ad        232:        int onice;
                    233:
1.118     ad        234:        KASSERT(mutex_owned(&chgp->p_mutex));
1.17      cgd       235:
                    236:        if (n > PRIO_MAX)
                    237:                n = PRIO_MAX;
                    238:        if (n < PRIO_MIN)
                    239:                n = PRIO_MIN;
1.37      ws        240:        n += NZERO;
1.113     ad        241:        onice = chgp->p_nice;
                    242:        onice = chgp->p_nice;
                    243:
                    244:   again:
1.112     elad      245:        if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp,
                    246:            KAUTH_ARG(n), NULL, NULL))
1.17      cgd       247:                return (EACCES);
1.124     ad        248:        mutex_spin_enter(&chgp->p_smutex);
1.113     ad        249:        if (onice != chgp->p_nice) {
1.124     ad        250:                mutex_spin_exit(&chgp->p_smutex);
1.113     ad        251:                goto again;
                    252:        }
1.117     yamt      253:        sched_nice(chgp, n);
1.124     ad        254:        mutex_spin_exit(&chgp->p_smutex);
1.17      cgd       255:        return (0);
                    256: }
                    257:
                    258: /* ARGSUSED */
1.25      cgd       259: int
1.134   ! rmind     260: sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap,
        !           261:     register_t *retval)
1.30      thorpej   262: {
1.128     dsl       263:        /* {
1.42      mycroft   264:                syscallarg(int) which;
1.39      cgd       265:                syscallarg(const struct rlimit *) rlp;
1.128     dsl       266:        } */
1.42      mycroft   267:        int which = SCARG(uap, which);
1.19      cgd       268:        struct rlimit alim;
1.17      cgd       269:        int error;
                    270:
1.46      perry     271:        error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
1.33      christos  272:        if (error)
1.17      cgd       273:                return (error);
1.102     ad        274:        return (dosetrlimit(l, l->l_proc, which, &alim));
1.17      cgd       275: }
                    276:
                    277: int
1.102     ad        278: dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
1.17      cgd       279: {
1.54      augustss  280:        struct rlimit *alimp;
1.17      cgd       281:        int error;
                    282:
1.67      itojun    283:        if ((u_int)which >= RLIM_NLIMITS)
1.17      cgd       284:                return (EINVAL);
1.38      matthias  285:
                    286:        if (limp->rlim_cur < 0 || limp->rlim_max < 0)
                    287:                return (EINVAL);
                    288:
1.62      jdolecek  289:        if (limp->rlim_cur > limp->rlim_max) {
                    290:                /*
                    291:                 * This is programming error. According to SUSv2, we should
                    292:                 * return error in this case.
                    293:                 */
                    294:                return (EINVAL);
                    295:        }
1.122     dsl       296:
                    297:        alimp = &p->p_rlimit[which];
                    298:        /* if we don't change the value, no need to limcopy() */
                    299:        if (limp->rlim_cur == alimp->rlim_cur &&
                    300:            limp->rlim_max == alimp->rlim_max)
                    301:                return 0;
                    302:
1.112     elad      303:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
1.131     elad      304:            p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which));
1.111     elad      305:        if (error)
1.122     dsl       306:                return (error);
1.62      jdolecek  307:
1.122     dsl       308:        lim_privatise(p, false);
                    309:        /* p->p_limit is now unchangeable */
                    310:        alimp = &p->p_rlimit[which];
1.17      cgd       311:
                    312:        switch (which) {
                    313:
                    314:        case RLIMIT_DATA:
1.19      cgd       315:                if (limp->rlim_cur > maxdmap)
                    316:                        limp->rlim_cur = maxdmap;
                    317:                if (limp->rlim_max > maxdmap)
                    318:                        limp->rlim_max = maxdmap;
1.17      cgd       319:                break;
                    320:
                    321:        case RLIMIT_STACK:
1.19      cgd       322:                if (limp->rlim_cur > maxsmap)
                    323:                        limp->rlim_cur = maxsmap;
                    324:                if (limp->rlim_max > maxsmap)
                    325:                        limp->rlim_max = maxsmap;
1.62      jdolecek  326:
                    327:                /*
                    328:                 * Return EINVAL if the new stack size limit is lower than
                    329:                 * current usage. Otherwise, the process would get SIGSEGV the
                    330:                 * moment it would try to access anything on it's current stack.
                    331:                 * This conforms to SUSv2.
                    332:                 */
                    333:                if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE
1.113     ad        334:                    || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) {
1.62      jdolecek  335:                        return (EINVAL);
1.113     ad        336:                }
1.40      enami     337:
1.17      cgd       338:                /*
1.40      enami     339:                 * Stack is allocated to the max at exec time with
                    340:                 * only "rlim_cur" bytes accessible (In other words,
                    341:                 * allocates stack dividing two contiguous regions at
                    342:                 * "rlim_cur" bytes boundary).
                    343:                 *
                    344:                 * Since allocation is done in terms of page, roundup
                    345:                 * "rlim_cur" (otherwise, contiguous regions
                    346:                 * overlap).  If stack limit is going up make more
                    347:                 * accessible, if going down make inaccessible.
1.17      cgd       348:                 */
1.40      enami     349:                limp->rlim_cur = round_page(limp->rlim_cur);
1.17      cgd       350:                if (limp->rlim_cur != alimp->rlim_cur) {
1.48      eeh       351:                        vaddr_t addr;
                    352:                        vsize_t size;
1.17      cgd       353:                        vm_prot_t prot;
                    354:
                    355:                        if (limp->rlim_cur > alimp->rlim_cur) {
1.73      chs       356:                                prot = VM_PROT_READ | VM_PROT_WRITE;
1.17      cgd       357:                                size = limp->rlim_cur - alimp->rlim_cur;
1.91      fvdl      358:                                addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
                    359:                                    limp->rlim_cur;
1.17      cgd       360:                        } else {
                    361:                                prot = VM_PROT_NONE;
                    362:                                size = alimp->rlim_cur - limp->rlim_cur;
1.91      fvdl      363:                                addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
                    364:                                     alimp->rlim_cur;
1.17      cgd       365:                        }
1.43      mrg       366:                        (void) uvm_map_protect(&p->p_vmspace->vm_map,
1.114     thorpej   367:                            addr, addr+size, prot, false);
1.17      cgd       368:                }
                    369:                break;
1.19      cgd       370:
                    371:        case RLIMIT_NOFILE:
                    372:                if (limp->rlim_cur > maxfiles)
                    373:                        limp->rlim_cur = maxfiles;
                    374:                if (limp->rlim_max > maxfiles)
                    375:                        limp->rlim_max = maxfiles;
                    376:                break;
                    377:
                    378:        case RLIMIT_NPROC:
                    379:                if (limp->rlim_cur > maxproc)
                    380:                        limp->rlim_cur = maxproc;
                    381:                if (limp->rlim_max > maxproc)
                    382:                        limp->rlim_max = maxproc;
                    383:                break;
1.17      cgd       384:        }
1.122     dsl       385:
                    386:        mutex_enter(&p->p_limit->pl_lock);
1.17      cgd       387:        *alimp = *limp;
1.122     dsl       388:        mutex_exit(&p->p_limit->pl_lock);
1.17      cgd       389:        return (0);
                    390: }
                    391:
                    392: /* ARGSUSED */
1.25      cgd       393: int
1.134   ! rmind     394: sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap,
        !           395:     register_t *retval)
1.30      thorpej   396: {
1.128     dsl       397:        /* {
1.42      mycroft   398:                syscallarg(int) which;
1.22      cgd       399:                syscallarg(struct rlimit *) rlp;
1.128     dsl       400:        } */
1.68      thorpej   401:        struct proc *p = l->l_proc;
1.42      mycroft   402:        int which = SCARG(uap, which);
1.119     ad        403:        struct rlimit rl;
1.17      cgd       404:
1.67      itojun    405:        if ((u_int)which >= RLIM_NLIMITS)
1.17      cgd       406:                return (EINVAL);
1.119     ad        407:
                    408:        mutex_enter(&p->p_mutex);
                    409:        memcpy(&rl, &p->p_rlimit[which], sizeof(rl));
                    410:        mutex_exit(&p->p_mutex);
                    411:
                    412:        return copyout(&rl, SCARG(uap, rlp), sizeof(rl));
1.17      cgd       413: }
                    414:
                    415: /*
                    416:  * Transform the running time and tick information in proc p into user,
                    417:  * system, and interrupt time usage.
1.113     ad        418:  *
                    419:  * Should be called with p->p_smutex held unless called from exit1().
1.17      cgd       420:  */
1.25      cgd       421: void
1.98      thorpej   422: calcru(struct proc *p, struct timeval *up, struct timeval *sp,
1.113     ad        423:     struct timeval *ip, struct timeval *rp)
1.17      cgd       424: {
1.129     yamt      425:        uint64_t u, st, ut, it, tot;
1.68      thorpej   426:        struct lwp *l;
1.129     yamt      427:        struct bintime tm;
                    428:        struct timeval tv;
1.17      cgd       429:
1.113     ad        430:        mutex_spin_enter(&p->p_stmutex);
1.17      cgd       431:        st = p->p_sticks;
                    432:        ut = p->p_uticks;
                    433:        it = p->p_iticks;
1.113     ad        434:        mutex_spin_exit(&p->p_stmutex);
1.17      cgd       435:
1.129     yamt      436:        tm = p->p_rtime;
1.113     ad        437:
1.70      dsl       438:        LIST_FOREACH(l, &p->p_lwps, l_sibling) {
1.113     ad        439:                lwp_lock(l);
1.129     yamt      440:                bintime_add(&tm, &l->l_rtime);
1.123     ad        441:                if ((l->l_flag & LW_RUNNING) != 0) {
1.129     yamt      442:                        struct bintime diff;
1.68      thorpej   443:                        /*
                    444:                         * Adjust for the current time slice.  This is
                    445:                         * actually fairly important since the error
                    446:                         * here is on the order of a time quantum,
                    447:                         * which is much greater than the sampling
1.87      perry     448:                         * error.
1.68      thorpej   449:                         */
1.129     yamt      450:                        binuptime(&diff);
                    451:                        bintime_sub(&diff, &l->l_stime);
                    452:                        bintime_add(&tm, &diff);
1.68      thorpej   453:                }
1.113     ad        454:                lwp_unlock(l);
1.17      cgd       455:        }
1.69      dsl       456:
                    457:        tot = st + ut + it;
1.129     yamt      458:        bintime2timeval(&tm, &tv);
                    459:        u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec;
1.70      dsl       460:
1.69      dsl       461:        if (tot == 0) {
                    462:                /* No ticks, so can't use to share time out, split 50-50 */
1.70      dsl       463:                st = ut = u / 2;
                    464:        } else {
                    465:                st = (u * st) / tot;
                    466:                ut = (u * ut) / tot;
1.69      dsl       467:        }
1.113     ad        468:        if (sp != NULL) {
                    469:                sp->tv_sec = st / 1000000;
                    470:                sp->tv_usec = st % 1000000;
                    471:        }
                    472:        if (up != NULL) {
                    473:                up->tv_sec = ut / 1000000;
                    474:                up->tv_usec = ut % 1000000;
                    475:        }
1.17      cgd       476:        if (ip != NULL) {
1.70      dsl       477:                if (it != 0)
                    478:                        it = (u * it) / tot;
1.17      cgd       479:                ip->tv_sec = it / 1000000;
                    480:                ip->tv_usec = it % 1000000;
                    481:        }
1.113     ad        482:        if (rp != NULL) {
1.129     yamt      483:                *rp = tv;
1.113     ad        484:        }
1.17      cgd       485: }
                    486:
                    487: /* ARGSUSED */
1.25      cgd       488: int
1.134   ! rmind     489: sys_getrusage(struct lwp *l, const struct sys_getrusage_args *uap,
        !           490:     register_t *retval)
1.30      thorpej   491: {
1.128     dsl       492:        /* {
1.22      cgd       493:                syscallarg(int) who;
                    494:                syscallarg(struct rusage *) rusage;
1.128     dsl       495:        } */
1.119     ad        496:        struct rusage ru;
1.68      thorpej   497:        struct proc *p = l->l_proc;
1.17      cgd       498:
1.22      cgd       499:        switch (SCARG(uap, who)) {
1.19      cgd       500:        case RUSAGE_SELF:
1.113     ad        501:                mutex_enter(&p->p_smutex);
1.119     ad        502:                memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
                    503:                calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
1.113     ad        504:                mutex_exit(&p->p_smutex);
1.17      cgd       505:                break;
                    506:
                    507:        case RUSAGE_CHILDREN:
1.119     ad        508:                mutex_enter(&p->p_smutex);
                    509:                memcpy(&ru, &p->p_stats->p_cru, sizeof(ru));
                    510:                mutex_exit(&p->p_smutex);
1.17      cgd       511:                break;
                    512:
                    513:        default:
1.119     ad        514:                return EINVAL;
1.17      cgd       515:        }
1.119     ad        516:
                    517:        return copyout(&ru, SCARG(uap, rusage), sizeof(ru));
1.17      cgd       518: }
                    519:
1.25      cgd       520: void
1.98      thorpej   521: ruadd(struct rusage *ru, struct rusage *ru2)
1.17      cgd       522: {
1.54      augustss  523:        long *ip, *ip2;
                    524:        int i;
1.17      cgd       525:
1.27      mycroft   526:        timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
                    527:        timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
1.17      cgd       528:        if (ru->ru_maxrss < ru2->ru_maxrss)
                    529:                ru->ru_maxrss = ru2->ru_maxrss;
                    530:        ip = &ru->ru_first; ip2 = &ru2->ru_first;
                    531:        for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
                    532:                *ip++ += *ip2++;
                    533: }
                    534:
                    535: /*
                    536:  * Make a copy of the plimit structure.
                    537:  * We share these structures copy-on-write after fork,
                    538:  * and copy when a limit is changed.
1.113     ad        539:  *
1.122     dsl       540:  * Unfortunately (due to PL_SHAREMOD) it is possibly for the structure
                    541:  * we are copying to change beneath our feet!
1.17      cgd       542:  */
                    543: struct plimit *
1.122     dsl       544: lim_copy(struct plimit *lim)
1.17      cgd       545: {
1.122     dsl       546:        struct plimit *newlim;
1.113     ad        547:        char *corename;
1.122     dsl       548:        size_t alen, len;
1.17      cgd       549:
1.130     ad        550:        newlim = pool_cache_get(plimit_cache, PR_WAITOK);
1.121     dsl       551:        mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
                    552:        newlim->pl_flags = 0;
                    553:        newlim->pl_refcnt = 1;
1.122     dsl       554:        newlim->pl_sv_limit = NULL;
                    555:
                    556:        mutex_enter(&lim->pl_lock);
                    557:        memcpy(newlim->pl_rlimit, lim->pl_rlimit,
                    558:            sizeof(struct rlimit) * RLIM_NLIMITS);
1.83      pk        559:
1.122     dsl       560:        alen = 0;
                    561:        corename = NULL;
1.113     ad        562:        for (;;) {
1.122     dsl       563:                if (lim->pl_corename == defcorename) {
                    564:                        newlim->pl_corename = defcorename;
                    565:                        break;
                    566:                }
                    567:                len = strlen(lim->pl_corename) + 1;
                    568:                if (len <= alen) {
                    569:                        newlim->pl_corename = corename;
                    570:                        memcpy(corename, lim->pl_corename, len);
                    571:                        corename = NULL;
                    572:                        break;
                    573:                }
                    574:                mutex_exit(&lim->pl_lock);
                    575:                if (corename != NULL)
                    576:                        free(corename, M_TEMP);
                    577:                alen = len;
                    578:                corename = malloc(alen, M_TEMP, M_WAITOK);
1.121     dsl       579:                mutex_enter(&lim->pl_lock);
1.122     dsl       580:        }
                    581:        mutex_exit(&lim->pl_lock);
                    582:        if (corename != NULL)
                    583:                free(corename, M_TEMP);
                    584:        return newlim;
                    585: }
                    586:
                    587: void
                    588: lim_addref(struct plimit *lim)
                    589: {
1.125     ad        590:        atomic_inc_uint(&lim->pl_refcnt);
1.122     dsl       591: }
1.113     ad        592:
1.122     dsl       593: /*
                    594:  * Give a process it's own private plimit structure.
                    595:  * This will only be shared (in fork) if modifications are to be shared.
                    596:  */
                    597: void
                    598: lim_privatise(struct proc *p, bool set_shared)
                    599: {
                    600:        struct plimit *lim, *newlim;
                    601:
                    602:        lim = p->p_limit;
                    603:        if (lim->pl_flags & PL_WRITEABLE) {
                    604:                if (set_shared)
                    605:                        lim->pl_flags |= PL_SHAREMOD;
                    606:                return;
                    607:        }
                    608:
                    609:        if (set_shared && lim->pl_flags & PL_SHAREMOD)
                    610:                return;
                    611:
                    612:        newlim = lim_copy(lim);
1.113     ad        613:
1.122     dsl       614:        mutex_enter(&p->p_mutex);
                    615:        if (p->p_limit->pl_flags & PL_WRITEABLE) {
                    616:                /* Someone crept in while we were busy */
                    617:                mutex_exit(&p->p_mutex);
                    618:                limfree(newlim);
                    619:                if (set_shared)
                    620:                        p->p_limit->pl_flags |= PL_SHAREMOD;
                    621:                return;
1.113     ad        622:        }
1.83      pk        623:
1.122     dsl       624:        /*
                    625:         * Since most accesses to p->p_limit aren't locked, we must not
                    626:         * delete the old limit structure yet.
                    627:         */
                    628:        newlim->pl_sv_limit = p->p_limit;
                    629:        newlim->pl_flags |= PL_WRITEABLE;
                    630:        if (set_shared)
                    631:                newlim->pl_flags |= PL_SHAREMOD;
                    632:        p->p_limit = newlim;
                    633:        mutex_exit(&p->p_mutex);
1.32      mycroft   634: }
                    635:
                    636: void
1.98      thorpej   637: limfree(struct plimit *lim)
1.32      mycroft   638: {
1.122     dsl       639:        struct plimit *sv_lim;
1.85      kleink    640:
1.122     dsl       641:        do {
1.125     ad        642:                if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0)
1.122     dsl       643:                        return;
                    644:                if (lim->pl_corename != defcorename)
                    645:                        free(lim->pl_corename, M_TEMP);
                    646:                sv_lim = lim->pl_sv_limit;
                    647:                mutex_destroy(&lim->pl_lock);
1.130     ad        648:                pool_cache_put(plimit_cache, lim);
1.122     dsl       649:        } while ((lim = sv_lim) != NULL);
1.68      thorpej   650: }
                    651:
                    652: struct pstats *
1.98      thorpej   653: pstatscopy(struct pstats *ps)
1.68      thorpej   654: {
1.87      perry     655:
1.68      thorpej   656:        struct pstats *newps;
                    657:
1.130     ad        658:        newps = pool_cache_get(pstats_cache, PR_WAITOK);
1.68      thorpej   659:
                    660:        memset(&newps->pstat_startzero, 0,
1.115     christos  661:        (unsigned) ((char *)&newps->pstat_endzero -
                    662:                    (char *)&newps->pstat_startzero));
1.68      thorpej   663:        memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy,
1.115     christos  664:        ((char *)&newps->pstat_endcopy -
                    665:         (char *)&newps->pstat_startcopy));
1.68      thorpej   666:
                    667:        return (newps);
                    668:
                    669: }
                    670:
                    671: void
1.98      thorpej   672: pstatsfree(struct pstats *ps)
1.68      thorpej   673: {
                    674:
1.130     ad        675:        pool_cache_put(pstats_cache, ps);
1.74      atatat    676: }
                    677:
                    678: /*
                    679:  * sysctl interface in five parts
                    680:  */
                    681:
                    682: /*
                    683:  * a routine for sysctl proc subtree helpers that need to pick a valid
                    684:  * process by pid.
                    685:  */
                    686: static int
1.102     ad        687: sysctl_proc_findproc(struct lwp *l, struct proc **p2, pid_t pid)
1.74      atatat    688: {
                    689:        struct proc *ptmp;
1.101     elad      690:        int error = 0;
1.74      atatat    691:
                    692:        if (pid == PROC_CURPROC)
1.102     ad        693:                ptmp = l->l_proc;
1.74      atatat    694:        else if ((ptmp = pfind(pid)) == NULL)
                    695:                error = ESRCH;
                    696:
                    697:        *p2 = ptmp;
                    698:        return (error);
                    699: }
                    700:
                    701: /*
                    702:  * sysctl helper routine for setting a process's specific corefile
                    703:  * name.  picks the process based on the given pid and checks the
                    704:  * correctness of the new value.
                    705:  */
                    706: static int
                    707: sysctl_proc_corename(SYSCTLFN_ARGS)
                    708: {
1.102     ad        709:        struct proc *ptmp;
1.83      pk        710:        struct plimit *lim;
1.74      atatat    711:        int error = 0, len;
1.100     yamt      712:        char *cname;
1.122     dsl       713:        char *ocore;
1.100     yamt      714:        char *tmp;
1.74      atatat    715:        struct sysctlnode node;
                    716:
                    717:        /*
                    718:         * is this all correct?
                    719:         */
                    720:        if (namelen != 0)
                    721:                return (EINVAL);
                    722:        if (name[-1] != PROC_PID_CORENAME)
                    723:                return (EINVAL);
                    724:
                    725:        /*
                    726:         * whom are we tweaking?
                    727:         */
1.102     ad        728:        error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
1.74      atatat    729:        if (error)
                    730:                return (error);
                    731:
1.131     elad      732:        /* XXX-elad */
                    733:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
                    734:            KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
1.111     elad      735:        if (error)
                    736:                return (error);
                    737:
1.131     elad      738:        if (newp == NULL) {
                    739:                error = kauth_authorize_process(l->l_cred,
                    740:                    KAUTH_PROCESS_CORENAME, ptmp,
                    741:                    KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL);
                    742:                if (error)
                    743:                        return (error);
                    744:        }
                    745:
1.74      atatat    746:        /*
                    747:         * let them modify a temporary copy of the core name
                    748:         */
1.122     dsl       749:        cname = PNBUF_GET();
                    750:        lim = ptmp->p_limit;
                    751:        mutex_enter(&lim->pl_lock);
                    752:        strlcpy(cname, lim->pl_corename, MAXPATHLEN);
                    753:        mutex_exit(&lim->pl_lock);
                    754:
1.74      atatat    755:        node = *rnode;
                    756:        node.sysctl_data = cname;
                    757:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    758:
                    759:        /*
                    760:         * if that failed, or they have nothing new to say, or we've
                    761:         * heard it before...
                    762:         */
1.122     dsl       763:        if (error || newp == NULL)
                    764:                goto done;
                    765:        lim = ptmp->p_limit;
                    766:        mutex_enter(&lim->pl_lock);
                    767:        error = strcmp(cname, lim->pl_corename);
                    768:        mutex_exit(&lim->pl_lock);
                    769:        if (error == 0)
                    770:                /* Unchanged */
1.100     yamt      771:                goto done;
1.74      atatat    772:
1.111     elad      773:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CORENAME,
1.131     elad      774:            ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cname, NULL);
1.111     elad      775:        if (error)
                    776:                return (error);
1.103     elad      777:
1.74      atatat    778:        /*
                    779:         * no error yet and cname now has the new core name in it.
                    780:         * let's see if it looks acceptable.  it must be either "core"
                    781:         * or end in ".core" or "/core".
                    782:         */
                    783:        len = strlen(cname);
1.100     yamt      784:        if (len < 4) {
                    785:                error = EINVAL;
                    786:        } else if (strcmp(cname + len - 4, "core") != 0) {
                    787:                error = EINVAL;
                    788:        } else if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') {
                    789:                error = EINVAL;
                    790:        }
                    791:        if (error != 0) {
                    792:                goto done;
                    793:        }
1.74      atatat    794:
                    795:        /*
                    796:         * hmm...looks good.  now...where do we put it?
                    797:         */
                    798:        tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL);
1.100     yamt      799:        if (tmp == NULL) {
                    800:                error = ENOMEM;
                    801:                goto done;
                    802:        }
1.122     dsl       803:        memcpy(tmp, cname, len + 1);
1.74      atatat    804:
1.122     dsl       805:        lim_privatise(ptmp, false);
1.83      pk        806:        lim = ptmp->p_limit;
1.122     dsl       807:        mutex_enter(&lim->pl_lock);
                    808:        ocore = lim->pl_corename;
1.83      pk        809:        lim->pl_corename = tmp;
1.122     dsl       810:        mutex_exit(&lim->pl_lock);
                    811:        if (ocore != defcorename)
                    812:                free(ocore, M_TEMP);
                    813:
1.100     yamt      814: done:
                    815:        PNBUF_PUT(cname);
                    816:        return error;
1.74      atatat    817: }
                    818:
                    819: /*
                    820:  * sysctl helper routine for checking/setting a process's stop flags,
                    821:  * one for fork and one for exec.
                    822:  */
                    823: static int
                    824: sysctl_proc_stop(SYSCTLFN_ARGS)
                    825: {
1.102     ad        826:        struct proc *ptmp;
1.74      atatat    827:        int i, f, error = 0;
                    828:        struct sysctlnode node;
                    829:
                    830:        if (namelen != 0)
                    831:                return (EINVAL);
                    832:
1.102     ad        833:        error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
1.74      atatat    834:        if (error)
                    835:                return (error);
                    836:
1.131     elad      837:        /* XXX-elad */
                    838:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
                    839:            KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
1.111     elad      840:        if (error)
                    841:                return (error);
                    842:
1.74      atatat    843:        switch (rnode->sysctl_num) {
                    844:        case PROC_PID_STOPFORK:
1.113     ad        845:                f = PS_STOPFORK;
1.74      atatat    846:                break;
                    847:        case PROC_PID_STOPEXEC:
1.113     ad        848:                f = PS_STOPEXEC;
1.74      atatat    849:                break;
                    850:        case PROC_PID_STOPEXIT:
1.113     ad        851:                f = PS_STOPEXIT;
1.74      atatat    852:                break;
                    853:        default:
                    854:                return (EINVAL);
                    855:        }
                    856:
                    857:        i = (ptmp->p_flag & f) ? 1 : 0;
                    858:        node = *rnode;
                    859:        node.sysctl_data = &i;
                    860:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    861:        if (error || newp == NULL)
                    862:                return (error);
                    863:
1.113     ad        864:        mutex_enter(&ptmp->p_smutex);
1.111     elad      865:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG,
                    866:            ptmp, KAUTH_ARG(f), NULL, NULL);
                    867:        if (error)
                    868:                return (error);
1.74      atatat    869:        if (i)
1.113     ad        870:                ptmp->p_sflag |= f;
1.74      atatat    871:        else
1.113     ad        872:                ptmp->p_sflag &= ~f;
                    873:        mutex_exit(&ptmp->p_smutex);
1.74      atatat    874:
                    875:        return (0);
                    876: }
                    877:
                    878: /*
                    879:  * sysctl helper routine for a process's rlimits as exposed by sysctl.
                    880:  */
                    881: static int
                    882: sysctl_proc_plimit(SYSCTLFN_ARGS)
                    883: {
1.102     ad        884:        struct proc *ptmp;
1.74      atatat    885:        u_int limitno;
                    886:        int which, error = 0;
                    887:         struct rlimit alim;
                    888:        struct sysctlnode node;
                    889:
                    890:        if (namelen != 0)
                    891:                return (EINVAL);
                    892:
                    893:        which = name[-1];
                    894:        if (which != PROC_PID_LIMIT_TYPE_SOFT &&
                    895:            which != PROC_PID_LIMIT_TYPE_HARD)
                    896:                return (EINVAL);
                    897:
                    898:        limitno = name[-2] - 1;
                    899:        if (limitno >= RLIM_NLIMITS)
                    900:                return (EINVAL);
                    901:
                    902:        if (name[-3] != PROC_PID_LIMIT)
                    903:                return (EINVAL);
                    904:
1.102     ad        905:        error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-4]);
1.74      atatat    906:        if (error)
                    907:                return (error);
                    908:
1.131     elad      909:        /* XXX-elad */
                    910:        error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
                    911:            KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
1.111     elad      912:        if (error)
                    913:                return (error);
                    914:
1.131     elad      915:        /* Check if we can view limits. */
                    916:        if (newp == NULL) {
                    917:                error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
                    918:                    ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim,
                    919:                    KAUTH_ARG(which));
                    920:                if (error)
                    921:                        return (error);
                    922:        }
                    923:
1.74      atatat    924:        node = *rnode;
                    925:        memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim));
                    926:        if (which == PROC_PID_LIMIT_TYPE_HARD)
                    927:                node.sysctl_data = &alim.rlim_max;
                    928:        else
                    929:                node.sysctl_data = &alim.rlim_cur;
                    930:
                    931:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                    932:        if (error || newp == NULL)
                    933:                return (error);
                    934:
1.102     ad        935:        return (dosetrlimit(l, ptmp, limitno, &alim));
1.74      atatat    936: }
                    937:
                    938: /*
                    939:  * and finally, the actually glue that sticks it to the tree
                    940:  */
                    941: SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup")
                    942: {
                    943:
1.76      atatat    944:        sysctl_createv(clog, 0, NULL, NULL,
                    945:                       CTLFLAG_PERMANENT,
1.74      atatat    946:                       CTLTYPE_NODE, "proc", NULL,
                    947:                       NULL, 0, NULL, 0,
                    948:                       CTL_PROC, CTL_EOL);
1.76      atatat    949:        sysctl_createv(clog, 0, NULL, NULL,
                    950:                       CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
1.78      atatat    951:                       CTLTYPE_NODE, "curproc",
                    952:                       SYSCTL_DESCR("Per-process settings"),
1.74      atatat    953:                       NULL, 0, NULL, 0,
                    954:                       CTL_PROC, PROC_CURPROC, CTL_EOL);
                    955:
1.76      atatat    956:        sysctl_createv(clog, 0, NULL, NULL,
1.103     elad      957:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1.78      atatat    958:                       CTLTYPE_STRING, "corename",
                    959:                       SYSCTL_DESCR("Core file name"),
1.74      atatat    960:                       sysctl_proc_corename, 0, NULL, MAXPATHLEN,
                    961:                       CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
1.76      atatat    962:        sysctl_createv(clog, 0, NULL, NULL,
                    963:                       CTLFLAG_PERMANENT,
1.78      atatat    964:                       CTLTYPE_NODE, "rlimit",
                    965:                       SYSCTL_DESCR("Process limits"),
1.74      atatat    966:                       NULL, 0, NULL, 0,
                    967:                       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
                    968:
                    969: #define create_proc_plimit(s, n) do {                                  \
1.76      atatat    970:        sysctl_createv(clog, 0, NULL, NULL,                             \
                    971:                       CTLFLAG_PERMANENT,                               \
1.78      atatat    972:                       CTLTYPE_NODE, s,                                 \
                    973:                       SYSCTL_DESCR("Process " s " limits"),            \
1.74      atatat    974:                       NULL, 0, NULL, 0,                                \
                    975:                       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
                    976:                       CTL_EOL);                                        \
1.76      atatat    977:        sysctl_createv(clog, 0, NULL, NULL,                             \
                    978:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1.78      atatat    979:                       CTLTYPE_QUAD, "soft",                            \
                    980:                       SYSCTL_DESCR("Process soft " s " limit"),        \
1.74      atatat    981:                       sysctl_proc_plimit, 0, NULL, 0,                  \
                    982:                       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
                    983:                       PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL);              \
1.76      atatat    984:        sysctl_createv(clog, 0, NULL, NULL,                             \
                    985:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1.78      atatat    986:                       CTLTYPE_QUAD, "hard",                            \
                    987:                       SYSCTL_DESCR("Process hard " s " limit"),        \
1.74      atatat    988:                       sysctl_proc_plimit, 0, NULL, 0,                  \
                    989:                       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,       \
                    990:                       PROC_PID_LIMIT_TYPE_HARD, CTL_EOL);              \
                    991:        } while (0/*CONSTCOND*/)
                    992:
                    993:        create_proc_plimit("cputime",           PROC_PID_LIMIT_CPU);
                    994:        create_proc_plimit("filesize",          PROC_PID_LIMIT_FSIZE);
                    995:        create_proc_plimit("datasize",          PROC_PID_LIMIT_DATA);
                    996:        create_proc_plimit("stacksize",         PROC_PID_LIMIT_STACK);
                    997:        create_proc_plimit("coredumpsize",      PROC_PID_LIMIT_CORE);
                    998:        create_proc_plimit("memoryuse",         PROC_PID_LIMIT_RSS);
                    999:        create_proc_plimit("memorylocked",      PROC_PID_LIMIT_MEMLOCK);
                   1000:        create_proc_plimit("maxproc",           PROC_PID_LIMIT_NPROC);
                   1001:        create_proc_plimit("descriptors",       PROC_PID_LIMIT_NOFILE);
1.79      christos 1002:        create_proc_plimit("sbsize",            PROC_PID_LIMIT_SBSIZE);
1.74      atatat   1003:
                   1004: #undef create_proc_plimit
                   1005:
1.76      atatat   1006:        sysctl_createv(clog, 0, NULL, NULL,
                   1007:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1.78      atatat   1008:                       CTLTYPE_INT, "stopfork",
                   1009:                       SYSCTL_DESCR("Stop process at fork(2)"),
1.74      atatat   1010:                       sysctl_proc_stop, 0, NULL, 0,
                   1011:                       CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
1.76      atatat   1012:        sysctl_createv(clog, 0, NULL, NULL,
                   1013:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1.78      atatat   1014:                       CTLTYPE_INT, "stopexec",
                   1015:                       SYSCTL_DESCR("Stop process at execve(2)"),
1.74      atatat   1016:                       sysctl_proc_stop, 0, NULL, 0,
                   1017:                       CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
1.76      atatat   1018:        sysctl_createv(clog, 0, NULL, NULL,
                   1019:                       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1.78      atatat   1020:                       CTLTYPE_INT, "stopexit",
                   1021:                       SYSCTL_DESCR("Stop process before completing exit"),
1.74      atatat   1022:                       sysctl_proc_stop, 0, NULL, 0,
                   1023:                       CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
1.17      cgd      1024: }
1.79      christos 1025:
1.118     ad       1026: void
                   1027: uid_init(void)
                   1028: {
                   1029:
                   1030:        /*
                   1031:         * XXXSMP This could be at IPL_SOFTNET, but for now we want
                   1032:         * to to be deadlock free, so it must be at IPL_VM.
                   1033:         */
1.127     ad       1034:        mutex_init(&uihashtbl_lock, MUTEX_DEFAULT, IPL_VM);
1.118     ad       1035:
                   1036:        /*
                   1037:         * Ensure that uid 0 is always in the user hash table, as
                   1038:         * sbreserve() expects it available from interrupt context.
                   1039:         */
                   1040:        (void)uid_find(0);
                   1041: }
                   1042:
1.88      christos 1043: struct uidinfo *
                   1044: uid_find(uid_t uid)
1.79      christos 1045: {
                   1046:        struct uidinfo *uip;
1.90      christos 1047:        struct uidinfo *newuip = NULL;
1.79      christos 1048:        struct uihashhead *uipp;
                   1049:
                   1050:        uipp = UIHASH(uid);
                   1051:
1.90      christos 1052: again:
1.118     ad       1053:        mutex_enter(&uihashtbl_lock);
1.79      christos 1054:        LIST_FOREACH(uip, uipp, ui_hash)
1.88      christos 1055:                if (uip->ui_uid == uid) {
1.118     ad       1056:                        mutex_exit(&uihashtbl_lock);
                   1057:                        if (newuip) {
1.120     rmind    1058:                                mutex_destroy(&newuip->ui_lock);
1.132     yamt     1059:                                kmem_free(newuip, sizeof(*newuip));
1.118     ad       1060:                        }
1.79      christos 1061:                        return uip;
1.88      christos 1062:                }
1.90      christos 1063:        if (newuip == NULL) {
1.118     ad       1064:                mutex_exit(&uihashtbl_lock);
                   1065:                /* Must not be called from interrupt context. */
1.132     yamt     1066:                newuip = kmem_zalloc(sizeof(*newuip), KM_SLEEP);
1.123     ad       1067:                /* XXX this could be IPL_SOFTNET */
1.127     ad       1068:                mutex_init(&newuip->ui_lock, MUTEX_DEFAULT, IPL_VM);
1.90      christos 1069:                goto again;
                   1070:        }
                   1071:        uip = newuip;
1.89      christos 1072:
1.79      christos 1073:        LIST_INSERT_HEAD(uipp, uip, ui_hash);
                   1074:        uip->ui_uid = uid;
1.118     ad       1075:        mutex_exit(&uihashtbl_lock);
1.89      christos 1076:
1.79      christos 1077:        return uip;
                   1078: }
                   1079:
                   1080: /*
                   1081:  * Change the count associated with number of processes
                   1082:  * a given user is using.
                   1083:  */
                   1084: int
                   1085: chgproccnt(uid_t uid, int diff)
                   1086: {
                   1087:        struct uidinfo *uip;
                   1088:
1.88      christos 1089:        uip = uid_find(uid);
1.118     ad       1090:        mutex_enter(&uip->ui_lock);
1.88      christos 1091:        uip->ui_proccnt += diff;
                   1092:        KASSERT(uip->ui_proccnt >= 0);
1.118     ad       1093:        mutex_exit(&uip->ui_lock);
1.88      christos 1094:        return uip->ui_proccnt;
1.79      christos 1095: }
                   1096:
                   1097: int
1.97      christos 1098: chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t xmax)
1.79      christos 1099: {
                   1100:        rlim_t nsb;
                   1101:
1.118     ad       1102:        mutex_enter(&uip->ui_lock);
1.80      yamt     1103:        nsb = uip->ui_sbsize + to - *hiwat;
1.97      christos 1104:        if (to > *hiwat && nsb > xmax) {
1.118     ad       1105:                mutex_exit(&uip->ui_lock);
1.88      christos 1106:                return 0;
1.94      christos 1107:        }
1.79      christos 1108:        *hiwat = to;
                   1109:        uip->ui_sbsize = nsb;
                   1110:        KASSERT(uip->ui_sbsize >= 0);
1.118     ad       1111:        mutex_exit(&uip->ui_lock);
1.88      christos 1112:        return 1;
1.79      christos 1113: }

CVSweb <webmaster@jp.NetBSD.org>