|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.