aboutsummaryrefslogtreecommitdiff
path: root/sys/netgraph/ng_base.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2008-01-31 08:51:48 +0000
committerAlexander Motin <mav@FreeBSD.org>2008-01-31 08:51:48 +0000
commit81a253a4ede94f5f284f5696da87a1394c126be5 (patch)
treee401ae1e6519d6fbdbbcd1a030ecceea296b79b8 /sys/netgraph/ng_base.c
parent2a57ca33c742c600a5837ba32f9325b79e669f45 (diff)
downloadsrc-81a253a4ede94f5f284f5696da87a1394c126be5.tar.gz
src-81a253a4ede94f5f284f5696da87a1394c126be5.zip
Implement stack protection based on GET_STACK_USAGE() macro.
This fixes system panics possible with complicated netgraph setups and allows to avoid unneded extra queueing for stack unwrapping.
Notes
Notes: svn path=/head/; revision=175847
Diffstat (limited to 'sys/netgraph/ng_base.c')
-rw-r--r--sys/netgraph/ng_base.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 47fde6078755..f61d2fd1c69c 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -60,6 +60,7 @@
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/refcount.h>
+#include <sys/proc.h>
#include <net/netisr.h>
@@ -2300,8 +2301,6 @@ ng_snd_item(item_p item, int flags)
ERROUT(EINVAL); /* No address */
}
- queue = (flags & NG_QUEUE) ? 1 : 0;
-
switch(item->el_flags & NGQF_TYPE) {
case NGQF_DATA:
/*
@@ -2327,9 +2326,6 @@ ng_snd_item(item_p item, int flags)
|| (NG_NODE_NOT_VALID(NG_HOOK_NODE(hook)))) {
ERROUT(ENOTCONN);
}
- if ((hook->hk_flags & HK_QUEUE)) {
- queue = 1;
- }
break;
case NGQF_MESG:
/*
@@ -2339,9 +2335,6 @@ ng_snd_item(item_p item, int flags)
* References are held by the item on the node and
* the hook if it is present.
*/
- if (hook && (hook->hk_flags & HK_QUEUE)) {
- queue = 1;
- }
break;
case NGQF_FN:
case NGQF_FN2:
@@ -2370,6 +2363,27 @@ ng_snd_item(item_p item, int flags)
|| (hook && (hook->hk_flags & HK_FORCE_WRITER)))
rw = NGQRW_W;
+ /*
+ * If sender or receiver requests queued delivery or stack usage
+ * level is dangerous - enqueue message.
+ */
+ queue = 0;
+ if ((flags & NG_QUEUE) || (hook && (hook->hk_flags & HK_QUEUE))) {
+ queue = 1;
+ }
+#ifdef GET_STACK_USAGE
+ else {
+ size_t st, su;
+ GET_STACK_USAGE(st, su);
+ su = (su * 128) / st;
+ if ((su > 100) ||
+ ((su > 64) && ((node->nd_flags & NGF_HI_STACK) ||
+ (hook && (hook->hk_flags & HK_HI_STACK))))) {
+ queue = 1;
+ }
+ }
+#endif
+
if (queue) {
/* Put it on the queue for that node*/
#ifdef NETGRAPH_DEBUG