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