summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-05-16 17:25:49 +0000
committerglebius <glebius@FreeBSD.org>2005-05-16 17:25:49 +0000
commit30c28c4860bdfd56962b842b52db06c033e6be31 (patch)
tree2f96444f09204ed3f6d9db44dbb912428db11178
parente982eb7d989de98e6df0e23e5cb484732c335c96 (diff)
downloadFreeBSD-src-30c28c4860bdfd56962b842b52db06c033e6be31.zip
FreeBSD-src-30c28c4860bdfd56962b842b52db06c033e6be31.tar.gz
Close race between node being shutdown and socket being detached. To
do this, obtain netgraph locking in detach method via ng_send_fn1(). Reviewed by: julian MFC after: 2 weeks
-rw-r--r--sys/netgraph/ng_socket.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c
index 125169c..130248f 100644
--- a/sys/netgraph/ng_socket.c
+++ b/sys/netgraph/ng_socket.c
@@ -122,7 +122,7 @@ static ng_disconnect_t ngs_disconnect;
static int ng_attach_data(struct socket *so);
static int ng_attach_cntl(struct socket *so);
static int ng_attach_common(struct socket *so, int type);
-static void ng_detach_common(struct ngpcb *pcbp, int type);
+static void ng_detach_common(node_p node, hook_p hook, void *arg1, int which);
/*static int ng_internalize(struct mbuf *m, struct thread *p); */
static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
@@ -190,7 +190,16 @@ ngc_detach(struct socket *so)
if (pcbp == NULL)
return (EINVAL);
- ng_detach_common(pcbp, NG_CONTROL);
+
+ /*
+ * If there is a node, then obtain netgraph locking first.
+ */
+ if (pcbp->sockdata != NULL)
+ ng_send_fn1(pcbp->sockdata->node, NULL, &ng_detach_common,
+ pcbp, NG_CONTROL, NG_WAITOK);
+ else
+ ng_detach_common(NULL, NULL, pcbp, NG_CONTROL);
+
return (0);
}
@@ -379,7 +388,16 @@ ngd_detach(struct socket *so)
if (pcbp == NULL)
return (EINVAL);
- ng_detach_common(pcbp, NG_DATA);
+
+ /*
+ * If there is a node, then obtain netgraph locking first.
+ */
+ if (pcbp->sockdata != NULL)
+ ng_send_fn1(pcbp->sockdata->node, NULL, &ng_detach_common,
+ pcbp, NG_DATA, NG_WAITOK);
+ else
+ ng_detach_common(NULL, NULL, pcbp, NG_DATA);
+
return (0);
}
@@ -521,14 +539,14 @@ ng_attach_cntl(struct socket *so)
MALLOC(privdata, struct ngsock *,
sizeof(*privdata), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO);
if (privdata == NULL) {
- ng_detach_common(pcbp, NG_CONTROL);
+ ng_detach_common(NULL, NULL, pcbp, NG_CONTROL);
return (ENOMEM);
}
/* Make the generic node components */
if ((error = ng_make_node_common(&typestruct, &privdata->node)) != 0) {
FREE(privdata, M_NETGRAPH_SOCK);
- ng_detach_common(pcbp, NG_CONTROL);
+ ng_detach_common(NULL, NULL, pcbp, NG_CONTROL);
return (error);
}
NG_NODE_SET_PRIVATE(privdata->node, privdata);
@@ -585,11 +603,13 @@ ng_attach_common(struct socket *so, int type)
* then shut down the entire node. Shared code for control and data sockets.
*/
static void
-ng_detach_common(struct ngpcb *pcbp, int which)
+ng_detach_common(node_p node, hook_p hook, void *arg1, int which)
{
- struct ngsock *priv;
+ struct ngpcb *pcbp = arg1;
if (pcbp->sockdata) {
+ struct ngsock *priv;
+
priv = pcbp->sockdata;
pcbp->sockdata = NULL;
switch (which) {
OpenPOWER on IntegriCloud