sctp: fix the processing for COOKIE_ECHO chunk
authorXin Long <lucien.xin@gmail.com>
Wed, 20 Oct 2021 11:42:44 +0000 (07:42 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 2 Nov 2021 17:25:12 +0000 (18:25 +0100)
[ Upstream commit a64b341b8695e1c744dd972b39868371b4f68f83 ]

1. In closed state: in sctp_sf_do_5_1D_ce():

  When asoc is NULL, making packet for abort will use chunk's vtag
  in sctp_ootb_pkt_new(). But when asoc exists, vtag from the chunk
  should be verified before using peer.i.init_tag to make packet
  for abort in sctp_ootb_pkt_new(), and just discard it if vtag is
  not correct.

2. In the other states: in sctp_sf_do_5_2_4_dupcook():

  asoc always exists, but duplicate cookie_echo's vtag will be
  handled by sctp_tietags_compare() and then take actions, so before
  that we only verify the vtag for the abort sent for invalid chunk
  length.

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

index b1200c4122b024501d595c829f5f1cc0cea75974..4b519ec35ab76688dcb2fb26371e6a0e625fb7c6 100644 (file)
@@ -704,6 +704,9 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
        struct sock *sk;
        int error = 0;
 
+       if (asoc && !sctp_vtag_verify(chunk, asoc))
+               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.
         */
@@ -718,7 +721,8 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
         * in sctp_unpack_cookie().
         */
        if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr)))
-               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+               return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+                                                 commands);
 
        /* If the endpoint is not listening or if the number of associations
         * on the TCP-style socket exceed the max backlog, respond with an
@@ -2080,9 +2084,11 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
         * enough for the chunk header.  Cookie length verification is
         * done later.
         */
-       if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr)))
-               return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
-                                                 commands);
+       if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr))) {
+               if (!sctp_vtag_verify(chunk, asoc))
+                       asoc = NULL;
+               return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, commands);
+       }
 
        /* "Decode" the chunk.  We have no optional parameters so we
         * are in good shape.