From 0532a7a2dff0d84bf0179cbaab5a43dd1a7f3080 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 14 May 2020 20:17:09 +0000 Subject: [PATCH] Fix r361037. Reorder flag manipulations and use barrier to ensure that the program order is followed by compiler and CPU, for unlocked reader of so_state. In collaboration with: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D24842 --- sys/kern/uipc_socket.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ef7083b4576..0b07350f6c9 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -4016,8 +4016,17 @@ soisdisconnected(struct socket *so) { SOCK_LOCK(so); - so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); + + /* + * There is at least one reader of so_state that does not + * acquire socket lock, namely soreceive_generic(). Ensure + * that it never sees all flags that track connection status + * cleared, by ordering the update with a barrier semantic of + * our release thread fence. + */ so->so_state |= SS_ISDISCONNECTED; + atomic_thread_fence_rel(); + so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); if (!SOLISTENING(so)) { SOCK_UNLOCK(so);