2008-04-29 19:51:23 +04:00
|
|
|
/* $NetBSD: kern_resource.c,v 1.140 2008/04/29 15:51:23 ad Exp $ */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/*-
|
1994-05-19 12:13:09 +04:00
|
|
|
* Copyright (c) 1982, 1986, 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1994-05-17 08:21:49 +04:00
|
|
|
* (c) UNIX System Laboratories, Inc.
|
|
|
|
* All or some portions of this file are derived from material licensed
|
|
|
|
* to the University of California by American Telephone and Telegraph
|
|
|
|
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
|
|
|
* the permission of UNIX System Laboratories, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1994-05-17 08:21:49 +04:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1998-03-01 05:20:01 +03:00
|
|
|
* @(#)kern_resource.c 8.8 (Berkeley) 2/14/95
|
1994-05-17 08:21:49 +04:00
|
|
|
*/
|
|
|
|
|
2001-11-12 18:25:01 +03:00
|
|
|
#include <sys/cdefs.h>
|
2008-04-29 19:51:23 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.140 2008/04/29 15:51:23 ad Exp $");
|
2001-11-12 18:25:01 +03:00
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
#include <sys/param.h>
|
1994-10-20 07:22:35 +03:00
|
|
|
#include <sys/systm.h>
|
1994-05-17 08:21:49 +04:00
|
|
|
#include <sys/kernel.h>
|
1994-05-19 12:13:09 +04:00
|
|
|
#include <sys/file.h>
|
1994-05-17 08:21:49 +04:00
|
|
|
#include <sys/resourcevar.h>
|
|
|
|
#include <sys/malloc.h>
|
2008-01-29 15:41:59 +03:00
|
|
|
#include <sys/kmem.h>
|
2006-02-04 15:09:50 +03:00
|
|
|
#include <sys/namei.h>
|
1998-09-01 03:53:19 +04:00
|
|
|
#include <sys/pool.h>
|
1994-05-17 08:21:49 +04:00
|
|
|
#include <sys/proc.h>
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
#include <sys/sysctl.h>
|
2007-12-22 04:14:53 +03:00
|
|
|
#include <sys/timevar.h>
|
2006-05-15 01:15:11 +04:00
|
|
|
#include <sys/kauth.h>
|
2007-11-29 21:21:03 +03:00
|
|
|
#include <sys/atomic.h>
|
1994-10-20 07:22:35 +03:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/syscallargs.h>
|
2008-03-18 05:35:29 +03:00
|
|
|
#include <sys/atomic.h>
|
1994-10-20 07:22:35 +03:00
|
|
|
|
1998-02-05 10:59:28 +03:00
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
|
2001-02-06 22:54:43 +03:00
|
|
|
/*
|
|
|
|
* Maximum process data and stack limits.
|
|
|
|
* They are variables so they are patchable.
|
|
|
|
*/
|
|
|
|
rlim_t maxdmap = MAXDSIZ;
|
|
|
|
rlim_t maxsmap = MAXSSIZ;
|
|
|
|
|
2008-03-18 00:16:03 +03:00
|
|
|
static SLIST_HEAD(uihashhead, uidinfo) *uihashtbl;
|
2008-03-17 03:18:24 +03:00
|
|
|
static u_long uihash;
|
2004-04-17 19:15:29 +04:00
|
|
|
|
2008-03-17 03:18:24 +03:00
|
|
|
#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
|
|
|
|
|
|
|
|
static pool_cache_t plimit_cache;
|
|
|
|
static pool_cache_t pstats_cache;
|
2007-12-26 19:01:34 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
resource_init(void)
|
|
|
|
{
|
2008-03-18 00:16:03 +03:00
|
|
|
/*
|
|
|
|
* In case of MP system, SLIST_FOREACH would force a cache line
|
|
|
|
* write-back for every modified 'uidinfo', thus we try to keep the
|
|
|
|
* lists short.
|
|
|
|
*/
|
|
|
|
const u_int uihash_sz = (maxproc > 1 ? 1024 : 64);
|
2007-12-26 19:01:34 +03:00
|
|
|
|
|
|
|
plimit_cache = pool_cache_init(sizeof(struct plimit), 0, 0, 0,
|
|
|
|
"plimitpl", NULL, IPL_NONE, NULL, NULL, NULL);
|
|
|
|
pstats_cache = pool_cache_init(sizeof(struct pstats), 0, 0, 0,
|
|
|
|
"pstatspl", NULL, IPL_NONE, NULL, NULL, NULL);
|
2008-03-18 00:16:03 +03:00
|
|
|
uihashtbl = hashinit(uihash_sz, HASH_SLIST, M_PROC, M_WAITOK, &uihash);
|
2007-12-26 19:01:34 +03:00
|
|
|
}
|
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/*
|
|
|
|
* Resource controls and accounting.
|
|
|
|
*/
|
|
|
|
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2008-03-17 03:18:24 +03:00
|
|
|
sys_getpriority(struct lwp *l, const struct sys_getpriority_args *uap,
|
|
|
|
register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int) which;
|
2004-04-26 02:18:08 +04:00
|
|
|
syscallarg(id_t) who;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *curp = l->l_proc, *p;
|
2000-03-30 13:27:11 +04:00
|
|
|
int low = NZERO + PRIO_MAX + 1;
|
2007-02-10 00:55:00 +03:00
|
|
|
int who = SCARG(uap, who);
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2008-04-24 19:35:27 +04:00
|
|
|
mutex_enter(proc_lock);
|
1994-10-20 07:22:35 +03:00
|
|
|
switch (SCARG(uap, which)) {
|
1994-05-17 08:21:49 +04:00
|
|
|
case PRIO_PROCESS:
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
1994-05-17 08:21:49 +04:00
|
|
|
p = curp;
|
|
|
|
else
|
2007-02-10 00:55:00 +03:00
|
|
|
p = p_find(who, PFIND_LOCKED);
|
|
|
|
if (p != NULL)
|
|
|
|
low = p->p_nice;
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PRIO_PGRP: {
|
2000-03-30 13:27:11 +04:00
|
|
|
struct pgrp *pg;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
1994-05-17 08:21:49 +04:00
|
|
|
pg = curp->p_pgrp;
|
2007-02-10 00:55:00 +03:00
|
|
|
else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
2002-09-04 05:32:31 +04:00
|
|
|
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
|
1994-05-17 08:21:49 +04:00
|
|
|
if (p->p_nice < low)
|
|
|
|
low = p->p_nice;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case PRIO_USER:
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
|
|
|
who = (int)kauth_cred_geteuid(l->l_cred);
|
2004-10-01 20:30:52 +04:00
|
|
|
PROCLIST_FOREACH(p, &allproc) {
|
2008-04-29 19:51:23 +04:00
|
|
|
if ((p->p_flag & PK_MARKER) != 0)
|
|
|
|
continue;
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2006-07-24 02:06:03 +04:00
|
|
|
if (kauth_cred_geteuid(p->p_cred) ==
|
2007-02-10 00:55:00 +03:00
|
|
|
(uid_t)who && p->p_nice < low)
|
1994-05-17 08:21:49 +04:00
|
|
|
low = p->p_nice;
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
2002-09-04 05:32:31 +04:00
|
|
|
}
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2008-04-24 19:35:27 +04:00
|
|
|
mutex_exit(proc_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
return (EINVAL);
|
|
|
|
}
|
2008-04-24 19:35:27 +04:00
|
|
|
mutex_exit(proc_lock);
|
2007-02-10 00:55:00 +03:00
|
|
|
|
1996-10-02 22:04:56 +04:00
|
|
|
if (low == NZERO + PRIO_MAX + 1)
|
1994-05-17 08:21:49 +04:00
|
|
|
return (ESRCH);
|
1996-10-02 22:04:56 +04:00
|
|
|
*retval = low - NZERO;
|
1994-05-17 08:21:49 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2008-03-17 03:18:24 +03:00
|
|
|
sys_setpriority(struct lwp *l, const struct sys_setpriority_args *uap,
|
|
|
|
register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int) which;
|
2004-04-26 02:18:08 +04:00
|
|
|
syscallarg(id_t) who;
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int) prio;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *curp = l->l_proc, *p;
|
1994-05-17 08:21:49 +04:00
|
|
|
int found = 0, error = 0;
|
2007-02-10 00:55:00 +03:00
|
|
|
int who = SCARG(uap, who);
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2008-04-24 19:35:27 +04:00
|
|
|
mutex_enter(proc_lock);
|
1994-10-20 07:22:35 +03:00
|
|
|
switch (SCARG(uap, which)) {
|
1994-05-17 08:21:49 +04:00
|
|
|
case PRIO_PROCESS:
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
1994-05-17 08:21:49 +04:00
|
|
|
p = curp;
|
|
|
|
else
|
2007-02-10 00:55:00 +03:00
|
|
|
p = p_find(who, PFIND_LOCKED);
|
|
|
|
if (p != 0) {
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2007-02-10 00:55:00 +03:00
|
|
|
error = donice(l, p, SCARG(uap, prio));
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
2007-02-10 00:55:00 +03:00
|
|
|
}
|
1994-05-17 08:21:49 +04:00
|
|
|
found++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PRIO_PGRP: {
|
2000-03-30 13:27:11 +04:00
|
|
|
struct pgrp *pg;
|
2005-02-27 00:34:55 +03:00
|
|
|
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
1994-05-17 08:21:49 +04:00
|
|
|
pg = curp->p_pgrp;
|
2007-02-10 00:55:00 +03:00
|
|
|
else if ((pg = pg_find(who, PFIND_LOCKED)) == NULL)
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
2002-09-04 05:32:31 +04:00
|
|
|
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2006-07-24 02:06:03 +04:00
|
|
|
error = donice(l, p, SCARG(uap, prio));
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
found++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case PRIO_USER:
|
2007-02-10 00:55:00 +03:00
|
|
|
if (who == 0)
|
|
|
|
who = (int)kauth_cred_geteuid(l->l_cred);
|
2004-10-01 20:30:52 +04:00
|
|
|
PROCLIST_FOREACH(p, &allproc) {
|
2008-04-29 19:51:23 +04:00
|
|
|
if ((p->p_flag & PK_MARKER) != 0)
|
|
|
|
continue;
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2006-07-24 02:06:03 +04:00
|
|
|
if (kauth_cred_geteuid(p->p_cred) ==
|
|
|
|
(uid_t)SCARG(uap, who)) {
|
|
|
|
error = donice(l, p, SCARG(uap, prio));
|
1994-05-17 08:21:49 +04:00
|
|
|
found++;
|
|
|
|
}
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
2002-09-04 05:32:31 +04:00
|
|
|
}
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-02-10 00:55:00 +03:00
|
|
|
error = EINVAL;
|
|
|
|
break;
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
2008-04-24 19:35:27 +04:00
|
|
|
mutex_exit(proc_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
if (found == 0)
|
|
|
|
return (ESRCH);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2007-02-10 00:55:00 +03:00
|
|
|
/*
|
|
|
|
* Renice a process.
|
|
|
|
*
|
|
|
|
* Call with the target process' credentials locked.
|
|
|
|
*/
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2006-07-24 02:06:03 +04:00
|
|
|
donice(struct lwp *l, struct proc *chgp, int n)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
2006-07-24 02:06:03 +04:00
|
|
|
kauth_cred_t cred = l->l_cred;
|
2007-02-10 00:55:00 +03:00
|
|
|
|
2008-04-24 22:39:20 +04:00
|
|
|
KASSERT(mutex_owned(chgp->p_lock));
|
1994-05-17 08:21:49 +04:00
|
|
|
|
|
|
|
if (n > PRIO_MAX)
|
|
|
|
n = PRIO_MAX;
|
|
|
|
if (n < PRIO_MIN)
|
|
|
|
n = PRIO_MIN;
|
1996-10-02 22:04:56 +04:00
|
|
|
n += NZERO;
|
2007-01-20 19:47:38 +03:00
|
|
|
if (kauth_authorize_process(cred, KAUTH_PROCESS_NICE, chgp,
|
|
|
|
KAUTH_ARG(n), NULL, NULL))
|
1994-05-17 08:21:49 +04:00
|
|
|
return (EACCES);
|
2007-05-17 18:51:11 +04:00
|
|
|
sched_nice(chgp, n);
|
1994-05-17 08:21:49 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2008-03-17 03:18:24 +03:00
|
|
|
sys_setrlimit(struct lwp *l, const struct sys_setrlimit_args *uap,
|
|
|
|
register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
1997-10-15 21:03:52 +04:00
|
|
|
syscallarg(int) which;
|
1996-12-22 13:21:06 +03:00
|
|
|
syscallarg(const struct rlimit *) rlp;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
1997-10-15 21:03:52 +04:00
|
|
|
int which = SCARG(uap, which);
|
1994-05-19 12:13:09 +04:00
|
|
|
struct rlimit alim;
|
1994-05-17 08:21:49 +04:00
|
|
|
int error;
|
|
|
|
|
1998-08-01 02:50:48 +04:00
|
|
|
error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
|
1996-02-04 05:15:01 +03:00
|
|
|
if (error)
|
1994-05-17 08:21:49 +04:00
|
|
|
return (error);
|
2006-07-24 02:06:03 +04:00
|
|
|
return (dosetrlimit(l, l->l_proc, which, &alim));
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2006-07-24 02:06:03 +04:00
|
|
|
dosetrlimit(struct lwp *l, struct proc *p, int which, struct rlimit *limp)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
2000-03-30 13:27:11 +04:00
|
|
|
struct rlimit *alimp;
|
1994-05-17 08:21:49 +04:00
|
|
|
int error;
|
|
|
|
|
2002-10-03 09:18:59 +04:00
|
|
|
if ((u_int)which >= RLIM_NLIMITS)
|
1994-05-17 08:21:49 +04:00
|
|
|
return (EINVAL);
|
1996-10-23 11:19:38 +04:00
|
|
|
|
|
|
|
if (limp->rlim_cur < 0 || limp->rlim_max < 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2001-11-23 21:56:33 +03:00
|
|
|
if (limp->rlim_cur > limp->rlim_max) {
|
|
|
|
/*
|
|
|
|
* This is programming error. According to SUSv2, we should
|
|
|
|
* return error in this case.
|
|
|
|
*/
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
2007-09-29 16:22:30 +04:00
|
|
|
|
|
|
|
alimp = &p->p_rlimit[which];
|
|
|
|
/* if we don't change the value, no need to limcopy() */
|
|
|
|
if (limp->rlim_cur == alimp->rlim_cur &&
|
|
|
|
limp->rlim_max == alimp->rlim_max)
|
|
|
|
return 0;
|
|
|
|
|
2007-01-20 19:47:38 +03:00
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
p, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_SET), limp, KAUTH_ARG(which));
|
2006-12-14 14:45:08 +03:00
|
|
|
if (error)
|
2007-09-29 16:22:30 +04:00
|
|
|
return (error);
|
2001-11-23 21:56:33 +03:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
lim_privatise(p, false);
|
|
|
|
/* p->p_limit is now unchangeable */
|
|
|
|
alimp = &p->p_rlimit[which];
|
1994-05-17 08:21:49 +04:00
|
|
|
|
|
|
|
switch (which) {
|
|
|
|
|
|
|
|
case RLIMIT_DATA:
|
1994-05-19 12:13:09 +04:00
|
|
|
if (limp->rlim_cur > maxdmap)
|
|
|
|
limp->rlim_cur = maxdmap;
|
|
|
|
if (limp->rlim_max > maxdmap)
|
|
|
|
limp->rlim_max = maxdmap;
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RLIMIT_STACK:
|
1994-05-19 12:13:09 +04:00
|
|
|
if (limp->rlim_cur > maxsmap)
|
|
|
|
limp->rlim_cur = maxsmap;
|
|
|
|
if (limp->rlim_max > maxsmap)
|
|
|
|
limp->rlim_max = maxsmap;
|
1997-10-09 05:04:13 +04:00
|
|
|
|
2001-11-23 21:56:33 +03:00
|
|
|
/*
|
|
|
|
* Return EINVAL if the new stack size limit is lower than
|
|
|
|
* current usage. Otherwise, the process would get SIGSEGV the
|
|
|
|
* moment it would try to access anything on it's current stack.
|
|
|
|
* This conforms to SUSv2.
|
|
|
|
*/
|
|
|
|
if (limp->rlim_cur < p->p_vmspace->vm_ssize * PAGE_SIZE
|
2007-02-10 00:55:00 +03:00
|
|
|
|| limp->rlim_max < p->p_vmspace->vm_ssize * PAGE_SIZE) {
|
2001-11-23 21:56:33 +03:00
|
|
|
return (EINVAL);
|
2007-02-10 00:55:00 +03:00
|
|
|
}
|
2001-11-23 21:56:33 +03:00
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/*
|
1997-10-09 05:04:13 +04:00
|
|
|
* Stack is allocated to the max at exec time with
|
|
|
|
* only "rlim_cur" bytes accessible (In other words,
|
|
|
|
* allocates stack dividing two contiguous regions at
|
|
|
|
* "rlim_cur" bytes boundary).
|
|
|
|
*
|
|
|
|
* Since allocation is done in terms of page, roundup
|
|
|
|
* "rlim_cur" (otherwise, contiguous regions
|
|
|
|
* overlap). If stack limit is going up make more
|
|
|
|
* accessible, if going down make inaccessible.
|
1994-05-17 08:21:49 +04:00
|
|
|
*/
|
1997-10-09 05:04:13 +04:00
|
|
|
limp->rlim_cur = round_page(limp->rlim_cur);
|
1994-05-17 08:21:49 +04:00
|
|
|
if (limp->rlim_cur != alimp->rlim_cur) {
|
1998-08-13 06:10:37 +04:00
|
|
|
vaddr_t addr;
|
|
|
|
vsize_t size;
|
1994-05-17 08:21:49 +04:00
|
|
|
vm_prot_t prot;
|
|
|
|
|
|
|
|
if (limp->rlim_cur > alimp->rlim_cur) {
|
2003-08-24 21:52:28 +04:00
|
|
|
prot = VM_PROT_READ | VM_PROT_WRITE;
|
1994-05-17 08:21:49 +04:00
|
|
|
size = limp->rlim_cur - alimp->rlim_cur;
|
2005-03-26 08:12:34 +03:00
|
|
|
addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
|
|
|
|
limp->rlim_cur;
|
1994-05-17 08:21:49 +04:00
|
|
|
} else {
|
|
|
|
prot = VM_PROT_NONE;
|
|
|
|
size = alimp->rlim_cur - limp->rlim_cur;
|
2005-03-26 08:12:34 +03:00
|
|
|
addr = (vaddr_t)p->p_vmspace->vm_minsaddr -
|
|
|
|
alimp->rlim_cur;
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
1998-02-05 10:59:28 +03:00
|
|
|
(void) uvm_map_protect(&p->p_vmspace->vm_map,
|
2007-02-22 09:34:42 +03:00
|
|
|
addr, addr+size, prot, false);
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
break;
|
1994-05-19 12:13:09 +04:00
|
|
|
|
|
|
|
case RLIMIT_NOFILE:
|
|
|
|
if (limp->rlim_cur > maxfiles)
|
|
|
|
limp->rlim_cur = maxfiles;
|
|
|
|
if (limp->rlim_max > maxfiles)
|
|
|
|
limp->rlim_max = maxfiles;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RLIMIT_NPROC:
|
|
|
|
if (limp->rlim_cur > maxproc)
|
|
|
|
limp->rlim_cur = maxproc;
|
|
|
|
if (limp->rlim_max > maxproc)
|
|
|
|
limp->rlim_max = maxproc;
|
|
|
|
break;
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
2007-09-29 16:22:30 +04:00
|
|
|
|
|
|
|
mutex_enter(&p->p_limit->pl_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
*alimp = *limp;
|
2007-09-29 16:22:30 +04:00
|
|
|
mutex_exit(&p->p_limit->pl_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2008-03-17 03:18:24 +03:00
|
|
|
sys_getrlimit(struct lwp *l, const struct sys_getrlimit_args *uap,
|
|
|
|
register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
1997-10-15 21:03:52 +04:00
|
|
|
syscallarg(int) which;
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(struct rlimit *) rlp;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
1997-10-15 21:03:52 +04:00
|
|
|
int which = SCARG(uap, which);
|
2007-08-08 18:07:11 +04:00
|
|
|
struct rlimit rl;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2002-10-03 09:18:59 +04:00
|
|
|
if ((u_int)which >= RLIM_NLIMITS)
|
1994-05-17 08:21:49 +04:00
|
|
|
return (EINVAL);
|
2007-08-08 18:07:11 +04:00
|
|
|
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2007-08-08 18:07:11 +04:00
|
|
|
memcpy(&rl, &p->p_rlimit[which], sizeof(rl));
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
2007-08-08 18:07:11 +04:00
|
|
|
|
|
|
|
return copyout(&rl, SCARG(uap, rlp), sizeof(rl));
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Transform the running time and tick information in proc p into user,
|
|
|
|
* system, and interrupt time usage.
|
2007-02-10 00:55:00 +03:00
|
|
|
*
|
2008-04-24 22:39:20 +04:00
|
|
|
* Should be called with p->p_lock held unless called from exit1().
|
1994-05-17 08:21:49 +04:00
|
|
|
*/
|
1994-12-24 18:07:22 +03:00
|
|
|
void
|
2005-06-24 03:15:12 +04:00
|
|
|
calcru(struct proc *p, struct timeval *up, struct timeval *sp,
|
2007-02-10 00:55:00 +03:00
|
|
|
struct timeval *ip, struct timeval *rp)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
2007-12-22 04:14:53 +03:00
|
|
|
uint64_t u, st, ut, it, tot;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct lwp *l;
|
2007-12-22 04:14:53 +03:00
|
|
|
struct bintime tm;
|
|
|
|
struct timeval tv;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2007-02-10 00:55:00 +03:00
|
|
|
mutex_spin_enter(&p->p_stmutex);
|
1994-05-17 08:21:49 +04:00
|
|
|
st = p->p_sticks;
|
|
|
|
ut = p->p_uticks;
|
|
|
|
it = p->p_iticks;
|
2007-02-10 00:55:00 +03:00
|
|
|
mutex_spin_exit(&p->p_stmutex);
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2007-12-22 04:14:53 +03:00
|
|
|
tm = p->p_rtime;
|
2007-02-10 00:55:00 +03:00
|
|
|
|
2003-03-15 00:38:26 +03:00
|
|
|
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
|
2007-02-10 00:55:00 +03:00
|
|
|
lwp_lock(l);
|
2007-12-22 04:14:53 +03:00
|
|
|
bintime_add(&tm, &l->l_rtime);
|
2007-10-09 00:06:17 +04:00
|
|
|
if ((l->l_flag & LW_RUNNING) != 0) {
|
2007-12-22 04:14:53 +03:00
|
|
|
struct bintime diff;
|
2003-01-18 13:06:22 +03:00
|
|
|
/*
|
|
|
|
* Adjust for the current time slice. This is
|
|
|
|
* actually fairly important since the error
|
|
|
|
* here is on the order of a time quantum,
|
|
|
|
* which is much greater than the sampling
|
2005-02-27 00:34:55 +03:00
|
|
|
* error.
|
2003-01-18 13:06:22 +03:00
|
|
|
*/
|
2007-12-22 04:14:53 +03:00
|
|
|
binuptime(&diff);
|
|
|
|
bintime_sub(&diff, &l->l_stime);
|
|
|
|
bintime_add(&tm, &diff);
|
2003-01-18 13:06:22 +03:00
|
|
|
}
|
2007-02-10 00:55:00 +03:00
|
|
|
lwp_unlock(l);
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
2003-03-05 14:44:01 +03:00
|
|
|
|
|
|
|
tot = st + ut + it;
|
2007-12-22 04:14:53 +03:00
|
|
|
bintime2timeval(&tm, &tv);
|
|
|
|
u = (uint64_t)tv.tv_sec * 1000000ul + tv.tv_usec;
|
2003-03-15 00:38:26 +03:00
|
|
|
|
2003-03-05 14:44:01 +03:00
|
|
|
if (tot == 0) {
|
|
|
|
/* No ticks, so can't use to share time out, split 50-50 */
|
2003-03-15 00:38:26 +03:00
|
|
|
st = ut = u / 2;
|
|
|
|
} else {
|
|
|
|
st = (u * st) / tot;
|
|
|
|
ut = (u * ut) / tot;
|
2003-03-05 14:44:01 +03:00
|
|
|
}
|
2007-02-10 00:55:00 +03:00
|
|
|
if (sp != NULL) {
|
|
|
|
sp->tv_sec = st / 1000000;
|
|
|
|
sp->tv_usec = st % 1000000;
|
|
|
|
}
|
|
|
|
if (up != NULL) {
|
|
|
|
up->tv_sec = ut / 1000000;
|
|
|
|
up->tv_usec = ut % 1000000;
|
|
|
|
}
|
1994-05-17 08:21:49 +04:00
|
|
|
if (ip != NULL) {
|
2003-03-15 00:38:26 +03:00
|
|
|
if (it != 0)
|
|
|
|
it = (u * it) / tot;
|
1994-05-17 08:21:49 +04:00
|
|
|
ip->tv_sec = it / 1000000;
|
|
|
|
ip->tv_usec = it % 1000000;
|
|
|
|
}
|
2007-02-10 00:55:00 +03:00
|
|
|
if (rp != NULL) {
|
2007-12-22 04:14:53 +03:00
|
|
|
*rp = tv;
|
2007-02-10 00:55:00 +03:00
|
|
|
}
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
1994-12-24 18:07:22 +03:00
|
|
|
int
|
2008-03-17 03:18:24 +03:00
|
|
|
sys_getrusage(struct lwp *l, const struct sys_getrusage_args *uap,
|
|
|
|
register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2007-12-21 02:02:38 +03:00
|
|
|
/* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int) who;
|
|
|
|
syscallarg(struct rusage *) rusage;
|
2007-12-21 02:02:38 +03:00
|
|
|
} */
|
2007-08-08 18:07:11 +04:00
|
|
|
struct rusage ru;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
switch (SCARG(uap, who)) {
|
1994-05-19 12:13:09 +04:00
|
|
|
case RUSAGE_SELF:
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2007-08-08 18:07:11 +04:00
|
|
|
memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
|
|
|
|
calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
|
2008-03-27 22:06:51 +03:00
|
|
|
rulwps(p, &ru);
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case RUSAGE_CHILDREN:
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2007-08-08 18:07:11 +04:00
|
|
|
memcpy(&ru, &p->p_stats->p_cru, sizeof(ru));
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
1994-05-17 08:21:49 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-08-08 18:07:11 +04:00
|
|
|
return EINVAL;
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
2007-08-08 18:07:11 +04:00
|
|
|
|
|
|
|
return copyout(&ru, SCARG(uap, rusage), sizeof(ru));
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
|
1994-12-24 18:07:22 +03:00
|
|
|
void
|
2005-06-24 03:15:12 +04:00
|
|
|
ruadd(struct rusage *ru, struct rusage *ru2)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
2000-03-30 13:27:11 +04:00
|
|
|
long *ip, *ip2;
|
|
|
|
int i;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
1995-03-21 16:33:34 +03:00
|
|
|
timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
|
|
|
|
timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
|
1994-05-17 08:21:49 +04:00
|
|
|
if (ru->ru_maxrss < ru2->ru_maxrss)
|
|
|
|
ru->ru_maxrss = ru2->ru_maxrss;
|
|
|
|
ip = &ru->ru_first; ip2 = &ru2->ru_first;
|
|
|
|
for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
|
|
|
|
*ip++ += *ip2++;
|
|
|
|
}
|
|
|
|
|
2008-03-27 22:06:51 +03:00
|
|
|
void
|
|
|
|
rulwps(proc_t *p, struct rusage *ru)
|
|
|
|
{
|
|
|
|
lwp_t *l;
|
|
|
|
|
2008-04-24 22:39:20 +04:00
|
|
|
KASSERT(mutex_owned(p->p_lock));
|
2008-03-27 22:06:51 +03:00
|
|
|
|
|
|
|
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
|
|
|
|
ruadd(ru, &l->l_ru);
|
|
|
|
ru->ru_nvcsw += (l->l_ncsw - l->l_nivcsw);
|
|
|
|
ru->ru_nivcsw += l->l_nivcsw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/*
|
|
|
|
* Make a copy of the plimit structure.
|
|
|
|
* We share these structures copy-on-write after fork,
|
|
|
|
* and copy when a limit is changed.
|
2007-02-10 00:55:00 +03:00
|
|
|
*
|
2007-09-29 16:22:30 +04:00
|
|
|
* Unfortunately (due to PL_SHAREMOD) it is possibly for the structure
|
|
|
|
* we are copying to change beneath our feet!
|
1994-05-17 08:21:49 +04:00
|
|
|
*/
|
|
|
|
struct plimit *
|
2007-09-29 16:22:30 +04:00
|
|
|
lim_copy(struct plimit *lim)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
2007-09-29 16:22:30 +04:00
|
|
|
struct plimit *newlim;
|
2007-02-10 00:55:00 +03:00
|
|
|
char *corename;
|
2007-09-29 16:22:30 +04:00
|
|
|
size_t alen, len;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2007-12-26 19:01:34 +03:00
|
|
|
newlim = pool_cache_get(plimit_cache, PR_WAITOK);
|
2007-09-21 23:19:20 +04:00
|
|
|
mutex_init(&newlim->pl_lock, MUTEX_DEFAULT, IPL_NONE);
|
|
|
|
newlim->pl_flags = 0;
|
|
|
|
newlim->pl_refcnt = 1;
|
2007-09-29 16:22:30 +04:00
|
|
|
newlim->pl_sv_limit = NULL;
|
2007-02-10 00:55:00 +03:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
mutex_enter(&lim->pl_lock);
|
|
|
|
memcpy(newlim->pl_rlimit, lim->pl_rlimit,
|
|
|
|
sizeof(struct rlimit) * RLIM_NLIMITS);
|
2007-02-10 00:55:00 +03:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
alen = 0;
|
|
|
|
corename = NULL;
|
|
|
|
for (;;) {
|
|
|
|
if (lim->pl_corename == defcorename) {
|
2007-02-10 00:55:00 +03:00
|
|
|
newlim->pl_corename = defcorename;
|
2007-09-29 16:22:30 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
len = strlen(lim->pl_corename) + 1;
|
|
|
|
if (len <= alen) {
|
|
|
|
newlim->pl_corename = corename;
|
|
|
|
memcpy(corename, lim->pl_corename, len);
|
|
|
|
corename = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2007-09-21 23:19:20 +04:00
|
|
|
mutex_exit(&lim->pl_lock);
|
2007-09-29 16:22:30 +04:00
|
|
|
if (corename != NULL)
|
|
|
|
free(corename, M_TEMP);
|
|
|
|
alen = len;
|
|
|
|
corename = malloc(alen, M_TEMP, M_WAITOK);
|
|
|
|
mutex_enter(&lim->pl_lock);
|
2007-02-10 00:55:00 +03:00
|
|
|
}
|
2007-09-29 16:22:30 +04:00
|
|
|
mutex_exit(&lim->pl_lock);
|
|
|
|
if (corename != NULL)
|
|
|
|
free(corename, M_TEMP);
|
|
|
|
return newlim;
|
|
|
|
}
|
2004-05-07 02:20:30 +04:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
void
|
|
|
|
lim_addref(struct plimit *lim)
|
|
|
|
{
|
2007-11-29 21:21:03 +03:00
|
|
|
atomic_inc_uint(&lim->pl_refcnt);
|
2007-09-29 16:22:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Give a process it's own private plimit structure.
|
|
|
|
* This will only be shared (in fork) if modifications are to be shared.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
lim_privatise(struct proc *p, bool set_shared)
|
|
|
|
{
|
|
|
|
struct plimit *lim, *newlim;
|
|
|
|
|
|
|
|
lim = p->p_limit;
|
|
|
|
if (lim->pl_flags & PL_WRITEABLE) {
|
|
|
|
if (set_shared)
|
|
|
|
lim->pl_flags |= PL_SHAREMOD;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (set_shared && lim->pl_flags & PL_SHAREMOD)
|
|
|
|
return;
|
|
|
|
|
|
|
|
newlim = lim_copy(lim);
|
|
|
|
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(p->p_lock);
|
2007-09-29 16:22:30 +04:00
|
|
|
if (p->p_limit->pl_flags & PL_WRITEABLE) {
|
|
|
|
/* Someone crept in while we were busy */
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
2007-09-29 16:22:30 +04:00
|
|
|
limfree(newlim);
|
|
|
|
if (set_shared)
|
|
|
|
p->p_limit->pl_flags |= PL_SHAREMOD;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since most accesses to p->p_limit aren't locked, we must not
|
|
|
|
* delete the old limit structure yet.
|
|
|
|
*/
|
|
|
|
newlim->pl_sv_limit = p->p_limit;
|
|
|
|
newlim->pl_flags |= PL_WRITEABLE;
|
|
|
|
if (set_shared)
|
|
|
|
newlim->pl_flags |= PL_SHAREMOD;
|
|
|
|
p->p_limit = newlim;
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(p->p_lock);
|
1995-12-09 07:09:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-06-24 03:15:12 +04:00
|
|
|
limfree(struct plimit *lim)
|
1995-12-09 07:09:32 +03:00
|
|
|
{
|
2007-09-29 16:22:30 +04:00
|
|
|
struct plimit *sv_lim;
|
2004-05-13 21:56:14 +04:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
do {
|
2007-11-29 21:21:03 +03:00
|
|
|
if (atomic_dec_uint_nv(&lim->pl_refcnt) > 0)
|
2007-09-29 16:22:30 +04:00
|
|
|
return;
|
|
|
|
if (lim->pl_corename != defcorename)
|
|
|
|
free(lim->pl_corename, M_TEMP);
|
|
|
|
sv_lim = lim->pl_sv_limit;
|
|
|
|
mutex_destroy(&lim->pl_lock);
|
2007-12-26 19:01:34 +03:00
|
|
|
pool_cache_put(plimit_cache, lim);
|
2007-09-29 16:22:30 +04:00
|
|
|
} while ((lim = sv_lim) != NULL);
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
2003-01-18 13:06:22 +03:00
|
|
|
|
|
|
|
struct pstats *
|
2005-06-24 03:15:12 +04:00
|
|
|
pstatscopy(struct pstats *ps)
|
2003-01-18 13:06:22 +03:00
|
|
|
{
|
2005-02-27 00:34:55 +03:00
|
|
|
|
2003-01-18 13:06:22 +03:00
|
|
|
struct pstats *newps;
|
|
|
|
|
2007-12-26 19:01:34 +03:00
|
|
|
newps = pool_cache_get(pstats_cache, PR_WAITOK);
|
2003-01-18 13:06:22 +03:00
|
|
|
|
|
|
|
memset(&newps->pstat_startzero, 0,
|
2007-03-04 08:59:00 +03:00
|
|
|
(unsigned) ((char *)&newps->pstat_endzero -
|
|
|
|
(char *)&newps->pstat_startzero));
|
2003-01-18 13:06:22 +03:00
|
|
|
memcpy(&newps->pstat_startcopy, &ps->pstat_startcopy,
|
2007-03-04 08:59:00 +03:00
|
|
|
((char *)&newps->pstat_endcopy -
|
|
|
|
(char *)&newps->pstat_startcopy));
|
2003-01-18 13:06:22 +03:00
|
|
|
|
|
|
|
return (newps);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-06-24 03:15:12 +04:00
|
|
|
pstatsfree(struct pstats *ps)
|
2003-01-18 13:06:22 +03:00
|
|
|
{
|
|
|
|
|
2007-12-26 19:01:34 +03:00
|
|
|
pool_cache_put(pstats_cache, ps);
|
2003-01-18 13:06:22 +03:00
|
|
|
}
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* sysctl interface in five parts
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* a routine for sysctl proc subtree helpers that need to pick a valid
|
|
|
|
* process by pid.
|
|
|
|
*/
|
|
|
|
static int
|
2006-07-24 02:06:03 +04:00
|
|
|
sysctl_proc_findproc(struct lwp *l, struct proc **p2, pid_t pid)
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
{
|
|
|
|
struct proc *ptmp;
|
2006-05-15 01:15:11 +04:00
|
|
|
int error = 0;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
|
|
|
if (pid == PROC_CURPROC)
|
2006-07-24 02:06:03 +04:00
|
|
|
ptmp = l->l_proc;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
else if ((ptmp = pfind(pid)) == NULL)
|
|
|
|
error = ESRCH;
|
|
|
|
|
|
|
|
*p2 = ptmp;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sysctl helper routine for setting a process's specific corefile
|
|
|
|
* name. picks the process based on the given pid and checks the
|
|
|
|
* correctness of the new value.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
sysctl_proc_corename(SYSCTLFN_ARGS)
|
|
|
|
{
|
2006-07-24 02:06:03 +04:00
|
|
|
struct proc *ptmp;
|
2004-05-07 02:20:30 +04:00
|
|
|
struct plimit *lim;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
int error = 0, len;
|
2006-02-04 15:09:50 +03:00
|
|
|
char *cname;
|
2007-09-29 16:22:30 +04:00
|
|
|
char *ocore;
|
2006-02-04 15:09:50 +03:00
|
|
|
char *tmp;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
struct sysctlnode node;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* is this all correct?
|
|
|
|
*/
|
|
|
|
if (namelen != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
if (name[-1] != PROC_PID_CORENAME)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* whom are we tweaking?
|
|
|
|
*/
|
2006-07-24 02:06:03 +04:00
|
|
|
error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
/* XXX-elad */
|
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
|
|
|
|
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
|
2006-12-14 14:45:08 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
if (newp == NULL) {
|
|
|
|
error = kauth_authorize_process(l->l_cred,
|
|
|
|
KAUTH_PROCESS_CORENAME, ptmp,
|
|
|
|
KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_GET), NULL, NULL);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
/*
|
|
|
|
* let them modify a temporary copy of the core name
|
|
|
|
*/
|
2007-09-29 16:22:30 +04:00
|
|
|
cname = PNBUF_GET();
|
|
|
|
lim = ptmp->p_limit;
|
|
|
|
mutex_enter(&lim->pl_lock);
|
|
|
|
strlcpy(cname, lim->pl_corename, MAXPATHLEN);
|
|
|
|
mutex_exit(&lim->pl_lock);
|
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
node = *rnode;
|
|
|
|
node.sysctl_data = cname;
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* if that failed, or they have nothing new to say, or we've
|
|
|
|
* heard it before...
|
|
|
|
*/
|
2007-09-29 16:22:30 +04:00
|
|
|
if (error || newp == NULL)
|
|
|
|
goto done;
|
|
|
|
lim = ptmp->p_limit;
|
|
|
|
mutex_enter(&lim->pl_lock);
|
|
|
|
error = strcmp(cname, lim->pl_corename);
|
|
|
|
mutex_exit(&lim->pl_lock);
|
|
|
|
if (error == 0)
|
|
|
|
/* Unchanged */
|
2006-02-04 15:09:50 +03:00
|
|
|
goto done;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
2006-12-14 14:45:08 +03:00
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CORENAME,
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_CORENAME_SET), cname, NULL);
|
2006-12-14 14:45:08 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2006-07-30 21:38:19 +04:00
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
/*
|
|
|
|
* no error yet and cname now has the new core name in it.
|
|
|
|
* let's see if it looks acceptable. it must be either "core"
|
|
|
|
* or end in ".core" or "/core".
|
|
|
|
*/
|
|
|
|
len = strlen(cname);
|
2006-02-04 15:09:50 +03:00
|
|
|
if (len < 4) {
|
|
|
|
error = EINVAL;
|
|
|
|
} else if (strcmp(cname + len - 4, "core") != 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
} else if (len > 4 && cname[len - 5] != '/' && cname[len - 5] != '.') {
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
|
|
|
if (error != 0) {
|
|
|
|
goto done;
|
|
|
|
}
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* hmm...looks good. now...where do we put it?
|
|
|
|
*/
|
|
|
|
tmp = malloc(len + 1, M_TEMP, M_WAITOK|M_CANFAIL);
|
2006-02-04 15:09:50 +03:00
|
|
|
if (tmp == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
2007-09-29 16:22:30 +04:00
|
|
|
memcpy(tmp, cname, len + 1);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
2007-09-29 16:22:30 +04:00
|
|
|
lim_privatise(ptmp, false);
|
2004-05-07 02:20:30 +04:00
|
|
|
lim = ptmp->p_limit;
|
2007-09-29 16:22:30 +04:00
|
|
|
mutex_enter(&lim->pl_lock);
|
|
|
|
ocore = lim->pl_corename;
|
2004-05-07 02:20:30 +04:00
|
|
|
lim->pl_corename = tmp;
|
2007-09-29 16:22:30 +04:00
|
|
|
mutex_exit(&lim->pl_lock);
|
|
|
|
if (ocore != defcorename)
|
|
|
|
free(ocore, M_TEMP);
|
|
|
|
|
2006-02-04 15:09:50 +03:00
|
|
|
done:
|
|
|
|
PNBUF_PUT(cname);
|
|
|
|
return error;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sysctl helper routine for checking/setting a process's stop flags,
|
|
|
|
* one for fork and one for exec.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
sysctl_proc_stop(SYSCTLFN_ARGS)
|
|
|
|
{
|
2006-07-24 02:06:03 +04:00
|
|
|
struct proc *ptmp;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
int i, f, error = 0;
|
|
|
|
struct sysctlnode node;
|
|
|
|
|
|
|
|
if (namelen != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2006-07-24 02:06:03 +04:00
|
|
|
error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-2]);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
/* XXX-elad */
|
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
|
|
|
|
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
|
2006-12-14 14:45:08 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
switch (rnode->sysctl_num) {
|
|
|
|
case PROC_PID_STOPFORK:
|
2007-02-10 00:55:00 +03:00
|
|
|
f = PS_STOPFORK;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
break;
|
|
|
|
case PROC_PID_STOPEXEC:
|
2007-02-10 00:55:00 +03:00
|
|
|
f = PS_STOPEXEC;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
break;
|
|
|
|
case PROC_PID_STOPEXIT:
|
2007-02-10 00:55:00 +03:00
|
|
|
f = PS_STOPEXIT;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
i = (ptmp->p_flag & f) ? 1 : 0;
|
|
|
|
node = *rnode;
|
|
|
|
node.sysctl_data = &i;
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
|
|
|
if (error || newp == NULL)
|
|
|
|
return (error);
|
|
|
|
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_enter(ptmp->p_lock);
|
2006-12-14 14:45:08 +03:00
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_STOPFLAG,
|
|
|
|
ptmp, KAUTH_ARG(f), NULL, NULL);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
if (i)
|
2007-02-10 00:55:00 +03:00
|
|
|
ptmp->p_sflag |= f;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
else
|
2007-02-10 00:55:00 +03:00
|
|
|
ptmp->p_sflag &= ~f;
|
2008-04-24 22:39:20 +04:00
|
|
|
mutex_exit(ptmp->p_lock);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sysctl helper routine for a process's rlimits as exposed by sysctl.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
sysctl_proc_plimit(SYSCTLFN_ARGS)
|
|
|
|
{
|
2006-07-24 02:06:03 +04:00
|
|
|
struct proc *ptmp;
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
u_int limitno;
|
|
|
|
int which, error = 0;
|
|
|
|
struct rlimit alim;
|
|
|
|
struct sysctlnode node;
|
|
|
|
|
|
|
|
if (namelen != 0)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
which = name[-1];
|
|
|
|
if (which != PROC_PID_LIMIT_TYPE_SOFT &&
|
|
|
|
which != PROC_PID_LIMIT_TYPE_HARD)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
limitno = name[-2] - 1;
|
|
|
|
if (limitno >= RLIM_NLIMITS)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
if (name[-3] != PROC_PID_LIMIT)
|
|
|
|
return (EINVAL);
|
|
|
|
|
2006-07-24 02:06:03 +04:00
|
|
|
error = sysctl_proc_findproc(l, &ptmp, (pid_t)name[-4]);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
/* XXX-elad */
|
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE, ptmp,
|
|
|
|
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
|
2006-12-14 14:45:08 +03:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
Tons of process scope changes.
- Add a KAUTH_PROCESS_SCHEDULER action, to handle scheduler related
requests, and add specific requests for set/get scheduler policy and
set/get scheduler parameters.
- Add a KAUTH_PROCESS_KEVENT_FILTER action, to handle kevent(2) related
requests.
- Add a KAUTH_DEVICE_TTY_STI action to handle requests to TIOCSTI.
- Add requests for the KAUTH_PROCESS_CANSEE action, indicating what
process information is being looked at (entry itself, args, env,
open files).
- Add requests for the KAUTH_PROCESS_RLIMIT action indicating set/get.
- Add requests for the KAUTH_PROCESS_CORENAME action indicating set/get.
- Make bsd44 secmodel code handle the newly added rqeuests appropriately.
All of the above make it possible to issue finer-grained kauth(9) calls in
many places, removing some KAUTH_GENERIC_ISSUSER requests.
- Remove the "CAN" from KAUTH_PROCESS_CAN{KTRACE,PROCFS,PTRACE,SIGNAL}.
Discussed with christos@ and yamt@.
2008-01-23 18:04:38 +03:00
|
|
|
/* Check if we can view limits. */
|
|
|
|
if (newp == NULL) {
|
|
|
|
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_RLIMIT,
|
|
|
|
ptmp, KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_GET), &alim,
|
|
|
|
KAUTH_ARG(which));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
node = *rnode;
|
|
|
|
memcpy(&alim, &ptmp->p_rlimit[limitno], sizeof(alim));
|
|
|
|
if (which == PROC_PID_LIMIT_TYPE_HARD)
|
|
|
|
node.sysctl_data = &alim.rlim_max;
|
|
|
|
else
|
|
|
|
node.sysctl_data = &alim.rlim_cur;
|
|
|
|
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
|
|
|
if (error || newp == NULL)
|
|
|
|
return (error);
|
|
|
|
|
2006-07-24 02:06:03 +04:00
|
|
|
return (dosetrlimit(l, ptmp, limitno, &alim));
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* and finally, the actually glue that sticks it to the tree
|
|
|
|
*/
|
|
|
|
SYSCTL_SETUP(sysctl_proc_setup, "sysctl proc subtree setup")
|
|
|
|
{
|
|
|
|
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
CTLTYPE_NODE, "proc", NULL,
|
|
|
|
NULL, 0, NULL, 0,
|
|
|
|
CTL_PROC, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_ANYNUMBER,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_NODE, "curproc",
|
|
|
|
SYSCTL_DESCR("Per-process settings"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
NULL, 0, NULL, 0,
|
|
|
|
CTL_PROC, PROC_CURPROC, CTL_EOL);
|
|
|
|
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
2006-07-30 21:38:19 +04:00
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_STRING, "corename",
|
|
|
|
SYSCTL_DESCR("Core file name"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_corename, 0, NULL, MAXPATHLEN,
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_CORENAME, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_NODE, "rlimit",
|
|
|
|
SYSCTL_DESCR("Process limits"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
NULL, 0, NULL, 0,
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, CTL_EOL);
|
|
|
|
|
|
|
|
#define create_proc_plimit(s, n) do { \
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL, \
|
|
|
|
CTLFLAG_PERMANENT, \
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_NODE, s, \
|
|
|
|
SYSCTL_DESCR("Process " s " limits"), \
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
NULL, 0, NULL, 0, \
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
|
|
|
|
CTL_EOL); \
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL, \
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_QUAD, "soft", \
|
|
|
|
SYSCTL_DESCR("Process soft " s " limit"), \
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_plimit, 0, NULL, 0, \
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
|
|
|
|
PROC_PID_LIMIT_TYPE_SOFT, CTL_EOL); \
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL, \
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE, \
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_QUAD, "hard", \
|
|
|
|
SYSCTL_DESCR("Process hard " s " limit"), \
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_plimit, 0, NULL, 0, \
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_LIMIT, n, \
|
|
|
|
PROC_PID_LIMIT_TYPE_HARD, CTL_EOL); \
|
|
|
|
} while (0/*CONSTCOND*/)
|
|
|
|
|
|
|
|
create_proc_plimit("cputime", PROC_PID_LIMIT_CPU);
|
|
|
|
create_proc_plimit("filesize", PROC_PID_LIMIT_FSIZE);
|
|
|
|
create_proc_plimit("datasize", PROC_PID_LIMIT_DATA);
|
|
|
|
create_proc_plimit("stacksize", PROC_PID_LIMIT_STACK);
|
|
|
|
create_proc_plimit("coredumpsize", PROC_PID_LIMIT_CORE);
|
|
|
|
create_proc_plimit("memoryuse", PROC_PID_LIMIT_RSS);
|
|
|
|
create_proc_plimit("memorylocked", PROC_PID_LIMIT_MEMLOCK);
|
|
|
|
create_proc_plimit("maxproc", PROC_PID_LIMIT_NPROC);
|
|
|
|
create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE);
|
2004-04-17 19:15:29 +04:00
|
|
|
create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE);
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
|
|
|
|
#undef create_proc_plimit
|
|
|
|
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_INT, "stopfork",
|
|
|
|
SYSCTL_DESCR("Stop process at fork(2)"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_stop, 0, NULL, 0,
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_STOPFORK, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_INT, "stopexec",
|
|
|
|
SYSCTL_DESCR("Stop process at execve(2)"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_stop, 0, NULL, 0,
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXEC, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
|
2004-04-08 10:20:29 +04:00
|
|
|
CTLTYPE_INT, "stopexit",
|
|
|
|
SYSCTL_DESCR("Stop process before completing exit"),
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
sysctl_proc_stop, 0, NULL, 0,
|
|
|
|
CTL_PROC, PROC_CURPROC, PROC_PID_STOPEXIT, CTL_EOL);
|
|
|
|
}
|
2004-04-17 19:15:29 +04:00
|
|
|
|
2007-07-10 00:51:58 +04:00
|
|
|
void
|
|
|
|
uid_init(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ensure that uid 0 is always in the user hash table, as
|
|
|
|
* sbreserve() expects it available from interrupt context.
|
|
|
|
*/
|
|
|
|
(void)uid_find(0);
|
|
|
|
}
|
|
|
|
|
2005-03-20 22:15:48 +03:00
|
|
|
struct uidinfo *
|
|
|
|
uid_find(uid_t uid)
|
2004-04-17 19:15:29 +04:00
|
|
|
{
|
2008-03-18 05:35:29 +03:00
|
|
|
struct uidinfo *uip, *uip_first, *newuip;
|
2004-04-17 19:15:29 +04:00
|
|
|
struct uihashhead *uipp;
|
|
|
|
|
|
|
|
uipp = UIHASH(uid);
|
2008-03-18 05:35:29 +03:00
|
|
|
newuip = NULL;
|
|
|
|
|
2008-03-18 00:16:03 +03:00
|
|
|
/*
|
|
|
|
* To make insertion atomic, abstraction of SLIST will be violated.
|
|
|
|
*/
|
|
|
|
uip_first = uipp->slh_first;
|
2008-03-18 05:35:29 +03:00
|
|
|
again:
|
2008-03-18 00:16:03 +03:00
|
|
|
SLIST_FOREACH(uip, uipp, ui_hash) {
|
|
|
|
if (uip->ui_uid != uid)
|
|
|
|
continue;
|
2008-03-18 05:35:29 +03:00
|
|
|
if (newuip != NULL)
|
2008-03-18 00:16:03 +03:00
|
|
|
kmem_free(newuip, sizeof(*newuip));
|
|
|
|
return uip;
|
|
|
|
}
|
2008-03-18 05:35:29 +03:00
|
|
|
if (newuip == NULL)
|
2008-01-29 15:41:59 +03:00
|
|
|
newuip = kmem_zalloc(sizeof(*newuip), KM_SLEEP);
|
2008-03-18 05:35:29 +03:00
|
|
|
newuip->ui_uid = uid;
|
2008-03-18 00:16:03 +03:00
|
|
|
|
|
|
|
/*
|
2008-03-18 05:35:29 +03:00
|
|
|
* If atomic insert is unsuccessful, another thread might be
|
2008-03-18 00:16:03 +03:00
|
|
|
* allocated this 'uid', thus full re-check is needed.
|
|
|
|
*/
|
2008-03-18 05:35:29 +03:00
|
|
|
newuip->ui_hash.sle_next = uip_first;
|
|
|
|
membar_producer();
|
|
|
|
uip = atomic_cas_ptr(&uipp->slh_first, uip_first, newuip);
|
|
|
|
if (uip != uip_first) {
|
|
|
|
uip_first = uip;
|
2008-03-18 00:16:03 +03:00
|
|
|
goto again;
|
2008-03-18 05:35:29 +03:00
|
|
|
}
|
2005-03-23 04:16:44 +03:00
|
|
|
|
2008-03-18 05:35:29 +03:00
|
|
|
return newuip;
|
2004-04-17 19:15:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change the count associated with number of processes
|
|
|
|
* a given user is using.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
chgproccnt(uid_t uid, int diff)
|
|
|
|
{
|
|
|
|
struct uidinfo *uip;
|
2008-03-18 00:16:03 +03:00
|
|
|
long proccnt;
|
2004-04-17 19:15:29 +04:00
|
|
|
|
2005-03-20 22:15:48 +03:00
|
|
|
uip = uid_find(uid);
|
2008-03-18 00:16:03 +03:00
|
|
|
proccnt = atomic_add_long_nv(&uip->ui_proccnt, diff);
|
|
|
|
KASSERT(proccnt >= 0);
|
|
|
|
return proccnt;
|
2004-04-17 19:15:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2005-05-30 02:24:14 +04:00
|
|
|
chgsbsize(struct uidinfo *uip, u_long *hiwat, u_long to, rlim_t xmax)
|
2004-04-17 19:15:29 +04:00
|
|
|
{
|
|
|
|
rlim_t nsb;
|
2008-03-18 00:16:03 +03:00
|
|
|
const long diff = to - *hiwat;
|
2004-04-17 19:15:29 +04:00
|
|
|
|
2008-03-18 00:16:03 +03:00
|
|
|
nsb = atomic_add_long_nv((long *)&uip->ui_sbsize, diff);
|
|
|
|
if (diff > 0 && nsb > xmax) {
|
|
|
|
atomic_add_long((long *)&uip->ui_sbsize, -diff);
|
2005-03-20 22:15:48 +03:00
|
|
|
return 0;
|
2005-05-07 21:42:09 +04:00
|
|
|
}
|
2004-04-17 19:15:29 +04:00
|
|
|
*hiwat = to;
|
2008-03-18 00:16:03 +03:00
|
|
|
KASSERT(nsb >= 0);
|
2005-03-20 22:15:48 +03:00
|
|
|
return 1;
|
2004-04-17 19:15:29 +04:00
|
|
|
}
|