]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Sat, 30 Oct 2021 20:33:18 +0000 (16:33 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 30 Oct 2021 20:33:18 +0000 (16:33 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/lan743x-fix-endianness-when-accessing-descriptors.patch [new file with mode: 0644]
queue-5.10/sctp-add-vtag-check-in-sctp_sf_do_8_5_1_e_sa.patch [new file with mode: 0644]
queue-5.10/sctp-add-vtag-check-in-sctp_sf_ootb.patch [new file with mode: 0644]
queue-5.10/sctp-add-vtag-check-in-sctp_sf_violation.patch [new file with mode: 0644]
queue-5.10/sctp-fix-the-processing-for-cookie_echo-chunk.patch [new file with mode: 0644]
queue-5.10/sctp-fix-the-processing-for-init_ack-chunk.patch [new file with mode: 0644]
queue-5.10/sctp-use-init_tag-from-inithdr-for-abort-chunk.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/lan743x-fix-endianness-when-accessing-descriptors.patch b/queue-5.10/lan743x-fix-endianness-when-accessing-descriptors.patch
new file mode 100644 (file)
index 0000000..3177868
--- /dev/null
@@ -0,0 +1,272 @@
+From 37b729bfdcae86ae5b93ebc044ca9215744fc43b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Jan 2021 09:48:59 +0500
+Subject: lan743x: fix endianness when accessing descriptors
+
+From: Alexey Denisov <rtgbnm@gmail.com>
+
+[ Upstream commit 462512824f902a24de794290dd622e664587da1d ]
+
+TX/RX descriptor ring fields are always little-endian, but conversion
+wasn't performed for big-endian CPUs, so the driver failed to work.
+
+This patch makes the driver work on big-endian CPUs. It was tested and
+confirmed to work on NXP P1010 processor (PowerPC).
+
+Signed-off-by: Alexey Denisov <rtgbnm@gmail.com>
+Link: https://lore.kernel.org/r/20210128044859.280219-1-rtgbnm@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan743x_main.c | 66 +++++++++----------
+ drivers/net/ethernet/microchip/lan743x_main.h | 20 +++---
+ 2 files changed, 43 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 3355e0a5b272..e14dfaafe439 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -1280,7 +1280,7 @@ static void lan743x_tx_release_desc(struct lan743x_tx *tx,
+       if (!(buffer_info->flags & TX_BUFFER_INFO_FLAG_ACTIVE))
+               goto done;
+-      descriptor_type = (descriptor->data0) &
++      descriptor_type = le32_to_cpu(descriptor->data0) &
+                         TX_DESC_DATA0_DTYPE_MASK_;
+       if (descriptor_type == TX_DESC_DATA0_DTYPE_DATA_)
+               goto clean_up_data_descriptor;
+@@ -1340,7 +1340,7 @@ static int lan743x_tx_next_index(struct lan743x_tx *tx, int index)
+ static void lan743x_tx_release_completed_descriptors(struct lan743x_tx *tx)
+ {
+-      while ((*tx->head_cpu_ptr) != (tx->last_head)) {
++      while (le32_to_cpu(*tx->head_cpu_ptr) != (tx->last_head)) {
+               lan743x_tx_release_desc(tx, tx->last_head, false);
+               tx->last_head = lan743x_tx_next_index(tx, tx->last_head);
+       }
+@@ -1426,10 +1426,10 @@ static int lan743x_tx_frame_start(struct lan743x_tx *tx,
+       if (dma_mapping_error(dev, dma_ptr))
+               return -ENOMEM;
+-      tx_descriptor->data1 = DMA_ADDR_LOW32(dma_ptr);
+-      tx_descriptor->data2 = DMA_ADDR_HIGH32(dma_ptr);
+-      tx_descriptor->data3 = (frame_length << 16) &
+-              TX_DESC_DATA3_FRAME_LENGTH_MSS_MASK_;
++      tx_descriptor->data1 = cpu_to_le32(DMA_ADDR_LOW32(dma_ptr));
++      tx_descriptor->data2 = cpu_to_le32(DMA_ADDR_HIGH32(dma_ptr));
++      tx_descriptor->data3 = cpu_to_le32((frame_length << 16) &
++              TX_DESC_DATA3_FRAME_LENGTH_MSS_MASK_);
+       buffer_info->skb = NULL;
+       buffer_info->dma_ptr = dma_ptr;
+@@ -1470,7 +1470,7 @@ static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx,
+               tx->frame_data0 |= TX_DESC_DATA0_IOC_;
+       }
+       tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
+-      tx_descriptor->data0 = tx->frame_data0;
++      tx_descriptor->data0 = cpu_to_le32(tx->frame_data0);
+       /* move to next descriptor */
+       tx->frame_tail = lan743x_tx_next_index(tx, tx->frame_tail);
+@@ -1514,7 +1514,7 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx,
+       /* wrap up previous descriptor */
+       tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail];
+-      tx_descriptor->data0 = tx->frame_data0;
++      tx_descriptor->data0 = cpu_to_le32(tx->frame_data0);
+       /* move to next descriptor */
+       tx->frame_tail = lan743x_tx_next_index(tx, tx->frame_tail);
+@@ -1540,10 +1540,10 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx,
+               return -ENOMEM;
+       }
+-      tx_descriptor->data1 = DMA_ADDR_LOW32(dma_ptr);
+-      tx_descriptor->data2 = DMA_ADDR_HIGH32(dma_ptr);
+-      tx_descriptor->data3 = (frame_length << 16) &
+-                             TX_DESC_DATA3_FRAME_LENGTH_MSS_MASK_;
++      tx_descriptor->data1 = cpu_to_le32(DMA_ADDR_LOW32(dma_ptr));
++      tx_descriptor->data2 = cpu_to_le32(DMA_ADDR_HIGH32(dma_ptr));
++      tx_descriptor->data3 = cpu_to_le32((frame_length << 16) &
++                             TX_DESC_DATA3_FRAME_LENGTH_MSS_MASK_);
+       buffer_info->skb = NULL;
+       buffer_info->dma_ptr = dma_ptr;
+@@ -1587,7 +1587,7 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx,
+       if (ignore_sync)
+               buffer_info->flags |= TX_BUFFER_INFO_FLAG_IGNORE_SYNC;
+-      tx_descriptor->data0 = tx->frame_data0;
++      tx_descriptor->data0 = cpu_to_le32(tx->frame_data0);
+       tx->frame_tail = lan743x_tx_next_index(tx, tx->frame_tail);
+       tx->last_tail = tx->frame_tail;
+@@ -2004,11 +2004,11 @@ static int lan743x_rx_init_ring_element(struct lan743x_rx *rx, int index,
+       }
+       buffer_info->buffer_length = length;
+-      descriptor->data1 = DMA_ADDR_LOW32(buffer_info->dma_ptr);
+-      descriptor->data2 = DMA_ADDR_HIGH32(buffer_info->dma_ptr);
++      descriptor->data1 = cpu_to_le32(DMA_ADDR_LOW32(buffer_info->dma_ptr));
++      descriptor->data2 = cpu_to_le32(DMA_ADDR_HIGH32(buffer_info->dma_ptr));
+       descriptor->data3 = 0;
+-      descriptor->data0 = (RX_DESC_DATA0_OWN_ |
+-                          (length & RX_DESC_DATA0_BUF_LENGTH_MASK_));
++      descriptor->data0 = cpu_to_le32((RX_DESC_DATA0_OWN_ |
++                          (length & RX_DESC_DATA0_BUF_LENGTH_MASK_)));
+       skb_reserve(buffer_info->skb, RX_HEAD_PADDING);
+       lan743x_rx_update_tail(rx, index);
+@@ -2023,12 +2023,12 @@ static void lan743x_rx_reuse_ring_element(struct lan743x_rx *rx, int index)
+       descriptor = &rx->ring_cpu_ptr[index];
+       buffer_info = &rx->buffer_info[index];
+-      descriptor->data1 = DMA_ADDR_LOW32(buffer_info->dma_ptr);
+-      descriptor->data2 = DMA_ADDR_HIGH32(buffer_info->dma_ptr);
++      descriptor->data1 = cpu_to_le32(DMA_ADDR_LOW32(buffer_info->dma_ptr));
++      descriptor->data2 = cpu_to_le32(DMA_ADDR_HIGH32(buffer_info->dma_ptr));
+       descriptor->data3 = 0;
+-      descriptor->data0 = (RX_DESC_DATA0_OWN_ |
++      descriptor->data0 = cpu_to_le32((RX_DESC_DATA0_OWN_ |
+                           ((buffer_info->buffer_length) &
+-                          RX_DESC_DATA0_BUF_LENGTH_MASK_));
++                          RX_DESC_DATA0_BUF_LENGTH_MASK_)));
+       lan743x_rx_update_tail(rx, index);
+ }
+@@ -2062,7 +2062,7 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
+ {
+       struct skb_shared_hwtstamps *hwtstamps = NULL;
+       int result = RX_PROCESS_RESULT_NOTHING_TO_DO;
+-      int current_head_index = *rx->head_cpu_ptr;
++      int current_head_index = le32_to_cpu(*rx->head_cpu_ptr);
+       struct lan743x_rx_buffer_info *buffer_info;
+       struct lan743x_rx_descriptor *descriptor;
+       int extension_index = -1;
+@@ -2077,14 +2077,14 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
+       if (rx->last_head != current_head_index) {
+               descriptor = &rx->ring_cpu_ptr[rx->last_head];
+-              if (descriptor->data0 & RX_DESC_DATA0_OWN_)
++              if (le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_OWN_)
+                       goto done;
+-              if (!(descriptor->data0 & RX_DESC_DATA0_FS_))
++              if (!(le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_FS_))
+                       goto done;
+               first_index = rx->last_head;
+-              if (descriptor->data0 & RX_DESC_DATA0_LS_) {
++              if (le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_LS_) {
+                       last_index = rx->last_head;
+               } else {
+                       int index;
+@@ -2092,10 +2092,10 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
+                       index = lan743x_rx_next_index(rx, first_index);
+                       while (index != current_head_index) {
+                               descriptor = &rx->ring_cpu_ptr[index];
+-                              if (descriptor->data0 & RX_DESC_DATA0_OWN_)
++                              if (le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_OWN_)
+                                       goto done;
+-                              if (descriptor->data0 & RX_DESC_DATA0_LS_) {
++                              if (le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_LS_) {
+                                       last_index = index;
+                                       break;
+                               }
+@@ -2104,17 +2104,17 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
+               }
+               if (last_index >= 0) {
+                       descriptor = &rx->ring_cpu_ptr[last_index];
+-                      if (descriptor->data0 & RX_DESC_DATA0_EXT_) {
++                      if (le32_to_cpu(descriptor->data0) & RX_DESC_DATA0_EXT_) {
+                               /* extension is expected to follow */
+                               int index = lan743x_rx_next_index(rx,
+                                                                 last_index);
+                               if (index != current_head_index) {
+                                       descriptor = &rx->ring_cpu_ptr[index];
+-                                      if (descriptor->data0 &
++                                      if (le32_to_cpu(descriptor->data0) &
+                                           RX_DESC_DATA0_OWN_) {
+                                               goto done;
+                                       }
+-                                      if (descriptor->data0 &
++                                      if (le32_to_cpu(descriptor->data0) &
+                                           RX_DESC_DATA0_EXT_) {
+                                               extension_index = index;
+                                       } else {
+@@ -2166,7 +2166,7 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
+                       }
+                       buffer_info->skb = NULL;
+                       packet_length = RX_DESC_DATA0_FRAME_LENGTH_GET_
+-                                      (descriptor->data0);
++                                      (le32_to_cpu(descriptor->data0));
+                       skb_put(skb, packet_length - 4);
+                       skb->protocol = eth_type_trans(skb,
+                                                      rx->adapter->netdev);
+@@ -2204,8 +2204,8 @@ process_extension:
+                       descriptor = &rx->ring_cpu_ptr[extension_index];
+                       buffer_info = &rx->buffer_info[extension_index];
+-                      ts_sec = descriptor->data1;
+-                      ts_nsec = (descriptor->data2 &
++                      ts_sec = le32_to_cpu(descriptor->data1);
++                      ts_nsec = (le32_to_cpu(descriptor->data2) &
+                                 RX_DESC_DATA2_TS_NS_MASK_);
+                       lan743x_rx_reuse_ring_element(rx, extension_index);
+                       real_last_index = extension_index;
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index a536f4a4994d..751f2bc9ce84 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -660,7 +660,7 @@ struct lan743x_tx {
+       struct lan743x_tx_buffer_info *buffer_info;
+-      u32             *head_cpu_ptr;
++      __le32          *head_cpu_ptr;
+       dma_addr_t      head_dma_ptr;
+       int             last_head;
+       int             last_tail;
+@@ -690,7 +690,7 @@ struct lan743x_rx {
+       struct lan743x_rx_buffer_info *buffer_info;
+-      u32             *head_cpu_ptr;
++      __le32          *head_cpu_ptr;
+       dma_addr_t      head_dma_ptr;
+       u32             last_head;
+       u32             last_tail;
+@@ -775,10 +775,10 @@ struct lan743x_adapter {
+ #define TX_DESC_DATA3_FRAME_LENGTH_MSS_MASK_  (0x3FFF0000)
+ struct lan743x_tx_descriptor {
+-      u32     data0;
+-      u32     data1;
+-      u32     data2;
+-      u32     data3;
++      __le32     data0;
++      __le32     data1;
++      __le32     data2;
++      __le32     data3;
+ } __aligned(DEFAULT_DMA_DESCRIPTOR_SPACING);
+ #define TX_BUFFER_INFO_FLAG_ACTIVE            BIT(0)
+@@ -813,10 +813,10 @@ struct lan743x_tx_buffer_info {
+ #define RX_HEAD_PADDING               NET_IP_ALIGN
+ struct lan743x_rx_descriptor {
+-      u32     data0;
+-      u32     data1;
+-      u32     data2;
+-      u32     data3;
++      __le32     data0;
++      __le32     data1;
++      __le32     data2;
++      __le32     data3;
+ } __aligned(DEFAULT_DMA_DESCRIPTOR_SPACING);
+ #define RX_BUFFER_INFO_FLAG_ACTIVE      BIT(0)
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-add-vtag-check-in-sctp_sf_do_8_5_1_e_sa.patch b/queue-5.10/sctp-add-vtag-check-in-sctp_sf_do_8_5_1_e_sa.patch
new file mode 100644 (file)
index 0000000..797dbe8
--- /dev/null
@@ -0,0 +1,65 @@
+From 2c242ee05566874e7f29e64442c5e48de9bf72d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:46 -0400
+Subject: sctp: add vtag check in sctp_sf_do_8_5_1_E_sa
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit ef16b1734f0a176277b7bb9c71a6d977a6ef3998 ]
+
+sctp_sf_do_8_5_1_E_sa() is called when processing SHUTDOWN_ACK chunk
+in cookie_wait and cookie_echoed state.
+
+The vtag in the chunk's sctphdr should be verified, otherwise, as
+later in chunk length check, it may send abort with the existent
+asoc's vtag, which can be exploited by one to cook a malicious
+chunk to terminate a SCTP asoc.
+
+Note that when fails to verify the vtag from SHUTDOWN-ACK chunk,
+SHUTDOWN COMPLETE message will still be sent back to peer, but
+with the vtag from SHUTDOWN-ACK chunk, as said in 5) of
+rfc4960#section-8.4.
+
+While at it, also remove the unnecessary chunk length check from
+sctp_sf_shut_8_4_5(), as it's already done in both places where
+it calls sctp_sf_shut_8_4_5().
+
+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 | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 324c0222d9e6..82a76fda226b 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -3683,12 +3683,6 @@ static enum sctp_disposition sctp_sf_shut_8_4_5(
+       SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS);
+-      /* If the chunk length is invalid, we don't want to process
+-       * the reset of the packet.
+-       */
+-      if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr)))
+-              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+-
+       /* We need to discard the rest of the packet to prevent
+        * potential bomming attacks from additional bundled chunks.
+        * This is documented in SCTP Threats ID.
+@@ -3716,6 +3710,9 @@ enum sctp_disposition sctp_sf_do_8_5_1_E_sa(struct net *net,
+ {
+       struct sctp_chunk *chunk = arg;
++      if (!sctp_vtag_verify(chunk, asoc))
++              asoc = NULL;
++
+       /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
+       if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr)))
+               return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-add-vtag-check-in-sctp_sf_ootb.patch b/queue-5.10/sctp-add-vtag-check-in-sctp_sf_ootb.patch
new file mode 100644 (file)
index 0000000..bf946a8
--- /dev/null
@@ -0,0 +1,47 @@
+From 94f1f57da0e8608e56d71c42d65b20cc013f80de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:47 -0400
+Subject: sctp: add vtag check in sctp_sf_ootb
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 9d02831e517aa36ee6bdb453a0eb47bd49923fe3 ]
+
+sctp_sf_ootb() is called when processing DATA chunk in closed state,
+and many other places are also using it.
+
+The vtag in the chunk's sctphdr should be verified, otherwise, as
+later in chunk length check, it may send abort with the existent
+asoc's vtag, which can be exploited by one to cook a malicious
+chunk to terminate a SCTP asoc.
+
+When fails to verify the vtag from the chunk, this patch sets asoc
+to NULL, so that the abort will be made with the vtag from the
+received chunk later.
+
+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 | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 82a76fda226b..096e6be1d8fc 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -3568,6 +3568,9 @@ enum sctp_disposition sctp_sf_ootb(struct net *net,
+       SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
++      if (asoc && !sctp_vtag_verify(chunk, asoc))
++              asoc = NULL;
++
+       ch = (struct sctp_chunkhdr *)chunk->chunk_hdr;
+       do {
+               /* Report violation if the chunk is less then minimal */
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-add-vtag-check-in-sctp_sf_violation.patch b/queue-5.10/sctp-add-vtag-check-in-sctp_sf_violation.patch
new file mode 100644 (file)
index 0000000..8206f03
--- /dev/null
@@ -0,0 +1,43 @@
+From 310232774f6bc3bc53669b6678c91c646154f1c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:45 -0400
+Subject: sctp: add vtag check in sctp_sf_violation
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit aa0f697e45286a6b5f0ceca9418acf54b9099d99 ]
+
+sctp_sf_violation() is called when processing HEARTBEAT_ACK chunk
+in cookie_wait state, and some other places are also using it.
+
+The vtag in the chunk's sctphdr should be verified, otherwise, as
+later in chunk length check, it may send abort with the existent
+asoc's vtag, which can be exploited by one to cook a malicious
+chunk to terminate a SCTP asoc.
+
+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 | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 0cfbf6046bf8..324c0222d9e6 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -4549,6 +4549,9 @@ enum sctp_disposition sctp_sf_violation(struct net *net,
+ {
+       struct sctp_chunk *chunk = arg;
++      if (!sctp_vtag_verify(chunk, asoc))
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
++
+       /* Make sure that the chunk has a valid length. */
+       if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_chunkhdr)))
+               return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-fix-the-processing-for-cookie_echo-chunk.patch b/queue-5.10/sctp-fix-the-processing-for-cookie_echo-chunk.patch
new file mode 100644 (file)
index 0000000..8602592
--- /dev/null
@@ -0,0 +1,75 @@
+From cb7de9600b3a64f23f0e851ee878c16e5d5f594c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:44 -0400
+Subject: sctp: fix the processing for COOKIE_ECHO chunk
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ 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 | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 5063f9884367..0cfbf6046bf8 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -697,6 +697,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.
+        */
+@@ -711,7 +714,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
+@@ -2141,9 +2145,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.
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-fix-the-processing-for-init_ack-chunk.patch b/queue-5.10/sctp-fix-the-processing-for-init_ack-chunk.patch
new file mode 100644 (file)
index 0000000..61c4d98
--- /dev/null
@@ -0,0 +1,135 @@
+From 1d539cf9008b54ccd9ccd456d52b1cc3237fbe76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:43 -0400
+Subject: sctp: fix the processing for INIT_ACK chunk
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 438b95a7c98f77d51cbf4db021f41b602d750a3f ]
+
+Currently INIT_ACK chunk in non-cookie_echoed state is processed in
+sctp_sf_discard_chunk() to send an abort with the existent asoc's
+vtag if the chunk length is not valid. But the vtag in the chunk's
+sctphdr is not verified, which may be exploited by one to cook a
+malicious chunk to terminal a SCTP asoc.
+
+sctp_sf_discard_chunk() also is called in many other places to send
+an abort, and most of those have this problem. This patch is to fix
+it by sending abort with the existent asoc's vtag only if the vtag
+from the chunk's sctphdr is verified in sctp_sf_discard_chunk().
+
+Note on sctp_sf_do_9_1_abort() and sctp_sf_shutdown_pending_abort(),
+the chunk length has been verified before sctp_sf_discard_chunk(),
+so replace it with sctp_sf_discard(). On sctp_sf_do_asconf_ack() and
+sctp_sf_do_asconf(), move the sctp_chunk_length_valid check ahead of
+sctp_sf_discard_chunk(), then replace it with sctp_sf_discard().
+
+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 | 37 +++++++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 89a86728184d..5063f9884367 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2280,7 +2280,7 @@ enum sctp_disposition sctp_sf_shutdown_pending_abort(
+        */
+       if (SCTP_ADDR_DEL ==
+                   sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
+-              return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+@@ -2326,7 +2326,7 @@ enum sctp_disposition sctp_sf_shutdown_sent_abort(
+        */
+       if (SCTP_ADDR_DEL ==
+                   sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
+-              return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+@@ -2596,7 +2596,7 @@ enum sctp_disposition sctp_sf_do_9_1_abort(
+        */
+       if (SCTP_ADDR_DEL ==
+                   sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
+-              return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+@@ -3745,6 +3745,11 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net,
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       }
++      /* Make sure that the ASCONF ADDIP chunk has a valid length.  */
++      if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk)))
++              return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
++                                                commands);
++
+       /* ADD-IP: Section 4.1.1
+        * This chunk MUST be sent in an authenticated way by using
+        * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk
+@@ -3753,13 +3758,7 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net,
+        */
+       if (!asoc->peer.asconf_capable ||
+           (!net->sctp.addip_noauth && !chunk->auth))
+-              return sctp_sf_discard_chunk(net, ep, asoc, type, arg,
+-                                           commands);
+-
+-      /* Make sure that the ASCONF ADDIP chunk has a valid length.  */
+-      if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_addip_chunk)))
+-              return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+-                                                commands);
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       hdr = (struct sctp_addiphdr *)chunk->skb->data;
+       serial = ntohl(hdr->serial);
+@@ -3888,6 +3887,12 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net *net,
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       }
++      /* Make sure that the ADDIP chunk has a valid length.  */
++      if (!sctp_chunk_length_valid(asconf_ack,
++                                   sizeof(struct sctp_addip_chunk)))
++              return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
++                                                commands);
++
+       /* ADD-IP, Section 4.1.2:
+        * This chunk MUST be sent in an authenticated way by using
+        * the mechanism defined in [I-D.ietf-tsvwg-sctp-auth]. If this chunk
+@@ -3896,14 +3901,7 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net *net,
+        */
+       if (!asoc->peer.asconf_capable ||
+           (!net->sctp.addip_noauth && !asconf_ack->auth))
+-              return sctp_sf_discard_chunk(net, ep, asoc, type, arg,
+-                                           commands);
+-
+-      /* Make sure that the ADDIP chunk has a valid length.  */
+-      if (!sctp_chunk_length_valid(asconf_ack,
+-                                   sizeof(struct sctp_addip_chunk)))
+-              return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+-                                                commands);
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+       addip_hdr = (struct sctp_addiphdr *)asconf_ack->skb->data;
+       rcvd_serial = ntohl(addip_hdr->serial);
+@@ -4475,6 +4473,9 @@ enum sctp_disposition sctp_sf_discard_chunk(struct net *net,
+ {
+       struct sctp_chunk *chunk = arg;
++      if (asoc && !sctp_vtag_verify(chunk, asoc))
++              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
++
+       /* Make sure that the chunk has a valid length.
+        * Since we don't know the chunk type, we use a general
+        * chunkhdr structure to make a comparison.
+-- 
+2.33.0
+
diff --git a/queue-5.10/sctp-use-init_tag-from-inithdr-for-abort-chunk.patch b/queue-5.10/sctp-use-init_tag-from-inithdr-for-abort-chunk.patch
new file mode 100644 (file)
index 0000000..5384694
--- /dev/null
@@ -0,0 +1,42 @@
+From 115fd3cae40afa55c75c6ebf5041151f567ff70d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Oct 2021 07:42:41 -0400
+Subject: sctp: use init_tag from inithdr for ABORT chunk
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 4f7019c7eb33967eb87766e0e4602b5576873680 ]
+
+Currently Linux SCTP uses the verification tag of the existing SCTP
+asoc when failing to process and sending the packet with the ABORT
+chunk. This will result in the peer accepting the ABORT chunk and
+removing the SCTP asoc. One could exploit this to terminate a SCTP
+asoc.
+
+This patch is to fix it by always using the initiate tag of the
+received INIT chunk for the ABORT chunk to be sent.
+
+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 | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index b65bdaa84228..89a86728184d 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -6248,6 +6248,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(
+                * yet.
+                */
+               switch (chunk->chunk_hdr->type) {
++              case SCTP_CID_INIT:
+               case SCTP_CID_INIT_ACK:
+               {
+                       struct sctp_initack_chunk *initack;
+-- 
+2.33.0
+
index 8a39ad56603d87f83bbda502cfb9137412d5ff58..29a25c67c0977eb1c3f52084b86d258835f4b21a 100644 (file)
@@ -63,3 +63,10 @@ phy-phy_ethtool_ksettings_get-lock-the-phy-for-consistency.patch
 phy-phy_ethtool_ksettings_set-move-after-phy_start_aneg.patch
 phy-phy_start_aneg-add-an-unlocked-version.patch
 phy-phy_ethtool_ksettings_set-lock-the-phy-while-changing-settings.patch
+sctp-use-init_tag-from-inithdr-for-abort-chunk.patch
+sctp-fix-the-processing-for-init_ack-chunk.patch
+sctp-fix-the-processing-for-cookie_echo-chunk.patch
+sctp-add-vtag-check-in-sctp_sf_violation.patch
+sctp-add-vtag-check-in-sctp_sf_do_8_5_1_e_sa.patch
+sctp-add-vtag-check-in-sctp_sf_ootb.patch
+lan743x-fix-endianness-when-accessing-descriptors.patch