From: Greg Kroah-Hartman Date: Thu, 16 Jul 2026 11:45:21 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=47f7096bddc3e812479c78164741fd946974f7ef;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: audit-fix-removal-of-dangling-executable-rules.patch dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch iommu-vt-d-avoid-warning-in-sva-unbind-path.patch iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch iommufd-set-veventq_depth-upper-bound.patch iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch landlock-set-audit_net.sk-for-socket-access-checks.patch loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch selftests-landlock-filter-dealloc-records-in-audit_count_records.patch udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch --- diff --git a/queue-6.18/audit-fix-removal-of-dangling-executable-rules.patch b/queue-6.18/audit-fix-removal-of-dangling-executable-rules.patch new file mode 100644 index 0000000000..51943e5a53 --- /dev/null +++ b/queue-6.18/audit-fix-removal-of-dangling-executable-rules.patch @@ -0,0 +1,61 @@ +From 888a0396e154524f4027f27da84bdbec9eb68916 Mon Sep 17 00:00:00 2001 +From: Ricardo Robaina +Date: Wed, 13 May 2026 18:47:59 -0300 +Subject: audit: fix removal of dangling executable rules + +From: Ricardo Robaina + +commit 888a0396e154524f4027f27da84bdbec9eb68916 upstream. + +When an audited executable is deleted from the disk, its dentry +becomes negative. Any later attempt to delete the associated audit +rule will lead to audit_alloc_mark() encountering this negative +dentry and immediately aborting, returning -ENOENT. + +This early abort prevents the subsystem from allocating the temporary +fsnotify mark needed to construct the search key, meaning the kernel +cannot find the existing rule in its own lists to delete it. This +leaves a dangling rule in memory, resulting in the following error +while attempting to delete the rule: + + # ./audit-dupe-exe-deadlock.sh + No rules + Error deleting rule (No such file or directory) + There was an error while processing parameters + + # auditctl -l + -a always,exit -S all -F exe=/tmp/file -F path=/tmp/file -F key=dr + + # auditctl -D + Error deleting rule (No such file or directory) + There was an error while processing parameters + +This patch fixes this issue by removing the d_really_is_negative() +check. By doing so, a dummy mark can be successfully generated for +the deleted path, which allows the audit subsystem to properly match +and flush the dangling rule. + +Cc: stable@kernel.org +Fixes: 76a53de6f7ff ("VFS/audit: introduce kern_path_parent() for audit") +Acked-by: Waiman Long +Acked-by: Richard Guy Briggs +Signed-off-by: Ricardo Robaina +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + kernel/audit_fsnotify.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/kernel/audit_fsnotify.c ++++ b/kernel/audit_fsnotify.c +@@ -84,10 +84,6 @@ struct audit_fsnotify_mark *audit_alloc_ + dentry = kern_path_parent(pathname, &path); + if (IS_ERR(dentry)) + return ERR_CAST(dentry); /* returning an error */ +- if (d_really_is_negative(dentry)) { +- audit_mark = ERR_PTR(-ENOENT); +- goto out; +- } + + audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL); + if (unlikely(!audit_mark)) { diff --git a/queue-6.18/dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch b/queue-6.18/dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch new file mode 100644 index 0000000000..6df4c9bca0 --- /dev/null +++ b/queue-6.18/dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch @@ -0,0 +1,81 @@ +From 504e2b4ab97a51d56d966cd36d0997ad30b65b2d Mon Sep 17 00:00:00 2001 +From: Mikhail Gavrilov +Date: Tue, 31 Mar 2026 11:16:57 +0500 +Subject: dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning + +From: Mikhail Gavrilov + +commit 504e2b4ab97a51d56d966cd36d0997ad30b65b2d upstream. + +When CONFIG_DMA_API_DEBUG_SG is enabled, importing a udmabuf into a DRM +driver (e.g. amdgpu for video playback in GNOME Videos / Showtime) +triggers a spurious warning: + + DMA-API: amdgpu 0000:03:00.0: cacheline tracking EEXIST, \ + overlapping mappings aren't supported + WARNING: kernel/dma/debug.c:619 at add_dma_entry+0x473/0x5f0 + +The call chain is: + + amdgpu_cs_ioctl + -> amdgpu_ttm_backend_bind + -> dma_buf_map_attachment + -> [udmabuf] map_udmabuf -> get_sg_table + -> dma_map_sgtable(dev, sg, direction, 0) // attrs=0 + -> debug_dma_map_sg -> add_dma_entry -> EEXIST + +This happens because udmabuf builds a per-page scatter-gather list via +sg_set_folio(). When begin_cpu_udmabuf() has already created an sg +table mapped for the misc device, and an importer such as amdgpu maps +the same pages for its own device via map_udmabuf(), the DMA debug +infrastructure sees two active mappings whose physical addresses share +cacheline boundaries and warns about the overlap. + +The DMA_ATTR_SKIP_CPU_SYNC flag suppresses this check in +add_dma_entry() because it signals that no CPU cache maintenance is +performed at map/unmap time, making the cacheline overlap harmless. + +All other major dma-buf exporters already pass this flag: + - drm_gem_map_dma_buf() passes DMA_ATTR_SKIP_CPU_SYNC + - amdgpu_dma_buf_map() passes DMA_ATTR_SKIP_CPU_SYNC + +The CPU sync at map/unmap time is also redundant for udmabuf: +begin_cpu_udmabuf() and end_cpu_udmabuf() already perform explicit +cache synchronization via dma_sync_sgtable_for_cpu/device() when CPU +access is requested through the dma-buf interface. + +Pass DMA_ATTR_SKIP_CPU_SYNC to dma_map_sgtable() and +dma_unmap_sgtable() in udmabuf to suppress the spurious warning and +skip the redundant sync. + +Fixes: 284562e1f348 ("udmabuf: implement begin_cpu_access/end_cpu_access hooks") +Cc: stable@vger.kernel.org +Signed-off-by: Mikhail Gavrilov +Acked-by: Vivek Kasireddy +Signed-off-by: Vivek Kasireddy +Link: https://patch.msgid.link/20260331061657.79983-1-mikhail.v.gavrilov@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma-buf/udmabuf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -163,7 +163,7 @@ static struct sg_table *get_sg_table(str + sg_set_folio(sgl, ubuf->folios[i], PAGE_SIZE, + ubuf->offsets[i]); + +- ret = dma_map_sgtable(dev, sg, direction, 0); ++ ret = dma_map_sgtable(dev, sg, direction, DMA_ATTR_SKIP_CPU_SYNC); + if (ret < 0) + goto err_map; + return sg; +@@ -178,7 +178,7 @@ err_alloc: + static void put_sg_table(struct device *dev, struct sg_table *sg, + enum dma_data_direction direction) + { +- dma_unmap_sgtable(dev, sg, direction, 0); ++ dma_unmap_sgtable(dev, sg, direction, DMA_ATTR_SKIP_CPU_SYNC); + sg_free_table(sg); + kfree(sg); + } diff --git a/queue-6.18/fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch b/queue-6.18/fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch new file mode 100644 index 0000000000..9b7d4bc93a --- /dev/null +++ b/queue-6.18/fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch @@ -0,0 +1,42 @@ +From fc3b071a7c8dc0f5d56defddf6e6fd5aaa3e1e27 Mon Sep 17 00:00:00 2001 +From: Sebastian Alba Vives +Date: Mon, 18 May 2026 13:07:41 -0600 +Subject: fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() + +From: Sebastian Alba Vives + +commit fc3b071a7c8dc0f5d56defddf6e6fd5aaa3e1e27 upstream. + +afu_ioctl_dma_map() accepts a 64-bit length from userspace via +DFL_FPGA_PORT_DMA_MAP ioctl without an upper bound check. The value +is passed to afu_dma_pin_pages() where npages is derived as +length >> PAGE_SHIFT and passed to pin_user_pages_fast() which takes +int nr_pages, causing implicit truncation if length is very large. + +Validate map.length at the ioctl entry point before calling +afu_dma_map_region(), rejecting values whose page count exceeds +INT_MAX. + +Fixes: fa8dda1edef9 ("fpga: dfl: afu: add DFL_FPGA_PORT_DMA_MAP/UNMAP ioctls support") +Cc: stable@vger.kernel.org +Signed-off-by: Sebastian Alba Vives +Reviewed-by: Xu Yilun +Link: https://lore.kernel.org/r/20260518190742.61426-3-sebasjosue84@gmail.com +Signed-off-by: Xu Yilun +Signed-off-by: Greg Kroah-Hartman +--- + drivers/fpga/dfl-afu-main.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/fpga/dfl-afu-main.c ++++ b/drivers/fpga/dfl-afu-main.c +@@ -723,6 +723,9 @@ afu_ioctl_dma_map(struct dfl_feature_dev + if (map.argsz < minsz || map.flags) + return -EINVAL; + ++ if (map.length >> PAGE_SHIFT > (u64)INT_MAX) ++ return -EINVAL; ++ + ret = afu_dma_map_region(fdata, map.user_addr, map.length, &map.iova); + if (ret) + return ret; diff --git a/queue-6.18/iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch b/queue-6.18/iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch new file mode 100644 index 0000000000..341a2ff86f --- /dev/null +++ b/queue-6.18/iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch @@ -0,0 +1,61 @@ +From 69fe699afe1afcb730164b86c228483c2da05f94 Mon Sep 17 00:00:00 2001 +From: Weinan Liu +Date: Thu, 28 May 2026 22:31:47 +0000 +Subject: iommu/amd: Don't split flush for amd_iommu_domain_flush_all() + +From: Weinan Liu + +commit 69fe699afe1afcb730164b86c228483c2da05f94 upstream. + +We have observed multiple full invalidations occurring during device +detach when we are done using the vfio-device. + +blocked_domain_attach_device() + -> detach_device() + -> amd_iommu_domain_flush_all() + -> amd_iommu_domain_flush_pages(..., CMD_INV_IOMMU_ALL_PAGES_ADDRESS) + + while (size != 0) { + + -> __domain_flush_pages( flush_size /* power of 2 flush_size */) + -> domain_flush_pages_v1() + -> build_inv_iommu_pages() + -> build_inv_address() + + } + +build_inv_address() will trigger a full invalidation if the chunk +size > (1 << 51). Consequently, the guest will issue multiple full +invalidations for a single call to amd_iommu_domain_flush_all() + +Without this patch, we will see 10 time instead of 1 time full +invalidations for every amd_iommu_domain_flush_all(). + +Cc: stable@vger.kernel.org +Fixes: a270be1b3fdf ("iommu/amd: Use only natural aligned flushes in a VM") +Suggested-by: Josef Bacik +Suggested-by: Jason Gunthorpe +Signed-off-by: Weinan Liu +Reviewed-by: Wei Wang +Reviewed-by: Jason Gunthorpe +Reviewed-by: Samiullah Khawaja +Reviewed-by: Suravee Suthikulpanit +Reviewed-by: Vasant Hegde +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/amd/iommu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -1689,7 +1689,8 @@ void amd_iommu_domain_flush_pages(struct + { + lockdep_assert_held(&domain->lock); + +- if (likely(!amd_iommu_np_cache)) { ++ if (likely(!amd_iommu_np_cache) || ++ size >= (1ULL<<52)) { + __domain_flush_pages(domain, address, size); + + /* Wait until IOMMU TLB and all device IOTLB flushes are complete */ diff --git a/queue-6.18/iommu-vt-d-avoid-warning-in-sva-unbind-path.patch b/queue-6.18/iommu-vt-d-avoid-warning-in-sva-unbind-path.patch new file mode 100644 index 0000000000..ea249d2ac8 --- /dev/null +++ b/queue-6.18/iommu-vt-d-avoid-warning-in-sva-unbind-path.patch @@ -0,0 +1,103 @@ +From 534b5f98ab7319d8004bbc7dab6481462243e883 Mon Sep 17 00:00:00 2001 +From: Lu Baolu +Date: Thu, 4 Jun 2026 14:03:06 +0800 +Subject: iommu/vt-d: Avoid WARNING in sva unbind path + +From: Lu Baolu + +commit 534b5f98ab7319d8004bbc7dab6481462243e883 upstream. + +The Intel IOMMU driver allows SVA on devices even if they do not support +PCI/PRI. Commit 39c20c4e83b9 ("iommu/vt-d: Only handle IOPF for SVA when +PRI is supported") modified the SVA bind path to allow this configuration +by skipping IOPF enablement when PRI is missing. However, it failed to +update the unbind path. + +This creates an imbalance: the unbind path attempts to disable IOPF for +a device that never had it enabled, triggering a WARNING in +intel_iommu_disable_iopf(): + + WARNING: drivers/iommu/intel/iommu.c:3475 at intel_iommu_disable_iopf+0x4f/0x90d + Call Trace: + + blocking_domain_set_dev_pasid+0x50/0x70 + iommu_detach_device_pasid+0x89/0xc0 + iommu_sva_unbind_device+0x73/0x150 + xe_vm_close_and_put+0x4d2/0x1200 [xe] + +Fix this by bypassing IOPF operations for SVA domains on non-PRI hardware +in both the bind and unbind paths. + +Fixes: 39c20c4e83b9 ("iommu/vt-d: Only handle IOPF for SVA when PRI is supported") +Cc: stable@vger.kernel.org +Reported-by: Nareshkumar Gollakoti +Signed-off-by: Lu Baolu +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20260519052917.3729796-1-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/intel/iommu.h | 11 +++++++++++ + drivers/iommu/intel/svm.c | 12 ++++-------- + 2 files changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/iommu/intel/iommu.h ++++ b/drivers/iommu/intel/iommu.h +@@ -1334,18 +1334,29 @@ void intel_iommu_disable_iopf(struct dev + static inline int iopf_for_domain_set(struct iommu_domain *domain, + struct device *dev) + { ++ struct device_domain_info *info = dev_iommu_priv_get(dev); ++ + if (!domain || !domain->iopf_handler) + return 0; + ++ /* SVA with non-IOMMU/PRI IOPF handling is allowed. */ ++ if (domain->type == IOMMU_DOMAIN_SVA && !info->pri_supported) ++ return 0; ++ + return intel_iommu_enable_iopf(dev); + } + + static inline void iopf_for_domain_remove(struct iommu_domain *domain, + struct device *dev) + { ++ struct device_domain_info *info = dev_iommu_priv_get(dev); ++ + if (!domain || !domain->iopf_handler) + return; + ++ if (domain->type == IOMMU_DOMAIN_SVA && !info->pri_supported) ++ return; ++ + intel_iommu_disable_iopf(dev); + } + +--- a/drivers/iommu/intel/svm.c ++++ b/drivers/iommu/intel/svm.c +@@ -164,12 +164,9 @@ static int intel_svm_set_dev_pasid(struc + if (IS_ERR(dev_pasid)) + return PTR_ERR(dev_pasid); + +- /* SVA with non-IOMMU/PRI IOPF handling is allowed. */ +- if (info->pri_supported) { +- ret = iopf_for_domain_replace(domain, old, dev); +- if (ret) +- goto out_remove_dev_pasid; +- } ++ ret = iopf_for_domain_replace(domain, old, dev); ++ if (ret) ++ goto out_remove_dev_pasid; + + /* Setup the pasid table: */ + sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0; +@@ -183,8 +180,7 @@ static int intel_svm_set_dev_pasid(struc + + return 0; + out_unwind_iopf: +- if (info->pri_supported) +- iopf_for_domain_replace(old, domain, dev); ++ iopf_for_domain_replace(old, domain, dev); + out_remove_dev_pasid: + domain_remove_dev_pasid(domain, dev, pasid); + return ret; diff --git a/queue-6.18/iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch b/queue-6.18/iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch new file mode 100644 index 0000000000..7c5ce1006c --- /dev/null +++ b/queue-6.18/iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch @@ -0,0 +1,70 @@ +From 091ab6d70dc444f56ed14faedbcacfc979f4c613 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Mon, 1 Jun 2026 13:42:37 -0700 +Subject: iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read() + +From: Nicolin Chen + +commit 091ab6d70dc444f56ed14faedbcacfc979f4c613 upstream. + +The cookie returned by xa_alloc() in iommufd_fault_fops_read() is per fault +group, but the inner copy_to_user() runs per fault inside the group. If a +copy fails mid-group, xa_erase clears the cookie and the group is restored +to the deliver list, yet done is not rolled back. The function returns the +partial byte count, with the successfully copied faults sitting at offsets +below done carrying the now-erased cookie. The next read() then re-fetches +the group, allocates a fresh cookie, and re-delivers every fault including +the ones already copied; userspace sees duplicates carrying the new cookie, +and a stale cookie that can never be responded to. + +Use a local group_done variable that tracks the per-group progress inside +the inner loop, and only commit done = group_done after the inner loop has +finished successfully. On a copy_to_user failure the outer break skips the +commit, so done remains at its prior start-of-group baseline; the partial +bytes already written past done are undefined to userspace per the read(2) +contract, and the next read re-delivers the whole group atomically. + +Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object") +Link: https://patch.msgid.link/r/360cab4d4aeccb0bae275a970e2b3c340a71e0e0.1780343944.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -139,6 +139,8 @@ static ssize_t iommufd_fault_fops_read(s + + mutex_lock(&fault->mutex); + while ((group = iommufd_fault_deliver_fetch(fault))) { ++ size_t group_done = done; ++ + if (done >= count || + group->fault_count * fault_size > count - done) { + iommufd_fault_deliver_restore(fault, group); +@@ -160,16 +162,17 @@ static ssize_t iommufd_fault_fops_read(s + iommufd_compose_fault_message(&iopf->fault, + &data, idev, + group->cookie); +- if (copy_to_user(buf + done, &data, fault_size)) { ++ if (copy_to_user(buf + group_done, &data, fault_size)) { + xa_erase(&fault->response, group->cookie); + iommufd_fault_deliver_restore(fault, group); + rc = -EFAULT; + break; + } +- done += fault_size; ++ group_done += fault_size; + } + if (rc) + break; ++ done = group_done; + } + mutex_unlock(&fault->mutex); + diff --git a/queue-6.18/iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch b/queue-6.18/iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch new file mode 100644 index 0000000000..0b4a0d768a --- /dev/null +++ b/queue-6.18/iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch @@ -0,0 +1,39 @@ +From 172fc8b19825a0f5884c38f2289188284e2d45ee Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Mon, 1 Jun 2026 13:42:36 -0700 +Subject: iommufd: Break the loop on failure in iommufd_fault_fops_read() + +From: Nicolin Chen + +commit 172fc8b19825a0f5884c38f2289188284e2d45ee upstream. + +On a copy_to_user() failure inside the inner list_for_each_entry, only the +inner loop breaks; the outer while re-fetches the just-restored fault group +and retries the failing copy_to_user() forever, spinning the reader at 100% +CPU with fault->mutex held. + +Check rc after the inner loop and break the outer while as well. + +Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object") +Link: https://patch.msgid.link/r/336a9b6e44fe66a24199d3be777c405c85c98622.1780343944.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -168,6 +168,8 @@ static ssize_t iommufd_fault_fops_read(s + } + done += fault_size; + } ++ if (rc) ++ break; + } + mutex_unlock(&fault->mutex); + diff --git a/queue-6.18/iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch b/queue-6.18/iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch new file mode 100644 index 0000000000..6eb07bd98c --- /dev/null +++ b/queue-6.18/iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch @@ -0,0 +1,40 @@ +From 85345becfead3255a5f875d4b4d82ea01d926239 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Thu, 21 May 2026 17:36:32 -0700 +Subject: iommufd: Fix data_len byte-count vs element-count mismatch + +From: Nicolin Chen + +commit 85345becfead3255a5f875d4b4d82ea01d926239 upstream. + +kzalloc_flex() computes the allocation size. With event_data typed as u64, +data_len is interpreted as a u64 element count. Yet, every caller and the +read path treat data_len as a byte count. The current code over-allocates +by sizeof(u64) and the __counted_by() annotation overstates the length by +the same factor. + +Re-type event_data as u8. No functional change in user-visible behavior. + +Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC") +Link: https://patch.msgid.link/r/f7665f839b9dce917d6bd394375a1cf56568d86b.1779408671.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Reviewed-by: Jason Gunthorpe +Signed-off-by: Nicolin Chen +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/iommufd_private.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iommu/iommufd/iommufd_private.h ++++ b/drivers/iommu/iommufd/iommufd_private.h +@@ -599,7 +599,7 @@ struct iommufd_vevent { + struct iommufd_vevent_header header; + struct list_head node; /* for iommufd_eventq::deliver */ + ssize_t data_len; +- u64 event_data[] __counted_by(data_len); ++ u8 event_data[] __counted_by(data_len); + }; + + #define vevent_for_lost_events_header(vevent) \ diff --git a/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch b/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch new file mode 100644 index 0000000000..df7b7b70d3 --- /dev/null +++ b/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch @@ -0,0 +1,40 @@ +From 47916a54eeb2a9e654512ee609f71bd5b29db702 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Mon, 1 Jun 2026 13:42:35 -0700 +Subject: iommufd: Reject invalid read count in iommufd_fault_fops_read() + +From: Nicolin Chen + +commit 47916a54eeb2a9e654512ee609f71bd5b29db702 upstream. + +The read count must be large enough to hold one fault or a group's faults. + +iommufd_fault_fops_read() does not validate the count, but returns 0 as if +the read had succeeded while leaving the pending fault in the queue. + +Return -EINVAL in the undersize cases. + +Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object") +Link: https://patch.msgid.link/r/85c118a606fbedc5c132a1f5ec223a5ba23b92d2.1780343944.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -142,6 +142,9 @@ static ssize_t iommufd_fault_fops_read(s + if (done >= count || + group->fault_count * fault_size > count - done) { + iommufd_fault_deliver_restore(fault, group); ++ /* Read count doesn't fit the first fault group */ ++ if (done == 0) ++ rc = -EINVAL; + break; + } + diff --git a/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch b/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch new file mode 100644 index 0000000000..6b1df4b122 --- /dev/null +++ b/queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch @@ -0,0 +1,56 @@ +From 00203ca8323f9714630408c19a209b52397975e6 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Mon, 1 Jun 2026 13:42:33 -0700 +Subject: iommufd: Reject invalid read count in iommufd_veventq_fops_read() + +From: Nicolin Chen + +commit 00203ca8323f9714630408c19a209b52397975e6 upstream. + +The read count must be large enough to hold a vEVENT header. For a normal +vEVENT, it must also hold the trailing data following the header. + +iommufd_veventq_fops_read() does not validate the count, but returns 0 as +if the read had succeeded while leaving the pending event in the queue. + +Return -EINVAL in both undersize cases. + +Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC") +Link: https://patch.msgid.link/r/e1111adcc8a8882fbfd84accd6674dc846dc5689.1780343944.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c +index 896f45be0d2e..ac485d010a43 100644 +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -310,6 +310,9 @@ static ssize_t iommufd_veventq_fops_read(struct file *filep, char __user *buf, + + if (*ppos) + return -ESPIPE; ++ /* Minimum read count is a vEVENT header */ ++ if (count < sizeof(*hdr)) ++ return -EINVAL; + + while ((cur = iommufd_veventq_deliver_fetch(veventq))) { + /* Validate the remaining bytes against the header size */ +@@ -323,6 +326,9 @@ static ssize_t iommufd_veventq_fops_read(struct file *filep, char __user *buf, + if (!vevent_for_lost_events_header(cur) && + sizeof(*hdr) + cur->data_len > count - done) { + iommufd_veventq_deliver_restore(veventq, cur); ++ /* Read count doesn't fit a single normal vEVENT */ ++ if (done == 0) ++ rc = -EINVAL; + break; + } + +-- +2.55.0 + diff --git a/queue-6.18/iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch b/queue-6.18/iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch new file mode 100644 index 0000000000..5fd235940f --- /dev/null +++ b/queue-6.18/iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch @@ -0,0 +1,36 @@ +From 01e41ad76c12ae5c49ab4ef4fc7dd54e9b8784d6 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Mon, 1 Jun 2026 13:42:32 -0700 +Subject: iommufd: Rewind header length in done if iommufd_veventq_fops_read() fails + +From: Nicolin Chen + +commit 01e41ad76c12ae5c49ab4ef4fc7dd54e9b8784d6 upstream. + +When the first event copy fails, rc = -EFAULT will not be reported as done +is set to the length of the copied header. + +Rewind it to report rc correctly. + +Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC") +Link: https://patch.msgid.link/r/78f8caeb6a5d667a26b870e3068cec47dd4b5be1.1780343944.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Signed-off-by: Nicolin Chen +Reviewed-by: Pranjal Shrivastava +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -336,6 +336,7 @@ static ssize_t iommufd_veventq_fops_read + if (cur->data_len && + copy_to_user(buf + done, cur->event_data, cur->data_len)) { + iommufd_veventq_deliver_restore(veventq, cur); ++ done -= sizeof(*hdr); + rc = -EFAULT; + break; + } diff --git a/queue-6.18/iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch b/queue-6.18/iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch new file mode 100644 index 0000000000..d67dc55078 --- /dev/null +++ b/queue-6.18/iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch @@ -0,0 +1,62 @@ +From 4d70986002f2f3eaaed89124fb2522bded38b016 Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Wed, 3 Jun 2026 14:26:53 -0700 +Subject: iommufd: Set upper bounds on cache invalidation entry_num and entry_len + +From: Nicolin Chen + +commit 4d70986002f2f3eaaed89124fb2522bded38b016 upstream. + +iommufd_hwpt_invalidate() takes a user-controlled entry_num and entry_len, +each bounded only by U32_MAX. An entry_len beyond the kernel's struct size +makes the copy helper verify the extra bytes are zero, scanning that excess +in one uninterruptible pass; a multi-gigabyte value over zeroed user memory +trips the soft-lockup watchdog. + +A large entry_num is the other half, driving the backend invalidation loop +with no reschedule. The VT-d nested handler, for one, copies each entry and +flushes caches per iteration, pinning the CPU on a non-preemptible kernel. + +Cap both in the ioctl. entry_len is held under PAGE_SIZE, above any request +struct, and entry_num under 1 << 19, the order of a hardware invalidation +queue and well beyond any real batch, bounding the per-call loop length. + +Fixes: 8c6eabae3807 ("iommufd: Add IOMMU_HWPT_INVALIDATE") +Link: https://patch.msgid.link/r/447fa93663f7526eb361719e83fa8b649464483d.1780521606.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Nicolin Chen +Reviewed-by: Lu Baolu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/hw_pagetable.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/iommu/iommufd/hw_pagetable.c ++++ b/drivers/iommu/iommufd/hw_pagetable.c +@@ -489,6 +489,9 @@ int iommufd_hwpt_get_dirty_bitmap(struct + return rc; + } + ++/* An arbitrary entry_num cap, far above any realistic invalidation batch */ ++#define IOMMU_HWPT_INVALIDATE_ENTRY_NUM_MAX (1U << 19) ++ + int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd) + { + struct iommu_hwpt_invalidate *cmd = ucmd->cmd; +@@ -507,7 +510,13 @@ int iommufd_hwpt_invalidate(struct iommu + goto out; + } + +- if (cmd->entry_num && (!cmd->data_uptr || !cmd->entry_len)) { ++ /* ++ * Bound entry_num and entry_len so a single call cannot pin the CPU; ++ * entry_len also caps the copy_struct_from_user() trailing-zero scan. ++ */ ++ if (cmd->entry_num && ++ (!cmd->data_uptr || !cmd->entry_len || cmd->entry_len > PAGE_SIZE || ++ cmd->entry_num > IOMMU_HWPT_INVALIDATE_ENTRY_NUM_MAX)) { + rc = -EINVAL; + goto out; + } diff --git a/queue-6.18/iommufd-set-veventq_depth-upper-bound.patch b/queue-6.18/iommufd-set-veventq_depth-upper-bound.patch new file mode 100644 index 0000000000..0ed09f4449 --- /dev/null +++ b/queue-6.18/iommufd-set-veventq_depth-upper-bound.patch @@ -0,0 +1,51 @@ +From 6ebf2eb46fbd5b40393ff8fbb847ba96925beaff Mon Sep 17 00:00:00 2001 +From: Nicolin Chen +Date: Thu, 21 May 2026 17:36:34 -0700 +Subject: iommufd: Set veventq_depth upper bound + +From: Nicolin Chen + +commit 6ebf2eb46fbd5b40393ff8fbb847ba96925beaff upstream. + +iommufd_veventq_alloc() accepts any !0 veventq_depth from userspace, with +an upper bound at U32_MAX. + +This leaves a vulnerability where userspace can allocate excessively large +queues to exhaust kernel memory reserves. + +Cap the veventq_depth (maximum number of entries) to 1 << 19, matching the +maximum number of entries in the SMMUv3 EVTQ (the largest use case today). + +Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC") +Link: https://patch.msgid.link/r/8426cbaa5e8294472ec7f076ef427cc473be5985.1779408671.git.nicolinc@nvidia.com +Cc: stable@vger.kernel.org +Reviewed-by: Jason Gunthorpe +Signed-off-by: Nicolin Chen +Reviewed-by: Kevin Tian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -473,6 +473,9 @@ int iommufd_fault_iopf_handler(struct io + static const struct file_operations iommufd_veventq_fops = + INIT_EVENTQ_FOPS(iommufd_veventq_fops_read, NULL); + ++/* An arbitrary upper bound for veventq_depth that fits all existing HWs */ ++#define VEVENTQ_MAX_DEPTH (1U << 19) ++ + int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd) + { + struct iommu_veventq_alloc *cmd = ucmd->cmd; +@@ -484,7 +487,7 @@ int iommufd_veventq_alloc(struct iommufd + if (cmd->flags || cmd->__reserved || + cmd->type == IOMMU_VEVENTQ_TYPE_DEFAULT) + return -EOPNOTSUPP; +- if (!cmd->veventq_depth) ++ if (!cmd->veventq_depth || cmd->veventq_depth > VEVENTQ_MAX_DEPTH) + return -EINVAL; + + viommu = iommufd_get_viommu(ucmd, cmd->viommu_id); diff --git a/queue-6.18/iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch b/queue-6.18/iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch new file mode 100644 index 0000000000..3fbbe66477 --- /dev/null +++ b/queue-6.18/iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch @@ -0,0 +1,68 @@ +From be93d186ae88a92e7aa77e122d4e661fa57b1e39 Mon Sep 17 00:00:00 2001 +From: Kai Aizen +Date: Thu, 30 Apr 2026 20:56:30 +0300 +Subject: iommufd: Use sizeof(*hdr) instead of sizeof(hdr) in veventq read + +From: Kai Aizen + +commit be93d186ae88a92e7aa77e122d4e661fa57b1e39 upstream. + +The bound-check in iommufd_veventq_fops_read() for the normal vEVENT +path uses sizeof(hdr) where the surrounding code uses sizeof(*hdr): + + if (!vevent_for_lost_events_header(cur) && + sizeof(hdr) + cur->data_len > count - done) { + +hdr is declared as struct iommufd_vevent_header *, so sizeof(hdr) +evaluates to the size of the pointer. Surrounding code uses +sizeof(*hdr) consistently: + + if (done >= count || sizeof(*hdr) > count - done) { + ... + if (copy_to_user(buf + done, hdr, sizeof(*hdr))) { + ... + done += sizeof(*hdr); + +struct iommufd_vevent_header is currently 8 bytes (two __u32 fields, +flags and sequence), so on 64-bit (sizeof(void *) == 8) the two +expressions happen to be equal and the check works as intended. + +On 32-bit (sizeof(void *) == 4) the check under-counts the header by +4 bytes: a vEVENT whose data_len causes 8 + cur->data_len to exceed +count - done while 4 + cur->data_len does not will pass the check, +then the loop will copy_to_user 8 bytes of header followed by data_len +bytes of payload, writing past the user-supplied buffer. + +It is also a latent bug for any future expansion of struct +iommufd_vevent_header beyond sizeof(void *) on 64-bit; the check +should not depend on the type happening to match the host pointer +width. + +Use sizeof(*hdr) to match the rest of the function and the actual +amount that will be copied. + +Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC") +Link: https://patch.msgid.link/r/20260430175630.67078-1-kai.aizen.dev@gmail.com +Cc: stable@vger.kernel.org +Reported-by: Kai Aizen +Signed-off-by: Kai Aizen +Reviewed-by: Kevin Tian +Reviewed-by: Nicolin Chen +Reviewed-by: Lu Baolu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/iommufd/eventq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iommu/iommufd/eventq.c ++++ b/drivers/iommu/iommufd/eventq.c +@@ -321,7 +321,7 @@ static ssize_t iommufd_veventq_fops_read + + /* If being a normal vEVENT, validate against the full size */ + if (!vevent_for_lost_events_header(cur) && +- sizeof(hdr) + cur->data_len > count - done) { ++ sizeof(*hdr) + cur->data_len > count - done) { + iommufd_veventq_deliver_restore(veventq, cur); + break; + } diff --git a/queue-6.18/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch b/queue-6.18/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch new file mode 100644 index 0000000000..c21a3c0f42 --- /dev/null +++ b/queue-6.18/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch @@ -0,0 +1,43 @@ +From e8042f6e1d7befb2fb6b10a75918642bcd0acf9a Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Sun, 7 Jun 2026 02:56:10 +0900 +Subject: KVM: arm64: Clear __hyp_running_vcpu when flushing the pKVM hyp vCPU + +From: Hyunwoo Kim + +commit e8042f6e1d7befb2fb6b10a75918642bcd0acf9a upstream. + +flush_hyp_vcpu() copies the host vCPU context into the hyp's private +vCPU on every run. ctxt_to_vcpu() expects a guest context to have a +NULL __hyp_running_vcpu, which is only ever set on the host context, so +that it resolves the vCPU via container_of(). While this is generally +the case, flush_hyp_vcpu() copies the context verbatim and does not +enforce this, so a value provided by the host is dereferenced at EL2 +(host -> EL2). + +Fix by clearing __hyp_running_vcpu after the copy. + +Cc: stable@vger.kernel.org +Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()") +Signed-off-by: Hyunwoo Kim +Reviewed-by: Fuad Tabba +Tested-by: Fuad Tabba +Link: https://patch.msgid.link/20260606175614.83273-2-imv4bel@gmail.com +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/hyp/nvhe/hyp-main.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c ++++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c +@@ -126,6 +126,9 @@ static void flush_hyp_vcpu(struct pkvm_h + + hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt; + ++ /* __hyp_running_vcpu must be NULL in a guest context. */ ++ hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL; ++ + hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2; + hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE); + hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) & diff --git a/queue-6.18/kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch b/queue-6.18/kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch new file mode 100644 index 0000000000..453ed3660b --- /dev/null +++ b/queue-6.18/kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch @@ -0,0 +1,38 @@ +From 9f76b039a72d7e06374aa96862f0232ed53f7787 Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Tue, 2 Jun 2026 16:54:46 -0700 +Subject: KVM: arm64: Don't leak PFN when kvm_translate_vncr() races MMU notifier + +From: Oliver Upton + +commit 9f76b039a72d7e06374aa96862f0232ed53f7787 upstream. + +In the case that kvm_translate_vncr() races with an MMU notifier the +early return does not release a reference on the faulted in PFN. Add +the necessary call to kvm_release_faultin_page() for the unused PFN. + +Cc: stable@vger.kernel.org +Fixes: 069a05e535496 ("KVM: arm64: nv: Handle VNCR_EL2-triggered faults") +Reported-by: Sashiko (local):gemini-3.1-pro +Signed-off-by: Oliver Upton +Link: https://patch.msgid.link/20260602235450.103057-2-oupton@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/nested.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/arm64/kvm/nested.c ++++ b/arch/arm64/kvm/nested.c +@@ -1238,8 +1238,10 @@ static int kvm_translate_vncr(struct kvm + } + + scoped_guard(write_lock, &vcpu->kvm->mmu_lock) { +- if (mmu_invalidate_retry(vcpu->kvm, mmu_seq)) ++ if (mmu_invalidate_retry(vcpu->kvm, mmu_seq)) { ++ kvm_release_faultin_page(vcpu->kvm, page, true, false); + return -EAGAIN; ++ } + + vt->gva = va; + vt->hpa = pfn << PAGE_SHIFT; diff --git a/queue-6.18/kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch b/queue-6.18/kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch new file mode 100644 index 0000000000..d4a6216a9f --- /dev/null +++ b/queue-6.18/kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch @@ -0,0 +1,104 @@ +From 4be6cbeb93d26994bd1827ddbce391e3c4395c8f Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Sun, 7 Jun 2026 18:57:45 +0100 +Subject: KVM: arm64: nv: Avoid dereferencing NULL VNCR pseudo-TLB + +From: Marc Zyngier + +commit 4be6cbeb93d26994bd1827ddbce391e3c4395c8f upstream. + +VNCR TLB invalidation occurs from MMU notifiers or TLBI instructions, +and either can race against a vcpu not being onlined yet (no pseudo-TLB +allocated). Similarly, the TLB might be invalid, and the invalidation +should be skipped in this case. + +Both kvm_invalidate_vncr_ipa() and kvm_invalidate_vncr_va() are +expected to perform the same checks, except that the latter doesn't +check for the allocation and blindly dereferences the pointer. + +Solve this by introducing a new iterator built on top of the usual +kvm_for_each_vcpu() that checks for both of the above conditions, +and convert the two users to it. + +Reported-by: Hyunwoo Kim +Link: https://lore.kernel.org/r/aiUvSbrWndQeUPc8@v4bel +Fixes: 4ffa72ad8f37 ("KVM: arm64: nv: Add S1 TLB invalidation primitive for VNCR_EL2") +Cc: stable@vger.kernel.org +Reviewed-by: Oliver Upton +Link: https://patch.msgid.link/20260607175745.297793-1-maz@kernel.org +Signed-off-by: Marc Zyngier +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/nested.c | 36 +++++++++++++++--------------------- + 1 file changed, 15 insertions(+), 21 deletions(-) + +--- a/arch/arm64/kvm/nested.c ++++ b/arch/arm64/kvm/nested.c +@@ -824,9 +824,21 @@ static void invalidate_vncr(struct vncr_ + clear_fixmap(vncr_fixmap(vt->cpu)); + } + ++/* ++ * VNCR TLB invalidation occurs from MMU notifiers or TLBI instructions, and ++ * either can race against a vcpu not being onlined yet (no pseudo-TLB ++ * allocated). Similarly, the TLB might be invalid. Skip those, as they ++ * obviously don't participate in the invalidation at this stage. ++ */ ++#define kvm_for_each_vncr_tlb(idx, vcpup, tlbp, kvm) \ ++ kvm_for_each_vcpu(idx, vcpup, kvm) \ ++ if (((tlbp) = vcpup->arch.vncr_tlb) && \ ++ (tlbp)->valid) ++ + static void kvm_invalidate_vncr_ipa(struct kvm *kvm, u64 start, u64 end) + { + struct kvm_vcpu *vcpu; ++ struct vncr_tlb *vt; + unsigned long i; + + lockdep_assert_held_write(&kvm->mmu_lock); +@@ -834,24 +846,9 @@ static void kvm_invalidate_vncr_ipa(stru + if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY)) + return; + +- kvm_for_each_vcpu(i, vcpu, kvm) { +- struct vncr_tlb *vt = vcpu->arch.vncr_tlb; ++ kvm_for_each_vncr_tlb(i, vcpu, vt, kvm) { + u64 ipa_start, ipa_end, ipa_size; + +- /* +- * Careful here: We end-up here from an MMU notifier, +- * and this can race against a vcpu not being onlined +- * yet, without the pseudo-TLB being allocated. +- * +- * Skip those, as they obviously don't participate in +- * the invalidation at this stage. +- */ +- if (!vt) +- continue; +- +- if (!vt->valid) +- continue; +- + ipa_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, + vt->wr.level)); + ipa_start = vt->wr.pa & ~(ipa_size - 1); +@@ -881,17 +878,14 @@ static void invalidate_vncr_va(struct kv + struct s1e2_tlbi_scope *scope) + { + struct kvm_vcpu *vcpu; ++ struct vncr_tlb *vt; + unsigned long i; + + lockdep_assert_held_write(&kvm->mmu_lock); + +- kvm_for_each_vcpu(i, vcpu, kvm) { +- struct vncr_tlb *vt = vcpu->arch.vncr_tlb; ++ kvm_for_each_vncr_tlb(i, vcpu, vt, kvm) { + u64 va_start, va_end, va_size; + +- if (!vt->valid) +- continue; +- + va_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, + vt->wr.level)); + va_start = vt->gva & ~(va_size - 1); diff --git a/queue-6.18/kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch b/queue-6.18/kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch new file mode 100644 index 0000000000..0c5b403a8d --- /dev/null +++ b/queue-6.18/kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch @@ -0,0 +1,79 @@ +From 7f4b7092d9a173a4271e28c0ed1fc235994e309b Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 14 May 2026 14:31:14 -0700 +Subject: KVM: SVM: Disable x2AVIC RDMSR interception for MSRs KVM actually supports + +From: Sean Christopherson + +commit 7f4b7092d9a173a4271e28c0ed1fc235994e309b upstream. + +When toggling x2AVIC on/off, use KVM's curated mask of x2APIC MSRs that +can/should be passed through to the guest (or not) when 2AVIC is enabled. +Using the effective list provided by the local APIC emulation fixes +multiple (classes of) bugs, as the existing hand-coded list of MSRs is +wrong on multiple fronts: + + - ARBPRI isn't supported by KVM, isn't accelerated by AVIC (for read or + write), and its #VMEXIT is fault-like, i.e. requires decoding the + instruction. Disabling interception is nonsensical and suboptimal. + + - DFR and ICR2 aren't supported by x2APIC and so don't need their + intercepts disabled for performance reasons. While the #GP due to + x2APIC being abled has higher priority than the trap-like #VMEXIT, + disabling interception of unsupported MSRs is confusing and unnecessary. + + - RRR is completely unsupported. + + - AVIC currently fails to pass through the "range of vectors" registers, + IRR, ISR, and TMR, as e.g. X2APIC_MSR(APIC_IRR) only affects IRR0, and + thus only disables intercept for vectors 31:0 (which are the *least* + interesting registers). + + - TMCCT (the current APIC timer count) isn't accelerated by hardware, and + generates a fault-like AVIC_UNACCELERATED_ACCESS #VMEXIT, i.e. requires + KVM to decode the instruction to figure out what the guest was trying to + access. Note, the only reason this isn't a fatal bug is that the AVIC + architecture had the foresight to guard against buggy hypervisors. E.g. + if hardware simply read from the virtual APIC page, the guest would get + garbage (because the timer is emulated in software). + +Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode") +Cc: stable@vger.kernel.org +Reviewed-by: Naveen N Rao (AMD) +Link: https://patch.msgid.link/20260514213115.1637082-3-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/avic.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/svm/avic.c ++++ b/arch/x86/kvm/svm/avic.c +@@ -111,6 +111,9 @@ static bool x2avic_enabled; + static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm, + bool intercept) + { ++ struct kvm_vcpu *vcpu = &svm->vcpu; ++ u64 rd_regs; ++ + static const u32 x2avic_passthrough_msrs[] = { + X2APIC_MSR(APIC_ID), + X2APIC_MSR(APIC_LVR), +@@ -151,9 +154,15 @@ static void avic_set_x2apic_msr_intercep + if (!x2avic_enabled) + return; + ++ rd_regs = kvm_x2apic_disable_read_intercept_reg_mask(vcpu); ++ ++ for_each_set_bit(i, (unsigned long *)&rd_regs, BITS_PER_TYPE(rd_regs)) ++ svm_set_intercept_for_msr(vcpu, APIC_BASE_MSR + i, ++ MSR_TYPE_R, intercept); ++ + for (i = 0; i < ARRAY_SIZE(x2avic_passthrough_msrs); i++) +- svm_set_intercept_for_msr(&svm->vcpu, x2avic_passthrough_msrs[i], +- MSR_TYPE_RW, intercept); ++ svm_set_intercept_for_msr(vcpu, x2avic_passthrough_msrs[i], ++ MSR_TYPE_W, intercept); + + svm->x2avic_msrs_intercepted = intercept; + } diff --git a/queue-6.18/kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch b/queue-6.18/kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch new file mode 100644 index 0000000000..5a9d105884 --- /dev/null +++ b/queue-6.18/kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch @@ -0,0 +1,100 @@ +From 8c63179d975f2029c948ecce622f72af616dbff7 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 14 May 2026 14:31:15 -0700 +Subject: KVM: SVM: Only disable x2AVIC WRMSR interception for MSRs that are accelerated + +From: Sean Christopherson + +commit 8c63179d975f2029c948ecce622f72af616dbff7 upstream. + +When x2AVIC is enabled, disable WRMSR interception only for MSRs that are +actually accelerated by hardware. Disabling interception for MSRs that +aren't accelerated is functionally "fine", and in some cases a weird "win" +for performance, but only for cases that should never be triggered by a +well-behaved VM (writes to read-only registers; the #GP will typically +occur in the guest without taking a #VMEXIT, even for fault-like exits). + +But overall, disabling interception for MSRs that aren't accelerated is at +best confusing and unintuitive, and at worst introduces avoidable risk, as +the APM's documentation is imperfect and contradictory. The table in +"15.29.3.1 Virtual APIC Register Accesses" of simply states that such +writes generate exits, where as "Section 15.29.10 x2AVIC" says: + + x2APIC MSR intercept checks and access checks have higher priority than + AVIC access permission checks. + +CPU behavior follows the latter (which makes perfect sense), but all in +all there's simply no reason to disable interception just to make a #GP +faster. + +Note, the set of MSRs that are passed through for write is identical to +VMX's set when IPI virtualization is enabled. This is not a coincidence, +and is another motiviating factor for cleaning up the intercepts, as x2AVIC +is functionally equivalent to APICv+IPIv. + +Fixes: 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode") +Cc: stable@vger.kernel.org +Reviewed-by: Naveen N Rao (AMD) +Link: https://patch.msgid.link/20260514213115.1637082-4-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/avic.c | 40 ++++------------------------------------ + 1 file changed, 4 insertions(+), 36 deletions(-) + +--- a/arch/x86/kvm/svm/avic.c ++++ b/arch/x86/kvm/svm/avic.c +@@ -113,39 +113,6 @@ static void avic_set_x2apic_msr_intercep + { + struct kvm_vcpu *vcpu = &svm->vcpu; + u64 rd_regs; +- +- static const u32 x2avic_passthrough_msrs[] = { +- X2APIC_MSR(APIC_ID), +- X2APIC_MSR(APIC_LVR), +- X2APIC_MSR(APIC_TASKPRI), +- X2APIC_MSR(APIC_ARBPRI), +- X2APIC_MSR(APIC_PROCPRI), +- X2APIC_MSR(APIC_EOI), +- X2APIC_MSR(APIC_RRR), +- X2APIC_MSR(APIC_LDR), +- X2APIC_MSR(APIC_DFR), +- X2APIC_MSR(APIC_SPIV), +- X2APIC_MSR(APIC_ISR), +- X2APIC_MSR(APIC_TMR), +- X2APIC_MSR(APIC_IRR), +- X2APIC_MSR(APIC_ESR), +- X2APIC_MSR(APIC_ICR), +- X2APIC_MSR(APIC_ICR2), +- +- /* +- * Note! Always intercept LVTT, as TSC-deadline timer mode +- * isn't virtualized by hardware, and the CPU will generate a +- * #GP instead of a #VMEXIT. +- */ +- X2APIC_MSR(APIC_LVTTHMR), +- X2APIC_MSR(APIC_LVTPC), +- X2APIC_MSR(APIC_LVT0), +- X2APIC_MSR(APIC_LVT1), +- X2APIC_MSR(APIC_LVTERR), +- X2APIC_MSR(APIC_TMICT), +- X2APIC_MSR(APIC_TMCCT), +- X2APIC_MSR(APIC_TDCR), +- }; + int i; + + if (intercept == svm->x2avic_msrs_intercepted) +@@ -160,9 +127,10 @@ static void avic_set_x2apic_msr_intercep + svm_set_intercept_for_msr(vcpu, APIC_BASE_MSR + i, + MSR_TYPE_R, intercept); + +- for (i = 0; i < ARRAY_SIZE(x2avic_passthrough_msrs); i++) +- svm_set_intercept_for_msr(vcpu, x2avic_passthrough_msrs[i], +- MSR_TYPE_W, intercept); ++ svm_set_intercept_for_msr(vcpu, X2APIC_MSR(APIC_TASKPRI), MSR_TYPE_W, intercept); ++ svm_set_intercept_for_msr(vcpu, X2APIC_MSR(APIC_EOI), MSR_TYPE_W, intercept); ++ svm_set_intercept_for_msr(vcpu, X2APIC_MSR(APIC_SELF_IPI), MSR_TYPE_W, intercept); ++ svm_set_intercept_for_msr(vcpu, X2APIC_MSR(APIC_ICR), MSR_TYPE_W, intercept); + + svm->x2avic_msrs_intercepted = intercept; + } diff --git a/queue-6.18/kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch b/queue-6.18/kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch new file mode 100644 index 0000000000..f228118e33 --- /dev/null +++ b/queue-6.18/kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch @@ -0,0 +1,59 @@ +From ca674df13b195eb6d124ab059799d4e03fa40624 Mon Sep 17 00:00:00 2001 +From: Xuanqing Shi <1356292400@qq.com> +Date: Tue, 26 May 2026 19:26:17 -0700 +Subject: KVM: VMX: Handle bad values on proxied writes to LBR MSRs + +From: Xuanqing Shi <1356292400@qq.com> + +commit ca674df13b195eb6d124ab059799d4e03fa40624 upstream. + +Use the "safe" WRMSR API when writing LBRs on behalf of the guest (or host +userspace), and propagate any errors back to the instigator, as the value +being written is untrusted. E.g. if the guest (or host userspace) attempts +to set reserved bits in LBR_SELECT, then KVM needs to return an error, and +not WARN on the bad value. + +Continue using the "unsafe" version of RDMSR, as it should be impossible to +reach the helper with a completely bogus MSR, i.e. WARNing on RDMSR failure +is very desirable, e.g. to make KVM bugs more visible. + + unchecked MSR access error: WRMSR to 0x1c8 (tried to write 0x0000000000004000) + Call Trace: + intel_pmu_set_msr+0x4e0/0x7f0 [kvm_intel] + kvm_pmu_set_msr+0x17e/0x1c0 [kvm] + kvm_set_msr_common+0xc76/0x1440 [kvm] + vmx_set_msr+0x5e6/0x1570 [kvm_intel] + kvm_emulate_wrmsr+0x54/0x1d0 [kvm] + vmx_handle_exit+0x7fc/0x970 [kvm_intel] + +Fixes: 1b5ac3226a1a ("KVM: vmx/pmu: Pass-through LBR msrs when the guest LBR event is ACTIVE") +Cc: stable@vger.kernel.org +Signed-off-by: Xuanqing Shi <1356292400@qq.com> +[sean: rework changelog, only modify WRMSR path, tag for stable@] +Link: https://patch.msgid.link/20260527022617.3973884-1-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx/pmu_intel.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/vmx/pmu_intel.c ++++ b/arch/x86/kvm/vmx/pmu_intel.c +@@ -320,13 +320,15 @@ static bool intel_pmu_handle_lbr_msrs_ac + */ + local_irq_disable(); + if (lbr_desc->event->state == PERF_EVENT_STATE_ACTIVE) { ++ int err = 0; ++ + if (read) + rdmsrq(index, msr_info->data); + else +- wrmsrq(index, msr_info->data); ++ err = wrmsrq_safe(index, msr_info->data); + __set_bit(INTEL_PMC_IDX_FIXED_VLBR, vcpu_to_pmu(vcpu)->pmc_in_use); + local_irq_enable(); +- return true; ++ return !err; + } + clear_bit(INTEL_PMC_IDX_FIXED_VLBR, vcpu_to_pmu(vcpu)->pmc_in_use); + local_irq_enable(); diff --git a/queue-6.18/kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch b/queue-6.18/kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch new file mode 100644 index 0000000000..e0669f1a67 --- /dev/null +++ b/queue-6.18/kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch @@ -0,0 +1,98 @@ +From c5bad4fa2d5dfd8c25140051a9807eba387a19b8 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Fri, 15 May 2026 15:26:29 -0700 +Subject: KVM: VMX: Refresh GUEST_PENDING_DBG_EXCEPTIONS.BS on all injected #DBs + +From: Sean Christopherson + +commit c5bad4fa2d5dfd8c25140051a9807eba387a19b8 upstream. + +Move KVM's stuffing of GUEST_PENDING_DBG_EXCEPTIONS.BS when RFLAGS.TF=1 and +MOV/POP SS or STI blocking is active into the exception injection code so +that KVM fixes up the VMCS for all injected #DBs, not only those that are +reflected back into the guest after #DB interception. E.g. if KVM queues +a #DB in the emulator, or more importantly if userspace does save/restore +exactly on the #DB+shadow boundary, then KVM needs to massage the VMCS to +avoid the VM-Entry consistency check. + +Opportunistically update the wording of the comment to describe the +behavior as a workaround of flawed CPU behavior/architecture, to make it +clear that the *only* thing KVM is doing is fudging around a consistency +check. Per the SDM: + + There are no pending debug exceptions after VM entry if any of the + following are true: + + * The VM entry is vectoring with one of the following interruption + types: external interrupt, non-maskable interrupt (NMI), hardware + exception, or privileged software exception. + +I.e. forcing GUEST_PENDING_DBG_EXCEPTIONS.BS does *not* impact guest- +visible behavior. + +Fixes: b9bed78e2fa9 ("KVM: VMX: Set vmcs.PENDING_DBG.BS on #DB in STI/MOVSS blocking shadow") +Cc: stable@vger.kernel.org +Reported-by: Hou Wenlong +Closes: https://lore.kernel.org/all/b1a294bc9ed4dae532474a5dc6c8cb6e5962de7c.1757416809.git.houwenlong.hwl@antgroup.com +Reviewed-by: Hou Wenlong +Link: https://patch.msgid.link/20260515222638.1949982-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx/vmx.c | 35 ++++++++++++++++++----------------- + 1 file changed, 18 insertions(+), 17 deletions(-) + +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -1790,6 +1790,24 @@ void vmx_inject_exception(struct kvm_vcp + u32 intr_info = ex->vector | INTR_INFO_VALID_MASK; + struct vcpu_vmx *vmx = to_vmx(vcpu); + ++ /* ++ * When injecting a #DB, single-stepping is enabled in RFLAGS, and STI ++ * or MOV-SS blocking is active, set vmcs.PENDING_DBG_EXCEPTIONS.BS to ++ * prevent a false positive from VM-Entry consistency check. VM-Entry ++ * asserts that a single-step #DB _must_ be pending in this scenario, ++ * as the previous instruction cannot have toggled RFLAGS.TF 0=>1 ++ * (because STI and POP/MOV don't modify RFLAGS), therefore the one ++ * instruction delay when activating single-step breakpoints must have ++ * already expired. However, the CPU isn't smart enough to peek at ++ * vmcs.VM_ENTRY_INTR_INFO_FIELD and so doesn't realize that yes, there ++ * is indeed a #DB pending/imminent. ++ */ ++ if (ex->vector == DB_VECTOR && ++ (vmx_get_rflags(vcpu) & X86_EFLAGS_TF) && ++ vmx_get_interrupt_shadow(vcpu)) ++ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, ++ vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS) | DR6_BS); ++ + kvm_deliver_exception_payload(vcpu, ex); + + if (ex->has_error_code) { +@@ -5287,26 +5305,9 @@ static int handle_exception_nmi(struct k + * avoid single-step #DB and MTF updates, as ICEBP is + * higher priority. Note, skipping ICEBP still clears + * STI and MOVSS blocking. +- * +- * For all other #DBs, set vmcs.PENDING_DBG_EXCEPTIONS.BS +- * if single-step is enabled in RFLAGS and STI or MOVSS +- * blocking is active, as the CPU doesn't set the bit +- * on VM-Exit due to #DB interception. VM-Entry has a +- * consistency check that a single-step #DB is pending +- * in this scenario as the previous instruction cannot +- * have toggled RFLAGS.TF 0=>1 (because STI and POP/MOV +- * don't modify RFLAGS), therefore the one instruction +- * delay when activating single-step breakpoints must +- * have already expired. Note, the CPU sets/clears BS +- * as appropriate for all other VM-Exits types. + */ + if (is_icebp(intr_info)) + WARN_ON(!skip_emulated_instruction(vcpu)); +- else if ((vmx_get_rflags(vcpu) & X86_EFLAGS_TF) && +- (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & +- (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS))) +- vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, +- vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS) | DR6_BS); + + kvm_queue_exception_p(vcpu, DB_VECTOR, dr6); + return 1; diff --git a/queue-6.18/kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch b/queue-6.18/kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch new file mode 100644 index 0000000000..986311d2fb --- /dev/null +++ b/queue-6.18/kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch @@ -0,0 +1,97 @@ +From 8ba621f335a519b47cb7d3e3f4f15b5101b3a56f Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 14 May 2026 14:31:13 -0700 +Subject: KVM: x86: Add dedicated API for getting mask of accelerated x2APIC MSRs + +From: Sean Christopherson + +commit 8ba621f335a519b47cb7d3e3f4f15b5101b3a56f upstream. + +Add a dedicated local APIC API, kvm_x2apic_disable_intercept_reg_mask(), +to provide the mask of x2APIC registers whose MSRs can and should be passed +through to the guest when x2APIC virtualization is enable, and use it in +lieu of the open-coded equivalent VMX logic. Providing a common helper +will allow sharing the logic with SVM (x2AVIC), and as a bonus eliminates +the somewhat confusing code where KVM enables interception for MSR_TYPE_RW, +even though only the READ case actually needs to be updated. + +No functional change intended. + +Cc: stable@vger.kernel.org +Reviewed-by: Naveen N Rao (AMD) +Link: https://patch.msgid.link/20260514213115.1637082-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/lapic.c | 21 +++++++++++++++++++-- + arch/x86/kvm/lapic.h | 2 +- + arch/x86/kvm/vmx/vmx.c | 3 +-- + 3 files changed, 21 insertions(+), 5 deletions(-) + +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1745,7 +1745,7 @@ static inline struct kvm_lapic *to_lapic + #define APIC_REGS_MASK(first, count) \ + (APIC_REG_MASK(first) * ((1ull << (count)) - 1)) + +-u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic) ++static u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic) + { + /* Leave bits '0' for reserved and write-only registers. */ + u64 valid_reg_mask = +@@ -1781,7 +1781,24 @@ u64 kvm_lapic_readable_reg_mask(struct k + + return valid_reg_mask; + } +-EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lapic_readable_reg_mask); ++ ++u64 kvm_x2apic_disable_read_intercept_reg_mask(struct kvm_vcpu *vcpu) ++{ ++ if (WARN_ON_ONCE(!lapic_in_kernel(vcpu))) ++ return 0; ++ ++ /* ++ * TMMCT, a.k.a. the current APIC timer count, reads aren't accelerated ++ * by hardware (Intel or AMD) as the timer is emulated in software (by ++ * KVM), i.e. reads from the virtual APIC page would return garbage. ++ * Intercept RDMSR, as handling the fault-like APIC-access VM-Exit is ++ * more expensive than handling a RDMSR VM-Exit (the APIC-access exit ++ * requires slow emulation of the code stream). ++ */ ++ return kvm_lapic_readable_reg_mask(vcpu->arch.apic) & ++ ~APIC_REG_MASK(APIC_TMCCT); ++} ++EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_x2apic_disable_read_intercept_reg_mask); + + static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len, + void *data) +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -150,7 +150,7 @@ int kvm_hv_vapic_msr_read(struct kvm_vcp + int kvm_lapic_set_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len); + void kvm_lapic_exit(void); + +-u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic); ++u64 kvm_x2apic_disable_read_intercept_reg_mask(struct kvm_vcpu *vcpu); + + static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic) + { +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -4080,7 +4080,7 @@ static void vmx_update_msr_bitmap_x2apic + * mode, only the current timer count needs on-demand emulation by KVM. + */ + if (mode & MSR_BITMAP_MODE_X2APIC_APICV) +- msr_bitmap[read_idx] = ~kvm_lapic_readable_reg_mask(vcpu->arch.apic); ++ msr_bitmap[read_idx] = ~kvm_x2apic_disable_read_intercept_reg_mask(vcpu); + else + msr_bitmap[read_idx] = ~0ull; + msr_bitmap[write_idx] = ~0ull; +@@ -4093,7 +4093,6 @@ static void vmx_update_msr_bitmap_x2apic + !(mode & MSR_BITMAP_MODE_X2APIC)); + + if (mode & MSR_BITMAP_MODE_X2APIC_APICV) { +- vmx_enable_intercept_for_msr(vcpu, X2APIC_MSR(APIC_TMCCT), MSR_TYPE_RW); + vmx_disable_intercept_for_msr(vcpu, X2APIC_MSR(APIC_EOI), MSR_TYPE_W); + vmx_disable_intercept_for_msr(vcpu, X2APIC_MSR(APIC_SELF_IPI), MSR_TYPE_W); + if (enable_ipiv) diff --git a/queue-6.18/kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch b/queue-6.18/kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch new file mode 100644 index 0000000000..a22a2be007 --- /dev/null +++ b/queue-6.18/kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch @@ -0,0 +1,69 @@ +From 0ffedf43910e44b76c2c1db4e9fbf12b268190c1 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 23 Apr 2026 09:26:27 -0700 +Subject: KVM: x86: Ensure vendor's exit handler runs before fastpath userspace exits + +From: Sean Christopherson + +commit 0ffedf43910e44b76c2c1db4e9fbf12b268190c1 upstream. + +Move the handling of fastpath userspace exits into vendor code to ensure +KVM runs vendor specific operations that need to run before userspace gains +control of the vCPU. E.g. for VMX (and soon to be for SVM as well), KVM +needs to flush the PML buffer prior to exiting to userspace, otherwise any +memory written by the final KVM_RUN might never be flagged as dirty. + +Note, waiting to snapshot CR0 and CR3 until svm_handle_exit() is flawed in +general, as that risks consuming stale state in a fastpath handler. That +will be addressed in a future change. + +Fixes: f7f39c50edb9 ("KVM: x86: Exit to userspace if fastpath triggers one on instruction skip") +Cc: stable@vger.kernel.org +Cc: Nikunj A. Dadhania +Reviewed-by: Nikunj A. Dadhania +Reviewed-by: Kai Huang +Link: https://patch.msgid.link/20260423162628.490962-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/svm/svm.c | 3 +++ + arch/x86/kvm/vmx/vmx.c | 3 +++ + arch/x86/kvm/x86.c | 3 --- + 3 files changed, 6 insertions(+), 3 deletions(-) + +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -3569,6 +3569,9 @@ static int svm_handle_exit(struct kvm_vc + vcpu->arch.cr3 = svm->vmcb->save.cr3; + } + ++ if (unlikely(exit_fastpath == EXIT_FASTPATH_EXIT_USERSPACE)) ++ return 0; ++ + if (is_guest_mode(vcpu)) { + int vmexit; + +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -6499,6 +6499,9 @@ static int __vmx_handle_exit(struct kvm_ + if (enable_pml && !is_guest_mode(vcpu)) + vmx_flush_pml_buffer(vcpu); + ++ if (unlikely(exit_fastpath == EXIT_FASTPATH_EXIT_USERSPACE)) ++ return 0; ++ + /* + * KVM should never reach this point with a pending nested VM-Enter. + * More specifically, short-circuiting VM-Entry to emulate L2 due to +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -11498,9 +11498,6 @@ static int vcpu_enter_guest(struct kvm_v + if (vcpu->arch.apic_attention) + kvm_lapic_sync_from_vapic(vcpu); + +- if (unlikely(exit_fastpath == EXIT_FASTPATH_EXIT_USERSPACE)) +- return 0; +- + r = kvm_x86_call(handle_exit)(vcpu, exit_fastpath); + return r; + diff --git a/queue-6.18/landlock-set-audit_net.sk-for-socket-access-checks.patch b/queue-6.18/landlock-set-audit_net.sk-for-socket-access-checks.patch new file mode 100644 index 0000000000..5fcd302116 --- /dev/null +++ b/queue-6.18/landlock-set-audit_net.sk-for-socket-access-checks.patch @@ -0,0 +1,125 @@ +From d936e1a9170f9cadaa5f37586b1dfe6f20f98799 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= +Date: Fri, 12 Jun 2026 19:27:55 +0200 +Subject: landlock: Set audit_net.sk for socket access checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mickaël Salaün + +commit d936e1a9170f9cadaa5f37586b1dfe6f20f98799 upstream. + +Set audit_net.sk in current_check_access_socket() to provide the socket +object to audit_log_lsm_data(). This makes Landlock consistent with +AppArmor, which always sets .sk for socket operations, and with +SELinux's generic socket permission checks. + +The socket's local and foreign address information (laddr, lport, faddr, +fport) is logged by the shared lsm_audit.c infrastructure when the +socket has bound or connected state. Fields with zero values are +suppressed by print_ipv4_addr()/print_ipv6_addr(), so the audit output +is unchanged for the common case of bind denials on unbound sockets. +For connect denials after a prior bind, the bound local address (laddr, +lport) appears before the existing sockaddr fields (daddr, dest). + +No existing fields are removed or reordered, and the new field names +(laddr, lport, faddr, fport) are standard audit fields already emitted +by other LSMs through the same lsm_audit.c code path. + +Add a connect_tcp_bound audit test that binds to an allowed port and +then connects to a denied one, verifying that the denial record reports +laddr/lport from the bound socket in addition to the connect +destination. + +Cc: Günther Noack +Cc: Tingmao Wang +Cc: stable@vger.kernel.org +Fixes: 9f74411a40ce ("landlock: Log TCP bind and connect denials") +Link: https://patch.msgid.link/20260612172757.1003481-1-mic@digikod.net +Signed-off-by: Mickaël Salaün +Signed-off-by: Greg Kroah-Hartman +--- + security/landlock/net.c | 1 + tools/testing/selftests/landlock/net_test.c | 62 ++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + +--- a/security/landlock/net.c ++++ b/security/landlock/net.c +@@ -199,6 +199,7 @@ static int current_check_access_socket(s + return 0; + + audit_net.family = address->sa_family; ++ audit_net.sk = sock->sk; + landlock_log_denial(subject, + &(struct landlock_request){ + .type = LANDLOCK_REQUEST_NET_ACCESS, +--- a/tools/testing/selftests/landlock/net_test.c ++++ b/tools/testing/selftests/landlock/net_test.c +@@ -2014,4 +2014,66 @@ TEST_F(audit, connect) + EXPECT_EQ(0, close(sock_fd)); + } + ++static int matches_log_tcp_bound(int audit_fd, const char *const addr, ++ __u16 lport, __u16 dport) ++{ ++ static const char log_template[] = REGEX_LANDLOCK_PREFIX ++ " blockers=net\\.connect_tcp laddr=%s lport=%u daddr=%s dest=%u$"; ++ /* Slack for two addresses and two port numbers. */ ++ char log_match[sizeof(log_template) + 40]; ++ int log_match_len; ++ ++ log_match_len = snprintf(log_match, sizeof(log_match), log_template, ++ addr, lport, addr, dport); ++ if (log_match_len > sizeof(log_match)) ++ return -E2BIG; ++ ++ return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match, ++ NULL); ++} ++ ++/* ++ * After a bind() to an allowed port, a denied connect must report laddr/lport ++ * from the bound socket (made available through audit_net.sk) in addition to ++ * the connect sockaddr's daddr/dest. ++ */ ++TEST_F(audit, connect_tcp_bound) ++{ ++ const struct landlock_ruleset_attr ruleset_attr = { ++ .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | ++ LANDLOCK_ACCESS_NET_CONNECT_TCP, ++ }; ++ const struct landlock_net_port_attr rule_bind = { ++ .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, ++ .port = self->srv0.port, ++ }; ++ struct service_fixture srv_remote; ++ struct audit_records records; ++ int ruleset_fd, sock_fd; ++ ++ /* Uses a second port as the denied connect target. */ ++ ASSERT_EQ(0, set_service(&srv_remote, variant->prot, 1)); ++ ++ ruleset_fd = ++ landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); ++ ASSERT_LE(0, ruleset_fd); ++ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, ++ &rule_bind, 0)); ++ enforce_ruleset(_metadata, ruleset_fd); ++ EXPECT_EQ(0, close(ruleset_fd)); ++ ++ sock_fd = socket_variant(&self->srv0); ++ ASSERT_LE(0, sock_fd); ++ EXPECT_EQ(0, bind_variant(sock_fd, &self->srv0)); ++ EXPECT_EQ(-EACCES, connect_variant(sock_fd, &srv_remote)); ++ EXPECT_EQ(0, matches_log_tcp_bound(self->audit_fd, variant->addr, ++ self->srv0.port, srv_remote.port)); ++ ++ EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); ++ EXPECT_EQ(0, records.access); ++ EXPECT_EQ(1, records.domain); ++ ++ EXPECT_EQ(0, close(sock_fd)); ++} ++ + TEST_HARNESS_MAIN diff --git a/queue-6.18/loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch b/queue-6.18/loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch new file mode 100644 index 0000000000..11ba1b6ba0 --- /dev/null +++ b/queue-6.18/loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch @@ -0,0 +1,77 @@ +From aeded601d6aceb57cdda4b2701d2ee00c43a8b69 Mon Sep 17 00:00:00 2001 +From: Zeng Chi +Date: Thu, 11 Jun 2026 20:46:44 +0800 +Subject: LoongArch: KVM: Add missing slots_lock for device register/unregister + +From: Zeng Chi + +commit aeded601d6aceb57cdda4b2701d2ee00c43a8b69 upstream. + +kvm_io_bus_register_dev() and kvm_io_bus_unregister_dev() should be +called under kvm->slots_lock. The unregister calls in ipi.c, eiointc.c +and pch_pic.c were also missing this protection. Add it to match the +register side. + +Cc: stable@vger.kernel.org +Reviewed-by: Bibo Mao +Signed-off-by: Zeng Chi +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kvm/intc/eiointc.c | 6 ++++++ + arch/loongarch/kvm/intc/ipi.c | 2 ++ + arch/loongarch/kvm/intc/pch_pic.c | 2 ++ + 3 files changed, 10 insertions(+) + +--- a/arch/loongarch/kvm/intc/eiointc.c ++++ b/arch/loongarch/kvm/intc/eiointc.c +@@ -654,10 +654,14 @@ static int kvm_eiointc_create(struct kvm + + device = &s->device_vext; + kvm_iodevice_init(device, &kvm_eiointc_virt_ops); ++ mutex_lock(&kvm->slots_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_IOCSR_BUS, + EIOINTC_VIRT_BASE, EIOINTC_VIRT_SIZE, device); ++ mutex_unlock(&kvm->slots_lock); + if (ret < 0) { ++ mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &s->device); ++ mutex_unlock(&kvm->slots_lock); + kfree(s); + return ret; + } +@@ -676,8 +680,10 @@ static void kvm_eiointc_destroy(struct k + + kvm = dev->kvm; + eiointc = kvm->arch.eiointc; ++ mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device); + kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &eiointc->device_vext); ++ mutex_unlock(&kvm->slots_lock); + kfree(eiointc); + kfree(dev); + } +--- a/arch/loongarch/kvm/intc/ipi.c ++++ b/arch/loongarch/kvm/intc/ipi.c +@@ -457,7 +457,9 @@ static void kvm_ipi_destroy(struct kvm_d + + kvm = dev->kvm; + ipi = kvm->arch.ipi; ++ mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_IOCSR_BUS, &ipi->device); ++ mutex_unlock(&kvm->slots_lock); + kfree(ipi); + kfree(dev); + } +--- a/arch/loongarch/kvm/intc/pch_pic.c ++++ b/arch/loongarch/kvm/intc/pch_pic.c +@@ -473,7 +473,9 @@ static void kvm_pch_pic_destroy(struct k + kvm = dev->kvm; + s = kvm->arch.pch_pic; + /* unregister pch pic device and free it's memory */ ++ mutex_lock(&kvm->slots_lock); + kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &s->device); ++ mutex_unlock(&kvm->slots_lock); + kfree(s); + kfree(dev); + } diff --git a/queue-6.18/selftests-landlock-filter-dealloc-records-in-audit_count_records.patch b/queue-6.18/selftests-landlock-filter-dealloc-records-in-audit_count_records.patch new file mode 100644 index 0000000000..216693a3fc --- /dev/null +++ b/queue-6.18/selftests-landlock-filter-dealloc-records-in-audit_count_records.patch @@ -0,0 +1,161 @@ +From 26679fad81a471428707d2dd7b0418204c52b7e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= +Date: Wed, 13 May 2026 12:51:08 +0200 +Subject: selftests/landlock: Filter dealloc records in audit_count_records() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mickaël Salaün + +commit 26679fad81a471428707d2dd7b0418204c52b7e4 upstream. + +audit_count_records() counts both AUDIT_LANDLOCK_DOMAIN allocation and +deallocation records in records.domain . Domain deallocation is tied to +asynchronous credential freeing via kworker threads +(landlock_put_ruleset_deferred), so the dealloc record can arrive after +the drain in audit_init() and after the preceding audit_match_record() +call. This causes flaky failures in tests that assert an exact +records.domain count: a stale dealloc record from a previous test's +domain inflates the count by one. + +Observed on x86_64 under build configurations that delay the kworker +firing the dealloc callback (e.g. coverage instrumentation): the +audit_layout1 tests in fs_test.c intermittently saw records.domain == 2 +where 1 was expected. The fix is in the shared helper, so those +existing checks become robust without needing a fs_test.c edit. + +Filter audit_count_records() with a regex to skip records containing +deallocation status. The remaining domain records (allocation, emitted +synchronously during landlock_log_denial()) are deterministic. +Deallocation records are already tested explicitly via +matches_log_domain_deallocated() in audit_test.c, which uses its own +domain-ID-based filtering and longer timeout. + +With this filter in place, re-add the records.domain == 0 checks that +were removed in commit 3647a4977fb7 ("selftests/landlock: Drain stale +audit records on init") as a workaround for this race. + +Cc: Günther Noack +Cc: stable@vger.kernel.org +Depends-on: 07c2572a8757 ("selftests/landlock: Skip stale records in audit_match_record()") +Fixes: 6a500b22971c ("selftests/landlock: Add tests for audit flags and domain IDs") +Tested-by: Günther Noack +Link: https://patch.msgid.link/20260513105112.140137-1-mic@digikod.net +Signed-off-by: Mickaël Salaün +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/landlock/audit.h | 39 +++++++---- + tools/testing/selftests/landlock/audit_test.c | 2 + tools/testing/selftests/landlock/ptrace_test.c | 1 + tools/testing/selftests/landlock/scoped_abstract_unix_test.c | 1 + 4 files changed, 30 insertions(+), 13 deletions(-) + +--- a/tools/testing/selftests/landlock/audit.h ++++ b/tools/testing/selftests/landlock/audit.h +@@ -381,18 +381,24 @@ struct audit_records { + }; + + /* +- * WARNING: Do not assert records.domain == 0 without a preceding +- * audit_match_record() call. Domain deallocation records are emitted +- * asynchronously from kworker threads and can arrive after the drain in +- * audit_init(), corrupting the domain count. A preceding audit_match_record() +- * call consumes stale records while scanning, making the assertion safe in +- * practice because stale deallocation records arrive before the expected access +- * records. ++ * Counts remaining audit records by type, skipping domain deallocation records. ++ * Deallocation records are emitted asynchronously from kworker threads after a ++ * previous test's child has exited, so they can arrive after the drain in ++ * audit_init() and after the preceding audit_match_record() call. Allocation ++ * records are emitted synchronously during landlock_log_denial() in the current ++ * test's syscall context, so only those are counted in records->domain. + */ + static int audit_count_records(int audit_fd, struct audit_records *records) + { ++ static const char dealloc_pattern[] = REGEX_LANDLOCK_PREFIX ++ " status=deallocated "; + struct audit_message msg; +- int err; ++ regex_t dealloc_re; ++ int ret, err = 0; ++ ++ ret = regcomp(&dealloc_re, dealloc_pattern, 0); ++ if (ret) ++ return -ENOMEM; + + records->access = 0; + records->domain = 0; +@@ -402,9 +408,8 @@ static int audit_count_records(int audit + err = audit_recv(audit_fd, &msg); + if (err) { + if (err == -EAGAIN) +- return 0; +- else +- return err; ++ err = 0; ++ break; + } + + switch (msg.header.nlmsg_type) { +@@ -412,12 +417,20 @@ static int audit_count_records(int audit + records->access++; + break; + case AUDIT_LANDLOCK_DOMAIN: +- records->domain++; ++ ret = regexec(&dealloc_re, msg.data, 0, NULL, 0); ++ if (ret == REG_NOMATCH) { ++ records->domain++; ++ } else if (ret != 0) { ++ err = -EIO; ++ goto out; ++ } + break; + } + } while (true); + +- return 0; ++out: ++ regfree(&dealloc_re); ++ return err; + } + + static int audit_init(void) +--- a/tools/testing/selftests/landlock/audit_test.c ++++ b/tools/testing/selftests/landlock/audit_test.c +@@ -497,6 +497,7 @@ TEST_F(audit_flags, signal) + } else { + EXPECT_EQ(1, records.access); + } ++ EXPECT_EQ(0, records.domain); + + /* Updates filter rules to match the drop record. */ + set_cap(_metadata, CAP_AUDIT_CONTROL); +@@ -684,6 +685,7 @@ TEST_F(audit_exec, signal_and_open) + /* Tests that there was no denial until now. */ + EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); + EXPECT_EQ(0, records.access); ++ EXPECT_EQ(0, records.domain); + + /* + * Wait for the child to do a first denied action by layer1 and +--- a/tools/testing/selftests/landlock/ptrace_test.c ++++ b/tools/testing/selftests/landlock/ptrace_test.c +@@ -486,6 +486,7 @@ TEST_F(audit, trace) + /* Makes sure there is no superfluous logged records. */ + EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); + EXPECT_EQ(0, records.access); ++ EXPECT_EQ(0, records.domain); + + yama_ptrace_scope = get_yama_ptrace_scope(); + ASSERT_LE(0, yama_ptrace_scope); +--- a/tools/testing/selftests/landlock/scoped_abstract_unix_test.c ++++ b/tools/testing/selftests/landlock/scoped_abstract_unix_test.c +@@ -312,6 +312,7 @@ TEST_F(scoped_audit, connect_to_child) + /* Makes sure there is no superfluous logged records. */ + EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); + EXPECT_EQ(0, records.access); ++ EXPECT_EQ(0, records.domain); + + ASSERT_EQ(0, pipe2(pipe_child, O_CLOEXEC)); + ASSERT_EQ(0, pipe2(pipe_parent, O_CLOEXEC)); diff --git a/queue-6.18/series b/queue-6.18/series index 8a2f6d8db4..ca459a3100 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -403,3 +403,30 @@ mm-page_ext-add-count-limit-to-page_ext_iter_next-to-prevent-invalid-pfn-access. mm-do-file-ownership-checks-with-the-proper-mount-idmap.patch selftests-mm-pagemap_ioctl-use-the-correct-page-size-for-transact_test.patch crypto-loongson-remove-broken-and-unused-loongson-rng.patch +iommu-vt-d-avoid-warning-in-sva-unbind-path.patch +iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch +iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch +iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch +iommufd-set-veventq_depth-upper-bound.patch +iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch +iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch +iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch +iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch +iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch +iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch +audit-fix-removal-of-dangling-executable-rules.patch +landlock-set-audit_net.sk-for-socket-access-checks.patch +selftests-landlock-filter-dealloc-records-in-audit_count_records.patch +kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch +loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch +kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch +kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch +kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch +kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch +kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch +kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch +kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch +kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch +udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch +dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch +fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch diff --git a/queue-6.18/udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch b/queue-6.18/udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch new file mode 100644 index 0000000000..efd99d01b4 --- /dev/null +++ b/queue-6.18/udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch @@ -0,0 +1,70 @@ +From fb7b1a0ab25a6077d26cb3829e31743972d4f31d Mon Sep 17 00:00:00 2001 +From: Mikhail Gavrilov +Date: Sun, 15 Mar 2026 04:27:22 +0500 +Subject: udmabuf: fix DMA direction mismatch in release_udmabuf() + +From: Mikhail Gavrilov + +commit fb7b1a0ab25a6077d26cb3829e31743972d4f31d upstream. + +begin_cpu_udmabuf() maps the sg_table with the caller-provided direction +(e.g., DMA_TO_DEVICE for a write-only sync), and caches it in ubuf->sg +for reuse. However, release_udmabuf() always unmaps this sg_table with +a hardcoded DMA_BIDIRECTIONAL, regardless of the direction that was +originally used for the mapping. + +With CONFIG_DMA_API_DEBUG=y this produces: + + DMA-API: misc udmabuf: device driver frees DMA memory with different + direction [device address=0x000000044a123000] [size=4096 bytes] + [mapped with DMA_TO_DEVICE] [unmapped with DMA_BIDIRECTIONAL] + +The issue was found during video playback when GStreamer performed a +write-only DMA_BUF_IOCTL_SYNC on a udmabuf. It can be reproduced +with CONFIG_DMA_API_DEBUG=y by creating a udmabuf from a memfd, +performing a write-only sync (DMA_BUF_SYNC_WRITE without +DMA_BUF_SYNC_READ), and closing the file descriptor. + +Fix this by storing the DMA direction used when the sg_table is first +created in begin_cpu_udmabuf(), and passing that same direction to +put_sg_table() in release_udmabuf(). + +Fixes: 284562e1f348 ("udmabuf: implement begin_cpu_access/end_cpu_access hooks") +Cc: stable@vger.kernel.org +Signed-off-by: Mikhail Gavrilov +Reviewed-by: Vivek Kasireddy +Signed-off-by: Vivek Kasireddy +Link: https://patch.msgid.link/20260314232722.15555-1-mikhail.v.gavrilov@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/dma-buf/udmabuf.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -40,6 +40,7 @@ struct udmabuf { + struct folio **pinned_folios; + + struct sg_table *sg; ++ enum dma_data_direction sg_dir; + struct miscdevice *device; + pgoff_t *offsets; + }; +@@ -237,7 +238,7 @@ static void release_udmabuf(struct dma_b + struct device *dev = ubuf->device->this_device; + + if (ubuf->sg) +- put_sg_table(dev, ubuf->sg, DMA_BIDIRECTIONAL); ++ put_sg_table(dev, ubuf->sg, ubuf->sg_dir); + + deinit_udmabuf(ubuf); + kfree(ubuf); +@@ -255,6 +256,8 @@ static int begin_cpu_udmabuf(struct dma_ + if (IS_ERR(ubuf->sg)) { + ret = PTR_ERR(ubuf->sg); + ubuf->sg = NULL; ++ } else { ++ ubuf->sg_dir = direction; + } + } else { + dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);