Home | History | Annotate | Line # | Download | only in kern
kern_resource.c revision 1.176.12.1
      1  1.176.12.1  pgoyette /*	$NetBSD: kern_resource.c,v 1.176.12.1 2018/04/16 02:00:07 pgoyette Exp $	*/
      2        1.20       cgd 
      3        1.17       cgd /*-
      4        1.19       cgd  * Copyright (c) 1982, 1986, 1991, 1993
      5        1.19       cgd  *	The Regents of the University of California.  All rights reserved.
      6        1.17       cgd  * (c) UNIX System Laboratories, Inc.
      7        1.17       cgd  * All or some portions of this file are derived from material licensed
      8        1.17       cgd  * to the University of California by American Telephone and Telegraph
      9        1.17       cgd  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     10        1.17       cgd  * the permission of UNIX System Laboratories, Inc.
     11        1.17       cgd  *
     12        1.17       cgd  * Redistribution and use in source and binary forms, with or without
     13        1.17       cgd  * modification, are permitted provided that the following conditions
     14        1.17       cgd  * are met:
     15        1.17       cgd  * 1. Redistributions of source code must retain the above copyright
     16        1.17       cgd  *    notice, this list of conditions and the following disclaimer.
     17        1.17       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     18        1.17       cgd  *    notice, this list of conditions and the following disclaimer in the
     19        1.17       cgd  *    documentation and/or other materials provided with the distribution.
     20        1.72       agc  * 3. Neither the name of the University nor the names of its contributors
     21        1.17       cgd  *    may be used to endorse or promote products derived from this software
     22        1.17       cgd  *    without specific prior written permission.
     23        1.17       cgd  *
     24        1.17       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25        1.17       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26        1.17       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27        1.17       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28        1.17       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29        1.17       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30        1.17       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31        1.17       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32        1.17       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33        1.17       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34        1.17       cgd  * SUCH DAMAGE.
     35        1.17       cgd  *
     36        1.45      fvdl  *	@(#)kern_resource.c	8.8 (Berkeley) 2/14/95
     37        1.17       cgd  */
     38        1.61     lukem 
     39        1.61     lukem #include <sys/cdefs.h>
     40  1.176.12.1  pgoyette __KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.176.12.1 2018/04/16 02:00:07 pgoyette Exp $");
     41        1.44       mrg 
     42        1.17       cgd #include <sys/param.h>
     43        1.22       cgd #include <sys/systm.h>
     44        1.17       cgd #include <sys/kernel.h>
     45        1.19       cgd #include <sys/file.h>
     46        1.17       cgd #include <sys/resourcevar.h>
     47       1.132      yamt #include <sys/kmem.h>
     48       1.100      yamt #include <sys/namei.h>
     49        1.49   thorpej #include <sys/pool.h>
     50        1.17       cgd #include <sys/proc.h>
     51        1.74    atatat #include <sys/sysctl.h>
     52       1.129      yamt #include <sys/timevar.h>
     53       1.101      elad #include <sys/kauth.h>
     54       1.125        ad #include <sys/atomic.h>
     55        1.22       cgd #include <sys/mount.h>
     56        1.22       cgd #include <sys/syscallargs.h>
     57       1.136        ad #include <sys/atomic.h>
     58        1.17       cgd 
     59        1.43       mrg #include <uvm/uvm_extern.h>
     60        1.43       mrg 
     61        1.17       cgd /*
     62        1.60       eeh  * Maximum process data and stack limits.
     63        1.60       eeh  * They are variables so they are patchable.
     64        1.60       eeh  */
     65       1.167     rmind rlim_t			maxdmap = MAXDSIZ;
     66       1.167     rmind rlim_t			maxsmap = MAXSSIZ;
     67        1.60       eeh 
     68       1.164     rmind static pool_cache_t	plimit_cache	__read_mostly;
     69       1.164     rmind static pool_cache_t	pstats_cache	__read_mostly;
     70       1.130        ad 
     71       1.154      elad static kauth_listener_t	resource_listener;
     72       1.164     rmind static struct sysctllog	*proc_sysctllog;
     73       1.153      elad 
     74       1.164     rmind static int	donice(struct lwp *, struct proc *, int);
     75       1.164     rmind static void	sysctl_proc_setup(void);
     76       1.156     pooka 
     77       1.153      elad static int
     78       1.154      elad resource_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
     79       1.153      elad     void *arg0, void *arg1, void *arg2, void *arg3)
     80       1.153      elad {
     81       1.153      elad 	struct proc *p;
     82       1.153      elad 	int result;
     83       1.153      elad 
     84       1.153      elad 	result = KAUTH_RESULT_DEFER;
     85       1.153      elad 	p = arg0;
     86       1.153      elad 
     87       1.154      elad 	switch (action) {
     88       1.154      elad 	case KAUTH_PROCESS_NICE:
     89       1.154      elad 		if (kauth_cred_geteuid(cred) != kauth_cred_geteuid(p->p_cred) &&
     90       1.164     rmind 		    kauth_cred_getuid(cred) != kauth_cred_geteuid(p->p_cred)) {
     91       1.164     rmind 			break;
     92       1.164     rmind 		}
     93       1.153      elad 
     94       1.164     rmind 		if ((u_long)arg1 >= p->p_nice)
     95       1.164     rmind 			result = KAUTH_RESULT_ALLOW;
     96       1.153      elad 
     97       1.154      elad 		break;
     98       1.154      elad 
     99       1.154      elad 	case KAUTH_PROCESS_RLIMIT: {
    100       1.154      elad 		enum kauth_process_req req;
    101       1.153      elad 
    102       1.154      elad 		req = (enum kauth_process_req)(unsigned long)arg1;
    103       1.153      elad 
    104       1.154      elad 		switch (req) {
    105       1.154      elad 		case KAUTH_REQ_PROCESS_RLIMIT_GET:
    106       1.153      elad 			result = KAUTH_RESULT_ALLOW;
    107       1.154      elad 			break;
    108       1.154      elad 
    109       1.154      elad 		case KAUTH_REQ_PROCESS_RLIMIT_SET: {
    110       1.154      elad 			struct rlimit *new_rlimit;
    111       1.154      elad 			u_long which;
    112       1.154      elad 
    113       1.154      elad 			if ((p != curlwp->l_proc) &&
    114       1.154      elad 			    (proc_uidmatch(cred, p->p_cred) != 0))
    115       1.154      elad 				break;
    116       1.154      elad 
    117       1.154      elad 			new_rlimit = arg2;
    118       1.154      elad 			which = (u_long)arg3;
    119       1.154      elad 
    120       1.154      elad 			if (new_rlimit->rlim_max <= p->p_rlimit[which].rlim_max)
    121       1.154      elad 				result = KAUTH_RESULT_ALLOW;
    122       1.154      elad 
    123       1.154      elad 			break;
    124       1.154      elad 			}
    125       1.154      elad 
    126       1.154      elad 		default:
    127       1.154      elad 			break;
    128       1.154      elad 		}
    129       1.154      elad 
    130       1.154      elad 		break;
    131       1.154      elad 	}
    132       1.154      elad 
    133       1.154      elad 	default:
    134       1.154      elad 		break;
    135       1.153      elad 	}
    136       1.153      elad 
    137       1.153      elad 	return result;
    138       1.153      elad }
    139       1.153      elad 
    140       1.130        ad void
    141       1.130        ad resource_init(void)
    142       1.130        ad {
    143       1.130        ad 
    144       1.130        ad 	plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0,
    145       1.130        ad 	    "plimitpl", NULL, IPL_NONE, NULL, NULL, NULL);
    146       1.130        ad 	pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0,
    147       1.130        ad 	    "pstatspl", NULL, IPL_NONE, NULL, NULL, NULL);
    148       1.153      elad 
    149       1.154      elad 	resource_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
    150       1.154      elad 	    resource_listener_cb, NULL);
    151       1.156     pooka 
    152       1.156     pooka 	sysctl_proc_setup();
    153       1.130        ad }
    154       1.130        ad 
    155        1.60       eeh /*
    156        1.17       cgd  * Resource controls and accounting.
    157        1.17       cgd  */
    158        1.17       cgd 
    159        1.25       cgd int
    160       1.134     rmind sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap,
    161       1.134     rmind     register_t *retval)
    162        1.30   thorpej {
    163       1.128       dsl 	/* {
    164        1.22       cgd 		syscallarg(int) which;
    165        1.81    kleink 		syscallarg(id_t) who;
    166       1.128       dsl 	} */
    167        1.68   thorpej 	struct proc *curp = l->l_proc, *p;
    168       1.164     rmind 	id_t who = SCARG(uap, who);
    169        1.54  augustss 	int low = NZERO + PRIO_MAX + 1;
    170        1.17       cgd 
    171       1.138        ad 	mutex_enter(proc_lock);
    172        1.22       cgd 	switch (SCARG(uap, which)) {
    173        1.17       cgd 	case PRIO_PROCESS:
    174       1.171     njoly 		p = who ? proc_find(who) : curp;
    175       1.113        ad 		if (p != NULL)
    176       1.113        ad 			low = p->p_nice;
    177        1.17       cgd 		break;
    178        1.17       cgd 
    179        1.17       cgd 	case PRIO_PGRP: {
    180        1.54  augustss 		struct pgrp *pg;
    181        1.17       cgd 
    182       1.113        ad 		if (who == 0)
    183        1.17       cgd 			pg = curp->p_pgrp;
    184       1.157     rmind 		else if ((pg = pgrp_find(who)) == NULL)
    185        1.17       cgd 			break;
    186        1.64      matt 		LIST_FOREACH(p, &pg->pg_members, p_pglist) {
    187        1.17       cgd 			if (p->p_nice < low)
    188        1.17       cgd 				low = p->p_nice;
    189        1.17       cgd 		}
    190        1.17       cgd 		break;
    191        1.17       cgd 	}
    192        1.17       cgd 
    193        1.17       cgd 	case PRIO_USER:
    194       1.113        ad 		if (who == 0)
    195       1.113        ad 			who = (int)kauth_cred_geteuid(l->l_cred);
    196        1.86      yamt 		PROCLIST_FOREACH(p, &allproc) {
    197       1.139        ad 			mutex_enter(p->p_lock);
    198       1.102        ad 			if (kauth_cred_geteuid(p->p_cred) ==
    199       1.113        ad 			    (uid_t)who && p->p_nice < low)
    200        1.17       cgd 				low = p->p_nice;
    201       1.139        ad 			mutex_exit(p->p_lock);
    202        1.64      matt 		}
    203        1.17       cgd 		break;
    204        1.17       cgd 
    205        1.17       cgd 	default:
    206       1.138        ad 		mutex_exit(proc_lock);
    207       1.164     rmind 		return EINVAL;
    208        1.17       cgd 	}
    209       1.138        ad 	mutex_exit(proc_lock);
    210       1.113        ad 
    211       1.164     rmind 	if (low == NZERO + PRIO_MAX + 1) {
    212       1.164     rmind 		return ESRCH;
    213       1.164     rmind 	}
    214        1.37        ws 	*retval = low - NZERO;
    215       1.164     rmind 	return 0;
    216        1.17       cgd }
    217        1.17       cgd 
    218        1.25       cgd int
    219       1.134     rmind sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap,
    220       1.134     rmind     register_t *retval)
    221        1.30   thorpej {
    222       1.128       dsl 	/* {
    223        1.22       cgd 		syscallarg(int) which;
    224        1.81    kleink 		syscallarg(id_t) who;
    225        1.22       cgd 		syscallarg(int) prio;
    226       1.128       dsl 	} */
    227        1.68   thorpej 	struct proc *curp = l->l_proc, *p;
    228       1.164     rmind 	id_t who = SCARG(uap, who);
    229        1.17       cgd 	int found = 0, error = 0;
    230        1.17       cgd 
    231       1.138        ad 	mutex_enter(proc_lock);
    232        1.22       cgd 	switch (SCARG(uap, which)) {
    233        1.17       cgd 	case PRIO_PROCESS:
    234       1.157     rmind 		p = who ? proc_find(who) : curp;
    235       1.157     rmind 		if (p != NULL) {
    236       1.139        ad 			mutex_enter(p->p_lock);
    237       1.162  christos 			found++;
    238       1.113        ad 			error = donice(l, p, SCARG(uap, prio));
    239       1.139        ad 			mutex_exit(p->p_lock);
    240       1.113        ad 		}
    241        1.17       cgd 		break;
    242        1.17       cgd 
    243        1.17       cgd 	case PRIO_PGRP: {
    244        1.54  augustss 		struct pgrp *pg;
    245        1.87     perry 
    246       1.113        ad 		if (who == 0)
    247        1.17       cgd 			pg = curp->p_pgrp;
    248       1.157     rmind 		else if ((pg = pgrp_find(who)) == NULL)
    249        1.17       cgd 			break;
    250        1.64      matt 		LIST_FOREACH(p, &pg->pg_members, p_pglist) {
    251       1.139        ad 			mutex_enter(p->p_lock);
    252       1.162  christos 			found++;
    253       1.102        ad 			error = donice(l, p, SCARG(uap, prio));
    254       1.139        ad 			mutex_exit(p->p_lock);
    255       1.162  christos 			if (error)
    256       1.162  christos 				break;
    257        1.17       cgd 		}
    258        1.17       cgd 		break;
    259        1.17       cgd 	}
    260        1.17       cgd 
    261        1.17       cgd 	case PRIO_USER:
    262       1.113        ad 		if (who == 0)
    263       1.113        ad 			who = (int)kauth_cred_geteuid(l->l_cred);
    264        1.86      yamt 		PROCLIST_FOREACH(p, &allproc) {
    265       1.139        ad 			mutex_enter(p->p_lock);
    266       1.102        ad 			if (kauth_cred_geteuid(p->p_cred) ==
    267       1.102        ad 			    (uid_t)SCARG(uap, who)) {
    268       1.162  christos 				found++;
    269       1.102        ad 				error = donice(l, p, SCARG(uap, prio));
    270        1.17       cgd 			}
    271       1.139        ad 			mutex_exit(p->p_lock);
    272       1.162  christos 			if (error)
    273       1.162  christos 				break;
    274        1.64      matt 		}
    275        1.17       cgd 		break;
    276        1.17       cgd 
    277        1.17       cgd 	default:
    278       1.144     njoly 		mutex_exit(proc_lock);
    279       1.144     njoly 		return EINVAL;
    280        1.17       cgd 	}
    281       1.138        ad 	mutex_exit(proc_lock);
    282       1.164     rmind 
    283       1.164     rmind 	return (found == 0) ? ESRCH : error;
    284        1.17       cgd }
    285        1.17       cgd 
    286       1.113        ad /*
    287       1.113        ad  * Renice a process.
    288       1.113        ad  *
    289       1.113        ad  * Call with the target process' credentials locked.
    290       1.113        ad  */
    291       1.164     rmind static int
    292       1.102        ad donice(struct lwp *l, struct proc *chgp, int n)
    293        1.17       cgd {
    294       1.102        ad 	kauth_cred_t cred = l->l_cred;
    295       1.113        ad 
    296       1.139        ad 	KASSERT(mutex_owned(chgp->p_lock));
    297        1.17       cgd 
    298       1.152      elad 	if (kauth_cred_geteuid(cred) && kauth_cred_getuid(cred) &&
    299       1.152      elad 	    kauth_cred_geteuid(cred) != kauth_cred_geteuid(chgp->p_cred) &&
    300       1.152      elad 	    kauth_cred_getuid(cred) != kauth_cred_geteuid(chgp->p_cred))
    301       1.164     rmind 		return EPERM;
    302       1.152      elad 
    303       1.164     rmind 	if (n > PRIO_MAX) {
    304        1.17       cgd 		n = PRIO_MAX;
    305       1.164     rmind 	}
    306       1.164     rmind 	if (n < PRIO_MIN) {
    307        1.17       cgd 		n = PRIO_MIN;
    308       1.164     rmind 	}
    309        1.37        ws 	n += NZERO;
    310       1.164     rmind 
    311       1.112      elad 	if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp,
    312       1.164     rmind 	    KAUTH_ARG(n), NULL, NULL)) {
    313       1.164     rmind 		return EACCES;
    314       1.164     rmind 	}
    315       1.164     rmind 
    316       1.117      yamt 	sched_nice(chgp, n);
    317       1.164     rmind 	return 0;
    318        1.17       cgd }
    319        1.17       cgd 
    320        1.25       cgd int
    321       1.134     rmind sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap,
    322       1.134     rmind     register_t *retval)
    323        1.30   thorpej {
    324       1.128       dsl 	/* {
    325        1.42   mycroft 		syscallarg(int) which;
    326        1.39       cgd 		syscallarg(const struct rlimit *) rlp;
    327       1.128       dsl 	} */
    328       1.164     rmind 	int error, which = SCARG(uap, which);
    329        1.19       cgd 	struct rlimit alim;
    330        1.17       cgd 
    331        1.46     perry 	error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
    332       1.164     rmind 	if (error) {
    333       1.164     rmind 		return error;
    334       1.164     rmind 	}
    335       1.164     rmind 	return dosetrlimit(l, l->l_proc, which, &alim);
    336        1.17       cgd }
    337        1.17       cgd 
    338        1.17       cgd int
    339       1.102        ad dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
    340        1.17       cgd {
    341        1.54  augustss 	struct rlimit *alimp;
    342        1.17       cgd 	int error;
    343        1.17       cgd 
    344        1.67    itojun 	if ((u_int)which >= RLIM_NLIMITS)
    345       1.164     rmind 		return EINVAL;
    346        1.38  matthias 
    347        1.62  jdolecek 	if (limp->rlim_cur > limp->rlim_max) {
    348        1.62  jdolecek 		/*
    349        1.62  jdolecek 		 * This is programming error. According to SUSv2, we should
    350        1.62  jdolecek 		 * return error in this case.
    351        1.62  jdolecek 		 */
    352       1.164     rmind 		return EINVAL;
    353        1.62  jdolecek 	}
    354       1.122       dsl 
    355       1.122       dsl 	alimp = &p->p_rlimit[which];
    356       1.122       dsl 	/* if we don't change the value, no need to limcopy() */
    357       1.122       dsl 	if (limp->rlim_cur == alimp->rlim_cur &&
    358       1.122       dsl 	    limp->rlim_max == alimp->rlim_max)
    359       1.122       dsl 		return 0;
    360       1.122       dsl 
    361       1.112      elad 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
    362       1.131      elad 	    p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which));
    363       1.111      elad 	if (error)
    364       1.164     rmind 		return error;
    365        1.62  jdolecek 
    366       1.161     rmind 	lim_privatise(p);
    367       1.122       dsl 	/* p->p_limit is now unchangeable */
    368       1.122       dsl 	alimp = &p->p_rlimit[which];
    369        1.17       cgd 
    370        1.17       cgd 	switch (which) {
    371        1.17       cgd 
    372        1.17       cgd 	case RLIMIT_DATA:
    373        1.19       cgd 		if (limp->rlim_cur > maxdmap)
    374        1.19       cgd 			limp->rlim_cur = maxdmap;
    375        1.19       cgd 		if (limp->rlim_max > maxdmap)
    376        1.19       cgd 			limp->rlim_max = maxdmap;
    377        1.17       cgd 		break;
    378        1.17       cgd 
    379        1.17       cgd 	case RLIMIT_STACK:
    380        1.19       cgd 		if (limp->rlim_cur > maxsmap)
    381        1.19       cgd 			limp->rlim_cur = maxsmap;
    382        1.19       cgd 		if (limp->rlim_max > maxsmap)
    383        1.19       cgd 			limp->rlim_max = maxsmap;
    384        1.62  jdolecek 
    385        1.62  jdolecek 		/*
    386        1.62  jdolecek 		 * Return EINVAL if the new stack size limit is lower than
    387        1.62  jdolecek 		 * current usage. Otherwise, the process would get SIGSEGV the
    388       1.174       snj 		 * moment it would try to access anything on its current stack.
    389        1.62  jdolecek 		 * This conforms to SUSv2.
    390        1.62  jdolecek 		 */
    391  1.176.12.1  pgoyette 		if (btoc(limp->rlim_cur) < p->p_vmspace->vm_ssize ||
    392  1.176.12.1  pgoyette 		    btoc(limp->rlim_max) < p->p_vmspace->vm_ssize) {
    393       1.164     rmind 			return EINVAL;
    394       1.113        ad 		}
    395        1.40     enami 
    396        1.17       cgd 		/*
    397        1.40     enami 		 * Stack is allocated to the max at exec time with
    398        1.40     enami 		 * only "rlim_cur" bytes accessible (In other words,
    399        1.40     enami 		 * allocates stack dividing two contiguous regions at
    400        1.40     enami 		 * "rlim_cur" bytes boundary).
    401        1.40     enami 		 *
    402        1.40     enami 		 * Since allocation is done in terms of page, roundup
    403        1.40     enami 		 * "rlim_cur" (otherwise, contiguous regions
    404        1.40     enami 		 * overlap).  If stack limit is going up make more
    405        1.40     enami 		 * accessible, if going down make inaccessible.
    406        1.17       cgd 		 */
    407       1.175     njoly 		limp->rlim_max = round_page(limp->rlim_max);
    408        1.40     enami 		limp->rlim_cur = round_page(limp->rlim_cur);
    409        1.17       cgd 		if (limp->rlim_cur != alimp->rlim_cur) {
    410        1.48       eeh 			vaddr_t addr;
    411        1.48       eeh 			vsize_t size;
    412        1.17       cgd 			vm_prot_t prot;
    413       1.172       chs 			char *base, *tmp;
    414        1.17       cgd 
    415       1.172       chs 			base = p->p_vmspace->vm_minsaddr;
    416        1.17       cgd 			if (limp->rlim_cur > alimp->rlim_cur) {
    417        1.73       chs 				prot = VM_PROT_READ | VM_PROT_WRITE;
    418        1.17       cgd 				size = limp->rlim_cur - alimp->rlim_cur;
    419       1.172       chs 				tmp = STACK_GROW(base, alimp->rlim_cur);
    420        1.17       cgd 			} else {
    421        1.17       cgd 				prot = VM_PROT_NONE;
    422        1.17       cgd 				size = alimp->rlim_cur - limp->rlim_cur;
    423       1.172       chs 				tmp = STACK_GROW(base, limp->rlim_cur);
    424        1.17       cgd 			}
    425       1.172       chs 			addr = (vaddr_t)STACK_ALLOC(tmp, size);
    426        1.43       mrg 			(void) uvm_map_protect(&p->p_vmspace->vm_map,
    427       1.172       chs 			    addr, addr + size, prot, false);
    428        1.17       cgd 		}
    429        1.17       cgd 		break;
    430        1.19       cgd 
    431        1.19       cgd 	case RLIMIT_NOFILE:
    432        1.19       cgd 		if (limp->rlim_cur > maxfiles)
    433        1.19       cgd 			limp->rlim_cur = maxfiles;
    434        1.19       cgd 		if (limp->rlim_max > maxfiles)
    435        1.19       cgd 			limp->rlim_max = maxfiles;
    436        1.19       cgd 		break;
    437        1.19       cgd 
    438        1.19       cgd 	case RLIMIT_NPROC:
    439        1.19       cgd 		if (limp->rlim_cur > maxproc)
    440        1.19       cgd 			limp->rlim_cur = maxproc;
    441        1.19       cgd 		if (limp->rlim_max > maxproc)
    442        1.19       cgd 			limp->rlim_max = maxproc;
    443        1.19       cgd 		break;
    444       1.169  christos 
    445       1.169  christos 	case RLIMIT_NTHR:
    446       1.169  christos 		if (limp->rlim_cur > maxlwp)
    447       1.169  christos 			limp->rlim_cur = maxlwp;
    448       1.169  christos 		if (limp->rlim_max > maxlwp)
    449       1.169  christos 			limp->rlim_max = maxlwp;
    450       1.169  christos 		break;
    451        1.17       cgd 	}
    452       1.122       dsl 
    453       1.122       dsl 	mutex_enter(&p->p_limit->pl_lock);
    454        1.17       cgd 	*alimp = *limp;
    455       1.122       dsl 	mutex_exit(&p->p_limit->pl_lock);
    456       1.164     rmind 	return 0;
    457        1.17       cgd }
    458        1.17       cgd 
    459        1.25       cgd int
    460       1.134     rmind sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap,
    461       1.134     rmind     register_t *retval)
    462        1.30   thorpej {
    463       1.128       dsl 	/* {
    464        1.42   mycroft 		syscallarg(int) which;
    465        1.22       cgd 		syscallarg(struct rlimit *) rlp;
    466       1.128       dsl 	} */
    467        1.68   thorpej 	struct proc *p = l->l_proc;
    468        1.42   mycroft 	int which = SCARG(uap, which);
    469       1.119        ad 	struct rlimit rl;
    470        1.17       cgd 
    471        1.67    itojun 	if ((u_int)which >= RLIM_NLIMITS)
    472       1.164     rmind 		return EINVAL;
    473       1.119        ad 
    474       1.139        ad 	mutex_enter(p->p_lock);
    475       1.119        ad 	memcpy(&rl, &p->p_rlimit[which], sizeof(rl));
    476       1.139        ad 	mutex_exit(p->p_lock);
    477       1.119        ad 
    478       1.119        ad 	return copyout(&rl, SCARG(uap, rlp), sizeof(rl));
    479        1.17       cgd }
    480        1.17       cgd 
    481        1.17       cgd /*
    482        1.17       cgd  * Transform the running time and tick information in proc p into user,
    483        1.17       cgd  * system, and interrupt time usage.
    484       1.113        ad  *
    485       1.139        ad  * Should be called with p->p_lock held unless called from exit1().
    486        1.17       cgd  */
    487        1.25       cgd void
    488        1.98   thorpej calcru(struct proc *p, struct timeval *up, struct timeval *sp,
    489       1.113        ad     struct timeval *ip, struct timeval *rp)
    490        1.17       cgd {
    491       1.129      yamt 	uint64_t u, st, ut, it, tot;
    492        1.68   thorpej 	struct lwp *l;
    493       1.129      yamt 	struct bintime tm;
    494       1.129      yamt 	struct timeval tv;
    495        1.17       cgd 
    496       1.168      yamt 	KASSERT(p->p_stat == SDEAD || mutex_owned(p->p_lock));
    497       1.168      yamt 
    498       1.113        ad 	mutex_spin_enter(&p->p_stmutex);
    499        1.17       cgd 	st = p->p_sticks;
    500        1.17       cgd 	ut = p->p_uticks;
    501        1.17       cgd 	it = p->p_iticks;
    502       1.113        ad 	mutex_spin_exit(&p->p_stmutex);
    503        1.17       cgd 
    504       1.129      yamt 	tm = p->p_rtime;
    505       1.113        ad 
    506        1.70       dsl 	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
    507       1.113        ad 		lwp_lock(l);
    508       1.129      yamt 		bintime_add(&tm, &l->l_rtime);
    509       1.142        ad 		if ((l->l_pflag & LP_RUNNING) != 0) {
    510       1.129      yamt 			struct bintime diff;
    511        1.68   thorpej 			/*
    512        1.68   thorpej 			 * Adjust for the current time slice.  This is
    513        1.68   thorpej 			 * actually fairly important since the error
    514        1.68   thorpej 			 * here is on the order of a time quantum,
    515        1.68   thorpej 			 * which is much greater than the sampling
    516        1.87     perry 			 * error.
    517        1.68   thorpej 			 */
    518       1.129      yamt 			binuptime(&diff);
    519       1.129      yamt 			bintime_sub(&diff, &l->l_stime);
    520       1.129      yamt 			bintime_add(&tm, &diff);
    521        1.68   thorpej 		}
    522       1.113        ad 		lwp_unlock(l);
    523        1.17       cgd 	}
    524        1.69       dsl 
    525        1.69       dsl 	tot = st + ut + it;
    526       1.129      yamt 	bintime2timeval(&tm, &tv);
    527       1.129      yamt 	u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec;
    528        1.70       dsl 
    529        1.69       dsl 	if (tot == 0) {
    530        1.69       dsl 		/* No ticks, so can't use to share time out, split 50-50 */
    531        1.70       dsl 		st = ut = u / 2;
    532        1.70       dsl 	} else {
    533        1.70       dsl 		st = (u * st) / tot;
    534        1.70       dsl 		ut = (u * ut) / tot;
    535        1.69       dsl 	}
    536       1.113        ad 	if (sp != NULL) {
    537       1.113        ad 		sp->tv_sec = st / 1000000;
    538       1.113        ad 		sp->tv_usec = st % 1000000;
    539       1.113        ad 	}
    540       1.113        ad 	if (up != NULL) {
    541       1.113        ad 		up->tv_sec = ut / 1000000;
    542       1.113        ad 		up->tv_usec = ut % 1000000;
    543       1.113        ad 	}
    544        1.17       cgd 	if (ip != NULL) {
    545        1.70       dsl 		if (it != 0)
    546        1.70       dsl 			it = (u * it) / tot;
    547        1.17       cgd 		ip->tv_sec = it / 1000000;
    548        1.17       cgd 		ip->tv_usec = it % 1000000;
    549        1.17       cgd 	}
    550       1.113        ad 	if (rp != NULL) {
    551       1.129      yamt 		*rp = tv;
    552       1.113        ad 	}
    553        1.17       cgd }
    554        1.17       cgd 
    555        1.25       cgd int
    556       1.148  christos sys___getrusage50(struct lwp *l, const struct sys___getrusage50_args *uap,
    557       1.134     rmind     register_t *retval)
    558        1.30   thorpej {
    559       1.128       dsl 	/* {
    560        1.22       cgd 		syscallarg(int) who;
    561        1.22       cgd 		syscallarg(struct rusage *) rusage;
    562       1.128       dsl 	} */
    563       1.170     njoly 	int error;
    564       1.119        ad 	struct rusage ru;
    565        1.68   thorpej 	struct proc *p = l->l_proc;
    566        1.17       cgd 
    567       1.170     njoly 	error = getrusage1(p, SCARG(uap, who), &ru);
    568       1.170     njoly 	if (error != 0)
    569       1.170     njoly 		return error;
    570       1.170     njoly 
    571       1.170     njoly 	return copyout(&ru, SCARG(uap, rusage), sizeof(ru));
    572       1.170     njoly }
    573       1.170     njoly 
    574       1.170     njoly int
    575       1.170     njoly getrusage1(struct proc *p, int who, struct rusage *ru) {
    576       1.170     njoly 
    577       1.170     njoly 	switch (who) {
    578        1.19       cgd 	case RUSAGE_SELF:
    579       1.139        ad 		mutex_enter(p->p_lock);
    580       1.170     njoly 		memcpy(ru, &p->p_stats->p_ru, sizeof(*ru));
    581       1.170     njoly 		calcru(p, &ru->ru_utime, &ru->ru_stime, NULL, NULL);
    582       1.170     njoly 		rulwps(p, ru);
    583       1.139        ad 		mutex_exit(p->p_lock);
    584        1.17       cgd 		break;
    585        1.17       cgd 	case RUSAGE_CHILDREN:
    586       1.139        ad 		mutex_enter(p->p_lock);
    587       1.170     njoly 		memcpy(ru, &p->p_stats->p_cru, sizeof(*ru));
    588       1.139        ad 		mutex_exit(p->p_lock);
    589        1.17       cgd 		break;
    590        1.17       cgd 	default:
    591       1.119        ad 		return EINVAL;
    592        1.17       cgd 	}
    593       1.119        ad 
    594       1.170     njoly 	return 0;
    595        1.17       cgd }
    596        1.17       cgd 
    597        1.25       cgd void
    598        1.98   thorpej ruadd(struct rusage *ru, struct rusage *ru2)
    599        1.17       cgd {
    600        1.54  augustss 	long *ip, *ip2;
    601        1.54  augustss 	int i;
    602        1.17       cgd 
    603        1.27   mycroft 	timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
    604        1.27   mycroft 	timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
    605        1.17       cgd 	if (ru->ru_maxrss < ru2->ru_maxrss)
    606        1.17       cgd 		ru->ru_maxrss = ru2->ru_maxrss;
    607        1.17       cgd 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
    608        1.17       cgd 	for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
    609        1.17       cgd 		*ip++ += *ip2++;
    610        1.17       cgd }
    611        1.17       cgd 
    612       1.137        ad void
    613       1.137        ad rulwps(proc_t *p, struct rusage *ru)
    614       1.137        ad {
    615       1.137        ad 	lwp_t *l;
    616       1.137        ad 
    617       1.139        ad 	KASSERT(mutex_owned(p->p_lock));
    618       1.137        ad 
    619       1.137        ad 	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
    620       1.137        ad 		ruadd(ru, &l->l_ru);
    621       1.137        ad 		ru->ru_nvcsw += (l->l_ncsw - l->l_nivcsw);
    622       1.137        ad 		ru->ru_nivcsw += l->l_nivcsw;
    623       1.137        ad 	}
    624       1.137        ad }
    625       1.137        ad 
    626        1.17       cgd /*
    627       1.161     rmind  * lim_copy: make a copy of the plimit structure.
    628       1.113        ad  *
    629       1.161     rmind  * We use copy-on-write after fork, and copy when a limit is changed.
    630        1.17       cgd  */
    631        1.17       cgd struct plimit *
    632       1.122       dsl lim_copy(struct plimit *lim)
    633        1.17       cgd {
    634       1.122       dsl 	struct plimit *newlim;
    635       1.113        ad 	char *corename;
    636       1.122       dsl 	size_t alen, len;
    637        1.17       cgd 
    638       1.130        ad 	newlim = pool_cache_get(plimit_cache, PR_WAITOK);
    639       1.121       dsl 	mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
    640       1.161     rmind 	newlim->pl_writeable = false;
    641       1.121       dsl 	newlim->pl_refcnt = 1;
    642       1.122       dsl 	newlim->pl_sv_limit = NULL;
    643       1.122       dsl 
    644       1.122       dsl 	mutex_enter(&lim->pl_lock);
    645       1.122       dsl 	memcpy(newlim->pl_rlimit, lim->pl_rlimit,
    646       1.122       dsl 	    sizeof(struct rlimit) * RLIM_NLIMITS);
    647        1.83        pk 
    648       1.161     rmind 	/*
    649       1.161     rmind 	 * Note: the common case is a use of default core name.
    650       1.161     rmind 	 */
    651       1.122       dsl 	alen = 0;
    652       1.122       dsl 	corename = NULL;
    653       1.113        ad 	for (;;) {
    654       1.122       dsl 		if (lim->pl_corename == defcorename) {
    655       1.122       dsl 			newlim->pl_corename = defcorename;
    656       1.161     rmind 			newlim->pl_cnlen = 0;
    657       1.122       dsl 			break;
    658       1.122       dsl 		}
    659       1.161     rmind 		len = lim->pl_cnlen;
    660       1.161     rmind 		if (len == alen) {
    661       1.122       dsl 			newlim->pl_corename = corename;
    662       1.161     rmind 			newlim->pl_cnlen = len;
    663       1.122       dsl 			memcpy(corename, lim->pl_corename, len);
    664       1.122       dsl 			corename = NULL;
    665       1.122       dsl 			break;
    666       1.122       dsl 		}
    667       1.122       dsl 		mutex_exit(&lim->pl_lock);
    668       1.161     rmind 		if (corename) {
    669       1.161     rmind 			kmem_free(corename, alen);
    670       1.161     rmind 		}
    671       1.122       dsl 		alen = len;
    672       1.161     rmind 		corename = kmem_alloc(alen, KM_SLEEP);
    673       1.121       dsl 		mutex_enter(&lim->pl_lock);
    674       1.122       dsl 	}
    675       1.122       dsl 	mutex_exit(&lim->pl_lock);
    676       1.161     rmind 
    677       1.161     rmind 	if (corename) {
    678       1.161     rmind 		kmem_free(corename, alen);
    679       1.161     rmind 	}
    680       1.122       dsl 	return newlim;
    681       1.122       dsl }
    682       1.122       dsl 
    683       1.122       dsl void
    684       1.122       dsl lim_addref(struct plimit *lim)
    685       1.122       dsl {
    686       1.125        ad 	atomic_inc_uint(&lim->pl_refcnt);
    687       1.122       dsl }
    688       1.113        ad 
    689       1.122       dsl /*
    690       1.161     rmind  * lim_privatise: give a process its own private plimit structure.
    691       1.122       dsl  */
    692       1.122       dsl void
    693       1.161     rmind lim_privatise(proc_t *p)
    694       1.122       dsl {
    695       1.161     rmind 	struct plimit *lim = p->p_limit, *newlim;
    696       1.122       dsl 
    697       1.161     rmind 	if (lim->pl_writeable) {
    698       1.122       dsl 		return;
    699       1.122       dsl 	}
    700       1.122       dsl 
    701       1.122       dsl 	newlim = lim_copy(lim);
    702       1.113        ad 
    703       1.139        ad 	mutex_enter(p->p_lock);
    704       1.161     rmind 	if (p->p_limit->pl_writeable) {
    705       1.161     rmind 		/* Other thread won the race. */
    706       1.139        ad 		mutex_exit(p->p_lock);
    707       1.159     rmind 		lim_free(newlim);
    708       1.122       dsl 		return;
    709       1.113        ad 	}
    710        1.83        pk 
    711       1.122       dsl 	/*
    712       1.161     rmind 	 * Since p->p_limit can be accessed without locked held,
    713       1.161     rmind 	 * old limit structure must not be deleted yet.
    714       1.122       dsl 	 */
    715       1.122       dsl 	newlim->pl_sv_limit = p->p_limit;
    716       1.161     rmind 	newlim->pl_writeable = true;
    717       1.122       dsl 	p->p_limit = newlim;
    718       1.139        ad 	mutex_exit(p->p_lock);
    719        1.32   mycroft }
    720        1.32   mycroft 
    721        1.32   mycroft void
    722       1.160     rmind lim_setcorename(proc_t *p, char *name, size_t len)
    723       1.160     rmind {
    724       1.160     rmind 	struct plimit *lim;
    725       1.160     rmind 	char *oname;
    726       1.161     rmind 	size_t olen;
    727       1.160     rmind 
    728       1.161     rmind 	lim_privatise(p);
    729       1.160     rmind 	lim = p->p_limit;
    730       1.160     rmind 
    731       1.160     rmind 	mutex_enter(&lim->pl_lock);
    732       1.160     rmind 	oname = lim->pl_corename;
    733       1.161     rmind 	olen = lim->pl_cnlen;
    734       1.160     rmind 	lim->pl_corename = name;
    735       1.161     rmind 	lim->pl_cnlen = len;
    736       1.160     rmind 	mutex_exit(&lim->pl_lock);
    737       1.160     rmind 
    738       1.160     rmind 	if (oname != defcorename) {
    739       1.161     rmind 		kmem_free(oname, olen);
    740       1.160     rmind 	}
    741       1.160     rmind }
    742       1.160     rmind 
    743       1.160     rmind void
    744       1.159     rmind lim_free(struct plimit *lim)
    745        1.32   mycroft {
    746       1.122       dsl 	struct plimit *sv_lim;
    747        1.85    kleink 
    748       1.122       dsl 	do {
    749       1.159     rmind 		if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0) {
    750       1.122       dsl 			return;
    751       1.159     rmind 		}
    752       1.159     rmind 		if (lim->pl_corename != defcorename) {
    753       1.161     rmind 			kmem_free(lim->pl_corename, lim->pl_cnlen);
    754       1.159     rmind 		}
    755       1.122       dsl 		sv_lim = lim->pl_sv_limit;
    756       1.122       dsl 		mutex_destroy(&lim->pl_lock);
    757       1.130        ad 		pool_cache_put(plimit_cache, lim);
    758       1.122       dsl 	} while ((lim = sv_lim) != NULL);
    759        1.68   thorpej }
    760        1.68   thorpej 
    761        1.68   thorpej struct pstats *
    762        1.98   thorpej pstatscopy(struct pstats *ps)
    763        1.68   thorpej {
    764       1.164     rmind 	struct pstats *nps;
    765       1.164     rmind 	size_t len;
    766        1.87     perry 
    767       1.164     rmind 	nps = pool_cache_get(pstats_cache, PR_WAITOK);
    768        1.68   thorpej 
    769       1.164     rmind 	len = (char *)&nps->pstat_endzero - (char *)&nps->pstat_startzero;
    770       1.164     rmind 	memset(&nps->pstat_startzero, 0, len);
    771        1.68   thorpej 
    772       1.164     rmind 	len = (char *)&nps->pstat_endcopy - (char *)&nps->pstat_startcopy;
    773       1.164     rmind 	memcpy(&nps->pstat_startcopy, &ps->pstat_startcopy, len);
    774        1.68   thorpej 
    775       1.164     rmind 	return nps;
    776        1.68   thorpej }
    777        1.68   thorpej 
    778        1.68   thorpej void
    779        1.98   thorpej pstatsfree(struct pstats *ps)
    780        1.68   thorpej {
    781        1.68   thorpej 
    782       1.130        ad 	pool_cache_put(pstats_cache, ps);
    783        1.74    atatat }
    784        1.74    atatat 
    785        1.74    atatat /*
    786       1.157     rmind  * sysctl_proc_findproc: a routine for sysctl proc subtree helpers that
    787       1.157     rmind  * need to pick a valid process by PID.
    788       1.157     rmind  *
    789       1.157     rmind  * => Hold a reference on the process, on success.
    790        1.74    atatat  */
    791        1.74    atatat static int
    792       1.157     rmind sysctl_proc_findproc(lwp_t *l, pid_t pid, proc_t **p2)
    793        1.74    atatat {
    794       1.157     rmind 	proc_t *p;
    795       1.157     rmind 	int error;
    796        1.74    atatat 
    797       1.157     rmind 	if (pid == PROC_CURPROC) {
    798       1.157     rmind 		p = l->l_proc;
    799       1.157     rmind 	} else {
    800       1.157     rmind 		mutex_enter(proc_lock);
    801       1.157     rmind 		p = proc_find(pid);
    802       1.157     rmind 		if (p == NULL) {
    803       1.157     rmind 			mutex_exit(proc_lock);
    804       1.157     rmind 			return ESRCH;
    805       1.157     rmind 		}
    806       1.157     rmind 	}
    807       1.157     rmind 	error = rw_tryenter(&p->p_reflock, RW_READER) ? 0 : EBUSY;
    808       1.157     rmind 	if (pid != PROC_CURPROC) {
    809       1.157     rmind 		mutex_exit(proc_lock);
    810       1.157     rmind 	}
    811       1.157     rmind 	*p2 = p;
    812       1.157     rmind 	return error;
    813        1.74    atatat }
    814        1.74    atatat 
    815        1.74    atatat /*
    816       1.176  pgoyette  * sysctl_proc_paxflags: helper routine to get process's paxctl flags
    817       1.176  pgoyette  */
    818       1.176  pgoyette static int
    819       1.176  pgoyette sysctl_proc_paxflags(SYSCTLFN_ARGS)
    820       1.176  pgoyette {
    821       1.176  pgoyette 	struct proc *p;
    822       1.176  pgoyette 	struct sysctlnode node;
    823       1.176  pgoyette 	int paxflags;
    824       1.176  pgoyette 	int error;
    825       1.176  pgoyette 
    826       1.176  pgoyette 	/* First, validate the request. */
    827       1.176  pgoyette 	if (namelen != 0 || name[-1] != PROC_PID_PAXFLAGS)
    828       1.176  pgoyette 		return EINVAL;
    829       1.176  pgoyette 
    830       1.176  pgoyette 	/* Find the process.  Hold a reference (p_reflock), if found. */
    831       1.176  pgoyette 	error = sysctl_proc_findproc(l, (pid_t)name[-2], &p);
    832       1.176  pgoyette 	if (error)
    833       1.176  pgoyette 		return error;
    834       1.176  pgoyette 
    835       1.176  pgoyette 	/* XXX-elad */
    836       1.176  pgoyette 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
    837       1.176  pgoyette 	    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
    838       1.176  pgoyette 	if (error) {
    839       1.176  pgoyette 		rw_exit(&p->p_reflock);
    840       1.176  pgoyette 		return error;
    841       1.176  pgoyette 	}
    842       1.176  pgoyette 
    843       1.176  pgoyette 	/* Retrieve the limits. */
    844       1.176  pgoyette 	node = *rnode;
    845       1.176  pgoyette 	paxflags = p->p_pax;
    846       1.176  pgoyette 	node.sysctl_data = &paxflags;
    847       1.176  pgoyette 
    848       1.176  pgoyette 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    849       1.176  pgoyette 
    850       1.176  pgoyette 	/* If attempting to write new value, it's an error */
    851       1.176  pgoyette 	if (error == 0 && newp != NULL)
    852       1.176  pgoyette 		error = EACCES;
    853       1.176  pgoyette 
    854       1.176  pgoyette 	rw_exit(&p->p_reflock);
    855       1.176  pgoyette 	return error;
    856       1.176  pgoyette }
    857       1.176  pgoyette 
    858       1.176  pgoyette /*
    859       1.158     rmind  * sysctl_proc_corename: helper routine to get or set the core file name
    860       1.158     rmind  * for a process specified by PID.
    861        1.74    atatat  */
    862        1.74    atatat static int
    863        1.74    atatat sysctl_proc_corename(SYSCTLFN_ARGS)
    864        1.74    atatat {
    865       1.158     rmind 	struct proc *p;
    866        1.83        pk 	struct plimit *lim;
    867       1.158     rmind 	char *cnbuf, *cname;
    868       1.157     rmind 	struct sysctlnode node;
    869       1.158     rmind 	size_t len;
    870       1.158     rmind 	int error;
    871        1.74    atatat 
    872       1.158     rmind 	/* First, validate the request. */
    873       1.158     rmind 	if (namelen != 0 || name[-1] != PROC_PID_CORENAME)
    874       1.158     rmind 		return EINVAL;
    875        1.74    atatat 
    876       1.157     rmind 	/* Find the process.  Hold a reference (p_reflock), if found. */
    877       1.158     rmind 	error = sysctl_proc_findproc(l, (pid_t)name[-2], &p);
    878        1.74    atatat 	if (error)
    879       1.157     rmind 		return error;
    880        1.74    atatat 
    881       1.131      elad 	/* XXX-elad */
    882       1.158     rmind 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
    883       1.131      elad 	    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
    884       1.157     rmind 	if (error) {
    885       1.158     rmind 		rw_exit(&p->p_reflock);
    886       1.157     rmind 		return error;
    887       1.157     rmind 	}
    888       1.111      elad 
    889       1.158     rmind 	cnbuf = PNBUF_GET();
    890       1.158     rmind 
    891       1.165       mrg 	if (oldp) {
    892       1.158     rmind 		/* Get case: copy the core name into the buffer. */
    893       1.131      elad 		error = kauth_authorize_process(l->l_cred,
    894       1.158     rmind 		    KAUTH_PROCESS_CORENAME, p,
    895       1.131      elad 		    KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL);
    896       1.157     rmind 		if (error) {
    897       1.158     rmind 			goto done;
    898       1.158     rmind 		}
    899       1.158     rmind 		lim = p->p_limit;
    900       1.158     rmind 		mutex_enter(&lim->pl_lock);
    901       1.158     rmind 		strlcpy(cnbuf, lim->pl_corename, MAXPATHLEN);
    902       1.158     rmind 		mutex_exit(&lim->pl_lock);
    903       1.165       mrg 	}
    904       1.131      elad 
    905        1.74    atatat 	node = *rnode;
    906       1.158     rmind 	node.sysctl_data = cnbuf;
    907        1.74    atatat 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    908        1.74    atatat 
    909       1.163     rmind 	/* Return if error, or if caller is only getting the core name. */
    910       1.158     rmind 	if (error || newp == NULL) {
    911       1.100      yamt 		goto done;
    912       1.157     rmind 	}
    913       1.103      elad 
    914        1.74    atatat 	/*
    915       1.166     rmind 	 * Set case.  Check permission and then validate new core name.
    916       1.166     rmind 	 * It must be either "core", "/core", or end in ".core".
    917        1.74    atatat 	 */
    918       1.166     rmind 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CORENAME,
    919       1.166     rmind 	    p, KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cnbuf, NULL);
    920       1.166     rmind 	if (error) {
    921       1.166     rmind 		goto done;
    922       1.166     rmind 	}
    923       1.158     rmind 	len = strlen(cnbuf);
    924       1.158     rmind 	if ((len < 4 || strcmp(cnbuf + len - 4, "core") != 0) ||
    925       1.158     rmind 	    (len > 4 && cnbuf[len - 5] != '/' && cnbuf[len - 5] != '.')) {
    926       1.100      yamt 		error = EINVAL;
    927       1.100      yamt 		goto done;
    928       1.100      yamt 	}
    929        1.74    atatat 
    930       1.158     rmind 	/* Allocate, copy and set the new core name for plimit structure. */
    931       1.161     rmind 	cname = kmem_alloc(++len, KM_NOSLEEP);
    932       1.158     rmind 	if (cname == NULL) {
    933       1.100      yamt 		error = ENOMEM;
    934       1.100      yamt 		goto done;
    935       1.100      yamt 	}
    936       1.158     rmind 	memcpy(cname, cnbuf, len);
    937       1.160     rmind 	lim_setcorename(p, cname, len);
    938       1.100      yamt done:
    939       1.158     rmind 	rw_exit(&p->p_reflock);
    940       1.158     rmind 	PNBUF_PUT(cnbuf);
    941       1.100      yamt 	return error;
    942        1.74    atatat }
    943        1.74    atatat 
    944        1.74    atatat /*
    945       1.163     rmind  * sysctl_proc_stop: helper routine for checking/setting the stop flags.
    946        1.74    atatat  */
    947        1.74    atatat static int
    948        1.74    atatat sysctl_proc_stop(SYSCTLFN_ARGS)
    949        1.74    atatat {
    950       1.163     rmind 	struct proc *p;
    951       1.163     rmind 	int isset, flag, error = 0;
    952        1.74    atatat 	struct sysctlnode node;
    953        1.74    atatat 
    954        1.74    atatat 	if (namelen != 0)
    955       1.163     rmind 		return EINVAL;
    956        1.74    atatat 
    957       1.157     rmind 	/* Find the process.  Hold a reference (p_reflock), if found. */
    958       1.163     rmind 	error = sysctl_proc_findproc(l, (pid_t)name[-2], &p);
    959        1.74    atatat 	if (error)
    960       1.157     rmind 		return error;
    961        1.74    atatat 
    962       1.131      elad 	/* XXX-elad */
    963       1.163     rmind 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
    964       1.131      elad 	    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
    965       1.163     rmind 	if (error) {
    966       1.157     rmind 		goto out;
    967       1.163     rmind 	}
    968       1.111      elad 
    969       1.163     rmind 	/* Determine the flag. */
    970        1.74    atatat 	switch (rnode->sysctl_num) {
    971        1.74    atatat 	case PROC_PID_STOPFORK:
    972       1.163     rmind 		flag = PS_STOPFORK;
    973        1.74    atatat 		break;
    974        1.74    atatat 	case PROC_PID_STOPEXEC:
    975       1.163     rmind 		flag = PS_STOPEXEC;
    976        1.74    atatat 		break;
    977        1.74    atatat 	case PROC_PID_STOPEXIT:
    978       1.163     rmind 		flag = PS_STOPEXIT;
    979        1.74    atatat 		break;
    980        1.74    atatat 	default:
    981       1.157     rmind 		error = EINVAL;
    982       1.157     rmind 		goto out;
    983        1.74    atatat 	}
    984       1.163     rmind 	isset = (p->p_flag & flag) ? 1 : 0;
    985        1.74    atatat 	node = *rnode;
    986       1.163     rmind 	node.sysctl_data = &isset;
    987        1.74    atatat 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    988       1.163     rmind 
    989       1.163     rmind 	/* Return if error, or if callers is only getting the flag. */
    990       1.163     rmind 	if (error || newp == NULL) {
    991       1.157     rmind 		goto out;
    992       1.163     rmind 	}
    993        1.74    atatat 
    994       1.163     rmind 	/* Check if caller can set the flags. */
    995       1.111      elad 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG,
    996       1.163     rmind 	    p, KAUTH_ARG(flag), NULL, NULL);
    997       1.163     rmind 	if (error) {
    998       1.163     rmind 		goto out;
    999       1.163     rmind 	}
   1000       1.163     rmind 	mutex_enter(p->p_lock);
   1001       1.163     rmind 	if (isset) {
   1002       1.163     rmind 		p->p_sflag |= flag;
   1003       1.163     rmind 	} else {
   1004       1.163     rmind 		p->p_sflag &= ~flag;
   1005       1.143     rmind 	}
   1006       1.163     rmind 	mutex_exit(p->p_lock);
   1007       1.157     rmind out:
   1008       1.163     rmind 	rw_exit(&p->p_reflock);
   1009       1.143     rmind 	return error;
   1010        1.74    atatat }
   1011        1.74    atatat 
   1012        1.74    atatat /*
   1013       1.163     rmind  * sysctl_proc_plimit: helper routine to get/set rlimits of a process.
   1014        1.74    atatat  */
   1015        1.74    atatat static int
   1016        1.74    atatat sysctl_proc_plimit(SYSCTLFN_ARGS)
   1017        1.74    atatat {
   1018       1.163     rmind 	struct proc *p;
   1019        1.74    atatat 	u_int limitno;
   1020        1.74    atatat 	int which, error = 0;
   1021        1.74    atatat         struct rlimit alim;
   1022        1.74    atatat 	struct sysctlnode node;
   1023        1.74    atatat 
   1024        1.74    atatat 	if (namelen != 0)
   1025       1.163     rmind 		return EINVAL;
   1026        1.74    atatat 
   1027        1.74    atatat 	which = name[-1];
   1028        1.74    atatat 	if (which != PROC_PID_LIMIT_TYPE_SOFT &&
   1029        1.74    atatat 	    which != PROC_PID_LIMIT_TYPE_HARD)
   1030       1.163     rmind 		return EINVAL;
   1031        1.74    atatat 
   1032        1.74    atatat 	limitno = name[-2] - 1;
   1033        1.74    atatat 	if (limitno >= RLIM_NLIMITS)
   1034       1.163     rmind 		return EINVAL;
   1035        1.74    atatat 
   1036        1.74    atatat 	if (name[-3] != PROC_PID_LIMIT)
   1037       1.163     rmind 		return EINVAL;
   1038        1.74    atatat 
   1039       1.157     rmind 	/* Find the process.  Hold a reference (p_reflock), if found. */
   1040       1.163     rmind 	error = sysctl_proc_findproc(l, (pid_t)name[-4], &p);
   1041        1.74    atatat 	if (error)
   1042       1.157     rmind 		return error;
   1043        1.74    atatat 
   1044       1.131      elad 	/* XXX-elad */
   1045       1.163     rmind 	error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, p,
   1046       1.131      elad 	    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
   1047       1.111      elad 	if (error)
   1048       1.157     rmind 		goto out;
   1049       1.111      elad 
   1050       1.163     rmind 	/* Check if caller can retrieve the limits. */
   1051       1.131      elad 	if (newp == NULL) {
   1052       1.131      elad 		error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
   1053       1.163     rmind 		    p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim,
   1054       1.131      elad 		    KAUTH_ARG(which));
   1055       1.131      elad 		if (error)
   1056       1.157     rmind 			goto out;
   1057       1.131      elad 	}
   1058       1.131      elad 
   1059       1.163     rmind 	/* Retrieve the limits. */
   1060        1.74    atatat 	node = *rnode;
   1061       1.163     rmind 	memcpy(&alim, &p->p_rlimit[limitno], sizeof(alim));
   1062       1.163     rmind 	if (which == PROC_PID_LIMIT_TYPE_HARD) {
   1063        1.74    atatat 		node.sysctl_data = &alim.rlim_max;
   1064       1.163     rmind 	} else {
   1065        1.74    atatat 		node.sysctl_data = &alim.rlim_cur;
   1066       1.163     rmind 	}
   1067       1.163     rmind 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
   1068        1.74    atatat 
   1069       1.163     rmind 	/* Return if error, or if we are only retrieving the limits. */
   1070       1.157     rmind 	if (error || newp == NULL) {
   1071       1.157     rmind 		goto out;
   1072       1.157     rmind 	}
   1073       1.163     rmind 	error = dosetrlimit(l, p, limitno, &alim);
   1074       1.157     rmind out:
   1075       1.163     rmind 	rw_exit(&p->p_reflock);
   1076       1.157     rmind 	return error;
   1077        1.74    atatat }
   1078        1.74    atatat 
   1079        1.74    atatat /*
   1080       1.164     rmind  * Setup sysctl nodes.
   1081        1.74    atatat  */
   1082       1.156     pooka static void
   1083       1.164     rmind sysctl_proc_setup(void)
   1084        1.74    atatat {
   1085        1.74    atatat 
   1086       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1087        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
   1088        1.78    atatat 		       CTLTYPE_NODE, "curproc",
   1089        1.78    atatat 		       SYSCTL_DESCR("Per-process settings"),
   1090        1.74    atatat 		       NULL, 0, NULL, 0,
   1091        1.74    atatat 		       CTL_PROC, PROC_CURPROC, CTL_EOL);
   1092        1.74    atatat 
   1093       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1094       1.176  pgoyette 		       CTLFLAG_PERMANENT|CTLFLAG_READONLY,
   1095       1.176  pgoyette 		       CTLTYPE_INT, "paxflags",
   1096       1.176  pgoyette 		       SYSCTL_DESCR("Process PAX control flags"),
   1097       1.176  pgoyette 		       sysctl_proc_paxflags, 0, NULL, 0,
   1098       1.176  pgoyette 		       CTL_PROC, PROC_CURPROC, PROC_PID_PAXFLAGS, CTL_EOL);
   1099       1.176  pgoyette 
   1100       1.176  pgoyette 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1101       1.103      elad 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
   1102        1.78    atatat 		       CTLTYPE_STRING, "corename",
   1103        1.78    atatat 		       SYSCTL_DESCR("Core file name"),
   1104        1.74    atatat 		       sysctl_proc_corename, 0, NULL, MAXPATHLEN,
   1105        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
   1106       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1107        1.76    atatat 		       CTLFLAG_PERMANENT,
   1108        1.78    atatat 		       CTLTYPE_NODE, "rlimit",
   1109        1.78    atatat 		       SYSCTL_DESCR("Process limits"),
   1110        1.74    atatat 		       NULL, 0, NULL, 0,
   1111        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
   1112        1.74    atatat 
   1113        1.74    atatat #define create_proc_plimit(s, n) do {					\
   1114       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,			\
   1115        1.76    atatat 		       CTLFLAG_PERMANENT,				\
   1116        1.78    atatat 		       CTLTYPE_NODE, s,					\
   1117        1.78    atatat 		       SYSCTL_DESCR("Process " s " limits"),		\
   1118        1.74    atatat 		       NULL, 0, NULL, 0,				\
   1119        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,	\
   1120        1.74    atatat 		       CTL_EOL);					\
   1121       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,			\
   1122        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
   1123        1.78    atatat 		       CTLTYPE_QUAD, "soft",				\
   1124        1.78    atatat 		       SYSCTL_DESCR("Process soft " s " limit"),	\
   1125        1.74    atatat 		       sysctl_proc_plimit, 0, NULL, 0,			\
   1126        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,	\
   1127        1.74    atatat 		       PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL);		\
   1128       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,			\
   1129        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
   1130        1.78    atatat 		       CTLTYPE_QUAD, "hard",				\
   1131        1.78    atatat 		       SYSCTL_DESCR("Process hard " s " limit"),	\
   1132        1.74    atatat 		       sysctl_proc_plimit, 0, NULL, 0,			\
   1133        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n,	\
   1134        1.74    atatat 		       PROC_PID_LIMIT_TYPE_HARD, CTL_EOL);		\
   1135        1.74    atatat 	} while (0/*CONSTCOND*/)
   1136        1.74    atatat 
   1137        1.74    atatat 	create_proc_plimit("cputime",		PROC_PID_LIMIT_CPU);
   1138        1.74    atatat 	create_proc_plimit("filesize",		PROC_PID_LIMIT_FSIZE);
   1139        1.74    atatat 	create_proc_plimit("datasize",		PROC_PID_LIMIT_DATA);
   1140        1.74    atatat 	create_proc_plimit("stacksize",		PROC_PID_LIMIT_STACK);
   1141        1.74    atatat 	create_proc_plimit("coredumpsize",	PROC_PID_LIMIT_CORE);
   1142        1.74    atatat 	create_proc_plimit("memoryuse",		PROC_PID_LIMIT_RSS);
   1143        1.74    atatat 	create_proc_plimit("memorylocked",	PROC_PID_LIMIT_MEMLOCK);
   1144        1.74    atatat 	create_proc_plimit("maxproc",		PROC_PID_LIMIT_NPROC);
   1145        1.74    atatat 	create_proc_plimit("descriptors",	PROC_PID_LIMIT_NOFILE);
   1146        1.79  christos 	create_proc_plimit("sbsize",		PROC_PID_LIMIT_SBSIZE);
   1147       1.151       mrg 	create_proc_plimit("vmemoryuse",	PROC_PID_LIMIT_AS);
   1148       1.169  christos 	create_proc_plimit("maxlwp",		PROC_PID_LIMIT_NTHR);
   1149        1.74    atatat 
   1150        1.74    atatat #undef create_proc_plimit
   1151        1.74    atatat 
   1152       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1153        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
   1154        1.78    atatat 		       CTLTYPE_INT, "stopfork",
   1155        1.78    atatat 		       SYSCTL_DESCR("Stop process at fork(2)"),
   1156        1.74    atatat 		       sysctl_proc_stop, 0, NULL, 0,
   1157        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
   1158       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1159        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
   1160        1.78    atatat 		       CTLTYPE_INT, "stopexec",
   1161        1.78    atatat 		       SYSCTL_DESCR("Stop process at execve(2)"),
   1162        1.74    atatat 		       sysctl_proc_stop, 0, NULL, 0,
   1163        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
   1164       1.156     pooka 	sysctl_createv(&proc_sysctllog, 0, NULL, NULL,
   1165        1.76    atatat 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
   1166        1.78    atatat 		       CTLTYPE_INT, "stopexit",
   1167        1.78    atatat 		       SYSCTL_DESCR("Stop process before completing exit"),
   1168        1.74    atatat 		       sysctl_proc_stop, 0, NULL, 0,
   1169        1.74    atatat 		       CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
   1170        1.17       cgd }
   1171