summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2020-07-22 18:52:12 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-07-31 19:37:48 +0300
commitf971676781e347c429db89afa46dca8a3d3a40ab (patch)
tree259b7c4c54fdea07d9fe3396f68b2f733fe43e9c
parentf2ee813189dd143c301965da44607117441d9ab0 (diff)
downloadlinux-f971676781e347c429db89afa46dca8a3d3a40ab.tar.xz
sctp: shrink stream outq when fails to do addstream reconf
[ Upstream commit 3ecdda3e9ad837cf9cb41b6faa11b1af3a5abc0c ] When adding a stream with stream reconf, the new stream firstly is in CLOSED state but new out chunks can still be enqueued. Then once gets the confirmation from the peer, the state will change to OPEN. However, if the peer denies, it needs to roll back the stream. But when doing that, it only sets the stream outcnt back, and the chunks already in the new stream don't get purged. It caused these chunks can still be dequeued in sctp_outq_dequeue_data(). As its stream is still in CLOSE, the chunk will be enqueued to the head again by sctp_outq_head_data(). This chunk will never be sent out, and the chunks after it can never be dequeued. The assoc will be 'hung' in a dead loop of sending this chunk. To fix it, this patch is to purge these chunks already in the new stream by calling sctp_stream_shrink_out() when failing to do the addstream reconf. Fixes: 11ae76e67a17 ("sctp: implement receiver-side procedures for the Reconf Response Parameter") Reported-by: Ying Xu <yinxu@redhat.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/sctp/stream.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 6752861d8668..516bc48be5bc 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -1143,11 +1143,13 @@ struct sctp_chunk *sctp_process_strreset_resp(
nums = ntohs(addstrm->number_of_streams);
number = stream->outcnt - nums;
- if (result == SCTP_STRRESET_PERFORMED)
+ if (result == SCTP_STRRESET_PERFORMED) {
for (i = number; i < stream->outcnt; i++)
SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
- else
+ } else {
+ sctp_stream_shrink_out(stream, number);
stream->outcnt = number;
+ }
*evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
0, nums, GFP_ATOMIC);