Date: Thu, 24 May 2018 21:13:46 +0000 (UTC) From: Matt Macy <mmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334185 - head/sys/kern Message-ID: <201805242113.w4OLDk6f014693@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mmacy Date: Thu May 24 21:13:46 2018 New Revision: 334185 URL: https://svnweb.freebsd.org/changeset/base/334185 Log: AF_UNIX: It is possible for UNIX datagram sockets to be connected to themselves. The updated code assumed that that could not happen and would try to lock the unp mutex twice. There may be a lingering issue here but this fixes it for the reporter. PR: 228458 Reported by: marieheleneka at gmail.com Modified: head/sys/kern/uipc_usrreq.c Modified: head/sys/kern/uipc_usrreq.c ============================================================================== --- head/sys/kern/uipc_usrreq.c Thu May 24 21:11:38 2018 (r334184) +++ head/sys/kern/uipc_usrreq.c Thu May 24 21:13:46 2018 (r334185) @@ -722,7 +722,9 @@ uipc_close(struct socket *so) } unp2 = unp->unp_conn; unp_pcb_hold(unp); - if (unp2 != NULL) { + if (__predict_false(unp == unp2)) { + unp_disconnect(unp, unp2); + } else if (unp2 != NULL) { unp_pcb_hold(unp2); unp_pcb_owned_lock2(unp, unp2, freed); unp_disconnect(unp, unp2); @@ -747,9 +749,13 @@ uipc_connect2(struct socket *so1, struct socket *so2) KASSERT(unp != NULL, ("uipc_connect2: unp == NULL")); unp2 = so2->so_pcb; KASSERT(unp2 != NULL, ("uipc_connect2: unp2 == NULL")); - unp_pcb_lock2(unp, unp2); + if (unp != unp2) + unp_pcb_lock2(unp, unp2); + else + UNP_PCB_LOCK(unp); error = unp_connect2(so1, so2, PRU_CONNECT2); - UNP_PCB_UNLOCK(unp2); + if (unp != unp2) + UNP_PCB_UNLOCK(unp2); UNP_PCB_UNLOCK(unp); return (error); } @@ -783,29 +789,30 @@ uipc_detach(struct socket *so) mtx_lock(vplock); } UNP_PCB_LOCK(unp); - if ((unp2 = unp->unp_conn) != NULL) { - unp_pcb_owned_lock2(unp, unp2, freeunp); - if (freeunp) - unp2 = NULL; - } if (unp->unp_vnode != vp && unp->unp_vnode != NULL) { if (vplock) mtx_unlock(vplock); UNP_PCB_UNLOCK(unp); - if (unp2) - UNP_PCB_UNLOCK(unp2); goto restart; } if ((unp->unp_flags & UNP_NASCENT) != 0) { - if (unp2) - UNP_PCB_UNLOCK(unp2); goto teardown; } if ((vp = unp->unp_vnode) != NULL) { VOP_UNP_DETACH(vp); unp->unp_vnode = NULL; } + if (__predict_false(unp == unp->unp_conn)) { + unp_disconnect(unp, unp); + unp2 = NULL; + goto connect_self; + } + if ((unp2 = unp->unp_conn) != NULL) { + unp_pcb_owned_lock2(unp, unp2, freeunp); + if (freeunp) + unp2 = NULL; + } unp_pcb_hold(unp); if (unp2 != NULL) { unp_pcb_hold(unp2); @@ -813,6 +820,7 @@ uipc_detach(struct socket *so) if (unp_pcb_rele(unp2) == 0) UNP_PCB_UNLOCK(unp2); } + connect_self: UNP_PCB_UNLOCK(unp); UNP_REF_LIST_LOCK(); while (!LIST_EMPTY(&unp->unp_refs)) { @@ -864,6 +872,10 @@ uipc_disconnect(struct socket *so) UNP_PCB_UNLOCK(unp); return (0); } + if (unp == unp2) { + if (unp_pcb_rele(unp) == 0) + UNP_PCB_UNLOCK(unp); + } unp_pcb_owned_lock2(unp, unp2, freed); if (__predict_false(freed)) { UNP_PCB_UNLOCK(unp); @@ -1925,7 +1937,9 @@ unp_drop(struct unpcb *unp) if (so) so->so_error = ECONNRESET; unp2 = unp->unp_conn; - if (unp2 != NULL) { + if (unp2 == unp) { + unp_disconnect(unp, unp2); + } else if (unp2 != NULL) { unp_pcb_hold(unp2); unp_pcb_owned_lock2(unp, unp2, freed); unp_disconnect(unp, unp2);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805242113.w4OLDk6f014693>