lkml.org 
[lkml]   [2021]   [Nov]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.14 100/125] sctp: fix the processing for INIT chunk
    Date
    From: Xin Long <lucien.xin@gmail.com>

    [ Upstream commit eae5783908042a762c24e1bd11876edb91d314b1 ]

    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 <lucien.xin@gmail.com>
    Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
    Signed-off-by: Jakub Kicinski <kuba@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/sctp/sm_statefuns.c | 72 ++++++++++++++++++++++++++---------------
    1 file changed, 46 insertions(+), 26 deletions(-)

    diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
    index 7f8306968c39..9bfa8cca9974 100644
    --- a/net/sctp/sm_statefuns.c
    +++ b/net/sctp/sm_statefuns.c
    @@ -156,6 +156,12 @@ static enum sctp_disposition __sctp_sf_do_9_1_abort(
    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.
    @@ -337,6 +343,14 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net,
    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.
    */
    @@ -351,14 +365,6 @@ enum sctp_disposition sctp_sf_do_5_1B_init(struct net *net,
    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 issues close().
    @@ -1524,20 +1530,16 @@ static enum sctp_disposition sctp_sf_do_unexpected_init(
    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);
    -
    if (SCTP_INPUT_CB(chunk->skb)->encap_port != chunk->transport->encap_port)
    return sctp_sf_new_encap_port(net, ep, asoc, type, arg, commands);

    @@ -1882,9 +1884,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
    * 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;

    @@ -2970,13 +2972,11 @@ enum sctp_disposition sctp_sf_do_9_2_shut_ctsn(
    * 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;
    @@ -3010,6 +3010,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
    *
    --
    2.33.0


    \
     
     \ /
      Last update: 2021-11-01 10:51    [W:4.240 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site