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.
This commit is contained in:
parent
2a57ca33c7
commit
81a253a4ed
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175847
@ -127,6 +127,7 @@ struct ng_hook {
|
||||
#define HK_QUEUE 0x0002 /* queue for later delivery */
|
||||
#define HK_FORCE_WRITER 0x0004 /* Incoming data queued as a writer */
|
||||
#define HK_DEAD 0x0008 /* This is the dead hook.. don't free */
|
||||
#define HK_HI_STACK 0x0010 /* Hook has hi stack usage */
|
||||
|
||||
/*
|
||||
* Public Methods for hook
|
||||
@ -147,6 +148,7 @@ void ng_unref_hook(hook_p hook); /* don't move this */
|
||||
#define _NG_HOOK_FORCE_WRITER(hook) \
|
||||
do { hook->hk_flags |= HK_FORCE_WRITER; } while (0)
|
||||
#define _NG_HOOK_FORCE_QUEUE(hook) do { hook->hk_flags |= HK_QUEUE; } while (0)
|
||||
#define _NG_HOOK_HI_STACK(hook) do { hook->hk_flags |= HK_HI_STACK; } while (0)
|
||||
|
||||
/* Some shortcuts */
|
||||
#define NG_PEER_NODE(hook) NG_HOOK_NODE(NG_HOOK_PEER(hook))
|
||||
@ -277,6 +279,13 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
|
||||
_NG_HOOK_FORCE_QUEUE(hook);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
_ng_hook_hi_stack(hook_p hook, char * file, int line)
|
||||
{
|
||||
_chkhook(hook, file, line);
|
||||
_NG_HOOK_HI_STACK(hook);
|
||||
}
|
||||
|
||||
|
||||
#define NG_HOOK_REF(hook) _ng_hook_ref(hook, _NN_)
|
||||
#define NG_HOOK_NAME(hook) _ng_hook_name(hook, _NN_)
|
||||
@ -291,6 +300,7 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
|
||||
#define NG_HOOK_PEER(hook) _ng_hook_peer(hook, _NN_)
|
||||
#define NG_HOOK_FORCE_WRITER(hook) _ng_hook_force_writer(hook, _NN_)
|
||||
#define NG_HOOK_FORCE_QUEUE(hook) _ng_hook_force_queue(hook, _NN_)
|
||||
#define NG_HOOK_HI_STACK(hook) _ng_hook_hi_stack(hook, _NN_)
|
||||
|
||||
#else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
|
||||
|
||||
@ -307,6 +317,7 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
|
||||
#define NG_HOOK_PEER(hook) _NG_HOOK_PEER(hook)
|
||||
#define NG_HOOK_FORCE_WRITER(hook) _NG_HOOK_FORCE_WRITER(hook)
|
||||
#define NG_HOOK_FORCE_QUEUE(hook) _NG_HOOK_FORCE_QUEUE(hook)
|
||||
#define NG_HOOK_HI_STACK(hook) _NG_HOOK_HI_STACK(hook)
|
||||
|
||||
#endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
|
||||
|
||||
@ -360,6 +371,7 @@ struct ng_node {
|
||||
#define NG_CLOSING NGF_CLOSING /* compat for old code */
|
||||
#define NGF_REALLY_DIE 0x00000010 /* "persistent" node is unloading */
|
||||
#define NG_REALLY_DIE NGF_REALLY_DIE /* compat for old code */
|
||||
#define NGF_HI_STACK 0x00000020 /* node has hi stack usage */
|
||||
#define NGF_TYPE1 0x10000000 /* reserved for type specific storage */
|
||||
#define NGF_TYPE2 0x20000000 /* reserved for type specific storage */
|
||||
#define NGF_TYPE3 0x40000000 /* reserved for type specific storage */
|
||||
@ -382,6 +394,8 @@ int ng_unref_node(node_p node); /* don't move this */
|
||||
#define _NG_NODE_NUMHOOKS(node) ((node)->nd_numhooks + 0) /* rvalue */
|
||||
#define _NG_NODE_FORCE_WRITER(node) \
|
||||
do{ node->nd_flags |= NGF_FORCE_WRITER; }while (0)
|
||||
#define _NG_NODE_HI_STACK(node) \
|
||||
do{ node->nd_flags |= NGF_HI_STACK; }while (0)
|
||||
#define _NG_NODE_REALLY_DIE(node) \
|
||||
do{ node->nd_flags |= (NGF_REALLY_DIE|NGF_INVALID); }while (0)
|
||||
#define _NG_NODE_REVIVE(node) \
|
||||
@ -512,6 +526,13 @@ _ng_node_force_writer(node_p node, char *file, int line)
|
||||
_NG_NODE_FORCE_WRITER(node);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
_ng_node_hi_stack(node_p node, char *file, int line)
|
||||
{
|
||||
_chknode(node, file, line);
|
||||
_NG_NODE_HI_STACK(node);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
_ng_node_really_die(node_p node, char *file, int line)
|
||||
{
|
||||
@ -546,6 +567,7 @@ _ng_node_foreach_hook(node_p node, ng_fn_eachhook *fn, void *arg,
|
||||
#define NG_NODE_IS_VALID(node) _ng_node_is_valid(node, _NN_)
|
||||
#define NG_NODE_NOT_VALID(node) _ng_node_not_valid(node, _NN_)
|
||||
#define NG_NODE_FORCE_WRITER(node) _ng_node_force_writer(node, _NN_)
|
||||
#define NG_NODE_HI_STACK(node) _ng_node_hi_stack(node, _NN_)
|
||||
#define NG_NODE_REALLY_DIE(node) _ng_node_really_die(node, _NN_)
|
||||
#define NG_NODE_NUMHOOKS(node) _ng_node_numhooks(node, _NN_)
|
||||
#define NG_NODE_REVIVE(node) _ng_node_revive(node, _NN_)
|
||||
@ -566,6 +588,7 @@ _ng_node_foreach_hook(node_p node, ng_fn_eachhook *fn, void *arg,
|
||||
#define NG_NODE_IS_VALID(node) _NG_NODE_IS_VALID(node)
|
||||
#define NG_NODE_NOT_VALID(node) _NG_NODE_NOT_VALID(node)
|
||||
#define NG_NODE_FORCE_WRITER(node) _NG_NODE_FORCE_WRITER(node)
|
||||
#define NG_NODE_HI_STACK(node) _NG_NODE_HI_STACK(node)
|
||||
#define NG_NODE_REALLY_DIE(node) _NG_NODE_REALLY_DIE(node)
|
||||
#define NG_NODE_NUMHOOKS(node) _NG_NODE_NUMHOOKS(node)
|
||||
#define NG_NODE_REVIVE(node) _NG_NODE_REVIVE(node)
|
||||
|
@ -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
|
||||
|
@ -573,6 +573,7 @@ ng_iface_newhook(node_p node, hook_p hook, const char *name)
|
||||
if (*hookptr != NULL)
|
||||
return (EISCONN);
|
||||
*hookptr = hook;
|
||||
NG_HOOK_HI_STACK(hook);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user