git: 608c8658c8c9 - stable/13 - sctp: improve handling of socket shutdown for reading

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Thu, 11 Jan 2024 12:49:22 UTC
The branch stable/13 has been updated by tuexen:

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

commit 608c8658c8c9e78ccce884e137ac341366653e01
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2023-08-24 13:52:55 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2024-01-11 12:48:31 +0000

    sctp: improve handling of socket shutdown for reading
    
    If a socket is marked as cannot read anymore, drop chunks which
    should be added to a control element in the receive queue.
    This is consistent with dropping control elements instead of
    adding them in the same situation.
    
    Reported by:    syzbot+291f6581cecb77097b16@syzkaller.appspotmail.com
    
    (cherry picked from commit 847fa61fad5ef118dc0591d876bf9449200aa818)
---
 sys/netinet/sctp_indata.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index f7f0e3fdfe7f..c195cce96f39 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1290,14 +1290,17 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
 	 * control and free up the chunk resources.
 	 */
 	uint32_t added = 0;
-	int i_locked = 0;
+	bool i_locked = false;
 
-	if (control->on_read_q && (hold_rlock == 0)) {
-		/*
-		 * Its being pd-api'd so we must do some locks.
-		 */
-		SCTP_INP_READ_LOCK(stcb->sctp_ep);
-		i_locked = 1;
+	if (control->on_read_q) {
+		if (hold_rlock == 0) {
+			/* Its being pd-api'd so we must do some locks. */
+			SCTP_INP_READ_LOCK(stcb->sctp_ep);
+			i_locked = true;
+		}
+		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
+			goto out;
+		}
 	}
 	if (control->data == NULL) {
 		control->data = chk->data;
@@ -1346,6 +1349,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *control,
 		control->end_added = 1;
 		control->last_frag_seen = 1;
 	}
+out:
 	if (i_locked) {
 		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
 	}