commit:     b721073a475fe58039da5c0daf37b3ec3cdbd942
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun May  5 13:38:57 2019 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun May  5 13:38:57 2019 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b721073a

Linux patch 5.0.13

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 1012_linux-5.0.13.patch | 1280 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1280 insertions(+)

diff --git a/1012_linux-5.0.13.patch b/1012_linux-5.0.13.patch
new file mode 100644
index 0000000..b3581f4
--- /dev/null
+++ b/1012_linux-5.0.13.patch
@@ -0,0 +1,1280 @@
+diff --git a/Makefile b/Makefile
+index fd044f594bbf..51a819544505 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 0
+-SUBLEVEL = 12
++SUBLEVEL = 13
+ EXTRAVERSION =
+ NAME = Shy Crocodile
+ 
+diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
+index dabfcf7c3941..7a0e64ccd6ff 100644
+--- a/arch/x86/include/uapi/asm/kvm.h
++++ b/arch/x86/include/uapi/asm/kvm.h
+@@ -381,6 +381,7 @@ struct kvm_sync_regs {
+ #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
+ #define KVM_X86_QUIRK_CD_NW_CLEARED   (1 << 1)
+ #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
++#define KVM_X86_QUIRK_OUT_7E_INC_RIP  (1 << 3)
+ 
+ #define KVM_STATE_NESTED_GUEST_MODE   0x00000001
+ #define KVM_STATE_NESTED_RUN_PENDING  0x00000002
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index f90b3a948291..a4bcac94392c 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -5407,7 +5407,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
+               return ret;
+ 
+       /* Empty 'VMXON' state is permitted */
+-      if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12))
++      if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12))
+               return 0;
+ 
+       if (kvm_state->vmx.vmcs_pa != -1ull) {
+@@ -5451,7 +5451,7 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
+           vmcs12->vmcs_link_pointer != -1ull) {
+               struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu);
+ 
+-              if (kvm_state->size < sizeof(kvm_state) + 2 * sizeof(*vmcs12))
++              if (kvm_state->size < sizeof(*kvm_state) + 2 * sizeof(*vmcs12))
+                       return -EINVAL;
+ 
+               if (copy_from_user(shadow_vmcs12,
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 8c9fb6453b2f..7e413ea19a9a 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -6536,6 +6536,12 @@ int kvm_emulate_instruction_from_buffer(struct kvm_vcpu 
*vcpu,
+ }
+ EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer);
+ 
++static int complete_fast_pio_out_port_0x7e(struct kvm_vcpu *vcpu)
++{
++      vcpu->arch.pio.count = 0;
++      return 1;
++}
++
+ static int complete_fast_pio_out(struct kvm_vcpu *vcpu)
+ {
+       vcpu->arch.pio.count = 0;
+@@ -6552,12 +6558,23 @@ static int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int 
size,
+       unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt,
+                                           size, port, &val, 1);
++      if (ret)
++              return ret;
+ 
+-      if (!ret) {
++      /*
++       * Workaround userspace that relies on old KVM behavior of %rip being
++       * incremented prior to exiting to userspace to handle "OUT 0x7e".
++       */
++      if (port == 0x7e &&
++          kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_OUT_7E_INC_RIP)) {
++              vcpu->arch.complete_userspace_io =
++                      complete_fast_pio_out_port_0x7e;
++              kvm_skip_emulated_instruction(vcpu);
++      } else {
+               vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu);
+               vcpu->arch.complete_userspace_io = complete_fast_pio_out;
+       }
+-      return ret;
++      return 0;
+ }
+ 
+ static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
+diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
+index e14663ab6dbc..8dd74700a2ef 100644
+--- a/drivers/net/dsa/bcm_sf2_cfp.c
++++ b/drivers/net/dsa/bcm_sf2_cfp.c
+@@ -854,6 +854,9 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int 
port,
+            fs->m_ext.data[1]))
+               return -EINVAL;
+ 
++      if (fs->location != RX_CLS_LOC_ANY && fs->location >= CFP_NUM_RULES)
++              return -EINVAL;
++
+       if (fs->location != RX_CLS_LOC_ANY &&
+           test_bit(fs->location, priv->cfp.used))
+               return -EBUSY;
+@@ -942,6 +945,9 @@ static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, 
int port, u32 loc)
+       struct cfp_rule *rule;
+       int ret;
+ 
++      if (loc >= CFP_NUM_RULES)
++              return -EINVAL;
++
+       /* Refuse deleting unused rules, and those that are not unique since
+        * that could leave IPv6 rules with one of the chained rule in the
+        * table.
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c 
b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 40ca339ec3df..c6ddbc0e084e 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -1621,7 +1621,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct 
bnxt_cp_ring_info *cpr,
+                       netdev_warn(bp->dev, "RX buffer error %x\n", rx_err);
+                       bnxt_sched_reset(bp, rxr);
+               }
+-              goto next_rx;
++              goto next_rx_no_len;
+       }
+ 
+       len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT;
+@@ -1702,12 +1702,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct 
bnxt_cp_ring_info *cpr,
+       rc = 1;
+ 
+ next_rx:
+-      rxr->rx_prod = NEXT_RX(prod);
+-      rxr->rx_next_cons = NEXT_RX(cons);
+-
+       cpr->rx_packets += 1;
+       cpr->rx_bytes += len;
+ 
++next_rx_no_len:
++      rxr->rx_prod = NEXT_RX(prod);
++      rxr->rx_next_cons = NEXT_RX(cons);
++
+ next_rx_no_prod_no_len:
+       *raw_cons = tmp_raw_cons;
+ 
+@@ -5131,10 +5132,10 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool 
close_path)
+       for (i = 0; i < bp->tx_nr_rings; i++) {
+               struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
+               struct bnxt_ring_struct *ring = &txr->tx_ring_struct;
+-              u32 cmpl_ring_id;
+ 
+-              cmpl_ring_id = bnxt_cp_ring_for_tx(bp, txr);
+               if (ring->fw_ring_id != INVALID_HW_RING_ID) {
++                      u32 cmpl_ring_id = bnxt_cp_ring_for_tx(bp, txr);
++
+                       hwrm_ring_free_send_msg(bp, ring,
+                                               RING_FREE_REQ_RING_TYPE_TX,
+                                               close_path ? cmpl_ring_id :
+@@ -5147,10 +5148,10 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool 
close_path)
+               struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
+               struct bnxt_ring_struct *ring = &rxr->rx_ring_struct;
+               u32 grp_idx = rxr->bnapi->index;
+-              u32 cmpl_ring_id;
+ 
+-              cmpl_ring_id = bnxt_cp_ring_for_rx(bp, rxr);
+               if (ring->fw_ring_id != INVALID_HW_RING_ID) {
++                      u32 cmpl_ring_id = bnxt_cp_ring_for_rx(bp, rxr);
++
+                       hwrm_ring_free_send_msg(bp, ring,
+                                               RING_FREE_REQ_RING_TYPE_RX,
+                                               close_path ? cmpl_ring_id :
+@@ -5169,10 +5170,10 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool 
close_path)
+               struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
+               struct bnxt_ring_struct *ring = &rxr->rx_agg_ring_struct;
+               u32 grp_idx = rxr->bnapi->index;
+-              u32 cmpl_ring_id;
+ 
+-              cmpl_ring_id = bnxt_cp_ring_for_rx(bp, rxr);
+               if (ring->fw_ring_id != INVALID_HW_RING_ID) {
++                      u32 cmpl_ring_id = bnxt_cp_ring_for_rx(bp, rxr);
++
+                       hwrm_ring_free_send_msg(bp, ring, type,
+                                               close_path ? cmpl_ring_id :
+                                               INVALID_HW_RING_ID);
+@@ -5311,17 +5312,16 @@ __bnxt_hwrm_reserve_pf_rings(struct bnxt *bp, struct 
hwrm_func_cfg_input *req,
+       req->num_tx_rings = cpu_to_le16(tx_rings);
+       if (BNXT_NEW_RM(bp)) {
+               enables |= rx_rings ? FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS : 0;
++              enables |= stats ? FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
+               if (bp->flags & BNXT_FLAG_CHIP_P5) {
+                       enables |= cp_rings ? FUNC_CFG_REQ_ENABLES_NUM_MSIX : 0;
+                       enables |= tx_rings + ring_grps ?
+-                                 FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS |
+-                                 FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
++                                 FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS : 0;
+                       enables |= rx_rings ?
+                               FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS : 0;
+               } else {
+                       enables |= cp_rings ?
+-                                 FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS |
+-                                 FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
++                                 FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS : 0;
+                       enables |= ring_grps ?
+                                  FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS |
+                                  FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS : 0;
+@@ -5361,14 +5361,13 @@ __bnxt_hwrm_reserve_vf_rings(struct bnxt *bp,
+       enables |= tx_rings ? FUNC_VF_CFG_REQ_ENABLES_NUM_TX_RINGS : 0;
+       enables |= rx_rings ? FUNC_VF_CFG_REQ_ENABLES_NUM_RX_RINGS |
+                             FUNC_VF_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS : 0;
++      enables |= stats ? FUNC_VF_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
+       if (bp->flags & BNXT_FLAG_CHIP_P5) {
+               enables |= tx_rings + ring_grps ?
+-                         FUNC_VF_CFG_REQ_ENABLES_NUM_CMPL_RINGS |
+-                         FUNC_VF_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
++                         FUNC_VF_CFG_REQ_ENABLES_NUM_CMPL_RINGS : 0;
+       } else {
+               enables |= cp_rings ?
+-                         FUNC_VF_CFG_REQ_ENABLES_NUM_CMPL_RINGS |
+-                         FUNC_VF_CFG_REQ_ENABLES_NUM_STAT_CTXS : 0;
++                         FUNC_VF_CFG_REQ_ENABLES_NUM_CMPL_RINGS : 0;
+               enables |= ring_grps ?
+                          FUNC_VF_CFG_REQ_ENABLES_NUM_HW_RING_GRPS : 0;
+       }
+@@ -6745,6 +6744,7 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp)
+       struct hwrm_queue_pri2cos_qcfg_input req2 = {0};
+       struct hwrm_port_qstats_ext_input req = {0};
+       struct bnxt_pf_info *pf = &bp->pf;
++      u32 tx_stat_size;
+       int rc;
+ 
+       if (!(bp->flags & BNXT_FLAG_PORT_STATS_EXT))
+@@ -6754,13 +6754,16 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp)
+       req.port_id = cpu_to_le16(pf->port_id);
+       req.rx_stat_size = cpu_to_le16(sizeof(struct rx_port_stats_ext));
+       req.rx_stat_host_addr = cpu_to_le64(bp->hw_rx_port_stats_ext_map);
+-      req.tx_stat_size = cpu_to_le16(sizeof(struct tx_port_stats_ext));
++      tx_stat_size = bp->hw_tx_port_stats_ext ?
++                     sizeof(*bp->hw_tx_port_stats_ext) : 0;
++      req.tx_stat_size = cpu_to_le16(tx_stat_size);
+       req.tx_stat_host_addr = cpu_to_le64(bp->hw_tx_port_stats_ext_map);
+       mutex_lock(&bp->hwrm_cmd_lock);
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (!rc) {
+               bp->fw_rx_stats_ext_size = le16_to_cpu(resp->rx_stat_size) / 8;
+-              bp->fw_tx_stats_ext_size = le16_to_cpu(resp->tx_stat_size) / 8;
++              bp->fw_tx_stats_ext_size = tx_stat_size ?
++                      le16_to_cpu(resp->tx_stat_size) / 8 : 0;
+       } else {
+               bp->fw_rx_stats_ext_size = 0;
+               bp->fw_tx_stats_ext_size = 0;
+@@ -8889,8 +8892,15 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
+ 
+ skip_uc:
+       rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
++      if (rc && vnic->mc_list_count) {
++              netdev_info(bp->dev, "Failed setting MC filters rc: %d, turning 
on ALL_MCAST mode\n",
++                          rc);
++              vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST;
++              vnic->mc_list_count = 0;
++              rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0);
++      }
+       if (rc)
+-              netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n",
++              netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %d\n",
+                          rc);
+ 
+       return rc;
+@@ -10625,6 +10635,7 @@ init_err_cleanup_tc:
+       bnxt_clear_int_mode(bp);
+ 
+ init_err_pci_clean:
++      bnxt_free_hwrm_short_cmd_req(bp);
+       bnxt_free_hwrm_resources(bp);
+       bnxt_free_ctx_mem(bp);
+       kfree(bp->ctx);
+diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
+index abb7876a8776..66573a218df5 100644
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -1494,9 +1494,10 @@ static int marvell_get_sset_count(struct phy_device 
*phydev)
+ 
+ static void marvell_get_strings(struct phy_device *phydev, u8 *data)
+ {
++      int count = marvell_get_sset_count(phydev);
+       int i;
+ 
+-      for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) {
++      for (i = 0; i < count; i++) {
+               strlcpy(data + i * ETH_GSTRING_LEN,
+                       marvell_hw_stats[i].string, ETH_GSTRING_LEN);
+       }
+@@ -1524,9 +1525,10 @@ static u64 marvell_get_stat(struct phy_device *phydev, 
int i)
+ static void marvell_get_stats(struct phy_device *phydev,
+                             struct ethtool_stats *stats, u64 *data)
+ {
++      int count = marvell_get_sset_count(phydev);
+       int i;
+ 
+-      for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++)
++      for (i = 0; i < count; i++)
+               data[i] = marvell_get_stat(phydev, i);
+ }
+ 
+diff --git a/drivers/net/wireless/ath/ath10k/mac.c 
b/drivers/net/wireless/ath/ath10k/mac.c
+index 49758490eaba..9560acc5f7da 100644
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -5705,7 +5705,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw 
*hw,
+       }
+ 
+       if (changed & BSS_CHANGED_MCAST_RATE &&
+-          !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) {
++          !ath10k_mac_vif_chan(arvif->vif, &def)) {
+               band = def.chan->band;
+               rateidx = vif->bss_conf.mcast_rate[band] - 1;
+ 
+@@ -5743,7 +5743,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw 
*hw,
+       }
+ 
+       if (changed & BSS_CHANGED_BASIC_RATES) {
+-              if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) {
++              if (ath10k_mac_vif_chan(vif, &def)) {
+                       mutex_unlock(&ar->conf_mutex);
+                       return;
+               }
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c 
b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+index 33b0af24a537..d61ab3e80759 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+@@ -1482,6 +1482,11 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, 
struct ieee80211_vif *vif)
+               return;
+ 
+       mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
++      if (IS_ERR_OR_NULL(mvmvif->dbgfs_dir)) {
++              IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
++                      dbgfs_dir);
++              return;
++      }
+ 
+       if (!mvmvif->dbgfs_dir) {
+               IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
+diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
+index 6640f84fe536..6d5beac29bc1 100644
+--- a/include/net/sctp/command.h
++++ b/include/net/sctp/command.h
+@@ -105,7 +105,6 @@ enum sctp_verb {
+       SCTP_CMD_T1_RETRAN,      /* Mark for retransmission after T1 timeout  */
+       SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */
+       SCTP_CMD_SEND_MSG,       /* Send the whole use message */
+-      SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
+       SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
+       SCTP_CMD_SET_ASOC,       /* Restore association context */
+       SCTP_CMD_LAST
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index c80188875f39..e8bb2e85c5a4 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -519,6 +519,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct 
sk_buff *from)
+       to->pkt_type = from->pkt_type;
+       to->priority = from->priority;
+       to->protocol = from->protocol;
++      to->skb_iif = from->skb_iif;
+       skb_dst_drop(to);
+       skb_dst_copy(to, from);
+       to->dev = from->dev;
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 00852f47a73d..9a2ff79a93ad 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -1673,7 +1673,9 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff 
*skb)
+       if (TCP_SKB_CB(tail)->end_seq != TCP_SKB_CB(skb)->seq ||
+           TCP_SKB_CB(tail)->ip_dsfield != TCP_SKB_CB(skb)->ip_dsfield ||
+           ((TCP_SKB_CB(tail)->tcp_flags |
+-            TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_URG) ||
++            TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_SYN | TCPHDR_RST | 
TCPHDR_URG)) ||
++          !((TCP_SKB_CB(tail)->tcp_flags &
++            TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_ACK) ||
+           ((TCP_SKB_CB(tail)->tcp_flags ^
+             TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_ECE | TCPHDR_CWR)) ||
+ #ifdef CONFIG_TLS_DEVICE
+@@ -1692,6 +1694,15 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff 
*skb)
+               if (after(TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(tail)->ack_seq))
+                       TCP_SKB_CB(tail)->ack_seq = TCP_SKB_CB(skb)->ack_seq;
+ 
++              /* We have to update both TCP_SKB_CB(tail)->tcp_flags and
++               * thtail->fin, so that the fast path in tcp_rcv_established()
++               * is not entered if we append a packet with a FIN.
++               * SYN, RST, URG are not present.
++               * ACK is set on both packets.
++               * PSH : we do not really care in TCP stack,
++               *       at least for 'GRO' packets.
++               */
++              thtail->fin |= th->fin;
+               TCP_SKB_CB(tail)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
+ 
+               if (TCP_SKB_CB(skb)->has_rxtstamp) {
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 64f9715173ac..065334b41d57 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -352,6 +352,7 @@ static struct sk_buff *udp_gro_receive_segment(struct 
list_head *head,
+       struct sk_buff *pp = NULL;
+       struct udphdr *uh2;
+       struct sk_buff *p;
++      unsigned int ulen;
+ 
+       /* requires non zero csum, for symmetry with GSO */
+       if (!uh->check) {
+@@ -359,6 +360,12 @@ static struct sk_buff *udp_gro_receive_segment(struct 
list_head *head,
+               return NULL;
+       }
+ 
++      /* Do not deal with padded or malicious packets, sorry ! */
++      ulen = ntohs(uh->len);
++      if (ulen <= sizeof(*uh) || ulen != skb_gro_len(skb)) {
++              NAPI_GRO_CB(skb)->flush = 1;
++              return NULL;
++      }
+       /* pull encapsulating udp header */
+       skb_gro_pull(skb, sizeof(struct udphdr));
+       skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr));
+@@ -377,13 +384,14 @@ static struct sk_buff *udp_gro_receive_segment(struct 
list_head *head,
+ 
+               /* Terminate the flow on len mismatch or if it grow "too much".
+                * Under small packet flood GRO count could elsewhere grow a lot
+-               * leading to execessive truesize values
++               * leading to excessive truesize values.
++               * On len mismatch merge the first packet shorter than gso_size,
++               * otherwise complete the GRO packet.
+                */
+-              if (!skb_gro_receive(p, skb) &&
++              if (ulen > ntohs(uh2->len) || skb_gro_receive(p, skb) ||
++                  ulen != ntohs(uh2->len) ||
+                   NAPI_GRO_CB(p)->count >= UDP_GRO_CNT_MAX)
+                       pp = p;
+-              else if (uh->len != uh2->len)
+-                      pp = p;
+ 
+               return pp;
+       }
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index 6613d8dbb0e5..91247a6fc67f 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -921,9 +921,7 @@ static void fib6_drop_pcpu_from(struct fib6_info *f6i,
+               if (pcpu_rt) {
+                       struct fib6_info *from;
+ 
+-                      from = rcu_dereference_protected(pcpu_rt->from,
+-                                           lockdep_is_held(&table->tb6_lock));
+-                      rcu_assign_pointer(pcpu_rt->from, NULL);
++                      from = xchg((__force struct fib6_info 
**)&pcpu_rt->from, NULL);
+                       fib6_info_release(from);
+               }
+       }
+diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
+index cb54a8a3c273..be5f3d7ceb96 100644
+--- a/net/ipv6/ip6_flowlabel.c
++++ b/net/ipv6/ip6_flowlabel.c
+@@ -94,15 +94,21 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, 
__be32 label)
+       return fl;
+ }
+ 
++static void fl_free_rcu(struct rcu_head *head)
++{
++      struct ip6_flowlabel *fl = container_of(head, struct ip6_flowlabel, 
rcu);
++
++      if (fl->share == IPV6_FL_S_PROCESS)
++              put_pid(fl->owner.pid);
++      kfree(fl->opt);
++      kfree(fl);
++}
++
+ 
+ static void fl_free(struct ip6_flowlabel *fl)
+ {
+-      if (fl) {
+-              if (fl->share == IPV6_FL_S_PROCESS)
+-                      put_pid(fl->owner.pid);
+-              kfree(fl->opt);
+-              kfree_rcu(fl, rcu);
+-      }
++      if (fl)
++              call_rcu(&fl->rcu, fl_free_rcu);
+ }
+ 
+ static void fl_release(struct ip6_flowlabel *fl)
+@@ -633,9 +639,9 @@ recheck:
+                               if (fl1->share == IPV6_FL_S_EXCL ||
+                                   fl1->share != fl->share ||
+                                   ((fl1->share == IPV6_FL_S_PROCESS) &&
+-                                   (fl1->owner.pid == fl->owner.pid)) ||
++                                   (fl1->owner.pid != fl->owner.pid)) ||
+                                   ((fl1->share == IPV6_FL_S_USER) &&
+-                                   uid_eq(fl1->owner.uid, fl->owner.uid)))
++                                   !uid_eq(fl1->owner.uid, fl->owner.uid)))
+                                       goto release;
+ 
+                               err = -ENOMEM;
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index b6a97115a906..59c90bba048c 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -379,11 +379,8 @@ static void ip6_dst_destroy(struct dst_entry *dst)
+               in6_dev_put(idev);
+       }
+ 
+-      rcu_read_lock();
+-      from = rcu_dereference(rt->from);
+-      rcu_assign_pointer(rt->from, NULL);
++      from = xchg((__force struct fib6_info **)&rt->from, NULL);
+       fib6_info_release(from);
+-      rcu_read_unlock();
+ }
+ 
+ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
+@@ -1288,9 +1285,7 @@ static void rt6_remove_exception(struct 
rt6_exception_bucket *bucket,
+       /* purge completely the exception to allow releasing the held resources:
+        * some [sk] cache may keep the dst around for unlimited time
+        */
+-      from = rcu_dereference_protected(rt6_ex->rt6i->from,
+-                                       lockdep_is_held(&rt6_exception_lock));
+-      rcu_assign_pointer(rt6_ex->rt6i->from, NULL);
++      from = xchg((__force struct fib6_info **)&rt6_ex->rt6i->from, NULL);
+       fib6_info_release(from);
+       dst_dev_put(&rt6_ex->rt6i->dst);
+ 
+@@ -3403,11 +3398,8 @@ static void rt6_do_redirect(struct dst_entry *dst, 
struct sock *sk, struct sk_bu
+ 
+       rcu_read_lock();
+       from = rcu_dereference(rt->from);
+-      /* This fib6_info_hold() is safe here because we hold reference to rt
+-       * and rt already holds reference to fib6_info.
+-       */
+-      fib6_info_hold(from);
+-      rcu_read_unlock();
++      if (!from)
++              goto out;
+ 
+       nrt = ip6_rt_cache_alloc(from, &msg->dest, NULL);
+       if (!nrt)
+@@ -3419,10 +3411,7 @@ static void rt6_do_redirect(struct dst_entry *dst, 
struct sock *sk, struct sk_bu
+ 
+       nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
+ 
+-      /* No need to remove rt from the exception table if rt is
+-       * a cached route because rt6_insert_exception() will
+-       * takes care of it
+-       */
++      /* rt6_insert_exception() will take care of duplicated exceptions */
+       if (rt6_insert_exception(nrt, from)) {
+               dst_release_immediate(&nrt->dst);
+               goto out;
+@@ -3435,7 +3424,7 @@ static void rt6_do_redirect(struct dst_entry *dst, 
struct sock *sk, struct sk_bu
+       call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
+ 
+ out:
+-      fib6_info_release(from);
++      rcu_read_unlock();
+       neigh_release(neigh);
+ }
+ 
+@@ -4957,16 +4946,20 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, 
struct nlmsghdr *nlh,
+ 
+       rcu_read_lock();
+       from = rcu_dereference(rt->from);
+-
+-      if (fibmatch)
+-              err = rt6_fill_node(net, skb, from, NULL, NULL, NULL, iif,
+-                                  RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
+-                                  nlh->nlmsg_seq, 0);
+-      else
+-              err = rt6_fill_node(net, skb, from, dst, &fl6.daddr,
+-                                  &fl6.saddr, iif, RTM_NEWROUTE,
+-                                  NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
+-                                  0);
++      if (from) {
++              if (fibmatch)
++                      err = rt6_fill_node(net, skb, from, NULL, NULL, NULL,
++                                          iif, RTM_NEWROUTE,
++                                          NETLINK_CB(in_skb).portid,
++                                          nlh->nlmsg_seq, 0);
++              else
++                      err = rt6_fill_node(net, skb, from, dst, &fl6.daddr,
++                                          &fl6.saddr, iif, RTM_NEWROUTE,
++                                          NETLINK_CB(in_skb).portid,
++                                          nlh->nlmsg_seq, 0);
++      } else {
++              err = -ENETUNREACH;
++      }
+       rcu_read_unlock();
+ 
+       if (err < 0) {
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index fed6becc5daf..52b5a2797c0c 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -169,8 +169,8 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, 
u32 tunnel_id)
+ 
+       rcu_read_lock_bh();
+       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
+-              if (tunnel->tunnel_id == tunnel_id) {
+-                      l2tp_tunnel_inc_refcount(tunnel);
++              if (tunnel->tunnel_id == tunnel_id &&
++                  refcount_inc_not_zero(&tunnel->ref_count)) {
+                       rcu_read_unlock_bh();
+ 
+                       return tunnel;
+@@ -190,8 +190,8 @@ struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net 
*net, int nth)
+ 
+       rcu_read_lock_bh();
+       list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
+-              if (++count > nth) {
+-                      l2tp_tunnel_inc_refcount(tunnel);
++              if (++count > nth &&
++                  refcount_inc_not_zero(&tunnel->ref_count)) {
+                       rcu_read_unlock_bh();
+                       return tunnel;
+               }
+@@ -909,7 +909,7 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff 
*skb)
+ {
+       struct l2tp_tunnel *tunnel;
+ 
+-      tunnel = l2tp_tunnel(sk);
++      tunnel = rcu_dereference_sk_user_data(sk);
+       if (tunnel == NULL)
+               goto pass_up;
+ 
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index 8406bf11eef4..faa2bc50cfa0 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -2603,8 +2603,8 @@ static int tpacket_snd(struct packet_sock *po, struct 
msghdr *msg)
+       void *ph;
+       DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name);
+       bool need_wait = !(msg->msg_flags & MSG_DONTWAIT);
++      unsigned char *addr = NULL;
+       int tp_len, size_max;
+-      unsigned char *addr;
+       void *data;
+       int len_sum = 0;
+       int status = TP_STATUS_AVAILABLE;
+@@ -2615,7 +2615,6 @@ static int tpacket_snd(struct packet_sock *po, struct 
msghdr *msg)
+       if (likely(saddr == NULL)) {
+               dev     = packet_cached_dev_get(po);
+               proto   = po->num;
+-              addr    = NULL;
+       } else {
+               err = -EINVAL;
+               if (msg->msg_namelen < sizeof(struct sockaddr_ll))
+@@ -2625,10 +2624,13 @@ static int tpacket_snd(struct packet_sock *po, struct 
msghdr *msg)
+                                               sll_addr)))
+                       goto out;
+               proto   = saddr->sll_protocol;
+-              addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
+               dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
+-              if (addr && dev && saddr->sll_halen < dev->addr_len)
+-                      goto out_put;
++              if (po->sk.sk_socket->type == SOCK_DGRAM) {
++                      if (dev && msg->msg_namelen < dev->addr_len +
++                                 offsetof(struct sockaddr_ll, sll_addr))
++                              goto out_put;
++                      addr = saddr->sll_addr;
++              }
+       }
+ 
+       err = -ENXIO;
+@@ -2800,7 +2802,7 @@ static int packet_snd(struct socket *sock, struct msghdr 
*msg, size_t len)
+       struct sk_buff *skb;
+       struct net_device *dev;
+       __be16 proto;
+-      unsigned char *addr;
++      unsigned char *addr = NULL;
+       int err, reserve = 0;
+       struct sockcm_cookie sockc;
+       struct virtio_net_hdr vnet_hdr = { 0 };
+@@ -2817,7 +2819,6 @@ static int packet_snd(struct socket *sock, struct msghdr 
*msg, size_t len)
+       if (likely(saddr == NULL)) {
+               dev     = packet_cached_dev_get(po);
+               proto   = po->num;
+-              addr    = NULL;
+       } else {
+               err = -EINVAL;
+               if (msg->msg_namelen < sizeof(struct sockaddr_ll))
+@@ -2825,10 +2826,13 @@ static int packet_snd(struct socket *sock, struct 
msghdr *msg, size_t len)
+               if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct 
sockaddr_ll, sll_addr)))
+                       goto out;
+               proto   = saddr->sll_protocol;
+-              addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
+               dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
+-              if (addr && dev && saddr->sll_halen < dev->addr_len)
+-                      goto out_unlock;
++              if (sock->type == SOCK_DGRAM) {
++                      if (dev && msg->msg_namelen < dev->addr_len +
++                                 offsetof(struct sockaddr_ll, sll_addr))
++                              goto out_unlock;
++                      addr = saddr->sll_addr;
++              }
+       }
+ 
+       err = -ENXIO;
+@@ -3345,20 +3349,29 @@ static int packet_recvmsg(struct socket *sock, struct 
msghdr *msg, size_t len,
+       sock_recv_ts_and_drops(msg, sk, skb);
+ 
+       if (msg->msg_name) {
++              int copy_len;
++
+               /* If the address length field is there to be filled
+                * in, we fill it in now.
+                */
+               if (sock->type == SOCK_PACKET) {
+                       __sockaddr_check_size(sizeof(struct sockaddr_pkt));
+                       msg->msg_namelen = sizeof(struct sockaddr_pkt);
++                      copy_len = msg->msg_namelen;
+               } else {
+                       struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
+ 
+                       msg->msg_namelen = sll->sll_halen +
+                               offsetof(struct sockaddr_ll, sll_addr);
++                      copy_len = msg->msg_namelen;
++                      if (msg->msg_namelen < sizeof(struct sockaddr_ll)) {
++                              memset(msg->msg_name +
++                                     offsetof(struct sockaddr_ll, sll_addr),
++                                     0, sizeof(sll->sll_addr));
++                              msg->msg_namelen = sizeof(struct sockaddr_ll);
++                      }
+               }
+-              memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
+-                     msg->msg_namelen);
++              memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len);
+       }
+ 
+       if (pkt_sk(sk)->auxdata) {
+diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
+index 8aa2937b069f..fe96881a334d 100644
+--- a/net/rxrpc/call_object.c
++++ b/net/rxrpc/call_object.c
+@@ -604,30 +604,30 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
+ 
+       _enter("");
+ 
+-      if (list_empty(&rxnet->calls))
+-              return;
++      if (!list_empty(&rxnet->calls)) {
++              write_lock(&rxnet->call_lock);
+ 
+-      write_lock(&rxnet->call_lock);
++              while (!list_empty(&rxnet->calls)) {
++                      call = list_entry(rxnet->calls.next,
++                                        struct rxrpc_call, link);
++                      _debug("Zapping call %p", call);
+ 
+-      while (!list_empty(&rxnet->calls)) {
+-              call = list_entry(rxnet->calls.next, struct rxrpc_call, link);
+-              _debug("Zapping call %p", call);
++                      rxrpc_see_call(call);
++                      list_del_init(&call->link);
+ 
+-              rxrpc_see_call(call);
+-              list_del_init(&call->link);
++                      pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
++                             call, atomic_read(&call->usage),
++                             rxrpc_call_states[call->state],
++                             call->flags, call->events);
+ 
+-              pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
+-                     call, atomic_read(&call->usage),
+-                     rxrpc_call_states[call->state],
+-                     call->flags, call->events);
++                      write_unlock(&rxnet->call_lock);
++                      cond_resched();
++                      write_lock(&rxnet->call_lock);
++              }
+ 
+               write_unlock(&rxnet->call_lock);
+-              cond_resched();
+-              write_lock(&rxnet->call_lock);
+       }
+ 
+-      write_unlock(&rxnet->call_lock);
+-
+       atomic_dec(&rxnet->nr_calls);
+       wait_var_event(&rxnet->nr_calls, !atomic_read(&rxnet->nr_calls));
+ }
+diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
+index 1d143bc3f73d..4aa03588f87b 100644
+--- a/net/sctp/sm_sideeffect.c
++++ b/net/sctp/sm_sideeffect.c
+@@ -1112,32 +1112,6 @@ static void sctp_cmd_send_msg(struct sctp_association 
*asoc,
+ }
+ 
+ 
+-/* Sent the next ASCONF packet currently stored in the association.
+- * This happens after the ASCONF_ACK was succeffully processed.
+- */
+-static void sctp_cmd_send_asconf(struct sctp_association *asoc)
+-{
+-      struct net *net = sock_net(asoc->base.sk);
+-
+-      /* Send the next asconf chunk from the addip chunk
+-       * queue.
+-       */
+-      if (!list_empty(&asoc->addip_chunk_list)) {
+-              struct list_head *entry = asoc->addip_chunk_list.next;
+-              struct sctp_chunk *asconf = list_entry(entry,
+-                                              struct sctp_chunk, list);
+-              list_del_init(entry);
+-
+-              /* Hold the chunk until an ASCONF_ACK is received. */
+-              sctp_chunk_hold(asconf);
+-              if (sctp_primitive_ASCONF(net, asoc, asconf))
+-                      sctp_chunk_free(asconf);
+-              else
+-                      asoc->addip_last_asconf = asconf;
+-      }
+-}
+-
+-
+ /* These three macros allow us to pull the debugging code out of the
+  * main flow of sctp_do_sm() to keep attention focused on the real
+  * functionality there.
+@@ -1783,9 +1757,6 @@ static int sctp_cmd_interpreter(enum sctp_event_type 
event_type,
+                       }
+                       sctp_cmd_send_msg(asoc, cmd->obj.msg, gfp);
+                       break;
+-              case SCTP_CMD_SEND_NEXT_ASCONF:
+-                      sctp_cmd_send_asconf(asoc);
+-                      break;
+               case SCTP_CMD_PURGE_ASCONF_QUEUE:
+                       sctp_asconf_queue_teardown(asoc);
+                       break;
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index c9ae3404b1bb..713a669d2058 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -3824,6 +3824,29 @@ enum sctp_disposition sctp_sf_do_asconf(struct net *net,
+       return SCTP_DISPOSITION_CONSUME;
+ }
+ 
++static enum sctp_disposition sctp_send_next_asconf(
++                                      struct net *net,
++                                      const struct sctp_endpoint *ep,
++                                      struct sctp_association *asoc,
++                                      const union sctp_subtype type,
++                                      struct sctp_cmd_seq *commands)
++{
++      struct sctp_chunk *asconf;
++      struct list_head *entry;
++
++      if (list_empty(&asoc->addip_chunk_list))
++              return SCTP_DISPOSITION_CONSUME;
++
++      entry = asoc->addip_chunk_list.next;
++      asconf = list_entry(entry, struct sctp_chunk, list);
++
++      list_del_init(entry);
++      sctp_chunk_hold(asconf);
++      asoc->addip_last_asconf = asconf;
++
++      return sctp_sf_do_prm_asconf(net, ep, asoc, type, asconf, commands);
++}
++
+ /*
+  * ADDIP Section 4.3 General rules for address manipulation
+  * When building TLV parameters for the ASCONF Chunk that will add or
+@@ -3915,14 +3938,10 @@ enum sctp_disposition sctp_sf_do_asconf_ack(struct net 
*net,
+                               SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
+ 
+               if (!sctp_process_asconf_ack((struct sctp_association *)asoc,
+-                                           asconf_ack)) {
+-                      /* Successfully processed ASCONF_ACK.  We can
+-                       * release the next asconf if we have one.
+-                       */
+-                      sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF,
+-                                      SCTP_NULL());
+-                      return SCTP_DISPOSITION_CONSUME;
+-              }
++                                           asconf_ack))
++                      return sctp_send_next_asconf(net, ep,
++                                      (struct sctp_association *)asoc,
++                                                      type, commands);
+ 
+               abort = sctp_make_abort(asoc, asconf_ack,
+                                       sizeof(struct sctp_errhdr));
+diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
+index 5f1d937c4be9..7d5136ecee78 100644
+--- a/net/tls/tls_device.c
++++ b/net/tls/tls_device.c
+@@ -579,7 +579,7 @@ void handle_device_resync(struct sock *sk, u32 seq, u64 
rcd_sn)
+ static int tls_device_reencrypt(struct sock *sk, struct sk_buff *skb)
+ {
+       struct strp_msg *rxm = strp_msg(skb);
+-      int err = 0, offset = rxm->offset, copy, nsg;
++      int err = 0, offset = rxm->offset, copy, nsg, data_len, pos;
+       struct sk_buff *skb_iter, *unused;
+       struct scatterlist sg[1];
+       char *orig_buf, *buf;
+@@ -610,25 +610,42 @@ static int tls_device_reencrypt(struct sock *sk, struct 
sk_buff *skb)
+       else
+               err = 0;
+ 
+-      copy = min_t(int, skb_pagelen(skb) - offset,
+-                   rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE);
++      data_len = rxm->full_len - TLS_CIPHER_AES_GCM_128_TAG_SIZE;
+ 
+-      if (skb->decrypted)
+-              skb_store_bits(skb, offset, buf, copy);
++      if (skb_pagelen(skb) > offset) {
++              copy = min_t(int, skb_pagelen(skb) - offset, data_len);
+ 
+-      offset += copy;
+-      buf += copy;
++              if (skb->decrypted)
++                      skb_store_bits(skb, offset, buf, copy);
+ 
++              offset += copy;
++              buf += copy;
++      }
++
++      pos = skb_pagelen(skb);
+       skb_walk_frags(skb, skb_iter) {
+-              copy = min_t(int, skb_iter->len,
+-                           rxm->full_len - offset + rxm->offset -
+-                           TLS_CIPHER_AES_GCM_128_TAG_SIZE);
++              int frag_pos;
++
++              /* Practically all frags must belong to msg if reencrypt
++               * is needed with current strparser and coalescing logic,
++               * but strparser may "get optimized", so let's be safe.
++               */
++              if (pos + skb_iter->len <= offset)
++                      goto done_with_frag;
++              if (pos >= data_len + rxm->offset)
++                      break;
++
++              frag_pos = offset - pos;
++              copy = min_t(int, skb_iter->len - frag_pos,
++                           data_len + rxm->offset - offset);
+ 
+               if (skb_iter->decrypted)
+-                      skb_store_bits(skb_iter, offset, buf, copy);
++                      skb_store_bits(skb_iter, frag_pos, buf, copy);
+ 
+               offset += copy;
+               buf += copy;
++done_with_frag:
++              pos += skb_iter->len;
+       }
+ 
+ free_buf:
+diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c
+index ef8934fd8698..426dd97725e4 100644
+--- a/net/tls/tls_device_fallback.c
++++ b/net/tls/tls_device_fallback.c
+@@ -200,13 +200,14 @@ static void complete_skb(struct sk_buff *nskb, struct 
sk_buff *skb, int headln)
+ 
+       skb_put(nskb, skb->len);
+       memcpy(nskb->data, skb->data, headln);
+-      update_chksum(nskb, headln);
+ 
+       nskb->destructor = skb->destructor;
+       nskb->sk = sk;
+       skb->destructor = NULL;
+       skb->sk = NULL;
+ 
++      update_chksum(nskb, headln);
++
+       delta = nskb->truesize - skb->truesize;
+       if (likely(delta < 0))
+               WARN_ON_ONCE(refcount_sub_and_test(-delta, &sk->sk_wmem_alloc));
+diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
+index c1376bfdc90b..aa28510d23ad 100644
+--- a/sound/usb/line6/driver.c
++++ b/sound/usb/line6/driver.c
+@@ -351,12 +351,16 @@ int line6_read_data(struct usb_line6 *line6, unsigned 
address, void *data,
+ {
+       struct usb_device *usbdev = line6->usbdev;
+       int ret;
+-      unsigned char len;
++      unsigned char *len;
+       unsigned count;
+ 
+       if (address > 0xffff || datalen > 0xff)
+               return -EINVAL;
+ 
++      len = kmalloc(sizeof(*len), GFP_KERNEL);
++      if (!len)
++              return -ENOMEM;
++
+       /* query the serial number: */
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
+                             USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+@@ -365,7 +369,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned 
address, void *data,
+ 
+       if (ret < 0) {
+               dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
+-              return ret;
++              goto exit;
+       }
+ 
+       /* Wait for data length. We'll get 0xff until length arrives. */
+@@ -375,28 +379,29 @@ int line6_read_data(struct usb_line6 *line6, unsigned 
address, void *data,
+               ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+                                     USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+                                     USB_DIR_IN,
+-                                    0x0012, 0x0000, &len, 1,
++                                    0x0012, 0x0000, len, 1,
+                                     LINE6_TIMEOUT * HZ);
+               if (ret < 0) {
+                       dev_err(line6->ifcdev,
+                               "receive length failed (error %d)\n", ret);
+-                      return ret;
++                      goto exit;
+               }
+ 
+-              if (len != 0xff)
++              if (*len != 0xff)
+                       break;
+       }
+ 
+-      if (len == 0xff) {
++      ret = -EIO;
++      if (*len == 0xff) {
+               dev_err(line6->ifcdev, "read failed after %d retries\n",
+                       count);
+-              return -EIO;
+-      } else if (len != datalen) {
++              goto exit;
++      } else if (*len != datalen) {
+               /* should be equal or something went wrong */
+               dev_err(line6->ifcdev,
+                       "length mismatch (expected %d, got %d)\n",
+-                      (int)datalen, (int)len);
+-              return -EIO;
++                      (int)datalen, (int)*len);
++              goto exit;
+       }
+ 
+       /* receive the result: */
+@@ -405,12 +410,12 @@ int line6_read_data(struct usb_line6 *line6, unsigned 
address, void *data,
+                             0x0013, 0x0000, data, datalen,
+                             LINE6_TIMEOUT * HZ);
+ 
+-      if (ret < 0) {
++      if (ret < 0)
+               dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
+-              return ret;
+-      }
+ 
+-      return 0;
++exit:
++      kfree(len);
++      return ret;
+ }
+ EXPORT_SYMBOL_GPL(line6_read_data);
+ 
+@@ -422,12 +427,16 @@ int line6_write_data(struct usb_line6 *line6, unsigned 
address, void *data,
+ {
+       struct usb_device *usbdev = line6->usbdev;
+       int ret;
+-      unsigned char status;
++      unsigned char *status;
+       int count;
+ 
+       if (address > 0xffff || datalen > 0xffff)
+               return -EINVAL;
+ 
++      status = kmalloc(sizeof(*status), GFP_KERNEL);
++      if (!status)
++              return -ENOMEM;
++
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
+                             USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+                             0x0022, address, data, datalen,
+@@ -436,7 +445,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned 
address, void *data,
+       if (ret < 0) {
+               dev_err(line6->ifcdev,
+                       "write request failed (error %d)\n", ret);
+-              return ret;
++              goto exit;
+       }
+ 
+       for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
+@@ -447,28 +456,29 @@ int line6_write_data(struct usb_line6 *line6, unsigned 
address, void *data,
+                                     USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+                                     USB_DIR_IN,
+                                     0x0012, 0x0000,
+-                                    &status, 1, LINE6_TIMEOUT * HZ);
++                                    status, 1, LINE6_TIMEOUT * HZ);
+ 
+               if (ret < 0) {
+                       dev_err(line6->ifcdev,
+                               "receiving status failed (error %d)\n", ret);
+-                      return ret;
++                      goto exit;
+               }
+ 
+-              if (status != 0xff)
++              if (*status != 0xff)
+                       break;
+       }
+ 
+-      if (status == 0xff) {
++      if (*status == 0xff) {
+               dev_err(line6->ifcdev, "write failed after %d retries\n",
+                       count);
+-              return -EIO;
+-      } else if (status != 0) {
++              ret = -EIO;
++      } else if (*status != 0) {
+               dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
+-              return -EIO;
++              ret = -EIO;
+       }
+-
+-      return 0;
++exit:
++      kfree(status);
++      return ret;
+ }
+ EXPORT_SYMBOL_GPL(line6_write_data);
+ 
+diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
+index 36ed9c85c0eb..5f3c87264e66 100644
+--- a/sound/usb/line6/podhd.c
++++ b/sound/usb/line6/podhd.c
+@@ -225,28 +225,32 @@ static void podhd_startup_start_workqueue(struct 
timer_list *t)
+ static int podhd_dev_start(struct usb_line6_podhd *pod)
+ {
+       int ret;
+-      u8 init_bytes[8];
++      u8 *init_bytes;
+       int i;
+       struct usb_device *usbdev = pod->line6.usbdev;
+ 
++      init_bytes = kmalloc(8, GFP_KERNEL);
++      if (!init_bytes)
++              return -ENOMEM;
++
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                                       0x67, USB_TYPE_VENDOR | 
USB_RECIP_DEVICE | USB_DIR_OUT,
+                                       0x11, 0,
+                                       NULL, 0, LINE6_TIMEOUT * HZ);
+       if (ret < 0) {
+               dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", 
ret);
+-              return ret;
++              goto exit;
+       }
+ 
+       /* NOTE: looks like some kind of ping message */
+       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+                                       USB_TYPE_VENDOR | USB_RECIP_DEVICE | 
USB_DIR_IN,
+                                       0x11, 0x0,
+-                                      &init_bytes, 3, LINE6_TIMEOUT * HZ);
++                                      init_bytes, 3, LINE6_TIMEOUT * HZ);
+       if (ret < 0) {
+               dev_err(pod->line6.ifcdev,
+                       "receive length failed (error %d)\n", ret);
+-              return ret;
++              goto exit;
+       }
+ 
+       pod->firmware_version =
+@@ -255,7 +259,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
+       for (i = 0; i <= 16; i++) {
+               ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, 
init_bytes, 8);
+               if (ret < 0)
+-                      return ret;
++                      goto exit;
+       }
+ 
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+@@ -263,10 +267,9 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
+                                       USB_TYPE_STANDARD | USB_RECIP_DEVICE | 
USB_DIR_OUT,
+                                       1, 0,
+                                       NULL, 0, LINE6_TIMEOUT * HZ);
+-      if (ret < 0)
+-              return ret;
+-
+-      return 0;
++exit:
++      kfree(init_bytes);
++      return ret;
+ }
+ 
+ static void podhd_startup_workqueue(struct work_struct *work)
+diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
+index f47ba94e6f4a..19bee725de00 100644
+--- a/sound/usb/line6/toneport.c
++++ b/sound/usb/line6/toneport.c
+@@ -365,16 +365,21 @@ static bool toneport_has_source_select(struct 
usb_line6_toneport *toneport)
+ /*
+       Setup Toneport device.
+ */
+-static void toneport_setup(struct usb_line6_toneport *toneport)
++static int toneport_setup(struct usb_line6_toneport *toneport)
+ {
+-      u32 ticks;
++      u32 *ticks;
+       struct usb_line6 *line6 = &toneport->line6;
+       struct usb_device *usbdev = line6->usbdev;
+ 
++      ticks = kmalloc(sizeof(*ticks), GFP_KERNEL);
++      if (!ticks)
++              return -ENOMEM;
++
+       /* sync time on device with host: */
+       /* note: 32-bit timestamps overflow in year 2106 */
+-      ticks = (u32)ktime_get_real_seconds();
+-      line6_write_data(line6, 0x80c6, &ticks, 4);
++      *ticks = (u32)ktime_get_real_seconds();
++      line6_write_data(line6, 0x80c6, ticks, 4);
++      kfree(ticks);
+ 
+       /* enable device: */
+       toneport_send_cmd(usbdev, 0x0301, 0x0000);
+@@ -389,6 +394,7 @@ static void toneport_setup(struct usb_line6_toneport 
*toneport)
+               toneport_update_led(toneport);
+ 
+       mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
++      return 0;
+ }
+ 
+ /*
+@@ -451,7 +457,9 @@ static int toneport_init(struct usb_line6 *line6,
+                       return err;
+       }
+ 
+-      toneport_setup(toneport);
++      err = toneport_setup(toneport);
++      if (err)
++              return err;
+ 
+       /* register audio system: */
+       return snd_card_register(line6->card);
+@@ -463,7 +471,11 @@ static int toneport_init(struct usb_line6 *line6,
+ */
+ static int toneport_reset_resume(struct usb_interface *interface)
+ {
+-      toneport_setup(usb_get_intfdata(interface));
++      int err;
++
++      err = toneport_setup(usb_get_intfdata(interface));
++      if (err)
++              return err;
+       return line6_resume(interface);
+ }
+ #endif
+diff --git a/tools/testing/selftests/net/fib_rule_tests.sh 
b/tools/testing/selftests/net/fib_rule_tests.sh
+index d4cfb6a7a086..4b7e107865bf 100755
+--- a/tools/testing/selftests/net/fib_rule_tests.sh
++++ b/tools/testing/selftests/net/fib_rule_tests.sh
+@@ -27,6 +27,7 @@ log_test()
+               nsuccess=$((nsuccess+1))
+               printf "\n    TEST: %-50s  [ OK ]\n" "${msg}"
+       else
++              ret=1
+               nfail=$((nfail+1))
+               printf "\n    TEST: %-50s  [FAIL]\n" "${msg}"
+               if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+@@ -147,8 +148,8 @@ fib_rule6_test()
+ 
+       fib_check_iproute_support "ipproto" "ipproto"
+       if [ $? -eq 0 ]; then
+-              match="ipproto icmp"
+-              fib_rule6_test_match_n_redirect "$match" "$match" "ipproto icmp 
match"
++              match="ipproto ipv6-icmp"
++              fib_rule6_test_match_n_redirect "$match" "$match" "ipproto 
ipv6-icmp match"
+       fi
+ }
+ 
+@@ -245,4 +246,9 @@ setup
+ run_fibrule_tests
+ cleanup
+ 
++if [ "$TESTS" != "none" ]; then
++      printf "\nTests passed: %3d\n" ${nsuccess}
++      printf "Tests failed: %3d\n"   ${nfail}
++fi
++
+ exit $ret

Reply via email to