X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/de355530ae67247cbd0da700edb3a2a1dae884c2..4452a7af2eac33dbad800bcc91f2399d62c18f53:/bsd/kern/kern_resource.c diff --git a/bsd/kern/kern_resource.c b/bsd/kern/kern_resource.c index 5a41676e2..c12b5bbd8 100644 --- a/bsd/kern/kern_resource.c +++ b/bsd/kern/kern_resource.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ /*- @@ -62,45 +68,63 @@ #include #include +#include #include -#include +#include #include #include -#include +#include +#include #include -#include +#include +#include + +#include #include #include #include #include +#include #include -int donice __P((struct proc *curp, struct proc *chgp, int n)); -int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); +int donice(struct proc *curp, struct proc *chgp, int n); +int dosetrlimit(struct proc *p, u_int which, struct rlimit *limp); rlim_t maxdmap = MAXDSIZ; /* XXX */ rlim_t maxsmap = MAXSSIZ; /* XXX */ +/* + * Limits on the number of open files per process, and the number + * of child processes per process. + * + * Note: would be in kern/subr_param.c in FreeBSD. + */ +extern int maxprocperuid; /* max # of procs per user */ +int maxfilesperproc = OPEN_MAX; /* per-proc open files limit */ + +SYSCTL_INT( _kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW, + &maxprocperuid, 0, "Maximum processes allowed per userid" ); + +SYSCTL_INT( _kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW, + &maxfilesperproc, 0, "Maximum files allowed open per process" ); + + /* * Resource controls and accounting. */ -struct getpriority_args { - int which; - int who; -}; int -getpriority(curp, uap, retval) - struct proc *curp; - register struct getpriority_args *uap; - register_t *retval; +getpriority(struct proc *curp, struct getpriority_args *uap, register_t *retval) { register struct proc *p; register int low = PRIO_MAX + 1; + if (uap->who < 0) + return (EINVAL); + switch (uap->which) { case PRIO_PROCESS: @@ -129,9 +153,9 @@ getpriority(curp, uap, retval) case PRIO_USER: if (uap->who == 0) - uap->who = curp->p_ucred->cr_uid; + uap->who = kauth_cred_getuid(kauth_cred_get()); for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) - if (p->p_ucred->cr_uid == uap->who && + if (kauth_cred_getuid(p->p_ucred) == uap->who && p->p_nice < low) low = p->p_nice; break; @@ -145,21 +169,20 @@ getpriority(curp, uap, retval) return (0); } -struct setpriority_args { - int which; - int who; - int prio; -}; /* ARGSUSED */ int -setpriority(curp, uap, retval) - struct proc *curp; - register struct setpriority_args *uap; - register_t *retval; +setpriority(struct proc *curp, struct setpriority_args *uap, __unused register_t *retval) { register struct proc *p; int found = 0, error = 0; + AUDIT_ARG(cmd, uap->which); + AUDIT_ARG(owner, uap->who, 0); + AUDIT_ARG(value, uap->prio); + + if (uap->who < 0) + return (EINVAL); + switch (uap->which) { case PRIO_PROCESS: @@ -190,9 +213,9 @@ setpriority(curp, uap, retval) case PRIO_USER: if (uap->who == 0) - uap->who = curp->p_ucred->cr_uid; + uap->who = kauth_cred_getuid(kauth_cred_get()); for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) - if (p->p_ucred->cr_uid == uap->who) { + if (kauth_cred_getuid(p->p_ucred) == uap->who) { error = donice(curp, p, uap->prio); found++; } @@ -211,89 +234,33 @@ donice(curp, chgp, n) register struct proc *curp, *chgp; register int n; { - register struct pcred *pcred = curp->p_cred; + kauth_cred_t ucred = curp->p_ucred; - if (pcred->pc_ucred->cr_uid && pcred->p_ruid && - pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid && - pcred->p_ruid != chgp->p_ucred->cr_uid) + if (suser(ucred, NULL) && ucred->cr_ruid && + kauth_cred_getuid(ucred) != kauth_cred_getuid(chgp->p_ucred) && + ucred->cr_ruid != kauth_cred_getuid(chgp->p_ucred)) return (EPERM); if (n > PRIO_MAX) n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; - if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag)) + if (n < chgp->p_nice && suser(ucred, &curp->p_acflag)) return (EACCES); chgp->p_nice = n; (void)resetpriority(chgp); return (0); } -#if COMPAT_43 -struct osetrlimit_args { - u_int which; - struct ogetrlimit * rlp; -}; -/* ARGSUSED */ -int -osetrlimit(p, uap, retval) - struct proc *p; - struct osetrlimit_args *uap; - register_t *retval; -{ - struct orlimit olim; - struct rlimit lim; - int error; - if (error = copyin((caddr_t)uap->rlp, (caddr_t)&olim, - sizeof (struct orlimit))) - return (error); - lim.rlim_cur = olim.rlim_cur; - lim.rlim_max = olim.rlim_max; - return (dosetrlimit(p, uap->which, &lim)); -} - -struct ogetrlimit_args { - u_int which; - struct ogetrlimit * rlp; -}; -/* ARGSUSED */ -int -ogetrlimit(p, uap, retval) - struct proc *p; - struct ogetrlimit_args *uap; - register_t *retval; -{ - struct orlimit olim; - - if (uap->which >= RLIM_NLIMITS) - return (EINVAL); - olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; - if (olim.rlim_cur == -1) - olim.rlim_cur = 0x7fffffff; - olim.rlim_max = p->p_rlimit[uap->which].rlim_max; - if (olim.rlim_max == -1) - olim.rlim_max = 0x7fffffff; - return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, - sizeof(olim))); -} -#endif /* COMPAT_43 */ - -struct setrlimit_args { - u_int which; - struct rlimit * rlp; -}; /* ARGSUSED */ int -setrlimit(p, uap, retval) - struct proc *p; - register struct setrlimit_args *uap; - register_t *retval; +setrlimit(struct proc *p, register struct setrlimit_args *uap, __unused register_t *retval) { struct rlimit alim; int error; - if (error = copyin((caddr_t)uap->rlp, (caddr_t)&alim, - sizeof (struct rlimit))) + if ((error = copyin(uap->rlp, (caddr_t)&alim, + sizeof (struct rlimit)))) return (error); return (dosetrlimit(p, uap->which, &alim)); } @@ -305,7 +272,6 @@ dosetrlimit(p, which, limp) struct rlimit *limp; { register struct rlimit *alimp; - extern rlim_t maxdmap, maxsmap; int error; if (which >= RLIM_NLIMITS) @@ -313,7 +279,7 @@ dosetrlimit(p, which, limp) alimp = &p->p_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) - if (error = suser(p->p_ucred, &p->p_acflag)) + if ((error = suser(kauth_cred_get(), &p->p_acflag))) return (error); if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; @@ -344,24 +310,24 @@ dosetrlimit(p, which, limp) * up make more accessible, if going down make inaccessible. */ if (limp->rlim_cur != alimp->rlim_cur) { - vm_offset_t addr; - vm_size_t size; - vm_prot_t prot; + user_addr_t addr; + user_size_t size; if (limp->rlim_cur > alimp->rlim_cur) { /* grow stack */ - size = round_page(limp->rlim_cur); - size -= round_page(alimp->rlim_cur); + size = round_page_64(limp->rlim_cur); + size -= round_page_64(alimp->rlim_cur); #if STACK_GROWTH_UP /* go to top of current stack */ - addr = trunc_page(p->user_stack + alimp->rlim_cur); + addr = p->user_stack + alimp->rlim_cur; #else STACK_GROWTH_UP - addr = trunc_page(p->user_stack - alimp->rlim_cur); + addr = p->user_stack - alimp->rlim_cur; addr -= size; #endif /* STACK_GROWTH_UP */ - if (vm_allocate(current_map(), - &addr, size, FALSE) != KERN_SUCCESS) + if (mach_vm_allocate(current_map(), + &addr, size, + VM_FLAGS_FIXED) != KERN_SUCCESS) return(EINVAL); } else { /* shrink stack */ @@ -370,59 +336,56 @@ dosetrlimit(p, which, limp) break; case RLIMIT_NOFILE: - /* - * Only root can get the maxfiles limits, as it is systemwide resource - */ - if (is_suser()) { + /* + * Only root can set the maxfiles limits, as it is systemwide resource + */ + if ( is_suser() ) { if (limp->rlim_cur > maxfiles) limp->rlim_cur = maxfiles; if (limp->rlim_max > maxfiles) limp->rlim_max = maxfiles; - } else { - if (limp->rlim_cur > OPEN_MAX) - limp->rlim_cur = OPEN_MAX; - if (limp->rlim_max > OPEN_MAX) - limp->rlim_max = OPEN_MAX; + } + else { + if (limp->rlim_cur > maxfilesperproc) + limp->rlim_cur = maxfilesperproc; + if (limp->rlim_max > maxfilesperproc) + limp->rlim_max = maxfilesperproc; } break; case RLIMIT_NPROC: - /* - * Only root can get the maxproc limits, as it is systemwide resource - */ - if (is_suser()) { + /* + * Only root can set to the maxproc limits, as it is + * systemwide resource; all others are limited to + * maxprocperuid (presumably less than maxproc). + */ + if ( is_suser() ) { if (limp->rlim_cur > maxproc) limp->rlim_cur = maxproc; if (limp->rlim_max > maxproc) limp->rlim_max = maxproc; - } else { - if (limp->rlim_cur > CHILD_MAX) - limp->rlim_cur = CHILD_MAX; - if (limp->rlim_max > CHILD_MAX) - limp->rlim_max = CHILD_MAX; + } + else { + if (limp->rlim_cur > maxprocperuid) + limp->rlim_cur = maxprocperuid; + if (limp->rlim_max > maxprocperuid) + limp->rlim_max = maxprocperuid; } break; - } + + } /* switch... */ *alimp = *limp; return (0); } -struct getrlimit_args { - u_int which; - struct rlimit * rlp; -}; /* ARGSUSED */ int -getrlimit(p, uap, retval) - struct proc *p; - register struct getrlimit_args *uap; - register_t *retval; +getrlimit(struct proc *p, register struct getrlimit_args *uap, __unused register_t *retval) { - if (uap->which >= RLIM_NLIMITS) return (EINVAL); return (copyout((caddr_t)&p->p_rlimit[uap->which], - (caddr_t)uap->rlp, sizeof (struct rlimit))); + uap->rlp, sizeof (struct rlimit))); } /* @@ -457,8 +420,8 @@ calcru(p, up, sp, ip) ut.tv_usec = tinfo.user_time.microseconds; st.tv_sec = tinfo.system_time.seconds; st.tv_usec = tinfo.system_time.microseconds; - timeradd(&ut,up,up); - timeradd(&st,up,up); + timeradd(&ut, up, up); + timeradd(&st, sp, sp); task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT; task_info(task, TASK_THREAD_TIMES_INFO, @@ -468,29 +431,27 @@ calcru(p, up, sp, ip) ut.tv_usec = ttimesinfo.user_time.microseconds; st.tv_sec = ttimesinfo.system_time.seconds; st.tv_usec = ttimesinfo.system_time.microseconds; - timeradd(&ut,up,up); - timeradd(&st,up,up); + timeradd(&ut, up, up); + timeradd(&st, sp, sp); } } -struct getrusage_args { - int who; - struct rusage * rusage; -}; +__private_extern__ void munge_rusage(struct rusage *a_rusage_p, struct user_rusage *a_user_rusage_p); + /* ARGSUSED */ int -getrusage(p, uap, retval) - register struct proc *p; - register struct getrusage_args *uap; - register_t *retval; +getrusage(register struct proc *p, register struct getrusage_args *uap, __unused register_t *retval) { struct rusage *rup, rubuf; + struct user_rusage rubuf64; + size_t retsize = sizeof(rubuf); /* default: 32 bits */ + caddr_t retbuf = (caddr_t)&rubuf; /* default: 32 bits */ switch (uap->who) { - case RUSAGE_SELF: rup = &p->p_stats->p_ru; calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); + // LP64todo: proc struct should have 64 bit version of struct rubuf = *rup; break; @@ -502,8 +463,12 @@ getrusage(p, uap, retval) default: return (EINVAL); } - return (copyout((caddr_t)&rubuf, (caddr_t)uap->rusage, - sizeof (struct rusage))); + if (IS_64BIT_PROCESS(p)) { + retsize = sizeof(rubuf64); + retbuf = (caddr_t)&rubuf64; + munge_rusage(&rubuf, &rubuf64); + } + return (copyout(retbuf, uap->rusage, retsize)); } void @@ -535,6 +500,8 @@ limcopy(lim) MALLOC_ZONE(copy, struct plimit *, sizeof(struct plimit), M_SUBPROC, M_WAITOK); + if (copy == NULL) + panic("limcopy"); bcopy(lim->pl_rlimit, copy->pl_rlimit, sizeof(struct rlimit) * RLIM_NLIMITS); copy->p_lflags = 0;