--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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