summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryasuoka <yasuoka@openbsd.org>2018-06-15 12:39:38 +0000
committeryasuoka <yasuoka@openbsd.org>2018-06-15 12:39:38 +0000
commita16d04158688c88ae56c04e779c9e00a97a9cb29 (patch)
tree2fae3bcbfd5773c142e27c15009b1973b77f574b
parentFix 304 Not Modified response: don't send a body, use the correct MIME type. (diff)
downloadwireguard-openbsd-a16d04158688c88ae56c04e779c9e00a97a9cb29.tar.xz
wireguard-openbsd-a16d04158688c88ae56c04e779c9e00a97a9cb29.zip
Fix the lock order problem found by witness. Release the lock for
pppx_ifs earlier not to overlap the protected section for ifnet. Also introduce pxi_ready flag to protect pxi not to be used before initialization. ok bluhm
-rw-r--r--sys/net/if_pppx.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c
index db96dbc0443..e81c09b1ec6 100644
--- a/sys/net/if_pppx.c
+++ b/sys/net/if_pppx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pppx.c,v 1.64 2018/03/29 04:53:17 jmatthew Exp $ */
+/* $OpenBSD: if_pppx.c,v 1.65 2018/06/15 12:39:38 yasuoka Exp $ */
/*
* Copyright (c) 2010 Claudio Jeker <claudio@openbsd.org>
@@ -145,6 +145,8 @@ struct pppx_if {
RBT_ENTRY(pppx_if) pxi_entry;
LIST_ENTRY(pppx_if) pxi_list;
+ int pxi_ready;
+
int pxi_unit;
struct ifnet pxi_if;
struct pppx_dev *pxi_dev;
@@ -646,6 +648,8 @@ pppx_if_find(struct pppx_dev *pxd, int session_id, int protocol)
rw_enter_read(&pppx_ifs_lk);
p = RBT_FIND(pppx_ifs, &pppx_ifs, s);
+ if (p && p->pxi_ready == 0)
+ p = NULL;
rw_exit_read(&pppx_ifs_lk);
free(s, M_DEVBUF, 0);
@@ -817,6 +821,7 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req)
if (unit < 0) {
pool_put(pppx_if_pl, pxi);
error = ENOMEM;
+ rw_exit_write(&pppx_ifs_lk);
goto out;
}
@@ -829,9 +834,15 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req)
if (RBT_FIND(pppx_ifs, &pppx_ifs, pxi) != NULL) {
pool_put(pppx_if_pl, pxi);
error = EADDRINUSE;
+ rw_exit_write(&pppx_ifs_lk);
goto out;
}
+ if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL)
+ panic("pppx_ifs modified while lock was held");
+ LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list);
+ rw_exit_write(&pppx_ifs_lk);
+
snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit);
ifp->if_mtu = req->pr_peer_mru; /* XXX */
ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP;
@@ -874,10 +885,6 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req)
#endif
SET(ifp->if_flags, IFF_RUNNING);
- if (RBT_INSERT(pppx_ifs, &pppx_ifs, pxi) != NULL)
- panic("pppx_ifs modified while lock was held");
- LIST_INSERT_HEAD(&pxd->pxd_pxis, pxi, pxi_list);
-
/* XXX ipv6 support? how does the caller indicate it wants ipv6
* instead of ipv4?
*/
@@ -914,10 +921,11 @@ pppx_add_session(struct pppx_dev *pxd, struct pipex_session_req *req)
} else {
dohooks(ifp->if_addrhooks, 0);
}
-
-out:
+ rw_enter_write(&pppx_ifs_lk);
+ pxi->pxi_ready = 1;
rw_exit_write(&pppx_ifs_lk);
+out:
return (error);
}