hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/net/sctp/sm_statefuns.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* SCTP kernel implementation
23 * (C) Copyright IBM Corp. 2001, 2004
34 * Copyright (c) 1999-2000 Cisco, Inc.
....@@ -8,22 +9,6 @@
89 * This is part of the SCTP Linux Kernel Implementation.
910 *
1011 * These are the state functions for the state machine.
11
- *
12
- * This SCTP implementation is free software;
13
- * you can redistribute it and/or modify it under the terms of
14
- * the GNU General Public License as published by
15
- * the Free Software Foundation; either version 2, or (at your option)
16
- * any later version.
17
- *
18
- * This SCTP implementation is distributed in the hope that it
19
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
20
- * ************************
21
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22
- * See the GNU General Public License for more details.
23
- *
24
- * You should have received a copy of the GNU General Public License
25
- * along with GNU CC; see the file COPYING. If not, see
26
- * <http://www.gnu.org/licenses/>.
2712 *
2813 * Please send any bug reports or fixes you make to the
2914 * email address(es):
....@@ -163,6 +148,12 @@
163148 const union sctp_subtype type,
164149 void *arg,
165150 struct sctp_cmd_seq *commands);
151
+
152
+static enum sctp_disposition
153
+__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep,
154
+ const struct sctp_association *asoc,
155
+ const union sctp_subtype type, void *arg,
156
+ struct sctp_cmd_seq *commands);
166157
167158 /* Small helper function that checks if the chunk length
168159 * is of the appropriate length. The 'required_length' argument
....@@ -345,6 +336,14 @@
345336 if (!chunk->singleton)
346337 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
347338
339
+ /* Make sure that the INIT chunk has a valid length.
340
+ * Normally, this would cause an ABORT with a Protocol Violation
341
+ * error, but since we don't have an association, we'll
342
+ * just discard the packet.
343
+ */
344
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk)))
345
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
346
+
348347 /* If the packet is an OOTB packet which is temporarily on the
349348 * control endpoint, respond with an ABORT.
350349 */
....@@ -358,14 +357,6 @@
358357 */
359358 if (chunk->sctp_hdr->vtag != 0)
360359 return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
361
-
362
- /* Make sure that the INIT chunk has a valid length.
363
- * Normally, this would cause an ABORT with a Protocol Violation
364
- * error, but since we don't have an association, we'll
365
- * just discard the packet.
366
- */
367
- if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk)))
368
- return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
369360
370361 /* If the INIT is coming toward a closing socket, we'll send back
371362 * and ABORT. Essentially, this catches the race of INIT being
....@@ -1349,7 +1340,7 @@
13491340 struct sctp_chunk *init,
13501341 struct sctp_cmd_seq *commands)
13511342 {
1352
- struct net *net = sock_net(new_asoc->base.sk);
1343
+ struct net *net = new_asoc->base.net;
13531344 struct sctp_transport *new_addr;
13541345 int ret = 1;
13551346
....@@ -1499,19 +1490,16 @@
14991490 if (!chunk->singleton)
15001491 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
15011492
1493
+ /* Make sure that the INIT chunk has a valid length. */
1494
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk)))
1495
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
1496
+
15021497 /* 3.1 A packet containing an INIT chunk MUST have a zero Verification
15031498 * Tag.
15041499 */
15051500 if (chunk->sctp_hdr->vtag != 0)
15061501 return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
15071502
1508
- /* Make sure that the INIT chunk has a valid length.
1509
- * In this case, we generate a protocol violation since we have
1510
- * an association established.
1511
- */
1512
- if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk)))
1513
- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
1514
- commands);
15151503 /* Grab the INIT header. */
15161504 chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data;
15171505
....@@ -1829,9 +1817,9 @@
18291817 * its peer.
18301818 */
18311819 if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {
1832
- disposition = sctp_sf_do_9_2_reshutack(net, ep, asoc,
1833
- SCTP_ST_CHUNK(chunk->chunk_hdr->type),
1834
- chunk, commands);
1820
+ disposition = __sctp_sf_do_9_2_reshutack(net, ep, asoc,
1821
+ SCTP_ST_CHUNK(chunk->chunk_hdr->type),
1822
+ chunk, commands);
18351823 if (SCTP_DISPOSITION_NOMEM == disposition)
18361824 goto nomem;
18371825
....@@ -2301,7 +2289,7 @@
23012289 */
23022290 if (SCTP_ADDR_DEL ==
23032291 sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
2304
- return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
2292
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
23052293
23062294 if (!sctp_err_chunk_valid(chunk))
23072295 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
....@@ -2347,7 +2335,7 @@
23472335 */
23482336 if (SCTP_ADDR_DEL ==
23492337 sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
2350
- return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
2338
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
23512339
23522340 if (!sctp_err_chunk_valid(chunk))
23532341 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
....@@ -2617,7 +2605,7 @@
26172605 */
26182606 if (SCTP_ADDR_DEL ==
26192607 sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
2620
- return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
2608
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
26212609
26222610 if (!sctp_err_chunk_valid(chunk))
26232611 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
....@@ -2930,13 +2918,11 @@
29302918 * that belong to this association, it should discard the INIT chunk and
29312919 * retransmit the SHUTDOWN ACK chunk.
29322920 */
2933
-enum sctp_disposition sctp_sf_do_9_2_reshutack(
2934
- struct net *net,
2935
- const struct sctp_endpoint *ep,
2936
- const struct sctp_association *asoc,
2937
- const union sctp_subtype type,
2938
- void *arg,
2939
- struct sctp_cmd_seq *commands)
2921
+static enum sctp_disposition
2922
+__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep,
2923
+ const struct sctp_association *asoc,
2924
+ const union sctp_subtype type, void *arg,
2925
+ struct sctp_cmd_seq *commands)
29402926 {
29412927 struct sctp_chunk *chunk = arg;
29422928 struct sctp_chunk *reply;
....@@ -2968,6 +2954,26 @@
29682954 return SCTP_DISPOSITION_CONSUME;
29692955 nomem:
29702956 return SCTP_DISPOSITION_NOMEM;
2957
+}
2958
+
2959
+enum sctp_disposition
2960
+sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep,
2961
+ const struct sctp_association *asoc,
2962
+ const union sctp_subtype type, void *arg,
2963
+ struct sctp_cmd_seq *commands)
2964
+{
2965
+ struct sctp_chunk *chunk = arg;
2966
+
2967
+ if (!chunk->singleton)
2968
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
2969
+
2970
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk)))
2971
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
2972
+
2973
+ if (chunk->sctp_hdr->vtag != 0)
2974
+ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands);
2975
+
2976
+ return __sctp_sf_do_9_2_reshutack(net, ep, asoc, type, arg, commands);
29712977 }
29722978
29732979 /*
....@@ -3330,8 +3336,6 @@
33303336 struct sctp_sackhdr *sackh;
33313337 __u32 ctsn;
33323338
3333
- trace_sctp_probe(ep, asoc, chunk);
3334
-
33353339 if (!sctp_vtag_verify(chunk, asoc))
33363340 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
33373341
....@@ -3348,6 +3352,15 @@
33483352 chunk->subh.sack_hdr = sackh;
33493353 ctsn = ntohl(sackh->cum_tsn_ack);
33503354
3355
+ /* If Cumulative TSN Ack beyond the max tsn currently
3356
+ * send, terminating the association and respond to the
3357
+ * sender with an ABORT.
3358
+ */
3359
+ if (TSN_lte(asoc->next_tsn, ctsn))
3360
+ return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
3361
+
3362
+ trace_sctp_probe(ep, asoc, chunk);
3363
+
33513364 /* i) If Cumulative TSN Ack is less than the Cumulative TSN
33523365 * Ack Point, then drop the SACK. Since Cumulative TSN
33533366 * Ack is monotonically increasing, a SACK whose
....@@ -3360,13 +3373,6 @@
33603373
33613374 return SCTP_DISPOSITION_DISCARD;
33623375 }
3363
-
3364
- /* If Cumulative TSN Ack beyond the max tsn currently
3365
- * send, terminating the association and respond to the
3366
- * sender with an ABORT.
3367
- */
3368
- if (!TSN_lt(ctsn, asoc->next_tsn))
3369
- return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
33703376
33713377 /* Return this SACK for further processing. */
33723378 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk));
....@@ -3766,20 +3772,20 @@
37663772 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
37673773 }
37683774
3775
+ /* Make sure that the ASCONF ADDIP chunk has a valid length. */
3776
+ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk)))
3777
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
3778
+ commands);
3779
+
37693780 /* ADD-IP: Section 4.1.1
37703781 * This chunk MUST be sent in an authenticated way by using
37713782 * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk
37723783 * is received unauthenticated it MUST be silently discarded as
37733784 * described in [I-D.ietf-tsvwg-sctp-auth].
37743785 */
3775
- if (!net->sctp.addip_noauth && !chunk->auth)
3776
- return sctp_sf_discard_chunk(net, ep, asoc, type, arg,
3777
- commands);
3778
-
3779
- /* Make sure that the ASCONF ADDIP chunk has a valid length. */
3780
- if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk)))
3781
- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
3782
- commands);
3786
+ if (!asoc->peer.asconf_capable ||
3787
+ (!net->sctp.addip_noauth && !chunk->auth))
3788
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
37833789
37843790 hdr = (struct sctp_addiphdr *)chunk->skb->data;
37853791 serial = ntohl(hdr->serial);
....@@ -3908,21 +3914,21 @@
39083914 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
39093915 }
39103916
3917
+ /* Make sure that the ADDIP chunk has a valid length. */
3918
+ if (!sctp_chunk_length_valid(asconf_ack,
3919
+ sizeof(struct sctp_addip_chunk)))
3920
+ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
3921
+ commands);
3922
+
39113923 /* ADD-IP, Section 4.1.2:
39123924 * This chunk MUST be sent in an authenticated way by using
39133925 * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk
39143926 * is received unauthenticated it MUST be silently discarded as
39153927 * described in [I-D.ietf-tsvwg-sctp-auth].
39163928 */
3917
- if (!net->sctp.addip_noauth && !asconf_ack->auth)
3918
- return sctp_sf_discard_chunk(net, ep, asoc, type, arg,
3919
- commands);
3920
-
3921
- /* Make sure that the ADDIP chunk has a valid length. */
3922
- if (!sctp_chunk_length_valid(asconf_ack,
3923
- sizeof(struct sctp_addip_chunk)))
3924
- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
3925
- commands);
3929
+ if (!asoc->peer.asconf_capable ||
3930
+ (!net->sctp.addip_noauth && !asconf_ack->auth))
3931
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
39263932
39273933 addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data;
39283934 rcvd_serial = ntohl(addip_hdr->serial);
....@@ -4350,7 +4356,7 @@
43504356 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
43514357 SCTP_CHUNK(err_chunk));
43524358 }
4353
- /* Fall Through */
4359
+ fallthrough;
43544360 case SCTP_IERROR_AUTH_BAD_KEYID:
43554361 case SCTP_IERROR_BAD_SIG:
43564362 return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
....@@ -4493,6 +4499,9 @@
44934499 struct sctp_cmd_seq *commands)
44944500 {
44954501 struct sctp_chunk *chunk = arg;
4502
+
4503
+ if (asoc && !sctp_vtag_verify(chunk, asoc))
4504
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
44964505
44974506 /* Make sure that the chunk has a valid length.
44984507 * Since we don't know the chunk type, we use a general
....@@ -6471,13 +6480,15 @@
64716480 * in sctp_ulpevent_make_rcvmsg will drop the frame if we grow our
64726481 * memory usage too much
64736482 */
6474
- if (*sk->sk_prot_creator->memory_pressure) {
6483
+ if (sk_under_memory_pressure(sk)) {
64756484 if (sctp_tsnmap_has_gap(map) &&
64766485 (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
64776486 pr_debug("%s: under pressure, reneging for tsn:%u\n",
64786487 __func__, tsn);
64796488 deliver = SCTP_CMD_RENEGE;
6480
- }
6489
+ } else {
6490
+ sk_mem_reclaim(sk);
6491
+ }
64816492 }
64826493
64836494 /*