kern_resource.c revision 1.100.4.3 1 /* $NetBSD: kern_resource.c,v 1.100.4.3 2006/03/12 23:33:56 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.3 2006/03/12 23:33:56 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 && kauth_authorize_generic(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 = kauth_authorize_generic(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 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 = kauth_authorize_generic(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 = kauth_authorize_generic(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 ismember = 0;
595
596 if (kauth_cred_ismember_gid(p->p_cred,
597 kauth_cred_getgid(ptmp->p_cred), &ismember) != 0 ||
598 !ismember) {
599 error = kauth_authorize_generic(p->p_cred,
600 KAUTH_GENERIC_ISSUSER, &p->p_acflag);
601 }
602 }
603 }
604
605 *p2 = ptmp;
606 return (error);
607 }
608
609 /*
610 * sysctl helper routine for setting a process's specific corefile
611 * name. picks the process based on the given pid and checks the
612 * correctness of the new value.
613 */
614 static int
615 sysctl_proc_corename(SYSCTLFN_ARGS)
616 {
617 struct proc *ptmp, *p;
618 struct plimit *lim;
619 int error = 0, len;
620 char *cname;
621 char *tmp;
622 struct sysctlnode node;
623
624 /*
625 * is this all correct?
626 */
627 if (namelen != 0)
628 return (EINVAL);
629 if (name[-1] != PROC_PID_CORENAME)
630 return (EINVAL);
631
632 /*
633 * whom are we tweaking?
634 */
635 p = l->l_proc;
636 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]);
637 if (error)
638 return (error);
639
640 cname = PNBUF_GET();
641 /*
642 * let them modify a temporary copy of the core name
643 */
644 node = *rnode;
645 strlcpy(cname, ptmp->p_limit->pl_corename, MAXPATHLEN);
646 node.sysctl_data = cname;
647 error = sysctl_lookup(SYSCTLFN_CALL(&node));
648
649 /*
650 * if that failed, or they have nothing new to say, or we've
651 * heard it before...
652 */
653 if (error || newp == NULL ||
654 strcmp(cname, ptmp->p_limit->pl_corename) == 0) {
655 goto done;
656 }
657
658 /*
659 * no error yet and cname now has the new core name in it.
660 * let's see if it looks acceptable. it must be either "core"
661 * or end in ".core" or "/core".
662 */
663 len = strlen(cname);
664 if (len < 4) {
665 error = EINVAL;
666 } else if (strcmp(cname + len - 4, "core") != 0) {
667 error = EINVAL;
668 } else if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') {
669 error = EINVAL;
670 }
671 if (error != 0) {
672 goto done;
673 }
674
675 /*
676 * hmm...looks good. now...where do we put it?
677 */
678 tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL);
679 if (tmp == NULL) {
680 error = ENOMEM;
681 goto done;
682 }
683 strlcpy(tmp, cname, len + 1);
684
685 lim = ptmp->p_limit;
686 if (lim->p_refcnt > 1 && (lim->p_lflags & PL_SHAREMOD) == 0) {
687 ptmp->p_limit = limcopy(lim);
688 limfree(lim);
689 lim = ptmp->p_limit;
690 }
691 if (lim->pl_corename != defcorename)
692 free(lim->pl_corename, M_TEMP);
693 lim->pl_corename = tmp;
694 done:
695 PNBUF_PUT(cname);
696 return error;
697 }
698
699 /*
700 * sysctl helper routine for checking/setting a process's stop flags,
701 * one for fork and one for exec.
702 */
703 static int
704 sysctl_proc_stop(SYSCTLFN_ARGS)
705 {
706 struct proc *p, *ptmp;
707 int i, f, error = 0;
708 struct sysctlnode node;
709
710 if (namelen != 0)
711 return (EINVAL);
712
713 p = l->l_proc;
714 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-2]);
715 if (error)
716 return (error);
717
718 switch (rnode->sysctl_num) {
719 case PROC_PID_STOPFORK:
720 f = P_STOPFORK;
721 break;
722 case PROC_PID_STOPEXEC:
723 f = P_STOPEXEC;
724 break;
725 case PROC_PID_STOPEXIT:
726 f = P_STOPEXIT;
727 break;
728 default:
729 return (EINVAL);
730 }
731
732 i = (ptmp->p_flag & f) ? 1 : 0;
733 node = *rnode;
734 node.sysctl_data = &i;
735 error = sysctl_lookup(SYSCTLFN_CALL(&node));
736 if (error || newp == NULL)
737 return (error);
738
739 if (i)
740 ptmp->p_flag |= f;
741 else
742 ptmp->p_flag &= ~f;
743
744 return (0);
745 }
746
747 /*
748 * sysctl helper routine for a process's rlimits as exposed by sysctl.
749 */
750 static int
751 sysctl_proc_plimit(SYSCTLFN_ARGS)
752 {
753 struct proc *ptmp, *p;
754 u_int limitno;
755 int which, error = 0;
756 struct rlimit alim;
757 struct sysctlnode node;
758
759 if (namelen != 0)
760 return (EINVAL);
761
762 which = name[-1];
763 if (which != PROC_PID_LIMIT_TYPE_SOFT &&
764 which != PROC_PID_LIMIT_TYPE_HARD)
765 return (EINVAL);
766
767 limitno = name[-2] - 1;
768 if (limitno >= RLIM_NLIMITS)
769 return (EINVAL);
770
771 if (name[-3] != PROC_PID_LIMIT)
772 return (EINVAL);
773
774 p = l->l_proc;
775 error = sysctl_proc_findproc(p, &ptmp, (pid_t)name[-4]);
776 if (error)
777 return (error);
778
779 node = *rnode;
780 memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim));
781 if (which == PROC_PID_LIMIT_TYPE_HARD)
782 node.sysctl_data = &alim.rlim_max;
783 else
784 node.sysctl_data = &alim.rlim_cur;
785
786 error = sysctl_lookup(SYSCTLFN_CALL(&node));
787 if (error || newp == NULL)
788 return (error);
789
790 return (dosetrlimit(ptmp, p->p_cred, limitno, &alim));
791 }
792
793 /*
794 * and finally, the actually glue that sticks it to the tree
795 */
796 SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup")
797 {
798
799 sysctl_createv(clog, 0, NULL, NULL,
800 CTLFLAG_PERMANENT,
801 CTLTYPE_NODE, "proc", NULL,
802 NULL, 0, NULL, 0,
803 CTL_PROC, CTL_EOL);
804 sysctl_createv(clog, 0, NULL, NULL,
805 CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
806 CTLTYPE_NODE, "curproc",
807 SYSCTL_DESCR("Per-process settings"),
808 NULL, 0, NULL, 0,
809 CTL_PROC, PROC_CURPROC, CTL_EOL);
810
811 sysctl_createv(clog, 0, NULL, NULL,
812 CTLFLAG_PERMANENT|CTLFLAG_READONLY2|CTLFLAG_ANYWRITE,
813 CTLTYPE_STRING, "corename",
814 SYSCTL_DESCR("Core file name"),
815 sysctl_proc_corename, 0, NULL, MAXPATHLEN,
816 CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
817 sysctl_createv(clog, 0, NULL, NULL,
818 CTLFLAG_PERMANENT,
819 CTLTYPE_NODE, "rlimit",
820 SYSCTL_DESCR("Process limits"),
821 NULL, 0, NULL, 0,
822 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
823
824 #define create_proc_plimit(s, n) do { \
825 sysctl_createv(clog, 0, NULL, NULL, \
826 CTLFLAG_PERMANENT, \
827 CTLTYPE_NODE, s, \
828 SYSCTL_DESCR("Process " s " limits"), \
829 NULL, 0, NULL, 0, \
830 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
831 CTL_EOL); \
832 sysctl_createv(clog, 0, NULL, NULL, \
833 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
834 CTLTYPE_QUAD, "soft", \
835 SYSCTL_DESCR("Process soft " s " limit"), \
836 sysctl_proc_plimit, 0, NULL, 0, \
837 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
838 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \
839 sysctl_createv(clog, 0, NULL, NULL, \
840 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
841 CTLTYPE_QUAD, "hard", \
842 SYSCTL_DESCR("Process hard " s " limit"), \
843 sysctl_proc_plimit, 0, NULL, 0, \
844 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
845 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \
846 } while (0/*CONSTCOND*/)
847
848 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU);
849 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE);
850 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA);
851 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK);
852 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE);
853 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS);
854 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK);
855 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC);
856 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE);
857 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE);
858
859 #undef create_proc_plimit
860
861 sysctl_createv(clog, 0, NULL, NULL,
862 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
863 CTLTYPE_INT, "stopfork",
864 SYSCTL_DESCR("Stop process at fork(2)"),
865 sysctl_proc_stop, 0, NULL, 0,
866 CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
867 sysctl_createv(clog, 0, NULL, NULL,
868 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
869 CTLTYPE_INT, "stopexec",
870 SYSCTL_DESCR("Stop process at execve(2)"),
871 sysctl_proc_stop, 0, NULL, 0,
872 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
873 sysctl_createv(clog, 0, NULL, NULL,
874 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
875 CTLTYPE_INT, "stopexit",
876 SYSCTL_DESCR("Stop process before completing exit"),
877 sysctl_proc_stop, 0, NULL, 0,
878 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
879 }
880
881 struct uidinfo *
882 uid_find(uid_t uid)
883 {
884 struct uidinfo *uip;
885 struct uidinfo *newuip = NULL;
886 struct uihashhead *uipp;
887
888 uipp = UIHASH(uid);
889
890 again:
891 simple_lock(&uihashtbl_slock);
892 LIST_FOREACH(uip, uipp, ui_hash)
893 if (uip->ui_uid == uid) {
894 simple_unlock(&uihashtbl_slock);
895 if (newuip)
896 free(newuip, M_PROC);
897 return uip;
898 }
899
900 if (newuip == NULL) {
901 simple_unlock(&uihashtbl_slock);
902 newuip = malloc(sizeof(*uip), M_PROC, M_WAITOK | M_ZERO);
903 goto again;
904 }
905 uip = newuip;
906
907 LIST_INSERT_HEAD(uipp, uip, ui_hash);
908 uip->ui_uid = uid;
909 simple_lock_init(&uip->ui_slock);
910 simple_unlock(&uihashtbl_slock);
911
912 return uip;
913 }
914
915 /*
916 * Change the count associated with number of processes
917 * a given user is using.
918 */
919 int
920 chgproccnt(uid_t uid, int diff)
921 {
922 struct uidinfo *uip;
923 int s;
924
925 if (diff == 0)
926 return 0;
927
928 uip = uid_find(uid);
929 UILOCK(uip, s);
930 uip->ui_proccnt += diff;
931 KASSERT(uip->ui_proccnt >= 0);
932 UIUNLOCK(uip, s);
933 return uip->ui_proccnt;
934 }
935
936 int
937 chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t xmax)
938 {
939 rlim_t nsb;
940 int s;
941
942 UILOCK(uip, s);
943 nsb = uip->ui_sbsize + to - *hiwat;
944 if (to > *hiwat && nsb > xmax) {
945 UIUNLOCK(uip, s);
946 splx(s);
947 return 0;
948 }
949 *hiwat = to;
950 uip->ui_sbsize = nsb;
951 KASSERT(uip->ui_sbsize >= 0);
952 UIUNLOCK(uip, s);
953 return 1;
954 }
955