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 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94
35 */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: src/sys/kern/kern_resource.c,v 1.143.2.3 2005/04/21 22:19:22 ps Exp $");
39
40 #include "opt_compat.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/sysproto.h>
45 #include <sys/file.h>
46 #include <sys/kernel.h>
47 #include <sys/lock.h>
48 #include <sys/malloc.h>
49 #include <sys/mutex.h>
50 #include <sys/proc.h>
51 #include <sys/resourcevar.h>
52 #include <sys/sched.h>
53 #include <sys/sx.h>
54 #include <sys/syscallsubr.h>
55 #include <sys/sysent.h>
56 #include <sys/time.h>
57
58 #include <vm/vm.h>
59 #include <vm/vm_param.h>
60 #include <vm/pmap.h>
61 #include <vm/vm_map.h>
62
63 static int donice(struct thread *td, struct proc *chgp, int n);
64
65 static MALLOC_DEFINE(M_PLIMIT, "plimit", "plimit structures");
66 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures");
67 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
68 static struct mtx uihashtbl_mtx;
69 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
70 static u_long uihash; /* size of hash table - 1 */
71
72 static struct uidinfo *uilookup(uid_t uid);
73
74 /*
75 * Resource controls and accounting.
76 */
77
78 #ifndef _SYS_SYSPROTO_H_
79 struct getpriority_args {
80 int which;
81 int who;
82 };
83 #endif
84 /*
85 * MPSAFE
86 */
87 int
88 getpriority(td, uap)
89 struct thread *td;
90 register struct getpriority_args *uap;
91 {
92 struct proc *p;
93 int error, low;
94
95 error = 0;
96 low = PRIO_MAX + 1;
97 switch (uap->which) {
98
99 case PRIO_PROCESS:
100 if (uap->who == 0)
101 low = td->td_proc->p_nice;
102 else {
103 p = pfind(uap->who);
104 if (p == NULL)
105 break;
106 if (p_cansee(td, p) == 0) {
107 low = p->p_nice;
108 }
109 PROC_UNLOCK(p);
110 }
111 break;
112
113 case PRIO_PGRP: {
114 register struct pgrp *pg;
115
116 sx_slock(&proctree_lock);
117 if (uap->who == 0) {
118 pg = td->td_proc->p_pgrp;
119 PGRP_LOCK(pg);
120 } else {
121 pg = pgfind(uap->who);
122 if (pg == NULL) {
123 sx_sunlock(&proctree_lock);
124 break;
125 }
126 }
127 sx_sunlock(&proctree_lock);
128 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
129 PROC_LOCK(p);
130 if (!p_cansee(td, p)) {
131 if (p->p_nice < low)
132 low = p->p_nice;
133 }
134 PROC_UNLOCK(p);
135 }
136 PGRP_UNLOCK(pg);
137 break;
138 }
139
140 case PRIO_USER:
141 if (uap->who == 0)
142 uap->who = td->td_ucred->cr_uid;
143 sx_slock(&allproc_lock);
144 LIST_FOREACH(p, &allproc, p_list) {
145 PROC_LOCK(p);
146 if (!p_cansee(td, p) &&
147 p->p_ucred->cr_uid == uap->who) {
148 if (p->p_nice < low)
149 low = p->p_nice;
150 }
151 PROC_UNLOCK(p);
152 }
153 sx_sunlock(&allproc_lock);
154 break;
155
156 default:
157 error = EINVAL;
158 break;
159 }
160 if (low == PRIO_MAX + 1 && error == 0)
161 error = ESRCH;
162 td->td_retval[0] = low;
163 return (error);
164 }
165
166 #ifndef _SYS_SYSPROTO_H_
167 struct setpriority_args {
168 int which;
169 int who;
170 int prio;
171 };
172 #endif
173 /*
174 * MPSAFE
175 */
176 int
177 setpriority(td, uap)
178 struct thread *td;
179 register struct setpriority_args *uap;
180 {
181 struct proc *curp;
182 register struct proc *p;
183 int found = 0, error = 0;
184
185 curp = td->td_proc;
186 switch (uap->which) {
187 case PRIO_PROCESS:
188 if (uap->who == 0) {
189 PROC_LOCK(curp);
190 error = donice(td, curp, uap->prio);
191 PROC_UNLOCK(curp);
192 } else {
193 p = pfind(uap->who);
194 if (p == 0)
195 break;
196 if (p_cansee(td, p) == 0)
197 error = donice(td, p, uap->prio);
198 PROC_UNLOCK(p);
199 }
200 found++;
201 break;
202
203 case PRIO_PGRP: {
204 register struct pgrp *pg;
205
206 sx_slock(&proctree_lock);
207 if (uap->who == 0) {
208 pg = curp->p_pgrp;
209 PGRP_LOCK(pg);
210 } else {
211 pg = pgfind(uap->who);
212 if (pg == NULL) {
213 sx_sunlock(&proctree_lock);
214 break;
215 }
216 }
217 sx_sunlock(&proctree_lock);
218 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
219 PROC_LOCK(p);
220 if (!p_cansee(td, p)) {
221 error = donice(td, p, uap->prio);
222 found++;
223 }
224 PROC_UNLOCK(p);
225 }
226 PGRP_UNLOCK(pg);
227 break;
228 }
229
230 case PRIO_USER:
231 if (uap->who == 0)
232 uap->who = td->td_ucred->cr_uid;
233 sx_slock(&allproc_lock);
234 FOREACH_PROC_IN_SYSTEM(p) {
235 PROC_LOCK(p);
236 if (p->p_ucred->cr_uid == uap->who &&
237 !p_cansee(td, p)) {
238 error = donice(td, p, uap->prio);
239 found++;
240 }
241 PROC_UNLOCK(p);
242 }
243 sx_sunlock(&allproc_lock);
244 break;
245
246 default:
247 error = EINVAL;
248 break;
249 }
250 if (found == 0 && error == 0)
251 error = ESRCH;
252 return (error);
253 }
254
255 /*
256 * Set "nice" for a (whole) process.
257 */
258 static int
259 donice(struct thread *td, struct proc *p, int n)
260 {
261 int error;
262
263 PROC_LOCK_ASSERT(p, MA_OWNED);
264 if ((error = p_cansched(td, p)))
265 return (error);
266 if (n > PRIO_MAX)
267 n = PRIO_MAX;
268 if (n < PRIO_MIN)
269 n = PRIO_MIN;
270 if (n < p->p_nice && suser(td) != 0)
271 return (EACCES);
272 mtx_lock_spin(&sched_lock);
273 sched_nice(p, n);
274 mtx_unlock_spin(&sched_lock);
275 return (0);
276 }
277
278 /*
279 * Set realtime priority
280 *
281 * MPSAFE
282 */
283 #ifndef _SYS_SYSPROTO_H_
284 struct rtprio_args {
285 int function;
286 pid_t pid;
287 struct rtprio *rtp;
288 };
289 #endif
290
291 int
292 rtprio(td, uap)
293 struct thread *td; /* curthread */
294 register struct rtprio_args *uap;
295 {
296 struct proc *curp;
297 struct proc *p;
298 struct ksegrp *kg;
299 struct rtprio rtp;
300 int cierror, error;
301
302 /* Perform copyin before acquiring locks if needed. */
303 if (uap->function == RTP_SET)
304 cierror = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
305 else
306 cierror = 0;
307
308 curp = td->td_proc;
309 if (uap->pid == 0) {
310 p = curp;
311 PROC_LOCK(p);
312 } else {
313 p = pfind(uap->pid);
314 if (p == NULL)
315 return (ESRCH);
316 }
317
318 switch (uap->function) {
319 case RTP_LOOKUP:
320 if ((error = p_cansee(td, p)))
321 break;
322 mtx_lock_spin(&sched_lock);
323 /*
324 * Return OUR priority if no pid specified,
325 * or if one is, report the highest priority
326 * in the process. There isn't much more you can do as
327 * there is only room to return a single priority.
328 * XXXKSE Maybe need a new interface to report
329 * priorities of multiple system scope threads.
330 * Note: specifying our own pid is not the same
331 * as leaving it zero.
332 */
333 if (uap->pid == 0) {
334 pri_to_rtp(td->td_ksegrp, &rtp);
335 } else {
336 struct rtprio rtp2;
337
338 rtp.type = RTP_PRIO_IDLE;
339 rtp.prio = RTP_PRIO_MAX;
340 FOREACH_KSEGRP_IN_PROC(p, kg) {
341 pri_to_rtp(kg, &rtp2);
342 if ((rtp2.type < rtp.type) ||
343 ((rtp2.type == rtp.type) &&
344 (rtp2.prio < rtp.prio))) {
345 rtp.type = rtp2.type;
346 rtp.prio = rtp2.prio;
347 }
348 }
349 }
350 mtx_unlock_spin(&sched_lock);
351 PROC_UNLOCK(p);
352 return (copyout(&rtp, uap->rtp, sizeof(struct rtprio)));
353 case RTP_SET:
354 if ((error = p_cansched(td, p)) || (error = cierror))
355 break;
356 /* disallow setting rtprio in most cases if not superuser */
357 if (suser(td) != 0) {
358 /* can't set someone else's */
359 if (uap->pid) {
360 error = EPERM;
361 break;
362 }
363 /* can't set realtime priority */
364 /*
365 * Realtime priority has to be restricted for reasons which should be
366 * obvious. However, for idle priority, there is a potential for
367 * system deadlock if an idleprio process gains a lock on a resource
368 * that other processes need (and the idleprio process can't run
369 * due to a CPU-bound normal process). Fix me! XXX
370 */
371 #if 0
372 if (RTP_PRIO_IS_REALTIME(rtp.type))
373 #endif
374 if (rtp.type != RTP_PRIO_NORMAL) {
375 error = EPERM;
376 break;
377 }
378 }
379 mtx_lock_spin(&sched_lock);
380 /*
381 * If we are setting our own priority, set just our
382 * KSEGRP but if we are doing another process,
383 * do all the groups on that process. If we
384 * specify our own pid we do the latter.
385 */
386 if (uap->pid == 0) {
387 error = rtp_to_pri(&rtp, td->td_ksegrp);
388 } else {
389 FOREACH_KSEGRP_IN_PROC(p, kg) {
390 if ((error = rtp_to_pri(&rtp, kg)) != 0) {
391 break;
392 }
393 }
394 }
395 mtx_unlock_spin(&sched_lock);
396 break;
397 default:
398 error = EINVAL;
399 break;
400 }
401 PROC_UNLOCK(p);
402 return (error);
403 }
404
405 int
406 rtp_to_pri(struct rtprio *rtp, struct ksegrp *kg)
407 {
408
409 mtx_assert(&sched_lock, MA_OWNED);
410 if (rtp->prio > RTP_PRIO_MAX)
411 return (EINVAL);
412 switch (RTP_PRIO_BASE(rtp->type)) {
413 case RTP_PRIO_REALTIME:
414 kg->kg_user_pri = PRI_MIN_REALTIME + rtp->prio;
415 break;
416 case RTP_PRIO_NORMAL:
417 kg->kg_user_pri = PRI_MIN_TIMESHARE + rtp->prio;
418 break;
419 case RTP_PRIO_IDLE:
420 kg->kg_user_pri = PRI_MIN_IDLE + rtp->prio;
421 break;
422 default:
423 return (EINVAL);
424 }
425 sched_class(kg, rtp->type);
426 if (curthread->td_ksegrp == kg) {
427 curthread->td_base_pri = kg->kg_user_pri;
428 sched_prio(curthread, kg->kg_user_pri); /* XXX dubious */
429 }
430 return (0);
431 }
432
433 void
434 pri_to_rtp(struct ksegrp *kg, struct rtprio *rtp)
435 {
436
437 mtx_assert(&sched_lock, MA_OWNED);
438 switch (PRI_BASE(kg->kg_pri_class)) {
439 case PRI_REALTIME:
440 rtp->prio = kg->kg_user_pri - PRI_MIN_REALTIME;
441 break;
442 case PRI_TIMESHARE:
443 rtp->prio = kg->kg_user_pri - PRI_MIN_TIMESHARE;
444 break;
445 case PRI_IDLE:
446 rtp->prio = kg->kg_user_pri - PRI_MIN_IDLE;
447 break;
448 default:
449 break;
450 }
451 rtp->type = kg->kg_pri_class;
452 }
453
454 #if defined(COMPAT_43)
455 #ifndef _SYS_SYSPROTO_H_
456 struct osetrlimit_args {
457 u_int which;
458 struct orlimit *rlp;
459 };
460 #endif
461 /*
462 * MPSAFE
463 */
464 int
465 osetrlimit(td, uap)
466 struct thread *td;
467 register struct osetrlimit_args *uap;
468 {
469 struct orlimit olim;
470 struct rlimit lim;
471 int error;
472
473 if ((error = copyin(uap->rlp, &olim, sizeof(struct orlimit))))
474 return (error);
475 lim.rlim_cur = olim.rlim_cur;
476 lim.rlim_max = olim.rlim_max;
477 error = kern_setrlimit(td, uap->which, &lim);
478 return (error);
479 }
480
481 #ifndef _SYS_SYSPROTO_H_
482 struct ogetrlimit_args {
483 u_int which;
484 struct orlimit *rlp;
485 };
486 #endif
487 /*
488 * MPSAFE
489 */
490 int
491 ogetrlimit(td, uap)
492 struct thread *td;
493 register struct ogetrlimit_args *uap;
494 {
495 struct orlimit olim;
496 struct rlimit rl;
497 struct proc *p;
498 int error;
499
500 if (uap->which >= RLIM_NLIMITS)
501 return (EINVAL);
502 p = td->td_proc;
503 PROC_LOCK(p);
504 lim_rlimit(p, uap->which, &rl);
505 PROC_UNLOCK(p);
506
507 /*
508 * XXX would be more correct to convert only RLIM_INFINITY to the
509 * old RLIM_INFINITY and fail with EOVERFLOW for other larger
510 * values. Most 64->32 and 32->16 conversions, including not
511 * unimportant ones of uids are even more broken than what we
512 * do here (they blindly truncate). We don't do this correctly
513 * here since we have little experience with EOVERFLOW yet.
514 * Elsewhere, getuid() can't fail...
515 */
516 olim.rlim_cur = rl.rlim_cur > 0x7fffffff ? 0x7fffffff : rl.rlim_cur;
517 olim.rlim_max = rl.rlim_max > 0x7fffffff ? 0x7fffffff : rl.rlim_max;
518 error = copyout(&olim, uap->rlp, sizeof(olim));
519 return (error);
520 }
521 #endif /* COMPAT_43 */
522
523 #ifndef _SYS_SYSPROTO_H_
524 struct __setrlimit_args {
525 u_int which;
526 struct rlimit *rlp;
527 };
528 #endif
529 /*
530 * MPSAFE
531 */
532 int
533 setrlimit(td, uap)
534 struct thread *td;
535 register struct __setrlimit_args *uap;
536 {
537 struct rlimit alim;
538 int error;
539
540 if ((error = copyin(uap->rlp, &alim, sizeof(struct rlimit))))
541 return (error);
542 error = kern_setrlimit(td, uap->which, &alim);
543 return (error);
544 }
545
546 int
547 kern_setrlimit(td, which, limp)
548 struct thread *td;
549 u_int which;
550 struct rlimit *limp;
551 {
552 struct plimit *newlim, *oldlim;
553 struct proc *p;
554 register struct rlimit *alimp;
555 rlim_t oldssiz;
556 int error;
557
558 if (which >= RLIM_NLIMITS)
559 return (EINVAL);
560
561 /*
562 * Preserve historical bugs by treating negative limits as unsigned.
563 */
564 if (limp->rlim_cur < 0)
565 limp->rlim_cur = RLIM_INFINITY;
566 if (limp->rlim_max < 0)
567 limp->rlim_max = RLIM_INFINITY;
568
569 oldssiz = 0;
570 p = td->td_proc;
571 newlim = lim_alloc();
572 PROC_LOCK(p);
573 oldlim = p->p_limit;
574 alimp = &oldlim->pl_rlimit[which];
575 if (limp->rlim_cur > alimp->rlim_max ||
576 limp->rlim_max > alimp->rlim_max)
577 if ((error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL))) {
578 PROC_UNLOCK(p);
579 lim_free(newlim);
580 return (error);
581 }
582 if (limp->rlim_cur > limp->rlim_max)
583 limp->rlim_cur = limp->rlim_max;
584 lim_copy(newlim, oldlim);
585 alimp = &newlim->pl_rlimit[which];
586
587 switch (which) {
588
589 case RLIMIT_CPU:
590 mtx_lock_spin(&sched_lock);
591 p->p_cpulimit = limp->rlim_cur;
592 mtx_unlock_spin(&sched_lock);
593 break;
594 case RLIMIT_DATA:
595 if (limp->rlim_cur > maxdsiz)
596 limp->rlim_cur = maxdsiz;
597 if (limp->rlim_max > maxdsiz)
598 limp->rlim_max = maxdsiz;
599 break;
600
601 case RLIMIT_STACK:
602 if (limp->rlim_cur > maxssiz)
603 limp->rlim_cur = maxssiz;
604 if (limp->rlim_max > maxssiz)
605 limp->rlim_max = maxssiz;
606 oldssiz = alimp->rlim_cur;
607 break;
608
609 case RLIMIT_NOFILE:
610 if (limp->rlim_cur > maxfilesperproc)
611 limp->rlim_cur = maxfilesperproc;
612 if (limp->rlim_max > maxfilesperproc)
613 limp->rlim_max = maxfilesperproc;
614 break;
615
616 case RLIMIT_NPROC:
617 if (limp->rlim_cur > maxprocperuid)
618 limp->rlim_cur = maxprocperuid;
619 if (limp->rlim_max > maxprocperuid)
620 limp->rlim_max = maxprocperuid;
621 if (limp->rlim_cur < 1)
622 limp->rlim_cur = 1;
623 if (limp->rlim_max < 1)
624 limp->rlim_max = 1;
625 break;
626 }
627 *alimp = *limp;
628 p->p_limit = newlim;
629 PROC_UNLOCK(p);
630 lim_free(oldlim);
631
632 if (which == RLIMIT_STACK) {
633 /*
634 * Stack is allocated to the max at exec time with only
635 * "rlim_cur" bytes accessible. If stack limit is going
636 * up make more accessible, if going down make inaccessible.
637 */
638 if (limp->rlim_cur != oldssiz) {
639 vm_offset_t addr;
640 vm_size_t size;
641 vm_prot_t prot;
642
643 mtx_lock(&Giant);
644 if (limp->rlim_cur > oldssiz) {
645 prot = p->p_sysent->sv_stackprot;
646 size = limp->rlim_cur - oldssiz;
647 addr = p->p_sysent->sv_usrstack -
648 limp->rlim_cur;
649 } else {
650 prot = VM_PROT_NONE;
651 size = oldssiz - limp->rlim_cur;
652 addr = p->p_sysent->sv_usrstack -
653 oldssiz;
654 }
655 addr = trunc_page(addr);
656 size = round_page(size);
657 (void) vm_map_protect(&p->p_vmspace->vm_map,
658 addr, addr+size, prot, FALSE);
659 mtx_unlock(&Giant);
660 }
661 }
662 return (0);
663 }
664
665 #ifndef _SYS_SYSPROTO_H_
666 struct __getrlimit_args {
667 u_int which;
668 struct rlimit *rlp;
669 };
670 #endif
671 /*
672 * MPSAFE
673 */
674 /* ARGSUSED */
675 int
676 getrlimit(td, uap)
677 struct thread *td;
678 register struct __getrlimit_args *uap;
679 {
680 struct rlimit rlim;
681 struct proc *p;
682 int error;
683
684 if (uap->which >= RLIM_NLIMITS)
685 return (EINVAL);
686 p = td->td_proc;
687 PROC_LOCK(p);
688 lim_rlimit(p, uap->which, &rlim);
689 PROC_UNLOCK(p);
690 error = copyout(&rlim, uap->rlp, sizeof(struct rlimit));
691 return(error);
692 }
693
694 /*
695 * Transform the running time and tick information in proc p into user,
696 * system, and interrupt time usage.
697 */
698 void
699 calcru(p, up, sp, ip)
700 struct proc *p;
701 struct timeval *up;
702 struct timeval *sp;
703 struct timeval *ip;
704 {
705 struct bintime bt, rt;
706 struct timeval tv;
707 struct thread *td;
708 /* {user, system, interrupt, total} {ticks, usec}; previous tu: */
709 u_int64_t ut, uu, st, su, it, iu, tt, tu, ptu;
710 int problemcase;
711
712 mtx_assert(&sched_lock, MA_OWNED);
713 /* XXX: why spl-protect ? worst case is an off-by-one report */
714
715 ut = p->p_uticks;
716 st = p->p_sticks;
717 it = p->p_iticks;
718
719 tt = ut + st + it;
720 if (tt == 0) {
721 st = 1;
722 tt = 1;
723 }
724 rt = p->p_runtime;
725 problemcase = 0;
726 FOREACH_THREAD_IN_PROC(p, td) {
727 /*
728 * Adjust for the current time slice. This is actually fairly
729 * important since the error here is on the order of a time
730 * quantum, which is much greater than the sampling error.
731 */
732 if (td == curthread) {
733 binuptime(&bt);
734 bintime_sub(&bt, PCPU_PTR(switchtime));
735 bintime_add(&rt, &bt);
736 } else if (TD_IS_RUNNING(td)) {
737 /*
738 * XXX: this case should add the difference between
739 * the current time and the switch time as above,
740 * but the switch time is inaccessible, so we can't
741 * do the adjustment and will end up with a wrong
742 * runtime. A previous call with a different
743 * curthread may have obtained a (right or wrong)
744 * runtime that is in advance of ours. Just set a
745 * flag to avoid warning about this known problem.
746 */
747 problemcase = 1;
748 }
749 }
750 bintime2timeval(&rt, &tv);
751 tu = (u_int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
752 ptu = p->p_uu + p->p_su + p->p_iu;
753 if (tu < ptu) {
754 if (!problemcase)
755 printf(
756 "calcru: runtime went backwards from %ju usec to %ju usec for pid %d (%s)\n",
757 (uintmax_t)ptu, (uintmax_t)tu, p->p_pid, p->p_comm);
758 tu = ptu;
759 }
760 if ((int64_t)tu < 0) {
761 printf("calcru: negative runtime of %jd usec for pid %d (%s)\n",
762 (intmax_t)tu, p->p_pid, p->p_comm);
763 tu = ptu;
764 }
765
766 /* Subdivide tu. */
767 uu = (tu * ut) / tt;
768 su = (tu * st) / tt;
769 iu = tu - uu - su;
770
771 /* Enforce monotonicity. */
772 if (uu < p->p_uu || su < p->p_su || iu < p->p_iu) {
773 if (uu < p->p_uu)
774 uu = p->p_uu;
775 else if (uu + p->p_su + p->p_iu > tu)
776 uu = tu - p->p_su - p->p_iu;
777 if (st == 0)
778 su = p->p_su;
779 else {
780 su = ((tu - uu) * st) / (st + it);
781 if (su < p->p_su)
782 su = p->p_su;
783 else if (uu + su + p->p_iu > tu)
784 su = tu - uu - p->p_iu;
785 }
786 KASSERT(uu + su + p->p_iu <= tu,
787 ("calcru: monotonisation botch 1"));
788 iu = tu - uu - su;
789 KASSERT(iu >= p->p_iu,
790 ("calcru: monotonisation botch 2"));
791 }
792 p->p_uu = uu;
793 p->p_su = su;
794 p->p_iu = iu;
795
796 up->tv_sec = uu / 1000000;
797 up->tv_usec = uu % 1000000;
798 sp->tv_sec = su / 1000000;
799 sp->tv_usec = su % 1000000;
800 if (ip != NULL) {
801 ip->tv_sec = iu / 1000000;
802 ip->tv_usec = iu % 1000000;
803 }
804 }
805
806 #ifndef _SYS_SYSPROTO_H_
807 struct getrusage_args {
808 int who;
809 struct rusage *rusage;
810 };
811 #endif
812 /*
813 * MPSAFE
814 */
815 /* ARGSUSED */
816 int
817 getrusage(td, uap)
818 register struct thread *td;
819 register struct getrusage_args *uap;
820 {
821 struct rusage ru;
822 struct proc *p;
823
824 p = td->td_proc;
825 switch (uap->who) {
826
827 case RUSAGE_SELF:
828 mtx_lock(&Giant);
829 mtx_lock_spin(&sched_lock);
830 calcru(p, &p->p_stats->p_ru.ru_utime, &p->p_stats->p_ru.ru_stime,
831 NULL);
832 mtx_unlock_spin(&sched_lock);
833 ru = p->p_stats->p_ru;
834 mtx_unlock(&Giant);
835 break;
836
837 case RUSAGE_CHILDREN:
838 mtx_lock(&Giant);
839 ru = p->p_stats->p_cru;
840 mtx_unlock(&Giant);
841 break;
842
843 default:
844 return (EINVAL);
845 break;
846 }
847 return (copyout(&ru, uap->rusage, sizeof(struct rusage)));
848 }
849
850 void
851 ruadd(ru, ru2)
852 register struct rusage *ru, *ru2;
853 {
854 register long *ip, *ip2;
855 register int i;
856
857 timevaladd(&ru->ru_utime, &ru2->ru_utime);
858 timevaladd(&ru->ru_stime, &ru2->ru_stime);
859 if (ru->ru_maxrss < ru2->ru_maxrss)
860 ru->ru_maxrss = ru2->ru_maxrss;
861 ip = &ru->ru_first; ip2 = &ru2->ru_first;
862 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
863 *ip++ += *ip2++;
864 }
865
866 /*
867 * Allocate a new resource limits structure and initialize its
868 * reference count and mutex pointer.
869 */
870 struct plimit *
871 lim_alloc()
872 {
873 struct plimit *limp;
874
875 limp = (struct plimit *)malloc(sizeof(struct plimit), M_PLIMIT,
876 M_WAITOK);
877 limp->pl_refcnt = 1;
878 limp->pl_mtx = mtx_pool_alloc(mtxpool_sleep);
879 return (limp);
880 }
881
882 struct plimit *
883 lim_hold(limp)
884 struct plimit *limp;
885 {
886
887 LIM_LOCK(limp);
888 limp->pl_refcnt++;
889 LIM_UNLOCK(limp);
890 return (limp);
891 }
892
893 void
894 lim_free(limp)
895 struct plimit *limp;
896 {
897
898 LIM_LOCK(limp);
899 KASSERT(limp->pl_refcnt > 0, ("plimit refcnt underflow"));
900 if (--limp->pl_refcnt == 0) {
901 LIM_UNLOCK(limp);
902 free((void *)limp, M_PLIMIT);
903 return;
904 }
905 LIM_UNLOCK(limp);
906 }
907
908 /*
909 * Make a copy of the plimit structure.
910 * We share these structures copy-on-write after fork.
911 */
912 void
913 lim_copy(dst, src)
914 struct plimit *dst, *src;
915 {
916
917 KASSERT(dst->pl_refcnt == 1, ("lim_copy to shared limit"));
918 bcopy(src->pl_rlimit, dst->pl_rlimit, sizeof(src->pl_rlimit));
919 }
920
921 /*
922 * Return the hard limit for a particular system resource. The
923 * which parameter specifies the index into the rlimit array.
924 */
925 rlim_t
926 lim_max(struct proc *p, int which)
927 {
928 struct rlimit rl;
929
930 lim_rlimit(p, which, &rl);
931 return (rl.rlim_max);
932 }
933
934 /*
935 * Return the current (soft) limit for a particular system resource.
936 * The which parameter which specifies the index into the rlimit array
937 */
938 rlim_t
939 lim_cur(struct proc *p, int which)
940 {
941 struct rlimit rl;
942
943 lim_rlimit(p, which, &rl);
944 return (rl.rlim_cur);
945 }
946
947 /*
948 * Return a copy of the entire rlimit structure for the system limit
949 * specified by 'which' in the rlimit structure pointed to by 'rlp'.
950 */
951 void
952 lim_rlimit(struct proc *p, int which, struct rlimit *rlp)
953 {
954
955 PROC_LOCK_ASSERT(p, MA_OWNED);
956 KASSERT(which >= 0 && which < RLIM_NLIMITS,
957 ("request for invalid resource limit"));
958 *rlp = p->p_limit->pl_rlimit[which];
959 }
960
961 /*
962 * Find the uidinfo structure for a uid. This structure is used to
963 * track the total resource consumption (process count, socket buffer
964 * size, etc.) for the uid and impose limits.
965 */
966 void
967 uihashinit()
968 {
969
970 uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash);
971 mtx_init(&uihashtbl_mtx, "uidinfo hash", NULL, MTX_DEF);
972 }
973
974 /*
975 * Look up a uidinfo struct for the parameter uid.
976 * uihashtbl_mtx must be locked.
977 */
978 static struct uidinfo *
979 uilookup(uid)
980 uid_t uid;
981 {
982 struct uihashhead *uipp;
983 struct uidinfo *uip;
984
985 mtx_assert(&uihashtbl_mtx, MA_OWNED);
986 uipp = UIHASH(uid);
987 LIST_FOREACH(uip, uipp, ui_hash)
988 if (uip->ui_uid == uid)
989 break;
990
991 return (uip);
992 }
993
994 /*
995 * Find or allocate a struct uidinfo for a particular uid.
996 * Increase refcount on uidinfo struct returned.
997 * uifree() should be called on a struct uidinfo when released.
998 */
999 struct uidinfo *
1000 uifind(uid)
1001 uid_t uid;
1002 {
1003 struct uidinfo *old_uip, *uip;
1004
1005 mtx_lock(&uihashtbl_mtx);
1006 uip = uilookup(uid);
1007 if (uip == NULL) {
1008 mtx_unlock(&uihashtbl_mtx);
1009 uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO);
1010 mtx_lock(&uihashtbl_mtx);
1011 /*
1012 * There's a chance someone created our uidinfo while we
1013 * were in malloc and not holding the lock, so we have to
1014 * make sure we don't insert a duplicate uidinfo.
1015 */
1016 if ((old_uip = uilookup(uid)) != NULL) {
1017 /* Someone else beat us to it. */
1018 free(uip, M_UIDINFO);
1019 uip = old_uip;
1020 } else {
1021 uip->ui_mtxp = mtx_pool_alloc(mtxpool_sleep);
1022 uip->ui_uid = uid;
1023 LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
1024 }
1025 }
1026 uihold(uip);
1027 mtx_unlock(&uihashtbl_mtx);
1028 return (uip);
1029 }
1030
1031 /*
1032 * Place another refcount on a uidinfo struct.
1033 */
1034 void
1035 uihold(uip)
1036 struct uidinfo *uip;
1037 {
1038
1039 UIDINFO_LOCK(uip);
1040 uip->ui_ref++;
1041 UIDINFO_UNLOCK(uip);
1042 }
1043
1044 /*-
1045 * Since uidinfo structs have a long lifetime, we use an
1046 * opportunistic refcounting scheme to avoid locking the lookup hash
1047 * for each release.
1048 *
1049 * If the refcount hits 0, we need to free the structure,
1050 * which means we need to lock the hash.
1051 * Optimal case:
1052 * After locking the struct and lowering the refcount, if we find
1053 * that we don't need to free, simply unlock and return.
1054 * Suboptimal case:
1055 * If refcount lowering results in need to free, bump the count
1056 * back up, loose the lock and aquire the locks in the proper
1057 * order to try again.
1058 */
1059 void
1060 uifree(uip)
1061 struct uidinfo *uip;
1062 {
1063
1064 /* Prepare for optimal case. */
1065 UIDINFO_LOCK(uip);
1066
1067 if (--uip->ui_ref != 0) {
1068 UIDINFO_UNLOCK(uip);
1069 return;
1070 }
1071
1072 /* Prepare for suboptimal case. */
1073 uip->ui_ref++;
1074 UIDINFO_UNLOCK(uip);
1075 mtx_lock(&uihashtbl_mtx);
1076 UIDINFO_LOCK(uip);
1077
1078 /*
1079 * We must subtract one from the count again because we backed out
1080 * our initial subtraction before dropping the lock.
1081 * Since another thread may have added a reference after we dropped the
1082 * initial lock we have to test for zero again.
1083 */
1084 if (--uip->ui_ref == 0) {
1085 LIST_REMOVE(uip, ui_hash);
1086 mtx_unlock(&uihashtbl_mtx);
1087 if (uip->ui_sbsize != 0)
1088 printf("freeing uidinfo: uid = %d, sbsize = %jd\n",
1089 uip->ui_uid, (intmax_t)uip->ui_sbsize);
1090 if (uip->ui_proccnt != 0)
1091 printf("freeing uidinfo: uid = %d, proccnt = %ld\n",
1092 uip->ui_uid, uip->ui_proccnt);
1093 UIDINFO_UNLOCK(uip);
1094 FREE(uip, M_UIDINFO);
1095 return;
1096 }
1097
1098 mtx_unlock(&uihashtbl_mtx);
1099 UIDINFO_UNLOCK(uip);
1100 }
1101
1102 /*
1103 * Change the count associated with number of processes
1104 * a given user is using. When 'max' is 0, don't enforce a limit
1105 */
1106 int
1107 chgproccnt(uip, diff, max)
1108 struct uidinfo *uip;
1109 int diff;
1110 int max;
1111 {
1112
1113 UIDINFO_LOCK(uip);
1114 /* Don't allow them to exceed max, but allow subtraction. */
1115 if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) {
1116 UIDINFO_UNLOCK(uip);
1117 return (0);
1118 }
1119 uip->ui_proccnt += diff;
1120 if (uip->ui_proccnt < 0)
1121 printf("negative proccnt for uid = %d\n", uip->ui_uid);
1122 UIDINFO_UNLOCK(uip);
1123 return (1);
1124 }
1125
1126 /*
1127 * Change the total socket buffer size a user has used.
1128 */
1129 int
1130 chgsbsize(uip, hiwat, to, max)
1131 struct uidinfo *uip;
1132 u_int *hiwat;
1133 u_int to;
1134 rlim_t max;
1135 {
1136 rlim_t new;
1137
1138 UIDINFO_LOCK(uip);
1139 new = uip->ui_sbsize + to - *hiwat;
1140 /* Don't allow them to exceed max, but allow subtraction */
1141 if (to > *hiwat && new > max) {
1142 UIDINFO_UNLOCK(uip);
1143 return (0);
1144 }
1145 uip->ui_sbsize = new;
1146 UIDINFO_UNLOCK(uip);
1147 *hiwat = to;
1148 if (new < 0)
1149 printf("negative sbsize for uid = %d\n", uip->ui_uid);
1150 return (1);
1151 }
Cache object: 71fb17ad72190afb61d903338391df71
|