diff options
author | glebius <glebius@FreeBSD.org> | 2007-03-22 13:21:24 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2007-03-22 13:21:24 +0000 |
commit | 88fc902c13d88b570a01f2ddfaea5e11847d96c5 (patch) | |
tree | 9777ba295373e3cf6062207c386dd30c26c21f03 /sys/kern/uipc_socket.c | |
parent | 060c94f5be5dc06fae3d10b45b46f15f5b349d26 (diff) | |
download | FreeBSD-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/uipc_socket.c')
-rw-r--r-- | sys/kern/uipc_socket.c | 9 |
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); |