From: Greg Kroah-Hartman Date: Wed, 16 Mar 2022 14:25:33 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v5.4.186~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7ab5633b49f8d8c1bcb4093a650c8de791b76229;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: sctp-fix-the-processing-for-init-chunk.patch --- diff --git a/queue-5.4/sctp-fix-the-processing-for-init-chunk.patch b/queue-5.4/sctp-fix-the-processing-for-init-chunk.patch new file mode 100644 index 00000000000..a1c0e7dc732 --- /dev/null +++ b/queue-5.4/sctp-fix-the-processing-for-init-chunk.patch @@ -0,0 +1,161 @@ +From eae5783908042a762c24e1bd11876edb91d314b1 Mon Sep 17 00:00:00 2001 +From: Xin Long +Date: Wed, 20 Oct 2021 07:42:42 -0400 +Subject: sctp: fix the processing for INIT chunk + +From: Xin Long + +commit eae5783908042a762c24e1bd11876edb91d314b1 upstream. + +This patch fixes the problems below: + +1. In non-shutdown_ack_sent states: in sctp_sf_do_5_1B_init() and + sctp_sf_do_5_2_2_dupinit(): + + chunk length check should be done before any checks that may cause + to send abort, as making packet for abort will access the init_tag + from init_hdr in sctp_ootb_pkt_new(). + +2. In shutdown_ack_sent state: in sctp_sf_do_9_2_reshutack(): + + The same checks as does in sctp_sf_do_5_2_2_dupinit() is needed + for sctp_sf_do_9_2_reshutack(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: Jakub Kicinski +Signed-off-by: Ovidiu Panait +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sm_statefuns.c | 71 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 46 insertions(+), 25 deletions(-) + +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -149,6 +149,12 @@ static enum sctp_disposition __sctp_sf_d + void *arg, + struct sctp_cmd_seq *commands); + ++static enum sctp_disposition ++__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, ++ const struct sctp_association *asoc, ++ const union sctp_subtype type, void *arg, ++ struct sctp_cmd_seq *commands); ++ + /* Small helper function that checks if the chunk length + * is of the appropriate length. The 'required_length' argument + * is set to be the size of a specific chunk we are testing. +@@ -330,6 +336,14 @@ enum sctp_disposition sctp_sf_do_5_1B_in + if (!chunk->singleton) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + ++ /* Make sure that the INIT chunk has a valid length. ++ * Normally, this would cause an ABORT with a Protocol Violation ++ * error, but since we don't have an association, we'll ++ * just discard the packet. ++ */ ++ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) ++ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); ++ + /* If the packet is an OOTB packet which is temporarily on the + * control endpoint, respond with an ABORT. + */ +@@ -344,14 +358,6 @@ enum sctp_disposition sctp_sf_do_5_1B_in + if (chunk->sctp_hdr->vtag != 0) + return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); + +- /* Make sure that the INIT chunk has a valid length. +- * Normally, this would cause an ABORT with a Protocol Violation +- * error, but since we don't have an association, we'll +- * just discard the packet. +- */ +- if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) +- return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); +- + /* If the INIT is coming toward a closing socket, we'll send back + * and ABORT. Essentially, this catches the race of INIT being + * backloged to the socket at the same time as the user isses close(). +@@ -1484,19 +1490,16 @@ static enum sctp_disposition sctp_sf_do_ + if (!chunk->singleton) + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); + ++ /* Make sure that the INIT chunk has a valid length. */ ++ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) ++ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); ++ + /* 3.1 A packet containing an INIT chunk MUST have a zero Verification + * Tag. + */ + if (chunk->sctp_hdr->vtag != 0) + return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); + +- /* Make sure that the INIT chunk has a valid length. +- * In this case, we generate a protocol violation since we have +- * an association established. +- */ +- if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) +- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, +- commands); + /* Grab the INIT header. */ + chunk->subh.init_hdr = (struct sctp_inithdr *)chunk->skb->data; + +@@ -1814,9 +1817,9 @@ static enum sctp_disposition sctp_sf_do_ + * its peer. + */ + if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) { +- disposition = sctp_sf_do_9_2_reshutack(net, ep, asoc, +- SCTP_ST_CHUNK(chunk->chunk_hdr->type), +- chunk, commands); ++ disposition = __sctp_sf_do_9_2_reshutack(net, ep, asoc, ++ SCTP_ST_CHUNK(chunk->chunk_hdr->type), ++ chunk, commands); + if (SCTP_DISPOSITION_NOMEM == disposition) + goto nomem; + +@@ -2915,13 +2918,11 @@ enum sctp_disposition sctp_sf_do_9_2_shu + * that belong to this association, it should discard the INIT chunk and + * retransmit the SHUTDOWN ACK chunk. + */ +-enum sctp_disposition sctp_sf_do_9_2_reshutack( +- struct net *net, +- const struct sctp_endpoint *ep, +- const struct sctp_association *asoc, +- const union sctp_subtype type, +- void *arg, +- struct sctp_cmd_seq *commands) ++static enum sctp_disposition ++__sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, ++ const struct sctp_association *asoc, ++ const union sctp_subtype type, void *arg, ++ struct sctp_cmd_seq *commands) + { + struct sctp_chunk *chunk = arg; + struct sctp_chunk *reply; +@@ -2955,6 +2956,26 @@ nomem: + return SCTP_DISPOSITION_NOMEM; + } + ++enum sctp_disposition ++sctp_sf_do_9_2_reshutack(struct net *net, const struct sctp_endpoint *ep, ++ const struct sctp_association *asoc, ++ const union sctp_subtype type, void *arg, ++ struct sctp_cmd_seq *commands) ++{ ++ struct sctp_chunk *chunk = arg; ++ ++ if (!chunk->singleton) ++ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); ++ ++ if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_init_chunk))) ++ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); ++ ++ if (chunk->sctp_hdr->vtag != 0) ++ return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); ++ ++ return __sctp_sf_do_9_2_reshutack(net, ep, asoc, type, arg, commands); ++} ++ + /* + * sctp_sf_do_ecn_cwr + * diff --git a/queue-5.4/series b/queue-5.4/series index 8f5aea7fa8b..a234b8229c8 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -1 +1,2 @@ revert-xfrm-state-and-policy-should-fail-if-xfrma_if_id-0.patch +sctp-fix-the-processing-for-init-chunk.patch