kern_resource.c revision 1.154.2.1 1 /* $NetBSD: kern_resource.c,v 1.154.2.1 2010/04/30 14:44:10 uebayasi 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.154.2.1 2010/04/30 14:44:10 uebayasi 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/kmem.h>
49 #include <sys/namei.h>
50 #include <sys/pool.h>
51 #include <sys/proc.h>
52 #include <sys/sysctl.h>
53 #include <sys/timevar.h>
54 #include <sys/kauth.h>
55 #include <sys/atomic.h>
56 #include <sys/mount.h>
57 #include <sys/syscallargs.h>
58 #include <sys/atomic.h>
59
60 #include <uvm/uvm_extern.h>
61
62 /*
63 * Maximum process data and stack limits.
64 * They are variables so they are patchable.
65 */
66 rlim_t maxdmap = MAXDSIZ;
67 rlim_t maxsmap = MAXSSIZ;
68
69 static pool_cache_t plimit_cache;
70 static pool_cache_t pstats_cache;
71
72 static kauth_listener_t resource_listener;
73
74 static int
75 resource_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
76 void *arg0, void *arg1, void *arg2, void *arg3)
77 {
78 struct proc *p;
79 int result;
80
81 result = KAUTH_RESULT_DEFER;
82 p = arg0;
83
84 switch (action) {
85 case KAUTH_PROCESS_NICE:
86 if (kauth_cred_geteuid(cred) != kauth_cred_geteuid(p->p_cred) &&
87 kauth_cred_getuid(cred) != kauth_cred_geteuid(p->p_cred)) {
88 break;
89 }
90
91 if ((u_long)arg1 >= p->p_nice)
92 result = KAUTH_RESULT_ALLOW;
93
94 break;
95
96 case KAUTH_PROCESS_RLIMIT: {
97 enum kauth_process_req req;
98
99 req = (enum kauth_process_req)(unsigned long)arg1;
100
101 switch (req) {
102 case KAUTH_REQ_PROCESS_RLIMIT_GET:
103 result = KAUTH_RESULT_ALLOW;
104 break;
105
106 case KAUTH_REQ_PROCESS_RLIMIT_SET: {
107 struct rlimit *new_rlimit;
108 u_long which;
109
110 if ((p != curlwp->l_proc) &&
111 (proc_uidmatch(cred, p->p_cred) != 0))
112 break;
113
114 new_rlimit = arg2;
115 which = (u_long)arg3;
116
117 if (new_rlimit->rlim_max <= p->p_rlimit[which].rlim_max)
118 result = KAUTH_RESULT_ALLOW;
119
120 break;
121 }
122
123 default:
124 break;
125 }
126
127 break;
128 }
129
130 default:
131 break;
132 }
133
134 return result;
135 }
136
137 void
138 resource_init(void)
139 {
140
141 plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0,
142 "plimitpl", NULL, IPL_NONE, NULL, NULL, NULL);
143 pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0,
144 "pstatspl", NULL, IPL_NONE, NULL, NULL, NULL);
145
146 resource_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
147 resource_listener_cb, NULL);
148 }
149
150 /*
151 * Resource controls and accounting.
152 */
153
154 int
155 sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap,
156 register_t *retval)
157 {
158 /* {
159 syscallarg(int) which;
160 syscallarg(id_t) who;
161 } */
162 struct proc *curp = l->l_proc, *p;
163 int low = NZERO + PRIO_MAX + 1;
164 int who = SCARG(uap, who);
165
166 mutex_enter(proc_lock);
167 switch (SCARG(uap, which)) {
168 case PRIO_PROCESS:
169 if (who == 0)
170 p = curp;
171 else
172 p = p_find(who, PFIND_LOCKED);
173 if (p != NULL)
174 low = p->p_nice;
175 break;
176
177 case PRIO_PGRP: {
178 struct pgrp *pg;
179
180 if (who == 0)
181 pg = curp->p_pgrp;
182 else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
183 break;
184 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
185 if (p->p_nice < low)
186 low = p->p_nice;
187 }
188 break;
189 }
190
191 case PRIO_USER:
192 if (who == 0)
193 who = (int)kauth_cred_geteuid(l->l_cred);
194 PROCLIST_FOREACH(p, &allproc) {
195 mutex_enter(p->p_lock);
196 if (kauth_cred_geteuid(p->p_cred) ==
197 (uid_t)who && p->p_nice < low)
198 low = p->p_nice;
199 mutex_exit(p->p_lock);
200 }
201 break;
202
203 default:
204 mutex_exit(proc_lock);
205 return (EINVAL);
206 }
207 mutex_exit(proc_lock);
208
209 if (low == NZERO + PRIO_MAX + 1)
210 return (ESRCH);
211 *retval = low - NZERO;
212 return (0);
213 }
214
215 /* ARGSUSED */
216 int
217 sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap,
218 register_t *retval)
219 {
220 /* {
221 syscallarg(int) which;
222 syscallarg(id_t) who;
223 syscallarg(int) prio;
224 } */
225 struct proc *curp = l->l_proc, *p;
226 int found = 0, error = 0;
227 int who = SCARG(uap, who);
228
229 mutex_enter(proc_lock);
230 switch (SCARG(uap, which)) {
231 case PRIO_PROCESS:
232 if (who == 0)
233 p = curp;
234 else
235 p = p_find(who, PFIND_LOCKED);
236 if (p != 0) {
237 mutex_enter(p->p_lock);
238 error = donice(l, p, SCARG(uap, prio));
239 mutex_exit(p->p_lock);
240 found++;
241 }
242 break;
243
244 case PRIO_PGRP: {
245 struct pgrp *pg;
246
247 if (who == 0)
248 pg = curp->p_pgrp;
249 else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
250 break;
251 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
252 mutex_enter(p->p_lock);
253 error = donice(l, p, SCARG(uap, prio));
254 mutex_exit(p->p_lock);
255 found++;
256 }
257 break;
258 }
259
260 case PRIO_USER:
261 if (who == 0)
262 who = (int)kauth_cred_geteuid(l->l_cred);
263 PROCLIST_FOREACH(p, &allproc) {
264 mutex_enter(p->p_lock);
265 if (kauth_cred_geteuid(p->p_cred) ==
266 (uid_t)SCARG(uap, who)) {
267 error = donice(l, p, SCARG(uap, prio));
268 found++;
269 }
270 mutex_exit(p->p_lock);
271 }
272 break;
273
274 default:
275 mutex_exit(proc_lock);
276 return EINVAL;
277 }
278 mutex_exit(proc_lock);
279 if (found == 0)
280 return (ESRCH);
281 return (error);
282 }
283
284 /*
285 * Renice a process.
286 *
287 * Call with the target process' credentials locked.
288 */
289 int
290 donice(struct lwp *l, struct proc *chgp, int n)
291 {
292 kauth_cred_t cred = l->l_cred;
293
294 KASSERT(mutex_owned(chgp->p_lock));
295
296 if (kauth_cred_geteuid(cred) && kauth_cred_getuid(cred) &&
297 kauth_cred_geteuid(cred) != kauth_cred_geteuid(chgp->p_cred) &&
298 kauth_cred_getuid(cred) != kauth_cred_geteuid(chgp->p_cred))
299 return (EPERM);
300
301 if (n > PRIO_MAX)
302 n = PRIO_MAX;
303 if (n < PRIO_MIN)
304 n = PRIO_MIN;
305 n += NZERO;
306 if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp,
307 KAUTH_ARG(n), NULL, NULL))
308 return (EACCES);
309 sched_nice(chgp, n);
310 return (0);
311 }
312
313 /* ARGSUSED */
314 int
315 sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap,
316 register_t *retval)
317 {
318 /* {
319 syscallarg(int) which;
320 syscallarg(const struct rlimit *) rlp;
321 } */
322 int which = SCARG(uap, which);
323 struct rlimit alim;
324 int error;
325
326 error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
327 if (error)
328 return (error);
329 return (dosetrlimit(l, l->l_proc, which, &alim));
330 }
331
332 int
333 dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
334 {
335 struct rlimit *alimp;
336 int error;
337
338 if ((u_int)which >= RLIM_NLIMITS)
339 return (EINVAL);
340
341 if (limp->rlim_cur > limp->rlim_max) {
342 /*
343 * This is programming error. According to SUSv2, we should
344 * return error in this case.
345 */
346 return (EINVAL);
347 }
348
349 alimp = &p->p_rlimit[which];
350 /* if we don't change the value, no need to limcopy() */
351 if (limp->rlim_cur == alimp->rlim_cur &&
352 limp->rlim_max == alimp->rlim_max)
353 return 0;
354
355 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
356 p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which));
357 if (error)
358 return (error);
359
360 lim_privatise(p, false);
361 /* p->p_limit is now unchangeable */
362 alimp = &p->p_rlimit[which];
363
364 switch (which) {
365
366 case RLIMIT_DATA:
367 if (limp->rlim_cur > maxdmap)
368 limp->rlim_cur = maxdmap;
369 if (limp->rlim_max > maxdmap)
370 limp->rlim_max = maxdmap;
371 break;
372
373 case RLIMIT_STACK:
374 if (limp->rlim_cur > maxsmap)
375 limp->rlim_cur = maxsmap;
376 if (limp->rlim_max > maxsmap)
377 limp->rlim_max = maxsmap;
378
379 /*
380 * Return EINVAL if the new stack size limit is lower than
381 * current usage. Otherwise, the process would get SIGSEGV the
382 * moment it would try to access anything on it's current stack.
383 * This conforms to SUSv2.
384 */
385 if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE
386 || limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) {
387 return (EINVAL);
388 }
389
390 /*
391 * Stack is allocated to the max at exec time with
392 * only "rlim_cur" bytes accessible (In other words,
393 * allocates stack dividing two contiguous regions at
394 * "rlim_cur" bytes boundary).
395 *
396 * Since allocation is done in terms of page, roundup
397 * "rlim_cur" (otherwise, contiguous regions
398 * overlap). If stack limit is going up make more
399 * accessible, if going down make inaccessible.
400 */
401 limp->rlim_cur = round_page(limp->rlim_cur);
402 if (limp->rlim_cur != alimp->rlim_cur) {
403 vaddr_t addr;
404 vsize_t size;
405 vm_prot_t prot;
406
407 if (limp->rlim_cur > alimp->rlim_cur) {
408 prot = VM_PROT_READ | VM_PROT_WRITE;
409 size = limp->rlim_cur - alimp->rlim_cur;
410 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
411 limp->rlim_cur;
412 } else {
413 prot = VM_PROT_NONE;
414 size = alimp->rlim_cur - limp->rlim_cur;
415 addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
416 alimp->rlim_cur;
417 }
418 (void) uvm_map_protect(&p->p_vmspace->vm_map,
419 addr, addr+size, prot, false);
420 }
421 break;
422
423 case RLIMIT_NOFILE:
424 if (limp->rlim_cur > maxfiles)
425 limp->rlim_cur = maxfiles;
426 if (limp->rlim_max > maxfiles)
427 limp->rlim_max = maxfiles;
428 break;
429
430 case RLIMIT_NPROC:
431 if (limp->rlim_cur > maxproc)
432 limp->rlim_cur = maxproc;
433 if (limp->rlim_max > maxproc)
434 limp->rlim_max = maxproc;
435 break;
436 }
437
438 mutex_enter(&p->p_limit->pl_lock);
439 *alimp = *limp;
440 mutex_exit(&p->p_limit->pl_lock);
441 return (0);
442 }
443
444 /* ARGSUSED */
445 int
446 sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap,
447 register_t *retval)
448 {
449 /* {
450 syscallarg(int) which;
451 syscallarg(struct rlimit *) rlp;
452 } */
453 struct proc *p = l->l_proc;
454 int which = SCARG(uap, which);
455 struct rlimit rl;
456
457 if ((u_int)which >= RLIM_NLIMITS)
458 return (EINVAL);
459
460 mutex_enter(p->p_lock);
461 memcpy(&rl, &p->p_rlimit[which], sizeof(rl));
462 mutex_exit(p->p_lock);
463
464 return copyout(&rl, SCARG(uap, rlp), sizeof(rl));
465 }
466
467 /*
468 * Transform the running time and tick information in proc p into user,
469 * system, and interrupt time usage.
470 *
471 * Should be called with p->p_lock held unless called from exit1().
472 */
473 void
474 calcru(struct proc *p, struct timeval *up, struct timeval *sp,
475 struct timeval *ip, struct timeval *rp)
476 {
477 uint64_t u, st, ut, it, tot;
478 struct lwp *l;
479 struct bintime tm;
480 struct timeval tv;
481
482 mutex_spin_enter(&p->p_stmutex);
483 st = p->p_sticks;
484 ut = p->p_uticks;
485 it = p->p_iticks;
486 mutex_spin_exit(&p->p_stmutex);
487
488 tm = p->p_rtime;
489
490 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
491 lwp_lock(l);
492 bintime_add(&tm, &l->l_rtime);
493 if ((l->l_pflag & LP_RUNNING) != 0) {
494 struct bintime diff;
495 /*
496 * Adjust for the current time slice. This is
497 * actually fairly important since the error
498 * here is on the order of a time quantum,
499 * which is much greater than the sampling
500 * error.
501 */
502 binuptime(&diff);
503 bintime_sub(&diff, &l->l_stime);
504 bintime_add(&tm, &diff);
505 }
506 lwp_unlock(l);
507 }
508
509 tot = st + ut + it;
510 bintime2timeval(&tm, &tv);
511 u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec;
512
513 if (tot == 0) {
514 /* No ticks, so can't use to share time out, split 50-50 */
515 st = ut = u / 2;
516 } else {
517 st = (u * st) / tot;
518 ut = (u * ut) / tot;
519 }
520 if (sp != NULL) {
521 sp->tv_sec = st / 1000000;
522 sp->tv_usec = st % 1000000;
523 }
524 if (up != NULL) {
525 up->tv_sec = ut / 1000000;
526 up->tv_usec = ut % 1000000;
527 }
528 if (ip != NULL) {
529 if (it != 0)
530 it = (u * it) / tot;
531 ip->tv_sec = it / 1000000;
532 ip->tv_usec = it % 1000000;
533 }
534 if (rp != NULL) {
535 *rp = tv;
536 }
537 }
538
539 /* ARGSUSED */
540 int
541 sys___getrusage50(struct lwp *l, const struct sys___getrusage50_args *uap,
542 register_t *retval)
543 {
544 /* {
545 syscallarg(int) who;
546 syscallarg(struct rusage *) rusage;
547 } */
548 struct rusage ru;
549 struct proc *p = l->l_proc;
550
551 switch (SCARG(uap, who)) {
552 case RUSAGE_SELF:
553 mutex_enter(p->p_lock);
554 memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
555 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
556 rulwps(p, &ru);
557 mutex_exit(p->p_lock);
558 break;
559
560 case RUSAGE_CHILDREN:
561 mutex_enter(p->p_lock);
562 memcpy(&ru, &p->p_stats->p_cru, sizeof(ru));
563 mutex_exit(p->p_lock);
564 break;
565
566 default:
567 return EINVAL;
568 }
569
570 return copyout(&ru, SCARG(uap, rusage), sizeof(ru));
571 }
572
573 void
574 ruadd(struct rusage *ru, struct rusage *ru2)
575 {
576 long *ip, *ip2;
577 int i;
578
579 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
580 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
581 if (ru->ru_maxrss < ru2->ru_maxrss)
582 ru->ru_maxrss = ru2->ru_maxrss;
583 ip = &ru->ru_first; ip2 = &ru2->ru_first;
584 for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
585 *ip++ += *ip2++;
586 }
587
588 void
589 rulwps(proc_t *p, struct rusage *ru)
590 {
591 lwp_t *l;
592
593 KASSERT(mutex_owned(p->p_lock));
594
595 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
596 ruadd(ru, &l->l_ru);
597 ru->ru_nvcsw += (l->l_ncsw - l->l_nivcsw);
598 ru->ru_nivcsw += l->l_nivcsw;
599 }
600 }
601
602 /*
603 * Make a copy of the plimit structure.
604 * We share these structures copy-on-write after fork,
605 * and copy when a limit is changed.
606 *
607 * Unfortunately (due to PL_SHAREMOD) it is possibly for the structure
608 * we are copying to change beneath our feet!
609 */
610 struct plimit *
611 lim_copy(struct plimit *lim)
612 {
613 struct plimit *newlim;
614 char *corename;
615 size_t alen, len;
616
617 newlim = pool_cache_get(plimit_cache, PR_WAITOK);
618 mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
619 newlim->pl_flags = 0;
620 newlim->pl_refcnt = 1;
621 newlim->pl_sv_limit = NULL;
622
623 mutex_enter(&lim->pl_lock);
624 memcpy(newlim->pl_rlimit, lim->pl_rlimit,
625 sizeof(struct rlimit) * RLIM_NLIMITS);
626
627 alen = 0;
628 corename = NULL;
629 for (;;) {
630 if (lim->pl_corename == defcorename) {
631 newlim->pl_corename = defcorename;
632 break;
633 }
634 len = strlen(lim->pl_corename) + 1;
635 if (len <= alen) {
636 newlim->pl_corename = corename;
637 memcpy(corename, lim->pl_corename, len);
638 corename = NULL;
639 break;
640 }
641 mutex_exit(&lim->pl_lock);
642 if (corename != NULL)
643 free(corename, M_TEMP);
644 alen = len;
645 corename = malloc(alen, M_TEMP, M_WAITOK);
646 mutex_enter(&lim->pl_lock);
647 }
648 mutex_exit(&lim->pl_lock);
649 if (corename != NULL)
650 free(corename, M_TEMP);
651 return newlim;
652 }
653
654 void
655 lim_addref(struct plimit *lim)
656 {
657 atomic_inc_uint(&lim->pl_refcnt);
658 }
659
660 /*
661 * Give a process it's own private plimit structure.
662 * This will only be shared (in fork) if modifications are to be shared.
663 */
664 void
665 lim_privatise(struct proc *p, bool set_shared)
666 {
667 struct plimit *lim, *newlim;
668
669 lim = p->p_limit;
670 if (lim->pl_flags & PL_WRITEABLE) {
671 if (set_shared)
672 lim->pl_flags |= PL_SHAREMOD;
673 return;
674 }
675
676 if (set_shared && lim->pl_flags & PL_SHAREMOD)
677 return;
678
679 newlim = lim_copy(lim);
680
681 mutex_enter(p->p_lock);
682 if (p->p_limit->pl_flags & PL_WRITEABLE) {
683 /* Someone crept in while we were busy */
684 mutex_exit(p->p_lock);
685 limfree(newlim);
686 if (set_shared)
687 p->p_limit->pl_flags |= PL_SHAREMOD;
688 return;
689 }
690
691 /*
692 * Since most accesses to p->p_limit aren't locked, we must not
693 * delete the old limit structure yet.
694 */
695 newlim->pl_sv_limit = p->p_limit;
696 newlim->pl_flags |= PL_WRITEABLE;
697 if (set_shared)
698 newlim->pl_flags |= PL_SHAREMOD;
699 p->p_limit = newlim;
700 mutex_exit(p->p_lock);
701 }
702
703 void
704 limfree(struct plimit *lim)
705 {
706 struct plimit *sv_lim;
707
708 do {
709 if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0)
710 return;
711 if (lim->pl_corename != defcorename)
712 free(lim->pl_corename, M_TEMP);
713 sv_lim = lim->pl_sv_limit;
714 mutex_destroy(&lim->pl_lock);
715 pool_cache_put(plimit_cache, lim);
716 } while ((lim = sv_lim) != NULL);
717 }
718
719 struct pstats *
720 pstatscopy(struct pstats *ps)
721 {
722
723 struct pstats *newps;
724
725 newps = pool_cache_get(pstats_cache, PR_WAITOK);
726
727 memset(&newps->pstat_startzero, 0,
728 (unsigned) ((char *)&newps->pstat_endzero -
729 (char *)&newps->pstat_startzero));
730 memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy,
731 ((char *)&newps->pstat_endcopy -
732 (char *)&newps->pstat_startcopy));
733
734 return (newps);
735
736 }
737
738 void
739 pstatsfree(struct pstats *ps)
740 {
741
742 pool_cache_put(pstats_cache, ps);
743 }
744
745 /*
746 * sysctl interface in five parts
747 */
748
749 /*
750 * a routine for sysctl proc subtree helpers that need to pick a valid
751 * process by pid.
752 */
753 static int
754 sysctl_proc_findproc(struct lwp *l, struct proc **p2, pid_t pid)
755 {
756 struct proc *ptmp;
757 int error = 0;
758
759 if (pid == PROC_CURPROC)
760 ptmp = l->l_proc;
761 else if ((ptmp = pfind(pid)) == NULL)
762 error = ESRCH;
763
764 *p2 = ptmp;
765 return (error);
766 }
767
768 /*
769 * sysctl helper routine for setting a process's specific corefile
770 * name. picks the process based on the given pid and checks the
771 * correctness of the new value.
772 */
773 static int
774 sysctl_proc_corename(SYSCTLFN_ARGS)
775 {
776 struct proc *ptmp;
777 struct plimit *lim;
778 int error = 0, len;
779 char *cname;
780 char *ocore;
781 char *tmp;
782 struct sysctlnode node;
783
784 /*
785 * is this all correct?
786 */
787 if (namelen != 0)
788 return (EINVAL);
789 if (name[-1] != PROC_PID_CORENAME)
790 return (EINVAL);
791
792 /*
793 * whom are we tweaking?
794 */
795 error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
796 if (error)
797 return (error);
798
799 /* XXX-elad */
800 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
801 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
802 if (error)
803 return (error);
804
805 if (newp == NULL) {
806 error = kauth_authorize_process(l->l_cred,
807 KAUTH_PROCESS_CORENAME, ptmp,
808 KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL);
809 if (error)
810 return (error);
811 }
812
813 /*
814 * let them modify a temporary copy of the core name
815 */
816 cname = PNBUF_GET();
817 lim = ptmp->p_limit;
818 mutex_enter(&lim->pl_lock);
819 strlcpy(cname, lim->pl_corename, MAXPATHLEN);
820 mutex_exit(&lim->pl_lock);
821
822 node = *rnode;
823 node.sysctl_data = cname;
824 error = sysctl_lookup(SYSCTLFN_CALL(&node));
825
826 /*
827 * if that failed, or they have nothing new to say, or we've
828 * heard it before...
829 */
830 if (error || newp == NULL)
831 goto done;
832 lim = ptmp->p_limit;
833 mutex_enter(&lim->pl_lock);
834 error = strcmp(cname, lim->pl_corename);
835 mutex_exit(&lim->pl_lock);
836 if (error == 0)
837 /* Unchanged */
838 goto done;
839
840 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CORENAME,
841 ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cname, NULL);
842 if (error)
843 return (error);
844
845 /*
846 * no error yet and cname now has the new core name in it.
847 * let's see if it looks acceptable. it must be either "core"
848 * or end in ".core" or "/core".
849 */
850 len = strlen(cname);
851 if (len < 4) {
852 error = EINVAL;
853 } else if (strcmp(cname + len - 4, "core") != 0) {
854 error = EINVAL;
855 } else if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') {
856 error = EINVAL;
857 }
858 if (error != 0) {
859 goto done;
860 }
861
862 /*
863 * hmm...looks good. now...where do we put it?
864 */
865 tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL);
866 if (tmp == NULL) {
867 error = ENOMEM;
868 goto done;
869 }
870 memcpy(tmp, cname, len + 1);
871
872 lim_privatise(ptmp, false);
873 lim = ptmp->p_limit;
874 mutex_enter(&lim->pl_lock);
875 ocore = lim->pl_corename;
876 lim->pl_corename = tmp;
877 mutex_exit(&lim->pl_lock);
878 if (ocore != defcorename)
879 free(ocore, M_TEMP);
880
881 done:
882 PNBUF_PUT(cname);
883 return error;
884 }
885
886 /*
887 * sysctl helper routine for checking/setting a process's stop flags,
888 * one for fork and one for exec.
889 */
890 static int
891 sysctl_proc_stop(SYSCTLFN_ARGS)
892 {
893 struct proc *ptmp;
894 int i, f, error = 0;
895 struct sysctlnode node;
896
897 if (namelen != 0)
898 return (EINVAL);
899
900 error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
901 if (error)
902 return (error);
903
904 /* XXX-elad */
905 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
906 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
907 if (error)
908 return (error);
909
910 switch (rnode->sysctl_num) {
911 case PROC_PID_STOPFORK:
912 f = PS_STOPFORK;
913 break;
914 case PROC_PID_STOPEXEC:
915 f = PS_STOPEXEC;
916 break;
917 case PROC_PID_STOPEXIT:
918 f = PS_STOPEXIT;
919 break;
920 default:
921 return (EINVAL);
922 }
923
924 i = (ptmp->p_flag & f) ? 1 : 0;
925 node = *rnode;
926 node.sysctl_data = &i;
927 error = sysctl_lookup(SYSCTLFN_CALL(&node));
928 if (error || newp == NULL)
929 return (error);
930
931 mutex_enter(ptmp->p_lock);
932 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG,
933 ptmp, KAUTH_ARG(f), NULL, NULL);
934 if (!error) {
935 if (i) {
936 ptmp->p_sflag |= f;
937 } else {
938 ptmp->p_sflag &= ~f;
939 }
940 }
941 mutex_exit(ptmp->p_lock);
942
943 return error;
944 }
945
946 /*
947 * sysctl helper routine for a process's rlimits as exposed by sysctl.
948 */
949 static int
950 sysctl_proc_plimit(SYSCTLFN_ARGS)
951 {
952 struct proc *ptmp;
953 u_int limitno;
954 int which, error = 0;
955 struct rlimit alim;
956 struct sysctlnode node;
957
958 if (namelen != 0)
959 return (EINVAL);
960
961 which = name[-1];
962 if (which != PROC_PID_LIMIT_TYPE_SOFT &&
963 which != PROC_PID_LIMIT_TYPE_HARD)
964 return (EINVAL);
965
966 limitno = name[-2] - 1;
967 if (limitno >= RLIM_NLIMITS)
968 return (EINVAL);
969
970 if (name[-3] != PROC_PID_LIMIT)
971 return (EINVAL);
972
973 error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-4]);
974 if (error)
975 return (error);
976
977 /* XXX-elad */
978 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
979 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
980 if (error)
981 return (error);
982
983 /* Check if we can view limits. */
984 if (newp == NULL) {
985 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
986 ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim,
987 KAUTH_ARG(which));
988 if (error)
989 return (error);
990 }
991
992 node = *rnode;
993 memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim));
994 if (which == PROC_PID_LIMIT_TYPE_HARD)
995 node.sysctl_data = &alim.rlim_max;
996 else
997 node.sysctl_data = &alim.rlim_cur;
998
999 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1000 if (error || newp == NULL)
1001 return (error);
1002
1003 return (dosetrlimit(l, ptmp, limitno, &alim));
1004 }
1005
1006 /*
1007 * and finally, the actually glue that sticks it to the tree
1008 */
1009 SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup")
1010 {
1011
1012 sysctl_createv(clog, 0, NULL, NULL,
1013 CTLFLAG_PERMANENT,
1014 CTLTYPE_NODE, "proc", NULL,
1015 NULL, 0, NULL, 0,
1016 CTL_PROC, CTL_EOL);
1017 sysctl_createv(clog, 0, NULL, NULL,
1018 CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
1019 CTLTYPE_NODE, "curproc",
1020 SYSCTL_DESCR("Per-process settings"),
1021 NULL, 0, NULL, 0,
1022 CTL_PROC, PROC_CURPROC, CTL_EOL);
1023
1024 sysctl_createv(clog, 0, NULL, NULL,
1025 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1026 CTLTYPE_STRING, "corename",
1027 SYSCTL_DESCR("Core file name"),
1028 sysctl_proc_corename, 0, NULL, MAXPATHLEN,
1029 CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
1030 sysctl_createv(clog, 0, NULL, NULL,
1031 CTLFLAG_PERMANENT,
1032 CTLTYPE_NODE, "rlimit",
1033 SYSCTL_DESCR("Process limits"),
1034 NULL, 0, NULL, 0,
1035 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
1036
1037 #define create_proc_plimit(s, n) do { \
1038 sysctl_createv(clog, 0, NULL, NULL, \
1039 CTLFLAG_PERMANENT, \
1040 CTLTYPE_NODE, s, \
1041 SYSCTL_DESCR("Process " s " limits"), \
1042 NULL, 0, NULL, 0, \
1043 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1044 CTL_EOL); \
1045 sysctl_createv(clog, 0, NULL, NULL, \
1046 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1047 CTLTYPE_QUAD, "soft", \
1048 SYSCTL_DESCR("Process soft " s " limit"), \
1049 sysctl_proc_plimit, 0, NULL, 0, \
1050 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1051 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \
1052 sysctl_createv(clog, 0, NULL, NULL, \
1053 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1054 CTLTYPE_QUAD, "hard", \
1055 SYSCTL_DESCR("Process hard " s " limit"), \
1056 sysctl_proc_plimit, 0, NULL, 0, \
1057 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1058 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \
1059 } while (0/*CONSTCOND*/)
1060
1061 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU);
1062 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE);
1063 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA);
1064 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK);
1065 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE);
1066 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS);
1067 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK);
1068 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC);
1069 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE);
1070 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE);
1071 create_proc_plimit("vmemoryuse", PROC_PID_LIMIT_AS);
1072
1073 #undef create_proc_plimit
1074
1075 sysctl_createv(clog, 0, NULL, NULL,
1076 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1077 CTLTYPE_INT, "stopfork",
1078 SYSCTL_DESCR("Stop process at fork(2)"),
1079 sysctl_proc_stop, 0, NULL, 0,
1080 CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
1081 sysctl_createv(clog, 0, NULL, NULL,
1082 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1083 CTLTYPE_INT, "stopexec",
1084 SYSCTL_DESCR("Stop process at execve(2)"),
1085 sysctl_proc_stop, 0, NULL, 0,
1086 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
1087 sysctl_createv(clog, 0, NULL, NULL,
1088 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
1089 CTLTYPE_INT, "stopexit",
1090 SYSCTL_DESCR("Stop process before completing exit"),
1091 sysctl_proc_stop, 0, NULL, 0,
1092 CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
1093 }
1094