diff options
author | 2018-06-15 12:39:38 +0000 | |
---|---|---|
committer | 2018-06-15 12:39:38 +0000 | |
commit | a16d04158688c88ae56c04e779c9e00a97a9cb29 (patch) | |
tree | 2fae3bcbfd5773c142e27c15009b1973b77f574b | |
parent | Fix 304 Not Modified response: don't send a body, use the correct MIME type. (diff) | |
download | wireguard-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.c | 22 |
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); } |