1 /* $NetBSD: kern_resource.c,v 1.153 2009/10/02 22:38:45 elad Exp $ */
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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
36 * @(#)kern_resource.c 8.8 (Berkeley) 2/14/95
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.153 2009/10/02 22:38:45 elad Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/resourcevar.h>
47 #include <sys/malloc.h>
49 #include <sys/namei.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>
60 #include <uvm/uvm_extern.h>
63 * Maximum process data and stack limits.
64 * They are variables so they are patchable.
66 rlim_t maxdmap
= MAXDSIZ
;
67 rlim_t maxsmap
= MAXSSIZ
;
69 static pool_cache_t plimit_cache
;
70 static pool_cache_t pstats_cache
;
72 static kauth_listener_t resource_listener
;
75 resource_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
76 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
81 result
= KAUTH_RESULT_DEFER
;
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
)) {
91 if ((u_long
)arg1
>= p
->p_nice
)
92 result
= KAUTH_RESULT_ALLOW
;
96 case KAUTH_PROCESS_RLIMIT
: {
97 enum kauth_process_req req
;
99 req
= (enum kauth_process_req
)(unsigned long)arg1
;
102 case KAUTH_REQ_PROCESS_RLIMIT_GET
:
103 result
= KAUTH_RESULT_ALLOW
;
106 case KAUTH_REQ_PROCESS_RLIMIT_SET
: {
107 struct rlimit
*new_rlimit
;
110 if ((p
!= curlwp
->l_proc
) &&
111 (proc_uidmatch(cred
, p
->p_cred
) != 0))
115 which
= (u_long
)arg3
;
117 if (new_rlimit
->rlim_max
<= p
->p_rlimit
[which
].rlim_max
)
118 result
= KAUTH_RESULT_ALLOW
;
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
);
146 resource_listener
= kauth_listen_scope(KAUTH_SCOPE_PROCESS
,
147 resource_listener_cb
, NULL
);
151 * Resource controls and accounting.
155 sys_getpriority(struct lwp
*l
, const struct sys_getpriority_args
*uap
,
159 syscallarg(int) which;
160 syscallarg(id_t) who;
162 struct proc
*curp
= l
->l_proc
, *p
;
163 int low
= NZERO
+ PRIO_MAX
+ 1;
164 int who
= SCARG(uap
, who
);
166 mutex_enter(proc_lock
);
167 switch (SCARG(uap
, which
)) {
172 p
= p_find(who
, PFIND_LOCKED
);
182 else if ((pg
= pg_find(who
, PFIND_LOCKED
)) == NULL
)
184 LIST_FOREACH(p
, &pg
->pg_members
, p_pglist
) {
193 who
= (int)kauth_cred_geteuid(l
->l_cred
);
194 PROCLIST_FOREACH(p
, &allproc
) {
195 if ((p
->p_flag
& PK_MARKER
) != 0)
197 mutex_enter(p
->p_lock
);
198 if (kauth_cred_geteuid(p
->p_cred
) ==
199 (uid_t
)who
&& p
->p_nice
< low
)
201 mutex_exit(p
->p_lock
);
206 mutex_exit(proc_lock
);
209 mutex_exit(proc_lock
);
211 if (low
== NZERO
+ PRIO_MAX
+ 1)
213 *retval
= low
- NZERO
;
219 sys_setpriority(struct lwp
*l
, const struct sys_setpriority_args
*uap
,
223 syscallarg(int) which;
224 syscallarg(id_t) who;
225 syscallarg(int) prio;
227 struct proc
*curp
= l
->l_proc
, *p
;
228 int found
= 0, error
= 0;
229 int who
= SCARG(uap
, who
);
231 mutex_enter(proc_lock
);
232 switch (SCARG(uap
, which
)) {
237 p
= p_find(who
, PFIND_LOCKED
);
239 mutex_enter(p
->p_lock
);
240 error
= donice(l
, p
, SCARG(uap
, prio
));
241 mutex_exit(p
->p_lock
);
251 else if ((pg
= pg_find(who
, PFIND_LOCKED
)) == NULL
)
253 LIST_FOREACH(p
, &pg
->pg_members
, p_pglist
) {
254 mutex_enter(p
->p_lock
);
255 error
= donice(l
, p
, SCARG(uap
, prio
));
256 mutex_exit(p
->p_lock
);
264 who
= (int)kauth_cred_geteuid(l
->l_cred
);
265 PROCLIST_FOREACH(p
, &allproc
) {
266 if ((p
->p_flag
& PK_MARKER
) != 0)
268 mutex_enter(p
->p_lock
);
269 if (kauth_cred_geteuid(p
->p_cred
) ==
270 (uid_t
)SCARG(uap
, who
)) {
271 error
= donice(l
, p
, SCARG(uap
, prio
));
274 mutex_exit(p
->p_lock
);
279 mutex_exit(proc_lock
);
282 mutex_exit(proc_lock
);
291 * Call with the target process' credentials locked.
294 donice(struct lwp
*l
, struct proc
*chgp
, int n
)
296 kauth_cred_t cred
= l
->l_cred
;
298 KASSERT(mutex_owned(chgp
->p_lock
));
300 if (kauth_cred_geteuid(cred
) && kauth_cred_getuid(cred
) &&
301 kauth_cred_geteuid(cred
) != kauth_cred_geteuid(chgp
->p_cred
) &&
302 kauth_cred_getuid(cred
) != kauth_cred_geteuid(chgp
->p_cred
))
310 if (kauth_authorize_process(cred
, KAUTH_PROCESS_NICE
, chgp
,
311 KAUTH_ARG(n
), NULL
, NULL
))
319 sys_setrlimit(struct lwp
*l
, const struct sys_setrlimit_args
*uap
,
323 syscallarg(int) which;
324 syscallarg(const struct rlimit *) rlp;
326 int which
= SCARG(uap
, which
);
330 error
= copyin(SCARG(uap
, rlp
), &alim
, sizeof(struct rlimit
));
333 return (dosetrlimit(l
, l
->l_proc
, which
, &alim
));
337 dosetrlimit(struct lwp
*l
, struct proc
*p
, int which
, struct rlimit
*limp
)
339 struct rlimit
*alimp
;
342 if ((u_int
)which
>= RLIM_NLIMITS
)
345 if (limp
->rlim_cur
> limp
->rlim_max
) {
347 * This is programming error. According to SUSv2, we should
348 * return error in this case.
353 alimp
= &p
->p_rlimit
[which
];
354 /* if we don't change the value, no need to limcopy() */
355 if (limp
->rlim_cur
== alimp
->rlim_cur
&&
356 limp
->rlim_max
== alimp
->rlim_max
)
359 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_RLIMIT
,
360 p
, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET
), limp
, KAUTH_ARG(which
));
364 lim_privatise(p
, false);
365 /* p->p_limit is now unchangeable */
366 alimp
= &p
->p_rlimit
[which
];
371 if (limp
->rlim_cur
> maxdmap
)
372 limp
->rlim_cur
= maxdmap
;
373 if (limp
->rlim_max
> maxdmap
)
374 limp
->rlim_max
= maxdmap
;
378 if (limp
->rlim_cur
> maxsmap
)
379 limp
->rlim_cur
= maxsmap
;
380 if (limp
->rlim_max
> maxsmap
)
381 limp
->rlim_max
= maxsmap
;
384 * Return EINVAL if the new stack size limit is lower than
385 * current usage. Otherwise, the process would get SIGSEGV the
386 * moment it would try to access anything on it's current stack.
387 * This conforms to SUSv2.
389 if (limp
->rlim_cur
< p
->p_vmspace
->vm_ssize
* PAGE_SIZE
390 || limp
->rlim_max
< p
->p_vmspace
->vm_ssize
* PAGE_SIZE
) {
395 * Stack is allocated to the max at exec time with
396 * only "rlim_cur" bytes accessible (In other words,
397 * allocates stack dividing two contiguous regions at
398 * "rlim_cur" bytes boundary).
400 * Since allocation is done in terms of page, roundup
401 * "rlim_cur" (otherwise, contiguous regions
402 * overlap). If stack limit is going up make more
403 * accessible, if going down make inaccessible.
405 limp
->rlim_cur
= round_page(limp
->rlim_cur
);
406 if (limp
->rlim_cur
!= alimp
->rlim_cur
) {
411 if (limp
->rlim_cur
> alimp
->rlim_cur
) {
412 prot
= VM_PROT_READ
| VM_PROT_WRITE
;
413 size
= limp
->rlim_cur
- alimp
->rlim_cur
;
414 addr
= (vaddr_t
)p
->p_vmspace
->vm_minsaddr
-
418 size
= alimp
->rlim_cur
- limp
->rlim_cur
;
419 addr
= (vaddr_t
)p
->p_vmspace
->vm_minsaddr
-
422 (void) uvm_map_protect(&p
->p_vmspace
->vm_map
,
423 addr
, addr
+size
, prot
, false);
428 if (limp
->rlim_cur
> maxfiles
)
429 limp
->rlim_cur
= maxfiles
;
430 if (limp
->rlim_max
> maxfiles
)
431 limp
->rlim_max
= maxfiles
;
435 if (limp
->rlim_cur
> maxproc
)
436 limp
->rlim_cur
= maxproc
;
437 if (limp
->rlim_max
> maxproc
)
438 limp
->rlim_max
= maxproc
;
442 mutex_enter(&p
->p_limit
->pl_lock
);
444 mutex_exit(&p
->p_limit
->pl_lock
);
450 sys_getrlimit(struct lwp
*l
, const struct sys_getrlimit_args
*uap
,
454 syscallarg(int) which;
455 syscallarg(struct rlimit *) rlp;
457 struct proc
*p
= l
->l_proc
;
458 int which
= SCARG(uap
, which
);
461 if ((u_int
)which
>= RLIM_NLIMITS
)
464 mutex_enter(p
->p_lock
);
465 memcpy(&rl
, &p
->p_rlimit
[which
], sizeof(rl
));
466 mutex_exit(p
->p_lock
);
468 return copyout(&rl
, SCARG(uap
, rlp
), sizeof(rl
));
472 * Transform the running time and tick information in proc p into user,
473 * system, and interrupt time usage.
475 * Should be called with p->p_lock held unless called from exit1().
478 calcru(struct proc
*p
, struct timeval
*up
, struct timeval
*sp
,
479 struct timeval
*ip
, struct timeval
*rp
)
481 uint64_t u
, st
, ut
, it
, tot
;
486 mutex_spin_enter(&p
->p_stmutex
);
490 mutex_spin_exit(&p
->p_stmutex
);
494 LIST_FOREACH(l
, &p
->p_lwps
, l_sibling
) {
496 bintime_add(&tm
, &l
->l_rtime
);
497 if ((l
->l_pflag
& LP_RUNNING
) != 0) {
500 * Adjust for the current time slice. This is
501 * actually fairly important since the error
502 * here is on the order of a time quantum,
503 * which is much greater than the sampling
507 bintime_sub(&diff
, &l
->l_stime
);
508 bintime_add(&tm
, &diff
);
514 bintime2timeval(&tm
, &tv
);
515 u
= (uint64_t)tv
.tv_sec
* 1000000ul + tv
.tv_usec
;
518 /* No ticks, so can't use to share time out, split 50-50 */
525 sp
->tv_sec
= st
/ 1000000;
526 sp
->tv_usec
= st
% 1000000;
529 up
->tv_sec
= ut
/ 1000000;
530 up
->tv_usec
= ut
% 1000000;
535 ip
->tv_sec
= it
/ 1000000;
536 ip
->tv_usec
= it
% 1000000;
545 sys___getrusage50(struct lwp
*l
, const struct sys___getrusage50_args
*uap
,
550 syscallarg(struct rusage *) rusage;
553 struct proc
*p
= l
->l_proc
;
555 switch (SCARG(uap
, who
)) {
557 mutex_enter(p
->p_lock
);
558 memcpy(&ru
, &p
->p_stats
->p_ru
, sizeof(ru
));
559 calcru(p
, &ru
.ru_utime
, &ru
.ru_stime
, NULL
, NULL
);
561 mutex_exit(p
->p_lock
);
564 case RUSAGE_CHILDREN
:
565 mutex_enter(p
->p_lock
);
566 memcpy(&ru
, &p
->p_stats
->p_cru
, sizeof(ru
));
567 mutex_exit(p
->p_lock
);
574 return copyout(&ru
, SCARG(uap
, rusage
), sizeof(ru
));
578 ruadd(struct rusage
*ru
, struct rusage
*ru2
)
583 timeradd(&ru
->ru_utime
, &ru2
->ru_utime
, &ru
->ru_utime
);
584 timeradd(&ru
->ru_stime
, &ru2
->ru_stime
, &ru
->ru_stime
);
585 if (ru
->ru_maxrss
< ru2
->ru_maxrss
)
586 ru
->ru_maxrss
= ru2
->ru_maxrss
;
587 ip
= &ru
->ru_first
; ip2
= &ru2
->ru_first
;
588 for (i
= &ru
->ru_last
- &ru
->ru_first
; i
>= 0; i
--)
593 rulwps(proc_t
*p
, struct rusage
*ru
)
597 KASSERT(mutex_owned(p
->p_lock
));
599 LIST_FOREACH(l
, &p
->p_lwps
, l_sibling
) {
601 ru
->ru_nvcsw
+= (l
->l_ncsw
- l
->l_nivcsw
);
602 ru
->ru_nivcsw
+= l
->l_nivcsw
;
607 * Make a copy of the plimit structure.
608 * We share these structures copy-on-write after fork,
609 * and copy when a limit is changed.
611 * Unfortunately (due to PL_SHAREMOD) it is possibly for the structure
612 * we are copying to change beneath our feet!
615 lim_copy(struct plimit
*lim
)
617 struct plimit
*newlim
;
621 newlim
= pool_cache_get(plimit_cache
, PR_WAITOK
);
622 mutex_init(&newlim
->pl_lock
, MUTEX_DEFAULT
, IPL_NONE
);
623 newlim
->pl_flags
= 0;
624 newlim
->pl_refcnt
= 1;
625 newlim
->pl_sv_limit
= NULL
;
627 mutex_enter(&lim
->pl_lock
);
628 memcpy(newlim
->pl_rlimit
, lim
->pl_rlimit
,
629 sizeof(struct rlimit
) * RLIM_NLIMITS
);
634 if (lim
->pl_corename
== defcorename
) {
635 newlim
->pl_corename
= defcorename
;
638 len
= strlen(lim
->pl_corename
) + 1;
640 newlim
->pl_corename
= corename
;
641 memcpy(corename
, lim
->pl_corename
, len
);
645 mutex_exit(&lim
->pl_lock
);
646 if (corename
!= NULL
)
647 free(corename
, M_TEMP
);
649 corename
= malloc(alen
, M_TEMP
, M_WAITOK
);
650 mutex_enter(&lim
->pl_lock
);
652 mutex_exit(&lim
->pl_lock
);
653 if (corename
!= NULL
)
654 free(corename
, M_TEMP
);
659 lim_addref(struct plimit
*lim
)
661 atomic_inc_uint(&lim
->pl_refcnt
);
665 * Give a process it's own private plimit structure.
666 * This will only be shared (in fork) if modifications are to be shared.
669 lim_privatise(struct proc
*p
, bool set_shared
)
671 struct plimit
*lim
, *newlim
;
674 if (lim
->pl_flags
& PL_WRITEABLE
) {
676 lim
->pl_flags
|= PL_SHAREMOD
;
680 if (set_shared
&& lim
->pl_flags
& PL_SHAREMOD
)
683 newlim
= lim_copy(lim
);
685 mutex_enter(p
->p_lock
);
686 if (p
->p_limit
->pl_flags
& PL_WRITEABLE
) {
687 /* Someone crept in while we were busy */
688 mutex_exit(p
->p_lock
);
691 p
->p_limit
->pl_flags
|= PL_SHAREMOD
;
696 * Since most accesses to p->p_limit aren't locked, we must not
697 * delete the old limit structure yet.
699 newlim
->pl_sv_limit
= p
->p_limit
;
700 newlim
->pl_flags
|= PL_WRITEABLE
;
702 newlim
->pl_flags
|= PL_SHAREMOD
;
704 mutex_exit(p
->p_lock
);
708 limfree(struct plimit
*lim
)
710 struct plimit
*sv_lim
;
713 if (atomic_dec_uint_nv(&lim
->pl_refcnt
) > 0)
715 if (lim
->pl_corename
!= defcorename
)
716 free(lim
->pl_corename
, M_TEMP
);
717 sv_lim
= lim
->pl_sv_limit
;
718 mutex_destroy(&lim
->pl_lock
);
719 pool_cache_put(plimit_cache
, lim
);
720 } while ((lim
= sv_lim
) != NULL
);
724 pstatscopy(struct pstats
*ps
)
727 struct pstats
*newps
;
729 newps
= pool_cache_get(pstats_cache
, PR_WAITOK
);
731 memset(&newps
->pstat_startzero
, 0,
732 (unsigned) ((char *)&newps
->pstat_endzero
-
733 (char *)&newps
->pstat_startzero
));
734 memcpy(&newps
->pstat_startcopy
, &ps
->pstat_startcopy
,
735 ((char *)&newps
->pstat_endcopy
-
736 (char *)&newps
->pstat_startcopy
));
743 pstatsfree(struct pstats
*ps
)
746 pool_cache_put(pstats_cache
, ps
);
750 * sysctl interface in five parts
754 * a routine for sysctl proc subtree helpers that need to pick a valid
758 sysctl_proc_findproc(struct lwp
*l
, struct proc
**p2
, pid_t pid
)
763 if (pid
== PROC_CURPROC
)
765 else if ((ptmp
= pfind(pid
)) == NULL
)
773 * sysctl helper routine for setting a process's specific corefile
774 * name. picks the process based on the given pid and checks the
775 * correctness of the new value.
778 sysctl_proc_corename(SYSCTLFN_ARGS
)
786 struct sysctlnode node
;
789 * is this all correct?
793 if (name
[-1] != PROC_PID_CORENAME
)
797 * whom are we tweaking?
799 error
= sysctl_proc_findproc(l
, &ptmp
, (pid_t
)name
[-2]);
804 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_CANSEE
, ptmp
,
805 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY
), NULL
, NULL
);
810 error
= kauth_authorize_process(l
->l_cred
,
811 KAUTH_PROCESS_CORENAME
, ptmp
,
812 KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET
), NULL
, NULL
);
818 * let them modify a temporary copy of the core name
822 mutex_enter(&lim
->pl_lock
);
823 strlcpy(cname
, lim
->pl_corename
, MAXPATHLEN
);
824 mutex_exit(&lim
->pl_lock
);
827 node
.sysctl_data
= cname
;
828 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
831 * if that failed, or they have nothing new to say, or we've
834 if (error
|| newp
== NULL
)
837 mutex_enter(&lim
->pl_lock
);
838 error
= strcmp(cname
, lim
->pl_corename
);
839 mutex_exit(&lim
->pl_lock
);
844 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_CORENAME
,
845 ptmp
, KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET
), cname
, NULL
);
850 * no error yet and cname now has the new core name in it.
851 * let's see if it looks acceptable. it must be either "core"
852 * or end in ".core" or "/core".
857 } else if (strcmp(cname
+ len
- 4, "core") != 0) {
859 } else if (len
> 4 && cname
[len
- 5] != '/' && cname
[len
- 5] != '.') {
867 * hmm...looks good. now...where do we put it?
869 tmp
= malloc(len
+ 1, M_TEMP
, M_WAITOK
|M_CANFAIL
);
874 memcpy(tmp
, cname
, len
+ 1);
876 lim_privatise(ptmp
, false);
878 mutex_enter(&lim
->pl_lock
);
879 ocore
= lim
->pl_corename
;
880 lim
->pl_corename
= tmp
;
881 mutex_exit(&lim
->pl_lock
);
882 if (ocore
!= defcorename
)
891 * sysctl helper routine for checking/setting a process's stop flags,
892 * one for fork and one for exec.
895 sysctl_proc_stop(SYSCTLFN_ARGS
)
899 struct sysctlnode node
;
904 error
= sysctl_proc_findproc(l
, &ptmp
, (pid_t
)name
[-2]);
909 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_CANSEE
, ptmp
,
910 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY
), NULL
, NULL
);
914 switch (rnode
->sysctl_num
) {
915 case PROC_PID_STOPFORK
:
918 case PROC_PID_STOPEXEC
:
921 case PROC_PID_STOPEXIT
:
928 i
= (ptmp
->p_flag
& f
) ? 1 : 0;
930 node
.sysctl_data
= &i
;
931 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
932 if (error
|| newp
== NULL
)
935 mutex_enter(ptmp
->p_lock
);
936 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_STOPFLAG
,
937 ptmp
, KAUTH_ARG(f
), NULL
, NULL
);
945 mutex_exit(ptmp
->p_lock
);
951 * sysctl helper routine for a process's rlimits as exposed by sysctl.
954 sysctl_proc_plimit(SYSCTLFN_ARGS
)
958 int which
, error
= 0;
960 struct sysctlnode node
;
966 if (which
!= PROC_PID_LIMIT_TYPE_SOFT
&&
967 which
!= PROC_PID_LIMIT_TYPE_HARD
)
970 limitno
= name
[-2] - 1;
971 if (limitno
>= RLIM_NLIMITS
)
974 if (name
[-3] != PROC_PID_LIMIT
)
977 error
= sysctl_proc_findproc(l
, &ptmp
, (pid_t
)name
[-4]);
982 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_CANSEE
, ptmp
,
983 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY
), NULL
, NULL
);
987 /* Check if we can view limits. */
989 error
= kauth_authorize_process(l
->l_cred
, KAUTH_PROCESS_RLIMIT
,
990 ptmp
, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET
), &alim
,
997 memcpy(&alim
, &ptmp
->p_rlimit
[limitno
], sizeof(alim
));
998 if (which
== PROC_PID_LIMIT_TYPE_HARD
)
999 node
.sysctl_data
= &alim
.rlim_max
;
1001 node
.sysctl_data
= &alim
.rlim_cur
;
1003 error
= sysctl_lookup(SYSCTLFN_CALL(&node
));
1004 if (error
|| newp
== NULL
)
1007 return (dosetrlimit(l
, ptmp
, limitno
, &alim
));
1011 * and finally, the actually glue that sticks it to the tree
1013 SYSCTL_SETUP(sysctl_proc_setup
, "sysctl proc subtree setup")
1016 sysctl_createv(clog
, 0, NULL
, NULL
,
1018 CTLTYPE_NODE
, "proc", NULL
,
1021 sysctl_createv(clog
, 0, NULL
, NULL
,
1022 CTLFLAG_PERMANENT
|CTLFLAG_ANYNUMBER
,
1023 CTLTYPE_NODE
, "curproc",
1024 SYSCTL_DESCR("Per-process settings"),
1026 CTL_PROC
, PROC_CURPROC
, CTL_EOL
);
1028 sysctl_createv(clog
, 0, NULL
, NULL
,
1029 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
|CTLFLAG_ANYWRITE
,
1030 CTLTYPE_STRING
, "corename",
1031 SYSCTL_DESCR("Core file name"),
1032 sysctl_proc_corename
, 0, NULL
, MAXPATHLEN
,
1033 CTL_PROC
, PROC_CURPROC
, PROC_PID_CORENAME
, CTL_EOL
);
1034 sysctl_createv(clog
, 0, NULL
, NULL
,
1036 CTLTYPE_NODE
, "rlimit",
1037 SYSCTL_DESCR("Process limits"),
1039 CTL_PROC
, PROC_CURPROC
, PROC_PID_LIMIT
, CTL_EOL
);
1041 #define create_proc_plimit(s, n) do { \
1042 sysctl_createv(clog, 0, NULL, NULL, \
1043 CTLFLAG_PERMANENT, \
1045 SYSCTL_DESCR("Process " s " limits"), \
1047 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1049 sysctl_createv(clog, 0, NULL, NULL, \
1050 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1051 CTLTYPE_QUAD, "soft", \
1052 SYSCTL_DESCR("Process soft " s " limit"), \
1053 sysctl_proc_plimit, 0, NULL, 0, \
1054 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1055 PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \
1056 sysctl_createv(clog, 0, NULL, NULL, \
1057 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
1058 CTLTYPE_QUAD, "hard", \
1059 SYSCTL_DESCR("Process hard " s " limit"), \
1060 sysctl_proc_plimit, 0, NULL, 0, \
1061 CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
1062 PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \
1063 } while (0/*CONSTCOND*/)
1065 create_proc_plimit("cputime", PROC_PID_LIMIT_CPU
);
1066 create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE
);
1067 create_proc_plimit("datasize", PROC_PID_LIMIT_DATA
);
1068 create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK
);
1069 create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE
);
1070 create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS
);
1071 create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK
);
1072 create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC
);
1073 create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE
);
1074 create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE
);
1075 create_proc_plimit("vmemoryuse", PROC_PID_LIMIT_AS
);
1077 #undef create_proc_plimit
1079 sysctl_createv(clog
, 0, NULL
, NULL
,
1080 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
|CTLFLAG_ANYWRITE
,
1081 CTLTYPE_INT
, "stopfork",
1082 SYSCTL_DESCR("Stop process at fork(2)"),
1083 sysctl_proc_stop
, 0, NULL
, 0,
1084 CTL_PROC
, PROC_CURPROC
, PROC_PID_STOPFORK
, CTL_EOL
);
1085 sysctl_createv(clog
, 0, NULL
, NULL
,
1086 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
|CTLFLAG_ANYWRITE
,
1087 CTLTYPE_INT
, "stopexec",
1088 SYSCTL_DESCR("Stop process at execve(2)"),
1089 sysctl_proc_stop
, 0, NULL
, 0,
1090 CTL_PROC
, PROC_CURPROC
, PROC_PID_STOPEXEC
, CTL_EOL
);
1091 sysctl_createv(clog
, 0, NULL
, NULL
,
1092 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
|CTLFLAG_ANYWRITE
,
1093 CTLTYPE_INT
, "stopexit",
1094 SYSCTL_DESCR("Stop process before completing exit"),
1095 sysctl_proc_stop
, 0, NULL
, 0,
1096 CTL_PROC
, PROC_CURPROC
, PROC_PID_STOPEXIT
, CTL_EOL
);