summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2007-03-22 13:21:24 +0000
committerglebius <glebius@FreeBSD.org>2007-03-22 13:21:24 +0000
commit88fc902c13d88b570a01f2ddfaea5e11847d96c5 (patch)
tree9777ba295373e3cf6062207c386dd30c26c21f03 /sys/kern
parent060c94f5be5dc06fae3d10b45b46f15f5b349d26 (diff)
downloadFreeBSD-src-88fc902c13d88b570a01f2ddfaea5e11847d96c5.zip
FreeBSD-src-88fc902c13d88b570a01f2ddfaea5e11847d96c5.tar.gz
Move the dom_dispose and pru_detach calls in sofree() earlier. Only after
calling pru_detach we can be absolutely sure, that we don't have any references to the socket in the stack. This closes race between lockless sbdestroy() and data arriving on socket. Reviewed by: rwatson
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/uipc_socket.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e4e35d5..2c9363e 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -606,6 +606,11 @@ sofree(so)
SOCK_UNLOCK(so);
ACCEPT_UNLOCK();
+ if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
+ (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
+ if (pr->pr_usrreqs->pru_detach != NULL)
+ (*pr->pr_usrreqs->pru_detach)(so);
+
/*
* From this point on, we assume that no other references to this
* socket exist anywhere else in the stack. Therefore, no locks need
@@ -624,11 +629,7 @@ sofree(so)
KASSERT((so->so_snd.sb_flags & SB_LOCK) == 0, ("sofree: snd sblock"));
KASSERT((so->so_rcv.sb_flags & SB_LOCK) == 0, ("sofree: rcv sblock"));
sbdestroy(&so->so_snd, so);
- if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose != NULL)
- (*pr->pr_domain->dom_dispose)(so->so_rcv.sb_mb);
sbdestroy(&so->so_rcv, so);
- if (pr->pr_usrreqs->pru_detach != NULL)
- (*pr->pr_usrreqs->pru_detach)(so);
knlist_destroy(&so->so_rcv.sb_sel.si_note);
knlist_destroy(&so->so_snd.sb_sel.si_note);
sodealloc(so);
OpenPOWER on IntegriCloud