kern_resource.c revision 1.100.4.1 1 /* $NetBSD: kern_resource.c,v 1.100.4.1 2006/03/08 00:53:40 elad Exp $ */
2
3 /*-
4 * Copyright (c) 1982, 1986, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)kern_resource.c 8.8 (Berkeley) 2/14/95
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.100.4.1 2006/03/08 00:53:40 elad Exp $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/file.h>
46 #include <sys/resourcevar.h>
47 #include <sys/malloc.h>
48 #include <sys/namei.h>
49 #include <sys/pool.h>
50 #include <sys/proc.h>
51 #include <sys/sysctl.h>
52
53 #include <sys/mount.h>
54 #include <sys/sa.h>
55 #include <sys/syscallargs.h>
56
57 #include <uvm/uvm_extern.h>
58
59 /*
60 * Maximum process data and stack limits.
61 * They are variables so they are patchable.
62 */
63 rlim_t maxdmap = MAXDSIZ;
64 rlim_t maxsmap = MAXSSIZ;
65
66 struct uihashhead *uihashtbl;
67 u_long uihash; /* size of hash table - 1 */
68 struct simplelock uihashtbl_slock = SIMPLELOCK_INITIALIZER;
69
70
71 /*
72 * Resource controls and accounting.
73 */
74
75 int
76 sys_getpriority(struct lwp *l, void *v, register_t *retval)
77 {
78 struct sys_getpriority_args /* {
79 syscallarg(int) which;
80 syscallarg(id_t) who;
81 } */ *uap = v;
82 struct proc *curp = l->l_proc, *p;
83 int low = NZERO + PRIO_MAX + 1;
84
85 switch (SCARG(uap, which)) {
86
87 case PRIO_PROCESS:
88 if (SCARG(uap, who) == 0)
89 p = curp;
90 else
91 p = pfind(SCARG(uap, who));
92 if (p == 0)
93 break;
94 low = p->p_nice;
95 break;
96
97 case PRIO_PGRP: {
98 struct pgrp *pg;
99
100 if (SCARG(uap, who) == 0)
101 pg = curp->p_pgrp;
102 else if ((pg = pgfind(SCARG(uap, who))) == NULL)
103 break;
104 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
105 if (p->p_nice < low)
106 low = p->p_nice;
107 }
108 break;
109 }
110
111 case PRIO_USER:
112 if (SCARG(uap, who) == 0)
113 SCARG(uap, who) = kauth_cred_geteuid(curp->p_cred);
114 proclist_lock_read();
115 PROCLIST_FOREACH(p, &allproc) {
116 if (kauth_cred_geteuid(p->p_cred) == (uid_t) SCARG(uap, who) &&
117 p->p_nice < low)
118 low = p->p_nice;
119 }
120 proclist_unlock_read();
121 break;
122
123 default:
124 return (EINVAL);
125 }
126 if (low == NZERO + PRIO_MAX + 1)
127 return (ESRCH);
128 *retval = low - NZERO;
129 return (0);
130 }
131
132 /* ARGSUSED */
133 int
134 sys_setpriority(struct lwp *l, void *v, register_t *retval)
135 {
136 struct sys_setpriority_args /* {
137 syscallarg(int) which;
138 syscallarg(id_t) who;
139 syscallarg(int) prio;
140 } */ *uap = v;
141 struct proc *curp = l->l_proc, *p;
142 int found = 0, error = 0;
143
144 switch (SCARG(uap, which)) {
145
146 case PRIO_PROCESS:
147 if (SCARG(uap, who) == 0)
148 p = curp;
149 else
150 p = pfind(SCARG(uap, who));
151 if (p == 0)
152 break;
153 error = donice(curp, p, SCARG(uap, prio));
154 found++;
155 break;
156
157 case PRIO_PGRP: {
158 struct pgrp *pg;
159
160 if (SCARG(uap, who) == 0)
161 pg = curp->p_pgrp;
162 else if ((pg = pgfind(SCARG(uap, who))) == NULL)
163 break;
164 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
165 error = donice(curp, p, SCARG(uap, prio));
166 found++;
167 }
168 break;
169 }
170
171 case PRIO_USER:
172 if (SCARG(uap, who) == 0)
173 SCARG(uap, who) = kauth_cred_geteuid(curp->p_cred);
174 proclist_lock_read();
175 PROCLIST_FOREACH(p, &allproc) {
176 if (kauth_cred_geteuid(p->p_cred) == (uid_t) SCARG(uap, who)) {
177 error = donice(curp, p, SCARG(uap, prio));
178 found++;
179 }
180 }
181 proclist_unlock_read();
182 break;
183
184 default:
185 return (EINVAL);
186 }
187 if (found == 0)
188 return (ESRCH);
189 return (error);
190 }
191
192 int
193 donice(struct proc *curp, struct proc *chgp, int n)
194 {
195 kauth_cred_t cred = curp->p_cred;
196 int s;
197
198 if (kauth_cred_geteuid(cred) && kauth_cred_getuid(cred) &&
199 kauth_cred_geteuid(cred) != kauth_cred_geteuid(chgp->p_cred) &&
200 kauth_cred_getuid(cred) != kauth_cred_geteuid(chgp->p_cred))
201 return (EPERM);
202 if (n > PRIO_MAX)
203 n = PRIO_MAX;
204 if (n < PRIO_MIN)
205 n = PRIO_MIN;
206 n += NZERO;
207 if (n < chgp->p_nice && generic_authorize(cred, KAUTH_GENERIC_ISSUSER,
208 &curp->p_acflag))
209 return (EACCES);
210 chgp->p_nice = n;
211 SCHED_LOCK(s);
212 (void)resetprocpriority(chgp);
213 SCHED_UNLOCK(s);
214 return (0);
215 }
216
217 /* ARGSUSED */
218 int
219 sys_setrlimit(struct lwp *l, void *v, register_t *retval)
220 {
221 struct sys_setrlimit_args /* {
222 syscallarg(int) which;
223 syscallarg(const struct rlimit *) rlp;
224 } */ *uap = v;
225 struct proc *p = l->l_proc;
226 int which = SCARG(uap, which);
227 struct rlimit alim;
228 int error;
229
230 error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
231 if (error)
232 return (error);
233 return (dosetrlimit(p, p->p_cred, which, &alim));
234 }
235
236 int
237 dosetrlimit(struct proc *p, kauth_cred_t cred, int which, struct rlimit *limp)
238 {
239 struct rlimit *alimp;
240 struct plimit *oldplim;
241 int error;
242
243 if ((u_int)which >= RLIM_NLIMITS)
244 return (EINVAL);
245
246 if (limp->rlim_cur < 0 || limp->rlim_max < 0)
247 return (EINVAL);
248
249 alimp = &p->p_rlimit[which];
250 /* if we don't change the value, no need to limcopy() */
251 if (limp->rlim_cur == alimp->rlim_cur &&
252 limp->rlim_max == alimp->rlim_max)
253 return 0;
254
255 if (limp->rlim_cur > limp->rlim_max) {
256 /*
257 * This is programming error. According to SUSv2, we should
258 * return error in this case.
259 */
260 return (EINVAL);
261 }
262 if (limp->rlim_max > alimp->rlim_max
263 && (error = generic_authorize(cred, KAUTH_GENERIC_ISSUSER,
264 &p->p_acflag)) != 0)
265 return (error);
266
267 if (p->p_limit->p_refcnt > 1 &&
268 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
269 p->p_limit = limcopy(oldplim = p->p_limit);
270 limfree(oldplim);
271 alimp = &p->p_rlimit[which];
272 }
273
274 switch (which) {
275
276 case RLIMIT_DATA:
277 if (limp->rlim_cur > maxdmap)
278 limp->rlim_cur = maxdmap;
279 if (limp->rlim_max > maxdmap)
280 limp->rlim_max = maxdmap;
281 break;
282
283 case RLIMIT_STACK:
284 if (limp->rlim_cur > maxsmap)
285 limp->rlim_cur = maxsmap;
286 if (limp->rlim_max > maxsmap)
287 limp->rlim_max = maxsmap;
288
289 /*
290 * Return EINVAL if the new stack size limit is lower than
291 * current usage. Otherwise, the process would get SIGSEGV the
292 * moment it would try to access anything on it's current stack.
293 * This conforms to SUSv2.
294 */
295 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE
296 || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE)
297 return (EINVAL);
298
299 /*
300 * Stack is allocated to the max at exec time with
301 * only "rlim_cur" bytes accessible (In other words,
302 * allocates stack dividing two contiguous regions at
303 * "rlim_cur" bytes boundary).
304 *
305 * Since allocation is done in terms of page, roundup
306 * "rlim_cur" (otherwise, contiguous regions
307 * overlap). If stack limit is going up make more
308 * accessible, if going down make inaccessible.
309 */
310 limp->rlim_cur = round_page(limp->rlim_cur);
311 if (limp->rlim_cur != alimp->rlim_cur) {
312 vaddr_t addr;
313 vsize_t size;
314 vm_prot_t prot;
315
316 if (limp->rlim_cur > alimp->rlim_cur) {
317 prot = VM_PROT_READ | VM_PROT_WRITE;
318 size = limp->rlim_cur - alimp->rlim_cur;
319 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
320 limp->rlim_cur;
321 } else {
322 prot = VM_PROT_NONE;
323 size = alimp->rlim_cur - limp->rlim_cur;
324 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
325 alimp->rlim_cur;
326 }
327 (void) uvm_map_protect(&p->p_vmspace->vm_map,
328 addr, addr+size, prot, FALSE);
329 }
330 break;
331
332 case RLIMIT_NOFILE:
333 if (limp->rlim_cur > maxfiles)
334 limp->rlim_cur = maxfiles;
335 if (limp->rlim_max > maxfiles)
336 limp->rlim_max = maxfiles;
337 break;
338
339 case RLIMIT_NPROC:
340 if (limp->rlim_cur > maxproc)
341 limp->rlim_cur = maxproc;
342 if (limp->rlim_max > maxproc)
343 limp->rlim_max = maxproc;
344 break;
345 }
346 *alimp = *limp;
347 return (0);
348 }
349
350 /* ARGSUSED */
351 int
352 sys_getrlimit(struct lwp *l, void *v, register_t *retval)
353 {
354 struct sys_getrlimit_args /* {
355 syscallarg(int) which;
356 syscallarg(struct rlimit *) rlp;
357 } */ *uap = v;
358 struct proc *p = l->l_proc;
359 int which = SCARG(uap, which);
360
361 if ((u_int)which >= RLIM_NLIMITS)
362 return (EINVAL);
363 return (copyout(&p->p_rlimit[which], SCARG(uap, rlp),
364 sizeof(struct rlimit)));
365 }
366
367 /*
368 * Transform the running time and tick information in proc p into user,
369 * system, and interrupt time usage.
370 */
371 void
372 calcru(struct proc *p, struct timeval *up, struct timeval *sp,
373 struct timeval *ip)
374 {
375 u_quad_t u, st, ut, it, tot;
376 unsigned long sec;
377 long usec;
378 int s;
379 struct timeval tv;
380 struct lwp *l;
381
382 s = splstatclock();
383 st = p->p_sticks;
384 ut = p->p_uticks;
385 it = p->p_iticks;
386 splx(s);
387
388 sec = p->p_rtime.tv_sec;
389 usec = p->p_rtime.tv_usec;
390 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
391 if (l->l_stat == LSONPROC) {
392 struct schedstate_percpu *spc;
393
394 KDASSERT(l->l_cpu != NULL);
395 spc = &l->l_cpu->ci_schedstate;
396
397 /*
398 * Adjust for the current time slice. This is
399 * actually fairly important since the error
400 * here is on the order of a time quantum,
401 * which is much greater than the sampling
402 * error.
403 */
404 microtime(&tv);
405 sec += tv.tv_sec - spc->spc_runtime.tv_sec;
406 usec += tv.tv_usec - spc->spc_runtime.tv_usec;
407 }
408 }
409
410 tot = st + ut + it;
411 u = sec * 1000000ull + usec;
412
413 if (tot == 0) {
414 /* No ticks, so can't use to share time out, split 50-50 */
415 st = ut = u / 2;
416 } else {
417 st = (u * st) / tot;
418 ut = (u * ut) / tot;
419 }
420 sp->tv_sec = st / 1000000;
421 sp->tv_usec = st % 1000000;
422 up->tv_sec = ut / 1000000;
423 up->tv_usec = ut % 1000000;
424 if (ip != NULL) {
425 if (it != 0)
426 it = (u * it) / tot;
427 ip->tv_sec = it / 1000000;
428 ip->tv_usec = it % 1000000;
429 }
430 }
431
432 /* ARGSUSED */
433 int
434 sys_getrusage(struct lwp *l, void *v, register_t *retval)
435 {
436 struct sys_getrusage_args /* {
437 syscallarg(int) who;
438 syscallarg(struct rusage *) rusage;
439 } */ *uap = v;
440 struct rusage *rup;
441 struct proc *p = l->l_proc;
442
443 switch (SCARG(uap, who)) {
444
445 case RUSAGE_SELF:
446 rup = &p->p_stats->p_ru;
447 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
448 break;
449
450 case RUSAGE_CHILDREN:
451 rup = &p->p_stats->p_cru;
452 break;
453
454 default:
455 return (EINVAL);
456 }
457 return (copyout(rup, SCARG(uap, rusage), sizeof(struct rusage)));
458 }
459
460 void
461 ruadd(struct rusage *ru, struct rusage *ru2)
462 {
463 long *ip, *ip2;
464 int i;
465
466 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
467 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
468 if (ru->ru_maxrss < ru2->ru_maxrss)
469 ru->ru_maxrss = ru2->ru_maxrss;
470 ip = &ru->ru_first; ip2 = &ru2->ru_first;
471 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
472 *ip++ += *ip2++;
473 }
474
475 /*
476 * Make a copy of the plimit structure.
477 * We share these structures copy-on-write after fork,
478 * and copy when a limit is changed.
479 */
480 struct plimit *
481 limcopy(struct plimit *lim)
482 {
483 struct plimit *newlim;
484 size_t l = 0;
485
486 simple_lock(&lim->p_slock);
487 if (lim->pl_corename != defcorename)
488 l = strlen(lim->pl_corename) + 1;
489 simple_unlock(&lim->p_slock);
490
491 newlim = pool_get(&plimit_pool, PR_WAITOK);
492 simple_lock_init(&newlim->p_slock);
493 newlim->p_lflags = 0;
494 newlim->p_refcnt = 1;
495 newlim->pl_corename = (l != 0)
496 ? malloc(l, M_TEMP, M_WAITOK)
497 : defcorename;
498
499 simple_lock(&lim->p_slock);
500 memcpy(newlim->pl_rlimit, lim->pl_rlimit,
501 sizeof(struct rlimit) * RLIM_NLIMITS);
502
503 if (l != 0)
504 strlcpy(newlim->pl_corename, lim->pl_corename, l);
505 simple_unlock(&lim->p_slock);
506
507 return (newlim);
508 }
509
510 void
511 limfree(struct plimit *lim)
512 {
513 int n;
514
515 simple_lock(&lim->p_slock);
516 n = --lim->p_refcnt;
517 simple_unlock(&lim->p_slock);
518 if (n > 0)
519 return;
520 #ifdef DIAGNOSTIC
521 if (n < 0)
522 panic("limfree");
523 #endif
524 if (lim->pl_corename != defcorename)
525 free(lim->pl_corename, M_TEMP);
526 pool_put(&plimit_pool, lim);
527 }
528
529 struct pstats *
530 pstatscopy(struct pstats *ps)
531 {
532
533 struct pstats *newps;
534
535 newps = pool_get(&pstats_pool, PR_WAITOK);
536
537 memset(&newps->pstat_startzero, 0,
538 (unsigned) ((caddr_t)&newps->pstat_endzero -
539 (caddr_t)&newps->pstat_startzero));
540 memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy,
541 ((caddr_t)&newps->pstat_endcopy -
542 (caddr_t)&newps->pstat_startcopy));
543
544 return (newps);
545
546 }
547
548 void
549 pstatsfree(struct pstats *ps)
550 {
551
552 pool_put(&pstats_pool, ps);
553 }
554
555 /*
556 * sysctl interface in five parts
557 */
558
559 /*
560 * a routine for sysctl proc subtree helpers that need to pick a valid
561 * process by pid.
562 */
563 static int
564 sysctl_proc_findproc(struct proc *p, struct proc **p2, pid_t pid)
565 {
566 struct proc *ptmp;
567 int i, error = 0;
568
569 if (pid == PROC_CURPROC)
570 ptmp = p;
571 else if ((ptmp = pfind(pid)) == NULL)
572 error = ESRCH;
573 else {
574 /*
575 * suid proc of ours or proc not ours
576 */
577 if (kauth_cred_getuid(p->p_cred) != kauth_cred_getuid(ptmp->p_cred) ||
578 kauth_cred_getuid(p->p_cred) != kauth_cred_getsvuid(ptmp->p_cred))
579 error = generic_authorize(p->p_cred,
580 KAUTH_GENERIC_ISSUSER, &p->p_acflag);
581
582 /*
583 * sgid proc has sgid back to us temporarily
584 */
585 else if (kauth_cred_getgid(ptmp->p_cred) != kauth_cred_getsvgid(ptmp->p_cred))
586 error = generic_authorize(p->p_cred,
587 KAUTH_GENERIC_ISSUSER, &p->p_acflag);
588
589 /*
590 * our rgid must be in target's group list (ie,
591 * sub-processes started by a sgid process)
592 */
593 else {
594 int do_ngroups;
595
596 do_ngroups = kauth_cred_ngroups(p->p_cred);
597 for (i = 0; i < do_ngroups; i++) {
598 if (kauth_cred_group(p->p_cred, i) ==
599 kauth_cred_getgid(ptmp->p_cred))
600 break;
601 }
602 if (i == kauth_cred_ngroups(p->p_cred))
603 error = generic_authorize(p->p_cred,
604 KAUTH_GENERIC_ISSUSER,
605 &p->p_acflag);
606 }
607 }
608
609 *p2 = ptmp;
610 return (error);
611 }
612
613 /*
614 * sysctl helper routine for setting a process's specific corefile
615 * name. picks the process based on the given pid and checks the
616 * correctness of the new value.
617 */
618 static int
619 sysctl_proc_corename(SYSCTLFN_ARGS)
620 {
621 struct proc *ptmp, *p;
622 struct plimit *lim;
623 int error = 0, len;
624 char *cname;
625 char *tmp;
626 struct sysctlnode node;
627
628 /*
629 * is this all correct?
630 */
631 if (namelen != 0)
632 return (EINVAL);
633 if (name[-1] != PROC_PID_CORENAME)
634 return (EINVAL);
635
636 /*
637 * whom are we tweaking?
638 */
639 p = l->l_proc;
640 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]);
641 if (error)
642 return (error);
643
644 cname = PNBUF_GET();
645 /*
646 * let them modify a temporary copy of the core name
647 */
648 node = *rnode;
649 strlcpy(cname, ptmp->p_limit->pl_corename, MAXPATHLEN);
650 node.sysctl_data = cname;
651 error = sysctl_lookup(SYSCTLFN_CALL(&node));
652
653 /*
654 * if that failed, or they have nothing new to say, or we've
655 * heard it before...
656 */
657 if (error || newp == NULL ||
658 strcmp(cname, ptmp->p_limit->pl_corename) == 0) {
659 goto done;
660 }
661
662 /*
663 * no error yet and cname now has the new core name in it.
664 * let's see if it looks acceptable. it must be either "core"
665 * or end in ".core" or "/core".
666 */
667 len = strlen(cname);
668 if (len < 4) {
669 error = EINVAL;
670 } else if (strcmp(cname + len - 4, "core") != 0) {
671 error = EINVAL;
672 } else if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') {
673 error = EINVAL;
674 }
675 if (error != 0) {
676 goto done;
677 }
678
679 /*
680 * hmm...looks good. now...where do we put it?
681 */
682 tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL);
683 if (tmp == NULL) {
684 error = ENOMEM;
685 goto done;
686 }
687 strlcpy(tmp, cname, len + 1);
688
689 lim = ptmp->p_limit;
690 if (lim->p_refcnt > 1 && (lim->p_lflags & PL_SHAREMOD) == 0) {
691 ptmp->p_limit = limcopy(lim);
692 limfree(lim);
693 lim = ptmp->p_limit;
694 }
695 if (lim->pl_corename != defcorename)
696 free(lim->pl_corename, M_TEMP);
697 lim->pl_corename = tmp;
698 done:
699 PNBUF_PUT(cname);
700 return error;
701 }
702
703 /*
704 * sysctl helper routine for checking/setting a process's stop flags,
705 * one for fork and one for exec.
706 */
707 static int
708 sysctl_proc_stop(SYSCTLFN_ARGS)
709 {
710 struct proc *p, *ptmp;
711 int i, f, error = 0;
712 struct sysctlnode node;
713
714 if (namelen != 0)
715 return (EINVAL);
716
717 p = l->l_proc;
718 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]);
719 if (error)
720 return (error);
721
722 switch (rnode->sysctl_num) {
723 case PROC_PID_STOPFORK:
724 f = P_STOPFORK;
725 break;
726 case PROC_PID_STOPEXEC:
727 f = P_STOPEXEC;
728 break;
729 case PROC_PID_STOPEXIT:
730 f = P_STOPEXIT;
731 break;
732 default:
733 return (EINVAL);
734 }
735
736 i = (ptmp->p_flag & f) ? 1 : 0;
737 node = *rnode;
738 node.sysctl_data = &i;
739 error = sysctl_lookup(SYSCTLFN_CALL(&node));
740 if (error || newp == NULL)
741 return (error);
742
743 if (i)
744 ptmp->p_flag |= f;
745 else
746 ptmp->p_flag &= ~f;
747
748 return (0);
749 }
750
751 /*
752 * sysctl helper routine for a process's rlimits as exposed by sysctl.
753 */
754 static int
755 sysctl_proc_plimit(SYSCTLFN_ARGS)
756 {
757 struct proc *ptmp, *p;
758 u_int limitno;
759 int which, error = 0;
760 struct rlimit alim;
761 struct sysctlnode node;
762
763 if (namelen != 0)
764 return (EINVAL);
765
766 which = name[-1];
767 if (which != PROC_PID_LIMIT_TYPE_SOFT &&
768 which != PROC_PID_LIMIT_TYPE_HARD)
769 return (EINVAL);
770
771 limitno = name[-2] - 1;
772 if (limitno >= RLIM_NLIMITS)
773 return (EINVAL);
774
775 if (name[-3] != PROC_PID_LIMIT)
776 return (EINVAL);
777
778 p = l->l_proc;
779 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-4]);
780 if (error)
781 return (error);
782
783 node = *rnode;
784 memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim));
785 if (which == PROC_PID_LIMIT_TYPE_HARD)
786 node.sysctl_data = &alim.rlim_max;
787 else
788 node.sysctl_data = &alim.rlim_cur;
789
790 error = sysctl_lookup(SYSCTLFN_CALL(&node));
791 if (error || newp == NULL)
792 return (error);
793
794 return (dosetrlimit(ptmp, p->p_cred, limitno, &alim));
795 }
796
797 /*
798 * and finally, the actually glue that sticks it to the tree
799 */
800 SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup")
801 {
802
803 sysctl_createv(clog, 0, NULL, NULL,
804 CTLFLAG_PERMANENT,
805 CTLTYPE_NODE, "proc", NULL,
806 NULL, 0, NULL, 0,
807 CTL_PROC, CTL_EOL);
808 sysctl_createv(clog, 0, NULL, NULL,
809 CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
810 CTLTYPE_NODE, "curproc",
811 SYSCTL_DESCR("Per-process settings"),
812 NULL, 0, NULL, 0,
813 CTL_PROC, PROC_CURPROC, CTL_EOL);
814
815 sysctl_createv(clog, 0, NULL, NULL,
816 CTLFLAG_PERMANENT|CTLFLAG_READONLY2|CTLFLAG_ANYWRITE,
817 CTLTYPE_STRING, "corename",
818 SYSCTL_DESCR("Core file name"),
819 sysctl_proc_corename, 0, NULL, MAXPATHLEN,
820 CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
821 sysctl_createv(clog, 0, NULL, NULL,
822 CTLFLAG_PERMANENT,
823 CTLTYPE_NODE, "rlimit",
824 SYSCTL_DESCR("Process limits"),
825 NULL, 0, NULL, 0,
826 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
827
828 #define create_proc_plimit(s, n) do { \
829 sysctl_createv(clog, 0, NULL, NULL, \
830 CTLFLAG_PERMANENT, \
831 CTLTYPE_NODE, s, \
832 SYSCTL_DESCR("Process " s " limits"), \
833 NULL, 0, NULL, 0, \
834 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
835 CTL_EOL); \
836 sysctl_createv(clog, 0, NULL, NULL, \
837 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
838 CTLTYPE_QUAD, "soft", \
839 SYSCTL_DESCR("Process soft " s " limit"), \
840 sysctl_proc_plimit, 0, NULL, 0, \
841 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
842 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \
843 sysctl_createv(clog, 0, NULL, NULL, \
844 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
845 CTLTYPE_QUAD, "hard", \
846 SYSCTL_DESCR("Process hard " s " limit"), \
847 sysctl_proc_plimit, 0, NULL, 0, \
848 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
849 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \
850 } while (0/*CONSTCOND*/)
851
852 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU);
853 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE);
854 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA);
855 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK);
856 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE);
857 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS);
858 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK);
859 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC);
860 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE);
861 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE);
862
863 #undef create_proc_plimit
864
865 sysctl_createv(clog, 0, NULL, NULL,
866 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
867 CTLTYPE_INT, "stopfork",
868 SYSCTL_DESCR("Stop process at fork(2)"),
869 sysctl_proc_stop, 0, NULL, 0,
870 CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
871 sysctl_createv(clog, 0, NULL, NULL,
872 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
873 CTLTYPE_INT, "stopexec",
874 SYSCTL_DESCR("Stop process at execve(2)"),
875 sysctl_proc_stop, 0, NULL, 0,
876 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
877 sysctl_createv(clog, 0, NULL, NULL,
878 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
879 CTLTYPE_INT, "stopexit",
880 SYSCTL_DESCR("Stop process before completing exit"),
881 sysctl_proc_stop, 0, NULL, 0,
882 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
883 }
884
885 struct uidinfo *
886 uid_find(uid_t uid)
887 {
888 struct uidinfo *uip;
889 struct uidinfo *newuip = NULL;
890 struct uihashhead *uipp;
891
892 uipp = UIHASH(uid);
893
894 again:
895 simple_lock(&uihashtbl_slock);
896 LIST_FOREACH(uip, uipp, ui_hash)
897 if (uip->ui_uid == uid) {
898 simple_unlock(&uihashtbl_slock);
899 if (newuip)
900 free(newuip, M_PROC);
901 return uip;
902 }
903
904 if (newuip == NULL) {
905 simple_unlock(&uihashtbl_slock);
906 newuip = malloc(sizeof(*uip), M_PROC, M_WAITOK | M_ZERO);
907 goto again;
908 }
909 uip = newuip;
910
911 LIST_INSERT_HEAD(uipp, uip, ui_hash);
912 uip->ui_uid = uid;
913 simple_lock_init(&uip->ui_slock);
914 simple_unlock(&uihashtbl_slock);
915
916 return uip;
917 }
918
919 /*
920 * Change the count associated with number of processes
921 * a given user is using.
922 */
923 int
924 chgproccnt(uid_t uid, int diff)
925 {
926 struct uidinfo *uip;
927 int s;
928
929 if (diff == 0)
930 return 0;
931
932 uip = uid_find(uid);
933 UILOCK(uip, s);
934 uip->ui_proccnt += diff;
935 KASSERT(uip->ui_proccnt >= 0);
936 UIUNLOCK(uip, s);
937 return uip->ui_proccnt;
938 }
939
940 int
941 chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t xmax)
942 {
943 rlim_t nsb;
944 int s;
945
946 UILOCK(uip, s);
947 nsb = uip->ui_sbsize + to - *hiwat;
948 if (to > *hiwat && nsb > xmax) {
949 UIUNLOCK(uip, s);
950 splx(s);
951 return 0;
952 }
953 *hiwat = to;
954 uip->ui_sbsize = nsb;
955 KASSERT(uip->ui_sbsize >= 0);
956 UIUNLOCK(uip, s);
957 return 1;
958 }
959