git: efad7cbfdc06 - main - ng_ksocket: fix upcall clearing on node shutdown

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Fri, 17 Nov 2023 17:24:52 UTC
The branch main has been updated by glebius:

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

commit efad7cbfdc06e92bcc589a6c0cae2f3bea0d5cb9
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2023-11-17 17:23:58 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2023-11-17 17:23:58 +0000

    ng_ksocket: fix upcall clearing on node shutdown
    
    Note: imho, the proper solution would be to guarantee that upcalls
    won't ever be called after soclose(), but this isn't the case, yet.
    This change at least makes the node work the way it always worked.
    
    Reviewed by:            afedorov
    Differential Revision:  https://reviews.freebsd.org/D42636
    PR:                     272319
    PR:                     275106
    Fixes:                  779f106aa169256b7010a1d8f963ff656b881e92
---
 sys/netgraph/ng_ksocket.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c
index 7e5be8c211ae..337248789473 100644
--- a/sys/netgraph/ng_ksocket.c
+++ b/sys/netgraph/ng_ksocket.c
@@ -929,17 +929,24 @@ static int
 ng_ksocket_shutdown(node_p node)
 {
 	const priv_p priv = NG_NODE_PRIVATE(node);
+	struct socket *so = priv->so;
 	priv_p embryo;
 
 	/* Close our socket (if any) */
 	if (priv->so != NULL) {
-		SOCKBUF_LOCK(&priv->so->so_rcv);
-		soupcall_clear(priv->so, SO_RCV);
-		SOCKBUF_UNLOCK(&priv->so->so_rcv);
-		SOCKBUF_LOCK(&priv->so->so_snd);
-		soupcall_clear(priv->so, SO_SND);
-		SOCKBUF_UNLOCK(&priv->so->so_snd);
-		soclose(priv->so);
+		if (SOLISTENING(so)) {
+			SOLISTEN_LOCK(so);
+			solisten_upcall_set(so, NULL, NULL);
+			SOLISTEN_UNLOCK(so);
+		} else {
+			SOCK_RECVBUF_LOCK(so);
+			soupcall_clear(so, SO_RCV);
+			SOCK_RECVBUF_UNLOCK(so);
+			SOCK_SENDBUF_LOCK(so);
+			soupcall_clear(so, SO_SND);
+			SOCK_SENDBUF_UNLOCK(so);
+		}
+		soclose(so);
 		priv->so = NULL;
 	}