git: d682c1eaa598 - main - unix: synchronize shutdown(2) with read(2)

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 03 Feb 2024 21:10:56 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=d682c1eaa598a6bb4b9b81ba80e8e1202a0c9611

commit d682c1eaa598a6bb4b9b81ba80e8e1202a0c9611
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-02-03 21:08:41 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-02-03 21:08:41 +0000

    unix: synchronize shutdown(2) with read(2)
    
    unp_dispose() is called on shutdown(2) and thus needs to acquire socket
    I/O receive sx(9) to synchronize with read(2) that may read top of the
    buffer without socket buffer mutex.  Notice in the last chunk of the diff
    that the function used to be called with the lock already acquired in the
    past.
---
 sys/kern/uipc_usrreq.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 976490dbe2d8..a9a7dd3a1189 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -3217,6 +3217,7 @@ unp_dispose(struct socket *so)
 	struct sockbuf *sb;
 	struct unpcb *unp;
 	struct mbuf *m;
+	int error __diagused;
 
 	MPASS(!SOLISTENING(so));
 
@@ -3228,6 +3229,8 @@ unp_dispose(struct socket *so)
 	/*
 	 * Grab our special mbufs before calling sbrelease().
 	 */
+	error = SOCK_IO_RECV_LOCK(so, SBL_WAIT | SBL_NOINTR);
+	MPASS(!error);
 	SOCK_RECVBUF_LOCK(so);
 	switch (so->so_type) {
 	case SOCK_DGRAM:
@@ -3279,8 +3282,7 @@ unp_dispose(struct socket *so)
 		break;
 	}
 	SOCK_RECVBUF_UNLOCK(so);
-	if (SOCK_IO_RECV_OWNED(so))
-		SOCK_IO_RECV_UNLOCK(so);
+	SOCK_IO_RECV_UNLOCK(so);
 
 	if (m != NULL) {
 		unp_scan(m, unp_freerights);