Annotation of kernel/bsd/kern/kern_resource.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
                     26: /*-
                     27:  * Copyright (c) 1982, 1986, 1991, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  * (c) UNIX System Laboratories, Inc.
                     30:  * All or some portions of this file are derived from material licensed
                     31:  * to the University of California by American Telephone and Telegraph
                     32:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     33:  * the permission of UNIX System Laboratories, Inc.
                     34:  *
                     35:  * Redistribution and use in source and binary forms, with or without
                     36:  * modification, are permitted provided that the following conditions
                     37:  * are met:
                     38:  * 1. Redistributions of source code must retain the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer.
                     40:  * 2. Redistributions in binary form must reproduce the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer in the
                     42:  *    documentation and/or other materials provided with the distribution.
                     43:  * 3. All advertising materials mentioning features or use of this software
                     44:  *    must display the following acknowledgement:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Berkeley and its contributors.
                     47:  * 4. Neither the name of the University nor the names of its contributors
                     48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  *
                     63:  *     @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
                     64:  */
                     65: 
                     66: #include <sys/param.h>
                     67: #include <sys/systm.h>
                     68: #include <sys/kernel.h>
                     69: #include <sys/file.h>
                     70: #include <sys/resourcevar.h>
                     71: #include <sys/malloc.h>
                     72: #include <sys/proc.h>
                     73: #include <machine/spl.h>
                     74: 
                     75: #include <sys/mount.h>
                     76: 
                     77: #include <machine/vmparam.h>
                     78: 
                     79: #include <mach/mach_types.h>
                     80: 
                     81: int    donice __P((struct proc *curp, struct proc *chgp, int n));
                     82: int    dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp));
                     83: 
                     84: rlim_t maxdmap = MAXDSIZ;      /* XXX */ 
                     85: rlim_t maxsmap = MAXSSIZ;      /* XXX */ 
                     86: 
                     87: /*
                     88:  * Resource controls and accounting.
                     89:  */
                     90: struct getpriority_args  {
                     91:                int which;
                     92:                int who;
                     93: };
                     94: int
                     95: getpriority(curp, uap, retval)
                     96:        struct proc *curp;
                     97:        register struct getpriority_args *uap;
                     98:        register_t *retval;
                     99: {
                    100:        register struct proc *p;
                    101:        register int low = PRIO_MAX + 1;
                    102: 
                    103:        switch (uap->which) {
                    104: 
                    105:        case PRIO_PROCESS:
                    106:                if (uap->who == 0)
                    107:                        p = curp;
                    108:                else
                    109:                        p = pfind(uap->who);
                    110:                if (p == 0)
                    111:                        break;
                    112:                low = p->p_nice;
                    113:                break;
                    114: 
                    115:        case PRIO_PGRP: {
                    116:                register struct pgrp *pg;
                    117: 
                    118:                if (uap->who == 0)
                    119:                        pg = curp->p_pgrp;
                    120:                else if ((pg = pgfind(uap->who)) == NULL)
                    121:                        break;
                    122:                for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
                    123:                        if (p->p_nice < low)
                    124:                                low = p->p_nice;
                    125:                }
                    126:                break;
                    127:        }
                    128: 
                    129:        case PRIO_USER:
                    130:                if (uap->who == 0)
                    131:                        uap->who = curp->p_ucred->cr_uid;
                    132:                for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
                    133:                        if (p->p_ucred->cr_uid == uap->who &&
                    134:                            p->p_nice < low)
                    135:                                low = p->p_nice;
                    136:                break;
                    137: 
                    138:        default:
                    139:                return (EINVAL);
                    140:        }
                    141:        if (low == PRIO_MAX + 1)
                    142:                return (ESRCH);
                    143:        *retval = low;
                    144:        return (0);
                    145: }
                    146: 
                    147: struct setpriority_args {
                    148:                int which;
                    149:                int who;
                    150:                int prio;
                    151: };
                    152: /* ARGSUSED */
                    153: int
                    154: setpriority(curp, uap, retval)
                    155:        struct proc *curp;
                    156:        register struct setpriority_args *uap;
                    157:        register_t *retval;
                    158: {
                    159:        register struct proc *p;
                    160:        int found = 0, error = 0;
                    161: 
                    162:        switch (uap->which) {
                    163: 
                    164:        case PRIO_PROCESS:
                    165:                if (uap->who == 0)
                    166:                        p = curp;
                    167:                else
                    168:                        p = pfind(uap->who);
                    169:                if (p == 0)
                    170:                        break;
                    171:                error = donice(curp, p, uap->prio);
                    172:                found++;
                    173:                break;
                    174: 
                    175:        case PRIO_PGRP: {
                    176:                register struct pgrp *pg;
                    177:                 
                    178:                if (uap->who == 0)
                    179:                        pg = curp->p_pgrp;
                    180:                else if ((pg = pgfind(uap->who)) == NULL)
                    181:                        break;
                    182:                for (p = pg->pg_members.lh_first; p != 0;
                    183:                    p = p->p_pglist.le_next) {
                    184:                        error = donice(curp, p, uap->prio);
                    185:                        found++;
                    186:                }
                    187:                break;
                    188:        }
                    189: 
                    190:        case PRIO_USER:
                    191:                if (uap->who == 0)
                    192:                        uap->who = curp->p_ucred->cr_uid;
                    193:                for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
                    194:                        if (p->p_ucred->cr_uid == uap->who) {
                    195:                                error = donice(curp, p, uap->prio);
                    196:                                found++;
                    197:                        }
                    198:                break;
                    199: 
                    200:        default:
                    201:                return (EINVAL);
                    202:        }
                    203:        if (found == 0)
                    204:                return (ESRCH);
                    205:        return (error);
                    206: }
                    207: 
                    208: int
                    209: donice(curp, chgp, n)
                    210:        register struct proc *curp, *chgp;
                    211:        register int n;
                    212: {
                    213:        register struct pcred *pcred = curp->p_cred;
                    214: 
                    215:        if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
                    216:            pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
                    217:            pcred->p_ruid != chgp->p_ucred->cr_uid)
                    218:                return (EPERM);
                    219:        if (n > PRIO_MAX)
                    220:                n = PRIO_MAX;
                    221:        if (n < PRIO_MIN)
                    222:                n = PRIO_MIN;
                    223:        if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
                    224:                return (EACCES);
                    225:        chgp->p_nice = n;
                    226:        (void)resetpriority(chgp);
                    227:        return (0);
                    228: }
                    229: 
                    230: #if COMPAT_43
                    231: struct osetrlimit_args {
                    232:                u_int which;
                    233:                struct ogetrlimit * rlp;
                    234: };
                    235: /* ARGSUSED */
                    236: int
                    237: osetrlimit(p, uap, retval)
                    238:        struct proc *p;
                    239:        struct osetrlimit_args *uap;
                    240:        register_t *retval;
                    241: {
                    242:        struct orlimit olim;
                    243:        struct rlimit lim;
                    244:        int error;
                    245: 
                    246:        if (error = copyin((caddr_t)uap->rlp, (caddr_t)&olim,
                    247:            sizeof (struct orlimit)))
                    248:                return (error);
                    249:        lim.rlim_cur = olim.rlim_cur;
                    250:        lim.rlim_max = olim.rlim_max;
                    251:        return (dosetrlimit(p, uap->which, &lim));
                    252: }
                    253: 
                    254: struct ogetrlimit_args {
                    255:                u_int which;
                    256:                struct ogetrlimit * rlp;
                    257: };
                    258: /* ARGSUSED */
                    259: int
                    260: ogetrlimit(p, uap, retval)
                    261:        struct proc *p;
                    262:        struct ogetrlimit_args *uap;
                    263:        register_t *retval;
                    264: {
                    265:        struct orlimit olim;
                    266: 
                    267:        if (uap->which >= RLIM_NLIMITS)
                    268:                return (EINVAL);
                    269:        olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur;
                    270:        if (olim.rlim_cur == -1)
                    271:                olim.rlim_cur = 0x7fffffff;
                    272:        olim.rlim_max = p->p_rlimit[uap->which].rlim_max;
                    273:        if (olim.rlim_max == -1)
                    274:                olim.rlim_max = 0x7fffffff;
                    275:        return (copyout((caddr_t)&olim, (caddr_t)uap->rlp,
                    276:            sizeof(olim)));
                    277: }
                    278: #endif /* COMPAT_43 */
                    279: 
                    280: struct setrlimit_args {
                    281:                u_int which;
                    282:                struct rlimit * rlp;
                    283: };
                    284: /* ARGSUSED */
                    285: int
                    286: setrlimit(p, uap, retval)
                    287:        struct proc *p;
                    288:        register struct setrlimit_args *uap;
                    289:        register_t *retval;
                    290: {
                    291:        struct rlimit alim;
                    292:        int error;
                    293: 
                    294:        if (error = copyin((caddr_t)uap->rlp, (caddr_t)&alim,
                    295:            sizeof (struct rlimit)))
                    296:                return (error);
                    297:        return (dosetrlimit(p, uap->which, &alim));
                    298: }
                    299: 
                    300: int
                    301: dosetrlimit(p, which, limp)
                    302:        struct proc *p;
                    303:        u_int which;
                    304:        struct rlimit *limp;
                    305: {
                    306:        register struct rlimit *alimp;
                    307:        extern rlim_t maxdmap, maxsmap;
                    308:        int error;
                    309: 
                    310:        if (which >= RLIM_NLIMITS)
                    311:                return (EINVAL);
                    312:        alimp = &p->p_rlimit[which];
                    313:        if (limp->rlim_cur > alimp->rlim_max || 
                    314:            limp->rlim_max > alimp->rlim_max)
                    315:                if (error = suser(p->p_ucred, &p->p_acflag))
                    316:                        return (error);
                    317:        if (limp->rlim_cur > limp->rlim_max)
                    318:                limp->rlim_cur = limp->rlim_max;
                    319:        if (p->p_limit->p_refcnt > 1 &&
                    320:            (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
                    321:                p->p_limit->p_refcnt--;
                    322:                p->p_limit = limcopy(p->p_limit);
                    323:                alimp = &p->p_rlimit[which];
                    324:        }
                    325: 
                    326:        switch (which) {
                    327: 
                    328:        case RLIMIT_DATA:
                    329:                if (limp->rlim_cur > maxdmap)
                    330:                        limp->rlim_cur = maxdmap;
                    331:                if (limp->rlim_max > maxdmap)
                    332:                        limp->rlim_max = maxdmap;
                    333:                break;
                    334: 
                    335:        case RLIMIT_STACK:
                    336:                if (limp->rlim_cur > maxsmap)
                    337:                        limp->rlim_cur = maxsmap;
                    338:                if (limp->rlim_max > maxsmap)
                    339:                        limp->rlim_max = maxsmap;
                    340:                /*
                    341:                 * Stack is allocated to the max at exec time with only
                    342:                 * "rlim_cur" bytes accessible.  If stack limit is going
                    343:                 * up make more accessible, if going down make inaccessible.
                    344:                 */
                    345:                if (limp->rlim_cur != alimp->rlim_cur) {
                    346:                        vm_offset_t addr;
                    347:                        vm_size_t size;
                    348:                        vm_prot_t prot;
                    349:                        
                    350:                        if (limp->rlim_cur > alimp->rlim_cur) {
                    351:                                /* grow stack */
                    352:                                size = round_page(limp->rlim_cur);
                    353:                                size -= round_page(alimp->rlim_cur);
                    354: 
                    355: #if STACK_GROWTH_UP
                    356:                                /* go to top of current stack */
                    357:                                addr = trunc_page(p->user_stack + alimp->rlim_cur);
                    358: #else STACK_GROWTH_UP
                    359:                                addr = trunc_page(p->user_stack - alimp->rlim_cur);
                    360:                                addr -= size;
                    361: #endif /* STACK_GROWTH_UP */
                    362:                                if (vm_allocate(current_task()->map, &addr, size,
                    363:                                        FALSE) != KERN_SUCCESS)
                    364:                                                return(EINVAL);
                    365:                        } else {
                    366:                                /* shrink stack */
                    367:                        }
                    368:                }
                    369:                break;
                    370: 
                    371:        case RLIMIT_NOFILE:
                    372:        /* 
                    373:         * Only root can get the maxfiles limits, as it is systemwide resource
                    374:         */
                    375:                if (is_suser()) {
                    376:                        if (limp->rlim_cur > maxfiles)
                    377:                                limp->rlim_cur = maxfiles;
                    378:                        if (limp->rlim_max > maxfiles)
                    379:                                limp->rlim_max = maxfiles;
                    380:                } else {
                    381:                        if (limp->rlim_cur > OPEN_MAX)
                    382:                                limp->rlim_cur = OPEN_MAX;
                    383:                        if (limp->rlim_max > OPEN_MAX)
                    384:                                limp->rlim_max = OPEN_MAX;
                    385:                }
                    386:                break;
                    387: 
                    388:        case RLIMIT_NPROC:
                    389:        /* 
                    390:         * Only root can get the maxproc limits, as it is systemwide resource
                    391:         */
                    392:                if (is_suser()) {
                    393:                        if (limp->rlim_cur > maxproc)
                    394:                                limp->rlim_cur = maxproc;
                    395:                        if (limp->rlim_max > maxproc)
                    396:                                limp->rlim_max = maxproc;
                    397:                } else {
                    398:                        if (limp->rlim_cur > CHILD_MAX)
                    399:                                limp->rlim_cur = CHILD_MAX;
                    400:                        if (limp->rlim_max > CHILD_MAX)
                    401:                                limp->rlim_max = CHILD_MAX;
                    402:                }
                    403:                break;
                    404:        }
                    405:        *alimp = *limp;
                    406:        return (0);
                    407: }
                    408: 
                    409: struct getrlimit_args {
                    410:                u_int which;
                    411:                struct rlimit * rlp;
                    412: };
                    413: /* ARGSUSED */
                    414: int
                    415: getrlimit(p, uap, retval)
                    416:        struct proc *p;
                    417:        register struct getrlimit_args *uap;
                    418:        register_t *retval;
                    419: {
                    420: 
                    421:        if (uap->which >= RLIM_NLIMITS)
                    422:                return (EINVAL);
                    423:        return (copyout((caddr_t)&p->p_rlimit[uap->which],
                    424:            (caddr_t)uap->rlp, sizeof (struct rlimit)));
                    425: }
                    426: 
                    427: /*
                    428:  * Transform the running time and tick information in proc p into user,
                    429:  * system, and interrupt time usage.
                    430:  */
                    431: void
                    432: calcru(p, up, sp, ip)
                    433:        register struct proc *p;
                    434:        register struct timeval *up;
                    435:        register struct timeval *sp;
                    436:        register struct timeval *ip;
                    437: {
                    438:        task_t                  task;
                    439: 
                    440:        timerclear(up);
                    441:        timerclear(sp);
                    442:        if (ip != NULL)
                    443:                timerclear(ip);
                    444: 
                    445:        if ((task = p->task) != NULL) {
                    446:                thread_t        thread;
                    447:                struct timeval  tmptv;
                    448:                int             s;
                    449: 
                    450:                task_lock(task);
                    451:                s = splsched();
                    452:                simple_lock(&task->thread_list_lock);
                    453: 
                    454:                thread = (thread_t)queue_first(&task->thread_list);
                    455:                while (!queue_end(&task->thread_list, (queue_entry_t)thread)) {
                    456:                        struct time_value       system, user;
                    457: 
                    458:                        thread_read_times(thread, &user, &system);
                    459: 
                    460:                        tmptv.tv_sec = user.seconds;
                    461:                        tmptv.tv_usec = user.microseconds;
                    462:                        timeradd(&tmptv, up, up);
                    463: 
                    464:                        tmptv.tv_sec = system.seconds;
                    465:                        tmptv.tv_usec = system.microseconds;
                    466:                        timeradd(&tmptv, sp, sp);
                    467: 
                    468:                        thread = (thread_t)queue_next(&thread->thread_list);
                    469:                }
                    470: 
                    471:                simple_unlock(&task->thread_list_lock);
                    472:                splx(s);
                    473: 
                    474:                tmptv.tv_sec = task->total_user_time.seconds;
                    475:                tmptv.tv_usec = task->total_user_time.microseconds;
                    476:                timeradd(&tmptv, up, up);
                    477: 
                    478:                tmptv.tv_sec = task->total_system_time.seconds;
                    479:                tmptv.tv_usec = task->total_system_time.microseconds;
                    480:                timeradd(&tmptv, sp, sp);
                    481: 
                    482:                task_unlock(task);
                    483:        }
                    484: }
                    485: 
                    486: struct getrusage_args {
                    487:                int who;
                    488:                struct rusage * rusage;
                    489: };
                    490: /* ARGSUSED */
                    491: int
                    492: getrusage(p, uap, retval)
                    493:        register struct proc *p;
                    494:        register struct getrusage_args *uap;
                    495:        register_t *retval;
                    496: {
                    497:        struct rusage *rup, rubuf;
                    498: 
                    499:        switch (uap->who) {
                    500: 
                    501:        case RUSAGE_SELF:
                    502:                rup = &p->p_stats->p_ru;
                    503:                calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
                    504:                rubuf = *rup;
                    505:                break;
                    506: 
                    507:        case RUSAGE_CHILDREN:
                    508:                rup = &p->p_stats->p_cru;
                    509:                rubuf = *rup;
                    510:                break;
                    511: 
                    512:        default:
                    513:                return (EINVAL);
                    514:        }
                    515:        return (copyout((caddr_t)&rubuf, (caddr_t)uap->rusage,
                    516:            sizeof (struct rusage)));
                    517: }
                    518: 
                    519: void
                    520: ruadd(ru, ru2)
                    521:        register struct rusage *ru, *ru2;
                    522: {
                    523:        register long *ip, *ip2;
                    524:        register int i;
                    525: 
                    526:        timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
                    527:        timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
                    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.
                    539:  */
                    540: struct plimit *
                    541: limcopy(lim)
                    542:        struct plimit *lim;
                    543: {
                    544:        register struct plimit *copy;
                    545: 
                    546:        MALLOC_ZONE(copy, struct plimit *,
                    547:                        sizeof(struct plimit), M_SUBPROC, M_WAITOK);
                    548:        bcopy(lim->pl_rlimit, copy->pl_rlimit,
                    549:            sizeof(struct rlimit) * RLIM_NLIMITS);
                    550:        copy->p_lflags = 0;
                    551:        copy->p_refcnt = 1;
                    552:        return (copy);
                    553: }

unix.superglobalmegacorp.com

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