git: e0127ea4c6b5 - main - sctp: improve locking

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Fri, 15 Apr 2022 13:15:24 UTC
The branch main has been updated by tuexen:

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

commit e0127ea4c6b50a5bf239482d8a99ae418174aee5
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2022-04-15 11:58:45 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2022-04-15 11:58:45 +0000

    sctp: improve locking
    
    Hold a refcount while giving up an stcp lock. This issue was
    found by running syzkaller.
    
    MFC after:      3 days
---
 sys/netinet/sctp_input.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 53e3de222ad5..52d8f6b7d523 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2326,15 +2326,22 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
 	/*
 	 * compute the signature/digest for the cookie
 	 */
-	ep = &(*inp_p)->sctp_ep;
-	l_inp = *inp_p;
-	if (l_stcb) {
+	if (l_stcb != NULL) {
+		atomic_add_int(&l_stcb->asoc.refcnt, 1);
 		SCTP_TCB_UNLOCK(l_stcb);
 	}
+	l_inp = *inp_p;
 	SCTP_INP_RLOCK(l_inp);
-	if (l_stcb) {
+	if (l_stcb != NULL) {
 		SCTP_TCB_LOCK(l_stcb);
+		atomic_subtract_int(&l_stcb->asoc.refcnt, 1);
 	}
+	if (l_inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
+		SCTP_INP_RUNLOCK(l_inp);
+		sctp_m_freem(m_sig);
+		return (NULL);
+	}
+	ep = &(*inp_p)->sctp_ep;
 	/* which cookie is it? */
 	if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) &&
 	    (ep->current_secret_number != ep->last_secret_number)) {