]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 Jul 2026 11:45:21 +0000 (13:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 Jul 2026 11:45:21 +0000 (13:45 +0200)
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

28 files changed:
queue-6.18/audit-fix-removal-of-dangling-executable-rules.patch [new file with mode: 0644]
queue-6.18/dma-buf-udmabuf-skip-redundant-cpu-sync-to-fix-cacheline-eexist-warning.patch [new file with mode: 0644]
queue-6.18/fpga-dfl-afu-validate-dma-mapping-length-in-afu_dma_map_region.patch [new file with mode: 0644]
queue-6.18/iommu-amd-don-t-split-flush-for-amd_iommu_domain_flush_all.patch [new file with mode: 0644]
queue-6.18/iommu-vt-d-avoid-warning-in-sva-unbind-path.patch [new file with mode: 0644]
queue-6.18/iommufd-avoid-partial-fault-group-delivery-in-iommufd_fault_fops_read.patch [new file with mode: 0644]
queue-6.18/iommufd-break-the-loop-on-failure-in-iommufd_fault_fops_read.patch [new file with mode: 0644]
queue-6.18/iommufd-fix-data_len-byte-count-vs-element-count-mismatch.patch [new file with mode: 0644]
queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_fault_fops_read.patch [new file with mode: 0644]
queue-6.18/iommufd-reject-invalid-read-count-in-iommufd_veventq_fops_read.patch [new file with mode: 0644]
queue-6.18/iommufd-rewind-header-length-in-done-if-iommufd_veventq_fops_read-fails.patch [new file with mode: 0644]
queue-6.18/iommufd-set-upper-bounds-on-cache-invalidation-entry_num-and-entry_len.patch [new file with mode: 0644]
queue-6.18/iommufd-set-veventq_depth-upper-bound.patch [new file with mode: 0644]
queue-6.18/iommufd-use-sizeof-hdr-instead-of-sizeof-hdr-in-veventq-read.patch [new file with mode: 0644]
queue-6.18/kvm-arm64-clear-__hyp_running_vcpu-when-flushing-the-pkvm-hyp-vcpu.patch [new file with mode: 0644]
queue-6.18/kvm-arm64-don-t-leak-pfn-when-kvm_translate_vncr-races-mmu-notifier.patch [new file with mode: 0644]
queue-6.18/kvm-arm64-nv-avoid-dereferencing-null-vncr-pseudo-tlb.patch [new file with mode: 0644]
queue-6.18/kvm-svm-disable-x2avic-rdmsr-interception-for-msrs-kvm-actually-supports.patch [new file with mode: 0644]
queue-6.18/kvm-svm-only-disable-x2avic-wrmsr-interception-for-msrs-that-are-accelerated.patch [new file with mode: 0644]
queue-6.18/kvm-vmx-handle-bad-values-on-proxied-writes-to-lbr-msrs.patch [new file with mode: 0644]
queue-6.18/kvm-vmx-refresh-guest_pending_dbg_exceptions.bs-on-all-injected-dbs.patch [new file with mode: 0644]
queue-6.18/kvm-x86-add-dedicated-api-for-getting-mask-of-accelerated-x2apic-msrs.patch [new file with mode: 0644]
queue-6.18/kvm-x86-ensure-vendor-s-exit-handler-runs-before-fastpath-userspace-exits.patch [new file with mode: 0644]
queue-6.18/landlock-set-audit_net.sk-for-socket-access-checks.patch [new file with mode: 0644]
queue-6.18/loongarch-kvm-add-missing-slots_lock-for-device-register-unregister.patch [new file with mode: 0644]
queue-6.18/selftests-landlock-filter-dealloc-records-in-audit_count_records.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/udmabuf-fix-dma-direction-mismatch-in-release_udmabuf.patch [new file with mode: 0644]

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 (file)
index 0000000..51943e5
--- /dev/null
@@ -0,0 +1,61 @@
+From 888a0396e154524f4027f27da84bdbec9eb68916 Mon Sep 17 00:00:00 2001
+From: Ricardo Robaina <rrobaina@redhat.com>
+Date: Wed, 13 May 2026 18:47:59 -0300
+Subject: audit: fix removal of dangling executable rules
+
+From: Ricardo Robaina <rrobaina@redhat.com>
+
+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 <longman@redhat.com>
+Acked-by: Richard Guy Briggs <rgb@redhat.com>
+Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6df4c9b
--- /dev/null
@@ -0,0 +1,81 @@
+From 504e2b4ab97a51d56d966cd36d0997ad30b65b2d Mon Sep 17 00:00:00 2001
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+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 <mikhail.v.gavrilov@gmail.com>
+
+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 <mikhail.v.gavrilov@gmail.com>
+Acked-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
+Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
+Link: https://patch.msgid.link/20260331061657.79983-1-mikhail.v.gavrilov@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9b7d4bc
--- /dev/null
@@ -0,0 +1,42 @@
+From fc3b071a7c8dc0f5d56defddf6e6fd5aaa3e1e27 Mon Sep 17 00:00:00 2001
+From: Sebastian Alba Vives <sebasjosue84@gmail.com>
+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 <sebasjosue84@gmail.com>
+
+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 <sebasjosue84@gmail.com>
+Reviewed-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20260518190742.61426-3-sebasjosue84@gmail.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..341a2ff
--- /dev/null
@@ -0,0 +1,61 @@
+From 69fe699afe1afcb730164b86c228483c2da05f94 Mon Sep 17 00:00:00 2001
+From: Weinan Liu <wnliu@google.com>
+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 <wnliu@google.com>
+
+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 <josef@toxicpanda.com>
+Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Weinan Liu <wnliu@google.com>
+Reviewed-by: Wei Wang <wei.w.wang@hotmail.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
+Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..ea249d2
--- /dev/null
@@ -0,0 +1,103 @@
+From 534b5f98ab7319d8004bbc7dab6481462243e883 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Thu, 4 Jun 2026 14:03:06 +0800
+Subject: iommu/vt-d: Avoid WARNING in sva unbind path
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+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:
+  <TASK>
+  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 <naresh.kumar.g@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20260519052917.3729796-1-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7c5ce10
--- /dev/null
@@ -0,0 +1,70 @@
+From 091ab6d70dc444f56ed14faedbcacfc979f4c613 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Mon, 1 Jun 2026 13:42:37 -0700
+Subject: iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Pranjal Shrivastava <praan@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0b4a0d7
--- /dev/null
@@ -0,0 +1,39 @@
+From 172fc8b19825a0f5884c38f2289188284e2d45ee Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Mon, 1 Jun 2026 13:42:36 -0700
+Subject: iommufd: Break the loop on failure in iommufd_fault_fops_read()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Pranjal Shrivastava <praan@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6eb07bd
--- /dev/null
@@ -0,0 +1,40 @@
+From 85345becfead3255a5f875d4b4d82ea01d926239 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Thu, 21 May 2026 17:36:32 -0700
+Subject: iommufd: Fix data_len byte-count vs element-count mismatch
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <jgg@nvidia.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..df7b7b7
--- /dev/null
@@ -0,0 +1,40 @@
+From 47916a54eeb2a9e654512ee609f71bd5b29db702 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Mon, 1 Jun 2026 13:42:35 -0700
+Subject: iommufd: Reject invalid read count in iommufd_fault_fops_read()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Pranjal Shrivastava <praan@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6b1df4b
--- /dev/null
@@ -0,0 +1,56 @@
+From 00203ca8323f9714630408c19a209b52397975e6 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Mon, 1 Jun 2026 13:42:33 -0700
+Subject: iommufd: Reject invalid read count in iommufd_veventq_fops_read()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Pranjal Shrivastava <praan@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5fd2359
--- /dev/null
@@ -0,0 +1,36 @@
+From 01e41ad76c12ae5c49ab4ef4fc7dd54e9b8784d6 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+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 <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Pranjal Shrivastava <praan@google.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d67dc55
--- /dev/null
@@ -0,0 +1,62 @@
+From 4d70986002f2f3eaaed89124fb2522bded38b016 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+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 <nicolinc@nvidia.com>
+
+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 <nicolinc@nvidia.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0ed09f4
--- /dev/null
@@ -0,0 +1,51 @@
+From 6ebf2eb46fbd5b40393ff8fbb847ba96925beaff Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Thu, 21 May 2026 17:36:34 -0700
+Subject: iommufd: Set veventq_depth upper bound
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+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 <jgg@nvidia.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..3fbbe66
--- /dev/null
@@ -0,0 +1,68 @@
+From be93d186ae88a92e7aa77e122d4e661fa57b1e39 Mon Sep 17 00:00:00 2001
+From: Kai Aizen <kai.aizen.dev@gmail.com>
+Date: Thu, 30 Apr 2026 20:56:30 +0300
+Subject: iommufd: Use sizeof(*hdr) instead of sizeof(hdr) in veventq read
+
+From: Kai Aizen <kai.aizen.dev@gmail.com>
+
+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 <kai.aizen.dev@gmail.com>
+Signed-off-by: Kai Aizen <kai.aizen.dev@gmail.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..c21a3c0
--- /dev/null
@@ -0,0 +1,43 @@
+From e8042f6e1d7befb2fb6b10a75918642bcd0acf9a Mon Sep 17 00:00:00 2001
+From: Hyunwoo Kim <imv4bel@gmail.com>
+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 <imv4bel@gmail.com>
+
+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 <imv4bel@gmail.com>
+Reviewed-by: Fuad Tabba <tabba@google.com>
+Tested-by: Fuad Tabba <tabba@google.com>
+Link: https://patch.msgid.link/20260606175614.83273-2-imv4bel@gmail.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..453ed36
--- /dev/null
@@ -0,0 +1,38 @@
+From 9f76b039a72d7e06374aa96862f0232ed53f7787 Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oupton@kernel.org>
+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 <oupton@kernel.org>
+
+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 <oupton@kernel.org>
+Link: https://patch.msgid.link/20260602235450.103057-2-oupton@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d4a6216
--- /dev/null
@@ -0,0 +1,104 @@
+From 4be6cbeb93d26994bd1827ddbce391e3c4395c8f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sun, 7 Jun 2026 18:57:45 +0100
+Subject: KVM: arm64: nv: Avoid dereferencing NULL VNCR pseudo-TLB
+
+From: Marc Zyngier <maz@kernel.org>
+
+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 <imv4bel@gmail.com>
+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 <oupton@kernel.org>
+Link: https://patch.msgid.link/20260607175745.297793-1-maz@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..0c5b403
--- /dev/null
@@ -0,0 +1,79 @@
+From 7f4b7092d9a173a4271e28c0ed1fc235994e309b Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Thu, 14 May 2026 14:31:14 -0700
+Subject: KVM: SVM: Disable x2AVIC RDMSR interception for MSRs KVM actually supports
+
+From: Sean Christopherson <seanjc@google.com>
+
+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) <naveen@kernel.org>
+Link: https://patch.msgid.link/20260514213115.1637082-3-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5a9d105
--- /dev/null
@@ -0,0 +1,100 @@
+From 8c63179d975f2029c948ecce622f72af616dbff7 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+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 <seanjc@google.com>
+
+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) <naveen@kernel.org>
+Link: https://patch.msgid.link/20260514213115.1637082-4-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..f228118
--- /dev/null
@@ -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 <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e0669f1
--- /dev/null
@@ -0,0 +1,98 @@
+From c5bad4fa2d5dfd8c25140051a9807eba387a19b8 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+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 <seanjc@google.com>
+
+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 <houwenlong.hwl@antgroup.com>
+Closes: https://lore.kernel.org/all/b1a294bc9ed4dae532474a5dc6c8cb6e5962de7c.1757416809.git.houwenlong.hwl@antgroup.com
+Reviewed-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
+Link: https://patch.msgid.link/20260515222638.1949982-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..986311d
--- /dev/null
@@ -0,0 +1,97 @@
+From 8ba621f335a519b47cb7d3e3f4f15b5101b3a56f Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+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 <seanjc@google.com>
+
+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) <naveen@kernel.org>
+Link: https://patch.msgid.link/20260514213115.1637082-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..a22a2be
--- /dev/null
@@ -0,0 +1,69 @@
+From 0ffedf43910e44b76c2c1db4e9fbf12b268190c1 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+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 <seanjc@google.com>
+
+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 <nikunj@amd.com>
+Reviewed-by: Nikunj A. Dadhania <nikunj@amd.com>
+Reviewed-by: Kai Huang <kai.huang@intel.com>
+Link: https://patch.msgid.link/20260423162628.490962-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5fcd302
--- /dev/null
@@ -0,0 +1,125 @@
+From d936e1a9170f9cadaa5f37586b1dfe6f20f98799 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+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 <mic@digikod.net>
+
+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 <gnoack@google.com>
+Cc: Tingmao Wang <m@maowtm.org>
+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 <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..11ba1b6
--- /dev/null
@@ -0,0 +1,77 @@
+From aeded601d6aceb57cdda4b2701d2ee00c43a8b69 Mon Sep 17 00:00:00 2001
+From: Zeng Chi <zengchi@kylinos.cn>
+Date: Thu, 11 Jun 2026 20:46:44 +0800
+Subject: LoongArch: KVM: Add missing slots_lock for device register/unregister
+
+From: Zeng Chi <zengchi@kylinos.cn>
+
+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 <maobibo@loongson.cn>
+Signed-off-by: Zeng Chi <zengchi@kylinos.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..216693a
--- /dev/null
@@ -0,0 +1,161 @@
+From 26679fad81a471428707d2dd7b0418204c52b7e4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+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 <mic@digikod.net>
+
+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 <gnoack@google.com>
+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 <gnoack3000@gmail.com>
+Link: https://patch.msgid.link/20260513105112.140137-1-mic@digikod.net
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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));
index 8a2f6d8db4dc1d507dbef6685700c4857b68dfc1..ca459a3100ca0ef024ffda5e9d91ac3cbcb2564e 100644 (file)
@@ -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 (file)
index 0000000..efd99d0
--- /dev/null
@@ -0,0 +1,70 @@
+From fb7b1a0ab25a6077d26cb3829e31743972d4f31d Mon Sep 17 00:00:00 2001
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+Date: Sun, 15 Mar 2026 04:27:22 +0500
+Subject: udmabuf: fix DMA direction mismatch in release_udmabuf()
+
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+
+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 <mikhail.v.gavrilov@gmail.com>
+Reviewed-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
+Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
+Link: https://patch.msgid.link/20260314232722.15555-1-mikhail.v.gavrilov@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);