diff --git a/blacklist.conf b/blacklist.conf index 8818b6d..33c47fa 100644 --- a/blacklist.conf +++ b/blacklist.conf @@ -1844,3 +1844,7 @@ e183d4e414b64711baf7a04e214b61969ca08dfa # incorrect, reverted by 5369ead83f5aff 74c1f1366eb7714b8b211554f6c5cee315ff3fbc # That fate was for SLE15 and not for SLE12 as for latter the respective 3b1902b87bf11f1c6a84368470dc13da6f3da3bd # feature requests were rejected. So blacklist those fixes here too. fa13680f5668cff05302a2f4753c49334a83a064 # +b166a20b07382b8bc1dcee2a448715c9c2c81b5b # reverted by 01bfe5e8e428, replaced by 34e5b0118685 +36e2d7cfdcf17b6126863d884d4200191e922524 # Missing dependencies +596efd57cfa1e1bee575e2a2df44fd8ec5e4a42d # Missing dependencies +e86be3a04bc4aeaf12f93af35f08f8d4385bcd98 # doesn't apply diff --git a/patches.kabi/cfg80211-kabi-workaround.patch b/patches.kabi/cfg80211-kabi-workaround.patch new file mode 100644 index 0000000..9f8b251 --- /dev/null +++ b/patches.kabi/cfg80211-kabi-workaround.patch @@ -0,0 +1,165 @@ +From: Takashi Iwai +Subject: kABI workaround for cfg80211 changes +Patch-mainline: Never, kABI workaround +References: CVE-2020-24586 bsc#1185859 + +Some ugly kABI workaround for the recently introduced wireless core +stack changes: +- The modified ieee80211_data_to_8023_exthdr() with an additional + argument is provided as __ieee80211_data_to_8023_exthdr(). + A compat wrapper is defined. +- The ieee80211_fragment_cache field in struct sta_info is factored + out into struct __sta_info. sta_info is embedded there. + +Signed-off-by: Takashi Iwai + +--- + include/net/cfg80211.h | 7 +++++++ + net/mac80211/rx.c | 2 +- + net/mac80211/sta_info.c | 14 +++++++++----- + net/mac80211/sta_info.h | 11 +++++++++-- + net/wireless/util.c | 11 ++++++++++- + 5 files changed, 36 insertions(+), 9 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4599,9 +4599,17 @@ unsigned int ieee80211_get_mesh_hdrlen(s + * @data_offset: offset of payload after the 802.11 header + * Return: 0 on success. Non-zero on error. + */ ++#ifdef __GENKSYMS__ + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype, ++ u8 data_offset); ++#else ++/* new version */ ++int __ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, ++ const u8 *addr, enum nl80211_iftype iftype, + u8 data_offset, bool is_amsdu); ++#define ieee80211_data_to_8023_exthdr __ieee80211_data_to_8023_exthdr ++#endif + + /** + * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2025,7 +2025,7 @@ ieee80211_rx_h_defragment(struct ieee802 + } + + if (rx->sta) +- cache = &rx->sta->frags; ++ cache = &sta_frags(rx->sta); + + if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) + goto out; +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -245,6 +245,8 @@ struct sta_info *sta_info_get_by_idx(str + */ + void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) + { ++ struct __sta_info *__sta = container_of(sta, struct __sta_info, sta); ++ + /* + * If we had used sta_info_pre_move_state() then we might not + * have gone through the state transitions down again, so do +@@ -255,7 +257,7 @@ void sta_info_free(struct ieee80211_loca + kfree(sta->mesh); + #endif + free_percpu(sta->pcpu_rx_stats); +- kfree(sta); ++ kfree(__sta); + } + + /* Caller must hold local->sta_mtx */ +@@ -306,11 +308,13 @@ struct sta_info *sta_info_alloc(struct i + struct ieee80211_local *local = sdata->local; + struct ieee80211_hw *hw = &local->hw; + struct sta_info *sta; ++ struct __sta_info *__sta; + int i; + +- sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); +- if (!sta) ++ __sta = kzalloc(sizeof(*__sta) + hw->sta_data_size, gfp); ++ if (!__sta) + return NULL; ++ sta = &__sta->sta; + + if (ieee80211_hw_check(hw, USES_RSS)) { + sta->pcpu_rx_stats = +@@ -348,7 +352,7 @@ struct sta_info *sta_info_alloc(struct i + + u64_stats_init(&sta->rx_stats.syncp); + +- ieee80211_init_frag_cache(&sta->frags); ++ ieee80211_init_frag_cache(&__sta->frags); + + sta->sta_state = IEEE80211_STA_NONE; + +@@ -984,7 +988,7 @@ static void __sta_info_destroy_part2(str + rate_control_remove_sta_debugfs(sta); + ieee80211_sta_debugfs_remove(sta); + +- ieee80211_destroy_frag_cache(&sta->frags); ++ ieee80211_destroy_frag_cache(&sta_frags(sta)); + + cleanup_single_sta(sta); + } +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -585,12 +585,19 @@ struct sta_info { + + struct cfg80211_chan_def tdls_chandef; + +- struct ieee80211_fragment_cache frags; +- + /* keep last! */ + struct ieee80211_sta sta; + }; + ++/* XXX frags is factoroed out for SLE kABI compatibility */ ++struct __sta_info { ++ struct ieee80211_fragment_cache frags; ++ void *reserved; ++ struct sta_info sta; ++}; ++ ++#define sta_frags(s) container_of(s, struct __sta_info, sta)->frags ++ + static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) + { + #ifdef CONFIG_MAC80211_MESH +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -419,9 +419,9 @@ unsigned int ieee80211_get_mesh_hdrlen(s + } + EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); + +-int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, +- const u8 *addr, enum nl80211_iftype iftype, +- u8 data_offset, bool is_amsdu) ++int __ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, ++ const u8 *addr, enum nl80211_iftype iftype, ++ u8 data_offset, bool is_amsdu) + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct { +@@ -527,6 +527,17 @@ int ieee80211_data_to_8023_exthdr(struct + + return 0; + } ++EXPORT_SYMBOL(__ieee80211_data_to_8023_exthdr); ++ ++// XXX for SLE kABI compatibility ++#undef ieee80211_data_to_8023_exthdr ++ ++int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, ++ const u8 *addr, enum nl80211_iftype iftype, ++ u8 data_offset) ++{ ++ return __ieee80211_data_to_8023_exthdr(skb, ehdr, addr, iftype, data_offset, false); ++} + EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr); + + static void diff --git a/patches.kabi/hci_chan-amp-kABI-workaround.patch b/patches.kabi/hci_chan-amp-kABI-workaround.patch new file mode 100644 index 0000000..4469a7e --- /dev/null +++ b/patches.kabi/hci_chan-amp-kABI-workaround.patch @@ -0,0 +1,27 @@ +From: Takashi Iwai +Subject: kABI workaround for hci_chan amp field addition +Patch-mainline: Never, kABI workaround +References: CVE-2021-33034 bsc#1186111 + +The newly added amp flag in hci_chan struct breaks kABI. +As the new field fits into a hole, we just need to wrap it with +__GENKSYMS__ ifndef as usual. + +Signed-off-by: Takashi Iwai + +--- + include/net/bluetooth/hci_core.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -540,7 +540,9 @@ struct hci_chan { + struct sk_buff_head data_q; + unsigned int sent; + __u8 state; ++#ifndef __GENKSYMS__ + bool amp; ++#endif + }; + + struct hci_conn_params { diff --git a/patches.kabi/kABI-powerpc-64-add-back-start_tb-and-accum_tb-to-th.patch b/patches.kabi/kABI-powerpc-64-add-back-start_tb-and-accum_tb-to-th.patch new file mode 100644 index 0000000..539da85 --- /dev/null +++ b/patches.kabi/kABI-powerpc-64-add-back-start_tb-and-accum_tb-to-th.patch @@ -0,0 +1,38 @@ +From 5dd6cdca8b67cf4e976fc0d9437045388c04811c Mon Sep 17 00:00:00 2001 +From: Michal Suchanek +Date: Thu, 27 May 2021 15:36:33 +0200 +Subject: [PATCH] kABI: powerpc/64: add back start_tb and accum_tb to + thread_struct + +Also rename the members to make sure no users remain. + +References: bsc#1186487 ltc#177613 +Patch-mainline: never, kABI + +Signed-off-by: Michal Suchanek +--- + arch/powerpc/include/asm/processor.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h +index 8c082cb7d9fc..18ef6b44b91f 100644 +--- a/arch/powerpc/include/asm/processor.h ++++ b/arch/powerpc/include/asm/processor.h +@@ -264,6 +264,14 @@ struct thread_struct { + struct thread_fp_state *fp_save_area; + int fpexc_mode; /* floating-point exception mode */ + unsigned int align_ctl; /* alignment handling control */ ++#ifdef CONFIG_PPC64 ++#ifdef __GENKSYMS__ ++ unsigned long start_tb; /* Start purr when proc switched in */ ++ unsigned long accum_tb; /* Total accumulated purr for process */ ++#else ++ unsigned long __unused_padding[2]; ++#endif ++#endif + #ifdef CONFIG_HAVE_HW_BREAKPOINT + struct perf_event *ptrace_bps[HBP_NUM]; + /* +-- +2.26.2 + diff --git a/patches.suse/0001-mm-mempolicy-fix-potential-pte_unmap_unlock-pte-erro.patch b/patches.suse/0001-mm-mempolicy-fix-potential-pte_unmap_unlock-pte-erro.patch new file mode 100644 index 0000000..df15e05 --- /dev/null +++ b/patches.suse/0001-mm-mempolicy-fix-potential-pte_unmap_unlock-pte-erro.patch @@ -0,0 +1,75 @@ +From 3f08842098e842c51e3b97d0dcdebf810b32558e Mon Sep 17 00:00:00 2001 +From: Shijie Luo +Date: Sun, 1 Nov 2020 17:07:40 -0800 +Subject: [PATCH] mm: mempolicy: fix potential pte_unmap_unlock pte error +Git-commit: 3f08842098e842c51e3b97d0dcdebf810b32558e +Patch-mainline: v5.10-rc3 +References: bsc#1185906 + +When flags in queue_pages_pte_range don't have MPOL_MF_MOVE or +MPOL_MF_MOVE_ALL bits, code breaks and passing origin pte - 1 to +pte_unmap_unlock seems like not a good idea. + +queue_pages_pte_range can run in MPOL_MF_MOVE_ALL mode which doesn't +migrate misplaced pages but returns with EIO when encountering such a +page. Since commit a7f40cfe3b7a ("mm: mempolicy: make mbind() return +-EIO when MPOL_MF_STRICT is specified") and early break on the first pte +in the range results in pte_unmap_unlock on an underflow pte. This can +lead to lockups later on when somebody tries to lock the pte resp. +page_table_lock again.. + +Fixes: a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when MPOL_MF_STRICT is specified") +Signed-off-by: Shijie Luo +Signed-off-by: Miaohe Lin +Signed-off-by: Andrew Morton +Reviewed-by: Oscar Salvador +Acked-by: Michal Hocko +Cc: Miaohe Lin +Cc: Feilong Lin +Cc: Shijie Luo +Cc: +Link: https://lkml.kernel.org/r/20201019074853.50856-1-luoshijie1@huawei.com +Signed-off-by: Linus Torvalds + +--- + mm/mempolicy.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -492,7 +492,7 @@ static int queue_pages_pte_range(pmd_t * + struct queue_pages *qp = walk->private; + unsigned long flags = qp->flags; + int nid, ret; +- pte_t *pte; ++ pte_t *pte, *mapped_pte; + spinlock_t *ptl; + + if (pmd_trans_huge(*pmd)) { +@@ -543,7 +543,7 @@ static int queue_pages_pte_range(pmd_t * + if (pmd_trans_unstable(pmd)) + return 0; + retry: +- pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); ++ mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) { + if (!pte_present(*pte)) + continue; +@@ -576,7 +576,7 @@ retry: + if (ret) { + if (flags & MPOL_MF_STRICT) + return -EIO; +- pte = pte_offset_map_lock(walk->mm, pmd, ++ mapped_pte = pte_offset_map_lock(walk->mm, pmd, + addr, &ptl); + continue; + } +@@ -590,7 +590,7 @@ retry: + } else + break; + } +- pte_unmap_unlock(pte - 1, ptl); ++ pte_unmap_unlock(mapped_pte, ptl); + cond_resched(); + return addr != end ? -EIO : 0; + } diff --git a/patches.suse/0001-mm-mempolicy-make-mbind-return-EIO-when-MPOL_MF_STRI.patch b/patches.suse/0001-mm-mempolicy-make-mbind-return-EIO-when-MPOL_MF_STRI.patch new file mode 100644 index 0000000..bdc2750 --- /dev/null +++ b/patches.suse/0001-mm-mempolicy-make-mbind-return-EIO-when-MPOL_MF_STRI.patch @@ -0,0 +1,160 @@ +From a7f40cfe3b7ada57af9b62fd28430eeb4a7cfcb7 Mon Sep 17 00:00:00 2001 +From: Yang Shi +Date: Thu, 28 Mar 2019 20:43:55 -0700 +Subject: [PATCH] mm: mempolicy: make mbind() return -EIO when MPOL_MF_STRICT + is specified +Git-commit: a7f40cfe3b7ada57af9b62fd28430eeb4a7cfcb7 +Patch-mainline: v5.1-rc3 +References: bsc#1185906 + +mhocko@suse.com: +This kernel splits THPs rather than migrate them so we have to check for +the mode and bail out early if this is a pure MPOL_MF_STRICT mode +without move. Otherwise would would just have split the page and +potentially end up on a different node breaking the syscall contract. + +When MPOL_MF_STRICT was specified and an existing page was already on a +node that does not follow the policy, mbind() should return -EIO. But +commit 6f4576e3687b ("mempolicy: apply page table walker on +queue_pages_range()") broke the rule. + +And commit c8633798497c ("mm: mempolicy: mbind and migrate_pages support +thp migration") didn't return the correct value for THP mbind() too. + +If MPOL_MF_STRICT is set, ignore vma_migratable() to make sure it +reaches queue_pages_to_pte_range() or queue_pages_pmd() to check if an +existing page was already on a node that does not follow the policy. +And, non-migratable vma may be used, return -EIO too if MPOL_MF_MOVE or +MPOL_MF_MOVE_ALL was specified. + +Tested with https://github.com/metan-ucw/ltp/blob/master/testcases/kernel/syscalls/mbind/mbind02.c + +[akpm@linux-foundation.org: tweak code comment] +Link: http://lkml.kernel.org/r/1553020556-38583-1-git-send-email-yang.shi@linux.alibaba.com +Fixes: 6f4576e3687b ("mempolicy: apply page table walker on queue_pages_range()") +Signed-off-by: Yang Shi +Signed-off-by: Oscar Salvador +Reported-by: Cyril Hrubis +Suggested-by: Kirill A. Shutemov +Acked-by: Rafael Aquini +Reviewed-by: Oscar Salvador +Acked-by: David Rientjes +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Michal Hocko + +--- + mm/mempolicy.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 47 insertions(+), 6 deletions(-) + +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -499,6 +499,22 @@ static int queue_pages_pte_range(pmd_t * + ptl = pmd_lock(walk->mm, pmd); + if (pmd_trans_huge(*pmd)) { + page = pmd_page(*pmd); ++ ++ nid = page_to_nid(page); ++ if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT)) { ++ spin_unlock(ptl); ++ return 0; ++ } ++ ++ /* ++ * We cannot modify (split) THP in pure strict mode. A misplaced ++ * page has to be reported by EIO ++ */ ++ if ((flags & (MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL) == MPOL_MF_STRICT)) { ++ spin_unlock(ptl); ++ return -EIO; ++ } ++ + if (is_huge_zero_page(page)) { + spin_unlock(ptl); + __split_huge_pmd(vma, pmd, addr, false, NULL); +@@ -509,8 +525,15 @@ static int queue_pages_pte_range(pmd_t * + ret = split_huge_page(page); + unlock_page(page); + put_page(page); +- if (ret) ++ if (ret) { ++ /* ++ * When moving pages in the strict mode we ++ * should report errors ++ */ ++ if (flags & MPOL_MF_STRICT) ++ return -EIO; + return 0; ++ } + } + } else { + spin_unlock(ptl); +@@ -536,6 +559,12 @@ retry: + nid = page_to_nid(page); + if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT)) + continue; ++ /* ++ * We cannot modify (split) THP in pure strict mode. A misplaced ++ * page has to be reported by EIO ++ */ ++ if ((flags & (MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL) == MPOL_MF_STRICT)) ++ break; + if (PageTransCompound(page)) { + get_page(page); + pte_unmap_unlock(pte, ptl); +@@ -543,8 +572,10 @@ retry: + ret = split_huge_page(page); + unlock_page(page); + put_page(page); +- /* Failed to split -- skip. */ ++ /* Failed to split -- skip. unless in strict mode */ + if (ret) { ++ if (flags & MPOL_MF_STRICT) ++ return -EIO; + pte = pte_offset_map_lock(walk->mm, pmd, + addr, &ptl); + continue; +@@ -552,11 +583,16 @@ retry: + goto retry; + } + +- migrate_page_add(page, qp->pagelist, flags); ++ if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { ++ if (!vma_migratable(vma)) ++ break; ++ migrate_page_add(page, qp->pagelist, flags); ++ } else ++ break; + } + pte_unmap_unlock(pte - 1, ptl); + cond_resched(); +- return 0; ++ return addr != end ? -EIO : 0; + } + + static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask, +@@ -628,7 +664,12 @@ static int queue_pages_test_walk(unsigne + unsigned long endvma = vma->vm_end; + unsigned long flags = qp->flags; + +- if (!vma_migratable(vma)) ++ /* ++ * Need check MPOL_MF_STRICT to return -EIO if possible ++ * regardless of vma_migratable ++ */ ++ if (!vma_migratable(vma) && ++ !(flags & MPOL_MF_STRICT)) + return 1; + + if (endvma > end) +@@ -655,7 +696,7 @@ static int queue_pages_test_walk(unsigne + } + + /* queue pages from current vma */ +- if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) ++ if (flags & MPOL_MF_VALID) + return 0; + return 1; + } diff --git a/patches.suse/ARM-footbridge-fix-PCI-interrupt-mapping.patch b/patches.suse/ARM-footbridge-fix-PCI-interrupt-mapping.patch new file mode 100644 index 0000000..90dd80e --- /dev/null +++ b/patches.suse/ARM-footbridge-fix-PCI-interrupt-mapping.patch @@ -0,0 +1,97 @@ +From: Russell King +Date: Thu, 25 Mar 2021 10:26:21 +0000 +Subject: ARM: footbridge: fix PCI interrupt mapping + +Git-commit: 30e3b4f256b4e366a61658c294f6a21b8626dda7 +Patch-mainline: v5.12-rc8 +References: git-fixes + +Since commit 30fdfb929e82 ("PCI: Add a call to pci_assign_irq() in +pci_device_probe()"), the PCI code will call the IRQ mapping function +whenever a PCI driver is probed. If these are marked as __init, this +causes an oops if a PCI driver is loaded or bound after the kernel has +initialised. + +Fixes: 30fdfb929e82 ("PCI: Add a call to pci_assign_irq() in pci_device_probe()") +Signed-off-by: Russell King +Signed-off-by: Mian Yousaf Kaukab +--- + arch/arm/mach-footbridge/cats-pci.c | 4 ++-- + arch/arm/mach-footbridge/ebsa285-pci.c | 4 ++-- + arch/arm/mach-footbridge/netwinder-pci.c | 2 +- + arch/arm/mach-footbridge/personal-pci.c | 5 ++--- + 4 files changed, 7 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c +index 0b2fd7e2e9b4..90b1e9be430e 100644 +--- a/arch/arm/mach-footbridge/cats-pci.c ++++ b/arch/arm/mach-footbridge/cats-pci.c +@@ -15,14 +15,14 @@ + #include + + /* cats host-specific stuff */ +-static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; ++static int irqmap_cats[] = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; + + static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin) + { + return 0; + } + +-static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++static int cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) + { + if (dev->irq >= 255) + return -1; /* not a valid interrupt. */ +diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c +index 6f28aaa9ca79..c3f280d08fa7 100644 +--- a/arch/arm/mach-footbridge/ebsa285-pci.c ++++ b/arch/arm/mach-footbridge/ebsa285-pci.c +@@ -14,9 +14,9 @@ + #include + #include + +-static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; ++static int irqmap_ebsa285[] = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; + +-static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++static int ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) + { + if (dev->vendor == PCI_VENDOR_ID_CONTAQ && + dev->device == PCI_DEVICE_ID_CONTAQ_82C693) +diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c +index 9473aa0305e5..e8304392074b 100644 +--- a/arch/arm/mach-footbridge/netwinder-pci.c ++++ b/arch/arm/mach-footbridge/netwinder-pci.c +@@ -18,7 +18,7 @@ + * We now use the slot ID instead of the device identifiers to select + * which interrupt is routed where. + */ +-static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++static int netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) + { + switch (slot) { + case 0: /* host bridge */ +diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c +index 4391e433a4b2..9d19aa98a663 100644 +--- a/arch/arm/mach-footbridge/personal-pci.c ++++ b/arch/arm/mach-footbridge/personal-pci.c +@@ -14,13 +14,12 @@ + #include + #include + +-static int irqmap_personal_server[] __initdata = { ++static int irqmap_personal_server[] = { + IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0, + IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI + }; + +-static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot, +- u8 pin) ++static int personal_server_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) + { + unsigned char line; + +-- +2.26.2 + diff --git a/patches.suse/Avoid-potentially-erroneos-RST-drop.patch b/patches.suse/Avoid-potentially-erroneos-RST-drop.patch deleted file mode 100644 index bd8e3a2..0000000 --- a/patches.suse/Avoid-potentially-erroneos-RST-drop.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 8fb924672cc295f56aeb572697adc1d615a908e1 Mon Sep 17 00:00:00 2001 -From: Ali Abdallah -Date: Tue, 4 May 2021 10:18:32 +0200 -Subject: [PATCH] Avoid potentially erroneos RST drop -Patch-mainline: Not yet, submitted -References: bsc#1183947 - -In ignore state, we let SYN goes in original, the server might respond -with RST/ACK, and that RST packet is erroneously dropped because of the -flag IP_CT_TCP_FLAG_MAXACK_SET being already set. So we reset the flag -in this case. - -Unfortunately that might not be enough, an out of order ACK in origin -might reset it back, and we might end up again dropping a valid RST when -the server responds with RST SEQ=0. - -The patch disables also the RST check when we are not in established -state and we receive an RST with SEQ=0 that is most likely a response to -a SYN we had let it go through. - -Signed-off-by: Ali Abdallah ---- - net/netfilter/nf_conntrack_proto_tcp.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c -index 9758a7d..3d887bf 100644 ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -928,6 +928,10 @@ static int tcp_packet(struct nf_conn *ct, - - ct->proto.tcp.last_flags = - ct->proto.tcp.last_wscale = 0; -+ /* Reset the max ack flag so in case the server replies -+ * with RST/ACK it will not be marked as an invalid rst. -+ */ -+ ct->proto.tcp.seen[dir].flags &= ~IP_CT_TCP_FLAG_MAXACK_SET; - tcp_options(skb, dataoff, th, &seen); - if (seen.flags & IP_CT_TCP_FLAG_WINDOW_SCALE) { - ct->proto.tcp.last_flags |= -@@ -996,6 +1000,16 @@ static int tcp_packet(struct nf_conn *ct, - } - break; - case TCP_CONNTRACK_CLOSE: -+ /* If we are not in established state, and an RST is -+ * observed with SEQ=0, this is most likely an answer -+ * to a SYN we had let go through above. -+ */ -+ if (index == TCP_RST_SET -+ && th->seq == 0 -+ && (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED -+ || !test_bit(IPS_ASSURED_BIT, &ct->status))) -+ break; -+ - if (index == TCP_RST_SET - && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) - && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) { --- -2.26.2 - diff --git a/patches.suse/Bluetooth-verify-AMP-hci_chan-before-amp_destroy.patch b/patches.suse/Bluetooth-verify-AMP-hci_chan-before-amp_destroy.patch new file mode 100644 index 0000000..8cd50e4 --- /dev/null +++ b/patches.suse/Bluetooth-verify-AMP-hci_chan-before-amp_destroy.patch @@ -0,0 +1,141 @@ +From 5c4c8c9544099bb9043a10a5318130a943e32fc3 Mon Sep 17 00:00:00 2001 +From: Archie Pusaka +Date: Mon, 22 Mar 2021 14:03:11 +0800 +Subject: [PATCH] Bluetooth: verify AMP hci_chan before amp_destroy +Git-commit: 5c4c8c9544099bb9043a10a5318130a943e32fc3 +Patch-mainline: v5.13-rc1 +References: CVE-2021-33034 bsc#1186111 + +hci_chan can be created in 2 places: hci_loglink_complete_evt() if +it is an AMP hci_chan, or l2cap_conn_add() otherwise. In theory, +Only AMP hci_chan should be removed by a call to +hci_disconn_loglink_complete_evt(). However, the controller might mess +up, call that function, and destroy an hci_chan which is not initiated +by hci_loglink_complete_evt(). + +This patch adds a verification that the destroyed hci_chan must have +been init'd by hci_loglink_complete_evt(). + +Example crash call trace: +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xe3/0x144 lib/dump_stack.c:118 + print_address_description+0x67/0x22a mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report mm/kasan/report.c:412 [inline] + kasan_report+0x251/0x28f mm/kasan/report.c:396 + hci_send_acl+0x3b/0x56e net/bluetooth/hci_core.c:4072 + l2cap_send_cmd+0x5af/0x5c2 net/bluetooth/l2cap_core.c:877 + l2cap_send_move_chan_cfm_icid+0x8e/0xb1 net/bluetooth/l2cap_core.c:4661 + l2cap_move_fail net/bluetooth/l2cap_core.c:5146 [inline] + l2cap_move_channel_rsp net/bluetooth/l2cap_core.c:5185 [inline] + l2cap_bredr_sig_cmd net/bluetooth/l2cap_core.c:5464 [inline] + l2cap_sig_channel net/bluetooth/l2cap_core.c:5799 [inline] + l2cap_recv_frame+0x1d12/0x51aa net/bluetooth/l2cap_core.c:7023 + l2cap_recv_acldata+0x2ea/0x693 net/bluetooth/l2cap_core.c:7596 + hci_acldata_packet net/bluetooth/hci_core.c:4606 [inline] + hci_rx_work+0x2bd/0x45e net/bluetooth/hci_core.c:4796 + process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 + worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 + kthread+0x2f0/0x304 kernel/kthread.c:253 + ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 + +Allocated by task 38: + set_track mm/kasan/kasan.c:460 [inline] + kasan_kmalloc+0x8d/0x9a mm/kasan/kasan.c:553 + kmem_cache_alloc_trace+0x102/0x129 mm/slub.c:2787 + kmalloc include/linux/slab.h:515 [inline] + kzalloc include/linux/slab.h:709 [inline] + hci_chan_create+0x86/0x26d net/bluetooth/hci_conn.c:1674 + l2cap_conn_add.part.0+0x1c/0x814 net/bluetooth/l2cap_core.c:7062 + l2cap_conn_add net/bluetooth/l2cap_core.c:7059 [inline] + l2cap_connect_cfm+0x134/0x852 net/bluetooth/l2cap_core.c:7381 + hci_connect_cfm+0x9d/0x122 include/net/bluetooth/hci_core.h:1404 + hci_remote_ext_features_evt net/bluetooth/hci_event.c:4161 [inline] + hci_event_packet+0x463f/0x72fa net/bluetooth/hci_event.c:5981 + hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 + process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 + worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 + kthread+0x2f0/0x304 kernel/kthread.c:253 + ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 + +Freed by task 1732: + set_track mm/kasan/kasan.c:460 [inline] + __kasan_slab_free mm/kasan/kasan.c:521 [inline] + __kasan_slab_free+0x106/0x128 mm/kasan/kasan.c:493 + slab_free_hook mm/slub.c:1409 [inline] + slab_free_freelist_hook+0xaa/0xf6 mm/slub.c:1436 + slab_free mm/slub.c:3009 [inline] + kfree+0x182/0x21e mm/slub.c:3972 + hci_disconn_loglink_complete_evt net/bluetooth/hci_event.c:4891 [inline] + hci_event_packet+0x6a1c/0x72fa net/bluetooth/hci_event.c:6050 + hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 + process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 + worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 + kthread+0x2f0/0x304 kernel/kthread.c:253 + ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 + +The buggy address belongs to the object at ffff8881d7af9180 + which belongs to the cache kmalloc-128 of size 128 +The buggy address is located 24 bytes inside of + 128-byte region [ffff8881d7af9180, ffff8881d7af9200) +The buggy address belongs to the page: +page:ffffea00075ebe40 count:1 mapcount:0 mapping:ffff8881da403200 index:0x0 +Flags: 0x8000000000000200(slab) +Raw: 8000000000000200 dead000000000100 dead000000000200 ffff8881da403200 +Raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8881d7af9080: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb + ffff8881d7af9100: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc +>ffff8881d7af9180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8881d7af9200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881d7af9280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + +Signed-off-by: Archie Pusaka +Reported-by: syzbot+98228e7407314d2d4ba2@syzkaller.appspotmail.com +Reviewed-by: Alain Michaud +Reviewed-by: Abhishek Pandit-Subedi +Signed-off-by: Marcel Holtmann +Acked-by: Takashi Iwai + +--- + include/net/bluetooth/hci_core.h | 1 + + net/bluetooth/hci_event.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index ebdd4afe30d2..ca4ac6603b9a 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -704,6 +704,7 @@ struct hci_chan { + struct sk_buff_head data_q; + unsigned int sent; + __u8 state; ++ bool amp; + }; + + struct hci_conn_params { +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index cf2f4a0abdbd..341c8ce93648 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -5032,6 +5032,7 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) + return; + + hchan->handle = le16_to_cpu(ev->handle); ++ hchan->amp = true; + + BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan); + +@@ -5064,7 +5065,7 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, + hci_dev_lock(hdev); + + hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle)); +- if (!hchan) ++ if (!hchan || !hchan->amp) + goto unlock; + + amp_destroy_logical_link(hchan, ev->reason); +-- +2.26.2 + diff --git a/patches.suse/Don-t-drop-out-of-segments-RST-if-tcp_be_liberal-is-.patch b/patches.suse/Don-t-drop-out-of-segments-RST-if-tcp_be_liberal-is-.patch deleted file mode 100644 index 7ae98a9..0000000 --- a/patches.suse/Don-t-drop-out-of-segments-RST-if-tcp_be_liberal-is-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f9924e69667423a1fb011e9fa369b91a09e20d74 Mon Sep 17 00:00:00 2001 -From: Ali Abdallah -Date: Tue, 4 May 2021 10:23:13 +0200 -Subject: [PATCH] Don't drop out of segments RST if tcp_be_liberal is set -Patch-mainline: Not yet, submitted -References: bsc#1183947 - -When tcp_be_liberal is set, don't be conservative on out of segments -RSTs. - -Signed-off-by: Ali Abdallah ---- - Documentation/networking/nf_conntrack-sysctl.txt | 2 +- - net/netfilter/nf_conntrack_proto_tcp.c | 3 ++- - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/Documentation/networking/nf_conntrack-sysctl.txt b/Documentation/networking/nf_conntrack-sysctl.txt -index 497d668..b5afe05 100644 ---- a/Documentation/networking/nf_conntrack-sysctl.txt -+++ b/Documentation/networking/nf_conntrack-sysctl.txt -@@ -112,7 +112,7 @@ nf_conntrack_tcp_be_liberal - BOOLEAN - not 0 - enabled - - Be conservative in what you do, be liberal in what you accept from others. -- If it's non-zero, we mark only out of window RST segments as INVALID. -+ If it's non-zero, we don't mark out of window segments as INVALID. - - nf_conntrack_tcp_loose - BOOLEAN - 0 - disabled -diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c -index 3d887bf..b7660b6 100644 ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -1013,7 +1013,8 @@ static int tcp_packet(struct nf_conn *ct, - - if (index == TCP_RST_SET - && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) -- && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) { -+ && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack) -+ && !tn->tcp_be_liberal) { - /* Invalid RST */ - spin_unlock_bh(&ct->lock); - if (LOG_INVALID(net, IPPROTO_TCP)) --- -2.26.2 - diff --git a/patches.suse/SUNRPC-in-case-of-backlog-hand-free-slots-directly-t.patch b/patches.suse/SUNRPC-in-case-of-backlog-hand-free-slots-directly-t.patch new file mode 100644 index 0000000..0571419 --- /dev/null +++ b/patches.suse/SUNRPC-in-case-of-backlog-hand-free-slots-directly-t.patch @@ -0,0 +1,202 @@ +From: NeilBrown +Date: Mon, 17 May 2021 09:34:38 +1000 +Subject: [PATCH] SUNRPC in case of backlog, hand free slots directly to + waiting task +Git-commit: e877a88d1f069edced4160792f42c2a8e2dba942 +Git-repo: git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git +Patch-mainline: Queued in subsystem maintainer repository +References: bsc#1185428 + +If sunrpc.tcp_max_slot_table_entries is small and there are tasks +on the backlog queue, then when a request completes it is freed and the +first task on the queue is woken. The expectation is that it will wake +and claim that request. However if it was a sync task and the waiting +process was killed at just that moment, it will wake and NOT claim the +request. + +As long as TASK_CONGESTED remains set, requests can only be claimed by +tasks woken from the backlog, and they are woken only as requests are +freed, so when a task doesn't claim a request, no other task can ever +get that request until TASK_CONGESTED is cleared. Each time this +happens the number of available requests is decreased by one. + +With a sufficiently high workload and sufficiently low setting of +max_slot (16 in the case where this was seen), TASK_CONGESTED can remain +set for an extended period, and the above scenario (of a process being +killed just as its task was woken) can repeat until no requests can be +allocated. Then traffic stops. + +This patch addresses the problem by introducing a positive handover of a +request from a completing task to a backlog task - the request is never +freed when there is a backlog. + +When a task is woken it might already have a request attached in which +case it is *not* freed (as with current code) but is initialised (if +needed) and used. If it isn't used it will eventually be freed by +rpc_exit_task(). xprt_release() is enhanced to be able to correctly +release an uninitialised request. + +Signed-off-by: NeilBrown +Acked-by: NeilBrown + +--- + net/sunrpc/clnt.c | 10 ------ + net/sunrpc/xprt.c | 86 +++++++++++++++++++++++++++++++++++------------------- + 2 files changed, 56 insertions(+), 40 deletions(-) + +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1630,16 +1630,6 @@ call_reserveresult(struct rpc_task *task + return; + } + +- /* +- * Even though there was an error, we may have acquired +- * a request slot somehow. Make sure not to leak it. +- */ +- if (task->tk_rqstp) { +- printk(KERN_ERR "%s: status=%d, request allocated anyway\n", +- __func__, status); +- xprt_release(task); +- } +- + switch (status) { + case -ENOMEM: + rpc_delay(task, HZ >> 2); +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -71,6 +71,7 @@ static void xprt_connect_status(struct r + static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); + static void __xprt_put_cong(struct rpc_xprt *, struct rpc_rqst *); + static void xprt_destroy(struct rpc_xprt *xprt); ++static void xprt_request_init(struct rpc_task *task); + + static DEFINE_SPINLOCK(xprt_list_lock); + static LIST_HEAD(xprt_list); +@@ -1088,10 +1089,26 @@ static void xprt_add_backlog(struct rpc_ + rpc_sleep_on(&xprt->backlog, task, NULL); + } + +-static void xprt_wake_up_backlog(struct rpc_xprt *xprt) ++static bool __xprt_set_rq(struct rpc_task *task, void *data) + { +- if (rpc_wake_up_next(&xprt->backlog) == NULL) ++ struct rpc_rqst *req = data; ++ ++ if (task->tk_rqstp == NULL) { ++ memset(req, 0, sizeof(*req)); /* mark unused */ ++ task->tk_status = -EAGAIN; ++ task->tk_rqstp = req; ++ return true; ++ } ++ return false; ++} ++ ++static bool xprt_wake_up_backlog(struct rpc_xprt *xprt, struct rpc_rqst *req) ++{ ++ if (rpc_wake_up_first(&xprt->backlog, __xprt_set_rq, req) == NULL) { + clear_bit(XPRT_CONGESTED, &xprt->state); ++ return false; ++ } ++ return true; + } + + static bool xprt_throttle_congested(struct rpc_xprt *xprt, struct rpc_task *task) +@@ -1192,11 +1209,11 @@ EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_sl + void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) + { + spin_lock(&xprt->reserve_lock); +- if (!xprt_dynamic_free_slot(xprt, req)) { ++ if (!xprt_wake_up_backlog(xprt, req) && ++ !xprt_dynamic_free_slot(xprt, req)) { + memset(req, 0, sizeof(*req)); /* mark unused */ + list_add(&req->rq_list, &xprt->free); + } +- xprt_wake_up_backlog(xprt); + spin_unlock(&xprt->reserve_lock); + } + EXPORT_SYMBOL_GPL(xprt_free_slot); +@@ -1272,6 +1289,10 @@ xprt_request_init(struct rpc_task *task) + struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_rqst *req = task->tk_rqstp; + ++ if (req->rq_task) ++ /* Already initialized */ ++ return; ++ + INIT_LIST_HEAD(&req->rq_list); + req->rq_timeout = task->tk_client->cl_timeout->to_initval; + req->rq_task = task; +@@ -1334,8 +1355,10 @@ void xprt_retry_reserve(struct rpc_task + struct rpc_xprt *xprt = task->tk_xprt; + + task->tk_status = 0; +- if (task->tk_rqstp != NULL) ++ if (task->tk_rqstp != NULL) { ++ xprt_request_init(task); + return; ++ } + + task->tk_timeout = 0; + task->tk_status = -EAGAIN; +@@ -1362,32 +1385,35 @@ void xprt_release(struct rpc_task *task) + } + + xprt = req->rq_xprt; +- if (task->tk_ops->rpc_count_stats != NULL) +- task->tk_ops->rpc_count_stats(task, task->tk_calldata); +- else if (task->tk_client) +- rpc_count_iostats(task, task->tk_client->cl_metrics); +- spin_lock(&xprt->recv_lock); +- if (!list_empty(&req->rq_list)) { +- list_del_init(&req->rq_list); +- xprt_wait_on_pinned_rqst(req); +- } +- spin_unlock(&xprt->recv_lock); +- spin_lock_bh(&xprt->transport_lock); +- xprt->ops->release_xprt(xprt, task); +- if (xprt->ops->release_request) +- xprt->ops->release_request(task); +- xprt->last_used = jiffies; +- xprt_schedule_autodisconnect(xprt); +- spin_unlock_bh(&xprt->transport_lock); +- if (req->rq_buffer) +- xprt->ops->buf_free(task); +- xprt_inject_disconnect(xprt); +- if (req->rq_cred != NULL) +- put_rpccred(req->rq_cred); +- task->tk_rqstp = NULL; +- if (req->rq_release_snd_buf) +- req->rq_release_snd_buf(req); ++ if (xprt) { ++ if (task->tk_ops->rpc_count_stats != NULL) ++ task->tk_ops->rpc_count_stats(task, task->tk_calldata); ++ else if (task->tk_client) ++ rpc_count_iostats(task, task->tk_client->cl_metrics); ++ spin_lock(&xprt->recv_lock); ++ if (!list_empty(&req->rq_list)) { ++ list_del_init(&req->rq_list); ++ xprt_wait_on_pinned_rqst(req); ++ } ++ spin_unlock(&xprt->recv_lock); ++ spin_lock_bh(&xprt->transport_lock); ++ xprt->ops->release_xprt(xprt, task); ++ if (xprt->ops->release_request) ++ xprt->ops->release_request(task); ++ xprt->last_used = jiffies; ++ xprt_schedule_autodisconnect(xprt); ++ spin_unlock_bh(&xprt->transport_lock); ++ if (req->rq_buffer) ++ xprt->ops->buf_free(task); ++ xprt_inject_disconnect(xprt); ++ if (req->rq_cred != NULL) ++ put_rpccred(req->rq_cred); ++ if (req->rq_release_snd_buf) ++ req->rq_release_snd_buf(req); ++ } else ++ xprt = task->tk_xprt; + ++ task->tk_rqstp = NULL; + dprintk("RPC: %5u release request %p\n", task->tk_pid, req); + if (likely(!bc_prealloc(req))) + xprt->ops->free_slot(xprt, req); diff --git a/patches.suse/ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch b/patches.suse/ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch new file mode 100644 index 0000000..3a69cf6 --- /dev/null +++ b/patches.suse/ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch @@ -0,0 +1,56 @@ +From 0dc267b13f3a7e8424a898815dd357211b737330 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 11 May 2021 20:02:56 +0200 +Subject: [PATCH] ath10k: Fix TKIP Michael MIC verification for PCIe +Git-commit: 0dc267b13f3a7e8424a898815dd357211b737330 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-26141 bsc#1185863 bsc#1185987 + +TKIP Michael MIC was not verified properly for PCIe cases since the +validation steps in ieee80211_rx_h_michael_mic_verify() in mac80211 did +not get fully executed due to unexpected flag values in +ieee80211_rx_status. + +Fix this by setting the flags property to meet mac80211 expectations for +performing Michael MIC validation there. This fixes CVE-2020-26141. It +does the same as ath10k_htt_rx_proc_rx_ind_hl() for SDIO which passed +MIC verification case. This applies only to QCA6174/QCA9377 PCIe. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.c3f1d42c6746.I795593fcaae941c471425b8c7d5f7bb185d29142@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1425,6 +1425,10 @@ static void ath10k_htt_rx_h_mpdu(struct + } + + ath10k_htt_rx_h_csum_offload(msdu); ++ ++ if (frag && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) ++ status->flag &= ~RX_FLAG_MMIC_STRIPPED; ++ + ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, + is_decrypted); + +@@ -1439,6 +1443,10 @@ static void ath10k_htt_rx_h_mpdu(struct + + hdr = (void *)msdu->data; + hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++ ++ if (frag && enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) ++ status->flag &= ~RX_FLAG_IV_STRIPPED & ++ ~RX_FLAG_MMIC_STRIPPED; + } + } + diff --git a/patches.suse/ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch b/patches.suse/ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch new file mode 100644 index 0000000..cef50f0 --- /dev/null +++ b/patches.suse/ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch @@ -0,0 +1,118 @@ +From 62a8ff67eba52dae9b107e1fb8827054ed00a265 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 11 May 2021 20:02:57 +0200 +Subject: [PATCH] ath10k: Validate first subframe of A-MSDU before processing the list +Git-commit: 62a8ff67eba52dae9b107e1fb8827054ed00a265 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-26141 bsc#1185863 bsc#1185987 + +In certain scenarios a normal MSDU can be received as an A-MSDU when +the A-MSDU present bit of a QoS header gets flipped during reception. +Since this bit is unauthenticated, the hardware crypto engine can pass +the frame to the driver without any error indication. + +This could result in processing unintended subframes collected in the +A-MSDU list. Hence, validate A-MSDU list by checking if the first frame +has a valid subframe header. + +Comparing the non-aggregated MSDU and an A-MSDU, the fields of the first +subframe DA matches the LLC/SNAP header fields of a normal MSDU. +In order to avoid processing such frames, add a validation to +filter such A-MSDU frames where the first subframe header DA matches +with the LLC/SNAP header pattern. + +Tested-on: QCA9984 hw1.0 PCI 10.4-3.10-00047 + +Cc: stable@vger.kernel.org +Signed-off-by: Sriram R +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.e6f5eb7b9847.I38a77ae26096862527a5eab73caebd7346af8b66@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 61 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1804,14 +1804,62 @@ static void ath10k_htt_rx_h_unchain(stru + ath10k_unchain_msdu(amsdu, unchain_cnt); + } + ++static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, ++ struct sk_buff_head *amsdu) ++{ ++ u8 *subframe_hdr; ++ struct sk_buff *first; ++ bool is_first, is_last; ++ struct htt_rx_desc *rxd; ++ struct ieee80211_hdr *hdr; ++ size_t hdr_len, crypto_len; ++ enum htt_rx_mpdu_encrypt_type enctype; ++ int bytes_aligned = ar->hw_params.decap_align_bytes; ++ ++ first = skb_peek(amsdu); ++ ++ rxd = (void *)first->data - sizeof(*rxd); ++ hdr = (void *)rxd->rx_hdr_status; ++ ++ is_first = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); ++ is_last = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); ++ ++ /* Return in case of non-aggregated msdu */ ++ if (is_first && is_last) ++ return true; ++ ++ /* First msdu flag is not set for the first msdu of the list */ ++ if (!is_first) ++ return false; ++ ++ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), ++ RX_MPDU_START_INFO0_ENCRYPT_TYPE); ++ ++ hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); ++ ++ subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) + ++ crypto_len; ++ ++ /* Validate if the amsdu has a proper first subframe. ++ * There are chances a single msdu can be received as amsdu when ++ * the unauthenticated amsdu flag of a QoS header ++ * gets flipped in non-SPP AMSDU's, in such cases the first ++ * subframe has llc/snap header in place of a valid da. ++ * return false if the da matches rfc1042 pattern ++ */ ++ if (ether_addr_equal(subframe_hdr, rfc1042_header)) ++ return false; ++ ++ return true; ++} ++ + static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, + struct sk_buff_head *amsdu, + struct ieee80211_rx_status *rx_status) + { +- /* FIXME: It might be a good idea to do some fuzzy-testing to drop +- * invalid/dangerous frames. +- */ +- + if (!rx_status->freq) { + ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n"); + return false; +@@ -1822,6 +1870,11 @@ static bool ath10k_htt_rx_amsdu_allowed( + return false; + } + ++ if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) { ++ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n"); ++ return false; ++ } ++ + return true; + } + diff --git a/patches.suse/ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch b/patches.suse/ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch new file mode 100644 index 0000000..74ce18a --- /dev/null +++ b/patches.suse/ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch @@ -0,0 +1,105 @@ +From 65c415a144ad8132b6a6d97d4a1919ffc728e2d1 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 11 May 2021 20:02:53 +0200 +Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe +Git-commit: 65c415a144ad8132b6a6d97d4a1919ffc728e2d1 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-26145 bsc#1185860 + +Fragmentation is not used with multicast frames. Discard unexpected +fragments with multicast DA. This fixes CVE-2020-26145. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.5a0bd289bda8.Idd6ebea20038fb1cfee6de924aa595e5647c9eae@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 35 +++++++++++++++++++++++++++---- + 1 file changed, 31 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1524,16 +1524,27 @@ static void ath10k_htt_rx_h_csum_offload + msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu); + } + ++static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar, ++ struct sk_buff *skb, ++ u16 offset) ++{ ++ struct ieee80211_hdr *hdr; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + offset); ++ return !is_multicast_ether_addr(hdr->addr1); ++} ++ + static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, + struct sk_buff_head *amsdu, + struct ieee80211_rx_status *status, + bool fill_crypt_header, + u8 *rx_hdr, +- enum ath10k_pkt_rx_err *err) ++ enum ath10k_pkt_rx_err *err, ++ bool frag) + { + struct sk_buff *first; + struct sk_buff *last; +- struct sk_buff *msdu; ++ struct sk_buff *msdu, *temp; + struct htt_rx_desc *rxd; + struct ieee80211_hdr *hdr; + enum htt_rx_mpdu_encrypt_type enctype; +@@ -1546,6 +1557,7 @@ static void ath10k_htt_rx_h_mpdu(struct + bool is_decrypted; + bool is_mgmt; + u32 attention; ++ bool multicast_check = true; + + if (skb_queue_empty(amsdu)) + return; +@@ -1644,6 +1656,21 @@ static void ath10k_htt_rx_h_mpdu(struct + } + + skb_queue_walk(amsdu, msdu) { ++ if (frag) ++ multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar, ++ msdu, ++ 0); ++ ++ if (!multicast_check) { ++ /* Discard the fragment with invalid PN or multicast DA ++ */ ++ temp = msdu->prev; ++ __skb_unlink(msdu, amsdu); ++ msdu = temp; ++ multicast_check = true; ++ continue; ++ } ++ + ath10k_htt_rx_h_csum_offload(msdu); + ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype, + is_decrypted); +@@ -1849,7 +1876,7 @@ static int ath10k_htt_rx_handle_amsdu(st + ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt); + + ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter); +- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err); ++ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, false); + msdus_to_queue = skb_queue_len(&amsdu); + ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); + +@@ -2200,7 +2227,7 @@ static int ath10k_htt_rx_in_ord_ind(stru + ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); + ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL); + ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL, +- NULL); ++ NULL, frag); + ath10k_htt_rx_h_enqueue(ar, &amsdu, status); + break; + case -EAGAIN: diff --git a/patches.suse/bpf-Fix-mask-direction-swap-upon-off-reg-sign-change.patch b/patches.suse/bpf-Fix-mask-direction-swap-upon-off-reg-sign-change.patch new file mode 100644 index 0000000..2e7b725 --- /dev/null +++ b/patches.suse/bpf-Fix-mask-direction-swap-upon-off-reg-sign-change.patch @@ -0,0 +1,72 @@ +From: Daniel Borkmann +Date: Fri, 21 May 2021 10:19:22 +0000 +Subject: bpf: Fix mask direction swap upon off reg sign change +Patch-mainline: v5.13 or v5.13-rc4 (next release) +Git-commit: bb01a1bba579b4b1c5566af24d95f1767859771e +References: bsc#1186484,CVE-2021-33200 + +Masking direction as indicated via mask_to_left is considered to be +calculated once and then used to derive pointer limits. Thus, this +needs to be placed into bpf_sanitize_info instead so we can pass it +to sanitize_ptr_alu() call after the pointer move. Piotr noticed a +corner case where the off reg causes masking direction change which +then results in an incorrect final aux->alu_limit. + +Fixes: 7fedb63a8307 ("bpf: Tighten speculative pointer arithmetic mask") +Reported-by: Piotr Krysiuk +Signed-off-by: Daniel Borkmann +Reviewed-by: Piotr Krysiuk +Acked-by: Alexei Starovoitov +Acked-by: Gary Lin +--- + kernel/bpf/verifier.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2725,18 +2725,10 @@ enum { + }; + + static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, +- const struct bpf_reg_state *off_reg, +- u32 *alu_limit, u8 opcode) ++ u32 *alu_limit, bool mask_to_left) + { +- bool off_is_neg = off_reg->smin_value < 0; +- bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || +- (opcode == BPF_SUB && !off_is_neg); + u32 max = 0, ptr_limit = 0; + +- if (!tnum_is_const(off_reg->var_off) && +- (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) +- return REASON_BOUNDS; +- + switch (ptr_reg->type) { + case PTR_TO_STACK: + /* Indirect variable offset stack access is prohibited in +@@ -2001,6 +1993,7 @@ static bool sanitize_needed(u8 opcode) + + struct bpf_sanitize_info { + struct bpf_insn_aux_data aux; ++ bool mask_to_left; + }; + + static int sanitize_ptr_alu(struct bpf_verifier_env *env, +@@ -2031,7 +2024,16 @@ static int sanitize_ptr_alu(struct bpf_v + if (vstate->speculative) + goto do_sim; + +- err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode); ++ if (!commit_window) { ++ if (!tnum_is_const(off_reg->var_off) && ++ (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) ++ return REASON_BOUNDS; ++ ++ info->mask_to_left = (opcode == BPF_ADD && off_is_neg) || ++ (opcode == BPF_SUB && !off_is_neg); ++ } ++ ++ err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left); + if (err < 0) + return err; + diff --git a/patches.suse/bpf-Wrap-aux-data-inside-bpf_sanitize_info-container.patch b/patches.suse/bpf-Wrap-aux-data-inside-bpf_sanitize_info-container.patch new file mode 100644 index 0000000..76489ed --- /dev/null +++ b/patches.suse/bpf-Wrap-aux-data-inside-bpf_sanitize_info-container.patch @@ -0,0 +1,82 @@ +From: Daniel Borkmann +Date: Fri, 21 May 2021 10:17:36 +0000 +Subject: bpf: Wrap aux data inside bpf_sanitize_info container +Patch-mainline: v5.13 or v5.13-rc4 (next release) +Git-commit: 3d0220f6861d713213b015b582e9f21e5b28d2e0 +References: bsc#1186484,CVE-2021-33200 + +Add a container structure struct bpf_sanitize_info which holds +the current aux info, and update call-sites to sanitize_ptr_alu() +to pass it in. This is needed for passing in additional state +later on. + +Signed-off-by: Daniel Borkmann +Reviewed-by: Piotr Krysiuk +Acked-by: Alexei Starovoitov +Acked-by: Gary Lin +--- + kernel/bpf/verifier.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1999,15 +1999,19 @@ static bool sanitize_needed(u8 opcode) + return opcode == BPF_ADD || opcode == BPF_SUB; + } + ++struct bpf_sanitize_info { ++ struct bpf_insn_aux_data aux; ++}; ++ + static int sanitize_ptr_alu(struct bpf_verifier_env *env, + struct bpf_insn *insn, + const struct bpf_reg_state *ptr_reg, + const struct bpf_reg_state *off_reg, + struct bpf_reg_state *dst_reg, +- struct bpf_insn_aux_data *tmp_aux, ++ struct bpf_sanitize_info *info, + const bool commit_window) + { +- struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux; ++ struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : &info->aux; + struct bpf_verifier_state *vstate = env->cur_state; + bool off_is_neg = off_reg->smin_value < 0; + bool ptr_is_dst_reg = ptr_reg == dst_reg; +@@ -2035,8 +2039,8 @@ static int sanitize_ptr_alu(struct bpf_v + /* In commit phase we narrow the masking window based on + * the observed pointer move after the simulated operation. + */ +- alu_state = tmp_aux->alu_state; +- alu_limit = abs(tmp_aux->alu_limit - alu_limit); ++ alu_state = info->aux.alu_state; ++ alu_limit = abs(info->aux.alu_limit - alu_limit); + } else { + alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0; + alu_state |= ptr_is_dst_reg ? +@@ -2163,7 +2167,7 @@ static int adjust_ptr_min_max_vals(struc + smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value; + u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value, + umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value; +- struct bpf_insn_aux_data tmp_aux = {}; ++ struct bpf_sanitize_info info = {}; + u8 opcode = BPF_OP(insn->code); + u32 dst = insn->dst_reg; + int ret; +@@ -2215,7 +2219,7 @@ static int adjust_ptr_min_max_vals(struc + + if (sanitize_needed(opcode)) { + ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg, +- &tmp_aux, false); ++ &info, false); + if (ret < 0) + return sanitize_err(env, insn, ret, off_reg, dst_reg); + } +@@ -2356,7 +2360,7 @@ static int adjust_ptr_min_max_vals(struc + return -EACCES; + if (sanitize_needed(opcode)) { + ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg, +- &tmp_aux, true); ++ &info, true); + if (ret < 0) + return sanitize_err(env, insn, ret, off_reg, dst_reg); + } diff --git a/patches.suse/btrfs-fix-race-between-transaction-aborts-and-fsyncs.patch b/patches.suse/btrfs-fix-race-between-transaction-aborts-and-fsyncs.patch new file mode 100644 index 0000000..5df8a4e --- /dev/null +++ b/patches.suse/btrfs-fix-race-between-transaction-aborts-and-fsyncs.patch @@ -0,0 +1,154 @@ +From: Filipe Manana +Date: Mon, 5 Apr 2021 12:32:16 +0100 +Git-commit: 061dde8245356d8864d29e25207aa4daa0be4d3c +Patch-mainline: v5.13-rc1 +Subject: [PATCH] btrfs: fix race between transaction aborts and fsyncs leading + to use-after-free +References: bsc#1186441 + +There is a race between a task aborting a transaction during a commit, +a task doing an fsync and the transaction kthread, which leads to an +use-after-free of the log root tree. When this happens, it results in a +stack trace like the following: + + BTRFS info (device dm-0): forced readonly + BTRFS warning (device dm-0): Skipping commit of aborted transaction. + BTRFS: error (device dm-0) in cleanup_transaction:1958: errno=-5 IO failure + BTRFS warning (device dm-0): lost page write due to IO error on /dev/mapper/error-test (-5) + BTRFS warning (device dm-0): Skipping commit of aborted transaction. + BTRFS warning (device dm-0): direct IO failed ino 261 rw 0,0 sector 0xa4e8 len 4096 err no 10 + BTRFS error (device dm-0): error writing primary super block to device 1 + BTRFS warning (device dm-0): direct IO failed ino 261 rw 0,0 sector 0x12e000 len 4096 err no 10 + BTRFS warning (device dm-0): direct IO failed ino 261 rw 0,0 sector 0x12e008 len 4096 err no 10 + BTRFS warning (device dm-0): direct IO failed ino 261 rw 0,0 sector 0x12e010 len 4096 err no 10 + BTRFS: error (device dm-0) in write_all_supers:4110: errno=-5 IO failure (1 errors while writing supers) + BTRFS: error (device dm-0) in btrfs_sync_log:3308: errno=-5 IO failure + general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b68: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI + CPU: 2 PID: 2458471 Comm: fsstress Not tainted 5.12.0-rc5-btrfs-next-84 #1 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 + RIP: 0010:__mutex_lock+0x139/0xa40 + Code: c0 74 19 (...) + RSP: 0018:ffff9f18830d7b00 EFLAGS: 00010202 + RAX: 6b6b6b6b6b6b6b68 RBX: 0000000000000001 RCX: 0000000000000002 + RDX: ffffffffb9c54d13 RSI: 0000000000000000 RDI: 0000000000000000 + RBP: ffff9f18830d7bc0 R08: 0000000000000000 R09: 0000000000000000 + R10: ffff9f18830d7be0 R11: 0000000000000001 R12: ffff8c6cd199c040 + R13: ffff8c6c95821358 R14: 00000000fffffffb R15: ffff8c6cbcf01358 + FS: 00007fa9140c2b80(0000) GS:ffff8c6fac600000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fa913d52000 CR3: 000000013d2b4003 CR4: 0000000000370ee0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + ? __btrfs_handle_fs_error+0xde/0x146 [btrfs] + ? btrfs_sync_log+0x7c1/0xf20 [btrfs] + ? btrfs_sync_log+0x7c1/0xf20 [btrfs] + btrfs_sync_log+0x7c1/0xf20 [btrfs] + btrfs_sync_file+0x40c/0x580 [btrfs] + do_fsync+0x38/0x70 + __x64_sys_fsync+0x10/0x20 + do_syscall_64+0x33/0x80 + entry_SYSCALL_64_after_hwframe+0x44/0xae + RIP: 0033:0x7fa9142a55c3 + Code: 8b 15 09 (...) + RSP: 002b:00007fff26278d48 EFLAGS: 00000246 ORIG_RAX: 000000000000004a + RAX: ffffffffffffffda RBX: 0000563c83cb4560 RCX: 00007fa9142a55c3 + RDX: 00007fff26278cb0 RSI: 00007fff26278cb0 RDI: 0000000000000005 + RBP: 0000000000000005 R08: 0000000000000001 R09: 00007fff26278d5c + R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000340 + R13: 00007fff26278de0 R14: 00007fff26278d96 R15: 0000563c83ca57c0 + Modules linked in: btrfs dm_zero dm_snapshot dm_thin_pool (...) + ---[ end trace ee2f1b19327d791d ]--- + +The steps that lead to this crash are the following: + +1) We are at transaction N; + +2) We have two tasks with a transaction handle attached to transaction N. + Task A and Task B. Task B is doing an fsync; + +3) Task B is at btrfs_sync_log(), and has saved fs_info->log_root_tree + into a local variable named 'log_root_tree' at the top of + btrfs_sync_log(). Task B is about to call write_all_supers(), but + before that... + +4) Task A calls btrfs_commit_transaction(), and after it sets the + transaction state to TRANS_STATE_COMMIT_START, an error happens before + it waits for the transaction's 'num_writers' counter to reach a value + of 1 (no one else attached to the transaction), so it jumps to the + label "cleanup_transaction"; + +5) Task A then calls cleanup_transaction(), where it aborts the + transaction, setting BTRFS_FS_STATE_TRANS_ABORTED on fs_info->fs_state, + setting the ->aborted field of the transaction and the handle to an + errno value and also setting BTRFS_FS_STATE_ERROR on fs_info->fs_state. + + After that, at cleanup_transaction(), it deletes the transaction from + the list of transactions (fs_info->trans_list), sets the transaction + to the state TRANS_STATE_COMMIT_DOING and then waits for the number + of writers to go down to 1, as it's currently 2 (1 for task A and 1 + for task B); + +6) The transaction kthread is running and sees that BTRFS_FS_STATE_ERROR + is set in fs_info->fs_state, so it calls btrfs_cleanup_transaction(). + + There it sees the list fs_info->trans_list is empty, and then proceeds + into calling btrfs_drop_all_logs(), which frees the log root tree with + a call to btrfs_free_log_root_tree(); + +7) Task B calls write_all_supers() and, shortly after, under the label + 'out_wake_log_root', it deferences the pointer stored in + 'log_root_tree', which was already freed in the previous step by the + transaction kthread. This results in a use-after-free leading to a + crash. + +Fix this by deleting the transaction from the list of transactions at +cleanup_transaction() only after setting the transaction state to +TRANS_STATE_COMMIT_DOING and waiting for all existing tasks that are +attached to the transaction to release their transaction handles. +This makes the transaction kthread wait for all the tasks attached to +the transaction to be done with the transaction before dropping the +log roots and doing other cleanups. + +Fixes: ef67963dac255b ("btrfs: drop logs when we've aborted a transaction") +CC: stable@vger.kernel.org # 5.10+ +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +--- + fs/btrfs/transaction.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 62f5195d0076..f75de9f6c0ad 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1986,7 +1986,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err) + */ + BUG_ON(list_empty(&cur_trans->list)); + +- list_del_init(&cur_trans->list); + if (cur_trans == fs_info->running_transaction) { + cur_trans->state = TRANS_STATE_COMMIT_DOING; + spin_unlock(&fs_info->trans_lock); +@@ -1995,6 +1994,17 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err) + + spin_lock(&fs_info->trans_lock); + } ++ ++ /* ++ * Now that we know no one else is still using the transaction we can ++ * remove the transaction from the list of transactions. This avoids ++ * the transaction kthread from cleaning up the transaction while some ++ * other task is still using it, which could result in a use-after-free ++ * on things like log trees, as it forces the transaction kthread to ++ * wait for this transaction to be cleaned up by us. ++ */ ++ list_del_init(&cur_trans->list); ++ + spin_unlock(&fs_info->trans_lock); + + btrfs_cleanup_one_transaction(trans->transaction, fs_info); +-- +2.26.2 + diff --git a/patches.suse/btrfs-fix-race-when-picking-most-recent-mod-log-oper.patch b/patches.suse/btrfs-fix-race-when-picking-most-recent-mod-log-oper.patch new file mode 100644 index 0000000..b132e2f --- /dev/null +++ b/patches.suse/btrfs-fix-race-when-picking-most-recent-mod-log-oper.patch @@ -0,0 +1,326 @@ +From: Filipe Manana +Date: Tue, 20 Apr 2021 10:55:44 +0100 +Git-commit: f9690f426b2134cc3e74bfc5d9dfd6a4b2ca5281 +Patch-mainline: v5.13-rc1 +Subject: [PATCH] btrfs: fix race when picking most recent mod log operation + for an old root +References: bsc#1186439 + +Commit dbcc7d57bffc0c ("btrfs: fix race when cloning extent buffer during +rewind of an old root"), fixed a race when we need to rewind the extent +buffer of an old root. It was caused by picking a new mod log operation +for the extent buffer while getting a cloned extent buffer with an outdated +number of items (off by -1), because we cloned the extent buffer without +locking it first. + +However there is still another similar race, but in the opposite direction. +The cloned extent buffer has a number of items that does not match the +number of tree mod log operations that are going to be replayed. This is +because right after we got the last (most recent) tree mod log operation to +replay and before locking and cloning the extent buffer, another task adds +a new pointer to the extent buffer, which results in adding a new tree mod +log operation and incrementing the number of items in the extent buffer. +So after cloning we have mismatch between the number of items in the extent +buffer and the number of mod log operations we are going to apply to it. +This results in hitting a BUG_ON() that produces the following stack trace: + + ------------[ cut here ]------------ + kernel BUG at fs/btrfs/tree-mod-log.c:675! + invalid opcode: 0000 [#1] SMP KASAN PTI + CPU: 3 PID: 4811 Comm: crawl_1215 Tainted: G W 5.12.0-7d1efdf501f8-misc-next+ #99 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 + RIP: 0010:tree_mod_log_rewind+0x3b1/0x3c0 + Code: 05 48 8d 74 10 (...) + RSP: 0018:ffffc90001027090 EFLAGS: 00010293 + RAX: 0000000000000000 RBX: ffff8880a8514600 RCX: ffffffffaa9e59b6 + RDX: 0000000000000007 RSI: dffffc0000000000 RDI: ffff8880a851462c + RBP: ffffc900010270e0 R08: 00000000000000c0 R09: ffffed1004333417 + R10: ffff88802199a0b7 R11: ffffed1004333416 R12: 000000000000000e + R13: ffff888135af8748 R14: ffff88818766ff00 R15: ffff8880a851462c + FS: 00007f29acf62700(0000) GS:ffff8881f2200000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f0e6013f718 CR3: 000000010d42e003 CR4: 0000000000170ee0 + Call Trace: + btrfs_get_old_root+0x16a/0x5c0 + ? lock_downgrade+0x400/0x400 + btrfs_search_old_slot+0x192/0x520 + ? btrfs_search_slot+0x1090/0x1090 + ? free_extent_buffer.part.61+0xd7/0x140 + ? free_extent_buffer+0x13/0x20 + resolve_indirect_refs+0x3e9/0xfc0 + ? lock_downgrade+0x400/0x400 + ? __kasan_check_read+0x11/0x20 + ? add_prelim_ref.part.11+0x150/0x150 + ? lock_downgrade+0x400/0x400 + ? __kasan_check_read+0x11/0x20 + ? lock_acquired+0xbb/0x620 + ? __kasan_check_write+0x14/0x20 + ? do_raw_spin_unlock+0xa8/0x140 + ? rb_insert_color+0x340/0x360 + ? prelim_ref_insert+0x12d/0x430 + find_parent_nodes+0x5c3/0x1830 + ? stack_trace_save+0x87/0xb0 + ? resolve_indirect_refs+0xfc0/0xfc0 + ? fs_reclaim_acquire+0x67/0xf0 + ? __kasan_check_read+0x11/0x20 + ? lockdep_hardirqs_on_prepare+0x210/0x210 + ? fs_reclaim_acquire+0x67/0xf0 + ? __kasan_check_read+0x11/0x20 + ? ___might_sleep+0x10f/0x1e0 + ? __kasan_kmalloc+0x9d/0xd0 + ? trace_hardirqs_on+0x55/0x120 + btrfs_find_all_roots_safe+0x142/0x1e0 + ? find_parent_nodes+0x1830/0x1830 + ? trace_hardirqs_on+0x55/0x120 + ? ulist_free+0x1f/0x30 + ? btrfs_inode_flags_to_xflags+0x50/0x50 + iterate_extent_inodes+0x20e/0x580 + ? tree_backref_for_extent+0x230/0x230 + ? release_extent_buffer+0x225/0x280 + ? read_extent_buffer+0xdd/0x110 + ? lock_downgrade+0x400/0x400 + ? __kasan_check_read+0x11/0x20 + ? lock_acquired+0xbb/0x620 + ? __kasan_check_write+0x14/0x20 + ? do_raw_spin_unlock+0xa8/0x140 + ? _raw_spin_unlock+0x22/0x30 + ? release_extent_buffer+0x225/0x280 + iterate_inodes_from_logical+0x129/0x170 + ? iterate_inodes_from_logical+0x129/0x170 + ? btrfs_inode_flags_to_xflags+0x50/0x50 + ? iterate_extent_inodes+0x580/0x580 + ? __vmalloc_node+0x92/0xb0 + ? init_data_container+0x34/0xb0 + ? init_data_container+0x34/0xb0 + ? kvmalloc_node+0x60/0x80 + btrfs_ioctl_logical_to_ino+0x158/0x230 + btrfs_ioctl+0x2038/0x4360 + ? __kasan_check_write+0x14/0x20 + ? mmput+0x3b/0x220 + ? btrfs_ioctl_get_supported_features+0x30/0x30 + ? __kasan_check_read+0x11/0x20 + ? __kasan_check_read+0x11/0x20 + ? lock_release+0xc8/0x650 + ? __might_fault+0x64/0xd0 + ? __kasan_check_read+0x11/0x20 + ? lock_downgrade+0x400/0x400 + ? lockdep_hardirqs_on_prepare+0x210/0x210 + ? lockdep_hardirqs_on_prepare+0x13/0x210 + ? _raw_spin_unlock_irqrestore+0x51/0x63 + ? __kasan_check_read+0x11/0x20 + ? do_vfs_ioctl+0xfc/0x9d0 + ? ioctl_file_clone+0xe0/0xe0 + ? lock_downgrade+0x400/0x400 + ? lockdep_hardirqs_on_prepare+0x210/0x210 + ? __kasan_check_read+0x11/0x20 + ? lock_release+0xc8/0x650 + ? __task_pid_nr_ns+0xd3/0x250 + ? __kasan_check_read+0x11/0x20 + ? __fget_files+0x160/0x230 + ? __fget_light+0xf2/0x110 + __x64_sys_ioctl+0xc3/0x100 + do_syscall_64+0x37/0x80 + entry_SYSCALL_64_after_hwframe+0x44/0xae + RIP: 0033:0x7f29ae85b427 + Code: 00 00 90 48 8b (...) + RSP: 002b:00007f29acf5fcf8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 + RAX: ffffffffffffffda RBX: 00007f29acf5ff40 RCX: 00007f29ae85b427 + RDX: 00007f29acf5ff48 RSI: 00000000c038943b RDI: 0000000000000003 + RBP: 0000000001000000 R08: 0000000000000000 R09: 00007f29acf60120 + R10: 00005640d5fc7b00 R11: 0000000000000246 R12: 0000000000000003 + R13: 00007f29acf5ff48 R14: 00007f29acf5ff40 R15: 00007f29acf5fef8 + Modules linked in: + ---[ end trace 85e5fce078dfbe04 ]--- + + (gdb) l *(tree_mod_log_rewind+0x3b1) + 0xffffffff819e5b21 is in tree_mod_log_rewind (fs/btrfs/tree-mod-log.c:675). + 670 * the modification. As we're going backwards, we do the + 671 * opposite of each operation here. + 672 */ + 673 switch (tm->op) { + 674 case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING: + 675 BUG_ON(tm->slot < n); + 676 fallthrough; + 677 case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING: + 678 case BTRFS_MOD_LOG_KEY_REMOVE: + 679 btrfs_set_node_key(eb, &tm->key, tm->slot); + (gdb) quit + +The following steps explain in more detail how it happens: + +1) We have one tree mod log user (through fiemap or the logical ino ioctl), + with a sequence number of 1, so we have fs_info->tree_mod_seq == 1. + This is task A; + +2) Another task is at ctree.c:balance_level() and we have eb X currently as + the root of the tree, and we promote its single child, eb Y, as the new + root. + + Then, at ctree.c:balance_level(), we call: + + ret = btrfs_tree_mod_log_insert_root(root->node, child, true); + +3) At btrfs_tree_mod_log_insert_root() we create a tree mod log operation + of type BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING, with a ->logical field + pointing to ebX->start. We only have one item in eb X, so we create + only one tree mod log operation, and store in the "tm_list" array; + +4) Then, still at btrfs_tree_mod_log_insert_root(), we create a tree mod + log element of operation type BTRFS_MOD_LOG_ROOT_REPLACE, ->logical set + to ebY->start, ->old_root.logical set to ebX->start, ->old_root.level + set to the level of eb X and ->generation set to the generation of eb X; + +5) Then btrfs_tree_mod_log_insert_root() calls tree_mod_log_free_eb() with + "tm_list" as argument. After that, tree_mod_log_free_eb() calls + tree_mod_log_insert(). This inserts the mod log operation of type + BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING from step 3 into the rbtree + with a sequence number of 2 (and fs_info->tree_mod_seq set to 2); + +6) Then, after inserting the "tm_list" single element into the tree mod + log rbtree, the BTRFS_MOD_LOG_ROOT_REPLACE element is inserted, which + gets the sequence number 3 (and fs_info->tree_mod_seq set to 3); + +7) Back to ctree.c:balance_level(), we free eb X by calling + btrfs_free_tree_block() on it. Because eb X was created in the current + transaction, has no other references and writeback did not happen for + it, we add it back to the free space cache/tree; + +8) Later some other task B allocates the metadata extent from eb X, since + it is marked as free space in the space cache/tree, and uses it as a + node for some other btree; + +9) The tree mod log user task calls btrfs_search_old_slot(), which calls + btrfs_get_old_root(), and finally that calls tree_mod_log_oldest_root() + with time_seq == 1 and eb_root == eb Y; + +10) The first iteration of the while loop finds the tree mod log element + with sequence number 3, for the logical address of eb Y and of type + BTRFS_MOD_LOG_ROOT_REPLACE; + +11) Because the operation type is BTRFS_MOD_LOG_ROOT_REPLACE, we don't + break out of the loop, and set root_logical to point to + tm->old_root.logical, which corresponds to the logical address of + eb X; + +12) On the next iteration of the while loop, the call to + tree_mod_log_search_oldest() returns the smallest tree mod log element + for the logical address of eb X, which has a sequence number of 2, an + operation type of BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING and + corresponds to the old slot 0 of eb X (eb X had only 1 item in it + before being freed at step 7); + +13) We then break out of the while loop and return the tree mod log + operation of type BTRFS_MOD_LOG_ROOT_REPLACE (eb Y), and not the one + for slot 0 of eb X, to btrfs_get_old_root(); + +14) At btrfs_get_old_root(), we process the BTRFS_MOD_LOG_ROOT_REPLACE + operation and set "logical" to the logical address of eb X, which was + the old root. We then call tree_mod_log_search() passing it the logical + address of eb X and time_seq == 1; + +15) But before calling tree_mod_log_search(), task B locks eb X, adds a + key to eb X, which results in adding a tree mod log operation of type + BTRFS_MOD_LOG_KEY_ADD, with a sequence number of 4, to the tree mod + log, and increments the number of items in eb X from 0 to 1. + Now fs_info->tree_mod_seq has a value of 4; + +16) Task A then calls tree_mod_log_search(), which returns the most recent + tree mod log operation for eb X, which is the one just added by task B + at the previous step, with a sequence number of 4, a type of + BTRFS_MOD_LOG_KEY_ADD and for slot 0; + +17) Before task A locks and clones eb X, task A adds another key to eb X, + which results in adding a new BTRFS_MOD_LOG_KEY_ADD mod log operation, + with a sequence number of 5, for slot 1 of eb X, increments the + number of items in eb X from 1 to 2, and unlocks eb X. + Now fs_info->tree_mod_seq has a value of 5; + +18) Task A then locks eb X and clones it. The clone has a value of 2 for + the number of items and the pointer "tm" points to the tree mod log + operation with sequence number 4, not the most recent one with a + sequence number of 5, so there is mismatch between the number of + mod log operations that are going to be applied to the cloned version + of eb X and the number of items in the clone; + +19) Task A then calls tree_mod_log_rewind() with the clone of eb X, the + tree mod log operation with sequence number 4 and a type of + BTRFS_MOD_LOG_KEY_ADD, and time_seq == 1; + +20) At tree_mod_log_rewind(), we set the local variable "n" with a value + of 2, which is the number of items in the clone of eb X. + + Then in the first iteration of the while loop, we process the mod log + operation with sequence number 4, which is targeted at slot 0 and has + a type of BTRFS_MOD_LOG_KEY_ADD. This results in decrementing "n" from + 2 to 1. + + Then we pick the next tree mod log operation for eb X, which is the + tree mod log operation with a sequence number of 2, a type of + BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING and for slot 0, it is the one + added in step 5 to the tree mod log tree. + + We go back to the top of the loop to process this mod log operation, + and because its slot is 0 and "n" has a value of 1, we hit the BUG_ON: + + (...) + switch (tm->op) { + case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING: + BUG_ON(tm->slot < n); + fallthrough; + (...) + +Fix this by checking for a more recent tree mod log operation after locking +and cloning the extent buffer of the old root node, and use it as the first +operation to apply to the cloned extent buffer when rewinding it. + +Stable backport notes: due to moved code and renames, in =< 5.11 the +change should be applied to ctree.c:get_old_root. + +Reported-by: Zygo Blaxell +Link: https://lore.kernel.org/linux-btrfs/20210404040732.GZ32440@hungrycats.org/ +Fixes: 834328a8493079 ("Btrfs: tree mod log's old roots could still be part of the tree") +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +--- + fs/btrfs/ctree.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 3c9da1aec..8780a7432 100755 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1384,10 +1384,30 @@ get_old_root(struct btrfs_root *root, u64 time_seq) + "failed to read tree block %llu from get_old_root", + logical); + } else { ++ struct tree_mod_elem *tm2; ++ + btrfs_tree_read_lock(old); + eb = btrfs_clone_extent_buffer(old); ++ /* ++ * After the lookup for the most recent tree mod operation ++ * above and before we locked and cloned the extent buffer ++ * 'old', a new tree mod log operation may have been added. ++ * So lookup for a more recent one to make sure the number ++ * of mod log operations we replay is consistent with the ++ * number of items we have in the cloned extent buffer, ++ * otherwise we can hit a BUG_ON when rewinding the extent ++ * buffer. ++ */ ++ tm2 = tree_mod_log_search(fs_info, logical, time_seq); + btrfs_tree_read_unlock(old); + free_extent_buffer(old); ++ ASSERT(tm2); ++ ASSERT(tm2 == tm || tm2->seq > tm->seq); ++ if (!tm2 || tm2->seq < tm->seq) { ++ free_extent_buffer(eb); ++ return NULL; ++ } ++ tm = tm2; + } + } else if (old_root) { + eb_root_owner = btrfs_header_owner(eb_root); +-- +2.26.2 + diff --git a/patches.suse/edac-amd64-fix-pci-component-registration.patch b/patches.suse/edac-amd64-fix-pci-component-registration.patch index 1831417..102a4ab 100644 --- a/patches.suse/edac-amd64-fix-pci-component-registration.patch +++ b/patches.suse/edac-amd64-fix-pci-component-registration.patch @@ -37,9 +37,9 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c -@@ -21,6 +21,9 @@ static struct ecc_settings **ecc_stngs; - /* Number of Unified Memory Controllers */ - static u8 num_umcs; +@@ -20,6 +20,9 @@ static struct amd64_family_type *fam_typ + /* Per-node stuff */ + static struct ecc_settings **ecc_stngs; +/* Device for the PCI component */ +static struct device *pci_ctl_dev; @@ -47,7 +47,7 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de /* * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- -@@ -2589,6 +2592,9 @@ reserve_mc_sibling_devs(struct amd64_pvt +@@ -2664,6 +2667,9 @@ reserve_mc_sibling_devs(struct amd64_pvt return -ENODEV; } @@ -57,7 +57,7 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de edac_dbg(1, "F0: %s\n", pci_name(pvt->F0)); edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); edac_dbg(1, "F6: %s\n", pci_name(pvt->F6)); -@@ -2613,6 +2619,9 @@ reserve_mc_sibling_devs(struct amd64_pvt +@@ -2688,6 +2694,9 @@ reserve_mc_sibling_devs(struct amd64_pvt return -ENODEV; } @@ -67,7 +67,7 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de edac_dbg(1, "F1: %s\n", pci_name(pvt->F1)); edac_dbg(1, "F2: %s\n", pci_name(pvt->F2)); edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); -@@ -3484,21 +3493,10 @@ static void remove_one_instance(unsigned +@@ -3590,21 +3599,10 @@ static void remove_one_instance(unsigned static void setup_pci_device(void) { @@ -90,7 +90,7 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de if (!pci_ctl) { pr_warn("%s(): Unable to create PCI control\n", __func__); pr_warn("%s(): PCI error report via EDAC not set\n", __func__); -@@ -3581,6 +3579,8 @@ static int __init amd64_edac_init(void) +@@ -3686,6 +3684,8 @@ static int __init amd64_edac_init(void) return 0; err_pci: @@ -99,7 +99,7 @@ Link: https://lkml.kernel.org/r/20201122150815.13808-1-bp@alien8.de msrs_free(msrs); msrs = NULL; -@@ -3612,6 +3612,8 @@ static void __exit amd64_edac_exit(void) +@@ -3717,6 +3717,8 @@ static void __exit amd64_edac_exit(void) kfree(ecc_stngs); ecc_stngs = NULL; diff --git a/patches.suse/edac-amd64-gather-hardware-information-early.patch b/patches.suse/edac-amd64-gather-hardware-information-early.patch new file mode 100644 index 0000000..e77b3d4 --- /dev/null +++ b/patches.suse/edac-amd64-gather-hardware-information-early.patch @@ -0,0 +1,227 @@ +From: Yazen Ghannam +Date: Tue, 22 Oct 2019 20:35:10 +0000 +Subject: EDAC/amd64: Gather hardware information early +Git-commit: 80355a3b2db9d0b713af5169e2cdd7f8fbfdad82 +Patch-mainline: v5.5-rc1 +References: bsc#1180552 + +Split out gathering hardware information from init_one_instance() +into a separate function hw_info_get(). This is necessary so that +the information can be cached earlier and used to check if memory is +populated and if ECC is enabled on a node. + +Also, define a function hw_info_put() to back out changes made in +hw_info_get(). + +Check for an allocated PCI device (Function 0 for Family 17h or Function +1 for pre-Family 17h) before freeing, since hw_info_put() may be called +before PCI siblings are reserved. + +Drop the family check when freeing pvt->umc. This will be NULL on +pre-Family 17h systems. However, kfree() is safe and will check for a +NULL pointer before freeing. + +Signed-off-by: Yazen Ghannam +Signed-off-by: Borislav Petkov +Cc: "linux-edac@vger.kernel.org" +Cc: James Morse +Cc: Mauro Carvalho Chehab +Cc: Robert Richter +Cc: Tony Luck +Link: https://lkml.kernel.org/r/20191106012448.243970-3-Yazen.Ghannam@amd.com +--- + drivers/edac/amd64_edac.c | 101 +++++++++++++++++++++++----------------------- + 1 file changed, 51 insertions(+), 50 deletions(-) + +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 83c659e38084..6e1c739b7fad 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -3418,34 +3418,15 @@ static void compute_num_umcs(void) + edac_dbg(1, "Number of UMCs: %x", num_umcs); + } + +-static int init_one_instance(unsigned int nid) ++static int hw_info_get(struct amd64_pvt *pvt) + { +- struct pci_dev *F3 = node_to_amd_nb(nid)->misc; +- struct mem_ctl_info *mci = NULL; +- struct edac_mc_layer layers[2]; +- struct amd64_pvt *pvt = NULL; + u16 pci_id1, pci_id2; +- int err = 0, ret; +- +- ret = -ENOMEM; +- pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); +- if (!pvt) +- goto err_ret; +- +- pvt->mc_node_id = nid; +- pvt->F3 = F3; +- +- ret = -EINVAL; +- fam_type = per_family_init(pvt); +- if (!fam_type) +- goto err_free; ++ int ret = -EINVAL; + + if (pvt->fam >= 0x17) { + pvt->umc = kcalloc(num_umcs, sizeof(struct amd64_umc), GFP_KERNEL); +- if (!pvt->umc) { +- ret = -ENOMEM; +- goto err_free; +- } ++ if (!pvt->umc) ++ return -ENOMEM; + + pci_id1 = fam_type->f0_id; + pci_id2 = fam_type->f6_id; +@@ -3454,21 +3435,37 @@ static int init_one_instance(unsigned int nid) + pci_id2 = fam_type->f2_id; + } + +- err = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); +- if (err) +- goto err_post_init; ++ ret = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); ++ if (ret) ++ return ret; + + read_mc_regs(pvt); + ++ return 0; ++} ++ ++static void hw_info_put(struct amd64_pvt *pvt) ++{ ++ if (pvt->F0 || pvt->F1) ++ free_mc_sibling_devs(pvt); ++ ++ kfree(pvt->umc); ++} ++ ++static int init_one_instance(struct amd64_pvt *pvt) ++{ ++ struct mem_ctl_info *mci = NULL; ++ struct edac_mc_layer layers[2]; ++ int ret = -EINVAL; ++ + /* + * We need to determine how many memory channels there are. Then use + * that information for calculating the size of the dynamic instance + * tables in the 'mci' structure. + */ +- ret = -EINVAL; + pvt->channel_count = pvt->ops->early_channel_count(pvt); + if (pvt->channel_count < 0) +- goto err_siblings; ++ return ret; + + ret = -ENOMEM; + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; +@@ -3490,9 +3487,9 @@ static int init_one_instance(unsigned int nid) + layers[1].size = 2; + layers[1].is_virt_csrow = false; + +- mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0); ++ mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0); + if (!mci) +- goto err_siblings; ++ return ret; + + mci->pvt_info = pvt; + mci->pdev = &pvt->F3->dev; +@@ -3505,31 +3502,17 @@ static int init_one_instance(unsigned int nid) + ret = -ENODEV; + if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) { + edac_dbg(1, "failed edac_mc_add_mc()\n"); +- goto err_add_mc; ++ edac_mc_free(mci); ++ return ret; + } + + return 0; +- +-err_add_mc: +- edac_mc_free(mci); +- +-err_siblings: +- free_mc_sibling_devs(pvt); +- +-err_post_init: +- if (pvt->fam >= 0x17) +- kfree(pvt->umc); +- +-err_free: +- kfree(pvt); +- +-err_ret: +- return ret; + } + + static int probe_one_instance(unsigned int nid) + { + struct pci_dev *F3 = node_to_amd_nb(nid)->misc; ++ struct amd64_pvt *pvt = NULL; + struct ecc_settings *s; + int ret; + +@@ -3540,6 +3523,21 @@ static int probe_one_instance(unsigned int nid) + + ecc_stngs[nid] = s; + ++ pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); ++ if (!pvt) ++ goto err_settings; ++ ++ pvt->mc_node_id = nid; ++ pvt->F3 = F3; ++ ++ fam_type = per_family_init(pvt); ++ if (!fam_type) ++ goto err_enable; ++ ++ ret = hw_info_get(pvt); ++ if (ret < 0) ++ goto err_enable; ++ + if (!ecc_enabled(F3, nid)) { + ret = 0; + +@@ -3556,7 +3554,7 @@ static int probe_one_instance(unsigned int nid) + goto err_enable; + } + +- ret = init_one_instance(nid); ++ ret = init_one_instance(pvt); + if (ret < 0) { + amd64_err("Error probing instance: %d\n", nid); + +@@ -3569,6 +3567,10 @@ static int probe_one_instance(unsigned int nid) + return ret; + + err_enable: ++ hw_info_put(pvt); ++ kfree(pvt); ++ ++err_settings: + kfree(s); + ecc_stngs[nid] = NULL; + +@@ -3595,14 +3597,13 @@ static void remove_one_instance(unsigned int nid) + + restore_ecc_error_reporting(s, nid, F3); + +- free_mc_sibling_devs(pvt); +- + kfree(ecc_stngs[nid]); + ecc_stngs[nid] = NULL; + + /* Free the EDAC CORE resources */ + mci->pvt_info = NULL; + ++ hw_info_put(pvt); + kfree(pvt); + edac_mc_free(mci); + } + diff --git a/patches.suse/edac-amd64-make-struct-amd64_family_type-global.patch b/patches.suse/edac-amd64-make-struct-amd64_family_type-global.patch new file mode 100644 index 0000000..2e567cd --- /dev/null +++ b/patches.suse/edac-amd64-make-struct-amd64_family_type-global.patch @@ -0,0 +1,78 @@ +From: Yazen Ghannam +Date: Tue, 22 Oct 2019 20:35:09 +0000 +Subject: EDAC/amd64: Make struct amd64_family_type global +Git-commit: 38ddd4d1574530e1447b6ad91d27225d0f7662fb +Patch-mainline: v5.5-rc1 +References: bsc#1180552 + +The struct amd64_family_type doesn't change between multiple nodes and +instances of the module, so make it global. + +Signed-off-by: Yazen Ghannam +Signed-off-by: Borislav Petkov +Cc: "linux-edac@vger.kernel.org" +Cc: James Morse +Cc: Mauro Carvalho Chehab +Cc: Robert Richter +Cc: Tony Luck +Link: https://lkml.kernel.org/r/20191106012448.243970-2-Yazen.Ghannam@amd.com +--- + drivers/edac/amd64_edac.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -15,6 +15,8 @@ module_param(ecc_enable_override, int, 0 + + static struct msr __percpu *msrs; + ++static struct amd64_family_type *fam_type; ++ + /* Per-node stuff */ + static struct ecc_settings **ecc_stngs; + +@@ -3268,8 +3270,7 @@ f17h_determine_edac_ctl_cap(struct mem_c + } + } + +-static void setup_mci_misc_attrs(struct mem_ctl_info *mci, +- struct amd64_family_type *fam) ++static void setup_mci_misc_attrs(struct mem_ctl_info *mci) + { + struct amd64_pvt *pvt = mci->pvt_info; + +@@ -3289,7 +3290,7 @@ static void setup_mci_misc_attrs(struct + mci->edac_cap = determine_edac_cap(pvt); + mci->mod_name = EDAC_MOD_STR; + mci->mod_ver = EDAC_AMD64_VERSION; +- mci->ctl_name = fam->ctl_name; ++ mci->ctl_name = fam_type->ctl_name; + mci->dev_name = pci_name(pvt->F3); + mci->ctl_page_to_phys = NULL; + +@@ -3303,8 +3304,6 @@ static void setup_mci_misc_attrs(struct + */ + static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) + { +- struct amd64_family_type *fam_type = NULL; +- + pvt->ext_model = boot_cpu_data.x86_model >> 4; + pvt->stepping = boot_cpu_data.x86_mask; + pvt->model = boot_cpu_data.x86_model; +@@ -3407,7 +3406,6 @@ static void compute_num_umcs(void) + static int init_one_instance(unsigned int nid) + { + struct pci_dev *F3 = node_to_amd_nb(nid)->misc; +- struct amd64_family_type *fam_type = NULL; + struct mem_ctl_info *mci = NULL; + struct edac_mc_layer layers[2]; + struct amd64_pvt *pvt = NULL; +@@ -3484,7 +3482,7 @@ static int init_one_instance(unsigned in + mci->pvt_info = pvt; + mci->pdev = &pvt->F3->dev; + +- setup_mci_misc_attrs(mci, fam_type); ++ setup_mci_misc_attrs(mci); + + if (init_csrows(mci)) + mci->edac_cap = EDAC_FLAG_NONE; diff --git a/patches.suse/edac-amd64-save-max-number-of-controllers-to-family-type.patch b/patches.suse/edac-amd64-save-max-number-of-controllers-to-family-type.patch new file mode 100644 index 0000000..8e8ec9e --- /dev/null +++ b/patches.suse/edac-amd64-save-max-number-of-controllers-to-family-type.patch @@ -0,0 +1,200 @@ +From: Yazen Ghannam +Date: Tue, 22 Oct 2019 20:35:11 +0000 +Subject: EDAC/amd64: Save max number of controllers to family type +Git-commit: 5e4c55276ae8758f5789722b384bb2ab3de3a24f +Patch-mainline: v5.5-rc1 +References: bsc#1180552 + +The maximum number of memory controllers is fixed within a family/model +group. In most cases, this has been fixed at 2, but some systems may +have up to 8. + +The struct amd64_family_type already contains family/model-specific +information, and this can be used rather than adding model checks to +various functions. + +Create a new field in struct amd64_family_type for max_mcs. +Set this when setting other family type information, and use this when +needing the maximum number of memory controllers possible for a system. + +Signed-off-by: Yazen Ghannam +Signed-off-by: Borislav Petkov +Cc: "linux-edac@vger.kernel.org" +Cc: James Morse +Cc: Mauro Carvalho Chehab +Cc: Robert Richter +Cc: Tony Luck +Link: https://lkml.kernel.org/r/20191106012448.243970-4-Yazen.Ghannam@amd.com +--- + drivers/edac/amd64_edac.c | 43 +++++++++++++------------------------------ + drivers/edac/amd64_edac.h | 2 ++ + 2 files changed, 15 insertions(+), 30 deletions(-) + +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -20,9 +20,6 @@ static struct amd64_family_type *fam_typ + /* Per-node stuff */ + static struct ecc_settings **ecc_stngs; + +-/* Number of Unified Memory Controllers */ +-static u8 num_umcs; +- + /* + * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing + * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- +@@ -455,7 +452,7 @@ static void get_cs_base_and_mask(struct + for (i = 0; i < pvt->csels[dct].m_cnt; i++) + + #define for_each_umc(i) \ +- for (i = 0; i < num_umcs; i++) ++ for (i = 0; i < fam_type->max_mcs; i++) + + /* + * @input_addr is an InputAddr associated with the node given by mci. Return the +@@ -2225,6 +2222,7 @@ static struct amd64_family_type family_t + .ctl_name = "K8", + .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, + .f2_id = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, ++ .max_mcs = 2, + .ops = { + .early_channel_count = k8_early_channel_count, + .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, +@@ -2235,6 +2233,7 @@ static struct amd64_family_type family_t + .ctl_name = "F10h", + .f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP, + .f2_id = PCI_DEVICE_ID_AMD_10H_NB_DRAM, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2245,6 +2244,7 @@ static struct amd64_family_type family_t + .ctl_name = "F15h", + .f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1, + .f2_id = PCI_DEVICE_ID_AMD_15H_NB_F2, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2255,6 +2255,7 @@ static struct amd64_family_type family_t + .ctl_name = "F15h_M30h", + .f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1, + .f2_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2265,6 +2266,7 @@ static struct amd64_family_type family_t + .ctl_name = "F15h_M60h", + .f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1, + .f2_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2275,6 +2277,7 @@ static struct amd64_family_type family_t + .ctl_name = "F16h", + .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, + .f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2285,6 +2288,7 @@ static struct amd64_family_type family_t + .ctl_name = "F16h_M30h", + .f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1, + .f2_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, +@@ -2295,6 +2299,7 @@ static struct amd64_family_type family_t + .ctl_name = "F17h", + .f0_id = PCI_DEVICE_ID_AMD_17H_DF_F0, + .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f17_early_channel_count, + .dbam_to_cs = f17_addr_mask_to_cs_size, +@@ -2304,6 +2309,7 @@ static struct amd64_family_type family_t + .ctl_name = "F17h_M10h", + .f0_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F0, + .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6, ++ .max_mcs = 2, + .ops = { + .early_channel_count = f17_early_channel_count, + .dbam_to_cs = f17_addr_mask_to_cs_size, +@@ -2313,6 +2319,7 @@ static struct amd64_family_type family_t + .ctl_name = "F17h_M30h", + .f0_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F0, + .f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6, ++ .max_mcs = 8, + .ops = { + .early_channel_count = f17_early_channel_count, + .dbam_to_cs = f17_addr_mask_to_cs_size, +@@ -3387,29 +3394,13 @@ static const struct attribute_group *amd + NULL + }; + +-/* Set the number of Unified Memory Controllers in the system. */ +-static void compute_num_umcs(void) +-{ +- u8 model = boot_cpu_data.x86_model; +- +- if (boot_cpu_data.x86 < 0x17) +- return; +- +- if (model >= 0x30 && model <= 0x3f) +- num_umcs = 8; +- else +- num_umcs = 2; +- +- edac_dbg(1, "Number of UMCs: %x", num_umcs); +-} +- + static int hw_info_get(struct amd64_pvt *pvt) + { + u16 pci_id1, pci_id2; + int ret = -EINVAL; + + if (pvt->fam >= 0x17) { +- pvt->umc = kcalloc(num_umcs, sizeof(struct amd64_umc), GFP_KERNEL); ++ pvt->umc = kcalloc(fam_type->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL); + if (!pvt->umc) + return -ENOMEM; + +@@ -3462,14 +3453,8 @@ static int init_one_instance(struct amd6 + * Always allocate two channels since we can have setups with DIMMs on + * only one channel. Also, this simplifies handling later for the price + * of a couple of KBs tops. +- * +- * On Fam17h+, the number of controllers may be greater than two. So set +- * the size equal to the maximum number of UMCs. + */ +- if (pvt->fam >= 0x17) +- layers[1].size = num_umcs; +- else +- layers[1].size = 2; ++ layers[1].size = fam_type->max_mcs; + layers[1].is_virt_csrow = false; + + mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0); +@@ -3654,8 +3639,6 @@ static int __init amd64_edac_init(void) + if (!msrs) + goto err_free; + +- compute_num_umcs(); +- + for (i = 0; i < amd_nb_num(); i++) { + err = probe_one_instance(i); + if (err) { +--- a/drivers/edac/amd64_edac.h ++++ b/drivers/edac/amd64_edac.h +@@ -476,6 +476,8 @@ struct low_ops { + struct amd64_family_type { + const char *ctl_name; + u16 f0_id, f1_id, f2_id, f6_id; ++ /* Maximum number of memory controllers per die/node. */ ++ u8 max_mcs; + struct low_ops ops; + }; + diff --git a/patches.suse/ipmi-watchdog-Stop-watchdog-timer-when-the-current-a.patch b/patches.suse/ipmi-watchdog-Stop-watchdog-timer-when-the-current-a.patch new file mode 100644 index 0000000..0d40a55 --- /dev/null +++ b/patches.suse/ipmi-watchdog-Stop-watchdog-timer-when-the-current-a.patch @@ -0,0 +1,76 @@ +From 2253042d86f57d90a621ac2513a7a7a13afcf809 Mon Sep 17 00:00:00 2001 +From: Petr Pavlu +Date: Thu, 13 May 2021 14:26:36 +0200 +Subject: [PATCH] ipmi/watchdog: Stop watchdog timer when the current action is + 'none' +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://github.com/cminyard/linux-ipmi.git +Git-commit: 2253042d86f57d90a621ac2513a7a7a13afcf809 +References: bsc#1184855 + +When an IPMI watchdog timer is being stopped in ipmi_close() or +ipmi_ioctl(WDIOS_DISABLECARD), the current watchdog action is updated to +WDOG_TIMEOUT_NONE and _ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB) is called +to install this action. The latter function ends up invoking +__ipmi_set_timeout() which makes the actual 'Set Watchdog Timer' IPMI +request. + +For IPMI 1.0, this operation results in fully stopping the watchdog timer. +For IPMI >= 1.5, function __ipmi_set_timeout() always specifies the "don't +stop" flag in the prepared 'Set Watchdog Timer' IPMI request. This causes +that the watchdog timer has its action correctly updated to 'none' but the +timer continues to run. A problem is that IPMI firmware can then still log +an expiration event when the configured timeout is reached, which is +unexpected because the watchdog timer was requested to be stopped. + +The patch fixes this problem by not setting the "don't stop" flag in +__ipmi_set_timeout() when the current action is WDOG_TIMEOUT_NONE which +results in stopping the watchdog timer. This makes the behaviour for +IPMI >= 1.5 consistent with IPMI 1.0. It also matches the logic in +__ipmi_heartbeat() which does not allow to reset the watchdog if the +current action is WDOG_TIMEOUT_NONE as that would start the timer. + +Signed-off-by: Petr Pavlu +Message-Id: <10a41bdc-9c99-089c-8d89-fa98ce5ea080@suse.com> +Cc: stable@vger.kernel.org +Signed-off-by: Corey Minyard +--- + drivers/char/ipmi/ipmi_watchdog.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c +index 32c334e34d55..e4ff3b50de7f 100644 +--- a/drivers/char/ipmi/ipmi_watchdog.c ++++ b/drivers/char/ipmi/ipmi_watchdog.c +@@ -371,16 +371,18 @@ static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, + data[0] = 0; + WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); + +- if ((ipmi_version_major > 1) +- || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) { +- /* This is an IPMI 1.5-only feature. */ +- data[0] |= WDOG_DONT_STOP_ON_SET; +- } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { +- /* +- * In ipmi 1.0, setting the timer stops the watchdog, we +- * need to start it back up again. +- */ +- hbnow = 1; ++ if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { ++ if ((ipmi_version_major > 1) || ++ ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) { ++ /* This is an IPMI 1.5-only feature. */ ++ data[0] |= WDOG_DONT_STOP_ON_SET; ++ } else { ++ /* ++ * In ipmi 1.0, setting the timer stops the watchdog, we ++ * need to start it back up again. ++ */ ++ hbnow = 1; ++ } + } + + data[1] = 0; +-- +2.26.2 + diff --git a/patches.suse/mac80211-add-fragment-cache-to-sta_info.patch b/patches.suse/mac80211-add-fragment-cache-to-sta_info.patch new file mode 100644 index 0000000..4bb675f --- /dev/null +++ b/patches.suse/mac80211-add-fragment-cache-to-sta_info.patch @@ -0,0 +1,324 @@ +From 3a11ce08c45b50d69c891d71760b7c5b92074709 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:47 +0200 +Subject: [PATCH] mac80211: add fragment cache to sta_info +Git-commit: 3a11ce08c45b50d69c891d71760b7c5b92074709 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185859 + +Prior patches protected against fragmentation cache attacks +by coloring keys, but this shows that it can lead to issues +when multiple stations use the same sequence number. Add a +fragment cache to struct sta_info (in addition to the one in +the interface) to separate fragments for different stations +properly. + +This then automatically clear most of the fragment cache when a +station disconnects (or reassociates) from an AP, or when client +interfaces disconnect from the network, etc. + +On the way, also fix the comment there since this brings us in line +with the recommendation in 802.11-2016 ("An AP should support ..."). +Additionally, remove a useless condition (since there's no problem +purging an already empty list). + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210511200110.fc35046b0d52.I1ef101e3784d13e8f6600d83de7ec9a3a45bcd52@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/ieee80211_i.h | 26 ++++---------------------- + net/mac80211/iface.c | 10 +++------- + net/mac80211/rx.c | 41 ++++++++++++++++++++++++++++++----------- + net/mac80211/sta_info.c | 5 +++++ + net/mac80211/sta_info.h | 31 +++++++++++++++++++++++++++++++ + 5 files changed, 73 insertions(+), 40 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -52,12 +52,6 @@ struct ieee80211_local; + #define IEEE80211_ENCRYPT_HEADROOM 8 + #define IEEE80211_ENCRYPT_TAILROOM 18 + +-/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent +- * reception of at least three fragmented frames. This limit can be increased +- * by changing this define, at the cost of slower frame reassembly and +- * increased memory use (about 2 kB of RAM per entry). */ +-#define IEEE80211_FRAGMENT_MAX 4 +- + /* power level hasn't been configured (or set to automatic) */ + #define IEEE80211_UNSET_POWER_LEVEL INT_MIN + +@@ -90,19 +84,6 @@ extern const u8 ieee80211_ac_to_qos_mask + + #define IEEE80211_MAX_NAN_INSTANCE_ID 255 + +-struct ieee80211_fragment_entry { +- struct sk_buff_head skb_list; +- unsigned long first_frag_time; +- u16 seq; +- u16 extra_len; +- u16 last_frag; +- u8 rx_queue; +- bool check_sequential_pn; /* needed for CCMP/GCMP */ +- u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ +- unsigned int key_color; +-}; +- +- + struct ieee80211_bss { + u32 device_ts_beacon, device_ts_presp; + +@@ -880,9 +861,7 @@ struct ieee80211_sub_if_data { + + char name[IFNAMSIZ]; + +- /* Fragment table for host-based reassembly */ +- struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; +- unsigned int fragment_next; ++ struct ieee80211_fragment_cache frags; + + /* TID bitmap for NoAck policy */ + u16 noack_map; +@@ -2167,4 +2146,7 @@ extern const struct ethtool_ops ieee8021 + #define debug_noinline + #endif + ++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache); ++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache); ++ + #endif /* IEEE80211_I_H */ +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -8,6 +8,7 @@ + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (c) 2016 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -1126,16 +1127,12 @@ static void ieee80211_set_multicast_list + */ + static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) + { +- int i; +- + /* free extra data */ + ieee80211_free_keys(sdata, false); + + ieee80211_debugfs_remove_netdev(sdata); + +- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) +- __skb_queue_purge(&sdata->fragments[i].skb_list); +- sdata->fragment_next = 0; ++ ieee80211_destroy_frag_cache(&sdata->frags); + + if (ieee80211_vif_is_mesh(&sdata->vif)) + ieee80211_mesh_teardown_sdata(sdata); +@@ -1860,8 +1857,7 @@ int ieee80211_if_add(struct ieee80211_lo + sdata->wdev.wiphy = local->hw.wiphy; + sdata->local = local; + +- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) +- skb_queue_head_init(&sdata->fragments[i].skb_list); ++ ieee80211_init_frag_cache(&sdata->frags); + + INIT_LIST_HEAD(&sdata->key_list); + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1904,19 +1904,34 @@ ieee80211_rx_h_decrypt(struct ieee80211_ + return result; + } + ++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cache->entries); i++) ++ skb_queue_head_init(&cache->entries[i].skb_list); ++} ++ ++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cache->entries); i++) ++ __skb_queue_purge(&cache->entries[i].skb_list); ++} ++ + static inline struct ieee80211_fragment_entry * +-ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, ++ieee80211_reassemble_add(struct ieee80211_fragment_cache *cache, + unsigned int frag, unsigned int seq, int rx_queue, + struct sk_buff **skb) + { + struct ieee80211_fragment_entry *entry; + +- entry = &sdata->fragments[sdata->fragment_next++]; +- if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX) +- sdata->fragment_next = 0; ++ entry = &cache->entries[cache->next++]; ++ if (cache->next >= IEEE80211_FRAGMENT_MAX) ++ cache->next = 0; + +- if (!skb_queue_empty(&entry->skb_list)) +- __skb_queue_purge(&entry->skb_list); ++ __skb_queue_purge(&entry->skb_list); + + __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */ + *skb = NULL; +@@ -1931,14 +1946,14 @@ ieee80211_reassemble_add(struct ieee8021 + } + + static inline struct ieee80211_fragment_entry * +-ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, ++ieee80211_reassemble_find(struct ieee80211_fragment_cache *cache, + unsigned int frag, unsigned int seq, + int rx_queue, struct ieee80211_hdr *hdr) + { + struct ieee80211_fragment_entry *entry; + int i, idx; + +- idx = sdata->fragment_next; ++ idx = cache->next; + for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { + struct ieee80211_hdr *f_hdr; + +@@ -1946,7 +1961,7 @@ ieee80211_reassemble_find(struct ieee802 + if (idx < 0) + idx = IEEE80211_FRAGMENT_MAX - 1; + +- entry = &sdata->fragments[idx]; ++ entry = &cache->entries[idx]; + if (skb_queue_empty(&entry->skb_list) || entry->seq != seq || + entry->rx_queue != rx_queue || + entry->last_frag + 1 != frag) +@@ -1986,6 +2001,7 @@ static bool requires_sequential_pn(struc + static ieee80211_rx_result debug_noinline + ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + { ++ struct ieee80211_fragment_cache *cache = &rx->sdata->frags; + struct ieee80211_hdr *hdr; + u16 sc; + __le16 fc; +@@ -2007,6 +2023,9 @@ ieee80211_rx_h_defragment(struct ieee802 + goto out_no_led; + } + ++ if (rx->sta) ++ cache = &rx->sta->frags; ++ + if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) + goto out; + +@@ -2025,7 +2044,7 @@ ieee80211_rx_h_defragment(struct ieee802 + + if (frag == 0) { + /* This is the first fragment of a new frame. */ +- entry = ieee80211_reassemble_add(rx->sdata, frag, seq, ++ entry = ieee80211_reassemble_add(cache, frag, seq, + rx->seqno_idx, &(rx->skb)); + if (requires_sequential_pn(rx, fc)) { + int queue = rx->security_idx; +@@ -2053,7 +2072,7 @@ ieee80211_rx_h_defragment(struct ieee802 + /* This is a fragment for a frame that should already be pending in + * fragment cache. Add this fragment to the end of the pending entry. + */ +- entry = ieee80211_reassemble_find(rx->sdata, frag, seq, ++ entry = ieee80211_reassemble_find(cache, frag, seq, + rx->seqno_idx, hdr); + if (!entry) { + I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -4,6 +4,7 @@ + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -347,6 +348,8 @@ struct sta_info *sta_info_alloc(struct i + + u64_stats_init(&sta->rx_stats.syncp); + ++ ieee80211_init_frag_cache(&sta->frags); ++ + sta->sta_state = IEEE80211_STA_NONE; + + /* Mark TID as unreserved */ +@@ -981,6 +984,8 @@ static void __sta_info_destroy_part2(str + rate_control_remove_sta_debugfs(sta); + ieee80211_sta_debugfs_remove(sta); + ++ ieee80211_destroy_frag_cache(&sta->frags); ++ + cleanup_single_sta(sta); + } + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -2,6 +2,7 @@ + * Copyright 2002-2005, Devicescape Software, Inc. + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2015-2017 Intel Deutschland GmbH ++ * Copyright(c) 2020-2021 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -412,6 +412,33 @@ struct ieee80211_sta_rx_stats { + }; + + /* ++ * IEEE 802.11-2016 (10.6 "Defragmentation") recommends support for "concurrent ++ * reception of at least one MSDU per access category per associated STA" ++ * on APs, or "at least one MSDU per access category" on other interface types. ++ * ++ * This limit can be increased by changing this define, at the cost of slower ++ * frame reassembly and increased memory use while fragments are pending. ++ */ ++#define IEEE80211_FRAGMENT_MAX 4 ++ ++struct ieee80211_fragment_entry { ++ struct sk_buff_head skb_list; ++ unsigned long first_frag_time; ++ u16 seq; ++ u16 extra_len; ++ u16 last_frag; ++ u8 rx_queue; ++ bool check_sequential_pn; /* needed for CCMP/GCMP */ ++ u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ ++ unsigned int key_color; ++}; ++ ++struct ieee80211_fragment_cache { ++ struct ieee80211_fragment_entry entries[IEEE80211_FRAGMENT_MAX]; ++ unsigned int next; ++}; ++ ++/* + * The bandwidth threshold below which the per-station CoDel parameters will be + * scaled to be more lenient (to prevent starvation of slow stations). This + * value will be scaled by the number of active stations when it is being +@@ -458,6 +486,7 @@ struct ieee80211_sta_rx_stats { + * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs + * this (by advertising the USES_RSS hw flag) + * @status_stats: TX status statistics ++ * @frags: fragment cache + */ + struct sta_info { + /* General information, mostly static */ +@@ -555,6 +584,8 @@ struct sta_info { + + struct cfg80211_chan_def tdls_chandef; + ++ struct ieee80211_fragment_cache frags; ++ + /* keep last! */ + struct ieee80211_sta sta; + }; diff --git a/patches.suse/mac80211-assure-all-fragments-are-encrypted.patch b/patches.suse/mac80211-assure-all-fragments-are-encrypted.patch new file mode 100644 index 0000000..7106066 --- /dev/null +++ b/patches.suse/mac80211-assure-all-fragments-are-encrypted.patch @@ -0,0 +1,84 @@ +From 965a7d72e798eb7af0aa67210e37cf7ecd1c9cad Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef +Date: Tue, 11 May 2021 20:02:42 +0200 +Subject: [PATCH] mac80211: assure all fragments are encrypted +Git-commit: 965a7d72e798eb7af0aa67210e37cf7ecd1c9cad +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-26147 bsc#1185863 bsc#1185859 + +Do not mix plaintext and encrypted fragments in protected Wi-Fi +networks. This fixes CVE-2020-26147. + +Previously, an attacker was able to first forward a legitimate encrypted +fragment towards a victim, followed by a plaintext fragment. The +encrypted and plaintext fragment would then be reassembled. For further +details see Section 6.3 and Appendix D in the paper "Fragment and Forge: +Breaking Wi-Fi Through Frame Aggregation and Fragmentation". + +Because of this change there are now two equivalent conditions in the +code to determine if a received fragment requires sequential PNs, so we +also move this test to a separate function to make the code easier to +maintain. + +Cc: stable@vger.kernel.org +Signed-off-by: Mathy Vanhoef +Link: https://lore.kernel.org/r/20210511200110.30c4394bb835.I5acfdb552cc1d20c339c262315950b3eac491397@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 62047e93e217..65fc674e27cc 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2194,6 +2194,16 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, + return NULL; + } + ++static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc) ++{ ++ return rx->key && ++ (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || ++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 || ++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP || ++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) && ++ ieee80211_has_protected(fc); ++} ++ + static ieee80211_rx_result debug_noinline + ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + { +@@ -2238,12 +2248,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + /* This is the first fragment of a new frame. */ + entry = ieee80211_reassemble_add(rx->sdata, frag, seq, + rx->seqno_idx, &(rx->skb)); +- if (rx->key && +- (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || +- rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 || +- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP || +- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) && +- ieee80211_has_protected(fc)) { ++ if (requires_sequential_pn(rx, fc)) { + int queue = rx->security_idx; + + /* Store CCMP/GCMP PN so that we can verify that the +@@ -2285,11 +2290,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; + int queue; + +- if (!rx->key || +- (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP && +- rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 && +- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP && +- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256)) ++ if (!requires_sequential_pn(rx, fc)) + return RX_DROP_UNUSABLE; + memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); + for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { +-- +2.26.2 + diff --git a/patches.suse/mac80211-check-defrag-PN-against-current-frame.patch b/patches.suse/mac80211-check-defrag-PN-against-current-frame.patch new file mode 100644 index 0000000..517eaa8 --- /dev/null +++ b/patches.suse/mac80211-check-defrag-PN-against-current-frame.patch @@ -0,0 +1,121 @@ +From bf30ca922a0c0176007e074b0acc77ed345e9990 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:48 +0200 +Subject: [PATCH] mac80211: check defrag PN against current frame +Git-commit: bf30ca922a0c0176007e074b0acc77ed345e9990 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185862 bsc#1185859 + +As pointed out by Mathy Vanhoef, we implement the RX PN check +on fragmented frames incorrectly - we check against the last +received PN prior to the new frame, rather than to the one in +this frame itself. + +Prior patches addressed the security issue here, but in order +to be able to reason better about the code, fix it to really +compare against the current frame's PN, not the last stored +one. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210511200110.bfbc340ff071.Id0b690e581da7d03d76df90bb0e3fd55930bc8a0@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/ieee80211_i.h | 11 +++++++++-- + net/mac80211/rx.c | 5 ++--- + net/mac80211/wpa.c | 13 +++++++++---- + 3 files changed, 20 insertions(+), 9 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -223,8 +223,15 @@ struct ieee80211_rx_data { + */ + int security_idx; + +- u32 tkip_iv32; +- u16 tkip_iv16; ++ union { ++ struct { ++ u32 iv32; ++ u16 iv16; ++ } tkip; ++ struct { ++ u8 pn[IEEE80211_CCMP_PN_LEN]; ++ } ccm_gcm; ++ }; + }; + + struct ieee80211_csa_settings { +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2087,7 +2087,6 @@ ieee80211_rx_h_defragment(struct ieee802 + if (entry->check_sequential_pn) { + int i; + u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; +- int queue; + + if (!requires_sequential_pn(rx, fc)) + return RX_DROP_UNUSABLE; +@@ -2102,8 +2101,8 @@ ieee80211_rx_h_defragment(struct ieee802 + if (pn[i]) + break; + } +- queue = rx->security_idx; +- rpn = rx->key->u.ccmp.rx_pn[queue]; ++ ++ rpn = rx->ccm_gcm.pn; + if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN)) + return RX_DROP_UNUSABLE; + memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -2,6 +2,7 @@ + * Copyright 2002-2004, Instant802 Networks, Inc. + * Copyright 2008, Jouni Malinen + * Copyright (C) 2016-2017 Intel Deutschland GmbH ++ * Copyright (C) 2020-2021 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -162,8 +163,8 @@ ieee80211_rx_h_michael_mic_verify(struct + + update_iv: + /* update IV in key information to be able to detect replays */ +- rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32; +- rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16; ++ rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip.iv32; ++ rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip.iv16; + + return RX_CONTINUE; + +@@ -289,8 +290,8 @@ ieee80211_crypto_tkip_decrypt(struct iee + key, skb->data + hdrlen, + skb->len - hdrlen, rx->sta->sta.addr, + hdr->addr1, hwaccel, rx->security_idx, +- &rx->tkip_iv32, +- &rx->tkip_iv16); ++ &rx->tkip.iv32, ++ &rx->tkip.iv16); + if (res != TKIP_DECRYPT_OK) + return RX_DROP_UNUSABLE; + +@@ -548,6 +549,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee + } + + memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); ++ if (unlikely(ieee80211_is_frag(hdr))) ++ memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN); + } + + /* Remove CCMP header and MIC */ +@@ -777,6 +780,8 @@ ieee80211_crypto_gcmp_decrypt(struct iee + } + + memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN); ++ if (unlikely(ieee80211_is_frag(hdr))) ++ memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN); + } + + /* Remove GCMP header and MIC */ diff --git a/patches.suse/mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch b/patches.suse/mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch new file mode 100644 index 0000000..e321ccb --- /dev/null +++ b/patches.suse/mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch @@ -0,0 +1,104 @@ +From a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:50 +0200 +Subject: [PATCH] mac80211: do not accept/forward invalid EAPOL frames +Git-commit: a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-26139 bsc#1186062 + +EAPOL frames are used for authentication and key management between the +AP and each individual STA associated in the BSS. Those frames are not +supposed to be sent by one associated STA to another associated STA +(either unicast for broadcast/multicast). + +Similarly, in 802.11 they're supposed to be sent to the authenticator +(AP) address. + +Since it is possible for unexpected EAPOL frames to result in misbehavior +in supplicant implementations, it is better for the AP to not allow such +cases to be forwarded to other clients either directly, or indirectly if +the AP interface is part of a bridge. + +Accept EAPOL (control port) frames only if they're transmitted to the +own address, or, due to interoperability concerns, to the PAE group +address. + +Disable forwarding of EAPOL (or well, the configured control port +protocol) frames back to wireless medium in all cases. Previously, these +frames were accepted from fully authenticated and authorized stations +and also from unauthenticated stations for one of the cases. + +Additionally, to avoid forwarding by the bridge, rewrite the PAE group +address case to the local MAC address. + +Cc: stable@vger.kernel.org +Co-developed-by: Jouni Malinen +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.cb327ed0cabe.Ib7dcffa2a31f0913d660de65ba3c8aca75b1d10f@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2409,13 +2409,13 @@ static bool ieee80211_frame_allowed(stru + struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; + + /* +- * Allow EAPOL frames to us/the PAE group address regardless +- * of whether the frame was encrypted or not. ++ * Allow EAPOL frames to us/the PAE group address regardless of ++ * whether the frame was encrypted or not, and always disallow ++ * all other destination addresses for them. + */ +- if (ehdr->h_proto == rx->sdata->control_port_protocol && +- (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || +- ether_addr_equal(ehdr->h_dest, pae_group_addr))) +- return true; ++ if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol)) ++ return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || ++ ether_addr_equal(ehdr->h_dest, pae_group_addr); + + if (ieee80211_802_1x_port_control(rx) || + ieee80211_drop_unencrypted(rx, fc)) +@@ -2439,8 +2439,28 @@ static void ieee80211_deliver_skb_to_loc + cfg80211_rx_control_port(dev, skb, noencrypt); + dev_kfree_skb(skb); + } else { ++ struct ethhdr *ehdr = (void *)skb_mac_header(skb); ++ + memset(skb->cb, 0, sizeof(skb->cb)); + ++ /* ++ * 802.1X over 802.11 requires that the authenticator address ++ * be used for EAPOL frames. However, 802.1X allows the use of ++ * the PAE group address instead. If the interface is part of ++ * a bridge and we pass the frame with the PAE group address, ++ * then the bridge will forward it to the network (even if the ++ * client was not associated yet), which isn't supposed to ++ * happen. ++ * To avoid that, rewrite the destination address to our own ++ * address, so that the authenticator (e.g. hostapd) will see ++ * the frame, but bridge won't forward it anywhere else. Note ++ * that due to earlier filtering, the only other address can ++ * be the PAE group address. ++ */ ++ if (unlikely(skb->protocol == sdata->control_port_protocol && ++ !ether_addr_equal(ehdr->h_dest, sdata->vif.addr))) ++ ether_addr_copy(ehdr->h_dest, sdata->vif.addr); ++ + /* deliver to local stack */ + if (rx->napi) + napi_gro_receive(rx->napi, skb); +@@ -2480,6 +2500,7 @@ ieee80211_deliver_skb(struct ieee80211_r + if ((sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && + !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && ++ ehdr->h_proto != rx->sdata->control_port_protocol && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { + if (is_multicast_ether_addr(ehdr->h_dest) && + ieee80211_vif_get_num_mcast_if(sdata) != 0) { diff --git a/patches.suse/mac80211-drop-A-MSDUs-on-old-ciphers.patch b/patches.suse/mac80211-drop-A-MSDUs-on-old-ciphers.patch new file mode 100644 index 0000000..f22572e --- /dev/null +++ b/patches.suse/mac80211-drop-A-MSDUs-on-old-ciphers.patch @@ -0,0 +1,63 @@ +From 270032a2a9c4535799736142e1e7c413ca7b836e Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:46 +0200 +Subject: [PATCH] mac80211: drop A-MSDUs on old ciphers +Git-commit: 270032a2a9c4535799736142e1e7c413ca7b836e +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185862 bsc#1185859 + +With old ciphers (WEP and TKIP) we shouldn't be using A-MSDUs +since A-MSDUs are only supported if we know that they are, and +the only practical way for that is HT support which doesn't +support old ciphers. + +However, we would normally accept them anyway. Since we check +the MMIC before deaggregating A-MSDUs, and the A-MSDU bit in +the QoS header is not protected in TKIP (or WEP), this enables +attacks similar to CVE-2020-24588. To prevent that, drop A-MSDUs +completely with old ciphers. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210511200110.076543300172.I548e6e71f1ee9cad4b9a37bf212ae7db723587aa@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -6,6 +6,7 @@ + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -2614,6 +2615,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + if (is_multicast_ether_addr(hdr->addr1)) + return RX_DROP_UNUSABLE; + ++ if (rx->key) { ++ /* ++ * We should not receive A-MSDUs on pre-HT connections, ++ * and HT connections cannot use old ciphers. Thus drop ++ * them, as in those cases we couldn't even have SPP ++ * A-MSDUs or such. ++ */ ++ switch (rx->key->conf.cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ case WLAN_CIPHER_SUITE_TKIP: ++ return RX_DROP_UNUSABLE; ++ default: ++ break; ++ } ++ } ++ + return __ieee80211_rx_h_amsdu(rx, 0); + } + diff --git a/patches.suse/mac80211-extend-protection-against-mixed-key-and-fra.patch b/patches.suse/mac80211-extend-protection-against-mixed-key-and-fra.patch new file mode 100644 index 0000000..4eea12a --- /dev/null +++ b/patches.suse/mac80211-extend-protection-against-mixed-key-and-fra.patch @@ -0,0 +1,82 @@ +From 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 11 May 2021 20:02:51 +0200 +Subject: [PATCH] mac80211: extend protection against mixed key and fragment cache attacks +Git-commit: 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24586 bsc#1185859 + +For some chips/drivers, e.g., QCA6174 with ath10k, the decryption is +done by the hardware, and the Protected bit in the Frame Control field +is cleared in the lower level driver before the frame is passed to +mac80211. In such cases, the condition for ieee80211_has_protected() is +not met in ieee80211_rx_h_defragment() of mac80211 and the new security +validation steps are not executed. + +Extend mac80211 to cover the case where the Protected bit has been +cleared, but the frame is indicated as having been decrypted by the +hardware. This extends protection against mixed key and fragment cache +attack for additional drivers/chips. This fixes CVE-2020-24586 and +CVE-2020-24587 for such cases. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 22a925899a9e..1bb43edd47b6 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2229,6 +2229,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + unsigned int frag, seq; + struct ieee80211_fragment_entry *entry; + struct sk_buff *skb; ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + + hdr = (struct ieee80211_hdr *)rx->skb->data; + fc = hdr->frame_control; +@@ -2287,7 +2288,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + sizeof(rx->key->u.gcmp.rx_pn[queue])); + BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != + IEEE80211_GCMP_PN_LEN); +- } else if (rx->key && ieee80211_has_protected(fc)) { ++ } else if (rx->key && ++ (ieee80211_has_protected(fc) || ++ (status->flag & RX_FLAG_DECRYPTED))) { + entry->is_protected = true; + entry->key_color = rx->key->color; + } +@@ -2332,13 +2335,19 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + return RX_DROP_UNUSABLE; + memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); + } else if (entry->is_protected && +- (!rx->key || !ieee80211_has_protected(fc) || ++ (!rx->key || ++ (!ieee80211_has_protected(fc) && ++ !(status->flag & RX_FLAG_DECRYPTED)) || + rx->key->color != entry->key_color)) { + /* Drop this as a mixed key or fragment cache attack, even + * if for TKIP Michael MIC should protect us, and WEP is a + * lost cause anyway. + */ + return RX_DROP_UNUSABLE; ++ } else if (entry->is_protected && rx->key && ++ entry->key_color != rx->key->color && ++ (status->flag & RX_FLAG_DECRYPTED)) { ++ return RX_DROP_UNUSABLE; + } + + skb_pull(rx->skb, ieee80211_hdrlen(fc)); +-- +2.26.2 + diff --git a/patches.suse/mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch b/patches.suse/mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch new file mode 100644 index 0000000..06280d8 --- /dev/null +++ b/patches.suse/mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch @@ -0,0 +1,80 @@ +From 7e44a0b597f04e67eee8cdcbe7ee706c6f5de38b Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:49 +0200 +Subject: [PATCH] mac80211: prevent attacks on TKIP/WEP as well +Git-commit: 7e44a0b597f04e67eee8cdcbe7ee706c6f5de38b +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24586 bsc#1185859 + +Similar to the issues fixed in previous patches, TKIP and WEP +should be protected even if for TKIP we have the Michael MIC +protecting it, and WEP is broken anyway. + +However, this also somewhat protects potential other algorithms +that drivers might implement. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210511200110.430e8c202313.Ia37e4e5b6b3eaab1a5ae050e015f6c92859dbe27@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/rx.c | 12 ++++++++++++ + net/mac80211/sta_info.h | 3 ++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index b619c47e1d12..4454ec47283f 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2274,6 +2274,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + * next fragment has a sequential PN value. + */ + entry->check_sequential_pn = true; ++ entry->is_protected = true; + entry->key_color = rx->key->color; + memcpy(entry->last_pn, + rx->key->u.ccmp.rx_pn[queue], +@@ -2286,6 +2287,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + sizeof(rx->key->u.gcmp.rx_pn[queue])); + BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != + IEEE80211_GCMP_PN_LEN); ++ } else if (rx->key && ieee80211_has_protected(fc)) { ++ entry->is_protected = true; ++ entry->key_color = rx->key->color; + } + return RX_QUEUED; + } +@@ -2327,6 +2331,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN)) + return RX_DROP_UNUSABLE; + memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); ++ } else if (entry->is_protected && ++ (!rx->key || !ieee80211_has_protected(fc) || ++ rx->key->color != entry->key_color)) { ++ /* Drop this as a mixed key or fragment cache attack, even ++ * if for TKIP Michael MIC should protect us, and WEP is a ++ * lost cause anyway. ++ */ ++ return RX_DROP_UNUSABLE; + } + + skb_pull(rx->skb, ieee80211_hdrlen(fc)); +diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h +index 5c56d29a619e..0333072ebd98 100644 +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -429,7 +429,8 @@ struct ieee80211_fragment_entry { + u16 extra_len; + u16 last_frag; + u8 rx_queue; +- bool check_sequential_pn; /* needed for CCMP/GCMP */ ++ u8 check_sequential_pn:1, /* needed for CCMP/GCMP */ ++ is_protected:1; + u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ + unsigned int key_color; + }; +-- +2.26.2 + diff --git a/patches.suse/mac80211-prevent-mixed-key-and-fragment-cache-attack.patch b/patches.suse/mac80211-prevent-mixed-key-and-fragment-cache-attack.patch new file mode 100644 index 0000000..fa58d73 --- /dev/null +++ b/patches.suse/mac80211-prevent-mixed-key-and-fragment-cache-attack.patch @@ -0,0 +1,100 @@ +From 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24 Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef +Date: Tue, 11 May 2021 20:02:43 +0200 +Subject: [PATCH] mac80211: prevent mixed key and fragment cache attacks +Git-commit: 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185862 bsc#1185859 + +Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment +cache attacks (CVE-2020-24586). This is accomplished by assigning a +unique color to every key (per interface) and using this to track which +key was used to decrypt a fragment. When reassembling frames, it is +now checked whether all fragments were decrypted using the same key. + +To assure that fragment cache attacks are also prevented, the ID that is +assigned to keys is unique even over (re)associations and (re)connects. +This means fragments separated by a (re)association or (re)connect will +not be reassembled. Because mac80211 now also prevents the reassembly of +mixed encrypted and plaintext fragments, all cache attacks are prevented. + +Cc: stable@vger.kernel.org +Signed-off-by: Mathy Vanhoef +Link: https://lore.kernel.org/r/20210511200110.3f8290e59823.I622a67769ed39257327a362cfc09c812320eb979@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + net/mac80211/ieee80211_i.h | 1 + + net/mac80211/key.c | 7 +++++++ + net/mac80211/key.h | 2 ++ + net/mac80211/rx.c | 6 ++++++ + 4 files changed, 16 insertions(+) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -99,6 +99,7 @@ struct ieee80211_fragment_entry { + u8 rx_queue; + bool check_sequential_pn; /* needed for CCMP/GCMP */ + u8 last_pn[6]; /* PN of the last fragment if CCMP was used */ ++ unsigned int key_color; + }; + + +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -647,6 +647,7 @@ int ieee80211_key_link(struct ieee80211_ + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta) + { ++ static atomic_t key_color = ATOMIC_INIT(0); + struct ieee80211_local *local = sdata->local; + struct ieee80211_key *old_key; + int idx = key->conf.keyidx; +@@ -682,6 +683,12 @@ int ieee80211_key_link(struct ieee80211_ + key->sdata = sdata; + key->sta = sta; + ++ /* ++ * Assign a unique ID to every key so we can easily prevent mixed ++ * key and fragment cache attacks. ++ */ ++ key->color = atomic_inc_return(&key_color); ++ + increment_tailroom_need_count(sdata); + + ieee80211_key_replace(sdata, sta, pairwise, old_key, key); +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -127,6 +127,8 @@ struct ieee80211_key { + } debugfs; + #endif + ++ unsigned int color; ++ + /* + * key config, must be last because it contains key + * material as variable length member +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2033,6 +2033,7 @@ ieee80211_rx_h_defragment(struct ieee802 + * next fragment has a sequential PN value. + */ + entry->check_sequential_pn = true; ++ entry->key_color = rx->key->color; + memcpy(entry->last_pn, + rx->key->u.ccmp.rx_pn[queue], + IEEE80211_CCMP_PN_LEN); +@@ -2070,6 +2071,11 @@ ieee80211_rx_h_defragment(struct ieee802 + + if (!requires_sequential_pn(rx, fc)) + return RX_DROP_UNUSABLE; ++ ++ /* Prevent mixed key and fragment cache attacks */ ++ if (entry->key_color != rx->key->color) ++ return RX_DROP_UNUSABLE; ++ + memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); + for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { + pn[i]++; diff --git a/patches.suse/mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch b/patches.suse/mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch new file mode 100644 index 0000000..3747d1a --- /dev/null +++ b/patches.suse/mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch @@ -0,0 +1,77 @@ +From a1d5ff5651ea592c67054233b14b30bf4452999c Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef +Date: Tue, 11 May 2021 20:02:44 +0200 +Subject: [PATCH] mac80211: properly handle A-MSDUs that start with an RFC 1042 header +Git-commit: a1d5ff5651ea592c67054233b14b30bf4452999c +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +Patch-mainline: Queued in subsystem maintainer repo +References: CVE-2020-24587 CVE-2020-24586 bsc#1185863 bsc#1185862 bsc#1185859 + +Properly parse A-MSDUs whose first 6 bytes happen to equal a rfc1042 +header. This can occur in practice when the destination MAC address +equals AA:AA:03:00:00:00. More importantly, this simplifies the next +patch to mitigate A-MSDU injection attacks. + +Cc: stable@vger.kernel.org +Signed-off-by: Mathy Vanhoef +Link: https://lore.kernel.org/r/20210511200110.0b2b886492f0.I23dd5d685fe16d3b0ec8106e8f01b59f499dffed@changeid +Signed-off-by: Johannes Berg +Acked-by: Takashi Iwai + +--- + include/net/cfg80211.h | 5 +++-- + net/mac80211/rx.c | 2 +- + net/wireless/util.c | 5 +++-- + 3 files changed, 7 insertions(+), 5 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4601,7 +4601,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s + */ + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype, +- u8 data_offset); ++ u8 data_offset, bool is_amsdu); + + /** + * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 +@@ -4613,7 +4613,7 @@ int ieee80211_data_to_8023_exthdr(struct + static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, + enum nl80211_iftype iftype) + { +- return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0); ++ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0, false); + } + + /** +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2557,7 +2557,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + if (ieee80211_data_to_8023_exthdr(skb, ðhdr, + rx->sdata->vif.addr, + rx->sdata->vif.type, +- data_offset)) ++ data_offset, true)) + return RX_DROP_UNUSABLE; + + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -421,7 +421,7 @@ EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen) + + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype, +- u8 data_offset) ++ u8 data_offset, bool is_amsdu) + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct { +@@ -509,7 +510,7 @@ int ieee80211_data_to_8023_exthdr(struct + skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)); + tmp.h_proto = payload.proto; + +- if (likely((ether_addr_equal(payload.hdr, rfc1042_header) && ++ if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) && + tmp.h_proto != htons(ETH_P_AARP) && + tmp.h_proto != htons(ETH_P_IPX)) || + ether_addr_equal(payload.hdr, bridge_tunnel_header))) diff --git a/patches.suse/msft-hv-2080-uio_hv_generic-add-missed-sysfs_remove_bin_file.patch b/patches.suse/msft-hv-2080-uio_hv_generic-add-missed-sysfs_remove_bin_file.patch new file mode 100644 index 0000000..231aa2f --- /dev/null +++ b/patches.suse/msft-hv-2080-uio_hv_generic-add-missed-sysfs_remove_bin_file.patch @@ -0,0 +1,30 @@ +From: Chuhong Yuan +Date: Thu, 7 May 2020 23:13:43 +0800 +Patch-mainline: v5.8-rc1 +References: git-fixes +Subject: uio_hv_generic: add missed sysfs_remove_bin_file +Git-commit: 7066c2f61ce49b131026fec68ed1c9b0d0d9a05a + +This driver calls sysfs_create_bin_file() in probe, but forgets to +call sysfs_remove_bin_file() in remove. +Add the missed call to fix it. + +Signed-off-by: Chuhong Yuan +Link: https://lore.kernel.org/r/20200507151343.792816-1-hslester96@gmail.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/uio/uio_hv_generic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c +--- a/drivers/uio/uio_hv_generic.c ++++ b/drivers/uio/uio_hv_generic.c +@@ -361,6 +361,7 @@ hv_uio_remove(struct hv_device *dev) + if (!pdata) + return 0; + ++ sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr); + uio_unregister_device(&pdata->info); + hv_uio_cleanup(dev, pdata); + hv_set_drvdata(dev, NULL); diff --git a/patches.suse/msft-hv-2197-uio-uio_hv_generic-use-devm_kzalloc-for-private-data.patch b/patches.suse/msft-hv-2197-uio-uio_hv_generic-use-devm_kzalloc-for-private-data.patch new file mode 100644 index 0000000..ba470ea --- /dev/null +++ b/patches.suse/msft-hv-2197-uio-uio_hv_generic-use-devm_kzalloc-for-private-data.patch @@ -0,0 +1,61 @@ +From: Alexandru Ardelean +Date: Thu, 19 Nov 2020 17:49:03 +0200 +Patch-mainline: v5.11-rc1 +References: git-fixes +Subject: uio: uio_hv_generic: use devm_kzalloc() for private data alloc +Git-commit: 74e71964b1a9ffd34fa4b6ec8f2fa13e7cf0ac7a + +This is a minor cleanup for the management of the private object of this +driver. The allocation can be tied to the life-time of the hv_device +object. +This cleans up a bit the exit & error paths, since the object doesn't need +to be explicitly free'd anymore. + +Signed-off-by: Alexandru Ardelean +Link: https://lore.kernel.org/r/20201119154903.82099-4-alexandru.ardelean@analog.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/uio/uio_hv_generic.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c +--- a/drivers/uio/uio_hv_generic.c ++++ b/drivers/uio/uio_hv_generic.c +@@ -247,14 +247,14 @@ hv_uio_probe(struct hv_device *dev, + return -ENOTSUPP; + } + +- pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); ++ pdata = devm_kzalloc(&dev->device, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = vmbus_alloc_ring(channel, HV_RING_SIZE * PAGE_SIZE, + HV_RING_SIZE * PAGE_SIZE); + if (ret) +- goto fail; ++ return ret; + + set_channel_read_mode(channel, HV_CALL_ISR); + +@@ -347,8 +347,6 @@ hv_uio_probe(struct hv_device *dev, + + fail_close: + hv_uio_cleanup(dev, pdata); +-fail: +- kfree(pdata); + + return ret; + } +@@ -364,10 +362,8 @@ hv_uio_remove(struct hv_device *dev) + sysfs_remove_bin_file(&dev->channel->kobj, &ring_buffer_bin_attr); + uio_unregister_device(&pdata->info); + hv_uio_cleanup(dev, pdata); +- hv_set_drvdata(dev, NULL); + + vmbus_free_ring(dev->channel); +- kfree(pdata); + return 0; + } + diff --git a/patches.suse/msft-hv-2305-Drivers-hv-vmbus-Use-after-free-in-__vmbus_open.patch b/patches.suse/msft-hv-2305-Drivers-hv-vmbus-Use-after-free-in-__vmbus_open.patch new file mode 100644 index 0000000..90dfcd6 --- /dev/null +++ b/patches.suse/msft-hv-2305-Drivers-hv-vmbus-Use-after-free-in-__vmbus_open.patch @@ -0,0 +1,34 @@ +From: Dan Carpenter +Date: Tue, 13 Apr 2021 13:50:04 +0300 +Patch-mainline: v5.13-rc1 +Subject: Drivers: hv: vmbus: Use after free in __vmbus_open() +Git-commit: 3e9bf43f7f7a46f21ec071cb47be92d0874c48da +References: git-fixes + +The "open_info" variable is added to the &vmbus_connection.chn_msg_list, +but the error handling frees "open_info" without removing it from the +list. This will result in a use after free. First remove it from the +list, and then free it. + +Fixes: 6f3d791f3006 ("Drivers: hv: vmbus: Fix rescind handling issues") +Signed-off-by: Dan Carpenter +Reviewed-by: Andrea Parri +Link: https://lore.kernel.org/r/YHV3XLCot6xBS44r@mwanda +Signed-off-by: Wei Liu +Acked-by: Olaf Hering +--- + drivers/hv/channel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -653,7 +653,7 @@ static int __vmbus_open(struct vmbus_channel *newchannel, + + if (newchannel->rescind) { + err = -ENODEV; +- goto error_free_info; ++ goto error_clean_msglist; + } + + err = vmbus_post_msg(open_msg, diff --git a/patches.suse/msft-hv-2310-Drivers-hv-vmbus-Initialize-unload_event-statically.patch b/patches.suse/msft-hv-2310-Drivers-hv-vmbus-Initialize-unload_event-statically.patch new file mode 100644 index 0000000..9f9e13b --- /dev/null +++ b/patches.suse/msft-hv-2310-Drivers-hv-vmbus-Initialize-unload_event-statically.patch @@ -0,0 +1,58 @@ +From: "Andrea Parri (Microsoft)" +Date: Tue, 20 Apr 2021 03:43:50 +0200 +Patch-mainline: v5.13-rc1 +Subject: Drivers: hv: vmbus: Initialize unload_event statically +Git-commit: 8c2d5e0640e53c14b6240e9bf1e32a2226e6e6ca +References: bsc#1185724 + +If a malicious or compromised Hyper-V sends a spurious message of type +CHANNELMSG_UNLOAD_RESPONSE, the function vmbus_unload_response() will +call complete() on an uninitialized event, and cause an oops. + +Reported-by: Michael Kelley +Signed-off-by: Andrea Parri (Microsoft) +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20210420014350.2002-1-parri.andrea@gmail.com +Signed-off-by: Wei Liu +Acked-by: Olaf Hering +--- + drivers/hv/channel_mgmt.c | 7 ++++++- + drivers/hv/connection.c | 2 ++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -826,6 +826,11 @@ static void vmbus_unload_response(struct vmbus_channel_message_header *hdr) + /* + * This is a global event; just wakeup the waiting thread. + * Once we successfully unload, we can cleanup the monitor state. ++ * ++ * NB. A malicious or compromised Hyper-V could send a spurious ++ * message of type CHANNELMSG_UNLOAD_RESPONSE, and trigger a call ++ * of the complete() below. Make sure that unload_event has been ++ * initialized by the time this complete() is executed. + */ + complete(&vmbus_connection.unload_event); + } +@@ -841,7 +846,7 @@ void vmbus_initiate_unload(bool crash) + if (vmbus_proto_version < VERSION_WIN8_1) + return; + +- init_completion(&vmbus_connection.unload_event); ++ reinit_completion(&vmbus_connection.unload_event); + memset(&hdr, 0, sizeof(struct vmbus_channel_message_header)); + hdr.msgtype = CHANNELMSG_UNLOAD; + vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header), +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -26,6 +26,8 @@ + + struct vmbus_connection vmbus_connection = { + .conn_state = DISCONNECTED, ++ .unload_event = COMPLETION_INITIALIZER( ++ vmbus_connection.unload_event), + .next_gpadl_handle = ATOMIC_INIT(0xE1E10), + }; + EXPORT_SYMBOL_GPL(vmbus_connection); diff --git a/patches.suse/msft-hv-2311-Drivers-hv-vmbus-Increase-wait-time-for-VMbus-unload.patch b/patches.suse/msft-hv-2311-Drivers-hv-vmbus-Increase-wait-time-for-VMbus-unload.patch new file mode 100644 index 0000000..5c21de3 --- /dev/null +++ b/patches.suse/msft-hv-2311-Drivers-hv-vmbus-Increase-wait-time-for-VMbus-unload.patch @@ -0,0 +1,92 @@ +From: Michael Kelley +Date: Mon, 19 Apr 2021 21:48:09 -0700 +Patch-mainline: v5.13-rc1 +Subject: Drivers: hv: vmbus: Increase wait time for VMbus unload +Git-commit: 77db0ec8b7764cb9b09b78066ebfd47b2c0c1909 +References: bsc#1185724 + +When running in Azure, disks may be connected to a Linux VM with +read/write caching enabled. If a VM panics and issues a VMbus +UNLOAD request to Hyper-V, the response is delayed until all dirty +data in the disk cache is flushed. In extreme cases, this flushing +can take 10's of seconds, depending on the disk speed and the amount +of dirty data. If kdump is configured for the VM, the current 10 second +timeout in vmbus_wait_for_unload() may be exceeded, and the UNLOAD +complete message may arrive well after the kdump kernel is already +running, causing problems. Note that no problem occurs if kdump is +not enabled because Hyper-V waits for the cache flush before doing +a reboot through the BIOS/UEFI code. + +Fix this problem by increasing the timeout in vmbus_wait_for_unload() +to 100 seconds. Also output periodic messages so that if anyone is +watching the serial console, they won't think the VM is completely +hung. + +Fixes: 911e1987efc8 ("Drivers: hv: vmbus: Add timeout to vmbus_wait_for_unload") +Signed-off-by: Michael Kelley +Reviewed-by: Vitaly Kuznetsov +Link: https://lore.kernel.org/r/1618894089-126662-1-git-send-email-mikelley@microsoft.com +Signed-off-by: Wei Liu +Acked-by: Olaf Hering +--- + drivers/hv/channel_mgmt.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -755,6 +755,12 @@ static void init_vp_index(struct vmbus_channel *channel) + free_cpumask_var(available_mask); + } + ++#define UNLOAD_DELAY_UNIT_MS 10 /* 10 milliseconds */ ++#define UNLOAD_WAIT_MS (100*1000) /* 100 seconds */ ++#define UNLOAD_WAIT_LOOPS (UNLOAD_WAIT_MS/UNLOAD_DELAY_UNIT_MS) ++#define UNLOAD_MSG_MS (5*1000) /* Every 5 seconds */ ++#define UNLOAD_MSG_LOOPS (UNLOAD_MSG_MS/UNLOAD_DELAY_UNIT_MS) ++ + static void vmbus_wait_for_unload(void) + { + int cpu; +@@ -772,12 +778,17 @@ static void vmbus_wait_for_unload(void) + * vmbus_connection.unload_event. If not, the last thing we can do is + * read message pages for all CPUs directly. + * +- * Wait no more than 10 seconds so that the panic path can't get +- * hung forever in case the response message isn't seen. ++ * Wait up to 100 seconds since an Azure host must writeback any dirty ++ * data in its disk cache before the VMbus UNLOAD request will ++ * complete. This flushing has been empirically observed to take up ++ * to 50 seconds in cases with a lot of dirty data, so allow additional ++ * leeway and for inaccuracies in mdelay(). But eventually time out so ++ * that the panic path can't get hung forever in case the response ++ * message isn't seen. + */ +- for (i = 0; i < 1000; i++) { ++ for (i = 1; i <= UNLOAD_WAIT_LOOPS; i++) { + if (completion_done(&vmbus_connection.unload_event)) +- break; ++ goto completed; + + for_each_online_cpu(cpu) { + struct hv_per_cpu_context *hv_cpu +@@ -800,9 +811,18 @@ static void vmbus_wait_for_unload(void) + vmbus_signal_eom(msg, message_type); + } + +- mdelay(10); ++ /* ++ * Give a notice periodically so someone watching the ++ * serial output won't think it is completely hung. ++ */ ++ if (!(i % UNLOAD_MSG_LOOPS)) ++ pr_notice("Waiting for VMBus UNLOAD to complete\n"); ++ ++ mdelay(UNLOAD_DELAY_UNIT_MS); + } ++ pr_err("Continuing even though VMBus UNLOAD did not complete\n"); + ++completed: + /* + * We're crashing and already got the UNLOAD_RESPONSE, cleanup all + * maybe-pending messages on all CPUs to be able to receive new diff --git a/patches.suse/msft-hv-2312-video-hyperv_fb-Add-ratelimit-on-error-message.patch b/patches.suse/msft-hv-2312-video-hyperv_fb-Add-ratelimit-on-error-message.patch new file mode 100644 index 0000000..ff4e9f2 --- /dev/null +++ b/patches.suse/msft-hv-2312-video-hyperv_fb-Add-ratelimit-on-error-message.patch @@ -0,0 +1,36 @@ +From: Michael Kelley +Date: Tue, 20 Apr 2021 08:44:19 -0700 +Patch-mainline: v5.13-rc1 +Subject: video: hyperv_fb: Add ratelimit on error message +Git-commit: aa5b7d11c7cb87c266d705b237368985e7171958 +References: bsc#1185724 + +Due to a full ring buffer, the driver may be unable to send updates to +the Hyper-V host. But outputing the error message can make the problem +worse because console output is also typically written to the frame +buffer. As a result, in some circumstances the error message is output +continuously. + +Break the cycle by rate limiting the error message. Also output +the error code for additional diagnosability. + +Signed-off-by: Michael Kelley +Link: https://lore.kernel.org/r/1618933459-10585-1-git-send-email-mikelley@microsoft.com +Signed-off-by: Wei Liu +Acked-by: Olaf Hering +--- + drivers/video/fbdev/hyperv_fb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c +--- a/drivers/video/fbdev/hyperv_fb.c ++++ b/drivers/video/fbdev/hyperv_fb.c +@@ -308,7 +308,7 @@ static inline int synthvid_send(struct hv_device *hdev, + VM_PKT_DATA_INBAND, 0); + + if (ret) +- pr_err("Unable to send packet via vmbus\n"); ++ pr_err_ratelimited("Unable to send packet via vmbus; error %d\n", ret); + + return ret; + } diff --git a/patches.suse/msft-hv-2316-uio_hv_generic-Fix-a-memory-leak-in-error-handling-p.patch b/patches.suse/msft-hv-2316-uio_hv_generic-Fix-a-memory-leak-in-error-handling-p.patch new file mode 100644 index 0000000..76ee174 --- /dev/null +++ b/patches.suse/msft-hv-2316-uio_hv_generic-Fix-a-memory-leak-in-error-handling-p.patch @@ -0,0 +1,50 @@ +From: Christophe JAILLET +Date: Sun, 9 May 2021 09:13:03 +0200 +Patch-mainline: v5.13-rc3 +References: git-fixes +Subject: uio_hv_generic: Fix a memory leak in error handling paths +Git-commit: 3ee098f96b8b6c1a98f7f97915f8873164e6af9d + +If 'vmbus_establish_gpadl()' fails, the (recv|send)_gpadl will not be +updated and 'hv_uio_cleanup()' in the error handling path will not be +able to free the corresponding buffer. + +In such a case, we need to free the buffer explicitly. + +Fixes: cdfa835c6e5e ("uio_hv_generic: defer opening vmbus until first use") +Cc: stable +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/4fdaff557deef6f0475d02ba7922ddbaa1ab08a6.1620544055.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/uio/uio_hv_generic.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c +--- a/drivers/uio/uio_hv_generic.c ++++ b/drivers/uio/uio_hv_generic.c +@@ -296,8 +296,10 @@ hv_uio_probe(struct hv_device *dev, + + ret = vmbus_establish_gpadl(channel, pdata->recv_buf, + RECV_BUFFER_SIZE, &pdata->recv_gpadl); +- if (ret) ++ if (ret) { ++ vfree(pdata->recv_buf); + goto fail_close; ++ } + + /* put Global Physical Address Label in name */ + snprintf(pdata->recv_name, sizeof(pdata->recv_name), +@@ -316,8 +318,10 @@ hv_uio_probe(struct hv_device *dev, + + ret = vmbus_establish_gpadl(channel, pdata->send_buf, + SEND_BUFFER_SIZE, &pdata->send_gpadl); +- if (ret) ++ if (ret) { ++ vfree(pdata->send_buf); + goto fail_close; ++ } + + snprintf(pdata->send_name, sizeof(pdata->send_name), + "send:%u", pdata->send_gpadl); diff --git a/patches.suse/msft-hv-2317-uio_hv_generic-Fix-another-memory-leak-in-error-hand.patch b/patches.suse/msft-hv-2317-uio_hv_generic-Fix-another-memory-leak-in-error-hand.patch new file mode 100644 index 0000000..e141e38 --- /dev/null +++ b/patches.suse/msft-hv-2317-uio_hv_generic-Fix-another-memory-leak-in-error-hand.patch @@ -0,0 +1,45 @@ +From: Christophe JAILLET +Date: Sun, 9 May 2021 09:13:12 +0200 +Patch-mainline: v5.13-rc3 +References: git-fixes +Subject: uio_hv_generic: Fix another memory leak in error handling paths +Git-commit: 0b0226be3a52dadd965644bc52a807961c2c26df + +Memory allocated by 'vmbus_alloc_ring()' at the beginning of the probe +function is never freed in the error handling path. + +Add the missing 'vmbus_free_ring()' call. + +Note that it is already freed in the .remove function. + +Fixes: cdfa835c6e5e ("uio_hv_generic: defer opening vmbus until first use") +Cc: stable +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/0d86027b8eeed8e6360bc3d52bcdb328ff9bdca1.1620544055.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +Acked-by: Olaf Hering +--- + drivers/uio/uio_hv_generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c +--- a/drivers/uio/uio_hv_generic.c ++++ b/drivers/uio/uio_hv_generic.c +@@ -291,7 +291,7 @@ hv_uio_probe(struct hv_device *dev, + pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE); + if (pdata->recv_buf == NULL) { + ret = -ENOMEM; +- goto fail_close; ++ goto fail_free_ring; + } + + ret = vmbus_establish_gpadl(channel, pdata->recv_buf, +@@ -351,6 +351,8 @@ hv_uio_probe(struct hv_device *dev, + + fail_close: + hv_uio_cleanup(dev, pdata); ++fail_free_ring: ++ vmbus_free_ring(dev->channel); + + return ret; + } diff --git a/patches.suse/net-nfc-fix-use-after-free-llcp_sock_bind-connect.patch b/patches.suse/net-nfc-fix-use-after-free-llcp_sock_bind-connect.patch new file mode 100644 index 0000000..9342d7e --- /dev/null +++ b/patches.suse/net-nfc-fix-use-after-free-llcp_sock_bind-connect.patch @@ -0,0 +1,73 @@ +From c61760e6940dd4039a7f5e84a6afc9cdbf4d82b6 Mon Sep 17 00:00:00 2001 +From: Or Cohen +Date: Tue, 4 May 2021 10:16:46 +0300 +Subject: [PATCH] net/nfc: fix use-after-free llcp_sock_bind/connect +Git-commit: c61760e6940dd4039a7f5e84a6afc9cdbf4d82b6 +Patch-mainline: v5.13-rc1 +References: CVE-2021-23134 bsc#1186060 + +Commits 8a4cd82d ("nfc: fix refcount leak in llcp_sock_connect()") +and c33b1cc62 ("nfc: fix refcount leak in llcp_sock_bind()") +fixed a refcount leak bug in bind/connect but introduced a +use-after-free if the same local is assigned to 2 different sockets. + +This can be triggered by the following simple program: + int sock1 = socket( AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP ); + int sock2 = socket( AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP ); + memset( &addr, 0, sizeof(struct sockaddr_nfc_llcp) ); + addr.sa_family = AF_NFC; + addr.nfc_protocol = NFC_PROTO_NFC_DEP; + bind( sock1, (struct sockaddr*) &addr, sizeof(struct sockaddr_nfc_llcp) ) + bind( sock2, (struct sockaddr*) &addr, sizeof(struct sockaddr_nfc_llcp) ) + close(sock1); + close(sock2); + +Fix this by assigning NULL to llcp_sock->local after calling +nfc_llcp_local_put. + +This addresses CVE-2021-23134. + +Reported-by: Or Cohen +Reported-by: Nadav Markus +Fixes: c33b1cc62 ("nfc: fix refcount leak in llcp_sock_bind()") +Signed-off-by: Or Cohen +Signed-off-by: David S. Miller +Acked-by: Takashi Iwai + +--- + net/nfc/llcp_sock.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -121,12 +121,14 @@ static int llcp_sock_bind(struct socket + GFP_KERNEL); + if (!llcp_sock->service_name) { + nfc_llcp_local_put(llcp_sock->local); ++ llcp_sock->local = NULL; + ret = -ENOMEM; + goto put_dev; + } + llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); + if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); ++ llcp_sock->local = NULL; + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; + ret = -EADDRINUSE; +@@ -722,6 +724,7 @@ static int llcp_sock_connect(struct sock + llcp_sock->ssap = nfc_llcp_get_local_ssap(local); + if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); ++ llcp_sock->local = NULL; + ret = -ENOMEM; + goto put_dev; + } +@@ -765,6 +768,7 @@ sock_unlink: + llcp_sock->service_name = NULL; + + nfc_llcp_local_put(llcp_sock->local); ++ llcp_sock->local = NULL; + + put_dev: + nfc_put_device(dev); diff --git a/patches.suse/netfilter-conntrack-add-new-sysctl-to-disable-RST-ch.patch b/patches.suse/netfilter-conntrack-add-new-sysctl-to-disable-RST-ch.patch new file mode 100644 index 0000000..9e91982 --- /dev/null +++ b/patches.suse/netfilter-conntrack-add-new-sysctl-to-disable-RST-ch.patch @@ -0,0 +1,108 @@ +From 3684346961e68b512591ca27c5422180054b2c73 Mon Sep 17 00:00:00 2001 +From: Ali Abdallah +Date: Fri, 28 May 2021 11:52:21 +0200 +Subject: [PATCH] netfilter: conntrack: add new sysctl to disable RST check +Patch-mainline: Not yet, submitted +References: bsc#1183947 bsc#1185950 + +This patch adds a new sysctl tcp_ignore_invalid_rst to disable marking +out of segments RSTs as INVALID. + +Signed-off-by: Ali Abdallah +Reviewed-by: Florian Westphal + +Acked-by: Ali Abdallah +--- + Documentation/networking/nf_conntrack-sysctl.txt | 6 ++++++ + include/net/netns/conntrack.h | 3 +++ + net/netfilter/nf_conntrack_proto_tcp.c | 14 +++++++++++++- + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/Documentation/networking/nf_conntrack-sysctl.txt b/Documentation/networking/nf_conntrack-sysctl.txt +index 497d66828..ae1f28f98 100644 +--- a/Documentation/networking/nf_conntrack-sysctl.txt ++++ b/Documentation/networking/nf_conntrack-sysctl.txt +@@ -114,6 +114,12 @@ nf_conntrack_tcp_be_liberal - BOOLEAN + Be conservative in what you do, be liberal in what you accept from others. + If it's non-zero, we mark only out of window RST segments as INVALID. + ++nf_conntrack_tcp_ignore_invalid_rst - BOOLEAN ++ - 0 - disabled (default) ++ - 1 - enabled ++ ++ If it's non-zero, we don't mark out of window RST segments as INVALID. ++ + nf_conntrack_tcp_loose - BOOLEAN + 0 - disabled + not 0 - enabled (default) +diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h +index 17724c62d..d78d2d088 100644 +--- a/include/net/netns/conntrack.h ++++ b/include/net/netns/conntrack.h +@@ -36,6 +36,9 @@ struct nf_tcp_net { + unsigned int tcp_loose; + unsigned int tcp_be_liberal; + unsigned int tcp_max_retrans; ++#ifndef __GENKSYMS__ ++ unsigned int tcp_ignore_invalid_rst; ++#endif + }; + + enum udp_conntrack { +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index d08e64776..751e551c4 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -38,6 +38,9 @@ + If it's non-zero, we mark only out of window RST segments as INVALID. */ + static int nf_ct_tcp_be_liberal __read_mostly = 0; + ++/* If it's non-zero, we turn off RST sequence number check */ ++static int nf_ct_tcp_ignore_invalid_rst __read_mostly = 0; ++ + /* If it is set to zero, we disable picking up already established + connections. */ + static int nf_ct_tcp_loose __read_mostly = 1; +@@ -1044,7 +1047,8 @@ static int tcp_packet(struct nf_conn *ct, + if (seq == 0 && !nf_conntrack_tcp_established(ct)) + break; + +- if (before(seq, ct->proto.tcp.seen[!dir].td_maxack)) { ++ if (before(seq, ct->proto.tcp.seen[!dir].td_maxack) && ++ !tn->tcp_ignore_invalid_rst) { + /* Invalid RST */ + spin_unlock_bh(&ct->lock); + nf_log_packet(net, pf, 0, skb, NULL, NULL, +@@ -1544,6 +1548,12 @@ static struct ctl_table tcp_sysctl_table[] = { + .mode = 0644, + .proc_handler = proc_dointvec, + }, ++ { ++ .procname = "nf_conntrack_tcp_ignore_invalid_rst", ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, + { } + }; + #endif /* CONFIG_SYSCTL */ +@@ -1574,6 +1584,7 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn, + pn->ctl_table[10].data = &tn->tcp_loose; + pn->ctl_table[11].data = &tn->tcp_be_liberal; + pn->ctl_table[12].data = &tn->tcp_max_retrans; ++ pn->ctl_table[13].data = &tn->tcp_ignore_invalid_rst; + #endif + return 0; + } +@@ -1592,6 +1603,7 @@ static int tcp_init_net(struct net *net, u_int16_t proto) + tn->tcp_loose = nf_ct_tcp_loose; + tn->tcp_be_liberal = nf_ct_tcp_be_liberal; + tn->tcp_max_retrans = nf_ct_tcp_max_retrans; ++ tn->tcp_ignore_invalid_rst = nf_ct_tcp_ignore_invalid_rst; + } + + return tcp_kmemdup_sysctl_table(pn, tn); +-- +2.26.2 + + diff --git a/patches.suse/netfilter-conntrack-avoid-misleading-invalid-in-log-.patch b/patches.suse/netfilter-conntrack-avoid-misleading-invalid-in-log-.patch new file mode 100644 index 0000000..7daf6ff --- /dev/null +++ b/patches.suse/netfilter-conntrack-avoid-misleading-invalid-in-log-.patch @@ -0,0 +1,40 @@ +From d9f8fbbdc0017d766dc278b6e9befaafff17fcb3 Mon Sep 17 00:00:00 2001 +From: Ali Abdallah +Date: Fri, 28 May 2021 08:37:38 +0200 +Subject: [PATCH] netfilter: conntrack: avoid misleading 'invalid' in log message +Patch-mainline: v5.12-rc3 +Git-commit: 07b5a76e18925a595bfef44531dbf2f397bb5507 +References: bsc#1183947 bsc#1185950 + +The packet is not flagged as invalid: conntrack will accept it and its +associated with the conntrack entry. + +This happens e.g. when receiving a retransmitted SYN in SYN_RECV state. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso + +Acked-by: Ali Abdallah +--- + net/netfilter/nf_conntrack_proto_tcp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 9758a7df..804ff7de 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -949,8 +949,9 @@ static int tcp_packet(struct nf_conn *ct, + spin_unlock_bh(&ct->lock); + if (LOG_INVALID(net, IPPROTO_TCP)) + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, +- "nf_ct_tcp: invalid packet ignored in " +- "state %s ", tcp_conntrack_names[old_state]); ++ "nf_ct_tcp: packet (index %d) in dir %d ignored, " ++ "state %s ", index, dir, ++ tcp_conntrack_names[old_state]); + return NF_ACCEPT; + case TCP_CONNTRACK_MAX: + /* Special case for SYN proxy: when the SYN to the server or +-- +2.26.2 + diff --git a/patches.suse/netfilter-conntrack-improve-RST-handling-when-tuple-.patch b/patches.suse/netfilter-conntrack-improve-RST-handling-when-tuple-.patch new file mode 100644 index 0000000..4301dd0 --- /dev/null +++ b/patches.suse/netfilter-conntrack-improve-RST-handling-when-tuple-.patch @@ -0,0 +1,122 @@ +From 2dd54ceb65466ddacb2468fe81bba54613b39b17 Mon Sep 17 00:00:00 2001 +From: Ali Abdallah +Date: Fri, 28 May 2021 09:23:42 +0200 +Subject: [PATCH] netfilter: conntrack: improve RST handling when tuple is + re-used +Patch-mainline: Not yet, submitted +References: bsc#1183947 bsc#1185950 + +If we receive a SYN packet in original direction on an existing +connection tracking entry, we let this SYN through because conntrack +might be out-of-sync. + +Conntrack gets back in sync when server responds with SYN/ACK and state +gets updated accordingly. + +However, if server replies with RST, this packet might be marked as +INVALID because td_maxack value reflects the *old* conntrack state +and not the state of the originator of the RST. + +Avoid td_maxack-based checks if previous packet was a SYN. + +Unfortunately that is not be enough: an out of order ACK in original +direction updates last_index, so we still end up marking valid RST. + +Thus disable the sequence check when we are not in established state and +the received RST has a sequence of 0. + +Because marking RSTs as invalid usually leads to unwanted timeouts, +also skip RST sequence checks if a conntrack entry is already closing. + +Such entries can already be evicted via GC in case the table is full. + +Co-developed-by: Florian Westphal +Signed-off-by: Florian Westphal +Signed-off-by: Ali Abdallah +--- + net/netfilter/nf_conntrack_proto_tcp.c | 53 +++++++++++++++++--------- + 1 file changed, 36 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 3d12d82a..d08e6477 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -810,6 +810,22 @@ static bool nf_conntrack_tcp_established(const struct nf_conn *ct) + test_bit(IPS_ASSURED_BIT, &ct->status); + } + ++static bool tcp_can_early_drop(const struct nf_conn *ct) ++{ ++ switch (ct->proto.tcp.state) { ++ case TCP_CONNTRACK_FIN_WAIT: ++ case TCP_CONNTRACK_LAST_ACK: ++ case TCP_CONNTRACK_TIME_WAIT: ++ case TCP_CONNTRACK_CLOSE: ++ case TCP_CONNTRACK_CLOSE_WAIT: ++ return true; ++ default: ++ break; ++ } ++ ++ return false; ++} ++ + /* Returns verdict for packet, or -1 for invalid. */ + static int tcp_packet(struct nf_conn *ct, + const struct sk_buff *skb, +@@ -1006,9 +1022,28 @@ static int tcp_packet(struct nf_conn *ct, + if (index != TCP_RST_SET) + break; + +- if (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) { ++ /* If we are closing, tuple might have been re-used already. ++ * last_index, last_ack, and all other ct fields used for ++ * sequence/window validation are outdated in that case. ++ * ++ * As the conntrack can already be expired by GC under pressure, ++ * just skip validation checks. ++ */ ++ if (tcp_can_early_drop(ct)) ++ goto in_window; ++ ++ /* td_maxack might be outdated if we let a SYN through earlier */ ++ if ((ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) && ++ ct->proto.tcp.last_index != TCP_SYN_SET) { + u32 seq = ntohl(th->seq); + ++ /* If we are not in established state and SEQ=0 this is most ++ * likely an answer to a SYN we let go through above (last_index ++ * can be updated due to out-of-order ACKs). ++ */ ++ if (seq == 0 && !nf_conntrack_tcp_established(ct)) ++ break; ++ + if (before(seq, ct->proto.tcp.seen[!dir].td_maxack)) { + /* Invalid RST */ + spin_unlock_bh(&ct->lock); +@@ -1202,22 +1237,6 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, + return true; + } + +-static bool tcp_can_early_drop(const struct nf_conn *ct) +-{ +- switch (ct->proto.tcp.state) { +- case TCP_CONNTRACK_FIN_WAIT: +- case TCP_CONNTRACK_LAST_ACK: +- case TCP_CONNTRACK_TIME_WAIT: +- case TCP_CONNTRACK_CLOSE: +- case TCP_CONNTRACK_CLOSE_WAIT: +- return true; +- default: +- break; +- } +- +- return false; +-} +- + #if IS_ENABLED(CONFIG_NF_CT_NETLINK) + + #include +-- +2.26.2 + diff --git a/patches.suse/netfilter-conntrack-tcp-only-close-if-RST-matches-ex.patch b/patches.suse/netfilter-conntrack-tcp-only-close-if-RST-matches-ex.patch new file mode 100644 index 0000000..681362a --- /dev/null +++ b/patches.suse/netfilter-conntrack-tcp-only-close-if-RST-matches-ex.patch @@ -0,0 +1,222 @@ +From d3b0ce4663733c7fd9482ff742a7133ed5c3e22e Mon Sep 17 00:00:00 2001 +From: Ali Abdallah +Date: Fri, 28 May 2021 09:03:25 +0200 +Patch-mainline: v5.1-rc1 +Git-commit: be0502a3f2e94211a8809a09ecbc3a017189b8fb +References: bsc#1183947 bsc#1185950 +Subject: [PATCH] netfilter: conntrack: tcp: only close if RST matches exact + sequence + +TCP resets cause instant transition from established to closed state +provided the reset is in-window. Endpoints that implement RFC 5961 +require resets to match the next expected sequence number. +RST segments that are in-window (but that do not match RCV.NXT) are +ignored, and a "challenge ACK" is sent back. + +Main problem for conntrack is that its a middlebox, i.e. whereas an end +host might have ACK'd SEQ (and would thus accept an RST with this +sequence number), conntrack might not have seen this ACK (yet). + +Therefore we can't simply flag RSTs with non-exact match as invalid. + +This updates RST processing as follows: + +1. If the connection is in a state other than ESTABLISHED, nothing is + changed, RST is subject to normal in-window check. + +2. If the RSTs sequence number either matches exactly RCV.NXT, + connection state moves to CLOSE. + +3. The same applies if the RST sequence number aligns with a previous + packet in the same direction. + +In all other cases, the connection remains in ESTABLISHED state. +If the normal-in-window check passes, the timeout will be lowered +to that of CLOSE. + +If the peer sends a challenge ack, connection timeout will be reset. + +If the challenge ACK triggers another RST (RST was valid after all), +this 2nd RST will match expected sequence and conntrack state changes to +CLOSE. + +If no challenge ACK is received, the connection will time out after +CLOSE seconds (10 seconds by default), just like without this patch. + +Packetdrill test case: + +0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0.000 bind(3, ..., ...) = 0 +0.000 listen(3, 1) = 0 + +0.100 < S 0:0(0) win 32792 +0.100 > S. 0:0(0) ack 1 win 64240 +0.200 < . 1:1(0) ack 1 win 257 +0.200 accept(3, ..., ...) = 4 + +// Receive a segment. +0.210 < P. 1:1001(1000) ack 1 win 46 +0.210 > . 1:1(0) ack 1001 + +// Application writes 1000 bytes. +0.250 write(4, ..., 1000) = 1000 +0.250 > P. 1:1001(1000) ack 1001 + +// First reset, old sequence. Conntrack (correctly) considers this +// invalid due to failed window validation (regardless of this patch). +0.260 < R 2:2(0) ack 1001 win 260 + +// 2nd reset, but too far ahead sequence. Same: correctly handled +// as invalid. +0.270 < R 99990001:99990001(0) ack 1001 win 260 + +// in-window, but not exact sequence. +// Current Linux kernels might reply with a challenge ack, and do not +// remove connection. +// Without this patch, conntrack state moves to CLOSE. +// With patch, timeout is lowered like CLOSE, but connection stays +// in ESTABLISHED state. +0.280 < R 1010:1010(0) ack 1001 win 260 + +// Expect challenge ACK +0.281 > . 1001:1001(0) ack 1001 win 501 + +// With or without this patch, RST will cause connection +// to move to CLOSE (sequence number matches) +// 0.282 < R 1001:1001(0) ack 1001 win 260 + +// ACK +0.300 < . 1001:1001(0) ack 1001 win 257 + +// more data could be exchanged here, connection +// is still established + +// Client closes the connection. +0.610 < F. 1001:1001(0) ack 1001 win 260 +0.650 > . 1001:1001(0) ack 1002 + +// Close the connection without reading outstanding data +0.700 close(4) = 0 + +// so one more reset. Will be deemed acceptable with patch as well: +// connection is already closing. +0.701 > R. 1001:1001(0) ack 1002 win 501 +// End packetdrill test case. + +With patch, this generates following conntrack events: + [NEW] 120 SYN_SENT src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 [UNREPLIED] +[UPDATE] 60 SYN_RECV src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 +[UPDATE] 432000 ESTABLISHED src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 [ASSURED] +[UPDATE] 120 FIN_WAIT src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 [ASSURED] +[UPDATE] 60 CLOSE_WAIT src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 [ASSURED] +[UPDATE] 10 CLOSE src=10.0.2.1 dst=10.0.0.1 sport=5437 dport=80 [ASSURED] + +Without patch, first RST moves connection to close, whereas socket state +does not change until FIN is received. + [NEW] 120 SYN_SENT src=10.0.2.1 dst=10.0.0.1 sport=5141 dport=80 [UNREPLIED] +[UPDATE] 60 SYN_RECV src=10.0.2.1 dst=10.0.0.1 sport=5141 dport=80 +[UPDATE] 432000 ESTABLISHED src=10.0.2.1 dst=10.0.0.1 sport=5141 dport=80 [ASSURED] +[UPDATE] 10 CLOSE src=10.0.2.1 dst=10.0.0.1 sport=5141 dport=80 [ASSURED] + +Cc: Jozsef Kadlecsik +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso + +[This patch is required to easily backport another important fix for +bsc#1183947 bsc#1185950] + +Acked-by: Ali Abdallah +--- + net/netfilter/nf_conntrack_proto_tcp.c | 52 ++++++++++++++++++++------ + 1 file changed, 41 insertions(+), 11 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c +index 804ff7de..3d12d82a 100644 +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -804,6 +804,12 @@ static unsigned int *tcp_get_timeouts(struct net *net) + return tcp_pernet(net)->timeouts; + } + ++static bool nf_conntrack_tcp_established(const struct nf_conn *ct) ++{ ++ return ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED && ++ test_bit(IPS_ASSURED_BIT, &ct->status); ++} ++ + /* Returns verdict for packet, or -1 for invalid. */ + static int tcp_packet(struct nf_conn *ct, + const struct sk_buff *skb, +@@ -997,18 +1003,40 @@ static int tcp_packet(struct nf_conn *ct, + } + break; + case TCP_CONNTRACK_CLOSE: +- if (index == TCP_RST_SET +- && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) +- && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) { +- /* Invalid RST */ +- spin_unlock_bh(&ct->lock); +- if (LOG_INVALID(net, IPPROTO_TCP)) ++ if (index != TCP_RST_SET) ++ break; ++ ++ if (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) { ++ u32 seq = ntohl(th->seq); ++ ++ if (before(seq, ct->proto.tcp.seen[!dir].td_maxack)) { ++ /* Invalid RST */ ++ spin_unlock_bh(&ct->lock); + nf_log_packet(net, pf, 0, skb, NULL, NULL, + NULL, "nf_ct_tcp: invalid RST "); +- return -NF_ACCEPT; +- } +- if (index == TCP_RST_SET +- && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) ++ return -NF_ACCEPT; ++ } ++ ++ if (!nf_conntrack_tcp_established(ct) || ++ seq == ct->proto.tcp.seen[!dir].td_maxack) ++ break; ++ ++ /* Check if rst is part of train, such as ++ * foo:80 > bar:4379: P, 235946583:235946602(19) ack 42 ++ * foo:80 > bar:4379: R, 235946602:235946602(0) ack 42 ++ */ ++ if (ct->proto.tcp.last_index == TCP_ACK_SET && ++ ct->proto.tcp.last_dir == dir && ++ seq == ct->proto.tcp.last_end) ++ break; ++ ++ /* ... RST sequence number doesn't match exactly, keep ++ * established state to allow a possible challenge ACK. ++ */ ++ new_state = old_state; ++ } ++ ++ if (((test_bit(IPS_SEEN_REPLY_BIT, &ct->status) + && ct->proto.tcp.last_index == TCP_SYN_SET) + || (!test_bit(IPS_ASSURED_BIT, &ct->status) + && ct->proto.tcp.last_index == TCP_ACK_SET)) +@@ -1024,7 +1052,7 @@ static int tcp_packet(struct nf_conn *ct, + * segments we ignored. */ + goto in_window; + } +- /* Just fall through */ ++ break; + default: + /* Keep compilers happy. */ + break; +@@ -1055,6 +1083,8 @@ static int tcp_packet(struct nf_conn *ct, + if (ct->proto.tcp.retrans >= tn->tcp_max_retrans && + timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS]) + timeout = timeouts[TCP_CONNTRACK_RETRANS]; ++ else if (unlikely(index == TCP_RST_SET)) ++ timeout = timeouts[TCP_CONNTRACK_CLOSE]; + else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) & + IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && + timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK]) +-- +2.26.2 + diff --git a/patches.suse/nvme-fc-clear-q_live-at-beginning-of-association-tea.patch b/patches.suse/nvme-fc-clear-q_live-at-beginning-of-association-tea.patch new file mode 100644 index 0000000..a9f915e --- /dev/null +++ b/patches.suse/nvme-fc-clear-q_live-at-beginning-of-association-tea.patch @@ -0,0 +1,59 @@ +From a7d139145a6640172516b193abf6d2398620aa14 Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Mon, 10 May 2021 21:56:35 -0700 +References: git-fixes +Git-commit: a7d139145a6640172516b193abf6d2398620aa14 +Patch-mainline: v5.13-rc3 +Subject: [PATCH] nvme-fc: clear q_live at beginning of association teardown + +The __nvmf_check_ready() routine used to bounce all filesystem io if the +controller state isn't LIVE. However, a later patch changed the logic so +that it rejection ends up being based on the Q live check. The FC +transport has a slightly different sequence from rdma and tcp for +shutting down queues/marking them non-live. FC marks its queue non-live +after aborting all ios and waiting for their termination, leaving a +rather large window for filesystem io to continue to hit the transport. +Unfortunately this resulted in filesystem I/O or applications seeing I/O +errors. + +Change the FC transport to mark the queues non-live at the first sign of +teardown for the association (when I/O is initially terminated). + +Fixes: 73a5379937ec ("nvme-fabrics: allow to queue requests for live queues") +Signed-off-by: James Smart +Reviewed-by: Sagi Grimberg +Reviewed-by: Himanshu Madhani +Reviewed-by: Hannes Reinecke +Signed-off-by: Christoph Hellwig +Acked-by: Enzo Matsumiya +--- + drivers/nvme/host/fc.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/nvme/host/fc.c ++++ b/drivers/nvme/host/fc.c +@@ -2790,6 +2790,7 @@ static void + nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) + { + unsigned long flags; ++ int q; + + if (!ctrl->assoc_active) + return; +@@ -2801,6 +2802,16 @@ nvme_fc_delete_association(struct nvme_f + spin_unlock_irqrestore(&ctrl->lock, flags); + + /* ++ * if aborting io, the queues are no longer good, mark them ++ * all as not live. ++ */ ++ if (ctrl->ctrl.queue_count > 1) { ++ for (q = 1; q < ctrl->ctrl.queue_count; q++) ++ clear_bit(NVME_FC_Q_LIVE, &ctrl->queues[q].flags); ++ } ++ clear_bit(NVME_FC_Q_LIVE, &ctrl->queues[0].flags); ++ ++ /* + * If io queues are present, stop them and terminate all outstanding + * ios on them. As FC allocates FC exchange for each io, the + * transport must contact the LLDD to terminate the exchange, diff --git a/patches.suse/powerpc-64-remove-start_tb-and-accum_tb-from-thread_.patch b/patches.suse/powerpc-64-remove-start_tb-and-accum_tb-from-thread_.patch new file mode 100644 index 0000000..9479a00 --- /dev/null +++ b/patches.suse/powerpc-64-remove-start_tb-and-accum_tb-from-thread_.patch @@ -0,0 +1,54 @@ +From 36d632ea831fd2fa3cb62599a465825f59076f64 Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Sat, 5 May 2018 03:19:29 +1000 +Subject: [PATCH] powerpc/64: remove start_tb and accum_tb from thread_struct + +References: bsc#1186487 ltc#177613 +Patch-mainline: v4.18-rc1 +Git-commit: 36d632ea831fd2fa3cb62599a465825f59076f64 + +These fields are only written to. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/processor.h | 4 ---- + arch/powerpc/kernel/process.c | 6 +----- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h +index c4b36a494a63..eff269adfa71 100644 +--- a/arch/powerpc/include/asm/processor.h ++++ b/arch/powerpc/include/asm/processor.h +@@ -264,10 +264,6 @@ struct thread_struct { + struct thread_fp_state *fp_save_area; + int fpexc_mode; /* floating-point exception mode */ + unsigned int align_ctl; /* alignment handling control */ +-#ifdef CONFIG_PPC64 +- unsigned long start_tb; /* Start purr when proc switched in */ +- unsigned long accum_tb; /* Total accumulated purr for process */ +-#endif + #ifdef CONFIG_HAVE_HW_BREAKPOINT + struct perf_event *ptrace_bps[HBP_NUM]; + /* +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index 25db000fa5b3..f4e5291584c5 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -1188,11 +1188,7 @@ struct task_struct *__switch_to(struct task_struct *prev, + */ + if (firmware_has_feature(FW_FEATURE_SPLPAR)) { + struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); +- long unsigned start_tb, current_tb; +- start_tb = old_thread->start_tb; +- cu->current_tb = current_tb = mfspr(SPRN_PURR); +- old_thread->accum_tb += (current_tb - start_tb); +- new_thread->start_tb = current_tb; ++ cu->current_tb = mfspr(SPRN_PURR); + } + #endif /* CONFIG_PPC64 */ + +-- +2.26.2 + diff --git a/patches.suse/powerpc-64s-Fix-crashes-when-toggling-entry-flush-ba.patch b/patches.suse/powerpc-64s-Fix-crashes-when-toggling-entry-flush-ba.patch index 2ee9bb1..f253b1c 100644 --- a/patches.suse/powerpc-64s-Fix-crashes-when-toggling-entry-flush-ba.patch +++ b/patches.suse/powerpc-64s-Fix-crashes-when-toggling-entry-flush-ba.patch @@ -3,7 +3,7 @@ From: Michael Ellerman Date: Thu, 6 May 2021 14:49:59 +1000 Subject: [PATCH] powerpc/64s: Fix crashes when toggling entry flush barrier -References: bsc#1177666 git-fixes +References: bsc#1177666 git-fixes bsc#1186460 ltc#192531 Patch-mainline: v5.13-rc2 Git-commit: aec86b052df6541cc97c5fca44e5934cbea4963b diff --git a/patches.suse/powerpc-64s-Fix-crashes-when-toggling-stf-barrier.patch b/patches.suse/powerpc-64s-Fix-crashes-when-toggling-stf-barrier.patch index cd43529..a327523 100644 --- a/patches.suse/powerpc-64s-Fix-crashes-when-toggling-stf-barrier.patch +++ b/patches.suse/powerpc-64s-Fix-crashes-when-toggling-stf-barrier.patch @@ -3,7 +3,7 @@ From: Michael Ellerman Date: Thu, 6 May 2021 14:49:58 +1000 Subject: [PATCH] powerpc/64s: Fix crashes when toggling stf barrier -References: bsc#1087082 git-fixes +References: bsc#1087082 git-fixes bsc#1186460 ltc#192531 Patch-mainline: v5.13-rc2 Git-commit: 8ec7791bae1327b1c279c5cd6e929c3b12daaf0a diff --git a/patches.suse/powerpc-pseries-lparcfg-calculate-PURR-on-demand.patch b/patches.suse/powerpc-pseries-lparcfg-calculate-PURR-on-demand.patch new file mode 100644 index 0000000..56fc71e --- /dev/null +++ b/patches.suse/powerpc-pseries-lparcfg-calculate-PURR-on-demand.patch @@ -0,0 +1,137 @@ +From 3d3a6021ddcbe9c31520e4e7b65e5ce5dc58274d Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Sat, 5 May 2018 03:19:30 +1000 +Subject: [PATCH] powerpc/pseries: lparcfg calculate PURR on demand + +References: bsc#1186487 ltc#177613 +Patch-mainline: v4.18-rc1 +Git-commit: 3d3a6021ddcbe9c31520e4e7b65e5ce5dc58274d + +For SPLPAR, lparcfg provides a sum of PURR registers for all CPUs. +Currently this is done by reading PURR in context switch and timer +interrupt, and storing that into a per-CPU variable. These are summed +to provide the value. + +This does not work with all timer schemes (e.g., NO_HZ_FULL), and it +is sub-optimal for performance because it reads the PURR register on +every context switch, although that's been difficult to distinguish +from noise in the contxt_switch microbenchmark. + +This patch implements the sum by calling a function on each CPU, to +read and add PURR values of each CPU. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/include/asm/time.h | 8 -------- + arch/powerpc/kernel/process.c | 14 -------------- + arch/powerpc/kernel/time.c | 8 -------- + arch/powerpc/platforms/pseries/lparcfg.c | 18 ++++++++++-------- + 4 files changed, 10 insertions(+), 38 deletions(-) + +diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h +--- a/arch/powerpc/include/asm/time.h ++++ b/arch/powerpc/include/asm/time.h +@@ -196,14 +196,6 @@ extern u64 mulhdu(u64, u64); + extern void div128_by_32(u64 dividend_high, u64 dividend_low, + unsigned divisor, struct div_result *dr); + +-/* Used to store Processor Utilization register (purr) values */ +- +-struct cpu_usage { +- u64 current_tb; /* Holds the current purr register values */ +-}; +- +-DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); +- + extern void secondary_cpu_time_init(void); + + DECLARE_PER_CPU(u64, decrementers_next_tb); +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index f4e5291584c5..2a7fa5000cce 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -846,10 +846,6 @@ bool ppc_breakpoint_available(void) + } + EXPORT_SYMBOL_GPL(ppc_breakpoint_available); + +-#ifdef CONFIG_PPC64 +-DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); +-#endif +- + static inline bool hw_brk_match(struct arch_hw_breakpoint *a, + struct arch_hw_breakpoint *b) + { +@@ -1182,16 +1178,6 @@ struct task_struct *__switch_to(struct task_struct *prev, + + WARN_ON(!irqs_disabled()); + +-#ifdef CONFIG_PPC64 +- /* +- * Collect processor utilization data per process +- */ +- if (firmware_has_feature(FW_FEATURE_SPLPAR)) { +- struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); +- cu->current_tb = mfspr(SPRN_PURR); +- } +-#endif /* CONFIG_PPC64 */ +- + #ifdef CONFIG_PPC_BOOK3S_64 + batch = this_cpu_ptr(&ppc64_tlb_batch); + if (batch->active) { +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index e7e8611e8863..1fe6a24357e7 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -597,14 +597,6 @@ static void __timer_interrupt(void) + __this_cpu_inc(irq_stat.timer_irqs_others); + } + +-#ifdef CONFIG_PPC64 +- /* collect purr register values often, for accurate calculations */ +- if (firmware_has_feature(FW_FEATURE_SPLPAR)) { +- struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); +- cu->current_tb = mfspr(SPRN_PURR); +- } +-#endif +- + trace_timer_interrupt_exit(regs); + } + +diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c +index c508c938dc71..7c872dc01bdb 100644 +--- a/arch/powerpc/platforms/pseries/lparcfg.c ++++ b/arch/powerpc/platforms/pseries/lparcfg.c +@@ -52,18 +52,20 @@ + * Track sum of all purrs across all processors. This is used to further + * calculate usage values by different applications + */ ++static void cpu_get_purr(void *arg) ++{ ++ atomic64_t *sum = arg; ++ ++ atomic64_add(mfspr(SPRN_PURR), sum); ++} ++ + static unsigned long get_purr(void) + { +- unsigned long sum_purr = 0; +- int cpu; ++ atomic64_t purr = ATOMIC64_INIT(0); + +- for_each_possible_cpu(cpu) { +- struct cpu_usage *cu; ++ on_each_cpu(cpu_get_purr, &purr, 1); + +- cu = &per_cpu(cpu_usage_array, cpu); +- sum_purr += cu->current_tb; +- } +- return sum_purr; ++ return atomic64_read(&purr); + } + + /* +-- +2.26.2 + diff --git a/patches.suse/proc-Avoid-mixing-integer-types-in-mem_rw.patch b/patches.suse/proc-Avoid-mixing-integer-types-in-mem_rw.patch new file mode 100644 index 0000000..3c76dad --- /dev/null +++ b/patches.suse/proc-Avoid-mixing-integer-types-in-mem_rw.patch @@ -0,0 +1,39 @@ +From 96c0a9035a0513a9e60c7a6b42e1f9c7b15bbbf6 Mon Sep 17 00:00:00 2001 +From: Marcelo Henrique Cerri +Date: Tue, 4 May 2021 14:46:27 -0300 +Subject: [PATCH] proc: Avoid mixing integer types in mem_rw() +Patch-mainline: Submitted, embargo ended 20210511 17:00 UTC. +References: CVE-2021-3491 bsc#1185642 + +Use size_t when capping the count argument received by mem_rw(). Since +count is size_t, using min_t(int, ...) can lead to a negative value +that will later be passed to access_remote_vm(), which can cause +unexpected behavior. + +Since we are capping the value to at maximum PAGE_SIZE, the conversion +from size_t to int when passing it to access_remote_vm() as "len" +shouldn't be a problem. + +Signed-off-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Marcelo Henrique Cerri +Reviewed-by: David Disseldorp +--- + fs/proc/base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 4cf48f248464..1f61f1baf201 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -837,7 +837,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf, + flags = FOLL_FORCE | (write ? FOLL_WRITE : 0); + + while (count > 0) { +- int this_len = min_t(int, count, PAGE_SIZE); ++ size_t this_len = min_t(size_t, count, PAGE_SIZE); + + if (write && copy_from_user(page, buf, this_len)) { + copied = -EFAULT; +-- +2.26.2 + diff --git a/patches.suse/scsi-core-Run-queue-in-case-of-I-O-resource-contenti.patch b/patches.suse/scsi-core-Run-queue-in-case-of-I-O-resource-contenti.patch new file mode 100644 index 0000000..ac4fe15 --- /dev/null +++ b/patches.suse/scsi-core-Run-queue-in-case-of-I-O-resource-contenti.patch @@ -0,0 +1,98 @@ +From: Ming Lei +Date: Mon, 20 Jul 2020 10:54:35 +0800 +Subject: scsi: core: Run queue in case of I/O resource contention failure +Patch-mainline: v5.8-rc7 +Git-commit: 3f0dcfbcd2e162fc0a11c1f59b7acd42ee45f126 +References: bsc#1186416 + +I/O requests may be held in scheduler queue because of resource contention. +The starvation scenario was handled properly in the regular completion +path but we failed to account for it during I/O submission. This lead to +the hang captured below. Make sure we run the queue when resource +contention is encountered in the submission path. + +[ 39.054963] scsi 13:0:0:0: rejecting I/O to dead device +[ 39.058700] scsi 13:0:0:0: rejecting I/O to dead device +[ 39.087855] sd 13:0:0:1: [sdd] Synchronizing SCSI cache +[ 39.088909] scsi 13:0:0:1: rejecting I/O to dead device +[ 39.095351] scsi 13:0:0:1: rejecting I/O to dead device +[ 39.096962] scsi 13:0:0:1: rejecting I/O to dead device +[ 247.021859] INFO: task scsi-stress-rem:813 blocked for more than 122 seconds. +[ 247.023258] Not tainted 5.8.0-rc2 #8 +[ 247.024069] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 247.025331] scsi-stress-rem D 0 813 802 0x00004000 +[ 247.025334] Call Trace: +[ 247.025354] __schedule+0x504/0x55f +[ 247.027987] schedule+0x72/0xa8 +[ 247.027991] blk_mq_freeze_queue_wait+0x63/0x8c +[ 247.027994] ? do_wait_intr_irq+0x7a/0x7a +[ 247.027996] blk_cleanup_queue+0x4b/0xc9 +[ 247.028000] __scsi_remove_device+0xf6/0x14e +[ 247.028002] scsi_remove_device+0x21/0x2b +[ 247.029037] sdev_store_delete+0x58/0x7c +[ 247.029041] kernfs_fop_write+0x10d/0x14f +[ 247.031281] vfs_write+0xa2/0xdf +[ 247.032670] ksys_write+0x6b/0xb3 +[ 247.032673] do_syscall_64+0x56/0x82 +[ 247.034053] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +[ 247.034059] RIP: 0033:0x7f69f39e9008 +[ 247.036330] Code: Bad RIP value. +[ 247.036331] RSP: 002b:00007ffdd8116498 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 +[ 247.037613] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f69f39e9008 +[ 247.039714] RDX: 0000000000000002 RSI: 000055cde92a0ab0 RDI: 0000000000000001 +[ 247.039715] RBP: 000055cde92a0ab0 R08: 000000000000000a R09: 00007f69f3a79e80 +[ 247.039716] R10: 000000000000000a R11: 0000000000000246 R12: 00007f69f3abb780 +[ 247.039717] R13: 0000000000000002 R14: 00007f69f3ab6740 R15: 0000000000000002 + +Link: https://lore.kernel.org/r/20200720025435.812030-1-ming.lei@redhat.com +Cc: linux-block@vger.kernel.org +Cc: Christoph Hellwig +Reviewed-by: Bart Van Assche +Reviewed-by: Christoph Hellwig +Signed-off-by: Ming Lei +Signed-off-by: Martin K. Petersen +[dwagner: updated context] +Acked-by: Daniel Wagner +--- + drivers/scsi/scsi_lib.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -661,6 +661,15 @@ static void scsi_release_bidi_buffers(st + cmd->request->next_rq->special = NULL; + } + ++static void scsi_run_queue_async(struct scsi_device *sdev) ++{ ++ if (scsi_target(sdev)->single_lun || ++ !list_empty(&sdev->host->starved_list)) ++ kblockd_schedule_work(&sdev->requeue_work); ++ else ++ blk_mq_run_hw_queues(sdev->request_queue, true); ++} ++ + static bool scsi_end_request(struct request *req, blk_status_t error, + unsigned int bytes, unsigned int bidi_bytes) + { +@@ -703,11 +712,7 @@ static bool scsi_end_request(struct requ + + __blk_mq_end_request(req, error); + +- if (scsi_target(sdev)->single_lun || +- !list_empty(&sdev->host->starved_list)) +- kblockd_schedule_work(&sdev->requeue_work); +- else +- blk_mq_run_hw_queues(q, true); ++ scsi_run_queue_async(sdev); + + percpu_ref_put(&q->q_usage_counter); + } else { +@@ -2113,6 +2118,7 @@ static blk_status_t scsi_queue_rq(struct + */ + if (req->rq_flags & RQF_DONTPREP) + scsi_mq_uninit_cmd(cmd); ++ scsi_run_queue_async(sdev); + break; + } + return ret; diff --git a/patches.suse/scsi-ibmvfc-Avoid-move-login-if-fast-fail-is-enabled.patch b/patches.suse/scsi-ibmvfc-Avoid-move-login-if-fast-fail-is-enabled.patch new file mode 100644 index 0000000..b53a622 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Avoid-move-login-if-fast-fail-is-enabled.patch @@ -0,0 +1,105 @@ +From 5114975eb2de4e70d9d43b57912e1aee12ec090b Mon Sep 17 00:00:00 2001 +From: Brian King +Date: Tue, 11 May 2021 13:12:19 -0500 +Subject: [PATCH] scsi: ibmvfc: Avoid move login if fast fail is enabled + +References: bsc#1185938 ltc#192043 +Patch-mainline: queued +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: 5114975eb2de4e70d9d43b57912e1aee12ec090b + +If fast fail is enabled and we encounter a WWPN moving from one port id to +another port id with I/O outstanding, if we use the move login MAD, +although it will work, it will leave any outstanding I/O still outstanding +to the old port id. Eventually, the SCSI command timers will fire and we +will abort these commands, however, this is generally much longer than the +fast fail timeout, which can lead to I/O operations being outstanding for a +long time. This patch changes the behavior to avoid the move login if fast +fail is enabled. Once terminate_rport_io cleans up the rport, then we force +the target back through the delete process, which re-drives the implicit +logout, then kicks us back into discovery where we will discover the WWPN +at the new location and do a PLOGI to it. + +Link: https://lore.kernel.org/r/1620756740-7045-3-git-send-email-brking@linux.vnet.ibm.com +Signed-off-by: Brian King +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 39 ++++++++++++++++++++++++---------- + drivers/scsi/ibmvscsi/ibmvfc.h | 1 + + 2 files changed, 29 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 4ac5bff69305..c8d3fdf65a7f 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -4728,19 +4728,24 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, + * and it failed for some reason, such as there being I/O + * pending to the target. In this case, we will have already + * deleted the rport from the FC transport so we do a move +- * login, which works even with I/O pending, as it will cancel +- * any active commands. ++ * login, which works even with I/O pending, however, if ++ * there is still I/O pending, it will stay outstanding, so ++ * we only do this if fast fail is disabled for the rport, ++ * otherwise we let terminate_rport_io clean up the port ++ * before we login at the new location. + */ + if (wtgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { +- /* +- * Do a move login here. The old target is no longer +- * known to the transport layer We don't use the +- * normal ibmvfc_set_tgt_action to set this, as we +- * don't normally want to allow this state change. +- */ +- wtgt->new_scsi_id = scsi_id; +- wtgt->action = IBMVFC_TGT_ACTION_INIT; +- ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login); ++ if (wtgt->move_login) { ++ /* ++ * Do a move login here. The old target is no longer ++ * known to the transport layer We don't use the ++ * normal ibmvfc_set_tgt_action to set this, as we ++ * don't normally want to allow this state change. ++ */ ++ wtgt->new_scsi_id = scsi_id; ++ wtgt->action = IBMVFC_TGT_ACTION_INIT; ++ ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login); ++ } + goto unlock_out; + } else { + tgt_err(wtgt, "Unexpected target state: %d, %p\n", +@@ -5486,6 +5491,18 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) + rport = tgt->rport; + tgt->rport = NULL; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT); ++ ++ /* ++ * If fast fail is enabled, we wait for it to fire and then clean up ++ * the old port, since we expect the fast fail timer to clean up the ++ * outstanding I/O faster than waiting for normal command timeouts. ++ * However, if fast fail is disabled, any I/O outstanding to the ++ * rport LUNs will stay outstanding indefinitely, since the EH handlers ++ * won't get invoked for I/O's timing out. If this is a NPIV failover ++ * scenario, the better alternative is to use the move login. ++ */ ++ if (rport && rport->fast_io_fail_tmo == -1) ++ tgt->move_login = 1; + spin_unlock_irqrestore(vhost->host->host_lock, flags); + if (rport) + fc_remote_port_delete(rport); +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h +index 4601bd21372d..4f0f3baefae4 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.h ++++ b/drivers/scsi/ibmvscsi/ibmvfc.h +@@ -726,6 +726,7 @@ struct ibmvfc_target { + int add_rport; + int init_retries; + int logo_rcvd; ++ int move_login; + u32 cancel_key; + struct ibmvfc_service_parms service_parms; + struct ibmvfc_service_parms service_parms_change; +-- +2.26.2 + diff --git a/patches.suse/scsi-ibmvfc-Handle-move-login-failure.patch b/patches.suse/scsi-ibmvfc-Handle-move-login-failure.patch new file mode 100644 index 0000000..3122558 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Handle-move-login-failure.patch @@ -0,0 +1,109 @@ +From d5b45dd5ba6c944b17118530843e67bf9c096e49 Mon Sep 17 00:00:00 2001 +From: Brian King +Date: Tue, 11 May 2021 13:12:18 -0500 +Subject: [PATCH] scsi: ibmvfc: Handle move login failure + +References: bsc#1185938 ltc#192043 +Patch-mainline: queued +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git +Git-commit: d5b45dd5ba6c944b17118530843e67bf9c096e49 + +When service is being performed on an SVC with NPIV enabled, the WWPN of +the canister / node being serviced fails over to the another canister / +node. This looks to the ibmvfc driver as a WWPN moving from one SCSI ID to +another. The driver will first attempt to do an implicit logout of the old +SCSI ID. If this works, we simply delete the rport at the old location and +add an rport at the new location and the FC transport class handles +everything. However, if there is I/O outstanding, this implicit logout will +fail, in which case we will send a "move login" request to the VIOS. This +will cancel any outstanding I/O to that port, logout the port, and PLOGI +the new port. Recently we've encountered a scenario where the move login +fails. This was resulting in an attempted plogi to the new scsi id, without +the old scsi id getting logged out, which is a VIOS protocol violation. To +solve this, we want to keep tracking the old scsi id as the current scsi +id. That way, once terminate_rport_io cancels the outstanding i/o, it will +send us back through to do an implicit logout of the old scsi id, rather +than the new scsi id, and then we can plogi the new scsi id. + +Link: https://lore.kernel.org/r/1620756740-7045-2-git-send-email-brking@linux.vnet.ibm.com +Signed-off-by: Brian King +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++++++++-------- + drivers/scsi/ibmvscsi/ibmvfc.h | 2 +- + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index 6540d48eb0e8..4ac5bff69305 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -4299,9 +4299,10 @@ static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt) + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); + switch (status) { + case IBMVFC_MAD_SUCCESS: +- tgt_dbg(tgt, "Move Login succeeded for old scsi_id: %llX\n", tgt->old_scsi_id); ++ tgt_dbg(tgt, "Move Login succeeded for new scsi_id: %llX\n", tgt->new_scsi_id); + tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); + tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); ++ tgt->scsi_id = tgt->new_scsi_id; + tgt->ids.port_id = tgt->scsi_id; + memcpy(&tgt->service_parms, &rsp->service_parms, + sizeof(tgt->service_parms)); +@@ -4319,8 +4320,8 @@ static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login); + + tgt_log(tgt, level, +- "Move Login failed: old scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n", +- tgt->old_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags), ++ "Move Login failed: new scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n", ++ tgt->new_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags), + status); + break; + } +@@ -4357,8 +4358,8 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt) + move->common.opcode = cpu_to_be32(IBMVFC_MOVE_LOGIN); + move->common.length = cpu_to_be16(sizeof(*move)); + +- move->old_scsi_id = cpu_to_be64(tgt->old_scsi_id); +- move->new_scsi_id = cpu_to_be64(tgt->scsi_id); ++ move->old_scsi_id = cpu_to_be64(tgt->scsi_id); ++ move->new_scsi_id = cpu_to_be64(tgt->new_scsi_id); + move->wwpn = cpu_to_be64(tgt->wwpn); + move->node_name = cpu_to_be64(tgt->ids.node_name); + +@@ -4367,7 +4368,7 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt) + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + kref_put(&tgt->kref, ibmvfc_release_tgt); + } else +- tgt_dbg(tgt, "Sent Move Login for old scsi_id: %llX\n", tgt->old_scsi_id); ++ tgt_dbg(tgt, "Sent Move Login for new scsi_id: %llX\n", tgt->new_scsi_id); + } + + /** +@@ -4737,8 +4738,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, + * normal ibmvfc_set_tgt_action to set this, as we + * don't normally want to allow this state change. + */ +- wtgt->old_scsi_id = wtgt->scsi_id; +- wtgt->scsi_id = scsi_id; ++ wtgt->new_scsi_id = scsi_id; + wtgt->action = IBMVFC_TGT_ACTION_INIT; + ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login); + goto unlock_out; +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h +index 19dcec3ae9ba..4601bd21372d 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.h ++++ b/drivers/scsi/ibmvscsi/ibmvfc.h +@@ -718,7 +718,7 @@ struct ibmvfc_target { + struct ibmvfc_host *vhost; + u64 scsi_id; + u64 wwpn; +- u64 old_scsi_id; ++ u64 new_scsi_id; + struct fc_rport *rport; + int target_id; + enum ibmvfc_target_action action; +-- +2.26.2 + diff --git a/patches.suse/scsi-ibmvfc-Reinit-target-retries.patch b/patches.suse/scsi-ibmvfc-Reinit-target-retries.patch new file mode 100644 index 0000000..7b975c2 --- /dev/null +++ b/patches.suse/scsi-ibmvfc-Reinit-target-retries.patch @@ -0,0 +1,68 @@ +From 2e51f78b5d8717bba243f5e857031b1d104a3577 Mon Sep 17 00:00:00 2001 +From: Brian King +Date: Tue, 11 May 2021 13:12:20 -0500 +Subject: [PATCH] scsi: ibmvfc: Reinit target retries + +References: bsc#1185938 ltc#192043 +Patch-mainline: queued +Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 2e51f78b5d8717bba243f5e857031b1d104a3577 + +If rport target discovery commands fail for some reason, they get retried +up to a set number of retries. Once the retry limit is exceeded, the target +is deleted. In order to delete the target, we either need to do an implicit +logout or a move login. In the move login case, if the move login fails, we +want to retry it. This ensures the retry counter gets reinitialized so the +move login will get retried. + +Link: https://lore.kernel.org/r/1620756740-7045-4-git-send-email-brking@linux.vnet.ibm.com +Signed-off-by: Brian King +Signed-off-by: Martin K. Petersen +Acked-by: Michal Suchanek +--- + drivers/scsi/ibmvscsi/ibmvfc.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c +index c8d3fdf65a7f..a251dbf630cc 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.c ++++ b/drivers/scsi/ibmvscsi/ibmvfc.c +@@ -654,8 +654,10 @@ static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) + **/ + static void ibmvfc_del_tgt(struct ibmvfc_target *tgt) + { +- if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT)) ++ if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT)) { + tgt->job_step = ibmvfc_tgt_implicit_logout_and_del; ++ tgt->init_retries = 0; ++ } + wake_up(&tgt->vhost->work_wait_q); + } + +@@ -4744,6 +4746,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, + */ + wtgt->new_scsi_id = scsi_id; + wtgt->action = IBMVFC_TGT_ACTION_INIT; ++ wtgt->init_retries = 0; + ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login); + } + goto unlock_out; +@@ -5336,6 +5339,7 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) + tgt_dbg(tgt, "Deleting rport with outstanding I/O\n"); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT); + tgt->rport = NULL; ++ tgt->init_retries = 0; + spin_unlock_irqrestore(vhost->host->host_lock, flags); + fc_remote_port_delete(rport); + return; +@@ -5490,6 +5494,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) + tgt_dbg(tgt, "Deleting rport with I/O outstanding\n"); + rport = tgt->rport; + tgt->rport = NULL; ++ tgt->init_retries = 0; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT); + + /* +-- +2.26.2 + diff --git a/patches.suse/scsi-libfc-Avoid-invoking-response-handler-twice-if-.patch b/patches.suse/scsi-libfc-Avoid-invoking-response-handler-twice-if-.patch new file mode 100644 index 0000000..924f6f5 --- /dev/null +++ b/patches.suse/scsi-libfc-Avoid-invoking-response-handler-twice-if-.patch @@ -0,0 +1,88 @@ +From: Javed Hasan +Date: Tue, 15 Dec 2020 11:47:31 -0800 +Subject: scsi: libfc: Avoid invoking response handler twice if ep is already + completed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Patch-mainline: v5.11-rc5 +Git-commit: b2b0f16fa65e910a3ec8771206bb49ee87a54ac5 +References: bsc#1186573 + +A race condition exists between the response handler getting called because +of exchange_mgr_reset() (which clears out all the active XIDs) and the +response we get via an interrupt. + +Sequence of events: + + rport ba0200: Port timeout, state PLOGI + rport ba0200: Port entered PLOGI state from PLOGI state + xid 1052: Exchange timer armed : 20000 msecs  xid timer armed here + rport ba0200: Received LOGO request while in state PLOGI + rport ba0200: Delete port + rport ba0200: work event 3 + rport ba0200: lld callback ev 3 + bnx2fc: rport_event_hdlr: event = 3, port_id = 0xba0200 + bnx2fc: ba0200 - rport not created Yet!! + /* Here we reset any outstanding exchanges before + freeing rport using the exch_mgr_reset() */ + xid 1052: Exchange timer canceled + /* Here we got two responses for one xid */ + xid 1052: invoking resp(), esb 20000000 state 3 + xid 1052: invoking resp(), esb 20000000 state 3 + xid 1052: fc_rport_plogi_resp() : ep->resp_active 2 + xid 1052: fc_rport_plogi_resp() : ep->resp_active 2 + +Skip the response if the exchange is already completed. + +Link: https://lore.kernel.org/r/20201215194731.2326-1-jhasan@marvell.com +Signed-off-by: Javed Hasan +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/libfc/fc_exch.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/libfc/fc_exch.c ++++ b/drivers/scsi/libfc/fc_exch.c +@@ -1631,8 +1631,13 @@ static void fc_exch_recv_seq_resp(struct + rc = fc_exch_done_locked(ep); + WARN_ON(fc_seq_exch(sp) != ep); + spin_unlock_bh(&ep->ex_lock); +- if (!rc) ++ if (!rc) { + fc_exch_delete(ep); ++ } else { ++ FC_EXCH_DBG(ep, "ep is completed already," ++ "hence skip calling the resp\n"); ++ goto skip_resp; ++ } + } + + /* +@@ -1651,6 +1656,7 @@ static void fc_exch_recv_seq_resp(struct + if (!fc_invoke_resp(ep, sp, fp)) + fc_frame_free(fp); + ++skip_resp: + fc_exch_release(ep); + return; + rel: +@@ -1907,10 +1913,16 @@ static void fc_exch_reset(struct fc_exch + + fc_exch_hold(ep); + +- if (!rc) ++ if (!rc) { + fc_exch_delete(ep); ++ } else { ++ FC_EXCH_DBG(ep, "ep is completed already," ++ "hence skip calling the resp\n"); ++ goto skip_resp; ++ } + + fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED)); ++skip_resp: + fc_seq_set_resp(sp, NULL, ep->arg); + fc_exch_release(ep); + } diff --git a/patches.suse/scsi-lpfc-Add-a-option-to-enable-interlocked-ABTS-be.patch b/patches.suse/scsi-lpfc-Add-a-option-to-enable-interlocked-ABTS-be.patch new file mode 100644 index 0000000..ecb9317 --- /dev/null +++ b/patches.suse/scsi-lpfc-Add-a-option-to-enable-interlocked-ABTS-be.patch @@ -0,0 +1,210 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:57 -0700 +Subject: scsi: lpfc: Add a option to enable interlocked ABTS before job + completion +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 3e49af9393c6e59d579de13333514fc9660a0e92 +References: bsc#1186452 + +Default behavior for the driver, when aborting an I/O, is to terminate the +I/O with the adapter. The adapter will initiate an ABTS to terminate the +exchange on the link and mark the exchange is terminated so that no further +use of the sgl or any traffic for the exchange is worked on. Completion on +the Abort is then posted to the driver, which as the I/O is terminated can +complete the I/O to the OS. This completion may occur prior to the ABTS +handshake completing on the wire. The ABTS handshake can take a long time +to complete with timeouts and retries reaching 60+ seconds. Note: if +retries fail, LOGO occurs. + +Some devices want to ensure that the ABTS handshake fully completes (this +device has fully ack'd it) before the I/O completion is posted back to the +OS, where a failed I/O may be retried via a different path. + +To support this behavior, an option was added to the driver to change I/O +completion from the Abort cmd completion to the Exchange termination (aka +ABTS) completion. + +Link: https://lore.kernel.org/r/20210514195559.119853-10-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_attr.c | 11 ++++++++++ + drivers/scsi/lpfc/lpfc_mbox.c | 3 +- + drivers/scsi/lpfc/lpfc_scsi.c | 45 ++++++++++++++++++++++++++++++++++++------ + 4 files changed, 53 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -914,6 +914,7 @@ struct lpfc_hba { + uint32_t cfg_request_firmware_upgrade; + uint32_t cfg_suppress_link_up; + uint32_t cfg_rrq_xri_bitmap_sz; ++ u32 cfg_fcp_wait_abts_rsp; + uint32_t cfg_delay_discovery; + uint32_t cfg_sli_mode; + #define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */ +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -3456,6 +3456,15 @@ LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2 + "FCF Fast failover=1 Priority failover=2"); + + /* ++ * lpfc_fcp_wait_abts_rsp: Modifies criteria for reporting completion of ++ * aborted IO. ++ * The range is [0,1]. Default value is 0 ++ * 0, IO completes after ABTS issued (default). ++ * 1, IO completes after receipt of ABTS response or timeout. ++ */ ++LPFC_ATTR_R(fcp_wait_abts_rsp, 0, 0, 1, "Wait for FCP ABTS completion"); ++ ++/* + # lpfc_enable_rrq: Track XRI/OXID reuse after IO failures + # 0x0 = disabled, XRI/OXID use not tracked. + # 0x1 = XRI/OXID reuse is timed with ratov, RRQ sent. +@@ -6167,6 +6176,7 @@ struct device_attribute *lpfc_hba_attrs[ + &dev_attr_lpfc_enable_npiv, + &dev_attr_lpfc_fcf_failover_policy, + &dev_attr_lpfc_enable_rrq, ++ &dev_attr_lpfc_fcp_wait_abts_rsp, + &dev_attr_nport_evt_cnt, + &dev_attr_board_mode, + &dev_attr_max_vpi, +@@ -7299,6 +7309,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) + lpfc_enable_npiv_init(phba, lpfc_enable_npiv); + lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy); + lpfc_enable_rrq_init(phba, lpfc_enable_rrq); ++ lpfc_fcp_wait_abts_rsp_init(phba, lpfc_fcp_wait_abts_rsp); + lpfc_fdmi_on_init(phba, lpfc_fdmi_on); + lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN); + lpfc_use_msi_init(phba, lpfc_use_msi); +--- a/drivers/scsi/lpfc/lpfc_mbox.c ++++ b/drivers/scsi/lpfc/lpfc_mbox.c +@@ -522,7 +522,8 @@ lpfc_init_link(struct lpfc_hba * phba, + } + + /* Enable asynchronous ABTS responses from firmware */ +- mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT; ++ if (phba->sli_rev == LPFC_SLI_REV3 && !phba->cfg_fcp_wait_abts_rsp) ++ mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT; + + /* NEW_FEATURE + * Setting up the link speed +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -518,6 +518,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba + struct lpfc_nodelist *ndlp; + int rrq_empty = 0; + struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring; ++ struct scsi_cmnd *cmd; + + if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) + return; +@@ -553,6 +554,31 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba + psb->cur_iocbq.sli4_lxritag, rxid, 1); + lpfc_sli4_abts_err_handler(phba, ndlp, axri); + } ++ ++ if (phba->cfg_fcp_wait_abts_rsp) { ++ spin_lock_irqsave(&psb->buf_lock, iflag); ++ cmd = psb->pCmd; ++ psb->pCmd = NULL; ++ spin_unlock_irqrestore(&psb->buf_lock, iflag); ++ ++ /* The sdev is not guaranteed to be valid post ++ * scsi_done upcall. ++ */ ++ if (cmd) ++ cmd->scsi_done(cmd); ++ ++ /* ++ * We expect there is an abort thread waiting ++ * for command completion wake up the thread. ++ */ ++ spin_lock_irqsave(&psb->buf_lock, iflag); ++ psb->cur_iocbq.iocb_flag &= ++ ~LPFC_DRIVER_ABORTED; ++ if (psb->waitq) ++ wake_up(psb->waitq); ++ spin_unlock_irqrestore(&psb->buf_lock, iflag); ++ } ++ + lpfc_release_scsi_buf_s4(phba, psb); + if (rrq_empty) + lpfc_worker_wake_up(phba); +@@ -780,7 +806,8 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba + qp = psb->hdwq; + if (psb->flags & LPFC_SBUF_XBUSY) { + spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag); +- psb->pCmd = NULL; ++ if (!phba->cfg_fcp_wait_abts_rsp) ++ psb->pCmd = NULL; + list_add_tail(&psb->list, &qp->lpfc_abts_io_buf_list); + qp->abts_scsi_io_bufs++; + spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag); +@@ -4045,6 +4072,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba + u32 logit = LOG_FCP; + u32 status, idx; + unsigned long iflags = 0; ++ u8 wait_xb_clr = 0; + + /* Sanity check on return of outstanding command */ + if (!lpfc_cmd) { +@@ -4096,8 +4124,11 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba + lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK); + + lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; +- if (bf_get(lpfc_wcqe_c_xb, wcqe)) ++ if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + lpfc_cmd->flags |= LPFC_SBUF_XBUSY; ++ if (phba->cfg_fcp_wait_abts_rsp) ++ wait_xb_clr = 1; ++ } + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (lpfc_cmd->prot_data_type) { +@@ -4329,6 +4360,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba + lpfc_io_ktime(phba, lpfc_cmd); + } + #endif ++ if (wait_xb_clr) ++ goto out; + lpfc_cmd->pCmd = NULL; + spin_unlock(&lpfc_cmd->buf_lock); + +@@ -4343,8 +4376,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba + lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; + if (lpfc_cmd->waitq) + wake_up(lpfc_cmd->waitq); ++out: + spin_unlock(&lpfc_cmd->buf_lock); +- + lpfc_release_scsi_buf(phba, lpfc_cmd); + } + +@@ -4398,11 +4431,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba + + lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK); + lpfc_cmd->status = pIocbOut->iocb.ulpStatus; +- /* pick up SLI4 exhange busy status from HBA */ ++ /* pick up SLI4 exchange busy status from HBA */ ++ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; + if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY) + lpfc_cmd->flags |= LPFC_SBUF_XBUSY; +- else +- lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; + + #ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (lpfc_cmd->prot_data_type) { +@@ -4601,6 +4633,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba + lpfc_io_ktime(phba, lpfc_cmd); + } + #endif ++ + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + cmd->scsi_done(cmd); + diff --git a/patches.suse/scsi-lpfc-Add-ndlp-kref-accounting-for-resume-RPI-pa.patch b/patches.suse/scsi-lpfc-Add-ndlp-kref-accounting-for-resume-RPI-pa.patch new file mode 100644 index 0000000..d6944af --- /dev/null +++ b/patches.suse/scsi-lpfc-Add-ndlp-kref-accounting-for-resume-RPI-pa.patch @@ -0,0 +1,91 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:52 -0700 +Subject: scsi: lpfc: Add ndlp kref accounting for resume RPI path +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 1037e4b4f81dc4ddf928e0ca2f1b182efdfdcc9d +References: bsc#1186452 + +The driver is crashing due to a bad pointer during driver load due in an +adisc acc receive routine. The driver is missing node get/put in the +mbx_resume_rpi paths. + +Fix by adding the proper gets and puts into the resume_rpi path. + +Link: https://lore.kernel.org/r/20210514195559.119853-5-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nportdisc.c | 4 ++++ + drivers/scsi/lpfc/lpfc_sli.c | 23 ++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -659,6 +659,10 @@ lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba + lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb, + ndlp, NULL); + } ++ ++ /* This nlp_put pairs with lpfc_sli4_resume_rpi */ ++ lpfc_nlp_put(ndlp); ++ + kfree(elsiocb); + mempool_free(mboxq, phba->mbox_mem_pool); + } +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -2682,6 +2682,12 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba * + } + } + ++ /* This nlp_put pairs with lpfc_sli4_resume_rpi */ ++ if (pmb->u.mb.mbxCommand == MBX_RESUME_RPI) { ++ ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; ++ lpfc_nlp_put(ndlp); ++ } ++ + /* Check security permission status on INIT_LINK mailbox command */ + if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) && + (pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION)) +@@ -18911,14 +18917,28 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelis + if (!mboxq) + return -ENOMEM; + ++ /* If cmpl assigned, then this nlp_get pairs with ++ * lpfc_mbx_cmpl_resume_rpi. ++ * ++ * Else cmpl is NULL, then this nlp_get pairs with ++ * lpfc_sli_def_mbox_cmpl. ++ */ ++ if (!lpfc_nlp_get(ndlp)) { ++ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, ++ "2122 %s: Failed to get nlp ref\n", ++ __func__); ++ mempool_free(mboxq, phba->mbox_mem_pool); ++ return -EIO; ++ } ++ + /* Post all rpi memory regions to the port. */ + lpfc_resume_rpi(mboxq, ndlp); + if (cmpl) { + mboxq->mbox_cmpl = cmpl; + mboxq->ctx_buf = arg; +- mboxq->ctx_ndlp = ndlp; + } else + mboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; ++ mboxq->ctx_ndlp = ndlp; + mboxq->vport = ndlp->vport; + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { +@@ -18926,6 +18946,7 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelis + "2010 Resume RPI Mailbox failed " + "status %d, mbxStatus x%x\n", rc, + bf_get(lpfc_mqe_status, &mboxq->u.mqe)); ++ lpfc_nlp_put(ndlp); + mempool_free(mboxq, phba->mbox_mem_pool); + return -EIO; + } diff --git a/patches.suse/scsi-lpfc-Fix-Node-recovery-when-driver-is-handling-.patch b/patches.suse/scsi-lpfc-Fix-Node-recovery-when-driver-is-handling-.patch new file mode 100644 index 0000000..35ba736 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-Node-recovery-when-driver-is-handling-.patch @@ -0,0 +1,73 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:53 -0700 +Subject: scsi: lpfc: Fix Node recovery when driver is handling simultaneous + PLOGIs +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 4012baeab6ca22b7f7beb121b6d0da0a62942fdd +References: bsc#1186452 + +When lpfc is handling a solicited and unsolicited PLOGI with another +initiator, the remote initiator is never recovered. The node for the +initiator is erroneouosly removed and all resources released. + +In lpfc_cmpl_els_plogi(), when lpfc_els_retry() returns a failure code, the +driver is calling the state machine with a device remove event because the +remote port is not currently registered with the SCSI or NVMe +transports. The issue is that on a PLOGI "collision" the driver correctly +aborts the solicited PLOGI and allows the unsolicited PLOGI to complete the +process, but this process is interrupted with a device_rm event. + +Introduce logic in the PLOGI completion to capture the PLOGI collision +event and jump out of the routine. This will avoid removal of the node. +If there is no collision, the normal node removal will occur. + +Fixes: 52edb2caf675 ("scsi: lpfc: Remove ndlp when a PLOGI/ADISC/PRLI/REG_RPI ultimately fails") +Cc: # v5.11+ +Link: https://lore.kernel.org/r/20210514195559.119853-6-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_els.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -2007,9 +2007,20 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phb + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_CMPL_PLOGI); + +- /* As long as this node is not registered with the scsi or nvme +- * transport, it is no longer an active node. Otherwise +- * devloss handles the final cleanup. ++ /* If a PLOGI collision occurred, the node needs to continue ++ * with the reglogin process. ++ */ ++ spin_lock_irq(&ndlp->lock); ++ if ((ndlp->nlp_flag & (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI)) && ++ ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) { ++ spin_unlock_irq(&ndlp->lock); ++ goto out; ++ } ++ spin_unlock_irq(&ndlp->lock); ++ ++ /* No PLOGI collision and the node is not registered with the ++ * scsi or nvme transport. It is no longer an active node. Just ++ * start the device remove process. + */ + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { + spin_lock_irq(&ndlp->lock); +@@ -4629,6 +4640,10 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, + (vport && vport->port_type == LPFC_NPIV_PORT) && + ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; ++ ndlp->nlp_flag &= ~NLP_RELEASE_RPI; ++ spin_unlock_irq(&ndlp->lock); + lpfc_drop_node(vport, ndlp); + } + diff --git a/patches.suse/scsi-lpfc-Fix-Unexpected-timeout-error-in-direct-att.patch b/patches.suse/scsi-lpfc-Fix-Unexpected-timeout-error-in-direct-att.patch new file mode 100644 index 0000000..90e9626 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-Unexpected-timeout-error-in-direct-att.patch @@ -0,0 +1,47 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:51 -0700 +Subject: scsi: lpfc: Fix "Unexpected timeout" error in direct attach topology +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: e30d55137edef47434c40d7570276a0846fe922c +References: bsc#1186452 + +An 'unexpected timeout' message may be seen in a point-2-point topology. +The message occurs when a PLOGI is received before the driver is notified +of FLOGI completion. The FLOGI completion failure causes discovery to be +triggered for a second time. The discovery timer is restarted but no new +discovery activity is initiated, thus the timeout message eventually +appears. + +In point-2-point, when discovery has progressed before the FLOGI completion +is processed, it is not a failure. Add code to FLOGI completion to detect +that discovery has progressed and exit the FLOGI handling (noop'ing it). + +Link: https://lore.kernel.org/r/20210514195559.119853-4-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_els.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -1175,6 +1175,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phb + phba->fcf.fcf_redisc_attempted = 0; /* reset */ + goto out; + } ++ } else if (vport->port_state > LPFC_FLOGI && ++ vport->fc_flag & FC_PT2PT) { ++ /* ++ * In a p2p topology, it is possible that discovery has ++ * already progressed, and this completion can be ignored. ++ * Recheck the indicated topology. ++ */ ++ if (!sp->cmn.fPort) ++ goto out; + } + + flogifail: diff --git a/patches.suse/scsi-lpfc-Fix-bad-memory-access-during-VPD-DUMP-mail.patch b/patches.suse/scsi-lpfc-Fix-bad-memory-access-during-VPD-DUMP-mail.patch new file mode 100644 index 0000000..95dff66 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-bad-memory-access-during-VPD-DUMP-mail.patch @@ -0,0 +1,84 @@ +From: James Smart +Date: Wed, 21 Apr 2021 16:45:11 -0700 +Subject: scsi: lpfc: Fix bad memory access during VPD DUMP mailbox command +Patch-mainline: v5.13-rc1 +Git-commit: e4ec10228fdf09b88ba018009f14a696fb50d3f2 +References: bsc#1186452 + +The dump command for reading a region passes a requested read length +specified in words (4-byte units). The response overwrites the same field +with the actual number of bytes read. + +The mailbox handler for DUMP which reads VPD data (region 23) is treating +the response field as if it were still a word_cnt, thus multiplying it by 4 +to set the read's "length". Given the read value was calculated based on +the size of the read buffer, the longer response length runs off the end of +the buffer. + +Fix by reworking the code to use the response field as a byte count. + +Link: https://lore.kernel.org/r/20210421234511.102206-1-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_init.c | 12 ++++++------ + drivers/scsi/lpfc/lpfc_sli.c | 15 ++++++++------- + 2 files changed, 14 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -257,13 +257,13 @@ lpfc_config_port_prep(struct lpfc_hba *p + if (mb->un.varDmp.word_cnt == 0) + break; + +- i = mb->un.varDmp.word_cnt * sizeof(uint32_t); +- if (offset + i > DMP_VPD_SIZE) +- i = DMP_VPD_SIZE - offset; ++ if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset) ++ mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset; + lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, +- lpfc_vpd_data + offset, i); +- offset += i; +- } while (offset < DMP_VPD_SIZE); ++ lpfc_vpd_data + offset, ++ mb->un.varDmp.word_cnt); ++ offset += mb->un.varDmp.word_cnt; ++ } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE); + + lpfc_parse_vpd(phba, lpfc_vpd_data, offset); + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -19650,7 +19650,7 @@ lpfc_sli_get_config_region23(struct lpfc + LPFC_MBOXQ_t *pmb = NULL; + MAILBOX_t *mb; + uint32_t offset = 0; +- int i, rc; ++ int rc; + + if (!rgn23_data) + return 0; +@@ -19681,13 +19681,14 @@ lpfc_sli_get_config_region23(struct lpfc + if (mb->un.varDmp.word_cnt == 0) + break; + +- i = mb->un.varDmp.word_cnt * sizeof(uint32_t); +- if (offset + i > DMP_RGN23_SIZE) +- i = DMP_RGN23_SIZE - offset; ++ if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset) ++ mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset; ++ + lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, +- rgn23_data + offset, i); +- offset += i; +- } while (offset < DMP_RGN23_SIZE); ++ rgn23_data + offset, ++ mb->un.varDmp.word_cnt); ++ offset += mb->un.varDmp.word_cnt; ++ } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE); + + mempool_free(pmb, phba->mbox_mem_pool); + return offset; diff --git a/patches.suse/scsi-lpfc-Fix-crash-when-lpfc_sli4_hba_setup-fails-t.patch b/patches.suse/scsi-lpfc-Fix-crash-when-lpfc_sli4_hba_setup-fails-t.patch new file mode 100644 index 0000000..98d7d3d --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-crash-when-lpfc_sli4_hba_setup-fails-t.patch @@ -0,0 +1,49 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:56 -0700 +Subject: scsi: lpfc: Fix crash when lpfc_sli4_hba_setup() fails to initialize + the SGLs +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 5aa615d195f1e142c662cb2253f057c9baec7531 +References: bsc#1186452 + +The driver is encountering a crash in lpfc_free_iocb_list() while +performing initial attachment. + +Code review found this to be an errant failure path that was taken, jumping +to a tag that then referenced structures that were uninitialized. + +Fix the failure path. + +Link: https://lore.kernel.org/r/20210514195559.119853-9-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_sli.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -7836,7 +7836,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phb + "0393 Error %d during rpi post operation\n", + rc); + rc = -ENODEV; +- goto out_destroy_queue; ++ goto out_free_iocblist; + } + lpfc_sli4_node_prep(phba); + +@@ -8002,8 +8002,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phb + out_unset_queue: + /* Unset all the queues set up in this routine when error out */ + lpfc_sli4_queue_unset(phba); +-out_destroy_queue: ++out_free_iocblist: + lpfc_free_iocb_list(phba); ++out_destroy_queue: + lpfc_sli4_queue_destroy(phba); + out_stop_timers: + lpfc_stop_hba_timers(phba); diff --git a/patches.suse/scsi-lpfc-Fix-node-handling-for-Fabric-Controller-an.patch b/patches.suse/scsi-lpfc-Fix-node-handling-for-Fabric-Controller-an.patch new file mode 100644 index 0000000..2ee8936 --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-node-handling-for-Fabric-Controller-an.patch @@ -0,0 +1,385 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:54 -0700 +Subject: scsi: lpfc: Fix node handling for Fabric Controller and Domain + Controller +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: fe83e3b9b422ac8ece2359c7b7290efe7f0335a2 +References: bsc#1186452 + +During link bounce testing, RPI counts were seen to differ from the number +of nodes. For fabric and domain controllers, a temporary RPI is assigned, +but the code isn't registering it. If the nodes do go away, such as on link +down, the temporary RPI isn't being released. + +Change the way these two fabric services are managed, make them behave like +any other remote port. Register the RPI and register with the transport. +Never leave the nodes in a NPR or UNUSED state where their RPI is in limbo. +This allows them to follow normal dev_loss_tmo handling, RPI refcounting, +and normal removal rules. It also allows fabric I/Os to use the RPI for +traffic requests. + +Note: There is some logic that still has a couple of exceptions when the +Domain controller (0xfffcXX). There are cases where the fabric won't have a +valid login but will send RDP. Other times, it will it send a LOGO then an +RDP. It makes for ad-hoc behavior to manage the node. Exceptions are +documented in the code. + +Link: https://lore.kernel.org/r/20210514195559.119853-7-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +[dwagner: context update in lpfc_rcv_logo] +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_debugfs.c | 4 - + drivers/scsi/lpfc/lpfc_disc.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 137 +++++++++++++++++++++++++++++++++---- + drivers/scsi/lpfc/lpfc_hbadisc.c | 54 +++++++++++++- + drivers/scsi/lpfc/lpfc_nportdisc.c | 12 +++ + drivers/scsi/lpfc/lpfc_sli.c | 1 + 7 files changed, 190 insertions(+), 20 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_crtn.h ++++ b/drivers/scsi/lpfc/lpfc_crtn.h +@@ -81,6 +81,7 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc + void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); + void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); + void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); ++void lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb); + void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); + void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *); + void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -866,10 +866,10 @@ lpfc_debugfs_nodelist_data(struct lpfc_v + len += scnprintf(buf+len, size-len, "%s DID:x%06x ", + statep, ndlp->nlp_DID); + len += scnprintf(buf+len, size-len, +- "WWPN x%llx ", ++ "WWPN x%016llx ", + wwn_to_u64(ndlp->nlp_portname.u.wwn)); + len += scnprintf(buf+len, size-len, +- "WWNN x%llx ", ++ "WWNN x%016llx ", + wwn_to_u64(ndlp->nlp_nodename.u.wwn)); + len += scnprintf(buf+len, size-len, "RPI:x%04x ", + ndlp->nlp_rpi); +--- a/drivers/scsi/lpfc/lpfc_disc.h ++++ b/drivers/scsi/lpfc/lpfc_disc.h +@@ -79,6 +79,7 @@ struct lpfc_node_rrqs { + + struct lpfc_nodelist { + struct list_head nlp_listp; ++ struct serv_parm fc_sparam; /* buffer for service params */ + struct lpfc_name nlp_portname; + struct lpfc_name nlp_nodename; + +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -3086,6 +3086,95 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, + } + + /** ++ * lpfc_reg_fab_ctrl_node - RPI register the fabric controller node. ++ * @vport: pointer to lpfc_vport data structure. ++ * @fc_ndlp: pointer to the fabric controller (0xfffffd) node. ++ * ++ * This routine registers the rpi assigned to the fabric controller ++ * NPort_ID (0xfffffd) with the port and moves the node to UNMAPPED ++ * state triggering a registration with the SCSI transport. ++ * ++ * This routine is single out because the fabric controller node ++ * does not receive a PLOGI. This routine is consumed by the ++ * SCR and RDF ELS commands. Callers are expected to qualify ++ * with SLI4 first. ++ **/ ++static int ++lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp) ++{ ++ int rc = 0; ++ struct lpfc_hba *phba = vport->phba; ++ struct lpfc_nodelist *ns_ndlp; ++ LPFC_MBOXQ_t *mbox; ++ struct lpfc_dmabuf *mp; ++ ++ if (fc_ndlp->nlp_flag & NLP_RPI_REGISTERED) ++ return rc; ++ ++ ns_ndlp = lpfc_findnode_did(vport, NameServer_DID); ++ if (!ns_ndlp) ++ return -ENODEV; ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "0935 %s: Reg FC RPI x%x on FC DID x%x NSSte: x%x\n", ++ __func__, fc_ndlp->nlp_rpi, fc_ndlp->nlp_DID, ++ ns_ndlp->nlp_state); ++ if (ns_ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) ++ return -ENODEV; ++ ++ mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); ++ if (!mbox) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, ++ "0936 %s: no memory for reg_login " ++ "Data: x%x x%x x%x x%x\n", __func__, ++ fc_ndlp->nlp_DID, fc_ndlp->nlp_state, ++ fc_ndlp->nlp_flag, fc_ndlp->nlp_rpi); ++ return -ENOMEM; ++ } ++ rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID, ++ (u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi); ++ if (rc) { ++ rc = -EACCES; ++ goto out; ++ } ++ ++ fc_ndlp->nlp_flag |= NLP_REG_LOGIN_SEND; ++ mbox->mbox_cmpl = lpfc_mbx_cmpl_fc_reg_login; ++ mbox->ctx_ndlp = lpfc_nlp_get(fc_ndlp); ++ if (!mbox->ctx_ndlp) { ++ rc = -ENOMEM; ++ goto out_mem; ++ } ++ ++ mbox->vport = vport; ++ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); ++ if (rc == MBX_NOT_FINISHED) { ++ rc = -ENODEV; ++ lpfc_nlp_put(fc_ndlp); ++ goto out_mem; ++ } ++ /* Success path. Exit. */ ++ lpfc_nlp_set_state(vport, fc_ndlp, ++ NLP_STE_REG_LOGIN_ISSUE); ++ return 0; ++ ++ out_mem: ++ fc_ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; ++ mp = (struct lpfc_dmabuf *)mbox->ctx_buf; ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); ++ kfree(mp); ++ ++ out: ++ mempool_free(mbox, phba->mbox_mem_pool); ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, ++ "0938 %s: failed to format reg_login " ++ "Data: x%x x%x x%x x%x\n", __func__, ++ fc_ndlp->nlp_DID, fc_ndlp->nlp_state, ++ fc_ndlp->nlp_flag, fc_ndlp->nlp_rpi); ++ return rc; ++} ++ ++/** + * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd + * @phba: pointer to lpfc hba data structure. + * @cmdiocb: pointer to lpfc command iocb data structure. +@@ -3231,10 +3320,18 @@ lpfc_issue_els_scr(struct lpfc_vport *vp + + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, + ndlp->nlp_DID, ELS_CMD_SCR); +- + if (!elsiocb) + return 1; + ++ if (phba->sli_rev == LPFC_SLI_REV4) { ++ rc = lpfc_reg_fab_ctrl_node(vport, ndlp); ++ if (rc) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, ++ "0937 %s: Failed to reg fc node, rc %d\n", ++ __func__, rc); ++ return 1; ++ } ++ } + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + + *((uint32_t *) (pcmd)) = ELS_CMD_SCR; +@@ -3522,6 +3619,17 @@ lpfc_issue_els_rdf(struct lpfc_vport *vp + if (!elsiocb) + return -ENOMEM; + ++ if (phba->sli_rev == LPFC_SLI_REV4 && ++ !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, ++ "0939 %s: FC_NODE x%x RPI x%x flag x%x " ++ "ste x%x type x%x Not registered\n", ++ __func__, ndlp->nlp_DID, ndlp->nlp_rpi, ++ ndlp->nlp_flag, ndlp->nlp_state, ++ ndlp->nlp_type); ++ return -ENODEV; ++ } ++ + /* Configure the payload for the supported FPIN events. */ + prdf = (struct lpfc_els_rdf_req *) + (((struct lpfc_dmabuf *)elsiocb->context2)->virt); +@@ -4396,7 +4504,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; + struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp; +- u32 xpt_flags = 0, did_mask = 0; + + irsp = &rspiocb->iocb; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, +@@ -4409,6 +4516,15 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag, + ndlp->nlp_state, ndlp->nlp_rpi); + ++ /* This clause allows the LOGO ACC to complete and free resources ++ * for the Fabric Domain Controller. It does deliberately skip ++ * the unreg_rpi and release rpi because some fabrics send RDP ++ * requests after logging out from the initiator. ++ */ ++ if (ndlp->nlp_type & NLP_FABRIC && ++ ((ndlp->nlp_DID & WELL_KNOWN_DID_MASK) != WELL_KNOWN_DID_MASK)) ++ goto out; ++ + if (ndlp->nlp_state == NLP_STE_NPR_NODE) { + /* NPort Recovery mode or node is just allocated */ + if (!lpfc_nlp_not_used(ndlp)) { +@@ -4416,16 +4532,11 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + * If this a fabric node that cleared its transport + * registration, release the rpi. + */ +- xpt_flags = SCSI_XPT_REGD | NVME_XPT_REGD; +- did_mask = ndlp->nlp_DID & Fabric_DID_MASK; +- if (did_mask == Fabric_DID_MASK && +- !(ndlp->fc4_xpt_flags & xpt_flags)) { +- spin_lock_irq(&ndlp->lock); +- ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; +- if (phba->sli_rev == LPFC_SLI_REV4) +- ndlp->nlp_flag |= NLP_RELEASE_RPI; +- spin_unlock_irq(&ndlp->lock); +- } ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ ndlp->nlp_flag |= NLP_RELEASE_RPI; ++ spin_unlock_irq(&ndlp->lock); + lpfc_unreg_rpi(vport, ndlp); + } else { + /* Indicate the node has already released, should +@@ -4434,7 +4545,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + cmdiocb->context1 = NULL; + } + } +- ++ out: + /* + * The driver received a LOGO from the rport and has ACK'd it. + * At this point, the driver is done so release the IOCB +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -79,9 +79,7 @@ static int + lpfc_valid_xpt_node(struct lpfc_nodelist *ndlp) + { + if (ndlp->nlp_fc4_type || +- ndlp->nlp_DID == Fabric_DID || +- ndlp->nlp_DID == NameServer_DID || +- ndlp->nlp_DID == FDMI_DID) ++ ndlp->nlp_type & NLP_FABRIC) + return 1; + return 0; + } +@@ -828,7 +826,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vpo + if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || + ((vport->port_type == LPFC_NPIV_PORT) && + ((ndlp->nlp_DID == NameServer_DID) || +- (ndlp->nlp_DID == FDMI_DID)))) ++ (ndlp->nlp_DID == FDMI_DID) || ++ (ndlp->nlp_DID == Fabric_Cntl_DID)))) + lpfc_unreg_rpi(vport, ndlp); + + /* Leave Fabric nodes alone on link down */ +@@ -4156,6 +4155,53 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_h + return; + } + ++/* ++ * This routine handles processing a Fabric Controller REG_LOGIN mailbox ++ * command upon completion. It is setup in the LPFC_MBOXQ ++ * as the completion routine when the command is handed off to the SLI layer. ++ */ ++void ++lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ++{ ++ struct lpfc_vport *vport = pmb->vport; ++ MAILBOX_t *mb = &pmb->u.mb; ++ struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); ++ struct lpfc_nodelist *ndlp; ++ ++ ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; ++ pmb->ctx_ndlp = NULL; ++ pmb->ctx_buf = NULL; ++ ++ if (mb->mbxStatus) { ++ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, ++ "0933 %s: Register FC login error: 0x%x\n", ++ __func__, mb->mbxStatus); ++ goto out; ++ } ++ ++ if (phba->sli_rev < LPFC_SLI_REV4) ++ ndlp->nlp_rpi = mb->un.varWords[0]; ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, ++ "0934 %s: Complete FC x%x RegLogin rpi x%x ste x%x\n", ++ __func__, ndlp->nlp_DID, ndlp->nlp_rpi, ++ ndlp->nlp_state); ++ ++ ndlp->nlp_flag |= NLP_RPI_REGISTERED; ++ ndlp->nlp_type |= NLP_FABRIC; ++ lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); ++ ++ out: ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); ++ kfree(mp); ++ mempool_free(pmb, phba->mbox_mem_pool); ++ ++ /* Drop the reference count from the mbox at the end after ++ * all the current reference to the ndlp have been done. ++ */ ++ lpfc_nlp_put(ndlp); ++} ++ + static void + lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) + { +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -781,6 +781,16 @@ lpfc_rcv_logo(struct lpfc_vport *vport, + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); + else + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); ++ ++ /* This clause allows the initiator to ACC the LOGO back to the ++ * Fabric Domain Controller. It does deliberately skip all other ++ * steps because some fabrics send RDP requests after logging out ++ * from the initiator. ++ */ ++ if (ndlp->nlp_type & NLP_FABRIC && ++ ((ndlp->nlp_DID & WELL_KNOWN_DID_MASK) != WELL_KNOWN_DID_MASK)) ++ return 0; ++ + if (ndlp->nlp_DID == Fabric_DID) { + if (vport->port_state <= LPFC_FDISC) + goto out; +@@ -1414,6 +1424,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_ + switch (ndlp->nlp_DID) { + case NameServer_DID: + mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; ++ /* Fabric Controller Node needs these parameters. */ ++ memcpy(&ndlp->fc_sparam, sp, sizeof(struct serv_parm)); + break; + case FDMI_DID: + mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login; +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -2758,7 +2758,6 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc + } else { + __lpfc_sli_rpi_release(vport, ndlp); + } +- + lpfc_nlp_put(ndlp); + } + } diff --git a/patches.suse/scsi-lpfc-Fix-non-optimized-ERSP-handling.patch b/patches.suse/scsi-lpfc-Fix-non-optimized-ERSP-handling.patch new file mode 100644 index 0000000..1bdb55b --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-non-optimized-ERSP-handling.patch @@ -0,0 +1,50 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:50 -0700 +Subject: scsi: lpfc: Fix non-optimized ERSP handling +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: fa21189db9ab022080e056cc6da219975da48fd6 +References: bsc#1186452 + +When processing an NVMe ERSP IU which didn't match the optimized CQE-only +path, the status was being left to the WQE status. WQE status is non-zero +as it is indicating a non-optimized completion that needs to be handled by +the driver. + +Fix by clearing the status field when falling into the non-optimized +case. Log message added to track optimized vs non-optimized debug. + +Link: https://lore.kernel.org/r/20210514195559.119853-3-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_nvme.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_nvme.c ++++ b/drivers/scsi/lpfc/lpfc_nvme.c +@@ -895,9 +895,19 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hb + nCmd->transferred_length = wcqe->total_data_placed; + nCmd->rcv_rsplen = wcqe->parameter; + nCmd->status = 0; +- /* Sanity check */ +- if (nCmd->rcv_rsplen == LPFC_NVME_ERSP_LEN) ++ ++ /* Check if this is really an ERSP */ ++ if (nCmd->rcv_rsplen == LPFC_NVME_ERSP_LEN) { ++ lpfc_ncmd->status = IOSTAT_SUCCESS; ++ lpfc_ncmd->result = 0; ++ ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, ++ "6084 NVME Completion ERSP: " ++ "xri %x placed x%x\n", ++ lpfc_ncmd->cur_iocbq.sli4_xritag, ++ wcqe->total_data_placed); + break; ++ } + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "6081 NVME Completion Protocol Error: " + "xri %x status x%x result x%x " diff --git a/patches.suse/scsi-lpfc-Fix-unreleased-RPIs-when-NPIV-ports-are-cr.patch b/patches.suse/scsi-lpfc-Fix-unreleased-RPIs-when-NPIV-ports-are-cr.patch new file mode 100644 index 0000000..700ceba --- /dev/null +++ b/patches.suse/scsi-lpfc-Fix-unreleased-RPIs-when-NPIV-ports-are-cr.patch @@ -0,0 +1,363 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:49 -0700 +Subject: scsi: lpfc: Fix unreleased RPIs when NPIV ports are created +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 01131e7aae5d30e23e3cdd1eebe51bbc5489ae8f +References: bsc#1186452 + +While testing NPIV and watching logins and used RPI levels, it was seen the +used RPI count was much higher than the number of remote ports discovered. + +Code inspection showed that remote port removals on any NPIV instance are +releasing the RPI, but not performing an UNREG_RPI with the adapter thus +the reference counting never fully drops and the RPI is never fully +released. This was happening on NPIV nodes due to a log of fabric ELS's to +fabric addresses. This lack of UNREG_RPI was introduced by a prior node +rework patch that performed the UNREG_RPI as part of node cleanup. + +To resolve the issue, do the following: + + - Restore the RPI release code, but move the location to so that it is in + line with the new node cleanup design. + + - NPIV ports now release the RPI and drop the node when the caller sets + the NLP_RELEASE_RPI flag. + + - Set the NLP_RELEASE_RPI flag in node cleanup which will trigger a + release of RPI to free pool. + + - Ensure there's an UNREG_RPI at LOGO completion so that RPI release is + completed. + + - Stop offline_prep from skipping nodes that are UNUSED. The RPI may + not have been released. + + - Stop the default RPI handling in lpfc_cmpl_els_rsp() for SLI4. + + - Fixed up debugfs RPI displays for better debugging. + +Fixes: a70e63eee1c1 ("scsi: lpfc: Fix NPIV Fabric Node reference counting") +Link: https://lore.kernel.org/r/20210514195559.119853-2-jsmart2021@gmail.com +Cc: # v5.11+ +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_debugfs.c | 7 --- + drivers/scsi/lpfc/lpfc_els.c | 79 +++++++++++++++++++++++++++++-------- + drivers/scsi/lpfc/lpfc_hbadisc.c | 27 +++++++++++- + drivers/scsi/lpfc/lpfc_init.c | 7 --- + drivers/scsi/lpfc/lpfc_nportdisc.c | 25 +++++++---- + drivers/scsi/lpfc/lpfc_sli.c | 10 +++- + 6 files changed, 115 insertions(+), 40 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -871,11 +871,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_v + len += scnprintf(buf+len, size-len, + "WWNN x%llx ", + wwn_to_u64(ndlp->nlp_nodename.u.wwn)); +- if (ndlp->nlp_flag & NLP_RPI_REGISTERED) +- len += scnprintf(buf+len, size-len, "RPI:%04d ", +- ndlp->nlp_rpi); +- else +- len += scnprintf(buf+len, size-len, "RPI:none "); ++ len += scnprintf(buf+len, size-len, "RPI:x%04x ", ++ ndlp->nlp_rpi); + len += scnprintf(buf+len, size-len, "flag:x%08x ", + ndlp->nlp_flag); + if (!ndlp->nlp_type) +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -2869,6 +2869,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba + * log into the remote port. + */ + if (ndlp->nlp_flag & NLP_TARGET_REMOVE) { ++ spin_lock_irq(&ndlp->lock); ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ ndlp->nlp_flag |= NLP_RELEASE_RPI; ++ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ++ spin_unlock_irq(&ndlp->lock); + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_DEVICE_RM); + lpfc_els_free_iocb(phba, cmdiocb); +@@ -4371,6 +4376,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; + struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp; ++ u32 xpt_flags = 0, did_mask = 0; + + irsp = &rspiocb->iocb; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, +@@ -4386,9 +4392,20 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * + if (ndlp->nlp_state == NLP_STE_NPR_NODE) { + /* NPort Recovery mode or node is just allocated */ + if (!lpfc_nlp_not_used(ndlp)) { +- /* If the ndlp is being used by another discovery +- * thread, just unregister the RPI. ++ /* A LOGO is completing and the node is in NPR state. ++ * If this a fabric node that cleared its transport ++ * registration, release the rpi. + */ ++ xpt_flags = SCSI_XPT_REGD | NVME_XPT_REGD; ++ did_mask = ndlp->nlp_DID & Fabric_DID_MASK; ++ if (did_mask == Fabric_DID_MASK && ++ !(ndlp->fc4_xpt_flags & xpt_flags)) { ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; ++ if (phba->sli_rev == LPFC_SLI_REV4) ++ ndlp->nlp_flag |= NLP_RELEASE_RPI; ++ spin_unlock_irq(&ndlp->lock); ++ } + lpfc_unreg_rpi(vport, ndlp); + } else { + /* Indicate the node has already released, should +@@ -4424,28 +4441,37 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba * + { + struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; ++ u32 mbx_flag = pmb->mbox_flag; ++ u32 mbx_cmd = pmb->u.mb.mbxCommand; + + pmb->ctx_buf = NULL; + pmb->ctx_ndlp = NULL; + +- lpfc_mbuf_free(phba, mp->virt, mp->phys); +- kfree(mp); +- mempool_free(pmb, phba->mbox_mem_pool); + if (ndlp) { + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, +- "0006 rpi x%x DID:%x flg:%x %d x%px\n", ++ "0006 rpi x%x DID:%x flg:%x %d x%px " ++ "mbx_cmd x%x mbx_flag x%x x%px\n", + ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, +- kref_read(&ndlp->kref), +- ndlp); +- /* This is the end of the default RPI cleanup logic for +- * this ndlp and it could get released. Clear the nlp_flags to +- * prevent any further processing. ++ kref_read(&ndlp->kref), ndlp, mbx_cmd, ++ mbx_flag, pmb); ++ ++ /* This ends the default/temporary RPI cleanup logic for this ++ * ndlp and the node and rpi needs to be released. Free the rpi ++ * first on an UNREG_LOGIN and then release the final ++ * references. + */ ++ spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; ++ if (mbx_cmd == MBX_UNREG_LOGIN) ++ ndlp->nlp_flag &= ~NLP_UNREG_INP; ++ spin_unlock_irq(&ndlp->lock); + lpfc_nlp_put(ndlp); +- lpfc_nlp_not_used(ndlp); ++ lpfc_drop_node(ndlp->vport, ndlp); + } + ++ lpfc_mbuf_free(phba, mp->virt, mp->phys); ++ kfree(mp); ++ mempool_free(pmb, phba->mbox_mem_pool); + return; + } + +@@ -4503,11 +4529,11 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, + /* ELS response tag completes */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0110 ELS response tag x%x completes " +- "Data: x%x x%x x%x x%x x%x x%x x%x\n", ++ "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%px\n", + cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, + rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, +- ndlp->nlp_rpi); ++ ndlp->nlp_rpi, kref_read(&ndlp->kref), mbox); + if (mbox) { + if ((rspiocb->iocb.ulpStatus == 0) && + (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { +@@ -4587,6 +4613,16 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, + spin_unlock_irq(&ndlp->lock); + } + ++ /* An SLI4 NPIV instance wants to drop the node at this point under ++ * these conditions and release the RPI. ++ */ ++ if (phba->sli_rev == LPFC_SLI_REV4 && ++ (vport && vport->port_type == LPFC_NPIV_PORT) && ++ ndlp->nlp_flag & NLP_RELEASE_RPI) { ++ lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); ++ lpfc_drop_node(vport, ndlp); ++ } ++ + /* Release the originating I/O reference. */ + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); +@@ -4775,10 +4811,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vpor + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0128 Xmit ELS ACC response Status: x%x, IoTag: x%x, " + "XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x " +- "RPI: x%x, fc_flag x%x\n", ++ "RPI: x%x, fc_flag x%x refcnt %d\n", + rc, elsiocb->iotag, elsiocb->sli4_xritag, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, +- ndlp->nlp_rpi, vport->fc_flag); ++ ndlp->nlp_rpi, vport->fc_flag, kref_read(&ndlp->kref)); + return 0; + } + +@@ -4856,6 +4892,17 @@ lpfc_els_rsp_reject(struct lpfc_vport *v + return 1; + } + ++ /* The NPIV instance is rejecting this unsolicited ELS. Make sure the ++ * node's assigned RPI needs to be released as this node will get ++ * freed. ++ */ ++ if (phba->sli_rev == LPFC_SLI_REV4 && ++ vport->port_type == LPFC_NPIV_PORT) { ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_flag |= NLP_RELEASE_RPI; ++ spin_unlock_irq(&ndlp->lock); ++ } ++ + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) { + lpfc_els_free_iocb(phba, elsiocb); +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -4786,12 +4786,17 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phb + ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING; + lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); + } else { ++ /* NLP_RELEASE_RPI is only set for SLI4 ports. */ + if (ndlp->nlp_flag & NLP_RELEASE_RPI) { + lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); ++ spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_RELEASE_RPI; + ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; ++ spin_unlock_irq(&ndlp->lock); + } ++ spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_UNREG_INP; ++ spin_unlock_irq(&ndlp->lock); + } + } + +@@ -5126,8 +5131,10 @@ lpfc_cleanup_node(struct lpfc_vport *vpo + list_del_init(&ndlp->dev_loss_evt.evt_listp); + list_del_init(&ndlp->recovery_evt.evt_listp); + lpfc_cleanup_vports_rrqs(vport, ndlp); ++ + if (phba->sli_rev == LPFC_SLI_REV4) + ndlp->nlp_flag |= NLP_RELEASE_RPI; ++ + return 0; + } + +@@ -6172,8 +6179,23 @@ lpfc_nlp_release(struct kref *kref) + lpfc_cancel_retry_delay_tmo(vport, ndlp); + lpfc_cleanup_node(vport, ndlp); + +- /* Clear Node key fields to give other threads notice +- * that this node memory is not valid anymore. ++ /* Not all ELS transactions have registered the RPI with the port. ++ * In these cases the rpi usage is temporary and the node is ++ * released when the WQE is completed. Catch this case to free the ++ * RPI to the pool. Because this node is in the release path, a lock ++ * is unnecessary. All references are gone and the node has been ++ * dequeued. ++ */ ++ if (ndlp->nlp_flag & NLP_RELEASE_RPI) { ++ if (ndlp->nlp_rpi != LPFC_RPI_ALLOC_ERROR && ++ !(ndlp->nlp_flag & (NLP_RPI_REGISTERED | NLP_UNREG_INP))) { ++ lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); ++ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; ++ } ++ } ++ ++ /* The node is not freed back to memory, it is released to a pool so ++ * the node fields need to be cleaned up. + */ + ndlp->vport = NULL; + ndlp->nlp_state = NLP_STE_FREED_NODE; +@@ -6253,6 +6275,7 @@ lpfc_nlp_not_used(struct lpfc_nodelist * + "node not used: did:x%x flg:x%x refcnt:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, + kref_read(&ndlp->kref)); ++ + if (kref_read(&ndlp->kref) == 1) + if (lpfc_nlp_put(ndlp)) + return 1; +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -3535,13 +3535,6 @@ lpfc_offline_prep(struct lpfc_hba *phba, + list_for_each_entry_safe(ndlp, next_ndlp, + &vports[i]->fc_nodes, + nlp_listp) { +- if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { +- /* Driver must assume RPI is invalid for +- * any unused or inactive node. +- */ +- ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; +- continue; +- } + + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -564,15 +564,24 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, + /* no deferred ACC */ + kfree(save_iocb); + +- /* In order to preserve RPIs, we want to cleanup +- * the default RPI the firmware created to rcv +- * this ELS request. The only way to do this is +- * to register, then unregister the RPI. ++ /* This is an NPIV SLI4 instance that does not need to register ++ * a default RPI. + */ +- spin_lock_irq(&ndlp->lock); +- ndlp->nlp_flag |= (NLP_RM_DFLT_RPI | NLP_ACC_REGLOGIN | +- NLP_RCV_PLOGI); +- spin_unlock_irq(&ndlp->lock); ++ if (phba->sli_rev == LPFC_SLI_REV4) { ++ mempool_free(login_mbox, phba->mbox_mem_pool); ++ login_mbox = NULL; ++ } else { ++ /* In order to preserve RPIs, we want to cleanup ++ * the default RPI the firmware created to rcv ++ * this ELS request. The only way to do this is ++ * to register, then unregister the RPI. ++ */ ++ spin_lock_irq(&ndlp->lock); ++ ndlp->nlp_flag |= (NLP_RM_DFLT_RPI | NLP_ACC_REGLOGIN | ++ NLP_RCV_PLOGI); ++ spin_unlock_irq(&ndlp->lock); ++ } ++ + stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD; + stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; + rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -13497,9 +13497,15 @@ lpfc_sli4_sp_handle_mbox_event(struct lp + if (mcqe_status == MB_CQE_STATUS_SUCCESS) { + mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); + ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; +- /* Reg_LOGIN of dflt RPI was successful. Now lets get +- * RID of the PPI using the same mbox buffer. ++ ++ /* Reg_LOGIN of dflt RPI was successful. Mark the ++ * node as having an UNREG_LOGIN in progress to stop ++ * an unsolicited PLOGI from the same NPortId from ++ * starting another mailbox transaction. + */ ++ spin_lock_irqsave(&ndlp->lock, iflags); ++ ndlp->nlp_flag |= NLP_UNREG_INP; ++ spin_unlock_irqrestore(&ndlp->lock, iflags); + lpfc_unreg_login(phba, vport->vpi, + pmbox->un.varWords[0], pmb); + pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; diff --git a/patches.suse/scsi-lpfc-Ignore-GID-FT-response-that-may-be-receive.patch b/patches.suse/scsi-lpfc-Ignore-GID-FT-response-that-may-be-receive.patch new file mode 100644 index 0000000..d360752 --- /dev/null +++ b/patches.suse/scsi-lpfc-Ignore-GID-FT-response-that-may-be-receive.patch @@ -0,0 +1,164 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:55 -0700 +Subject: scsi: lpfc: Ignore GID-FT response that may be received after a link + flip +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 04c1d9c50ae32d6efd0b71024b3829051821c7a2 +References: bsc#1186452 + +When a link bounce happens, there is a possibility that responses to +requests posted prior to the link bounce could be received. This is +problematic as the counter to track reglogin completion after link up can +become out of sync with the real state. + +As there is no reason to process a request made in a prior link up context, +eliminate all the disturbance by tagging the request with the event_tag +maintained by the SLI Port for the link. The event_tag will change on every +link state transition. As long as the tag matches the current event_tag, +the response can be processed. If it doesn't match, just discard the +response. + +Link: https://lore.kernel.org/r/20210514195559.119853-8-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_ct.c | 43 ++++++++++++++++++++++++++++++++++++------- + drivers/scsi/lpfc/lpfc_sli.h | 3 ++- + 2 files changed, 38 insertions(+), 8 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -588,7 +588,7 @@ lpfc_gen_req(struct lpfc_vport *vport, s + struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, + void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_iocbq *), +- struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry, ++ struct lpfc_nodelist *ndlp, uint32_t event_tag, uint32_t num_entry, + uint32_t tmo, uint8_t retry) + { + struct lpfc_hba *phba = vport->phba; +@@ -609,15 +609,14 @@ lpfc_gen_req(struct lpfc_vport *vport, s + icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; + icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64)); + +- if (usr_flg) +- geniocb->context3 = NULL; +- else +- geniocb->context3 = (uint8_t *) bmp; ++ geniocb->context3 = (uint8_t *) bmp; + + /* Save for completion so we can release these resources */ + geniocb->context1 = (uint8_t *) inp; + geniocb->context2 = (uint8_t *) outp; + ++ geniocb->event_tag = event_tag; ++ + /* Fill in payload, bp points to frame payload */ + icmd->ulpCommand = CMD_GEN_REQUEST64_CR; + +@@ -708,8 +707,8 @@ lpfc_ct_cmd(struct lpfc_vport *vport, st + * lpfc_alloc_ct_rsp. + */ + cnt += 1; +- status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0, +- cnt, 0, retry); ++ status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, ++ phba->fc_eventTag, cnt, 0, retry); + if (status) { + lpfc_free_ct_rsp(phba, outmp); + return -ENOMEM; +@@ -958,6 +957,13 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba + "GID_FT cmpl: status:x%x/x%x rtry:%d", + irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); + ++ /* Ignore response if link flipped after this request was made */ ++ if (cmdiocb->event_tag != phba->fc_eventTag) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, ++ "9043 Event tag mismatch. Ignoring NS rsp\n"); ++ goto out; ++ } ++ + /* Don't bother processing response if vport is being torn down. */ + if (vport->load_flag & FC_UNLOADING) { + if (vport->fc_flag & FC_RSCN_MODE) +@@ -1168,6 +1174,13 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba + irsp->ulpStatus, irsp->un.ulpWord[4], + vport->fc_ns_retry); + ++ /* Ignore response if link flipped after this request was made */ ++ if (cmdiocb->event_tag != phba->fc_eventTag) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, ++ "9044 Event tag mismatch. Ignoring NS rsp\n"); ++ goto out; ++ } ++ + /* Don't bother processing response if vport is being torn down. */ + if (vport->load_flag & FC_UNLOADING) { + if (vport->fc_flag & FC_RSCN_MODE) +@@ -1367,6 +1380,13 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba + "GFF_ID cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], did); + ++ /* Ignore response if link flipped after this request was made */ ++ if (cmdiocb->event_tag != phba->fc_eventTag) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, ++ "9045 Event tag mismatch. Ignoring NS rsp\n"); ++ goto iocb_free; ++ } ++ + if (irsp->ulpStatus == IOSTAT_SUCCESS) { + /* Good status, continue checking */ + CTrsp = (struct lpfc_sli_ct_request *) outp->virt; +@@ -1480,6 +1500,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba + lpfc_disc_start(vport); + } + ++iocb_free: + free_ndlp = cmdiocb->context_un.ndlp; + lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); +@@ -1507,6 +1528,13 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba + "GFT_ID cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], did); + ++ /* Ignore response if link flipped after this request was made */ ++ if ((uint32_t) cmdiocb->event_tag != phba->fc_eventTag) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, ++ "9046 Event tag mismatch. Ignoring NS rsp\n"); ++ goto out; ++ } ++ + /* Preserve the nameserver node to release the reference. */ + ns_ndlp = cmdiocb->context_un.ndlp; + +@@ -1573,6 +1601,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); + ++out: + lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ns_ndlp); + } +--- a/drivers/scsi/lpfc/lpfc_sli.h ++++ b/drivers/scsi/lpfc/lpfc_sli.h +@@ -1,7 +1,7 @@ + /******************************************************************* + * This file is part of the Emulex Linux Device Driver for * + * Fibre Channel Host Bus Adapters. * +- * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * ++ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term * + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * + * Copyright (C) 2004-2016 Emulex. All rights reserved. * + * EMULEX and SLI are trademarks of Emulex. * +@@ -106,6 +106,7 @@ struct lpfc_iocbq { + void *context1; /* caller context information */ + void *context2; /* caller context information */ + void *context3; /* caller context information */ ++ uint32_t event_tag; /* LA Event tag */ + union { + wait_queue_head_t *wait_queue; + struct lpfc_iocbq *rsp_iocb; diff --git a/patches.suse/scsi-lpfc-Reregister-FPIN-types-if-ELS_RDF-is-receiv.patch b/patches.suse/scsi-lpfc-Reregister-FPIN-types-if-ELS_RDF-is-receiv.patch new file mode 100644 index 0000000..ab7be52 --- /dev/null +++ b/patches.suse/scsi-lpfc-Reregister-FPIN-types-if-ELS_RDF-is-receiv.patch @@ -0,0 +1,143 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:58 -0700 +Subject: scsi: lpfc: Reregister FPIN types if ELS_RDF is received from fabric + controller +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: 8eced807077d198fc264629bd2592795d270c9f1 +References: bsc#1186452 + +FC-LS-5 specifies that a received RDF implies a possible change to fabric +supported diagnostic functions. Endpoints are to re-perform the RDF +exchange with the fabric to enable possible new features or adapt to +changes in values. + +This patch adds the logic to RDF receive to re-perform the RDF exchange +with the switch. + +Link: https://lore.kernel.org/r/20210514195559.119853-11-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc.h | 1 + drivers/scsi/lpfc/lpfc_els.c | 75 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 76 insertions(+) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -266,6 +266,7 @@ struct lpfc_stats { + uint32_t elsRcvECHO; + uint32_t elsRcvLCB; + uint32_t elsRcvRDP; ++ uint32_t elsRcvRDF; + uint32_t elsXmitFLOGI; + uint32_t elsXmitFDISC; + uint32_t elsXmitPLOGI; +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -3670,6 +3670,43 @@ lpfc_issue_els_rdf(struct lpfc_vport *vp + return 0; + } + ++ /** ++ * lpfc_els_rcv_rdf - Receive RDF ELS request from the fabric. ++ * @vport: pointer to a host virtual N_Port data structure. ++ * @cmdiocb: pointer to lpfc command iocb data structure. ++ * @ndlp: pointer to a node-list data structure. ++ * ++ * A received RDF implies a possible change to fabric supported diagnostic ++ * functions. This routine sends LS_ACC and then has the Nx_Port issue a new ++ * RDF request to reregister for supported diagnostic functions. ++ * ++ * Return code ++ * 0 - Success ++ * -EIO - Failed to process received RDF ++ **/ ++static int ++lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ++ struct lpfc_nodelist *ndlp) ++{ ++ /* Send LS_ACC */ ++ if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "1623 Failed to RDF_ACC from x%x for x%x\n", ++ ndlp->nlp_DID, vport->fc_myDID); ++ return -EIO; ++ } ++ ++ /* Issue new RDF for reregistering */ ++ if (lpfc_issue_els_rdf(vport, 0)) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, ++ "2623 Failed to re register RDF for x%x\n", ++ vport->fc_myDID); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ + /** + * lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry + * @vport: pointer to a host virtual N_Port data structure. +@@ -4803,6 +4840,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vpor + uint16_t cmdsize; + int rc; + ELS_PKT *els_pkt_ptr; ++ struct fc_els_rdf_resp *rdf_resp; + + oldcmd = &oldiocb->iocb; + +@@ -4914,6 +4952,29 @@ lpfc_els_rsp_acc(struct lpfc_vport *vpor + "Issue ACC PRLO: did:x%x flg:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, 0); + break; ++ case ELS_CMD_RDF: ++ cmdsize = sizeof(*rdf_resp); ++ elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ++ ndlp, ndlp->nlp_DID, ELS_CMD_ACC); ++ if (!elsiocb) ++ return 1; ++ ++ icmd = &elsiocb->iocb; ++ icmd->ulpContext = oldcmd->ulpContext; /* Xri / rx_id */ ++ icmd->unsli3.rcvsli3.ox_id = oldcmd->unsli3.rcvsli3.ox_id; ++ pcmd = (((struct lpfc_dmabuf *)elsiocb->context2)->virt); ++ rdf_resp = (struct fc_els_rdf_resp *)pcmd; ++ memset(rdf_resp, 0, sizeof(*rdf_resp)); ++ rdf_resp->acc_hdr.la_cmd = ELS_LS_ACC; ++ ++ /* FC-LS-5 specifies desc_list_len shall be set to 12 */ ++ rdf_resp->desc_list_len = cpu_to_be32(12); ++ ++ /* FC-LS-5 specifies LS REQ Information descriptor */ ++ rdf_resp->lsri.desc_tag = cpu_to_be32(1); ++ rdf_resp->lsri.desc_len = cpu_to_be32(sizeof(u32)); ++ rdf_resp->lsri.rqst_w0.cmd = ELS_RDF; ++ break; + default: + return 1; + } +@@ -9027,6 +9088,20 @@ lpfc_els_unsol_buffer(struct lpfc_hba *p + + /* There are no replies, so no rjt codes */ + break; ++ case ELS_CMD_RDF: ++ phba->fc_stat.elsRcvRDF++; ++ /* Accept RDF only from fabric controller */ ++ if (did != Fabric_Cntl_DID) { ++ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, ++ "1115 Received RDF from invalid DID " ++ "x%x\n", did); ++ rjt_err = LSRJT_PROTOCOL_ERR; ++ rjt_exp = LSEXP_NOTHING_MORE; ++ goto lsrjt; ++ } ++ ++ lpfc_els_rcv_rdf(vport, elsiocb, ndlp); ++ break; + default: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, + "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", diff --git a/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.10.patch b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.10.patch new file mode 100644 index 0000000..b19a3d3 --- /dev/null +++ b/patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.10.patch @@ -0,0 +1,31 @@ +From: James Smart +Date: Fri, 14 May 2021 12:55:59 -0700 +Subject: scsi: lpfc: Update lpfc version to 12.8.0.10 +Patch-mainline: Queued in subsystem maintainer repository +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git +Git-commit: e5e0280db792953ee7acbdbf01179d53187a6083 +References: bsc#1186452 + +Update lpfc version to 12.8.0.10 + +Link: https://lore.kernel.org/r/20210514195559.119853-12-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Acked-by: Daniel Wagner +--- + drivers/scsi/lpfc/lpfc_version.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/lpfc/lpfc_version.h ++++ b/drivers/scsi/lpfc/lpfc_version.h +@@ -20,7 +20,7 @@ + * included with this package. * + *******************************************************************/ + +-#define LPFC_DRIVER_VERSION "12.8.0.9" ++#define LPFC_DRIVER_VERSION "12.8.0.10" + #define LPFC_DRIVER_NAME "lpfc" + + /* Used for SLI 2/3 */ diff --git a/patches.suse/sctp-delay-auto_asconf-init-until-binding-the-first-.patch b/patches.suse/sctp-delay-auto_asconf-init-until-binding-the-first-.patch new file mode 100644 index 0000000..02aca9c --- /dev/null +++ b/patches.suse/sctp-delay-auto_asconf-init-until-binding-the-first-.patch @@ -0,0 +1,103 @@ +Message-Id: <94980f802bdcec0fcc50f6e2add841ba70c311cc.1620752894.git.mkubecek@suse.cz> +From: Xin Long +Date: Mon, 3 May 2021 05:11:42 +0800 +Subject: sctp: delay auto_asconf init until binding the first addr +Patch-mainline: v5.13-rc1 +Git-commit: 34e5b01186858b36c4d7c87e1a025071e8e2401f +References: CVE-2021-23133 bsc#1184675 + +As Or Cohen described: + + If sctp_destroy_sock is called without sock_net(sk)->sctp.addr_wq_lock + held and sp->do_auto_asconf is true, then an element is removed + from the auto_asconf_splist without any proper locking. + + This can happen in the following functions: + 1. In sctp_accept, if sctp_sock_migrate fails. + 2. In inet_create or inet6_create, if there is a bpf program + attached to BPF_CGROUP_INET_SOCK_CREATE which denies + creation of the sctp socket. + +This patch is to fix it by moving the auto_asconf init out of +sctp_init_sock(), by which inet_create()/inet6_create() won't +need to operate it in sctp_destroy_sock() when calling +sk_common_release(). + +It also makes more sense to do auto_asconf init while binding the +first addr, as auto_asconf actually requires an ANY addr bind, +see it in sctp_addr_wq_timeout_handler(). + +This addresses CVE-2021-23133. + +Fixes: 610236587600 ("bpf: Add new cgroup attach type to enable sock modifications") +Reported-by: Or Cohen +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Acked-by: Michal Kubecek + +--- + net/sctp/socket.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -353,6 +353,18 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, + return af; + } + ++static void sctp_auto_asconf_init(struct sctp_sock *sp) ++{ ++ struct net *net = sock_net(&sp->inet.sk); ++ ++ if (net->sctp.default_auto_asconf) { ++ spin_lock(&net->sctp.addr_wq_lock); ++ list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist); ++ spin_unlock(&net->sctp.addr_wq_lock); ++ sp->do_auto_asconf = 1; ++ } ++} ++ + /* Bind a local address either to an endpoint or to an association. */ + static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) + { +@@ -415,8 +427,10 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) + } + + /* Refresh ephemeral port. */ +- if (!bp->port) ++ if (!bp->port) { + bp->port = inet_sk(sk)->inet_num; ++ sctp_auto_asconf_init(sp); ++ } + + /* Add the address to the bind address list. + * Use GFP_ATOMIC since BHs will be disabled. +@@ -4419,19 +4433,6 @@ static int sctp_init_sock(struct sock *sk) + sk_sockets_allocated_inc(sk); + sock_prot_inuse_add(net, sk->sk_prot, 1); + +- /* Nothing can fail after this block, otherwise +- * sctp_destroy_sock() will be called without addr_wq_lock held +- */ +- if (net->sctp.default_auto_asconf) { +- spin_lock(&sock_net(sk)->sctp.addr_wq_lock); +- list_add_tail(&sp->auto_asconf_list, +- &net->sctp.auto_asconf_splist); +- sp->do_auto_asconf = 1; +- spin_unlock(&sock_net(sk)->sctp.addr_wq_lock); +- } else { +- sp->do_auto_asconf = 0; +- } +- + local_bh_enable(); + + return 0; +@@ -8130,6 +8131,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, + sctp_bind_addr_dup(&newsp->ep->base.bind_addr, + &oldsp->ep->base.bind_addr, GFP_KERNEL); + ++ sctp_auto_asconf_init(newsp); ++ + /* Move any messages in the old socket's receive queue that are for the + * peeled off association to the new socket's receive queue. + */ diff --git a/patches.suse/usb-core-hub-fix-race-condition-about-TRSMRCY-of-res.patch b/patches.suse/usb-core-hub-fix-race-condition-about-TRSMRCY-of-res.patch new file mode 100644 index 0000000..4c21413 --- /dev/null +++ b/patches.suse/usb-core-hub-fix-race-condition-about-TRSMRCY-of-res.patch @@ -0,0 +1,50 @@ +From 975f94c7d6c306b833628baa9aec3f79db1eb3a1 Mon Sep 17 00:00:00 2001 +From: Chunfeng Yun +Date: Wed, 12 May 2021 10:07:38 +0800 +Subject: [PATCH] usb: core: hub: fix race condition about TRSMRCY of resume +Git-commit: 975f94c7d6c306b833628baa9aec3f79db1eb3a1 +References: git-fixes +Patch-mainline: v5.13-rc2 + +This may happen if the port becomes resume status exactly +when usb_port_resume() gets port status, it still need provide +a TRSMCRY time before access the device. + +CC: +Reported-by: Tianping Fang +Acked-by: Alan Stern +Signed-off-by: Chunfeng Yun +Link: https://lore.kernel.org/r/20210512020738.52961-1-chunfeng.yun@mediatek.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/core/hub.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index b2bc4b7c4289..fc7d6cdacf16 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3642,9 +3642,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + * sequence. + */ + status = hub_port_status(hub, port1, &portstatus, &portchange); +- +- /* TRSMRCY = 10 msec */ +- msleep(10); + } + + SuspendCleared: +@@ -3659,6 +3656,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_SUSPEND); + } ++ ++ /* TRSMRCY = 10 msec */ ++ msleep(10); + } + + if (udev->persist_enabled) +-- +2.26.2 + diff --git a/patches.suse/usb-xhci-Increase-timeout-for-HC-halt.patch b/patches.suse/usb-xhci-Increase-timeout-for-HC-halt.patch new file mode 100644 index 0000000..0cfa8ae --- /dev/null +++ b/patches.suse/usb-xhci-Increase-timeout-for-HC-halt.patch @@ -0,0 +1,38 @@ +From ca09b1bea63ab83f4cca3a2ae8bc4f597ec28851 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Wed, 12 May 2021 11:08:15 +0300 +Subject: [PATCH] usb: xhci: Increase timeout for HC halt +Git-commit: ca09b1bea63ab83f4cca3a2ae8bc4f597ec28851 +References: git-fixes +Patch-mainline: v5.13-rc2 + +On some devices (specifically the SC8180x based Surface Pro X with +QCOM04A6) HC halt / xhci_halt() times out during boot. Manually binding +the xhci-hcd driver at some point later does not exhibit this behavior. +To work around this, double XHCI_MAX_HALT_USEC, which also resolves this +issue. + +Cc: +Signed-off-by: Maximilian Luz +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20210512080816.866037-5-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci-ext-caps.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci-ext-caps.h ++++ b/drivers/usb/host/xhci-ext-caps.h +@@ -19,8 +19,9 @@ + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +-/* Up to 16 ms to halt an HC */ +-#define XHCI_MAX_HALT_USEC (16*1000) ++ ++/* HC should halt within 16 ms, but use 32 ms as some hosts take longer */ ++#define XHCI_MAX_HALT_USEC (32 * 1000) + /* HC not running - set to 1 when run/stop bit is cleared. */ + #define XHCI_STS_HALT (1<<0) + diff --git a/patches.suse/xhci-Do-not-use-GFP_KERNEL-in-potentially-atomic-con.patch b/patches.suse/xhci-Do-not-use-GFP_KERNEL-in-potentially-atomic-con.patch new file mode 100644 index 0000000..cc83122 --- /dev/null +++ b/patches.suse/xhci-Do-not-use-GFP_KERNEL-in-potentially-atomic-con.patch @@ -0,0 +1,58 @@ +From dda32c00c9a0fa103b5d54ef72c477b7aa993679 Mon Sep 17 00:00:00 2001 +From: Christophe JAILLET +Date: Wed, 12 May 2021 11:08:14 +0300 +Subject: [PATCH] xhci: Do not use GFP_KERNEL in (potentially) atomic context +Git-commit: dda32c00c9a0fa103b5d54ef72c477b7aa993679 +References: git-fixes +Patch-mainline: v5.13-rc2 + +'xhci_urb_enqueue()' is passed a 'mem_flags' argument, because "URBs may be +submitted in interrupt context" (see comment related to 'usb_submit_urb()' +in 'drivers/usb/core/urb.c') + +So this flag should be used in all the calling chain. +Up to now, 'xhci_check_maxpacket()' which is only called from +'xhci_urb_enqueue()', uses GFP_KERNEL. + +Be safe and pass the mem_flags to this function as well. + +Fixes: ddba5cd0aeff ("xhci: Use command structures when queuing commands on the command ring") +Cc: +Signed-off-by: Christophe JAILLET +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20210512080816.866037-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Oliver Neukum +--- + drivers/usb/host/xhci.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1386,7 +1386,7 @@ static int xhci_configure_endpoint(struc + * we need to issue an evaluate context command and wait on it. + */ + static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, +- unsigned int ep_index, struct urb *urb) ++ unsigned int ep_index, struct urb *urb, gfp_t mem_flags) + { + struct xhci_container_ctx *out_ctx; + struct xhci_input_control_ctx *ctrl_ctx; +@@ -1417,7 +1417,7 @@ static int xhci_check_maxpacket(struct x + * changes max packet sizes. + */ + +- command = xhci_alloc_command(xhci, false, true, GFP_KERNEL); ++ command = xhci_alloc_command(xhci, false, true, mem_flags); + if (!command) + return -ENOMEM; + +@@ -1508,7 +1508,7 @@ static int xhci_urb_enqueue(struct usb_h + */ + if (urb->dev->speed == USB_SPEED_FULL) { + ret = xhci_check_maxpacket(xhci, slot_id, +- ep_index, urb); ++ ep_index, urb, mem_flags); + if (ret < 0) { + xhci_urb_free_priv(urb_priv); + urb->hcpriv = NULL; diff --git a/scripts/lib/SUSE/MyBS.pm b/scripts/lib/SUSE/MyBS.pm index dd53462..afb9840 100644 --- a/scripts/lib/SUSE/MyBS.pm +++ b/scripts/lib/SUSE/MyBS.pm @@ -566,6 +566,10 @@ sub upload_package { $self->delete("/source/$project/$link"); &$progresscb('DELETE', "$project/$link"); } + # delete stale kernel-obs-build + my $kob = "kernel-obs-build"; + $self->post("/build/$project?cmd=wipe&package=$kob"); + &$progresscb('WIPE', "$project $kob"); return $revision; } diff --git a/series.conf b/series.conf index 0b6ae2a..aeac709 100644 --- a/series.conf +++ b/series.conf @@ -33966,6 +33966,8 @@ patches.suse/mm-pkeys-x86-powerpc-Display-pkey-in-smaps-if-arch-s.patch patches.suse/powerpc-pkeys-Drop-private-VM_PKEY-definitions.patch patches.suse/powerpc-powernv-ioda2-Remove-redundant-free-of-TCE-p.patch + patches.suse/powerpc-64-remove-start_tb-and-accum_tb-from-thread_.patch + patches.suse/powerpc-pseries-lparcfg-calculate-PURR-on-demand.patch patches.suse/powerpc-mm-hugetlb-Update-huge_ptep_set_access_flags.patch patches.suse/powerpc-mm-radix-Move-function-from-radix.h-to-pgtab.patch patches.suse/powerpc-mm-Change-function-prototype.patch @@ -47074,6 +47076,7 @@ patches.suse/wil6210-ignore-HALP-ICR-if-already-handled.patch patches.suse/wil6210-check-null-pointer-in-_wil_cfg80211_merge_ex.patch patches.suse/Bluetooth-hci_ldisc-Postpone-HCI_UART_PROTO_READY-bi.patch + patches.suse/netfilter-conntrack-tcp-only-close-if-RST-matches-ex.patch patches.suse/netfilter-nf_tables-check-the-result-of-dereferencin.patch patches.suse/net-mlx5-Update-the-list-of-the-PCI-supported-device-85327a9c.patch patches.suse/tls-Fix-tls_device-handling-of-partial-records.patch @@ -48162,6 +48165,7 @@ patches.suse/fs-open.c-allow-opening-only-regular-files-during-ex.patch patches.suse/mm-hotplug-fix-offline-undo_isolate_page_range.patch patches.suse/ocfs2-fix-inode-bh-swapping-mixup-in-ocfs2_reflink_i.patch + patches.suse/0001-mm-mempolicy-make-mbind-return-EIO-when-MPOL_MF_STRI.patch patches.suse/0001-mm-debug.c-fix-__dump_page-when-mapping-host-is-not-.patch patches.suse/ptrace-take-into-account-saved_sigmask-in-PTRACE-GET.patch patches.suse/0001-mm-page_isolation.c-fix-a-wrong-flag-in-set_migratet.patch @@ -53033,6 +53037,9 @@ patches.suse/kvm-vmx-implement-msr_ia32_tsx_ctrl-disable-rtm-functionality patches.suse/kvm-vmx-use-msr_ia32_tsx_ctrl-to-hard-disable-tsx-on-guest-that-lack-it patches.suse/kvm-x86-remove-a-spurious-export-of-a-static-function + patches.suse/edac-amd64-make-struct-amd64_family_type-global.patch + patches.suse/edac-amd64-gather-hardware-information-early.patch + patches.suse/edac-amd64-save-max-number-of-controllers-to-family-type.patch patches.suse/edac-ghes-fix-locking-and-memory-barrier-issues.patch patches.suse/edac-ghes-do-not-warn-when-incrementing-refcount-on-0.patch patches.suse/0001-workqueue-Fix-pwq-ref-leak-in-rescuer_thread.patch @@ -55981,6 +55988,7 @@ patches.suse/staging-rtl8712-Fix-IEEE80211_ADDBA_PARAM_BUF_SIZE_M.patch patches.suse/drivers-base-Fix-NULL-pointer-exception-in-__platfor.patch patches.suse/drivers-char-tlclk.c-Avoid-data-race-between-init-an.patch + patches.suse/msft-hv-2080-uio_hv_generic-add-missed-sysfs_remove_bin_file.patch patches.suse/fpga-dfl-afu-Corrected-error-handling-levels.patch patches.suse/dev-mem-Revoke-mappings-when-a-driver-claims-the-reg.patch patches.suse/w1-omap-hdq-cleanup-to-add-missing-newline-for-some-.patch @@ -56323,6 +56331,7 @@ patches.suse/0001-ipvs-fix-the-connection-sync-failed-in-some-cases.patch patches.suse/0010-dev-Defer-free-of-skbs-in-flush_backlog.patch patches.suse/x86-unwind-orc-fix-orc-for-newly-forked-tasks.patch + patches.suse/scsi-core-Run-queue-in-case-of-I-O-resource-contenti.patch patches.suse/usb-xhci-mtk-fix-the-failure-of-bandwidth-allocation.patch patches.suse/usb-xhci-Fix-ASM2142-ASM3142-DMA-addressing.patch patches.suse/vt-Reject-zero-sized-screen-buffer-size.patch @@ -57542,6 +57551,7 @@ patches.suse/docs-ABI-sysfs-c2port-remove-a-duplicated-entry.patch patches.suse/futex-Fix-incorrect-should_fail_futex-handling.patch patches.suse/time-Prevent-undefined-behaviour-in-timespec64_to_ns.patch + patches.suse/0001-mm-mempolicy-fix-potential-pte_unmap_unlock-pte-erro.patch patches.suse/lib-crc32test-remove-extra-local_irq_disable-enable.patch patches.suse/kthread_worker-prevent-queuing-delayed-work-from-tim.patch patches.suse/mm-always-have-io_remap_pfn_range-set-pgprot_decrypted.patch @@ -57875,6 +57885,7 @@ patches.suse/serial-8250_omap-Avoid-FIFO-corruption-caused-by-MDR.patch patches.suse/misc-vmw_vmci-fix-kernel-info-leak-by-initializing-d.patch patches.suse/bus-fsl-mc-fix-error-return-code-in-fsl_mc_object_al.patch + patches.suse/msft-hv-2197-uio-uio_hv_generic-use-devm_kzalloc-for-private-data.patch patches.suse/extcon-max77693-Fix-modalias-string.patch patches.suse/iio-buffer-Fix-demux-update.patch patches.suse/iio-imu-bmi160-Fix-too-large-a-buffer.patch @@ -58163,6 +58174,7 @@ patches.suse/platform-x86-i2c-multi-instantiate-Don-t-create-plat.patch patches.suse/mmc-sdhci-xenon-fix-1.8v-regulator-stabilization.patch patches.suse/dm-avoid-filesystem-lookup-in-dm_get_dev_t.patch + patches.suse/scsi-libfc-Avoid-invoking-response-handler-twice-if-.patch patches.suse/scsi-ibmvfc-Set-default-timeout-to-avoid-crash-durin.patch patches.suse/i2c-octeon-check-correct-size-of-maximum-RECV_LEN-pa.patch patches.suse/objtool-don-t-fail-on-missing-symbol-table.patch @@ -58416,6 +58428,7 @@ patches.suse/ibmvnic-remove-excessive-irqsave.patch patches.suse/gianfar-fix-jumbo-packets-napi-rx-overrun-crash.patch patches.suse/ethernet-alx-fix-order-of-calls-on-resume.patch + patches.suse/netfilter-conntrack-avoid-misleading-invalid-in-log-.patch patches.suse/cifs-print-MIDs-in-decimal-notation.patch patches.suse/cifs-change-noisy-error-message-to-FYI.patch patches.suse/cifs-return-proper-error-code-in-statfs-2-.patch @@ -58586,6 +58599,7 @@ patches.suse/bpf-Refactor-and-streamline-bounds-check-into-helper.patch patches.suse/bpf-Move-sanitize_val_alu-out-of-op-switch.patch patches.suse/bpf-Tighten-speculative-pointer-arithmetic-mask.patch + patches.suse/ARM-footbridge-fix-PCI-interrupt-mapping.patch patches.suse/pinctrl-lewisburg-Update-number-of-pins-in-community.patch patches.suse/x86-crash-fix-crash_setup_memmap_entries-out-of-bounds-access.patch patches.suse/locking-qrwlock-Fix-ordering-in-queued_write_lock_sl.patch @@ -58595,6 +58609,10 @@ patches.suse/crypto-qat-Fix-a-double-free-in-adf_create_ring.patch patches.suse/x86-microcode-check-for-offline-cpus-before-requesting-new-microcode.patch patches.suse/genirq-Reduce-irqdebug-cacheline-bouncing.patch + patches.suse/msft-hv-2305-Drivers-hv-vmbus-Use-after-free-in-__vmbus_open.patch + patches.suse/msft-hv-2310-Drivers-hv-vmbus-Initialize-unload_event-statically.patch + patches.suse/msft-hv-2311-Drivers-hv-vmbus-Increase-wait-time-for-VMbus-unload.patch + patches.suse/msft-hv-2312-video-hyperv_fb-Add-ratelimit-on-error-message.patch patches.suse/platform-x86-pmc_atom-Match-all-Beckhoff-Automation-.patch patches.suse/misc-lis3lv02d-Fix-false-positive-WARN-on-various-HP.patch patches.suse/misc-vmw_vmci-explicitly-initialize-vmci_notify_bm_s.patch @@ -58609,6 +58627,8 @@ patches.suse/USB-serial-fix-return-value-for-unsupported-ioctls.patch patches.suse/bus-qcom-Put-child-node-before-return.patch patches.suse/soc-qcom-mdt_loader-Validate-that-p_filesz-p_memsz.patch + patches.suse/btrfs-fix-race-between-transaction-aborts-and-fsyncs.patch + patches.suse/btrfs-fix-race-when-picking-most-recent-mod-log-oper.patch patches.suse/ACPI-CPPC-Replace-cppc_attr-with-kobj_attribute.patch patches.suse/clk-mvebu-armada-37xx-periph-remove-.set_parent-meth.patch patches.suse/clk-mvebu-armada-37xx-periph-Fix-switching-CPU-freq-.patch @@ -58724,6 +58744,7 @@ patches.suse/nfc-pn533-prevent-potential-memory-corruption.patch patches.suse/ibmvnic-Use-skb_frag_address-instead-of-hand-coding-.patch patches.suse/liquidio-Fix-unintented-sign-extension-of-a-left-shi.patch + patches.suse/Bluetooth-verify-AMP-hci_chan-before-amp_destroy.patch patches.suse/cxgb4-Fix-unintentional-sign-extension-issues.patch patches.suse/net-thunderx-Fix-unintentional-sign-extension-issue.patch patches.suse/ibmvnic-clean-up-the-remaining-debugfs-data-structur.patch @@ -58775,7 +58796,9 @@ patches.suse/net-hns3-use-netif_tx_disable-to-stop-the-transmit-q.patch patches.suse/net-hns3-disable-phy-loopback-setting-in-hclge_mac_s.patch patches.suse/ethernet-enic-Fix-a-use-after-free-bug-in-enic_hard_.patch + patches.suse/sctp-delay-auto_asconf-init-until-binding-the-first-.patch patches.suse/bpf-Fix-masking-negation-logic-upon-negative-dst-reg.patch + patches.suse/net-nfc-fix-use-after-free-llcp_sock_bind-connect.patch patches.suse/smc-disallow-TCP_ULP-in-smc_setsockopt.patch patches.suse/mlxsw-spectrum_mr-Update-egress-RIF-list-before-rout.patch patches.suse/i40e-fix-broken-XDP-support.patch @@ -58784,12 +58807,25 @@ patches.suse/i40e-Fix-PHY-type-identifiers-for-2.5G-and-5G-adapte.patch patches.suse/scsi-lpfc-Fix-illegal-memory-access-on-Abort-IOCBs.patch patches.suse/scsi-lpfc-Fix-DMA-virtual-address-ptr-assignment-in-.patch + patches.suse/scsi-lpfc-Fix-bad-memory-access-during-VPD-DUMP-mail.patch patches.suse/scsi-qla2xxx-Prevent-PRLI-in-target-mode.patch patches.suse/powerpc-64s-Fix-crashes-when-toggling-stf-barrier.patch + patches.suse/xhci-Do-not-use-GFP_KERNEL-in-potentially-atomic-con.patch + patches.suse/usb-xhci-Increase-timeout-for-HC-halt.patch + patches.suse/usb-core-hub-fix-race-condition-about-TRSMRCY-of-res.patch + patches.suse/msft-hv-2316-uio_hv_generic-Fix-a-memory-leak-in-error-handling-p.patch + patches.suse/msft-hv-2317-uio_hv_generic-Fix-another-memory-leak-in-error-hand.patch + patches.suse/nvme-fc-clear-q_live-at-beginning-of-association-tea.patch + patches.suse/bpf-Wrap-aux-data-inside-bpf_sanitize_info-container.patch + patches.suse/bpf-Fix-mask-direction-swap-upon-off-reg-sign-change.patch # netdev/net-next patches.suse/ibmvnic-remove-default-label-from-to_string-switch.patch + # jejb/scsi for-next + patches.suse/scsi-ibmvfc-Handle-move-login-failure.patch + patches.suse/scsi-ibmvfc-Avoid-move-login-if-fast-fail-is-enabled.patch + # dhowells/linux-fs keys-uefi patches.suse/0001-KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch patches.suse/0003-efi-Add-an-EFI-signature-blob-parser.patch @@ -58797,6 +58833,23 @@ patches.suse/0005-MODSIGN-Allow-the-db-UEFI-variable-to-be-suppressed.patch patches.suse/0006-modsign-Use-secondary-trust-keyring-for-module-signi.patch + # mkp/scsi queue + patches.suse/scsi-lpfc-Fix-unreleased-RPIs-when-NPIV-ports-are-cr.patch + patches.suse/scsi-lpfc-Fix-non-optimized-ERSP-handling.patch + patches.suse/scsi-lpfc-Fix-Unexpected-timeout-error-in-direct-att.patch + patches.suse/scsi-lpfc-Add-ndlp-kref-accounting-for-resume-RPI-pa.patch + patches.suse/scsi-lpfc-Fix-Node-recovery-when-driver-is-handling-.patch + patches.suse/scsi-lpfc-Fix-node-handling-for-Fabric-Controller-an.patch + patches.suse/scsi-lpfc-Ignore-GID-FT-response-that-may-be-receive.patch + patches.suse/scsi-lpfc-Fix-crash-when-lpfc_sli4_hba_setup-fails-t.patch + patches.suse/scsi-lpfc-Add-a-option-to-enable-interlocked-ABTS-be.patch + patches.suse/scsi-lpfc-Reregister-FPIN-types-if-ELS_RDF-is-receiv.patch + patches.suse/scsi-lpfc-Update-lpfc-version-to-12.8.0.10.patch + patches.suse/scsi-ibmvfc-Reinit-target-retries.patch + + # git://github.com/cminyard/linux-ipmi.git for-next + patches.suse/ipmi-watchdog-Stop-watchdog-timer-when-the-current-a.patch + # out-of-tree patches patches.suse/net-mvpp2-fix-condition-for-setting-up-link-interrup.patch patches.suse/cifs-handle-netapp-error-codes.patch @@ -58825,8 +58878,10 @@ patches.suse/kabi-Fix-nvmet-error-log-definitions.patch patches.suse/kabi-nvme-fix-fast_io_fail_tmo.patch patches.kabi/kABI-powerpc-pseries-Add-shutdown-to-vio_driver-and-.patch - patches.suse/Avoid-potentially-erroneos-RST-drop.patch - patches.suse/Don-t-drop-out-of-segments-RST-if-tcp_be_liberal-is-.patch + patches.suse/proc-Avoid-mixing-integer-types-in-mem_rw.patch + patches.suse/netfilter-conntrack-improve-RST-handling-when-tuple-.patch + patches.suse/netfilter-conntrack-add-new-sysctl-to-disable-RST-ch.patch + patches.kabi/kABI-powerpc-64-add-back-start_tb-and-accum_tb-to-th.patch ######################################################## # end of sorted patches @@ -59213,6 +59268,7 @@ patches.suse/sunrpc-svcauth_gss_register_pseudoflavor-must-reject.patch patches.suse/sunrpc-clean-up-properly-in-gss_mech_unregister.patch patches.suse/NFS-only-invalidate-dentrys-that-are-clearly-invalid.patch + patches.suse/SUNRPC-in-case-of-backlog-hand-free-slots-directly-t.patch ######################################################## # Overlayfs @@ -59326,6 +59382,20 @@ patches.kabi/mwifiex-power_cfg-kabi-workaround.patch patches.kabi/netlink-nla_policy-kabi-workaround.patch + patches.suse/mac80211-assure-all-fragments-are-encrypted.patch + patches.suse/mac80211-prevent-mixed-key-and-fragment-cache-attack.patch + patches.suse/mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch + patches.suse/mac80211-drop-A-MSDUs-on-old-ciphers.patch + patches.suse/mac80211-add-fragment-cache-to-sta_info.patch + patches.suse/mac80211-check-defrag-PN-against-current-frame.patch + patches.suse/mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch + patches.suse/mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch + patches.suse/mac80211-extend-protection-against-mixed-key-and-fra.patch + + patches.suse/ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch + patches.suse/ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch + patches.suse/ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch + ######################################################## # ISDN ######################################################## @@ -59693,6 +59763,8 @@ patches.kabi/powerpc-kABI-add-back-suspend_disable_cpu-in-machdep.patch patches.kabi/struct-usbip_device-kABI-fixup.patch patches.kabi/kabi-preserve-struct-header_ops-after-bsc-1176081-fi.patch + patches.kabi/cfg80211-kabi-workaround.patch + patches.kabi/hci_chan-amp-kABI-workaround.patch ######################################################## # You'd better have a good reason for adding a patch