Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add a new resource to limit the number of lwps per user, ...
details: https://anonhg.NetBSD.org/src/rev/939101df3867
branches: trunk
changeset: 779654:939101df3867
user: christos <christos%NetBSD.org@localhost>
date: Sat Jun 09 02:31:14 2012 +0000
description:
Add a new resource to limit the number of lwps per user, RLIMIT_NTHR. There
is a global sysctl kern.maxlwp to control this, which is by default 2048.
The first lwp of each process or kernel threads are not counted against the
limit. To show the current resource usage per user, I added a new sysctl
that dumps the uidinfo structure fields.
diffstat:
sys/conf/param.c | 6 +-
sys/kern/kern_lwp.c | 76 ++++++++++++++++++++++++++++++++++-
sys/kern/kern_proc.c | 7 ++-
sys/kern/kern_prot.c | 12 ++++-
sys/kern/kern_resource.c | 12 ++++-
sys/kern/kern_uidinfo.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-
sys/sys/lwp.h | 9 +++-
sys/sys/resource.h | 5 +-
sys/sys/sysctl.h | 4 +-
sys/sys/uidinfo.h | 4 +-
10 files changed, 219 insertions(+), 17 deletions(-)
diffs (truncated from 495 to 300 lines):
diff -r 2262a3c684d4 -r 939101df3867 sys/conf/param.c
--- a/sys/conf/param.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/conf/param.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: param.c,v 1.63 2010/02/08 19:02:33 joerg Exp $ */
+/* $NetBSD: param.c,v 1.64 2012/06/09 02:31:14 christos Exp $ */
/*
* Copyright (c) 1980, 1986, 1989 Regents of the University of California.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: param.c,v 1.63 2010/02/08 19:02:33 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: param.c,v 1.64 2012/06/09 02:31:14 christos Exp $");
#include "opt_hz.h"
#include "opt_rtc_offset.h"
@@ -58,6 +58,7 @@
#include <sys/kernel.h>
#include <sys/utsname.h>
#include <sys/ksem.h>
+#include <sys/lwp.h>
#ifdef SYSVSHM
#include <machine/vmparam.h>
#include <sys/shm.h>
@@ -117,6 +118,7 @@
int tickadj = (240000 / (60 * HZ)) ? (240000 / (60 * HZ)) : 1;
int rtc_offset = RTC_OFFSET;
int maxproc = NPROC;
+int maxlwp = MAXLWP;
int desiredvnodes = NVNODE;
u_int maxfiles = MAXFILES;
int fscale = FSCALE; /* kernel uses `FSCALE', user uses `fscale' */
diff -r 2262a3c684d4 -r 939101df3867 sys/kern/kern_lwp.c
--- a/sys/kern/kern_lwp.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/kern/kern_lwp.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_lwp.c,v 1.168 2012/04/13 15:32:43 yamt Exp $ */
+/* $NetBSD: kern_lwp.c,v 1.169 2012/06/09 02:31:14 christos Exp $ */
/*-
* Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -211,7 +211,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.168 2012/04/13 15:32:43 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.169 2012/06/09 02:31:14 christos Exp $");
#include "opt_ddb.h"
#include "opt_lockdebug.h"
@@ -239,6 +239,8 @@
#include <sys/dtrace_bsd.h>
#include <sys/sdt.h>
#include <sys/xcall.h>
+#include <sys/uidinfo.h>
+#include <sys/sysctl.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm_object.h>
@@ -286,6 +288,47 @@
.l_fd = &filedesc0,
};
+static int sysctl_kern_maxlwp(SYSCTLFN_PROTO);
+
+/*
+ * sysctl helper routine for kern.maxlwp. Ensures that the new
+ * values are not too low or too high.
+ */
+static int
+sysctl_kern_maxlwp(SYSCTLFN_ARGS)
+{
+ int error, nmaxlwp;
+ struct sysctlnode node;
+
+ nmaxlwp = maxlwp;
+ node = *rnode;
+ node.sysctl_data = &nmaxlwp;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+
+ if (nmaxlwp < 0 || nmaxlwp >= 65536)
+ return EINVAL;
+ if (nmaxlwp > cpu_maxlwp())
+ return EINVAL;
+ maxlwp = nmaxlwp;
+
+ return 0;
+}
+
+static void
+sysctl_kern_lwp_setup(void)
+{
+ struct sysctllog *clog = NULL;
+
+ sysctl_createv(&clog, 0, NULL, NULL,
+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+ CTLTYPE_INT, "maxlwp",
+ SYSCTL_DESCR("Maximum number of simultaneous threads"),
+ sysctl_kern_maxlwp, 0, NULL, 0,
+ CTL_KERN, CTL_CREATE, CTL_EOL);
+}
+
void
lwpinit(void)
{
@@ -295,6 +338,9 @@
lwp_sys_init();
lwp_cache = pool_cache_init(sizeof(lwp_t), MIN_LWP_ALIGNMENT, 0, 0,
"lwppl", NULL, IPL_NONE, NULL, lwp_dtor, NULL);
+
+ maxlwp = cpu_maxlwp();
+ sysctl_kern_lwp_setup();
}
void
@@ -677,6 +723,28 @@
KASSERT(l1 == curlwp || l1->l_proc == &proc0);
/*
+ * Enforce limits, excluding the first lwp and kthreads.
+ */
+ if (p2->p_nlwps != 0 && p2 != &proc0) {
+ uid_t uid = kauth_cred_getuid(l1->l_cred);
+ int count = chglwpcnt(uid, 1);
+ if (__predict_false(count >
+ p2->p_rlimit[RLIMIT_NTHR].rlim_cur)) {
+ if (kauth_authorize_process(l1->l_cred,
+ KAUTH_PROCESS_RLIMIT, p2,
+ KAUTH_ARG(KAUTH_REQ_PROCESS_RLIMIT_BYPASS),
+ &p2->p_rlimit[RLIMIT_NTHR], KAUTH_ARG(RLIMIT_NTHR))
+ != 0) {
+ if ((count = chglwpcnt(uid, -1)) < 0)
+ printf("%s, %d: %s, %d, %d\n", __FILE__,
+ __LINE__, l1->l_proc->p_comm,
+ l1->l_proc->p_pid, count);
+ // return EAGAIN;
+ }
+ }
+ }
+
+ /*
* First off, reap any detached LWP waiting to be collected.
* We can re-use its LWP structure and turnstile.
*/
@@ -1041,6 +1109,10 @@
KASSERT(l != curlwp);
KASSERT(last || mutex_owned(p->p_lock));
+ if (p != &proc0 && p->p_nlwps != 1)
+ if (chglwpcnt(kauth_cred_getuid(l->l_cred), -1) < 0)
+ printf("%s, %d: %d, %s\n", __FILE__, __LINE__,
+ p->p_pid, p->p_comm);
/*
* If this was not the last LWP in the process, then adjust
* counters and unlock.
diff -r 2262a3c684d4 -r 939101df3867 sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/kern/kern_proc.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_proc.c,v 1.185 2012/06/06 11:20:21 martin Exp $ */
+/* $NetBSD: kern_proc.c,v 1.186 2012/06/09 02:31:14 christos Exp $ */
/*-
* Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.185 2012/06/06 11:20:21 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.186 2012/06/09 02:31:14 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_kstack.h"
@@ -459,6 +459,9 @@
rlim[RLIMIT_MEMLOCK].rlim_max = lim;
rlim[RLIMIT_MEMLOCK].rlim_cur = lim / 3;
+ rlim[RLIMIT_NTHR].rlim_max = maxlwp;
+ rlim[RLIMIT_NTHR].rlim_cur = maxlwp < maxuprc ? maxlwp : maxuprc;
+
/* Note that default core name has zero length. */
limit0.pl_corename = defcorename;
limit0.pl_cnlen = 0;
diff -r 2262a3c684d4 -r 939101df3867 sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/kern/kern_prot.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_prot.c,v 1.114 2012/03/19 06:04:19 matt Exp $ */
+/* $NetBSD: kern_prot.c,v 1.115 2012/06/09 02:31:15 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.114 2012/03/19 06:04:19 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.115 2012/06/09 02:31:15 christos Exp $");
#include "opt_compat_43.h"
@@ -346,6 +346,14 @@
/* Update count of processes for this user */
(void)chgproccnt(kauth_cred_getuid(ncred), -1);
(void)chgproccnt(r, 1);
+
+ /* The first lwp of a process is not counted */
+ int nlwps = p->p_nlwps - 1;
+ if (chglwpcnt(kauth_cred_getuid(ncred), -nlwps) < 0)
+ printf("%s, %d: %d, %s %d\n", __FILE__, __LINE__,
+ p->p_pid, p->p_comm, nlwps);
+ (void)chglwpcnt(r, nlwps);
+
kauth_cred_setuid(ncred, r);
}
if (sv != -1)
diff -r 2262a3c684d4 -r 939101df3867 sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/kern/kern_resource.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_resource.c,v 1.168 2011/12/02 12:33:12 yamt Exp $ */
+/* $NetBSD: kern_resource.c,v 1.169 2012/06/09 02:31:15 christos Exp $ */
/*-
* Copyright (c) 1982, 1986, 1991, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.168 2011/12/02 12:33:12 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.169 2012/06/09 02:31:15 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -439,6 +439,13 @@
if (limp->rlim_max > maxproc)
limp->rlim_max = maxproc;
break;
+
+ case RLIMIT_NTHR:
+ if (limp->rlim_cur > maxlwp)
+ limp->rlim_cur = maxlwp;
+ if (limp->rlim_max > maxlwp)
+ limp->rlim_max = maxlwp;
+ break;
}
mutex_enter(&p->p_limit->pl_lock);
@@ -1082,6 +1089,7 @@
create_proc_plimit("descriptors", PROC_PID_LIMIT_NOFILE);
create_proc_plimit("sbsize", PROC_PID_LIMIT_SBSIZE);
create_proc_plimit("vmemoryuse", PROC_PID_LIMIT_AS);
+ create_proc_plimit("maxlwp", PROC_PID_LIMIT_NTHR);
#undef create_proc_plimit
diff -r 2262a3c684d4 -r 939101df3867 sys/kern/kern_uidinfo.c
--- a/sys/kern/kern_uidinfo.c Fri Jun 08 23:35:23 2012 +0000
+++ b/sys/kern/kern_uidinfo.c Sat Jun 09 02:31:14 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_uidinfo.c,v 1.5 2009/03/22 00:49:13 ad Exp $ */
+/* $NetBSD: kern_uidinfo.c,v 1.6 2012/06/09 02:31:15 christos Exp $ */
/*-
* Copyright (c) 1982, 1986, 1991, 1993
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_uidinfo.c,v 1.5 2009/03/22 00:49:13 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_uidinfo.c,v 1.6 2012/06/09 02:31:15 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,6 +43,8 @@
#include <sys/proc.h>
#include <sys/atomic.h>
#include <sys/uidinfo.h>
+#include <sys/sysctl.h>
+#include <sys/kauth.h>
#include <sys/cpu.h>
static SLIST_HEAD(uihashhead, uidinfo) *uihashtbl;
@@ -50,6 +52,79 @@
#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
+static int
+sysctl_kern_uidinfo_cnt(SYSCTLFN_ARGS)
+{
+ static const struct {
+ const char *name;
+ u_int value;
+ } nv[] = {
+#define _MEM(n) { # n, offsetof(struct uidinfo, ui_ ## n) }
+ _MEM(proccnt),
Home |
Main Index |
Thread Index |
Old Index