diff options
author | glebius <glebius@FreeBSD.org> | 2005-05-16 17:25:49 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-05-16 17:25:49 +0000 |
commit | 30c28c4860bdfd56962b842b52db06c033e6be31 (patch) | |
tree | 2f96444f09204ed3f6d9db44dbb912428db11178 | |
parent | e982eb7d989de98e6df0e23e5cb484732c335c96 (diff) | |
download | FreeBSD-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.c | 34 |
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) { |