hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/net/sctp/stream_interleave.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* SCTP kernel implementation
23 * (C) Copyright Red Hat Inc. 2017
34 *
....@@ -5,22 +6,6 @@
56 *
67 * These functions implement sctp stream message interleaving, mostly
78 * including I-DATA and I-FORWARD-TSN chunks process.
8
- *
9
- * This SCTP implementation is free software;
10
- * you can redistribute it and/or modify it under the terms of
11
- * the GNU General Public License as published by
12
- * the Free Software Foundation; either version 2, or (at your option)
13
- * any later version.
14
- *
15
- * This SCTP implementation is distributed in the hope that it
16
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
17
- * ************************
18
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
- * See the GNU General Public License for more details.
20
- *
21
- * You should have received a copy of the GNU General Public License
22
- * along with GNU CC; see the file COPYING. If not, see
23
- * <http://www.gnu.org/licenses/>.
249 *
2510 * Please send any bug reports or fixes you make to the
2611 * email addresched(es):
....@@ -101,7 +86,7 @@
10186
10287 static bool sctp_validate_data(struct sctp_chunk *chunk)
10388 {
104
- const struct sctp_stream *stream;
89
+ struct sctp_stream *stream;
10590 __u16 sid, ssn;
10691
10792 if (chunk->chunk_hdr->type != SCTP_CID_DATA)
....@@ -140,7 +125,7 @@
140125 struct sctp_ulpevent *event)
141126 {
142127 struct sctp_ulpevent *cevent;
143
- struct sk_buff *pos;
128
+ struct sk_buff *pos, *loc;
144129
145130 pos = skb_peek_tail(&ulpq->reasm);
146131 if (!pos) {
....@@ -166,23 +151,30 @@
166151 return;
167152 }
168153
154
+ loc = NULL;
169155 skb_queue_walk(&ulpq->reasm, pos) {
170156 cevent = sctp_skb2event(pos);
171157
172158 if (event->stream < cevent->stream ||
173159 (event->stream == cevent->stream &&
174
- MID_lt(event->mid, cevent->mid)))
160
+ MID_lt(event->mid, cevent->mid))) {
161
+ loc = pos;
175162 break;
176
-
163
+ }
177164 if (event->stream == cevent->stream &&
178165 event->mid == cevent->mid &&
179166 !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
180167 (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
181
- event->fsn < cevent->fsn))
168
+ event->fsn < cevent->fsn)) {
169
+ loc = pos;
182170 break;
171
+ }
183172 }
184173
185
- __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event));
174
+ if (!loc)
175
+ __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
176
+ else
177
+ __skb_queue_before(&ulpq->reasm, loc, sctp_event2skb(event));
186178 }
187179
188180 static struct sctp_ulpevent *sctp_intl_retrieve_partial(
....@@ -249,9 +241,8 @@
249241 if (!first_frag)
250242 return NULL;
251243
252
- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
253
- &ulpq->reasm, first_frag,
254
- last_frag);
244
+ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm,
245
+ first_frag, last_frag);
255246 if (retval) {
256247 sin->fsn = next_fsn;
257248 if (is_last) {
....@@ -334,7 +325,7 @@
334325
335326 pd_point = sctp_sk(asoc->base.sk)->pd_point;
336327 if (pd_point && pd_point <= pd_len) {
337
- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
328
+ retval = sctp_make_reassembled_event(asoc->base.net,
338329 &ulpq->reasm,
339330 pd_first, pd_last);
340331 if (retval) {
....@@ -345,8 +336,7 @@
345336 goto out;
346337
347338 found:
348
- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
349
- &ulpq->reasm,
339
+ retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm,
350340 first_frag, pos);
351341 if (retval)
352342 retval->msg_flags |= MSG_EOR;
....@@ -383,7 +373,7 @@
383373 struct sctp_ulpevent *event)
384374 {
385375 struct sctp_ulpevent *cevent;
386
- struct sk_buff *pos;
376
+ struct sk_buff *pos, *loc;
387377
388378 pos = skb_peek_tail(&ulpq->lobby);
389379 if (!pos) {
....@@ -403,18 +393,25 @@
403393 return;
404394 }
405395
396
+ loc = NULL;
406397 skb_queue_walk(&ulpq->lobby, pos) {
407398 cevent = (struct sctp_ulpevent *)pos->cb;
408399
409
- if (cevent->stream > event->stream)
400
+ if (cevent->stream > event->stream) {
401
+ loc = pos;
410402 break;
411
-
403
+ }
412404 if (cevent->stream == event->stream &&
413
- MID_lt(event->mid, cevent->mid))
405
+ MID_lt(event->mid, cevent->mid)) {
406
+ loc = pos;
414407 break;
408
+ }
415409 }
416410
417
- __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event));
411
+ if (!loc)
412
+ __skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
413
+ else
414
+ __skb_queue_before(&ulpq->lobby, loc, sctp_event2skb(event));
418415 }
419416
420417 static void sctp_intl_retrieve_ordered(struct sctp_ulpq *ulpq,
....@@ -470,14 +467,15 @@
470467 }
471468
472469 static int sctp_enqueue_event(struct sctp_ulpq *ulpq,
473
- struct sctp_ulpevent *event)
470
+ struct sk_buff_head *skb_list)
474471 {
475
- struct sk_buff *skb = sctp_event2skb(event);
476472 struct sock *sk = ulpq->asoc->base.sk;
477473 struct sctp_sock *sp = sctp_sk(sk);
478
- struct sk_buff_head *skb_list;
474
+ struct sctp_ulpevent *event;
475
+ struct sk_buff *skb;
479476
480
- skb_list = (struct sk_buff_head *)skb->prev;
477
+ skb = __skb_peek(skb_list);
478
+ event = sctp_skb2event(skb);
481479
482480 if (sk->sk_shutdown & RCV_SHUTDOWN &&
483481 (sk->sk_shutdown & SEND_SHUTDOWN ||
....@@ -489,7 +487,7 @@
489487 sk_incoming_cpu_update(sk);
490488 }
491489
492
- if (!sctp_ulpevent_is_enabled(event, &sp->subscribe))
490
+ if (!sctp_ulpevent_is_enabled(event, ulpq->asoc->subscribe))
493491 goto out_free;
494492
495493 if (skb_list)
....@@ -630,7 +628,7 @@
630628 if (!first_frag)
631629 return NULL;
632630
633
- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
631
+ retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
634632 &ulpq->reasm_uo, first_frag,
635633 last_frag);
636634 if (retval) {
....@@ -716,7 +714,7 @@
716714
717715 pd_point = sctp_sk(asoc->base.sk)->pd_point;
718716 if (pd_point && pd_point <= pd_len) {
719
- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
717
+ retval = sctp_make_reassembled_event(asoc->base.net,
720718 &ulpq->reasm_uo,
721719 pd_first, pd_last);
722720 if (retval) {
....@@ -727,8 +725,7 @@
727725 goto out;
728726
729727 found:
730
- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk),
731
- &ulpq->reasm_uo,
728
+ retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm_uo,
732729 first_frag, pos);
733730 if (retval)
734731 retval->msg_flags |= MSG_EOR;
....@@ -814,7 +811,7 @@
814811 return NULL;
815812
816813 out:
817
- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
814
+ retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
818815 &ulpq->reasm_uo, first_frag,
819816 last_frag);
820817 if (retval) {
....@@ -844,19 +841,24 @@
844841
845842 if (!(event->msg_flags & SCTP_DATA_UNORDERED)) {
846843 event = sctp_intl_reasm(ulpq, event);
847
- if (event && event->msg_flags & MSG_EOR) {
844
+ if (event) {
848845 skb_queue_head_init(&temp);
849846 __skb_queue_tail(&temp, sctp_event2skb(event));
850847
851
- event = sctp_intl_order(ulpq, event);
848
+ if (event->msg_flags & MSG_EOR)
849
+ event = sctp_intl_order(ulpq, event);
852850 }
853851 } else {
854852 event = sctp_intl_reasm_uo(ulpq, event);
853
+ if (event) {
854
+ skb_queue_head_init(&temp);
855
+ __skb_queue_tail(&temp, sctp_event2skb(event));
856
+ }
855857 }
856858
857859 if (event) {
858860 event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0;
859
- sctp_enqueue_event(ulpq, event);
861
+ sctp_enqueue_event(ulpq, &temp);
860862 }
861863
862864 return event_eor;
....@@ -916,7 +918,7 @@
916918 return NULL;
917919
918920 out:
919
- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk),
921
+ retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
920922 &ulpq->reasm, first_frag,
921923 last_frag);
922924 if (retval) {
....@@ -930,20 +932,27 @@
930932 static void sctp_intl_start_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
931933 {
932934 struct sctp_ulpevent *event;
935
+ struct sk_buff_head temp;
933936
934937 if (!skb_queue_empty(&ulpq->reasm)) {
935938 do {
936939 event = sctp_intl_retrieve_first(ulpq);
937
- if (event)
938
- sctp_enqueue_event(ulpq, event);
940
+ if (event) {
941
+ skb_queue_head_init(&temp);
942
+ __skb_queue_tail(&temp, sctp_event2skb(event));
943
+ sctp_enqueue_event(ulpq, &temp);
944
+ }
939945 } while (event);
940946 }
941947
942948 if (!skb_queue_empty(&ulpq->reasm_uo)) {
943949 do {
944950 event = sctp_intl_retrieve_first_uo(ulpq);
945
- if (event)
946
- sctp_enqueue_event(ulpq, event);
951
+ if (event) {
952
+ skb_queue_head_init(&temp);
953
+ __skb_queue_tail(&temp, sctp_event2skb(event));
954
+ sctp_enqueue_event(ulpq, &temp);
955
+ }
947956 } while (event);
948957 }
949958 }
....@@ -980,17 +989,19 @@
980989 struct sock *sk = ulpq->asoc->base.sk;
981990 struct sctp_ulpevent *ev = NULL;
982991
983
- if (!sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT,
984
- &sctp_sk(sk)->subscribe))
992
+ if (!sctp_ulpevent_type_enabled(ulpq->asoc->subscribe,
993
+ SCTP_PARTIAL_DELIVERY_EVENT))
985994 return;
986995
987996 ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED,
988997 sid, mid, flags, gfp);
989998 if (ev) {
999
+ struct sctp_sock *sp = sctp_sk(sk);
1000
+
9901001 __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
9911002
992
- if (!sctp_sk(sk)->data_ready_signalled) {
993
- sctp_sk(sk)->data_ready_signalled = 1;
1003
+ if (!sp->data_ready_signalled) {
1004
+ sp->data_ready_signalled = 1;
9941005 sk->sk_data_ready(sk);
9951006 }
9961007 }
....@@ -1043,7 +1054,7 @@
10431054
10441055 if (event) {
10451056 sctp_intl_retrieve_ordered(ulpq, event);
1046
- sctp_enqueue_event(ulpq, event);
1057
+ sctp_enqueue_event(ulpq, &temp);
10471058 }
10481059 }
10491060
....@@ -1145,7 +1156,7 @@
11451156
11461157 if (ftsn_chunk) {
11471158 list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
1148
- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS);
1159
+ SCTP_INC_STATS(asoc->base.net, SCTP_MIB_OUTCTRLCHUNKS);
11491160 }
11501161 }
11511162
....@@ -1282,6 +1293,15 @@
12821293 ntohl(skip->mid), skip->flags);
12831294 }
12841295
1296
+static int do_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
1297
+{
1298
+ struct sk_buff_head temp;
1299
+
1300
+ skb_queue_head_init(&temp);
1301
+ __skb_queue_tail(&temp, sctp_event2skb(event));
1302
+ return sctp_ulpq_tail_event(ulpq, &temp);
1303
+}
1304
+
12851305 static struct sctp_stream_interleave sctp_stream_interleave_0 = {
12861306 .data_chunk_len = sizeof(struct sctp_data_chunk),
12871307 .ftsn_chunk_len = sizeof(struct sctp_fwdtsn_chunk),
....@@ -1290,7 +1310,7 @@
12901310 .assign_number = sctp_chunk_assign_ssn,
12911311 .validate_data = sctp_validate_data,
12921312 .ulpevent_data = sctp_ulpq_tail_data,
1293
- .enqueue_event = sctp_ulpq_tail_event,
1313
+ .enqueue_event = do_ulpq_tail_event,
12941314 .renege_events = sctp_ulpq_renege,
12951315 .start_pd = sctp_ulpq_partial_delivery,
12961316 .abort_pd = sctp_ulpq_abort_pd,
....@@ -1301,6 +1321,16 @@
13011321 .handle_ftsn = sctp_handle_fwdtsn,
13021322 };
13031323
1324
+static int do_sctp_enqueue_event(struct sctp_ulpq *ulpq,
1325
+ struct sctp_ulpevent *event)
1326
+{
1327
+ struct sk_buff_head temp;
1328
+
1329
+ skb_queue_head_init(&temp);
1330
+ __skb_queue_tail(&temp, sctp_event2skb(event));
1331
+ return sctp_enqueue_event(ulpq, &temp);
1332
+}
1333
+
13041334 static struct sctp_stream_interleave sctp_stream_interleave_1 = {
13051335 .data_chunk_len = sizeof(struct sctp_idata_chunk),
13061336 .ftsn_chunk_len = sizeof(struct sctp_ifwdtsn_chunk),
....@@ -1309,7 +1339,7 @@
13091339 .assign_number = sctp_chunk_assign_mid,
13101340 .validate_data = sctp_validate_idata,
13111341 .ulpevent_data = sctp_ulpevent_idata,
1312
- .enqueue_event = sctp_enqueue_event,
1342
+ .enqueue_event = do_sctp_enqueue_event,
13131343 .renege_events = sctp_renege_events,
13141344 .start_pd = sctp_intl_start_pd,
13151345 .abort_pd = sctp_intl_abort_pd,
....@@ -1325,6 +1355,6 @@
13251355 struct sctp_association *asoc;
13261356
13271357 asoc = container_of(stream, struct sctp_association, stream);
1328
- stream->si = asoc->intl_enable ? &sctp_stream_interleave_1
1329
- : &sctp_stream_interleave_0;
1358
+ stream->si = asoc->peer.intl_capable ? &sctp_stream_interleave_1
1359
+ : &sctp_stream_interleave_0;
13301360 }