|
|
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.