git: 429f2fb48b92 - main - sctp: hold tcp lock when calling sctp_calc_rwnd()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 11 Oct 2026 20:05:21 UTC
The branch main has been updated by tuexen:
URL: https://cgit.FreeBSD.org/src/commit/?id=429f2fb48b92011d07798e681d96aa628fd8e387
commit 429f2fb48b92011d07798e681d96aa628fd8e387
Author: Lukas Book <lkbook@outlook.de>
AuthorDate: 2026-10-11 20:00:06 +0000
Commit: Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2026-10-11 20:00:06 +0000
sctp: hold tcp lock when calling sctp_calc_rwnd()
This was done in all code paths except one. Fix this to avoid
race conditions.
Reported by: syzbot+2e2dc35c0e24a74663a7@syzkaller.appspotmail.com
Reviewed by: tuexen
MFC after: 1 week
MFC to: stable/14
MFC to: stable/15
---
sys/netinet/sctputil.c | 35 ++++++++++++++---------------------
1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index ddfa71d5c7ed..119fad13c3f0 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -5452,9 +5452,20 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
goto out;
}
atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far);
- /* Have you have freed enough to look */
*freed_so_far = 0;
- /* Yep, its worth a look and the lock overhead */
+ if (hold_rlock) {
+ SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
+ r_unlocked = 1;
+ }
+ if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ goto out;
+ }
+ SCTP_TCB_LOCK(stcb);
+ if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ /* No reports here */
+ SCTP_TCB_UNLOCK(stcb);
+ goto out;
+ }
/* Figure out what the rwnd would be */
rwnd = sctp_calc_rwnd(stcb, &stcb->asoc);
@@ -5464,24 +5475,6 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
dif = 0;
}
if (dif >= rwnd_req) {
- if (hold_rlock) {
- SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
- r_unlocked = 1;
- }
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
- /*
- * One last check before we allow the guy possibly
- * to get in. There is a race, where the guy has not
- * reached the gate. In that case
- */
- goto out;
- }
- SCTP_TCB_LOCK(stcb);
- if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
- /* No reports here */
- SCTP_TCB_UNLOCK(stcb);
- goto out;
- }
SCTP_STAT_INCR(sctps_wu_sacks_sent);
NET_EPOCH_ENTER(et);
sctp_send_sack(stcb, SCTP_SO_LOCKED);
@@ -5492,11 +5485,11 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
NET_EPOCH_EXIT(et);
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL,
SCTP_FROM_SCTPUTIL + SCTP_LOC_6);
- SCTP_TCB_UNLOCK(stcb);
} else {
/* Update how much we have pending */
stcb->freed_by_sorcv_sincelast = dif;
}
+ SCTP_TCB_UNLOCK(stcb);
out:
if (so && r_unlocked && hold_rlock) {
SCTP_INP_READ_LOCK(stcb->sctp_ep);