.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* SCTP kernel implementation |
---|
2 | 3 | * (C) Copyright IBM Corp. 2001, 2004 |
---|
3 | 4 | * Copyright (c) 1999-2000 Cisco, Inc. |
---|
.. | .. |
---|
8 | 9 | * This is part of the SCTP Linux Kernel Implementation. |
---|
9 | 10 | * |
---|
10 | 11 | * 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/>. |
---|
27 | 12 | * |
---|
28 | 13 | * Please send any bug reports or fixes you make to the |
---|
29 | 14 | * email address(es): |
---|
.. | .. |
---|
163 | 148 | const union sctp_subtype type, |
---|
164 | 149 | void *arg, |
---|
165 | 150 | 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); |
---|
166 | 157 | |
---|
167 | 158 | /* Small helper function that checks if the chunk length |
---|
168 | 159 | * is of the appropriate length. The 'required_length' argument |
---|
.. | .. |
---|
345 | 336 | if (!chunk->singleton) |
---|
346 | 337 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
347 | 338 | |
---|
| 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 | + |
---|
348 | 347 | /* If the packet is an OOTB packet which is temporarily on the |
---|
349 | 348 | * control endpoint, respond with an ABORT. |
---|
350 | 349 | */ |
---|
.. | .. |
---|
358 | 357 | */ |
---|
359 | 358 | if (chunk->sctp_hdr->vtag != 0) |
---|
360 | 359 | 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); |
---|
369 | 360 | |
---|
370 | 361 | /* If the INIT is coming toward a closing socket, we'll send back |
---|
371 | 362 | * and ABORT. Essentially, this catches the race of INIT being |
---|
.. | .. |
---|
1349 | 1340 | struct sctp_chunk *init, |
---|
1350 | 1341 | struct sctp_cmd_seq *commands) |
---|
1351 | 1342 | { |
---|
1352 | | - struct net *net = sock_net(new_asoc->base.sk); |
---|
| 1343 | + struct net *net = new_asoc->base.net; |
---|
1353 | 1344 | struct sctp_transport *new_addr; |
---|
1354 | 1345 | int ret = 1; |
---|
1355 | 1346 | |
---|
.. | .. |
---|
1499 | 1490 | if (!chunk->singleton) |
---|
1500 | 1491 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
1501 | 1492 | |
---|
| 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 | + |
---|
1502 | 1497 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification |
---|
1503 | 1498 | * Tag. |
---|
1504 | 1499 | */ |
---|
1505 | 1500 | if (chunk->sctp_hdr->vtag != 0) |
---|
1506 | 1501 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
---|
1507 | 1502 | |
---|
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); |
---|
1515 | 1503 | /* Grab the INIT header. */ |
---|
1516 | 1504 | chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; |
---|
1517 | 1505 | |
---|
.. | .. |
---|
1829 | 1817 | * its peer. |
---|
1830 | 1818 | */ |
---|
1831 | 1819 | 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); |
---|
1835 | 1823 | if (SCTP_DISPOSITION_NOMEM == disposition) |
---|
1836 | 1824 | goto nomem; |
---|
1837 | 1825 | |
---|
.. | .. |
---|
2301 | 2289 | */ |
---|
2302 | 2290 | if (SCTP_ADDR_DEL == |
---|
2303 | 2291 | 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); |
---|
2305 | 2293 | |
---|
2306 | 2294 | if (!sctp_err_chunk_valid(chunk)) |
---|
2307 | 2295 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
.. | .. |
---|
2347 | 2335 | */ |
---|
2348 | 2336 | if (SCTP_ADDR_DEL == |
---|
2349 | 2337 | 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); |
---|
2351 | 2339 | |
---|
2352 | 2340 | if (!sctp_err_chunk_valid(chunk)) |
---|
2353 | 2341 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
.. | .. |
---|
2617 | 2605 | */ |
---|
2618 | 2606 | if (SCTP_ADDR_DEL == |
---|
2619 | 2607 | 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); |
---|
2621 | 2609 | |
---|
2622 | 2610 | if (!sctp_err_chunk_valid(chunk)) |
---|
2623 | 2611 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
.. | .. |
---|
2930 | 2918 | * that belong to this association, it should discard the INIT chunk and |
---|
2931 | 2919 | * retransmit the SHUTDOWN ACK chunk. |
---|
2932 | 2920 | */ |
---|
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) |
---|
2940 | 2926 | { |
---|
2941 | 2927 | struct sctp_chunk *chunk = arg; |
---|
2942 | 2928 | struct sctp_chunk *reply; |
---|
.. | .. |
---|
2968 | 2954 | return SCTP_DISPOSITION_CONSUME; |
---|
2969 | 2955 | nomem: |
---|
2970 | 2956 | 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); |
---|
2971 | 2977 | } |
---|
2972 | 2978 | |
---|
2973 | 2979 | /* |
---|
.. | .. |
---|
3330 | 3336 | struct sctp_sackhdr *sackh; |
---|
3331 | 3337 | __u32 ctsn; |
---|
3332 | 3338 | |
---|
3333 | | - trace_sctp_probe(ep, asoc, chunk); |
---|
3334 | | - |
---|
3335 | 3339 | if (!sctp_vtag_verify(chunk, asoc)) |
---|
3336 | 3340 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
3337 | 3341 | |
---|
.. | .. |
---|
3348 | 3352 | chunk->subh.sack_hdr = sackh; |
---|
3349 | 3353 | ctsn = ntohl(sackh->cum_tsn_ack); |
---|
3350 | 3354 | |
---|
| 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 | + |
---|
3351 | 3364 | /* i) If Cumulative TSN Ack is less than the Cumulative TSN |
---|
3352 | 3365 | * Ack Point, then drop the SACK. Since Cumulative TSN |
---|
3353 | 3366 | * Ack is monotonically increasing, a SACK whose |
---|
.. | .. |
---|
3360 | 3373 | |
---|
3361 | 3374 | return SCTP_DISPOSITION_DISCARD; |
---|
3362 | 3375 | } |
---|
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); |
---|
3370 | 3376 | |
---|
3371 | 3377 | /* Return this SACK for further processing. */ |
---|
3372 | 3378 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk)); |
---|
.. | .. |
---|
3766 | 3772 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
3767 | 3773 | } |
---|
3768 | 3774 | |
---|
| 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 | + |
---|
3769 | 3780 | /* ADD-IP: Section 4.1.1 |
---|
3770 | 3781 | * This chunk MUST be sent in an authenticated way by using |
---|
3771 | 3782 | * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk |
---|
3772 | 3783 | * is received unauthenticated it MUST be silently discarded as |
---|
3773 | 3784 | * described in [I-D.ietf-tsvwg-sctp-auth]. |
---|
3774 | 3785 | */ |
---|
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); |
---|
3783 | 3789 | |
---|
3784 | 3790 | hdr = (struct sctp_addiphdr *)chunk->skb->data; |
---|
3785 | 3791 | serial = ntohl(hdr->serial); |
---|
.. | .. |
---|
3908 | 3914 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
3909 | 3915 | } |
---|
3910 | 3916 | |
---|
| 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 | + |
---|
3911 | 3923 | /* ADD-IP, Section 4.1.2: |
---|
3912 | 3924 | * This chunk MUST be sent in an authenticated way by using |
---|
3913 | 3925 | * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk |
---|
3914 | 3926 | * is received unauthenticated it MUST be silently discarded as |
---|
3915 | 3927 | * described in [I-D.ietf-tsvwg-sctp-auth]. |
---|
3916 | 3928 | */ |
---|
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); |
---|
3926 | 3932 | |
---|
3927 | 3933 | addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data; |
---|
3928 | 3934 | rcvd_serial = ntohl(addip_hdr->serial); |
---|
.. | .. |
---|
4350 | 4356 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
---|
4351 | 4357 | SCTP_CHUNK(err_chunk)); |
---|
4352 | 4358 | } |
---|
4353 | | - /* Fall Through */ |
---|
| 4359 | + fallthrough; |
---|
4354 | 4360 | case SCTP_IERROR_AUTH_BAD_KEYID: |
---|
4355 | 4361 | case SCTP_IERROR_BAD_SIG: |
---|
4356 | 4362 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
---|
.. | .. |
---|
4493 | 4499 | struct sctp_cmd_seq *commands) |
---|
4494 | 4500 | { |
---|
4495 | 4501 | 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); |
---|
4496 | 4505 | |
---|
4497 | 4506 | /* Make sure that the chunk has a valid length. |
---|
4498 | 4507 | * Since we don't know the chunk type, we use a general |
---|
.. | .. |
---|
6471 | 6480 | * in sctp_ulpevent_make_rcvmsg will drop the frame if we grow our |
---|
6472 | 6481 | * memory usage too much |
---|
6473 | 6482 | */ |
---|
6474 | | - if (*sk->sk_prot_creator->memory_pressure) { |
---|
| 6483 | + if (sk_under_memory_pressure(sk)) { |
---|
6475 | 6484 | if (sctp_tsnmap_has_gap(map) && |
---|
6476 | 6485 | (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { |
---|
6477 | 6486 | pr_debug("%s: under pressure, reneging for tsn:%u\n", |
---|
6478 | 6487 | __func__, tsn); |
---|
6479 | 6488 | deliver = SCTP_CMD_RENEGE; |
---|
6480 | | - } |
---|
| 6489 | + } else { |
---|
| 6490 | + sk_mem_reclaim(sk); |
---|
| 6491 | + } |
---|
6481 | 6492 | } |
---|
6482 | 6493 | |
---|
6483 | 6494 | /* |
---|