--- /dev/null
+From stable+bounces-278562-greg=kroah.com@vger.kernel.org Tue Jul 21 13:50:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 07:47:00 -0400
+Subject: bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized
+To: stable@vger.kernel.org
+Cc: Matt Bobrowski <mattbobrowski@google.com>, oxsignal <awo@kakao.com>, Daniel Borkmann <daniel@iogearbox.net>, Emil Tsalapatis <emil@etsalapatis.com>, Amery Hung <ameryhung@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721114700.3688104-1-sashal@kernel.org>
+
+From: Matt Bobrowski <mattbobrowski@google.com>
+
+[ Upstream commit a6f0643e4f63cfaa0d5d4a69de4f132eac4b8fe4 ]
+
+When CONFIG_BPF_LSM=y is set, BPF inode storage maps
+(BPF_MAP_TYPE_INODE_STORAGE) are compiled into the kernel. However,
+if the BPF LSM is not explicitly enabled at boot time (e.g. omitted
+from the "lsm=" boot parameter), lsm_prepare() is never executed for
+the BPF LSM.
+
+Consequently, the BPF inode security blob offset
+(bpf_lsm_blob_sizes.lbs_inode) is never initialized and remains at
+its default compiled size of 8 bytes instead of being updated to a
+valid offset past the reserved struct rcu_head (typically 16 bytes
+or more).
+
+When a privileged user creates and updates a BPF_MAP_TYPE_INODE_STORAGE
+map, bpf_inode() evaluates inode->i_security + 8. This erroneously
+aliases the struct rcu_head.func callback pointer at the beginning
+of the inode->i_security blob. During subsequent map element cleanup
+or inode destruction, writing NULL to owner_storage clears the queued
+RCU callback pointer. When rcu_do_batch() later executes the queued
+callback, it attempts an instruction fetch at address 0x0, triggering
+an immediate kernel panic.
+
+Fix this by introducing a global bpf_lsm_initialized boolean flag
+marked with __ro_after_init. Set this flag to true inside bpf_lsm_init()
+when the LSM framework successfully registers the BPF LSM. Gate map
+allocation in inode_storage_map_alloc() on this flag, returning
+-EOPNOTSUPP if the BPF LSM is in turn uninitialized.
+
+This fail-fast approach prevents userspace from allocating inode
+storage maps when the supporting BPF LSM infrastructure is absent,
+avoiding zombie map states.
+
+Fixes: 8ea636848aca ("bpf: Implement bpf_local_storage for inodes")
+Reported-by: oxsignal <awo@kakao.com>
+Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
+Reviewed-by: Amery Hung <ameryhung@gmail.com>
+Link: https://lore.kernel.org/bpf/20260628201103.3624525-1-mattbobrowski@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/bpf_lsm.h | 4 ++++
+ kernel/bpf/bpf_inode_storage.c | 9 +++++++++
+ security/bpf/hooks.c | 3 +++
+ 3 files changed, 16 insertions(+)
+
+--- a/include/linux/bpf_lsm.h
++++ b/include/linux/bpf_lsm.h
+@@ -14,6 +14,8 @@
+
+ #ifdef CONFIG_BPF_LSM
+
++extern bool bpf_lsm_initialized __ro_after_init;
++
+ #define LSM_HOOK(RET, DEFAULT, NAME, ...) \
+ RET bpf_lsm_##NAME(__VA_ARGS__);
+ #include <linux/lsm_hook_defs.h>
+@@ -56,6 +58,8 @@ bool bpf_lsm_hook_returns_errno(u32 btf_
+
+ #else /* !CONFIG_BPF_LSM */
+
++#define bpf_lsm_initialized false
++
+ static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id)
+ {
+ return false;
+--- a/kernel/bpf/bpf_inode_storage.c
++++ b/kernel/bpf/bpf_inode_storage.c
+@@ -181,6 +181,15 @@ static int notsupp_get_next_key(struct b
+
+ static struct bpf_map *inode_storage_map_alloc(union bpf_attr *attr)
+ {
++ /*
++ * Do not allow allocation of BPF_MAP_TYPE_INODE_STORAGE if the BPF LSM
++ * was not initialized by the LSM framework at boot. Without proper
++ * initialization, the BPF inode security blob offset remains unprepared,
++ * causing bpf_inode() to calculate an invalid memory offset and corrupt
++ * inode->i_security.
++ */
++ if (!bpf_lsm_initialized)
++ return ERR_PTR(-EOPNOTSUPP);
+ return bpf_local_storage_map_alloc(attr, &inode_cache, false);
+ }
+
+--- a/security/bpf/hooks.c
++++ b/security/bpf/hooks.c
+@@ -7,6 +7,8 @@
+ #include <linux/bpf_lsm.h>
+ #include <uapi/linux/lsm.h>
+
++bool bpf_lsm_initialized __ro_after_init;
++
+ static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
+ #define LSM_HOOK(RET, DEFAULT, NAME, ...) \
+ LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
+@@ -24,6 +26,7 @@ static int __init bpf_lsm_init(void)
+ {
+ security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks),
+ &bpf_lsmid);
++ bpf_lsm_initialized = true;
+ pr_info("LSM support for eBPF active\n");
+ return 0;
+ }
--- /dev/null
+From stable+bounces-278589-greg=kroah.com@vger.kernel.org Tue Jul 21 14:22:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 08:22:46 -0400
+Subject: iommufd: Move vevent memory allocation outside spinlock
+To: stable@vger.kernel.org
+Cc: Nicolin Chen <nicolinc@nvidia.com>, Jason Gunthorpe <jgg@nvidia.com>, Kevin Tian <kevin.tian@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721122246.3827754-1-sashal@kernel.org>
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+[ Upstream commit 47443565d10c51366c9382dbc8597cd6c460b8a2 ]
+
+The veventq memory allocation happens inside the spinlock. Given its depth
+is decided by the user space, this leaves a vulnerability, where userspace
+can allocate large queues to exhaust atomic memory reserves.
+
+Move the allocation outside the spinlock and use GFP_NOWAIT, which can fail
+fast under memory pressure without dipping into the GFP_ATOMIC reserves or
+direct-reclaiming from the threaded IRQ handler. On allocation failure,
+queue the lost_events_header (so userspace learns of the drop) and return
+-ENOMEM so the caller learns of the kernel-side memory pressure.
+
+This is intentionally distinct from the queue-overflow path, which also
+queues the lost_events_header but returns 0: a full queue is an expected
+userspace-pacing condition rather than a kernel error.
+
+A subsequent change will cap the upper bound of the veventq_depth.
+
+Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC")
+Link: https://patch.msgid.link/r/5ff36b5d80f7f6299f851be532a5195c1d2f1dae.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: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommufd/driver.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/iommufd/driver.c
++++ b/drivers/iommu/iommufd/driver.c
+@@ -149,15 +149,18 @@ int iommufd_viommu_report_event(struct i
+ goto out_unlock_veventqs;
+ }
+
+- spin_lock(&veventq->common.lock);
+- if (veventq->num_events == veventq->depth) {
++ /* Pre-allocate to avoid GFP_ATOMIC; use GFP_NOWAIT to avoid sleeping */
++ vevent = kzalloc_flex(*vevent, event_data, data_len, GFP_NOWAIT);
++ if (!vevent) {
++ spin_lock(&veventq->common.lock);
+ vevent = &veventq->lost_events_header;
++ rc = -ENOMEM;
+ goto out_set_header;
+ }
+
+- vevent = kzalloc(struct_size(vevent, event_data, data_len), GFP_ATOMIC);
+- if (!vevent) {
+- rc = -ENOMEM;
++ spin_lock(&veventq->common.lock);
++ if (veventq->num_events == veventq->depth) {
++ kfree(vevent);
+ vevent = &veventq->lost_events_header;
+ goto out_set_header;
+ }
--- /dev/null
+From stable+bounces-278590-greg=kroah.com@vger.kernel.org Tue Jul 21 14:22:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2026 08:22:50 -0400
+Subject: iommufd: Propagate allocation failure in iommufd_veventq_deliver_fetch()
+To: stable@vger.kernel.org
+Cc: Nicolin Chen <nicolinc@nvidia.com>, Pranjal Shrivastava <praan@google.com>, Kevin Tian <kevin.tian@intel.com>, Jason Gunthorpe <jgg@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260721122250.3827936-1-sashal@kernel.org>
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+[ Upstream commit 489e63dd120bad52eba63f5506c214750cd5bc75 ]
+
+When the kzalloc_obj() fails in iommufd_veventq_deliver_fetch(), it returns
+NULL, falsely advertising to userspace that the queue is empty.
+
+Propagate the -ENOMEM properly to the caller.
+
+Fixes: e36ba5ab808e ("iommufd: Add IOMMUFD_OBJ_VEVENTQ and IOMMUFD_CMD_VEVENTQ_ALLOC")
+Link: https://patch.msgid.link/r/25d29feac909e36f78c145fa99ef2d4cb7a415da.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: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommufd/eventq.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/iommu/iommufd/eventq.c
++++ b/drivers/iommu/iommufd/eventq.c
+@@ -272,8 +272,10 @@ iommufd_veventq_deliver_fetch(struct iom
+ /* Make a copy of the lost_events_header for copy_to_user */
+ if (next == &veventq->lost_events_header) {
+ vevent = kzalloc(sizeof(*vevent), GFP_ATOMIC);
+- if (!vevent)
++ if (!vevent) {
++ vevent = ERR_PTR(-ENOMEM);
+ goto out_unlock;
++ }
+ }
+ list_del(&next->node);
+ if (vevent)
+@@ -323,6 +325,12 @@ static ssize_t iommufd_veventq_fops_read
+ return -EINVAL;
+
+ while ((cur = iommufd_veventq_deliver_fetch(veventq))) {
++ if (IS_ERR(cur)) {
++ if (done == 0)
++ rc = PTR_ERR(cur);
++ break;
++ }
++
+ /* Validate the remaining bytes against the header size */
+ if (done >= count || sizeof(*hdr) > count - done) {
+ iommufd_veventq_deliver_restore(veventq, cur);
samples-damon-mtier-fail-early-if-address-range-parameters-are-invalid.patch
kvm-arm64-deduplicate-asid-retrieval-code.patch
kvm-arm64-nv-re-translate-vncr-before-injecting-abort.patch
+iommufd-propagate-allocation-failure-in-iommufd_veventq_deliver_fetch.patch
+iommufd-move-vevent-memory-allocation-outside-spinlock.patch
+bpf-reject-bpf_map_type_inode_storage-creation-if-bpf-lsm-is-uninitialized.patch