aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2013-10-21 16:46:12 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2013-10-21 16:46:12 +0000
commit85a0ddfd0b269f9527883973092c457f04c1af19 (patch)
tree04786befd82e74b0298aa6139cca4192ba215854
parent9110db818a1e36cffed5208b6d005d9c1b84236a (diff)
Add a resource limit for the total number of kqueues available to the
user. Kqueue now saves the ucred of the allocating thread, to correctly decrement the counter on close. Under some specific and not real-world use scenario for kqueue, it is possible for the kqueues to consume memory proportional to the square of the number of the filedescriptors available to the process. Limit allows administrator to prevent the abuse. This is kernel-mode side of the change, with the user-mode enabling commit following. Reported and tested by: pho Discussed with: jmg Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=256850
-rw-r--r--bin/sh/miscbltin.c5
-rw-r--r--etc/login.conf1
-rw-r--r--lib/libc/sys/getrlimit.22
-rw-r--r--lib/libutil/login_class.31
-rw-r--r--lib/libutil/login_class.c1
-rw-r--r--usr.bin/limits/limits.c16
-rw-r--r--usr.bin/procstat/procstat_rlimit.c5
7 files changed, 23 insertions, 8 deletions
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index 2ecd4f22f27e..27fa53db2fb4 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -405,6 +405,9 @@ static const struct limits limits[] = {
#ifdef RLIMIT_NPTS
{ "pseudo-terminals", (char *)0, RLIMIT_NPTS, 1, 'p' },
#endif
+#ifdef RLIMIT_KQUEUES
+ { "kqueues", (char *)0, RLIMIT_KQUEUES, 1, 'k' },
+#endif
{ (char *) 0, (char *)0, 0, 0, '\0' }
};
@@ -421,7 +424,7 @@ ulimitcmd(int argc __unused, char **argv __unused)
struct rlimit limit;
what = 'f';
- while ((optc = nextopt("HSatfdsmcnuvlbpw")) != '\0')
+ while ((optc = nextopt("HSatfdsmcnuvlbpwk")) != '\0')
switch (optc) {
case 'H':
how = HARD;
diff --git a/etc/login.conf b/etc/login.conf
index 67509f93ea0f..ff98d1ce5beb 100644
--- a/etc/login.conf
+++ b/etc/login.conf
@@ -42,6 +42,7 @@ default:\
:vmemoryuse=unlimited:\
:swapuse=unlimited:\
:pseudoterminals=unlimited:\
+ :kqueues=unlimited:\
:priority=0:\
:ignoretime@:\
:umask=022:
diff --git a/lib/libc/sys/getrlimit.2 b/lib/libc/sys/getrlimit.2
index 35198bce3062..1f84bfb0f0e8 100644
--- a/lib/libc/sys/getrlimit.2
+++ b/lib/libc/sys/getrlimit.2
@@ -108,6 +108,8 @@ Please see
for a complete description of this sysctl.
.It Dv RLIMIT_NPTS
The maximum number of pseudo-terminals created by this user id.
+.It Dv RLIMIT_KQUEUES
+The maximum number of kqueues created by this user id.
.El
.Pp
A resource limit is specified as a soft limit and a hard limit.
diff --git a/lib/libutil/login_class.3 b/lib/libutil/login_class.3
index 62a65f20c799..75f361481c81 100644
--- a/lib/libutil/login_class.3
+++ b/lib/libutil/login_class.3
@@ -118,6 +118,7 @@ sbsize RLIMIT_SBSIZE
vmemoryuse RLIMIT_VMEM
pseudoterminals RLIMIT_NPTS
swapuse RLIMIT_SWAP
+kqueues RLIMIT_KQUEUES
.Ed
.It LOGIN_SETPRIORITY
Set the scheduling priority for the current process based on the
diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
index 263044f446a9..39cce12f7f60 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -66,6 +66,7 @@ static struct login_res {
{ "vmemoryuse", login_getcapsize, RLIMIT_VMEM },
{ "pseudoterminals", login_getcapnum, RLIMIT_NPTS },
{ "swapuse", login_getcapsize, RLIMIT_SWAP },
+ { "kqueues", login_getcapsize, RLIMIT_KQUEUES },
{ NULL, 0, 0 }
};
diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c
index 3c5fd6de3104..83167434a91a 100644
--- a/usr.bin/limits/limits.c
+++ b/usr.bin/limits/limits.c
@@ -89,7 +89,8 @@ static struct {
{ " sbsize%-4s %8s", " bytes\n", 1 },
{ " vmemoryuse%-4s %8s", " kB\n", 1024 },
{ " pseudo-terminals%-4s %8s", "\n", 1 },
- { " swapuse%-4s %8s", " kB\n", 1024 }
+ { " swapuse%-4s %8s", " kB\n", 1024 },
+ { " kqueues%-4s %8s", "\n", 1 },
}
},
{ "sh", "unlimited", "", " -H", " -S", "",
@@ -106,7 +107,8 @@ static struct {
{ "ulimit%s -b %s", ";\n", 1 },
{ "ulimit%s -v %s", ";\n", 1024 },
{ "ulimit%s -p %s", ";\n", 1 },
- { "ulimit%s -w %s", ";\n", 1024 }
+ { "ulimit%s -w %s", ";\n", 1024 },
+ { "ulimit%s -k %s", ";\n", 1 },
}
},
{ "csh", "unlimited", "", " -h", "", NULL,
@@ -123,7 +125,8 @@ static struct {
{ "limit%s sbsize %s", ";\n", 1 },
{ "limit%s vmemoryuse %s", ";\n", 1024 },
{ "limit%s pseudoterminals %s", ";\n", 1 },
- { "limit%s swapuse %s", ";\n", 1024 }
+ { "limit%s swapuse %s", ";\n", 1024 },
+ { "limit%s kqueues %s", ";\n", 1 },
}
},
{ "bash|bash2", "unlimited", "", " -H", " -S", "",
@@ -157,7 +160,8 @@ static struct {
{ "limit%s sbsize %s", ";\n", 1 },
{ "limit%s vmemoryuse %s", ";\n", 1024 },
{ "limit%s pseudoterminals %s", ";\n", 1 },
- { "limit%s swapuse %s", ";\n", 1024 }
+ { "limit%s swapuse %s", ";\n", 1024 },
+ { "limit%s kqueues %s", ";\n", 1 },
}
},
{ "ksh|pdksh", "unlimited", "", " -H", " -S", "",
@@ -232,7 +236,8 @@ static struct {
{ "sbsize", login_getcapsize },
{ "vmemoryuse", login_getcapsize },
{ "pseudoterminals",login_getcapnum },
- { "swapuse", login_getcapsize }
+ { "swapuse", login_getcapsize },
+ { "kqueues", login_getcapnum },
};
/*
@@ -647,6 +652,7 @@ resource_num(int which, int ch, const char *str)
case RLIMIT_NPROC:
case RLIMIT_NOFILE:
case RLIMIT_NPTS:
+ case RLIMIT_KQUEUES:
res = strtoq(s, &e, 0);
s = e;
break;
diff --git a/usr.bin/procstat/procstat_rlimit.c b/usr.bin/procstat/procstat_rlimit.c
index f3ed5fc45177..f7f67af1e0ff 100644
--- a/usr.bin/procstat/procstat_rlimit.c
+++ b/usr.bin/procstat/procstat_rlimit.c
@@ -46,7 +46,7 @@
static struct {
const char *name;
const char *suffix;
-} rlimit_param[13] = {
+} rlimit_param[14] = {
{"cputime", "sec"},
{"filesize", "B "},
{"datasize", "B "},
@@ -60,9 +60,10 @@ static struct {
{"vmemoryuse", "B "},
{"pseudo-terminals", " "},
{"swapuse", "B "},
+ {"kqueues", " "},
};
-#if RLIM_NLIMITS > 13
+#if RLIM_NLIMITS > 14
#error "Resource limits have grown. Add new entries to rlimit_param[]."
#endif