diff options
author | glebius <glebius@FreeBSD.org> | 2004-07-27 20:30:56 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2004-07-27 20:30:56 +0000 |
commit | 1a302abfe10a4008193863aa28d2f3bff8a91b19 (patch) | |
tree | eacfbebb8ab24714d31e2956f059a1feae6822b7 | |
parent | b050f5c62b8c2eb737e52df3b4c97fdd01b72cb0 (diff) | |
download | FreeBSD-src-1a302abfe10a4008193863aa28d2f3bff8a91b19.zip FreeBSD-src-1a302abfe10a4008193863aa28d2f3bff8a91b19.tar.gz |
When making a peer of unknown type framework tries to load module
using linker_load_module(). This works OK if NGM_MKPEER message came
from userland and we have process associated with thread. But when
NGM_MKPEER was queued because target node was busy, linker_load_module()
is called from netisr thread leading to panic.
To workaround that we do not load modules by framework, instead ng_socket
loads module (if this is required) before sending NGM_MKPEER.
However, the race condition between return from NgSendMsg() and actual
creation of node still exist and needs to be solved.
PR: kern/62789
Approved by: julian
-rw-r--r-- | sys/netgraph/netgraph.h | 1 | ||||
-rw-r--r-- | sys/netgraph/ng_base.c | 24 | ||||
-rw-r--r-- | sys/netgraph/ng_socket.c | 34 |
3 files changed, 40 insertions, 19 deletions
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h index f0925c4..b390a4c 100644 --- a/sys/netgraph/netgraph.h +++ b/sys/netgraph/netgraph.h @@ -1059,6 +1059,7 @@ int ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr); int ng_address_path(node_p here, item_p item, char *address, ng_ID_t raddr); int ng_bypass(hook_p hook1, hook_p hook2); hook_p ng_findhook(node_p node, const char *name); +struct ng_type *ng_findtype(const char *type); int ng_make_node_common(struct ng_type *typep, node_p *nodep); int ng_name_node(node_p node, const char *name); int ng_newtype(struct ng_type *tp); diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 74032a5..601ac9b 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -53,7 +53,6 @@ #include <sys/malloc.h> #include <sys/syslog.h> #include <sys/sysctl.h> -#include <sys/linker.h> #include <sys/queue.h> #include <sys/mbuf.h> #include <sys/ctype.h> @@ -205,7 +204,6 @@ void ng_destroy_hook(hook_p hook); node_p ng_name2noderef(node_p node, const char *name); int ng_path2noderef(node_p here, const char *path, node_p *dest, hook_p *lasthook); -struct ng_type *ng_findtype(const char *type); int ng_make_node(const char *type, node_p *nodepp); int ng_path_parse(char *addr, char **node, char **path, char **hook); void ng_rmnode(node_p node, hook_p dummy1, void *dummy2, int dummy3); @@ -547,23 +545,11 @@ ng_make_node(const char *typename, node_p *nodepp) return (EINVAL); } - /* Locate the node type */ - if ((type = ng_findtype(typename)) == NULL) { - char filename[NG_TYPESIZ + 3]; - linker_file_t lf; - int error; - - /* Not found, try to load it as a loadable module */ - snprintf(filename, sizeof(filename), "ng_%s", typename); - error = linker_load_module(NULL, filename, NULL, NULL, &lf); - if (error != 0) - return (error); - lf->userrefs++; /* pretend loaded by the syscall */ - - /* Try again, as now the type should have linked itself in */ - if ((type = ng_findtype(typename)) == NULL) - return (ENXIO); - } + /* Locate the node type. If we fail we return. Do not try to load + * module. + */ + if ((type = ng_findtype(typename)) == NULL) + return (ENXIO); /* * If we have a constructor, then make the node and diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index 52308f4..6f60a1c 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -52,6 +52,7 @@ #include <sys/errno.h> #include <sys/kdb.h> #include <sys/kernel.h> +#include <sys/linker.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mbuf.h> @@ -281,6 +282,39 @@ printf("errx=%d\n",error); } while (0); #else + /* + * Hack alert! + * We look into the message and if it mkpeers a node of unknown type, we + * try to load it. We need to do this now, in syscall thread, because if + * message gets queued and applied later we will get panic. + */ + if (msg->header.cmd == NGM_MKPEER) { + struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data; + struct ng_type *type; + + if ((type = ng_findtype(mkp->type)) == NULL) { + char filename[NG_TYPESIZ + 3]; + linker_file_t lf; + int error; + + /* Not found, try to load it as a loadable module */ + snprintf(filename, sizeof(filename), "ng_%s", mkp->type); + error = linker_load_module(NULL, filename, NULL, NULL, &lf); + if (error != 0) { + FREE(msg, M_NETGRAPH_MSG); + goto release; + } + lf->userrefs++; + + /* Try again, as now the type should have linked itself in */ + if ((type = ng_findtype(mkp->type)) == NULL) { + FREE(msg, M_NETGRAPH_MSG); + error = ENXIO; + goto release; + } + } + } + /* The callee will free the msg when done. The path is our business. */ NG_SEND_MSG_PATH(error, pcbp->sockdata->node, msg, path, 0); #endif |