aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/uipc_sockbuf.c
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2017-06-08 06:16:47 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2017-06-08 06:16:47 +0000
commit8d40bada3e78464d08e397b568dba17d8e593a4c (patch)
treecfb464cabd17c9ad4ae35e000cfbcb041f72aeef /sys/kern/uipc_sockbuf.c
parent62b2dd31afcb0f978ddb4f05bba2343049842e74 (diff)
downloadsrc-8d40bada3e78464d08e397b568dba17d8e593a4c.tar.gz
src-8d40bada3e78464d08e397b568dba17d8e593a4c.zip
Fix a degenerate case when soisdisconnected() would call soisconnected().
This happens when closing a socket with upcall, and trace is: soclose()-> ... protocol ... -> soisdisconnected() -> socantrcvmore_locked() -> sowakeup() -> soisconnected(). Right now this case is innocent for two reasons. First, soisconnected() doesn't clear SS_ISDISCONNECTED flag. Second, the mutex to lock the socket is the socket receive buffer mutex, and sodisconnected() first disables the receive buffer. But in future code, the mutex to lock socket is different to buffer mutex, and we would get undesired mutex recursion. The fix is to check SS_ISDISCONNECTED flag before calling upcall.
Notes
Notes: svn path=/head/; revision=319685
Diffstat (limited to 'sys/kern/uipc_sockbuf.c')
-rw-r--r--sys/kern/uipc_sockbuf.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index b6c59ba7ea67..788f35d02c5c 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -322,7 +322,7 @@ sowakeup(struct socket *so, struct sockbuf *sb)
wakeup(&sb->sb_acc);
}
KNOTE_LOCKED(&sb->sb_sel.si_note, 0);
- if (sb->sb_upcall != NULL) {
+ if (sb->sb_upcall != NULL && !(so->so_state & SS_ISDISCONNECTED)) {
ret = sb->sb_upcall(so, sb->sb_upcallarg, M_NOWAIT);
if (ret == SU_ISCONNECTED) {
KASSERT(sb == &so->so_rcv,