1 /*-
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94
39 * $FreeBSD: src/sys/kern/kern_resource.c,v 1.20.2.3 1999/09/05 08:15:02 peter Exp $
40 */
41
42 #include "opt_rlimit.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/sysproto.h>
47 #include <sys/kernel.h>
48 #include <sys/file.h>
49 #include <sys/resourcevar.h>
50 #include <sys/malloc.h>
51 #include <sys/proc.h>
52
53 #include <vm/vm.h>
54 #include <vm/vm_param.h>
55 #include <vm/vm_prot.h>
56 #include <vm/lock.h>
57 #include <vm/pmap.h>
58 #include <vm/vm_map.h>
59
60 int donice __P((struct proc *curp, struct proc *chgp, int n));
61 int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp));
62
63 /*
64 * Resource controls and accounting.
65 */
66
67 #ifndef _SYS_SYSPROTO_H_
68 struct getpriority_args {
69 int which;
70 int who;
71 };
72 #endif
73 int
74 getpriority(curp, uap, retval)
75 struct proc *curp;
76 register struct getpriority_args *uap;
77 int *retval;
78 {
79 register struct proc *p;
80 register int low = PRIO_MAX + 1;
81
82 switch (uap->which) {
83
84 case PRIO_PROCESS:
85 if (uap->who == 0)
86 p = curp;
87 else
88 p = pfind(uap->who);
89 if (p == 0)
90 break;
91 low = p->p_nice;
92 break;
93
94 case PRIO_PGRP: {
95 register struct pgrp *pg;
96
97 if (uap->who == 0)
98 pg = curp->p_pgrp;
99 else if ((pg = pgfind(uap->who)) == NULL)
100 break;
101 for (p = pg->pg_members.lh_first; p != 0;
102 p = p->p_pglist.le_next) {
103 if (p->p_nice < low)
104 low = p->p_nice;
105 }
106 break;
107 }
108
109 case PRIO_USER:
110 if (uap->who == 0)
111 uap->who = curp->p_ucred->cr_uid;
112 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
113 if (p->p_ucred->cr_uid == uap->who &&
114 p->p_nice < low)
115 low = p->p_nice;
116 break;
117
118 default:
119 return (EINVAL);
120 }
121 if (low == PRIO_MAX + 1)
122 return (ESRCH);
123 *retval = low;
124 return (0);
125 }
126
127 #ifndef _SYS_SYSPROTO_H_
128 struct setpriority_args {
129 int which;
130 int who;
131 int prio;
132 };
133 #endif
134 /* ARGSUSED */
135 int
136 setpriority(curp, uap, retval)
137 struct proc *curp;
138 register struct setpriority_args *uap;
139 int *retval;
140 {
141 register struct proc *p;
142 int found = 0, error = 0;
143
144 switch (uap->which) {
145
146 case PRIO_PROCESS:
147 if (uap->who == 0)
148 p = curp;
149 else
150 p = pfind(uap->who);
151 if (p == 0)
152 break;
153 error = donice(curp, p, uap->prio);
154 found++;
155 break;
156
157 case PRIO_PGRP: {
158 register struct pgrp *pg;
159
160 if (uap->who == 0)
161 pg = curp->p_pgrp;
162 else if ((pg = pgfind(uap->who)) == NULL)
163 break;
164 for (p = pg->pg_members.lh_first; p != 0;
165 p = p->p_pglist.le_next) {
166 error = donice(curp, p, uap->prio);
167 found++;
168 }
169 break;
170 }
171
172 case PRIO_USER:
173 if (uap->who == 0)
174 uap->who = curp->p_ucred->cr_uid;
175 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
176 if (p->p_ucred->cr_uid == uap->who) {
177 error = donice(curp, p, uap->prio);
178 found++;
179 }
180 break;
181
182 default:
183 return (EINVAL);
184 }
185 if (found == 0)
186 return (ESRCH);
187 return (error);
188 }
189
190 int
191 donice(curp, chgp, n)
192 register struct proc *curp, *chgp;
193 register int n;
194 {
195 register struct pcred *pcred = curp->p_cred;
196
197 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
198 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
199 pcred->p_ruid != chgp->p_ucred->cr_uid)
200 return (EPERM);
201 if (n > PRIO_MAX)
202 n = PRIO_MAX;
203 if (n < PRIO_MIN)
204 n = PRIO_MIN;
205 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
206 return (EACCES);
207 chgp->p_nice = n;
208 (void)resetpriority(chgp);
209 return (0);
210 }
211
212 /* rtprio system call */
213 #ifndef _SYS_SYSPROTO_H_
214 struct rtprio_args {
215 int function;
216 pid_t pid;
217 struct rtprio *rtp;
218 };
219 #endif
220
221 /*
222 * Set realtime priority
223 */
224
225 /* ARGSUSED */
226 int
227 rtprio(curp, uap, retval)
228 struct proc *curp;
229 register struct rtprio_args *uap;
230 int *retval;
231 {
232 register struct proc *p;
233 register struct pcred *pcred = curp->p_cred;
234 struct rtprio rtp;
235 int error;
236
237 error = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
238 if (error)
239 return (error);
240
241 if (uap->pid == 0)
242 p = curp;
243 else
244 p = pfind(uap->pid);
245
246 if (p == 0)
247 return (ESRCH);
248
249 switch (uap->function) {
250 case RTP_LOOKUP:
251 return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio)));
252 case RTP_SET:
253 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
254 pcred->pc_ucred->cr_uid != p->p_ucred->cr_uid &&
255 pcred->p_ruid != p->p_ucred->cr_uid)
256 return (EPERM);
257 /* disallow setting rtprio in most cases if not superuser */
258 if (suser(pcred->pc_ucred, &curp->p_acflag)) {
259 /* can't set someone else's */
260 if (uap->pid)
261 return (EPERM);
262 /* can't set realtime priority */
263 /*
264 * Realtime priority has to be restricted for reasons which should be
265 * obvious. However, for idle priority, there is a potential for
266 * system deadlock if an idleprio process gains a lock on a resource
267 * that other processes need (and the idleprio process can't run
268 * due to a CPU-bound normal process). Fix me! XXX
269 */
270 #if 0
271 if (rtp.type == RTP_PRIO_REALTIME)
272 #endif
273 if (rtp.type != RTP_PRIO_NORMAL)
274 return (EPERM);
275 }
276 switch (rtp.type) {
277 case RTP_PRIO_REALTIME:
278 case RTP_PRIO_NORMAL:
279 case RTP_PRIO_IDLE:
280 if (rtp.prio > RTP_PRIO_MAX)
281 return (EINVAL);
282 p->p_rtprio = rtp;
283 return (0);
284 default:
285 return (EINVAL);
286 }
287
288 default:
289 return (EINVAL);
290 }
291 }
292
293 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
294 #ifndef _SYS_SYSPROTO_H_
295 struct osetrlimit_args {
296 u_int which;
297 struct orlimit *rlp;
298 };
299 #endif
300 /* ARGSUSED */
301 int
302 osetrlimit(p, uap, retval)
303 struct proc *p;
304 register struct osetrlimit_args *uap;
305 int *retval;
306 {
307 struct orlimit olim;
308 struct rlimit lim;
309 int error;
310
311 if ((error =
312 copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit))))
313 return (error);
314 lim.rlim_cur = olim.rlim_cur;
315 lim.rlim_max = olim.rlim_max;
316 return (dosetrlimit(p, uap->which, &lim));
317 }
318
319 #ifndef _SYS_SYSPROTO_H_
320 struct ogetrlimit_args {
321 u_int which;
322 struct orlimit *rlp;
323 };
324 #endif
325 /* ARGSUSED */
326 int
327 ogetrlimit(p, uap, retval)
328 struct proc *p;
329 register struct ogetrlimit_args *uap;
330 int *retval;
331 {
332 struct orlimit olim;
333
334 if (uap->which >= RLIM_NLIMITS)
335 return (EINVAL);
336 olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur;
337 if (olim.rlim_cur == -1)
338 olim.rlim_cur = 0x7fffffff;
339 olim.rlim_max = p->p_rlimit[uap->which].rlim_max;
340 if (olim.rlim_max == -1)
341 olim.rlim_max = 0x7fffffff;
342 return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim)));
343 }
344 #endif /* COMPAT_43 || COMPAT_SUNOS */
345
346 #ifndef _SYS_SYSPROTO_H_
347 struct __setrlimit_args {
348 u_int which;
349 struct rlimit *rlp;
350 };
351 #endif
352 /* ARGSUSED */
353 int
354 setrlimit(p, uap, retval)
355 struct proc *p;
356 register struct __setrlimit_args *uap;
357 int *retval;
358 {
359 struct rlimit alim;
360 int error;
361
362 if ((error =
363 copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit))))
364 return (error);
365 return (dosetrlimit(p, uap->which, &alim));
366 }
367
368 int
369 dosetrlimit(p, which, limp)
370 struct proc *p;
371 u_int which;
372 struct rlimit *limp;
373 {
374 register struct rlimit *alimp;
375 int error;
376
377 if (which >= RLIM_NLIMITS)
378 return (EINVAL);
379 alimp = &p->p_rlimit[which];
380
381 /*
382 * Preserve historical bugs by treating negative limits as unsigned.
383 */
384 if (limp->rlim_cur < 0)
385 limp->rlim_cur = RLIM_INFINITY;
386 if (limp->rlim_max < 0)
387 limp->rlim_max = RLIM_INFINITY;
388
389 if (limp->rlim_cur > alimp->rlim_max ||
390 limp->rlim_max > alimp->rlim_max)
391 if ((error = suser(p->p_ucred, &p->p_acflag)))
392 return (error);
393 if (limp->rlim_cur > limp->rlim_max)
394 limp->rlim_cur = limp->rlim_max;
395 if (p->p_limit->p_refcnt > 1 &&
396 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
397 p->p_limit->p_refcnt--;
398 p->p_limit = limcopy(p->p_limit);
399 alimp = &p->p_rlimit[which];
400 }
401
402 switch (which) {
403
404 case RLIMIT_DATA:
405 if (limp->rlim_cur > MAXDSIZ)
406 limp->rlim_cur = MAXDSIZ;
407 if (limp->rlim_max > MAXDSIZ)
408 limp->rlim_max = MAXDSIZ;
409 break;
410
411 case RLIMIT_STACK:
412 if (limp->rlim_cur > MAXSSIZ)
413 limp->rlim_cur = MAXSSIZ;
414 if (limp->rlim_max > MAXSSIZ)
415 limp->rlim_max = MAXSSIZ;
416 /*
417 * Stack is allocated to the max at exec time with only
418 * "rlim_cur" bytes accessible. If stack limit is going
419 * up make more accessible, if going down make inaccessible.
420 */
421 if (limp->rlim_cur != alimp->rlim_cur) {
422 vm_offset_t addr;
423 vm_size_t size;
424 vm_prot_t prot;
425
426 if (limp->rlim_cur > alimp->rlim_cur) {
427 prot = VM_PROT_ALL;
428 size = limp->rlim_cur - alimp->rlim_cur;
429 addr = USRSTACK - limp->rlim_cur;
430 } else {
431 prot = VM_PROT_NONE;
432 size = alimp->rlim_cur - limp->rlim_cur;
433 addr = USRSTACK - alimp->rlim_cur;
434 }
435 addr = trunc_page(addr);
436 size = round_page(size);
437 (void) vm_map_protect(&p->p_vmspace->vm_map,
438 addr, addr+size, prot, FALSE);
439 }
440 break;
441
442 case RLIMIT_NOFILE:
443 if (limp->rlim_cur > maxfilesperproc)
444 limp->rlim_cur = maxfilesperproc;
445 if (limp->rlim_max > maxfilesperproc)
446 limp->rlim_max = maxfilesperproc;
447 break;
448
449 case RLIMIT_NPROC:
450 if (limp->rlim_cur > maxprocperuid)
451 limp->rlim_cur = maxprocperuid;
452 if (limp->rlim_max > maxprocperuid)
453 limp->rlim_max = maxprocperuid;
454 break;
455 }
456 *alimp = *limp;
457 return (0);
458 }
459
460 #ifndef _SYS_SYSPROTO_H_
461 struct __getrlimit_args {
462 u_int which;
463 struct rlimit *rlp;
464 };
465 #endif
466 /* ARGSUSED */
467 int
468 getrlimit(p, uap, retval)
469 struct proc *p;
470 register struct __getrlimit_args *uap;
471 int *retval;
472 {
473
474 if (uap->which >= RLIM_NLIMITS)
475 return (EINVAL);
476 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
477 sizeof (struct rlimit)));
478 }
479
480 /*
481 * Transform the running time and tick information in proc p into user,
482 * system, and interrupt time usage.
483 */
484 void
485 calcru(p, up, sp, ip)
486 struct proc *p;
487 struct timeval *up;
488 struct timeval *sp;
489 struct timeval *ip;
490 {
491 quad_t totusec;
492 u_quad_t u, st, ut, it, tot;
493 long sec, usec;
494 int s;
495 struct timeval tv;
496
497 s = splstatclock();
498 st = p->p_sticks;
499 ut = p->p_uticks;
500 it = p->p_iticks;
501 splx(s);
502
503 tot = st + ut + it;
504 if (tot == 0) {
505 st = 1;
506 tot = 1;
507 }
508
509 sec = p->p_rtime.tv_sec;
510 usec = p->p_rtime.tv_usec;
511 if (p == curproc) {
512 /*
513 * Adjust for the current time slice. This is actually fairly
514 * important since the error here is on the order of a time
515 * quantum, which is much greater than the sampling error.
516 */
517 microtime(&tv);
518 sec += tv.tv_sec - runtime.tv_sec;
519 usec += tv.tv_usec - runtime.tv_usec;
520 }
521 totusec = (quad_t)sec * 1000000 + usec;
522 if (totusec < 0) {
523 /* XXX no %qd in kernel. Truncate. */
524 printf("calcru: negative time: %ld usec\n", (long)totusec);
525 totusec = 0;
526 }
527 u = totusec;
528 st = (u * st) / tot;
529 sp->tv_sec = st / 1000000;
530 sp->tv_usec = st % 1000000;
531 ut = (u * ut) / tot;
532 up->tv_sec = ut / 1000000;
533 up->tv_usec = ut % 1000000;
534 if (ip != NULL) {
535 it = (u * it) / tot;
536 ip->tv_sec = it / 1000000;
537 ip->tv_usec = it % 1000000;
538 }
539 }
540
541 #ifndef _SYS_SYSPROTO_H_
542 struct getrusage_args {
543 int who;
544 struct rusage *rusage;
545 };
546 #endif
547 /* ARGSUSED */
548 int
549 getrusage(p, uap, retval)
550 register struct proc *p;
551 register struct getrusage_args *uap;
552 int *retval;
553 {
554 register struct rusage *rup;
555
556 switch (uap->who) {
557
558 case RUSAGE_SELF:
559 rup = &p->p_stats->p_ru;
560 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
561 break;
562
563 case RUSAGE_CHILDREN:
564 rup = &p->p_stats->p_cru;
565 break;
566
567 default:
568 return (EINVAL);
569 }
570 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
571 sizeof (struct rusage)));
572 }
573
574 void
575 ruadd(ru, ru2)
576 register struct rusage *ru, *ru2;
577 {
578 register long *ip, *ip2;
579 register int i;
580
581 timevaladd(&ru->ru_utime, &ru2->ru_utime);
582 timevaladd(&ru->ru_stime, &ru2->ru_stime);
583 if (ru->ru_maxrss < ru2->ru_maxrss)
584 ru->ru_maxrss = ru2->ru_maxrss;
585 ip = &ru->ru_first; ip2 = &ru2->ru_first;
586 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
587 *ip++ += *ip2++;
588 }
589
590 /*
591 * Make a copy of the plimit structure.
592 * We share these structures copy-on-write after fork,
593 * and copy when a limit is changed.
594 */
595 struct plimit *
596 limcopy(lim)
597 struct plimit *lim;
598 {
599 register struct plimit *copy;
600
601 MALLOC(copy, struct plimit *, sizeof(struct plimit),
602 M_SUBPROC, M_WAITOK);
603 bcopy(lim->pl_rlimit, copy->pl_rlimit,
604 sizeof(struct rlimit) * RLIM_NLIMITS);
605 copy->p_lflags = 0;
606 copy->p_refcnt = 1;
607 return (copy);
608 }
Cache object: e53d9316797db622201eb5b7ed8a10fe
|