From: Greg Kroah-Hartman Date: Tue, 16 Jun 2026 03:45:27 +0000 (+0530) Subject: 6.12-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cf05781990fa738864d8e9a99530d9ab73769acb;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch mailbox-fix-null-message-support-in-mbox_send_message.patch mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch rdma-move-dma-block-iterator-logic-into-dedicated-files.patch rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch rdma-umem-fix-kernel-doc-warnings.patch rdma-umem-fix-truncation-for-block-sizes-4g.patch rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch wifi-iwlwifi-fix-22000-series-smem-parsing.patch --- diff --git a/queue-6.12/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch b/queue-6.12/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch new file mode 100644 index 0000000000..3c76433c18 --- /dev/null +++ b/queue-6.12/hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch @@ -0,0 +1,92 @@ +From stable+bounces-263423-greg=kroah.com@vger.kernel.org Mon Jun 15 23:33:08 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 14:01:58 -0400 +Subject: hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf +To: stable@vger.kernel.org +Cc: Anton Leontev , Paolo Abeni , Sasha Levin +Message-ID: <20260615180158.2315829-1-sashal@kernel.org> + +From: Anton Leontev + +[ Upstream commit 004e9ecfe6c5384f9e0b2f6f6389d42ec22789af ] + +netvsc_copy_to_send_buf() copies page buffer entries into the VMBus +send buffer using phys_to_virt() on the entry PFN. Entries for the +RNDIS header and the skb linear data come from kmalloc'd memory and +are always in the kernel direct map, but entries for skb fragments +reference page cache or user pages, which on 32-bit x86 with +CONFIG_HIGHMEM=y can live above the LOWMEM boundary. For such a page +phys_to_virt() returns an address outside the direct map and the +subsequent memcpy() faults on the transmit softirq path, which is +fatal. + +Map the pages with kmap_local_page() instead, handling two properties +of the page buffer entries: + + - pb[i].pfn is a Hyper-V PFN at HV_HYP_PAGE_SIZE (4K) granularity, + not a native PFN. Reconstruct the physical address first and derive + the native page from it, so the mapping stays correct where + PAGE_SIZE > HV_HYP_PAGE_SIZE (e.g. arm64 with 64K pages). + + - Since commit 41a6328b2c55 ("hv_netvsc: Preserve contiguous PFN + grouping in the page buffer array"), an entry describes a full + physically contiguous fragment and pb[i].len can exceed PAGE_SIZE, + while kmap_local_page() maps a single page. Copy page by page, + splitting at native page boundaries. + +The copy path only handles packets smaller than the send section size +(6144 bytes by default); larger packets take the cp_partial path where +only the RNDIS header is copied. So entries here are bounded by the +section size and a copy is split at most once on 4K-page systems. On +!CONFIG_HIGHMEM configs kmap_local_page() folds to page_address() and +no mapping work is added. + +Fixes: c25aaf814a63 ("hyperv: Enable sendbuf mechanism on the send path") +Cc: stable@vger.kernel.org +Signed-off-by: Anton Leontev +Link: https://patch.msgid.link/20260604165938.32033-1-leontyevantony@gmail.com +Signed-off-by: Paolo Abeni +[ adapted `phys_to_page(paddr)` to `pfn_to_page(PHYS_PFN(paddr))` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hyperv/netvsc.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -964,12 +965,22 @@ static void netvsc_copy_to_send_buf(stru + } + + for (i = 0; i < page_count; i++) { +- char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT); +- u32 offset = pb[i].offset; ++ phys_addr_t paddr = (pb[i].pfn << HV_HYP_PAGE_SHIFT) + ++ pb[i].offset; + u32 len = pb[i].len; + +- memcpy(dest, (src + offset), len); +- dest += len; ++ while (len) { ++ struct page *page = pfn_to_page(PHYS_PFN(paddr)); ++ u32 off = offset_in_page(paddr); ++ u32 chunk = min_t(u32, len, PAGE_SIZE - off); ++ char *src = kmap_local_page(page); ++ ++ memcpy(dest, src + off, chunk); ++ kunmap_local(src); ++ dest += chunk; ++ paddr += chunk; ++ len -= chunk; ++ } + } + + if (padding) diff --git a/queue-6.12/mailbox-fix-null-message-support-in-mbox_send_message.patch b/queue-6.12/mailbox-fix-null-message-support-in-mbox_send_message.patch new file mode 100644 index 0000000000..03d219ef69 --- /dev/null +++ b/queue-6.12/mailbox-fix-null-message-support-in-mbox_send_message.patch @@ -0,0 +1,160 @@ +From c58e9456e30c7098cbcd9f04571992be8a2e4e63 Mon Sep 17 00:00:00 2001 +From: Jassi Brar +Date: Fri, 27 Mar 2026 17:00:40 -0500 +Subject: mailbox: Fix NULL message support in mbox_send_message() + +From: Jassi Brar + +commit c58e9456e30c7098cbcd9f04571992be8a2e4e63 upstream. + +The active_req field serves double duty as both the "is a TX in +flight" flag (NULL means idle) and the storage for the in-flight +message pointer. When a client sends NULL via mbox_send_message(), +active_req is set to NULL, which the framework misinterprets as +"no active request". This breaks the TX state machine by: + + - tx_tick() short-circuits on (!mssg), skipping the tx_done + callback and the tx_complete completion + - txdone_hrtimer() skips the channel entirely since active_req + is NULL, so poll-based TX-done detection never fires. + +Fix this by introducing a MBOX_NO_MSG sentinel value that means +"no active request," freeing NULL to be valid message data. The +sentinel is defined in the subsystem-internal mailbox.h so that +controller drivers within drivers/mailbox/ can reference it, but +it is not exposed to clients outside the subsystem. + +Fifteen in-tree callers send NULL (doorbell-style IPCs on Qualcomm, +Tegra, TI, Xilinx, i.MX, SCMI, and PCC platforms). All were +audited for regression: + + - Most already work around the bug via knows_txdone=true with a + manual mbox_client_txdone() call, making the framework's + tracking irrelevant. These are unaffected. + + - Poll-based callers (Xilinx zynqmp/r5) are strictly better off: + the poll timer now correctly detects NULL-active channels + instead of silently skipping them. + + - irq-qcom-mpm.c was a pre-existing bug -- the only Qualcomm + caller that omitted the knows_txdone + mbox_client_txdone() + pattern. Fixed in a companion commit ("irqchip/qcom-mpm: Fix + missing mailbox TX done acknowledgment"). + + - No caller sets both a tx_done callback and sends NULL, nor + combines tx_block=true with NULL sends, so the newly reachable + callback/completion paths are never exercised. + +Also update tegra-hsp's flush callback, which directly inspects +active_req to wait for the channel to drain: the old "!= NULL" +check becomes "!= MBOX_NO_MSG", otherwise flush spins until +timeout since the sentinel is non-NULL. + +The only tradeoff is that 'MBOX_NO_MSG' can not be used as a message +by clients. + +Reported-by: Joonwon Kang +Reviewed-by: Douglas Anderson +Signed-off-by: Jassi Brar +Signed-off-by: Joonwon Kang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mailbox/mailbox.c | 15 ++++++++------- + drivers/mailbox/tegra-hsp.c | 2 +- + include/linux/mailbox_controller.h | 3 +++ + 3 files changed, 12 insertions(+), 8 deletions(-) + +--- a/drivers/mailbox/mailbox.c ++++ b/drivers/mailbox/mailbox.c +@@ -59,7 +59,7 @@ static void msg_submit(struct mbox_chan + + spin_lock_irqsave(&chan->lock, flags); + +- if (!chan->msg_count || chan->active_req) ++ if (!chan->msg_count || chan->active_req != MBOX_NO_MSG) + goto exit; + + count = chan->msg_count; +@@ -97,13 +97,13 @@ static void tx_tick(struct mbox_chan *ch + + spin_lock_irqsave(&chan->lock, flags); + mssg = chan->active_req; +- chan->active_req = NULL; ++ chan->active_req = MBOX_NO_MSG; + spin_unlock_irqrestore(&chan->lock, flags); + + /* Submit next message */ + msg_submit(chan); + +- if (!mssg) ++ if (mssg == MBOX_NO_MSG) + return; + + /* Notify the client */ +@@ -125,7 +125,7 @@ static enum hrtimer_restart txdone_hrtim + for (i = 0; i < mbox->num_chans; i++) { + struct mbox_chan *chan = &mbox->chans[i]; + +- if (chan->active_req && chan->cl) { ++ if (chan->active_req != MBOX_NO_MSG && chan->cl) { + txdone = chan->mbox->ops->last_tx_done(chan); + if (txdone) + tx_tick(chan, 0); +@@ -257,7 +257,7 @@ int mbox_send_message(struct mbox_chan * + { + int t; + +- if (!chan || !chan->cl) ++ if (!chan || !chan->cl || mssg == MBOX_NO_MSG) + return -EINVAL; + + t = add_to_rbuf(chan, mssg); +@@ -331,7 +331,7 @@ static int __mbox_bind_client(struct mbo + spin_lock_irqsave(&chan->lock, flags); + chan->msg_free = 0; + chan->msg_count = 0; +- chan->active_req = NULL; ++ chan->active_req = MBOX_NO_MSG; + chan->cl = cl; + init_completion(&chan->tx_complete); + +@@ -492,7 +492,7 @@ void mbox_free_channel(struct mbox_chan + /* The queued TX requests are simply aborted, no callbacks are made */ + spin_lock_irqsave(&chan->lock, flags); + chan->cl = NULL; +- chan->active_req = NULL; ++ chan->active_req = MBOX_NO_MSG; + if (chan->txdone_method == TXDONE_BY_ACK) + chan->txdone_method = TXDONE_BY_POLL; + +@@ -548,6 +548,7 @@ int mbox_controller_register(struct mbox + + chan->cl = NULL; + chan->mbox = mbox; ++ chan->active_req = MBOX_NO_MSG; + chan->txdone_method = txdone; + spin_lock_init(&chan->lock); + } +--- a/drivers/mailbox/tegra-hsp.c ++++ b/drivers/mailbox/tegra-hsp.c +@@ -497,7 +497,7 @@ static int tegra_hsp_mailbox_flush(struc + mbox_chan_txdone(chan, 0); + + /* Wait until channel is empty */ +- if (chan->active_req != NULL) ++ if (chan->active_req != MBOX_NO_MSG) + continue; + + return 0; +--- a/include/linux/mailbox_controller.h ++++ b/include/linux/mailbox_controller.h +@@ -11,6 +11,9 @@ + + struct mbox_chan; + ++/* Sentinel value distinguishing "no active request" from "NULL message data" */ ++#define MBOX_NO_MSG ((void *)-1) ++ + /** + * struct mbox_chan_ops - methods to control mailbox channels + * @send_data: The API asks the MBOX controller driver, in atomic diff --git a/queue-6.12/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch b/queue-6.12/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch new file mode 100644 index 0000000000..211ec6f6a7 --- /dev/null +++ b/queue-6.12/mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch @@ -0,0 +1,199 @@ +From stable+bounces-263201-greg=kroah.com@vger.kernel.org Mon Jun 15 18:59:29 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 09:28:59 -0400 +Subject: mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison +To: stable@vger.kernel.org +Cc: Wupeng Ma , "Oscar Salvador (SUSE)" , Muchun Song , Kefeng Wang , Miaohe Lin , David Hildenbrand , Liam Howlett , Lorenzo Stoakes , Michal Hocko , Mike Rapoport , Naoya Horiguchi , Suren Baghdasaryan , Vlastimil Babka , Andrew Morton , Sasha Levin +Message-ID: <20260615132859.2064439-1-sashal@kernel.org> + +From: Wupeng Ma + +[ Upstream commit 3c2d42b8ee345b17a4ba56b0f6492d1ff4c1178e ] + +Two concurrent madvise(MADV_HWPOISON) calls on the same hugetlb page can +trigger a recursive spinlock self-deadlock (AA deadlock) on hugetlb_lock +when racing with a concurrent unmap: + + thread#0 thread#1 + -------- -------- + madvise(folio, MADV_HWPOISON) + -> poisons the folio successfully + madvise(folio, MADV_HWPOISON) unmap(folio) + try_memory_failure_hugetlb + get_huge_page_for_hwpoison + spin_lock_irq(&hugetlb_lock) <- held + __get_huge_page_for_hwpoison + hugetlb_update_hwpoison() + -> MF_HUGETLB_FOLIO_PRE_POISONED + goto out: + folio_put() + refcount: 1 -> 0 + free_huge_folio() + spin_lock_irqsave(&hugetlb_lock) + -> AA DEADLOCK! + +The out: path in __get_huge_page_for_hwpoison() calls folio_put() to drop +the GUP reference while the hugetlb_lock is still held by the hugetlb.c +wrapper get_huge_page_for_hwpoison(). If concurrent unmap has released +the page table mapping reference, folio_put() drops the folio refcount to +zero, triggering free_huge_folio() which attempts to re-acquire the +non-recursive hugetlb_lock. + +Fix this by moving hugetlb_lock acquisition from the hugetlb.c wrapper +into get_huge_page_for_hwpoison(). Place spin_unlock_irq() before the +folio_put() at the out: label so the folio is always released outside the +lock. + +[akpm@linux-foundation.org: fix race, rename label per Miaohe] + Link: https://sashiko.dev/#/patchset/20260522010305.4099834-1-mawupeng1@huawei.com + Link: https://lore.kernel.org/f39f405e-4b4b-8f79-70fe-a2b5b62114eb@huawei.com +Link: https://lore.kernel.org/20260522010305.4099834-1-mawupeng1@huawei.com +Fixes: 405ce051236c ("mm/hwpoison: fix race between hugetlb free/demotion and memory_failure_hugetlb()") +Signed-off-by: Wupeng Ma +Acked-by: Oscar Salvador (SUSE) +Acked-by: Muchun Song +Reviewed-by: Kefeng Wang +Acked-by: Miaohe Lin +Cc: David Hildenbrand +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Naoya Horiguchi +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/hugetlb.h | 8 -------- + include/linux/mm.h | 8 -------- + mm/hugetlb.c | 11 ----------- + mm/memory-failure.c | 19 ++++++++++--------- + 4 files changed, 10 insertions(+), 36 deletions(-) + +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -155,8 +155,6 @@ long hugetlb_unreserve_pages(struct inod + long freed); + bool isolate_hugetlb(struct folio *folio, struct list_head *list); + int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison); +-int get_huge_page_for_hwpoison(unsigned long pfn, int flags, +- bool *migratable_cleared); + void folio_putback_active_hugetlb(struct folio *folio); + void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason); + void hugetlb_fix_reserve_counts(struct inode *inode); +@@ -429,12 +427,6 @@ static inline int get_hwpoison_hugetlb_f + { + return 0; + } +- +-static inline int get_huge_page_for_hwpoison(unsigned long pfn, int flags, +- bool *migratable_cleared) +-{ +- return 0; +-} + + static inline void folio_putback_active_hugetlb(struct folio *folio) + { +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -3995,8 +3995,6 @@ extern int soft_offline_page(unsigned lo + */ + extern const struct attribute_group memory_failure_attr_group; + extern void memory_failure_queue(unsigned long pfn, int flags); +-extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags, +- bool *migratable_cleared); + void num_poisoned_pages_inc(unsigned long pfn); + void num_poisoned_pages_sub(unsigned long pfn, long i); + #else +@@ -4004,12 +4002,6 @@ static inline void memory_failure_queue( + { + } + +-static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags, +- bool *migratable_cleared) +-{ +- return 0; +-} +- + static inline void num_poisoned_pages_inc(unsigned long pfn) + { + } +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -7459,17 +7459,6 @@ int get_hwpoison_hugetlb_folio(struct fo + return ret; + } + +-int get_huge_page_for_hwpoison(unsigned long pfn, int flags, +- bool *migratable_cleared) +-{ +- int ret; +- +- spin_lock_irq(&hugetlb_lock); +- ret = __get_huge_page_for_hwpoison(pfn, flags, migratable_cleared); +- spin_unlock_irq(&hugetlb_lock); +- return ret; +-} +- + void folio_putback_active_hugetlb(struct folio *folio) + { + spin_lock_irq(&hugetlb_lock); +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -2020,20 +2020,19 @@ void folio_clear_hugetlb_hwpoison(struct + folio_free_raw_hwp(folio, true); + } + +-/* +- * Called from hugetlb code with hugetlb_lock held. +- */ +-int __get_huge_page_for_hwpoison(unsigned long pfn, int flags, ++static int get_huge_page_for_hwpoison(unsigned long pfn, int flags, + bool *migratable_cleared) + { + struct page *page = pfn_to_page(pfn); +- struct folio *folio = page_folio(page); ++ struct folio *folio; + bool count_increased = false; + int ret, rc; + ++ spin_lock_irq(&hugetlb_lock); ++ folio = page_folio(page); + if (!folio_test_hugetlb(folio)) { + ret = MF_HUGETLB_NON_HUGEPAGE; +- goto out; ++ goto out_unlock; + } else if (flags & MF_COUNT_INCREASED) { + ret = MF_HUGETLB_IN_USED; + count_increased = true; +@@ -2049,13 +2048,13 @@ int __get_huge_page_for_hwpoison(unsigne + } else { + ret = MF_HUGETLB_RETRY; + if (!(flags & MF_NO_RETRY)) +- goto out; ++ goto out_unlock; + } + + rc = hugetlb_update_hwpoison(folio, page); + if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) { + ret = rc; +- goto out; ++ goto out_unlock; + } + + /* +@@ -2067,8 +2066,10 @@ int __get_huge_page_for_hwpoison(unsigne + *migratable_cleared = true; + } + ++ spin_unlock_irq(&hugetlb_lock); + return ret; +-out: ++out_unlock: ++ spin_unlock_irq(&hugetlb_lock); + if (count_increased) + folio_put(folio); + return ret; diff --git a/queue-6.12/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch b/queue-6.12/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch new file mode 100644 index 0000000000..7d6d1a99cb --- /dev/null +++ b/queue-6.12/netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch @@ -0,0 +1,86 @@ +From stable+bounces-263202-greg=kroah.com@vger.kernel.org Mon Jun 15 19:04:59 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 09:34:53 -0400 +Subject: netfilter: nft_fib: fix stale stack leak via the OIFNAME register +To: stable@vger.kernel.org +Cc: Davide Ornaghi , Florian Westphal , Pablo Neira Ayuso , Sasha Levin +Message-ID: <20260615133453.2065964-1-sashal@kernel.org> + +From: Davide Ornaghi + +[ Upstream commit ab185e0c4fb82dfba6fb86f8271e06f931d9c64c ] + +For NFT_FIB_RESULT_OIFNAME the destination register is declared with +len = IFNAMSIZ (four 32-bit registers), but on the lookup-fail, +RTN_LOCAL and oif-mismatch paths nft_fib{4,6}_eval() only writes one +register via "*dest = 0". The remaining three registers are left as +whatever was on the stack in nft_do_chain()'s struct nft_regs, and a +downstream expression that loads the register span can leak that +uninitialised kernel stack to userspace. + +The NFTA_FIB_F_PRESENT existence check has the same shape: it is only +meaningful for NFT_FIB_RESULT_OIF, yet it was accepted for any result type +while the eval stores a single byte via nft_reg_store8(), leaving the rest +of the declared span stale. + +Fix both: + + - replace the bare "*dest = 0" in the eval with nft_fib_store_result(), + which strscpy_pad()s the whole IFNAMSIZ for OIFNAME (and is already + used on the other early-return path), and + + - restrict NFTA_FIB_F_PRESENT to NFT_FIB_RESULT_OIF and declare its + destination as a single u8, so the marked span matches the one byte + the eval writes. + +Fixes: f6d0cbcf09c5 ("netfilter: nf_tables: add fib expression") +Suggested-by: Florian Westphal +Cc: stable@vger.kernel.org +Signed-off-by: Davide Ornaghi +Signed-off-by: Pablo Neira Ayuso +[ kept the tree's older `ip6_route_lookup()`/`rt6_info` IPv6 context and changed only `*dest = 0;` to `nft_fib_store_result(dest, priv, NULL);` ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/netfilter/nft_fib_ipv4.c | 2 +- + net/ipv6/netfilter/nft_fib_ipv6.c | 2 +- + net/netfilter/nft_fib.c | 6 ++++++ + 3 files changed, 8 insertions(+), 2 deletions(-) + +--- a/net/ipv4/netfilter/nft_fib_ipv4.c ++++ b/net/ipv4/netfilter/nft_fib_ipv4.c +@@ -127,7 +127,7 @@ void nft_fib4_eval(const struct nft_expr + fl4.saddr = get_saddr(iph->daddr); + } + +- *dest = 0; ++ nft_fib_store_result(dest, priv, NULL); + + if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE)) + return; +--- a/net/ipv6/netfilter/nft_fib_ipv6.c ++++ b/net/ipv6/netfilter/nft_fib_ipv6.c +@@ -192,7 +192,7 @@ void nft_fib6_eval(const struct nft_expr + + lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph); + +- *dest = 0; ++ nft_fib_store_result(dest, priv, NULL); + rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb, + lookup_flags); + if (rt->dst.error) +--- a/net/netfilter/nft_fib.c ++++ b/net/netfilter/nft_fib.c +@@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *c + return -EINVAL; + } + ++ if (priv->flags & NFTA_FIB_F_PRESENT) { ++ if (priv->result != NFT_FIB_RESULT_OIF) ++ return -EINVAL; ++ len = sizeof(u8); ++ } ++ + err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg, + NULL, NFT_DATA_VALUE, len); + if (err < 0) diff --git a/queue-6.12/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch b/queue-6.12/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch new file mode 100644 index 0000000000..8dc17e7e52 --- /dev/null +++ b/queue-6.12/rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch @@ -0,0 +1,157 @@ +From stable+bounces-263468-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:18 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 17:29:10 -0400 +Subject: RDMA: During rereg_mr ensure that REREG_ACCESS is compatible +To: stable@vger.kernel.org +Cc: Jason Gunthorpe , Philip Tsukerman , Sasha Levin +Message-ID: <20260615212910.2473729-4-sashal@kernel.org> + +From: Jason Gunthorpe + +[ Upstream commit badad6fad60def1b9805559dd81dbab3d97b82aa ] + +If IB_MR_REREG_ACCESS changes from RO to RW then the umem has to be +re-evaluated to ensure it is properly pinned as RW. Since the umem is +hidden inside each driver's mr struct add a ib_umem_check_rereg() function +that each driver has to call before processing IB_MR_REREG_ACCESS. + +mlx4 has to retain its duplicate ib_access_writable check because it +implements IB_MR_REREG_ACCESS | IB_MR_REREG_TRANS by changing both items +in place sequentially while the MR is live, so it will continue to not +support this combination. + +Cc: stable@vger.kernel.org +Fixes: b40656aa7d55 ("RDMA/umem: remove FOLL_FORCE usage") +Link: https://patch.msgid.link/r/0-v1-06fb1a2d6cf5+107-rereg_access_jgg@nvidia.com +Reported-by: Philip Tsukerman +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/umem.c | 16 ++++++++++++++++ + drivers/infiniband/hw/hns/hns_roce_mr.c | 4 ++++ + drivers/infiniband/hw/irdma/verbs.c | 4 ++++ + drivers/infiniband/hw/mlx4/mr.c | 4 ++++ + drivers/infiniband/hw/mlx5/mr.c | 4 ++++ + drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++ + include/rdma/ib_umem.h | 8 ++++++++ + 7 files changed, 45 insertions(+) + +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -326,3 +326,19 @@ int ib_umem_copy_from(void *dst, struct + return 0; + } + EXPORT_SYMBOL(ib_umem_copy_from); ++ ++/* ++ * Called during rereg mr if the driver is able to re-use a umem for ++ * IB_MR_REREG_ACCESS. ++ */ ++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags) ++{ ++ if (!umem) ++ return 0; ++ ++ if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS)) ++ if (ib_access_writable(new_access_flags) && !umem->writable) ++ return -EACCES; ++ return 0; ++} ++EXPORT_SYMBOL(ib_umem_check_rereg); +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -292,6 +292,10 @@ struct ib_mr *hns_roce_rereg_user_mr(str + goto err_out; + } + ++ ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags); ++ if (ret) ++ goto err_out; ++ + mailbox = hns_roce_alloc_cmd_mailbox(hr_dev); + ret = PTR_ERR_OR_ZERO(mailbox); + if (ret) +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3245,6 +3245,10 @@ static struct ib_mr *irdma_rereg_user_mr + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ ret = ib_umem_check_rereg(iwmr->region, flags, new_access); ++ if (ret) ++ return ERR_PTR(ret); ++ + ret = irdma_hwdereg_mr(ib_mr); + if (ret) + return ERR_PTR(ret); +--- a/drivers/infiniband/hw/mlx4/mr.c ++++ b/drivers/infiniband/hw/mlx4/mr.c +@@ -466,6 +466,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(stru + struct mlx4_mpt_entry **pmpt_entry = &mpt_entry; + int err; + ++ err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags); ++ if (err) ++ return ERR_PTR(err); ++ + /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs, + * we assume that the calls can't run concurrently. Otherwise, a + * race exists. +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -1829,6 +1829,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(stru + if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) + return ERR_PTR(-EOPNOTSUPP); + ++ err = ib_umem_check_rereg(mr->umem, flags, new_access_flags); ++ if (err) ++ return ERR_PTR(err); ++ + if (!(flags & IB_MR_REREG_ACCESS)) + new_access_flags = mr->access_flags; + if (!(flags & IB_MR_REREG_PD)) +--- a/drivers/infiniband/sw/rxe/rxe_verbs.c ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c +@@ -1312,6 +1312,7 @@ static struct ib_mr *rxe_rereg_user_mr(s + struct rxe_mr *mr = to_rmr(ibmr); + struct rxe_pd *old_pd = to_rpd(ibmr->pd); + struct rxe_pd *pd = to_rpd(ibpd); ++ int err; + + /* for now only support the two easy cases: + * rereg_pd and rereg_access +@@ -1321,6 +1322,10 @@ static struct ib_mr *rxe_rereg_user_mr(s + return ERR_PTR(-EOPNOTSUPP); + } + ++ err = ib_umem_check_rereg(mr->umem, flags, access); ++ if (err) ++ return ERR_PTR(err); ++ + if (flags & IB_MR_REREG_PD) { + rxe_put(old_pd); + rxe_get(pd); +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -163,6 +163,8 @@ void ib_umem_dmabuf_revoke_lock(struct i + void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); + ++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags); ++ + #else /* CONFIG_INFINIBAND_USER_MEM */ + + #include +@@ -225,5 +227,11 @@ static inline void ib_umem_dmabuf_revoke + static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} + static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} + ++static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags, ++ int new_access_flags) ++{ ++ return -EOPNOTSUPP; ++} ++ + #endif /* CONFIG_INFINIBAND_USER_MEM */ + #endif /* IB_UMEM_H */ diff --git a/queue-6.12/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch b/queue-6.12/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch new file mode 100644 index 0000000000..446ef53fa5 --- /dev/null +++ b/queue-6.12/rdma-move-dma-block-iterator-logic-into-dedicated-files.patch @@ -0,0 +1,509 @@ +From stable+bounces-263483-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:24 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 18:52:14 -0400 +Subject: RDMA: Move DMA block iterator logic into dedicated files +To: stable@vger.kernel.org +Cc: Leon Romanovsky , Sasha Levin +Message-ID: <20260615225215.2520173-2-sashal@kernel.org> + +From: Leon Romanovsky + +[ Upstream commit 6094ea64c69520ed1e770e7c79c43412de202bfa ] + +The DMA iterator logic was mixed into verbs and umem-specific code, +forcing all users to include rdma/ib_umem.h. Move the block iterator +logic into iter.c and rdma/iter.h so that rdma/ib_umem.h and +rdma/ib_verbs.h can be separated in a follow-up patch. + +Link: https://patch.msgid.link/20260213-refactor-umem-v1-1-f3be85847922@nvidia.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/Makefile | 2 + drivers/infiniband/core/iter.c | 43 +++++++++++++ + drivers/infiniband/core/verbs.c | 38 ----------- + drivers/infiniband/hw/bnxt_re/qplib_res.c | 2 + drivers/infiniband/hw/cxgb4/mem.c | 2 + drivers/infiniband/hw/efa/efa_verbs.c | 2 + drivers/infiniband/hw/erdma/erdma_verbs.c | 2 + drivers/infiniband/hw/hns/hns_roce_alloc.c | 2 + drivers/infiniband/hw/irdma/main.h | 2 + drivers/infiniband/hw/mana/mana_ib.h | 2 + drivers/infiniband/hw/mlx4/mr.c | 1 + drivers/infiniband/hw/mlx5/mem.c | 1 + drivers/infiniband/hw/mlx5/umr.c | 1 + drivers/infiniband/hw/mthca/mthca_provider.c | 2 + drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 + drivers/infiniband/hw/qedr/verbs.c | 2 + drivers/infiniband/hw/vmw_pvrdma/pvrdma.h | 2 + include/rdma/ib_umem.h | 32 --------- + include/rdma/ib_verbs.h | 48 -------------- + include/rdma/iter.h | 88 +++++++++++++++++++++++++++ + 20 files changed, 146 insertions(+), 130 deletions(-) + create mode 100644 drivers/infiniband/core/iter.c + create mode 100644 include/rdma/iter.h + +--- a/drivers/infiniband/core/Makefile ++++ b/drivers/infiniband/core/Makefile +@@ -12,7 +12,7 @@ ib_core-y := packer.o ud_header.o verb + roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \ + multicast.o mad.o smi.o agent.o mad_rmpp.o \ + nldev.o restrack.o counters.o ib_core_uverbs.o \ +- trace.o lag.o ++ trace.o lag.o iter.o + + ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o + ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o +--- /dev/null ++++ b/drivers/infiniband/core/iter.c +@@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB ++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */ ++ ++#include ++#include ++ ++void __rdma_block_iter_start(struct ib_block_iter *biter, ++ struct scatterlist *sglist, unsigned int nents, ++ unsigned long pgsz) ++{ ++ memset(biter, 0, sizeof(struct ib_block_iter)); ++ biter->__sg = sglist; ++ biter->__sg_nents = nents; ++ ++ /* Driver provides best block size to use */ ++ biter->__pg_bit = __fls(pgsz); ++} ++EXPORT_SYMBOL(__rdma_block_iter_start); ++ ++bool __rdma_block_iter_next(struct ib_block_iter *biter) ++{ ++ unsigned int block_offset; ++ unsigned int delta; ++ ++ if (!biter->__sg_nents || !biter->__sg) ++ return false; ++ ++ biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; ++ block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); ++ delta = BIT_ULL(biter->__pg_bit) - block_offset; ++ ++ while (biter->__sg_nents && biter->__sg && ++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) { ++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance; ++ biter->__sg_advance = 0; ++ biter->__sg = sg_next(biter->__sg); ++ biter->__sg_nents--; ++ } ++ biter->__sg_advance += delta; ++ ++ return true; ++} ++EXPORT_SYMBOL(__rdma_block_iter_next); +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -3093,44 +3093,6 @@ int rdma_init_netdev(struct ib_device *d + } + EXPORT_SYMBOL(rdma_init_netdev); + +-void __rdma_block_iter_start(struct ib_block_iter *biter, +- struct scatterlist *sglist, unsigned int nents, +- unsigned long pgsz) +-{ +- memset(biter, 0, sizeof(struct ib_block_iter)); +- biter->__sg = sglist; +- biter->__sg_nents = nents; +- +- /* Driver provides best block size to use */ +- biter->__pg_bit = __fls(pgsz); +-} +-EXPORT_SYMBOL(__rdma_block_iter_start); +- +-bool __rdma_block_iter_next(struct ib_block_iter *biter) +-{ +- unsigned int block_offset; +- unsigned int delta; +- +- if (!biter->__sg_nents || !biter->__sg) +- return false; +- +- biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; +- block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); +- delta = BIT_ULL(biter->__pg_bit) - block_offset; +- +- while (biter->__sg_nents && biter->__sg && +- sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) { +- delta -= sg_dma_len(biter->__sg) - biter->__sg_advance; +- biter->__sg_advance = 0; +- biter->__sg = sg_next(biter->__sg); +- biter->__sg_nents--; +- } +- biter->__sg_advance += delta; +- +- return true; +-} +-EXPORT_SYMBOL(__rdma_block_iter_next); +- + /** + * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct + * for the drivers. +--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c +@@ -46,7 +46,7 @@ + #include + #include + #include +-#include ++#include + + #include "roce_hsi.h" + #include "qplib_res.h" +--- a/drivers/infiniband/hw/cxgb4/mem.c ++++ b/drivers/infiniband/hw/cxgb4/mem.c +@@ -32,9 +32,9 @@ + + #include + #include +-#include + #include + #include ++#include + + #include "iw_cxgb4.h" + +--- a/drivers/infiniband/hw/efa/efa_verbs.c ++++ b/drivers/infiniband/hw/efa/efa_verbs.c +@@ -9,9 +9,9 @@ + #include + + #include +-#include + #include + #include ++#include + #include + #define UVERBS_MODULE_NAME efa_ib + #include +--- a/drivers/infiniband/hw/erdma/erdma_verbs.c ++++ b/drivers/infiniband/hw/erdma/erdma_verbs.c +@@ -12,7 +12,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include "erdma.h" +--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c ++++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c +@@ -32,7 +32,7 @@ + */ + + #include +-#include ++#include + #include "hns_roce_device.h" + + void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf) +--- a/drivers/infiniband/hw/irdma/main.h ++++ b/drivers/infiniband/hw/irdma/main.h +@@ -37,8 +37,8 @@ + #include + #include + #include +-#include + #include ++#include + #include + #include "osdep.h" + #include "defs.h" +--- a/drivers/infiniband/hw/mana/mana_ib.h ++++ b/drivers/infiniband/hw/mana/mana_ib.h +@@ -8,7 +8,7 @@ + + #include + #include +-#include ++#include + #include + #include + +--- a/drivers/infiniband/hw/mlx4/mr.c ++++ b/drivers/infiniband/hw/mlx4/mr.c +@@ -33,6 +33,7 @@ + + #include + #include ++#include + + #include "mlx4_ib.h" + +--- a/drivers/infiniband/hw/mlx5/mem.c ++++ b/drivers/infiniband/hw/mlx5/mem.c +@@ -31,6 +31,7 @@ + */ + + #include ++#include + #include "mlx5_ib.h" + + /* +--- a/drivers/infiniband/hw/mlx5/umr.c ++++ b/drivers/infiniband/hw/mlx5/umr.c +@@ -2,6 +2,7 @@ + /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */ + + #include ++#include + #include "mlx5_ib.h" + #include "umr.h" + #include "wr.h" +--- a/drivers/infiniband/hw/mthca/mthca_provider.c ++++ b/drivers/infiniband/hw/mthca/mthca_provider.c +@@ -35,8 +35,8 @@ + */ + + #include +-#include + #include ++#include + #include + + #include +--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c ++++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +@@ -45,9 +45,9 @@ + #include + #include + #include +-#include + #include + #include ++#include + #include + + #include "ocrdma.h" +--- a/drivers/infiniband/hw/qedr/verbs.c ++++ b/drivers/infiniband/hw/qedr/verbs.c +@@ -39,9 +39,9 @@ + #include + #include + #include +-#include + #include + #include ++#include + #include + + #include +--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h ++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h +@@ -53,8 +53,8 @@ + #include + #include + #include +-#include + #include ++#include + #include + + #include "pvrdma_ring.h" +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -71,38 +71,6 @@ static inline size_t ib_umem_num_pages(s + { + return ib_umem_num_dma_blocks(umem, PAGE_SIZE); + } +- +-static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter, +- struct ib_umem *umem, +- unsigned long pgsz) +-{ +- __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl, +- umem->sgt_append.sgt.nents, pgsz); +- biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1); +- biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz); +-} +- +-static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter) +-{ +- return __rdma_block_iter_next(biter) && biter->__sg_numblocks--; +-} +- +-/** +- * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem +- * @umem: umem to iterate over +- * @biter: block iterator variable +- * @pgsz: Page size to split the list into +- * +- * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The +- * returned DMA blocks will be aligned to pgsz and span the range: +- * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz) +- * +- * Performs exactly ib_umem_num_dma_blocks() iterations. +- */ +-#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \ +- for (__rdma_umem_block_iter_start(biter, umem, pgsz); \ +- __rdma_umem_block_iter_next(biter);) +- + #ifdef CONFIG_INFINIBAND_USER_MEM + + struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr, +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -2849,22 +2849,6 @@ struct ib_client { + u8 no_kverbs_req:1; + }; + +-/* +- * IB block DMA iterator +- * +- * Iterates the DMA-mapped SGL in contiguous memory blocks aligned +- * to a HW supported page size. +- */ +-struct ib_block_iter { +- /* internal states */ +- struct scatterlist *__sg; /* sg holding the current aligned block */ +- dma_addr_t __dma_addr; /* unaligned DMA address of this block */ +- size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */ +- unsigned int __sg_nents; /* number of SG entries */ +- unsigned int __sg_advance; /* number of bytes to advance in sg in next step */ +- unsigned int __pg_bit; /* alignment of current block */ +-}; +- + struct ib_device *_ib_alloc_device(size_t size); + #define ib_alloc_device(drv_struct, member) \ + container_of(_ib_alloc_device(sizeof(struct drv_struct) + \ +@@ -2886,38 +2870,6 @@ void ib_unregister_device_queued(struct + int ib_register_client (struct ib_client *client); + void ib_unregister_client(struct ib_client *client); + +-void __rdma_block_iter_start(struct ib_block_iter *biter, +- struct scatterlist *sglist, +- unsigned int nents, +- unsigned long pgsz); +-bool __rdma_block_iter_next(struct ib_block_iter *biter); +- +-/** +- * rdma_block_iter_dma_address - get the aligned dma address of the current +- * block held by the block iterator. +- * @biter: block iterator holding the memory block +- */ +-static inline dma_addr_t +-rdma_block_iter_dma_address(struct ib_block_iter *biter) +-{ +- return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1); +-} +- +-/** +- * rdma_for_each_block - iterate over contiguous memory blocks of the sg list +- * @sglist: sglist to iterate over +- * @biter: block iterator holding the memory block +- * @nents: maximum number of sg entries to iterate over +- * @pgsz: best HW supported page size to use +- * +- * Callers may use rdma_block_iter_dma_address() to get each +- * blocks aligned DMA address. +- */ +-#define rdma_for_each_block(sglist, biter, nents, pgsz) \ +- for (__rdma_block_iter_start(biter, sglist, nents, \ +- pgsz); \ +- __rdma_block_iter_next(biter);) +- + /** + * ib_get_client_data - Get IB client context + * @device:Device to get context for +--- /dev/null ++++ b/include/rdma/iter.h +@@ -0,0 +1,88 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ ++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */ ++ ++#ifndef _RDMA_ITER_H_ ++#define _RDMA_ITER_H_ ++ ++#include ++#include ++ ++/** ++ * IB block DMA iterator ++ * ++ * Iterates the DMA-mapped SGL in contiguous memory blocks aligned ++ * to a HW supported page size. ++ */ ++struct ib_block_iter { ++ /* internal states */ ++ struct scatterlist *__sg; /* sg holding the current aligned block */ ++ dma_addr_t __dma_addr; /* unaligned DMA address of this block */ ++ size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */ ++ unsigned int __sg_nents; /* number of SG entries */ ++ unsigned int __sg_advance; /* number of bytes to advance in sg in next step */ ++ unsigned int __pg_bit; /* alignment of current block */ ++}; ++ ++void __rdma_block_iter_start(struct ib_block_iter *biter, ++ struct scatterlist *sglist, ++ unsigned int nents, ++ unsigned long pgsz); ++bool __rdma_block_iter_next(struct ib_block_iter *biter); ++ ++/** ++ * rdma_block_iter_dma_address - get the aligned dma address of the current ++ * block held by the block iterator. ++ * @biter: block iterator holding the memory block ++ */ ++static inline dma_addr_t ++rdma_block_iter_dma_address(struct ib_block_iter *biter) ++{ ++ return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1); ++} ++ ++/** ++ * rdma_for_each_block - iterate over contiguous memory blocks of the sg list ++ * @sglist: sglist to iterate over ++ * @biter: block iterator holding the memory block ++ * @nents: maximum number of sg entries to iterate over ++ * @pgsz: best HW supported page size to use ++ * ++ * Callers may use rdma_block_iter_dma_address() to get each ++ * blocks aligned DMA address. ++ */ ++#define rdma_for_each_block(sglist, biter, nents, pgsz) \ ++ for (__rdma_block_iter_start(biter, sglist, nents, \ ++ pgsz); \ ++ __rdma_block_iter_next(biter);) ++ ++static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter, ++ struct ib_umem *umem, ++ unsigned long pgsz) ++{ ++ __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl, ++ umem->sgt_append.sgt.nents, pgsz); ++ biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1); ++ biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz); ++} ++ ++static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter) ++{ ++ return __rdma_block_iter_next(biter) && biter->__sg_numblocks--; ++} ++ ++/** ++ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem ++ * @umem: umem to iterate over ++ * @pgsz: Page size to split the list into ++ * ++ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The ++ * returned DMA blocks will be aligned to pgsz and span the range: ++ * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz) ++ * ++ * Performs exactly ib_umem_num_dma_blocks() iterations. ++ */ ++#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \ ++ for (__rdma_umem_block_iter_start(biter, umem, pgsz); \ ++ __rdma_umem_block_iter_next(biter);) ++ ++#endif /* _RDMA_ITER_H_ */ diff --git a/queue-6.12/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch b/queue-6.12/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch new file mode 100644 index 0000000000..d02cb8e0db --- /dev/null +++ b/queue-6.12/rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch @@ -0,0 +1,74 @@ +From stable+bounces-263467-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:18 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 17:29:09 -0400 +Subject: RDMA/umem: Add helpers for umem dmabuf revoke lock +To: stable@vger.kernel.org +Cc: Jacob Moroni , Leon Romanovsky , Sasha Levin +Message-ID: <20260615212910.2473729-3-sashal@kernel.org> + +From: Jacob Moroni + +[ Upstream commit 3a0b171302eea1732a168e26db3b8461f51cc1f9 ] + +Added helpers to acquire and release the umem dmabuf revoke +lock. The intent is to avoid the need for drivers to peek +into the ib_umem_dmabuf internals to get the dma_resv_lock +and bring us one step closer to abstracting ib_umem_dmabuf +away from drivers in general. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-5-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/umem_dmabuf.c | 16 ++++++++++++++++ + include/rdma/ib_umem.h | 4 ++++ + 2 files changed, 20 insertions(+) + +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -276,6 +276,22 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_ge + } + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned); + ++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf) ++{ ++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; ++ ++ dma_resv_lock(dmabuf->resv, NULL); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_lock); ++ ++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) ++{ ++ struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; ++ ++ dma_resv_unlock(dmabuf->resv); ++} ++EXPORT_SYMBOL(ib_umem_dmabuf_revoke_unlock); ++ + void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) + { + struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -159,6 +159,8 @@ ib_umem_dmabuf_get_pinned_with_dma_devic + int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf); ++void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf); ++void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf); + void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf); + + #else /* CONFIG_INFINIBAND_USER_MEM */ +@@ -219,6 +221,8 @@ static inline int ib_umem_dmabuf_map_pag + } + static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { } + static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { } ++static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf) {} ++static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {} + static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {} + + #endif /* CONFIG_INFINIBAND_USER_MEM */ diff --git a/queue-6.12/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch b/queue-6.12/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch new file mode 100644 index 0000000000..47923ddcd4 --- /dev/null +++ b/queue-6.12/rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch @@ -0,0 +1,90 @@ +From stable+bounces-263465-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:40 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 17:29:07 -0400 +Subject: RDMA/umem: Add ib_umem_dmabuf_get_pinned_and_lock helper +To: stable@vger.kernel.org +Cc: Jacob Moroni , Leon Romanovsky , Sasha Levin +Message-ID: <20260615212910.2473729-1-sashal@kernel.org> + +From: Jacob Moroni + +[ Upstream commit 553dfa8cbd0c6d36adae042d9738ddf8f8765ac7 ] + +Move the inner logic of ib_umem_dmabuf_get_pinned_with_dma_device() +to a new static function that returns with the lock held upon success. + +The intent is to allow reuse for the future get_pinned_revocable_and_lock +function. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-2-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/umem_dmabuf.c | 35 +++++++++++++++++++++++++--------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -198,18 +198,19 @@ static struct dma_buf_attach_ops ib_umem + .move_notify = ib_umem_dmabuf_unsupported_move_notify, + }; + +-struct ib_umem_dmabuf * +-ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, +- struct device *dma_device, +- unsigned long offset, size_t size, +- int fd, int access) ++static struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, ++ size_t size, int fd, int access, ++ const struct dma_buf_attach_ops *ops) + { + struct ib_umem_dmabuf *umem_dmabuf; + int err; + +- umem_dmabuf = ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset, +- size, fd, access, +- &ib_umem_dmabuf_attach_pinned_ops); ++ umem_dmabuf = ++ ib_umem_dmabuf_get_with_dma_device(device, dma_device, offset, ++ size, fd, access, ops); + if (IS_ERR(umem_dmabuf)) + return umem_dmabuf; + +@@ -222,7 +223,6 @@ ib_umem_dmabuf_get_pinned_with_dma_devic + err = ib_umem_dmabuf_map_pages(umem_dmabuf); + if (err) + goto err_release; +- dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); + + return umem_dmabuf; + +@@ -231,6 +231,23 @@ err_release: + ib_umem_release(&umem_dmabuf->umem); + return ERR_PTR(err); + } ++ ++struct ib_umem_dmabuf * ++ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device, ++ struct device *dma_device, ++ unsigned long offset, size_t size, ++ int fd, int access) ++{ ++ struct ib_umem_dmabuf *umem_dmabuf = ++ ib_umem_dmabuf_get_pinned_and_lock(device, dma_device, offset, ++ size, fd, access, ++ &ib_umem_dmabuf_attach_pinned_ops); ++ if (IS_ERR(umem_dmabuf)) ++ return umem_dmabuf; ++ ++ dma_resv_unlock(umem_dmabuf->attach->dmabuf->resv); ++ return umem_dmabuf; ++} + EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device); + + struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device, diff --git a/queue-6.12/rdma-umem-fix-kernel-doc-warnings.patch b/queue-6.12/rdma-umem-fix-kernel-doc-warnings.patch new file mode 100644 index 0000000000..f88b98e059 --- /dev/null +++ b/queue-6.12/rdma-umem-fix-kernel-doc-warnings.patch @@ -0,0 +1,60 @@ +From stable+bounces-263481-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:17 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 18:52:13 -0400 +Subject: RDMA/umem: fix kernel-doc warnings +To: stable@vger.kernel.org +Cc: Randy Dunlap , Leon Romanovsky , Sasha Levin +Message-ID: <20260615225215.2520173-1-sashal@kernel.org> + +From: Randy Dunlap + +[ Upstream commit ff46d1392750444fab5ae5a0194764ffdc4ac0d2 ] + +Add or correct kernel-doc comments to eliminate warnings: + +Warning: include/rdma/ib_umem.h:104 function parameter 'biter' not + described in 'rdma_umem_for_each_dma_block' +Warning: include/rdma/ib_umem.h:140 function parameter 'pgsz_bitmap' not + described in 'ib_umem_find_best_pgoff' +Warning: include/rdma/ib_umem.h:141 No description found for return + value of 'ib_umem_find_best_pgoff' + +Signed-off-by: Randy Dunlap +Link: https://patch.msgid.link/20260224003120.3173892-1-rdunlap@infradead.org +Signed-off-by: Leon Romanovsky +Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/rdma/ib_umem.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/rdma/ib_umem.h ++++ b/include/rdma/ib_umem.h +@@ -90,6 +90,7 @@ static inline bool __rdma_umem_block_ite + /** + * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem + * @umem: umem to iterate over ++ * @biter: block iterator variable + * @pgsz: Page size to split the list into + * + * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The +@@ -117,7 +118,7 @@ unsigned long ib_umem_find_best_pgsz(str + * ib_umem_find_best_pgoff - Find best HW page size + * + * @umem: umem struct +- * @pgsz_bitmap bitmap of HW supported page sizes ++ * @pgsz_bitmap: bitmap of HW supported page sizes + * @pgoff_bitmask: Mask of bits that can be represented with an offset + * + * This is very similar to ib_umem_find_best_pgsz() except instead of accepting +@@ -130,6 +131,9 @@ unsigned long ib_umem_find_best_pgsz(str + * + * If the pgoff_bitmask requires either alignment in the low bit or an + * unavailable page size for the high bits, this function returns 0. ++ * ++ * Returns: best HW page size for the parameters or 0 if none available ++ * for the given parameters. + */ + static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem, + unsigned long pgsz_bitmap, diff --git a/queue-6.12/rdma-umem-fix-truncation-for-block-sizes-4g.patch b/queue-6.12/rdma-umem-fix-truncation-for-block-sizes-4g.patch new file mode 100644 index 0000000000..927dface89 --- /dev/null +++ b/queue-6.12/rdma-umem-fix-truncation-for-block-sizes-4g.patch @@ -0,0 +1,44 @@ +From stable+bounces-263482-greg=kroah.com@vger.kernel.org Tue Jun 16 04:22:23 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 18:52:15 -0400 +Subject: RDMA/umem: Fix truncation for block sizes >= 4G +To: stable@vger.kernel.org +Cc: Jason Gunthorpe , Sasha Levin +Message-ID: <20260615225215.2520173-3-sashal@kernel.org> + +From: Jason Gunthorpe + +[ Upstream commit 15fe76e23615f502d051ef0768f86babaf08746c ] + +When the iommu is used the linearization of the mapping can give a single +block that is very large split across multiple SG entries. + +When __rdma_block_iter_next() reassembles the split SG entries it is +overflowing the 32 bit stack values and computed the wrong DMA addresses +for blocks after the truncation. + +Use the right types to hold DMA addresses. + +Link: https://patch.msgid.link/r/1-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com +Cc: stable@vger.kernel.org +Fixes: a808273a495c ("RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks") +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/iter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/infiniband/core/iter.c ++++ b/drivers/infiniband/core/iter.c +@@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start); + + bool __rdma_block_iter_next(struct ib_block_iter *biter) + { +- unsigned int block_offset; +- unsigned int delta; ++ dma_addr_t block_offset; ++ dma_addr_t delta; + + if (!biter->__sg_nents || !biter->__sg) + return false; diff --git a/queue-6.12/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch b/queue-6.12/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch new file mode 100644 index 0000000000..c2e67abcb5 --- /dev/null +++ b/queue-6.12/rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch @@ -0,0 +1,68 @@ +From stable+bounces-263466-greg=kroah.com@vger.kernel.org Tue Jun 16 02:59:43 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 17:29:08 -0400 +Subject: RDMA/umem: Move umem dmabuf revoke logic into helper function +To: stable@vger.kernel.org +Cc: Jacob Moroni , Leon Romanovsky , Sasha Levin +Message-ID: <20260615212910.2473729-2-sashal@kernel.org> + +From: Jacob Moroni + +[ Upstream commit 797291a66ce346c96114b72222fc290d402da005 ] + +This same logic will eventually be reused from within the +invalidate_mappings callback which already has the dma_resv_lock +held, so break it out into a separate function so it can be reused. + +Signed-off-by: Jacob Moroni +Link: https://patch.msgid.link/20260305170826.3803155-3-jmoroni@google.com +Signed-off-by: Leon Romanovsky +Stable-dep-of: badad6fad60d ("RDMA: During rereg_mr ensure that REREG_ACCESS is compatible") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/umem_dmabuf.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +--- a/drivers/infiniband/core/umem_dmabuf.c ++++ b/drivers/infiniband/core/umem_dmabuf.c +@@ -198,6 +198,22 @@ static struct dma_buf_attach_ops ib_umem + .move_notify = ib_umem_dmabuf_unsupported_move_notify, + }; + ++static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach) ++{ ++ struct ib_umem_dmabuf *umem_dmabuf = attach->importer_priv; ++ ++ dma_resv_assert_held(attach->dmabuf->resv); ++ ++ if (umem_dmabuf->revoked) ++ return; ++ ib_umem_dmabuf_unmap_pages(umem_dmabuf); ++ if (umem_dmabuf->pinned) { ++ dma_buf_unpin(umem_dmabuf->attach); ++ umem_dmabuf->pinned = 0; ++ } ++ umem_dmabuf->revoked = 1; ++} ++ + static struct ib_umem_dmabuf * + ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device, + struct device *dma_device, +@@ -265,15 +281,7 @@ void ib_umem_dmabuf_revoke(struct ib_ume + struct dma_buf *dmabuf = umem_dmabuf->attach->dmabuf; + + dma_resv_lock(dmabuf->resv, NULL); +- if (umem_dmabuf->revoked) +- goto end; +- ib_umem_dmabuf_unmap_pages(umem_dmabuf); +- if (umem_dmabuf->pinned) { +- dma_buf_unpin(umem_dmabuf->attach); +- umem_dmabuf->pinned = 0; +- } +- umem_dmabuf->revoked = 1; +-end: ++ ib_umem_dmabuf_revoke_locked(umem_dmabuf->attach); + dma_resv_unlock(dmabuf->resv); + } + EXPORT_SYMBOL(ib_umem_dmabuf_revoke); diff --git a/queue-6.12/sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch b/queue-6.12/sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch new file mode 100644 index 0000000000..754a6ed6f5 --- /dev/null +++ b/queue-6.12/sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch @@ -0,0 +1,74 @@ +From stable+bounces-263417-greg=kroah.com@vger.kernel.org Mon Jun 15 23:07:37 2026 +From: Sasha Levin +Date: Mon, 15 Jun 2026 13:37:30 -0400 +Subject: sched_ext: Don't warn on NULL cgrp_moving_from in scx_cgroup_move_task() +To: stable@vger.kernel.org +Cc: Tejun Heo , Matt Fleming , Andrea Righi , Sasha Levin +Message-ID: <20260615173730.2303601-1-sashal@kernel.org> + +From: Tejun Heo + +[ Upstream commit 02e545c4297a26dbbc41df81b831e7f605bcd306 ] + +A WARN fires when systemd's user manager writes "+cpu +memory +pids" to +its own subtree_control while a sched_ext scheduler is loaded: + + WARNING: at kernel/sched/ext.c:3227 scx_cgroup_move_task+0xa8/0xb0 + scx_cgroup_move_task+0xa8/0xb0 + sched_move_task+0x134/0x290 + cpu_cgroup_attach+0x39/0x70 + cgroup_migrate_execute+0x37d/0x450 + cgroup_update_dfl_csses+0x1e3/0x270 + cgroup_subtree_control_write+0x3e7/0x440 + +scx_cgroup_can_attach() arms cgrp_moving_from only when a task's cpu +cgroup changes. It can still be NULL when scx_cgroup_move_task() runs, +through this sequence: + + Step Result + --------------------------------- ---------------------------------- + 1. cpu enabled on cgroup G cpu css = A + 2. cpu toggled off then on for G A killed, B created (same cgroup) + 3. an exiting task keeps A alive migration skips it, A now stale + 4. +memory migrates G stale A vs current B pulls cpu in + 5. cpu attach runs for all tasks hits a live, cpu-unchanged task + 6. scx_cgroup_move_task() on it cgrp_moving_from NULL -> WARN + +The mismatch is that scx_cgroup_can_attach() keys on cgroup identity +while migration drives the move on css identity, so a NULL cgrp_moving_from +here is a legitimate css-only migration, not a missing prep. + +The call is already gated on cgrp_moving_from, so just drop the warning. +ops.cgroup_prep_move() and ops.cgroup_move() stay paired. + +Fixes: 819513666966 ("sched_ext: Add cgroup support") +Cc: stable@vger.kernel.org # v6.12+ +Reported-by: Matt Fleming +Closes: https://lore.kernel.org/all/20260601124156.2205704-1-mfleming@cloudflare.com/ +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/ext.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/kernel/sched/ext.c ++++ b/kernel/sched/ext.c +@@ -4069,10 +4069,13 @@ void scx_cgroup_move_task(struct task_st + return; + + /* +- * @p must have ops.cgroup_prep_move() called on it and thus +- * cgrp_moving_from set. ++ * scx_cgroup_can_attach() sets cgrp_moving_from only when the task's ++ * cgroup changes. Migration keys off css rather than cgroup identity, ++ * so it can hand an unchanged-cgroup task here with cgrp_moving_from ++ * NULL. Nothing to report to the BPF scheduler then, so skip it and ++ * keep prep_move and move paired. + */ +- if (SCX_HAS_OP(cgroup_move) && !WARN_ON_ONCE(!p->scx.cgrp_moving_from)) ++ if (SCX_HAS_OP(cgroup_move) && p->scx.cgrp_moving_from) + SCX_CALL_OP_TASK(SCX_KF_UNLOCKED, cgroup_move, p, + p->scx.cgrp_moving_from, tg_cgrp(task_group(p))); + p->scx.cgrp_moving_from = NULL; diff --git a/queue-6.12/series b/queue-6.12/series index 99a4987133..f9caf864dc 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -228,5 +228,18 @@ drm-amd-display-fix-null-deref-and-buffer-over-read-in-sdp-debugfs.patch drm-amd-display-use-krealloc_array-in-dal_vector_reserve.patch fs-fcntl-fix-softirq-unsafe-lock-order-in-fasync-signaling.patch driver-core-reject-devices-with-unregistered-buses.patch +mailbox-fix-null-message-support-in-mbox_send_message.patch +wifi-iwlwifi-fix-22000-series-smem-parsing.patch +hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch +sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx_cgroup_move_task.patch +netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch +mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch +rdma-umem-add-ib_umem_dmabuf_get_pinned_and_lock-helper.patch +rdma-umem-move-umem-dmabuf-revoke-logic-into-helper-function.patch +rdma-umem-add-helpers-for-umem-dmabuf-revoke-lock.patch +rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch +rdma-umem-fix-kernel-doc-warnings.patch +rdma-move-dma-block-iterator-logic-into-dedicated-files.patch +rdma-umem-fix-truncation-for-block-sizes-4g.patch mm-hugetlb-avoid-false-positive-lockdep-assertion.patch sched_ext-don-t-warn-on-null-cgrp_moving_from-in-scx.patch diff --git a/queue-6.12/wifi-iwlwifi-fix-22000-series-smem-parsing.patch b/queue-6.12/wifi-iwlwifi-fix-22000-series-smem-parsing.patch new file mode 100644 index 0000000000..af90363407 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-fix-22000-series-smem-parsing.patch @@ -0,0 +1,54 @@ +From 58192b9ce09b0f0f86e2036683bd542130b91a98 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Mon, 10 Nov 2025 15:02:19 +0200 +Subject: wifi: iwlwifi: fix 22000 series SMEM parsing + +From: Johannes Berg + +commit 58192b9ce09b0f0f86e2036683bd542130b91a98 upstream. + +If the firmware were to report three LMACs (which doesn't +exist in hardware) then using "fwrt->smem_cfg.lmac[2]" is +an overrun of the array. Reject such and use IWL_FW_CHECK +instead of WARN_ON in this function. + +Signed-off-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110150012.16e8c2d70c26.Iadfcc1aedf43c5175b3f0757bea5aa232454f1ac@changeid +Signed-off-by: Nazar Kalashnikov +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intel/iwlwifi/fw/smem.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c +@@ -6,6 +6,7 @@ + */ + #include "iwl-drv.h" + #include "runtime.h" ++#include "dbg.h" + #include "fw/api/commands.h" + + static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt, +@@ -17,7 +18,9 @@ static void iwl_parse_shared_mem_22000(s + u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP, + SHARED_MEM_CFG_CMD, 0); + +- if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem))) ++ /* Note: notification has 3 entries, but we only expect 2 */ ++ if (IWL_FW_CHECK(fwrt, lmac_num > ARRAY_SIZE(fwrt->smem_cfg.lmac), ++ "FW advertises %d LMACs\n", lmac_num)) + return; + + fwrt->smem_cfg.num_lmacs = lmac_num; +@@ -26,7 +29,8 @@ static void iwl_parse_shared_mem_22000(s + fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size); + + if (api_ver >= 4 && +- !WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) { ++ !IWL_FW_CHECK(fwrt, iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg), ++ "bad shared mem notification size\n")) { + fwrt->smem_cfg.rxfifo2_control_size = + le32_to_cpu(mem_cfg->rxfifo2_control_size); + }