--- /dev/null
+From stable+bounces-276926-greg=kroah.com@vger.kernel.org Fri Jul 17 06:47:26 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:42:59 -0700
+Subject: add default_gfp() helper macro and use it in the new *alloc_obj() helpers
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Linus Torvalds <torvalds@linux-foundation.org>, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-4-ebiggers@kernel.org>
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit e19e1b480ac73c3e62ffebbca1174f0f511f43e7 upstream.
+
+Most simple allocations use GFP_KERNEL, and with the new allocation
+helpers being introduced, let's just take advantage of that to simplify
+that default case.
+
+It's a numbers game:
+
+ git grep 'alloc_obj(' |
+ sed 's/.*\(GFP_[_A-Z]*\).*/\1/' |
+ sort | uniq -c | sort -n | tail
+
+shows that about 90% of all those new allocator instances just use that
+standard GFP_KERNEL.
+
+Those helpers are already macros, and we can easily just make it be the
+default case when the gfp argument is missing.
+
+And yes, we could do that for all the legacy interfaces too, but let's
+keep it to just the new ones at least for now, since those all got
+converted recently anyway, so this is not any "extra" noise outside of
+that limited conversion.
+
+And, in fact, I want to do this before doing the -rc1 release, exactly
+so that we don't get extra merge conflicts.
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/gfp.h | 4 ++++
+ include/linux/slab.h | 48 ++++++++++++++++++++++++------------------------
+ 2 files changed, 28 insertions(+), 24 deletions(-)
+
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -12,6 +12,10 @@
+ struct vm_area_struct;
+ struct mempolicy;
+
++/* Helper macro to avoid gfp flags if they are the default one */
++#define __default_gfp(a,...) a
++#define default_gfp(...) __default_gfp(__VA_ARGS__ __VA_OPT__(,) GFP_KERNEL)
++
+ /* Convert GFP flags to their corresponding migrate type */
+ #define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
+ #define GFP_MOVABLE_SHIFT 3
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -929,8 +929,8 @@ static __always_inline __alloc_size(1) v
+ * Returns: newly allocated pointer to a @VAR_OR_TYPE on success, or NULL
+ * on failure.
+ */
+-#define kmalloc_obj(VAR_OR_TYPE, GFP) \
+- __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), 1)
++#define kmalloc_obj(VAR_OR_TYPE, ...) \
++ __alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), 1)
+
+ /**
+ * kmalloc_objs - Allocate an array of the given type
+@@ -941,8 +941,8 @@ static __always_inline __alloc_size(1) v
+ * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success,
+ * or NULL on failure.
+ */
+-#define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \
+- __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT)
++#define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \
++ __alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), COUNT)
+
+ /**
+ * kmalloc_flex - Allocate a single instance of the given flexible structure
+@@ -956,32 +956,32 @@ static __always_inline __alloc_size(1) v
+ * will immediately fail if @COUNT is larger than what the type of the
+ * struct's counter variable can represent.
+ */
+-#define kmalloc_flex(VAR_OR_TYPE, FAM, COUNT, GFP) \
+- __alloc_flex(kmalloc, GFP, typeof(VAR_OR_TYPE), FAM, COUNT)
++#define kmalloc_flex(VAR_OR_TYPE, FAM, COUNT, ...) \
++ __alloc_flex(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), FAM, COUNT)
+
+ /* All kzalloc aliases for kmalloc_(obj|objs|flex). */
+-#define kzalloc_obj(P, GFP) \
+- __alloc_objs(kzalloc, GFP, typeof(P), 1)
+-#define kzalloc_objs(P, COUNT, GFP) \
+- __alloc_objs(kzalloc, GFP, typeof(P), COUNT)
+-#define kzalloc_flex(P, FAM, COUNT, GFP) \
+- __alloc_flex(kzalloc, GFP, typeof(P), FAM, COUNT)
++#define kzalloc_obj(P, ...) \
++ __alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
++#define kzalloc_objs(P, COUNT, ...) \
++ __alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
++#define kzalloc_flex(P, FAM, COUNT, ...) \
++ __alloc_flex(kzalloc, default_gfp(__VA_ARGS__), typeof(P), FAM, COUNT)
+
+ /* All kvmalloc aliases for kmalloc_(obj|objs|flex). */
+-#define kvmalloc_obj(P, GFP) \
+- __alloc_objs(kvmalloc, GFP, typeof(P), 1)
+-#define kvmalloc_objs(P, COUNT, GFP) \
+- __alloc_objs(kvmalloc, GFP, typeof(P), COUNT)
+-#define kvmalloc_flex(P, FAM, COUNT, GFP) \
+- __alloc_flex(kvmalloc, GFP, typeof(P), FAM, COUNT)
++#define kvmalloc_obj(P, ...) \
++ __alloc_objs(kvmalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
++#define kvmalloc_objs(P, COUNT, ...) \
++ __alloc_objs(kvmalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
++#define kvmalloc_flex(P, FAM, COUNT, ...) \
++ __alloc_flex(kvmalloc, default_gfp(__VA_ARGS__), typeof(P), FAM, COUNT)
+
+ /* All kvzalloc aliases for kmalloc_(obj|objs|flex). */
+-#define kvzalloc_obj(P, GFP) \
+- __alloc_objs(kvzalloc, GFP, typeof(P), 1)
+-#define kvzalloc_objs(P, COUNT, GFP) \
+- __alloc_objs(kvzalloc, GFP, typeof(P), COUNT)
+-#define kvzalloc_flex(P, FAM, COUNT, GFP) \
+- __alloc_flex(kvzalloc, GFP, typeof(P), FAM, COUNT)
++#define kvzalloc_obj(P, ...) \
++ __alloc_objs(kvzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
++#define kvzalloc_objs(P, COUNT, ...) \
++ __alloc_objs(kvzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
++#define kvzalloc_flex(P, FAM, COUNT, ...) \
++ __alloc_flex(kvzalloc, default_gfp(__VA_ARGS__), typeof(P), FAM, COUNT)
+
+ #define kmem_buckets_alloc(_b, _size, _flags) \
+ alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))
--- /dev/null
+From a6f0643e4f63cfaa0d5d4a69de4f132eac4b8fe4 Mon Sep 17 00:00:00 2001
+From: Matt Bobrowski <mattbobrowski@google.com>
+Date: Sun, 28 Jun 2026 20:11:03 +0000
+Subject: bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized
+
+From: Matt Bobrowski <mattbobrowski@google.com>
+
+commit a6f0643e4f63cfaa0d5d4a69de4f132eac4b8fe4 upstream.
+
+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>
+@@ -50,6 +52,8 @@ int bpf_lsm_get_retval_range(const struc
+ struct bpf_retval_range *range);
+ #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
+@@ -182,6 +182,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),
+@@ -25,6 +27,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-276927-greg=kroah.com@vger.kernel.org Fri Jul 17 06:47:05 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:43:00 -0700
+Subject: default_gfp(): avoid using the "newfangled" __VA_OPT__ trick
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Linus Torvalds <torvalds@linux-foundation.org>, Ricardo Ribalda <ribalda@chromium.org>, Richard Fitzgerald <rf@opensource.cirrus.com>, Ben Dooks <ben.dooks@codethink.co.uk>, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-5-ebiggers@kernel.org>
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 551d44200152cb26f75d2ef990aeb6185b7e37fd upstream.
+
+The default_gfp() helper that I added is not wrong, but it turns out
+that it causes unnecessary headaches for 'sparse' which doesn't support
+the use of __VA_OPT__ (introduced in C++20 and C23, and supported by gcc
+and clang for a long time).
+
+We do already use __VA_OPT__ in some other cases in the kernel (drm/xe
+and btrfs), but it has been fairly limited. Now it triggers for pretty
+much everything, and sparse ends up not working at all.
+
+We can use the traditional gcc ',##__VA_ARGS__' syntax instead: it may
+not be the "C standard" way and is slightly less natural in this
+context, but it is the traditional model for this and avoids the sparse
+problem.
+
+Reported-and-tested-by: Ricardo Ribalda <ribalda@chromium.org>
+Reported-and-tested-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Reported-by: Ben Dooks <ben.dooks@codethink.co.uk>
+Fixes: e19e1b480ac7 ("add default_gfp() helper macro and use it in the new *alloc_obj() helpers")
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/gfp.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -13,8 +13,8 @@ struct vm_area_struct;
+ struct mempolicy;
+
+ /* Helper macro to avoid gfp flags if they are the default one */
+-#define __default_gfp(a,...) a
+-#define default_gfp(...) __default_gfp(__VA_ARGS__ __VA_OPT__(,) GFP_KERNEL)
++#define __default_gfp(a,b,...) b
++#define default_gfp(...) __default_gfp(,##__VA_ARGS__,GFP_KERNEL)
+
+ /* Convert GFP flags to their corresponding migrate type */
+ #define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
--- /dev/null
+From stable+bounces-276929-greg=kroah.com@vger.kernel.org Fri Jul 17 06:48:56 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:43:02 -0700
+Subject: fscrypt: Fix key setup in edge case with multiple data unit sizes
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-7-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit dd015b566d505d698386103e9c80b739c7336eb8 upstream.
+
+The addition of support for customizable data unit sizes introduced an
+edge case where a file's contents can be en/decrypted with the wrong
+data unit size. It occurs when there are multiple v2 policies that:
+
+- Have *different* data unit sizes, via the log2_data_unit_size field
+
+- Share the same master_key_identifier, contents_encryption_mode, and
+ either FSCRYPT_POLICY_FLAG_DIRECT_KEY,
+ FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32, or
+ FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64
+
+- Are being used on the same filesystem, which also must be mounted with
+ the "inlinecrypt" mount option.
+
+Fortunately this edge case doesn't actually occur in practice. I just
+found it via code review. But it needs to be fixed regardless.
+
+The bug is caused by the data unit size not being fully considered when
+blk_crypto_keys are cached in mk_direct_keys, mk_iv_ino_lblk_32_keys,
+and mk_iv_ino_lblk_64_keys. They're differentiated only by master key,
+encryption mode, and flag. However, each one actually has a data unit
+size too. Only the first data unit size that is cached is used.
+
+To fix this, start using the data unit size to differentiate the cached
+keys. For several reasons, including avoiding increasing the size of
+struct fscrypt_master_key, just replace all three arrays with a single
+linked list instead of changing them into two-dimensional arrays. This
+works well when considering that in practice at most 2 entries are used
+across all three arrays, so it was already mostly wasted space.
+
+For simplicity, make the list also take over the publish/subscribe of
+the prepared key itself. That is, create separate list nodes for
+blk_crypto_keys vs crypto_skciphers, and add nodes to the list only when
+their key is actually prepared. (Note that the legacy
+fscrypt_direct_keys table in fs/crypto/keysetup_v1.c already works this
+way.) This eliminates the need for the additional memory barriers when
+reading and writing the fields of struct fscrypt_prepared_key.
+
+Note that I technically should have included the data unit size in the
+HKDF info string as well. But it's too late to change that.
+
+Fixes: 5b1188847180 ("fscrypt: support crypto data unit size less than filesystem block size")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618180652.52742-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/crypto/fscrypt_private.h | 55 ++++++++++++--------
+ fs/crypto/inline_crypt.c | 8 --
+ fs/crypto/keyring.c | 23 +++++---
+ fs/crypto/keysetup.c | 121 ++++++++++++++++++++++++++++----------------
+ 4 files changed, 126 insertions(+), 81 deletions(-)
+
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -27,6 +27,9 @@
+ */
+ #define FSCRYPT_MIN_KEY_SIZE 16
+
++/* Maximum size of a raw fscrypt master key */
++#define FSCRYPT_MAX_RAW_KEY_SIZE 64
++
+ /*
+ * This mask is passed as the third argument to the crypto_alloc_*() functions
+ * to prevent fscrypt from using the Crypto API drivers for non-inline crypto
+@@ -217,7 +220,7 @@ struct fscrypt_symlink_data {
+ * @tfm: crypto API transform object
+ * @blk_key: key for blk-crypto
+ *
+- * Normally only one of the fields will be non-NULL.
++ * Only one of the fields is non-NULL.
+ */
+ struct fscrypt_prepared_key {
+ struct crypto_skcipher *tfm;
+@@ -226,6 +229,15 @@ struct fscrypt_prepared_key {
+ #endif
+ };
+
++/* An entry in the linked list ->mk_mode_keys */
++struct fscrypt_mode_key {
++ struct fscrypt_prepared_key key;
++ struct list_head link;
++ u8 hkdf_context;
++ u8 mode_num;
++ u8 data_unit_bits;
++};
++
+ /*
+ * fscrypt_inode_info - the "encryption key" for an inode
+ *
+@@ -413,20 +425,12 @@ void fscrypt_destroy_inline_crypt_key(st
+ * @prep_key, depending on which encryption implementation the file will use.
+ */
+ static inline bool
+-fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
++fscrypt_is_key_prepared(const struct fscrypt_prepared_key *prep_key,
+ const struct fscrypt_inode_info *ci)
+ {
+- /*
+- * The two smp_load_acquire()'s here pair with the smp_store_release()'s
+- * in fscrypt_prepare_inline_crypt_key() and fscrypt_prepare_key().
+- * I.e., in some cases (namely, if this prep_key is a per-mode
+- * encryption key) another task can publish blk_key or tfm concurrently,
+- * executing a RELEASE barrier. We need to use smp_load_acquire() here
+- * to safely ACQUIRE the memory the other task published.
+- */
+ if (fscrypt_using_inline_encryption(ci))
+- return smp_load_acquire(&prep_key->blk_key) != NULL;
+- return smp_load_acquire(&prep_key->tfm) != NULL;
++ return prep_key->blk_key != NULL;
++ return prep_key->tfm != NULL;
+ }
+
+ #else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
+@@ -458,10 +462,10 @@ fscrypt_destroy_inline_crypt_key(struct
+ }
+
+ static inline bool
+-fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
++fscrypt_is_key_prepared(const struct fscrypt_prepared_key *prep_key,
+ const struct fscrypt_inode_info *ci)
+ {
+- return smp_load_acquire(&prep_key->tfm) != NULL;
++ return prep_key->tfm != NULL;
+ }
+ #endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
+
+@@ -531,8 +535,8 @@ struct fscrypt_master_key {
+ /*
+ * Active and structural reference counts. An active ref guarantees
+ * that the struct continues to exist, continues to be in the keyring
+- * ->s_master_keys, and that any embedded subkeys (e.g.
+- * ->mk_direct_keys) that have been prepared continue to exist.
++ * ->s_master_keys, and that any non-file-scoped subkeys (e.g.
++ * ->mk_mode_keys) that have been prepared continue to exist.
+ * A structural ref only guarantees that the struct continues to exist.
+ *
+ * There is one active ref associated with ->mk_present being true, and
+@@ -586,12 +590,21 @@ struct fscrypt_master_key {
+ spinlock_t mk_decrypted_inodes_lock;
+
+ /*
+- * Per-mode encryption keys for the various types of encryption policies
+- * that use them. Allocated and derived on-demand.
++ * A list of 'struct fscrypt_mode_key' for the (hkdf_context, mode_num,
++ * data_unit_bits, inlinecrypt) combinations that are in use for this
++ * master key, for hkdf_context in [HKDF_CONTEXT_DIRECT_KEY,
++ * HKDF_CONTEXT_IV_INO_LBLK_32_KEY, HKDF_CONTEXT_IV_INO_LBLK_64_KEY].
++ *
++ * This is a linked list and not a hash table because in practice
++ * there's just a single encryption policy per master key, using
++ * _at most_ 2 nodes in this list. Per-file keys don't use this at all.
++ *
++ * This list is append-only until the master key is fully removed, at
++ * which time the list is cleared. Before then,
++ * fscrypt_mode_key_setup_mutex synchronizes appends, and searches use
++ * the RCU read lock together with ->mk_sem held for read.
+ */
+- struct fscrypt_prepared_key mk_direct_keys[FSCRYPT_MODE_MAX + 1];
+- struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[FSCRYPT_MODE_MAX + 1];
+- struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[FSCRYPT_MODE_MAX + 1];
++ struct list_head mk_mode_keys;
+
+ /* Hash key for inode numbers. Initialized only when needed. */
+ siphash_key_t mk_ino_hash_key;
+--- a/fs/crypto/inline_crypt.c
++++ b/fs/crypto/inline_crypt.c
+@@ -191,13 +191,7 @@ int fscrypt_prepare_inline_crypt_key(str
+ goto fail;
+ }
+
+- /*
+- * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
+- * I.e., here we publish ->blk_key with a RELEASE barrier so that
+- * concurrent tasks can ACQUIRE it. Note that this concurrency is only
+- * possible for per-mode keys, not for per-file keys.
+- */
+- smp_store_release(&prep_key->blk_key, blk_key);
++ prep_key->blk_key = blk_key;
+ return 0;
+
+ fail:
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -86,14 +86,14 @@ void fscrypt_put_master_key(struct fscry
+ void fscrypt_put_master_key_activeref(struct super_block *sb,
+ struct fscrypt_master_key *mk)
+ {
+- size_t i;
++ struct fscrypt_mode_key *node, *tmp;
+
+ if (!refcount_dec_and_test(&mk->mk_active_refs))
+ return;
+ /*
+ * No active references left, so complete the full removal of this
+ * fscrypt_master_key struct by removing it from the keyring and
+- * destroying any subkeys embedded in it.
++ * destroying any non-file-scoped subkeys.
+ */
+
+ if (WARN_ON_ONCE(!sb->s_master_keys))
+@@ -109,13 +109,16 @@ void fscrypt_put_master_key_activeref(st
+ WARN_ON_ONCE(mk->mk_present);
+ WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes));
+
+- for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
+- fscrypt_destroy_prepared_key(
+- sb, &mk->mk_direct_keys[i]);
+- fscrypt_destroy_prepared_key(
+- sb, &mk->mk_iv_ino_lblk_64_keys[i]);
+- fscrypt_destroy_prepared_key(
+- sb, &mk->mk_iv_ino_lblk_32_keys[i]);
++ /*
++ * Destroy any non-file-scoped subkeys. Since ->mk_active_refs == 0,
++ * they're no longer referenced by any inodes. Nor can key setup run
++ * and use them again. So they're no longer needed. (This implies no
++ * concurrent readers, so we don't need list_del_rcu() for example.)
++ */
++ list_for_each_entry_safe(node, tmp, &mk->mk_mode_keys, link) {
++ fscrypt_destroy_prepared_key(sb, &node->key);
++ list_del(&node->link);
++ kfree(node);
+ }
+ memzero_explicit(&mk->mk_ino_hash_key,
+ sizeof(mk->mk_ino_hash_key));
+@@ -444,6 +447,8 @@ static int add_new_master_key(struct sup
+ INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
+ spin_lock_init(&mk->mk_decrypted_inodes_lock);
+
++ INIT_LIST_HEAD(&mk->mk_mode_keys);
++
+ if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
+ err = allocate_master_key_users_keyring(mk);
+ if (err)
+--- a/fs/crypto/keysetup.c
++++ b/fs/crypto/keysetup.c
+@@ -159,13 +159,7 @@ int fscrypt_prepare_key(struct fscrypt_p
+ tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+- /*
+- * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
+- * I.e., here we publish ->tfm with a RELEASE barrier so that
+- * concurrent tasks can ACQUIRE it. Note that this concurrency is only
+- * possible for per-mode keys, not for per-file keys.
+- */
+- smp_store_release(&prep_key->tfm, tfm);
++ prep_key->tfm = tfm;
+ return 0;
+ }
+
+@@ -186,9 +180,37 @@ int fscrypt_set_per_file_enc_key(struct
+ return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci);
+ }
+
++/*
++ * Find the fscrypt_prepared_key (if any) for a particular (mk, hkdf_context,
++ * mode_num, data_unit_bits, inlinecrypt) combination.
++ *
++ * The caller must hold ->mk_sem for reading and ->mk_present must be true,
++ * ensuring that ->mk_mode_keys is still append-only.
++ */
++static struct fscrypt_prepared_key *
++fscrypt_find_mode_key(struct fscrypt_master_key *mk, u8 hkdf_context,
++ u8 mode_num, const struct fscrypt_inode_info *ci)
++{
++ struct fscrypt_mode_key *node;
++
++ /*
++ * The RCU read lock here is used only to synchronize with concurrent
++ * list_add_tail_rcu(). Concurrent deletions are impossible here, so
++ * returning a pointer to a node without taking any refcount is safe.
++ */
++ guard(rcu)();
++ list_for_each_entry_rcu(node, &mk->mk_mode_keys, link) {
++ if (node->hkdf_context == hkdf_context &&
++ node->mode_num == mode_num &&
++ node->data_unit_bits == ci->ci_data_unit_bits &&
++ fscrypt_is_key_prepared(&node->key, ci))
++ return &node->key;
++ }
++ return NULL;
++}
++
+ static int setup_per_mode_enc_key(struct fscrypt_inode_info *ci,
+ struct fscrypt_master_key *mk,
+- struct fscrypt_prepared_key *keys,
+ u8 hkdf_context, bool include_fs_uuid)
+ {
+ const struct inode *inode = ci->ci_inode;
+@@ -196,7 +218,8 @@ static int setup_per_mode_enc_key(struct
+ struct fscrypt_mode *mode = ci->ci_mode;
+ const u8 mode_num = mode - fscrypt_modes;
+ struct fscrypt_prepared_key *prep_key;
+- u8 mode_key[FSCRYPT_MAX_KEY_SIZE];
++ struct fscrypt_mode_key *new_node;
++ u8 raw_mode_key[FSCRYPT_MAX_RAW_KEY_SIZE];
+ u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
+ unsigned int hkdf_infolen = 0;
+ int err;
+@@ -204,41 +227,52 @@ static int setup_per_mode_enc_key(struct
+ if (WARN_ON_ONCE(mode_num > FSCRYPT_MODE_MAX))
+ return -EINVAL;
+
+- prep_key = &keys[mode_num];
+- if (fscrypt_is_key_prepared(prep_key, ci)) {
++ prep_key = fscrypt_find_mode_key(mk, hkdf_context, mode_num, ci);
++ if (prep_key) {
+ ci->ci_enc_key = *prep_key;
+ return 0;
+ }
+
+- mutex_lock(&fscrypt_mode_key_setup_mutex);
++ guard(mutex)(&fscrypt_mode_key_setup_mutex);
+
+- if (fscrypt_is_key_prepared(prep_key, ci))
+- goto done_unlock;
++ prep_key = fscrypt_find_mode_key(mk, hkdf_context, mode_num, ci);
++ if (prep_key) {
++ ci->ci_enc_key = *prep_key;
++ return 0;
++ }
+
+- BUILD_BUG_ON(sizeof(mode_num) != 1);
+- BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
+- BUILD_BUG_ON(sizeof(hkdf_info) != 17);
+- hkdf_info[hkdf_infolen++] = mode_num;
+- if (include_fs_uuid) {
+- memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
+- sizeof(sb->s_uuid));
+- hkdf_infolen += sizeof(sb->s_uuid);
+- }
+- err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
+- hkdf_context, hkdf_info, hkdf_infolen,
+- mode_key, mode->keysize);
+- if (err)
+- goto out_unlock;
+- err = fscrypt_prepare_key(prep_key, mode_key, ci);
+- memzero_explicit(mode_key, mode->keysize);
+- if (err)
+- goto out_unlock;
+-done_unlock:
++ new_node = kzalloc_obj(*new_node);
++ if (!new_node)
++ return -ENOMEM;
++ new_node->hkdf_context = hkdf_context;
++ new_node->mode_num = mode_num;
++ new_node->data_unit_bits = ci->ci_data_unit_bits;
++ prep_key = &new_node->key;
++
++ {
++ static_assert(sizeof(mode_num) == 1);
++ static_assert(sizeof(sb->s_uuid) == 16);
++ static_assert(sizeof(hkdf_info) == 17);
++ hkdf_info[hkdf_infolen++] = mode_num;
++ if (include_fs_uuid) {
++ memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
++ sizeof(sb->s_uuid));
++ hkdf_infolen += sizeof(sb->s_uuid);
++ }
++ err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context,
++ hkdf_info, hkdf_infolen, raw_mode_key,
++ mode->keysize);
++ if (!err)
++ err = fscrypt_prepare_key(prep_key, raw_mode_key, ci);
++ memzero_explicit(raw_mode_key, mode->keysize);
++ }
++ if (err) {
++ kfree(new_node);
++ return err;
++ }
++ list_add_tail_rcu(&new_node->link, &mk->mk_mode_keys);
+ ci->ci_enc_key = *prep_key;
+- err = 0;
+-out_unlock:
+- mutex_unlock(&fscrypt_mode_key_setup_mutex);
+- return err;
++ return 0;
+ }
+
+ /*
+@@ -296,8 +330,8 @@ static int fscrypt_setup_iv_ino_lblk_32_
+ {
+ int err;
+
+- err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_32_keys,
+- HKDF_CONTEXT_IV_INO_LBLK_32_KEY, true);
++ err = setup_per_mode_enc_key(ci, mk, HKDF_CONTEXT_IV_INO_LBLK_32_KEY,
++ true);
+ if (err)
+ return err;
+
+@@ -346,8 +380,8 @@ static int fscrypt_setup_v2_file_key(str
+ * encryption key. This ensures that the master key is
+ * consistently used only for HKDF, avoiding key reuse issues.
+ */
+- err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_keys,
+- HKDF_CONTEXT_DIRECT_KEY, false);
++ err = setup_per_mode_enc_key(ci, mk, HKDF_CONTEXT_DIRECT_KEY,
++ false);
+ } else if (ci->ci_policy.v2.flags &
+ FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
+ /*
+@@ -356,9 +390,8 @@ static int fscrypt_setup_v2_file_key(str
+ * the IVs. This format is optimized for use with inline
+ * encryption hardware compliant with the UFS standard.
+ */
+- err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys,
+- HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
+- true);
++ err = setup_per_mode_enc_key(
++ ci, mk, HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true);
+ } else if (ci->ci_policy.v2.flags &
+ FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
+ err = fscrypt_setup_iv_ino_lblk_32_key(ci, mk);
--- /dev/null
+From stable+bounces-276930-greg=kroah.com@vger.kernel.org Fri Jul 17 06:47:25 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:43:03 -0700
+Subject: fscrypt: Replace mk_users keyring with simple list
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>, syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com, Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Message-ID: <20260717044303.425265-8-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
+
+Change mk_users (the set of user claims to an fscrypt master key) from a
+'struct key' keyring to a simple linked list.
+
+It's still a collection of 'struct key' for quota tracking. It was
+originally thought to be natural that a collection of 'struct key'
+should be held in a 'struct key' keyring. In reality, it's just been
+causing problems, similar to how using 'struct key' for the filesystem
+keyring caused problems and was removed in commit d7e7b9af104c
+("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
+
+Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()")
+fixed mk_users cleanup to be synchronous. But that apparently wasn't
+enough: the keyring subsystem's redundant locking is still generating
+lockdep false positives due to the interaction with filesystem reclaim.
+
+With the simple list, the redundant locking and lockdep issue goes away.
+
+Of course, searching a linked list is linear-time whereas the
+'struct key' keyring used a fancy constant-time associative array. But
+that's fine here, since in practice there's just one entry in the list.
+In fact the new code is much faster in practice, since it's much smaller
+and doesn't have to convert the kuid_t into a string to search for it.
+
+Reported-by: syzbot+f55b043dacf43776b50c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=f55b043dacf43776b50c
+Reported-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
+Closes: https://lore.kernel.org/keyrings/20260614150041.21172-1-med08elkadiri@gmail.com/
+Fixes: 23c688b54016 ("fscrypt: allow unprivileged users to add/remove keys for v2 policies")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260618221921.87896-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/crypto/fscrypt_private.h | 36 ++++---
+ fs/crypto/keyring.c | 220 ++++++++++++++++++--------------------------
+ 2 files changed, 117 insertions(+), 139 deletions(-)
+
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -472,6 +472,19 @@ fscrypt_is_key_prepared(const struct fsc
+ /* keyring.c */
+
+ /*
++ * fscrypt_master_key_user - a user's claim to a master key
++ */
++struct fscrypt_master_key_user {
++ struct list_head link;
++ kuid_t uid;
++ /*
++ * This 'struct key' contains no secret. It exists solely to charge the
++ * appropriate user's key quota.
++ */
++ struct key *quota_key;
++};
++
++/*
+ * fscrypt_master_key_secret - secret key material of an in-use master key
+ */
+ struct fscrypt_master_key_secret {
+@@ -568,19 +581,18 @@ struct fscrypt_master_key {
+ struct fscrypt_key_specifier mk_spec;
+
+ /*
+- * Keyring which contains a key of type 'key_type_fscrypt_user' for each
+- * user who has added this key. Normally each key will be added by just
+- * one user, but it's possible that multiple users share a key, and in
+- * that case we need to keep track of those users so that one user can't
+- * remove the key before the others want it removed too.
+- *
+- * This is NULL for v1 policy keys; those can only be added by root.
+- *
+- * Locking: protected by ->mk_sem. (We don't just rely on the keyrings
+- * subsystem semaphore ->mk_users->sem, as we need support for atomic
+- * search+insert along with proper synchronization with other fields.)
++ * List of user claims to this key (struct fscrypt_master_key_user).
++ * Normally each key will be added by just one user, but it's possible
++ * that multiple users share a key, and in that case we need to keep
++ * track of those users so that one user can't remove the key before the
++ * others want it removed too.
++ *
++ * Used only for v2 policy keys. v1 policy keys can be added only by
++ * root, so user tracking doesn't apply to them.
++ *
++ * Locking: protected by ->mk_sem.
+ */
+- struct key *mk_users;
++ struct list_head mk_users;
+
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -64,22 +64,19 @@ static void fscrypt_free_master_key(stru
+ kfree_sensitive(mk);
+ }
+
++static void clear_mk_users(struct fscrypt_master_key *mk);
++
+ void fscrypt_put_master_key(struct fscrypt_master_key *mk)
+ {
+ if (!refcount_dec_and_test(&mk->mk_struct_refs))
+ return;
+ /*
+- * No structural references left, so free ->mk_users, and also free the
++ * No structural references left, so clear ->mk_users, and also free the
+ * fscrypt_master_key struct itself after an RCU grace period ensures
+ * that concurrent keyring lookups can no longer find it.
+ */
+ WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 0);
+- if (mk->mk_users) {
+- /* Clear the keyring so the quota gets released right away. */
+- keyring_clear(mk->mk_users);
+- key_put(mk->mk_users);
+- mk->mk_users = NULL;
+- }
++ clear_mk_users(mk);
+ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
+ }
+
+@@ -164,8 +161,8 @@ static void fscrypt_user_key_describe(co
+ }
+
+ /*
+- * Type of key in ->mk_users. Each key of this type represents a particular
+- * user who has added a particular master key.
++ * Type of fscrypt_master_key_user::quota_key. This contains no secret; it
++ * exists solely to charge a user's key quota.
+ *
+ * Note that the name of this key type really should be something like
+ * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen
+@@ -179,30 +176,9 @@ static struct key_type key_type_fscrypt_
+ .describe = fscrypt_user_key_describe,
+ };
+
+-#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+- CONST_STRLEN("-users") + 1)
+-
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_mk_users_keyring_description(
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+- sprintf(description, "fscrypt-%*phN-users",
+- FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier);
+-}
+-
+-static void format_mk_user_description(
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE],
+- const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+-{
+-
+- sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE,
+- mk_identifier, __kuid_val(current_fsuid()));
+-}
+-
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+@@ -337,91 +313,94 @@ out:
+ return mk;
+ }
+
+-static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
+-{
+- char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE];
+- struct key *keyring;
+-
+- format_mk_users_keyring_description(description,
+- mk->mk_spec.u.identifier);
+- keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+- current_cred(), KEY_POS_SEARCH |
+- KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
+- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+- if (IS_ERR(keyring))
+- return PTR_ERR(keyring);
+-
+- mk->mk_users = keyring;
+- return 0;
+-}
+-
+-/*
+- * Find the current user's "key" in the master key's ->mk_users.
+- * Returns ERR_PTR(-ENOKEY) if not found.
+- */
+-static struct key *find_master_key_user(struct fscrypt_master_key *mk)
+-{
+- char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- key_ref_t keyref;
+-
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+-
+- /*
+- * We need to mark the keyring reference as "possessed" so that we
+- * acquire permission to search it, via the KEY_POS_SEARCH permission.
+- */
+- keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
+- &key_type_fscrypt_user, description, false);
+- if (IS_ERR(keyref)) {
+- if (PTR_ERR(keyref) == -EAGAIN || /* not found */
+- PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
+- keyref = ERR_PTR(-ENOKEY);
+- return ERR_CAST(keyref);
++/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */
++static struct fscrypt_master_key_user *
++find_master_key_user(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user;
++ kuid_t uid = current_fsuid();
++
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ if (uid_eq(mk_user->uid, uid))
++ return mk_user;
+ }
+- return key_ref_to_ptr(keyref);
++ return NULL;
+ }
+
+ /*
+- * Give the current user a "key" in ->mk_users. This charges the user's quota
++ * Give the current user a claim in ->mk_users. This charges the user's quota
+ * and marks the master key as added by the current user, so that it cannot be
+ * removed by another user with the key. Either ->mk_sem must be held for
+ * write, or the master key must be still undergoing initialization.
+ */
+ static int add_master_key_user(struct fscrypt_master_key *mk)
+ {
++ kuid_t uid = current_fsuid();
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
+- struct key *mk_user;
++ struct key *quota_key;
++ struct fscrypt_master_key_user *mk_user;
+ int err;
+
+- format_mk_user_description(description, mk->mk_spec.u.identifier);
+- mk_user = key_alloc(&key_type_fscrypt_user, description,
+- current_fsuid(), current_gid(), current_cred(),
+- KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
++ snprintf(description, sizeof(description), "%*phN.uid.%u",
++ FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier,
++ __kuid_val(uid));
++ quota_key = key_alloc(&key_type_fscrypt_user, description, uid,
++ current_gid(), current_cred(),
++ KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL);
++ if (IS_ERR(quota_key))
++ return PTR_ERR(quota_key);
++
++ err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL);
++ if (err) {
++ key_put(quota_key);
++ return err;
++ }
++
++ mk_user = kzalloc_obj(*mk_user);
++ if (!mk_user) {
++ key_put(quota_key);
++ return -ENOMEM;
++ }
++ mk_user->uid = uid;
++ mk_user->quota_key = quota_key;
++ list_add(&mk_user->link, &mk->mk_users);
++ return 0;
++}
+
+- err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL);
+- key_put(mk_user);
+- return err;
++static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user)
++{
++ list_del(&mk_user->link);
++ key_put(mk_user->quota_key);
++ kfree(mk_user);
+ }
+
+ /*
+- * Remove the current user's "key" from ->mk_users.
++ * Remove the current user's claim from ->mk_users.
+ * ->mk_sem must be held for write.
+ *
+- * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
++ * Returns 0 if removed or -ENOKEY if not found.
+ */
+ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ {
+- struct key *mk_user;
+- int err;
++ struct fscrypt_master_key_user *mk_user;
+
+ mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- err = key_unlink(mk->mk_users, mk_user);
+- key_put(mk_user);
+- return err;
++ if (!mk_user)
++ return -ENOKEY;
++ unlink_and_free_mk_user(mk_user);
++ return 0;
++}
++
++/*
++ * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have
++ * no structural references left.
++ */
++static void clear_mk_users(struct fscrypt_master_key *mk)
++{
++ struct fscrypt_master_key_user *mk_user, *tmp;
++
++ list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link)
++ unlink_and_free_mk_user(mk_user);
+ }
+
+ /*
+@@ -444,15 +423,14 @@ static int add_new_master_key(struct sup
+ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
++ INIT_LIST_HEAD(&mk->mk_users);
++
+ INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
+ spin_lock_init(&mk->mk_decrypted_inodes_lock);
+
+ INIT_LIST_HEAD(&mk->mk_mode_keys);
+
+ if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
+- err = allocate_master_key_users_keyring(mk);
+- if (err)
+- goto out_put;
+ err = add_master_key_user(mk);
+ if (err)
+ goto out_put;
+@@ -481,19 +459,13 @@ static int add_existing_master_key(struc
+ int err;
+
+ /*
+- * If the current user is already in ->mk_users, then there's nothing to
+- * do. Otherwise, we need to add the user to ->mk_users. (Neither is
+- * applicable for v1 policy keys, which have NULL ->mk_users.)
++ * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current
++ * user is already in ->mk_users, then there's nothing to do.
++ * Otherwise, add the user to ->mk_users.
+ */
+- if (mk->mk_users) {
+- struct key *mk_user = find_master_key_user(mk);
+-
+- if (mk_user != ERR_PTR(-ENOKEY)) {
+- if (IS_ERR(mk_user))
+- return PTR_ERR(mk_user);
+- key_put(mk_user);
++ if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
++ if (find_master_key_user(mk) != NULL)
+ return 0;
+- }
+ err = add_master_key_user(mk);
+ if (err)
+ return err;
+@@ -847,7 +819,6 @@ int fscrypt_verify_key_added(struct supe
+ {
+ struct fscrypt_key_specifier mk_spec;
+ struct fscrypt_master_key *mk;
+- struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+@@ -859,13 +830,10 @@ int fscrypt_verify_key_added(struct supe
+ goto out;
+ }
+ down_read(&mk->mk_sem);
+- mk_user = find_master_key_user(mk);
+- if (IS_ERR(mk_user)) {
+- err = PTR_ERR(mk_user);
+- } else {
+- key_put(mk_user);
++ if (find_master_key_user(mk) != NULL)
+ err = 0;
+- }
++ else
++ err = -ENOKEY;
+ up_read(&mk->mk_sem);
+ fscrypt_put_master_key(mk);
+ out:
+@@ -1057,16 +1025,18 @@ static int do_remove_key(struct file *fi
+ down_write(&mk->mk_sem);
+
+ /* If relevant, remove current user's (or all users) claim to the key */
+- if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
+- if (all_users)
+- err = keyring_clear(mk->mk_users);
+- else
++ if (!list_empty(&mk->mk_users)) {
++ if (all_users) {
++ clear_mk_users(mk);
++ err = 0;
++ } else {
+ err = remove_master_key_user(mk);
++ }
+ if (err) {
+ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+- if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
++ if (!list_empty(&mk->mk_users)) {
+ /*
+ * Other users have still added the key too. We removed
+ * the current user's claim to the key, but we still
+@@ -1152,6 +1122,8 @@ int fscrypt_ioctl_get_key_status(struct
+ struct super_block *sb = file_inode(filp)->i_sb;
+ struct fscrypt_get_key_status_arg arg;
+ struct fscrypt_master_key *mk;
++ kuid_t uid;
++ const struct fscrypt_master_key_user *mk_user;
+ int err;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+@@ -1184,19 +1156,13 @@ int fscrypt_ioctl_get_key_status(struct
+ }
+
+ arg.status = FSCRYPT_KEY_STATUS_PRESENT;
+- if (mk->mk_users) {
+- struct key *mk_user;
+
+- arg.user_count = mk->mk_users->keys.nr_leaves_on_tree;
+- mk_user = find_master_key_user(mk);
+- if (!IS_ERR(mk_user)) {
++ uid = current_fsuid();
++ list_for_each_entry(mk_user, &mk->mk_users, link) {
++ arg.user_count++;
++ if (uid_eq(mk_user->uid, uid))
+ arg.status_flags |=
+ FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF;
+- key_put(mk_user);
+- } else if (mk_user != ERR_PTR(-ENOKEY)) {
+- err = PTR_ERR(mk_user);
+- goto out_release_key;
+- }
+ }
+ err = 0;
+ out_release_key:
--- /dev/null
+From 100baf0184896f859290a684f864b8200d8ac872 Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oupton@kernel.org>
+Date: Wed, 1 Jul 2026 16:16:19 -0700
+Subject: KVM: arm64: Ensure level is always initialized when relaxing perms
+
+From: Oliver Upton <oupton@kernel.org>
+
+commit 100baf0184896f859290a684f864b8200d8ac872 upstream.
+
+stage2_update_leaf_attrs() returns early before writing to @level if the
+table walker returned an error. At the same time,
+kvm_pgtable_stage2_relax_perms() uses the level as a TLBI TTL hint when the
+error was EAGAIN, indicating the vCPU raced with a table update and the TLB
+entry it hit is now stale.
+
+Fall back to an unknown TTL if none was provided by the walk.
+
+Cc: stable@vger.kernel.org
+Fixes: be097997a273 ("KVM: arm64: Always invalidate TLB for stage-2 permission faults")
+Signed-off-by: Oliver Upton <oupton@kernel.org>
+Reviewed-by: Wei-Lin Chang <weilin.chang@arm.com>
+Link: https://patch.msgid.link/20260701231620.3300204-2-oupton@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/hyp/pgtable.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/kvm/hyp/pgtable.c
++++ b/arch/arm64/kvm/hyp/pgtable.c
+@@ -1314,7 +1314,7 @@ int kvm_pgtable_stage2_relax_perms(struc
+ enum kvm_pgtable_prot prot)
+ {
+ int ret;
+- s8 level;
++ s8 level = TLBI_TTL_UNKNOWN;
+ kvm_pte_t set = 0, clr = 0;
+
+ if (prot & KVM_PTE_LEAF_ATTR_HI_SW)
--- /dev/null
+From 8d187d4b33c262c0f3e44842553521151d8629e8 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Tue, 7 Jul 2026 17:29:35 +0100
+Subject: KVM: arm64: Fix propagation of TLBI level in kvm_pgtable_stage2_relax_perms()
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 8d187d4b33c262c0f3e44842553521151d8629e8 upstream.
+
+Assigning the invalidation level (an s8 value) with TLBI_TTL_UNKNOWN
+(a 32bit signed value) is not ideal, to say the least. Instead of
+this, only pass TLBI_TTL_UNKNOWN to __kvm_tlb_flush_vmid_ipa_nsh()
+when we know for sure that we don't have a provided level.
+
+Fixes: 100baf0184896 ("KVM: arm64: Ensure level is always initialized when relaxing perms")
+Reported-by: Mark Brown <broonie@kernel.org>
+Reviewed-by: Oliver Upton <oupton@kernel.org>
+Link: https://lore.kernel.org/r/akztC7H2IsEKaq4i@sirena.org.uk
+Link: https://patch.msgid.link/20260707162935.1900874-1-maz@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/hyp/pgtable.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/kvm/hyp/pgtable.c
++++ b/arch/arm64/kvm/hyp/pgtable.c
+@@ -1314,7 +1314,7 @@ int kvm_pgtable_stage2_relax_perms(struc
+ enum kvm_pgtable_prot prot)
+ {
+ int ret;
+- s8 level = TLBI_TTL_UNKNOWN;
++ s8 level;
+ kvm_pte_t set = 0, clr = 0;
+
+ if (prot & KVM_PTE_LEAF_ATTR_HI_SW)
+@@ -1333,7 +1333,8 @@ int kvm_pgtable_stage2_relax_perms(struc
+ KVM_PGTABLE_WALK_HANDLE_FAULT |
+ KVM_PGTABLE_WALK_SHARED);
+ if (!ret || ret == -EAGAIN)
+- kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr, level);
++ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa_nsh, pgt->mmu, addr,
++ (ret == -EAGAIN) ? TLBI_TTL_UNKNOWN : level);
+ return ret;
+ }
+
--- /dev/null
+From 3a07249981629ace483ebbef81ef6b34c2d2afec Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sat, 27 Jun 2026 11:51:05 +0100
+Subject: KVM: Move kvm_io_bus_get_dev() locking responsibilities to callers
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 3a07249981629ace483ebbef81ef6b34c2d2afec upstream.
+
+kvm_io_bus_get_dev() returns a device that is only matched by the
+address, and nothing else. This can cause a lifetime issue if
+the matched device is not the expected type, as by the time
+the caller can introspect the object, it might be gone (the srcu
+lock having been dropped).
+
+Given that there is only a single user of this helper, the simplest
+option is to move the locking responsibility to the caller, which
+can keep the srcu lock held for as long as it wants.
+
+Note that this aligns with other kvm_io_bus*() helpers, which
+already require the srcu lock to be held by the callers.
+
+Reported-by: Will Deacon <will@kernel.org>
+Fixes: 8a39d00670f07 ("KVM: kvm_io_bus: Add kvm_io_bus_get_dev() call")
+Link: https://lore.kernel.org/all/20260626111344.802555-1-maz@kernel.org
+Cc: stable@vger.kernel.org
+Reviewed-by: Oliver Upton <oupton@kernel.org>
+Link: https://patch.msgid.link/20260627105105.1005990-1-maz@kernel.org
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic-its.c | 2 ++
+ virt/kvm/kvm_main.c | 16 +++++-----------
+ 2 files changed, 7 insertions(+), 11 deletions(-)
+
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -510,6 +510,8 @@ static struct vgic_its *__vgic_doorbell_
+ struct kvm_io_device *kvm_io_dev;
+ struct vgic_io_device *iodev;
+
++ guard(srcu)(&kvm->srcu);
++
+ kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, db);
+ if (!kvm_io_dev)
+ return ERR_PTR(-EINVAL);
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -6063,25 +6063,19 @@ struct kvm_io_device *kvm_io_bus_get_dev
+ gpa_t addr)
+ {
+ struct kvm_io_bus *bus;
+- int dev_idx, srcu_idx;
+- struct kvm_io_device *iodev = NULL;
++ int dev_idx;
+
+- srcu_idx = srcu_read_lock(&kvm->srcu);
++ lockdep_assert_held(&kvm->srcu);
+
+ bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+ if (!bus)
+- goto out_unlock;
++ return NULL;
+
+ dev_idx = kvm_io_bus_get_first_dev(bus, addr, 1);
+ if (dev_idx < 0)
+- goto out_unlock;
++ return NULL;
+
+- iodev = bus->range[dev_idx].dev;
+-
+-out_unlock:
+- srcu_read_unlock(&kvm->srcu, srcu_idx);
+-
+- return iodev;
++ return bus->range[dev_idx].dev;
+ }
+ EXPORT_SYMBOL_GPL(kvm_io_bus_get_dev);
+
--- /dev/null
+From 6a66c557a2ab2609575bafd15e093669c05f9711 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Thu, 4 Jun 2026 18:38:48 -0700
+Subject: mm/damon/core: always put unsuccessfully committed target pids
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 6a66c557a2ab2609575bafd15e093669c05f9711 upstream.
+
+damon_commit_target() puts and gets the destination and the source target
+pids. It puts the destination target pid because it will be overwritten
+by the source target pid. It gets the source pid because the caller is
+supposed to eventually put the pids. In more detail, the caller will call
+damon_destroy_ctx() after damon_commit_ctx() to destroy the entire source
+context. And in this case, [f]vaddr operation set's cleanup_target()
+callback will put the pids.
+
+The commit operation is made at the context level. The operation can fail
+in multiple places including in the middle and after the targets commit
+operations. For any such failures, immediately the error is returned to
+the damon_commit_ctx() caller. If some or all of the source target pids
+were committed to the destination during the unsuccessful context commit
+attempt, those pids should be put twice.
+
+The source context will do the put operations using the above explained
+routine. However, let's suppose the destination context was not
+originally using [f]vaddr operation set and the commit failed before the
+ops of the source context is committed. The destination does not have the
+cleanup_target() ops callback, so it cannot put the pids via the
+damon_destroy_ctx().
+
+As a result, the pids are leaked. The issue in the real world would be
+not very common. The commit feature is for changing parameters of running
+DAMON context while inheriting internal status like the monitoring
+results. The monitoring results of a physical address range ain't have
+things that are beneficial to be inherited to a virtual address ranges
+monitoring. So the problem-causing DAMON control would be not very common
+in the real world. That said, it is a supported feature. And
+damon_commit_target() failure due to memory allocation is relatively
+realistic [1] if there are a huge number of target regions.
+
+Fix by putting the pids in the commit operation in case of the failures.
+
+The issue was discovered [2] by Sashiko.
+
+Link: https://lore.kernel.org/20260605013849.83750-1-sj@kernel.org
+Link: https://lore.kernel.org/20260603112306.58490-1-akinobu.mita@gmail.com [1]
+Link: https://lore.kernel.org/20260320020056.835-1-sj@kernel.org [2]
+Fixes: 83dc7bbaecae ("mm/damon/sysfs: use damon_commit_ctx()")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.11.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/core.c | 49 +++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 43 insertions(+), 6 deletions(-)
+
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -938,10 +938,36 @@ static int damon_commit_target(
+ return 0;
+ }
+
++/*
++ * damon_revert_target_commits() - revert unsuccessful target commits.
++ * @dst: Commit destination context
++ * @failed: Commit failed destination target
++ * @src: Commit source context
++ *
++ * Revert target states that changed by damon_commit_target(), and cannot be
++ * cleaned up by the destination context's ops.cleanup_target().
++ */
++static void damon_revert_target_commits(struct damon_ctx *dst,
++ struct damon_target *failed, struct damon_ctx *src)
++{
++ struct damon_target *target;
++
++ if (!damon_target_has_pid(src))
++ return;
++ if (damon_target_has_pid(dst))
++ return;
++ damon_for_each_target(target, dst) {
++ if (target == failed)
++ return;
++ put_pid(target->pid);
++ }
++}
++
+ static int damon_commit_targets(
+ struct damon_ctx *dst, struct damon_ctx *src)
+ {
+ struct damon_target *dst_target, *next, *src_target, *new_target;
++ struct damon_target *failed;
+ int i = 0, j = 0, err;
+
+ damon_for_each_target_safe(dst_target, next, dst) {
+@@ -950,8 +976,10 @@ static int damon_commit_targets(
+ err = damon_commit_target(
+ dst_target, damon_target_has_pid(dst),
+ src_target, damon_target_has_pid(src));
+- if (err)
+- return err;
++ if (err) {
++ failed = dst_target;
++ goto out;
++ }
+ } else {
+ if (damon_target_has_pid(dst))
+ put_pid(dst_target->pid);
+@@ -959,21 +987,28 @@ static int damon_commit_targets(
+ }
+ }
+
++ failed = NULL;
+ damon_for_each_target_safe(src_target, next, src) {
+ if (j++ < i)
+ continue;
+ new_target = damon_new_target();
+- if (!new_target)
+- return -ENOMEM;
++ if (!new_target) {
++ err = -ENOMEM;
++ goto out;
++ }
+ err = damon_commit_target(new_target, false,
+ src_target, damon_target_has_pid(src));
+ if (err) {
+ damon_destroy_target(new_target);
+- return err;
++ goto out;
+ }
+ damon_add_target(dst, new_target);
+ }
+ return 0;
++
++out:
++ damon_revert_target_commits(dst, failed, src);
++ return err;
+ }
+
+ /**
+@@ -1007,8 +1042,10 @@ int damon_commit_ctx(struct damon_ctx *d
+ * committing require putting pids).
+ */
+ err = damon_set_attrs(dst, &src->attrs);
+- if (err)
++ if (err) {
++ damon_revert_target_commits(dst, NULL, src);
+ return err;
++ }
+ dst->ops = src->ops;
+
+ return 0;
--- /dev/null
+From 47915e855fb38b42133e31ba917d99565f862154 Mon Sep 17 00:00:00 2001
+From: Sandipan Das <sandipan.das@amd.com>
+Date: Fri, 10 Jul 2026 22:04:49 +0530
+Subject: perf/x86/amd/brs: Fix kernel address leakage
+
+From: Sandipan Das <sandipan.das@amd.com>
+
+commit 47915e855fb38b42133e31ba917d99565f862154 upstream.
+
+A user-only branch stack can contain branches that originate from
+the kernel. As a result, kernel addresses are exposed to user space
+even when PERF_SAMPLE_BRANCH_USER is requested. On AMD processors
+supporting X86_FEATURE_BRS (Zen 3 only), perf can still report entries
+such as SYSRET/interrupt returns for which the branch-from addresses
+are in the kernel.
+
+E.g.
+
+ $ perf record -j any,u -c 4000 -e branch-brs -o - -- \
+ perf bench syscall basic --loop 1000 | \
+ perf script -i - -F brstack|tr ' ' '\n'| \
+ grep -E '0x[89a-f][0-9a-f]{15}'
+
+ ...
+ 0xffffffff810001c4/0x72e2e32955eb/-/-/-/0//-
+ 0xffffffff810001c4/0x72e2d94a9821/-/-/-/0//-
+ 0xffffffff810001c4/0x72e2d94ffa1b/-/-/-/0//-
+ ...
+
+BRS provides no hardware branch filtering, so privilege level
+filtering is performed entirely in software. However, amd_brs_match_plm()
+only validates the branch-to address against the requested privilege
+levels. For branches from the kernel to user space, the branch-from
+address is left unchecked and is leaked. Extend the software filter to
+also validate the branch-from address, so that any branch record whose
+branch-from address is in the kernel is dropped when
+PERF_SAMPLE_BRANCH_USER is requested.
+
+Fixes: 8910075d61a3 ("perf/x86/amd: Enable branch sampling priv level filtering")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Signed-off-by: Sandipan Das <sandipan.das@amd.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: stable@vger.kernel.org
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Stephane Eranian <eranian@google.com>
+Link: https://patch.msgid.link/f05931c4f89a146c364bd5dc6b8170b1ac611c65.1783701239.git.sandipan.das@amd.com
+Closes: https://lore.kernel.org/all/20260710110235.F3FD81F000E9@smtp.kernel.org/
+[sandipan: backport to linux-6.6.y]
+Signed-off-by: Sandipan Das <sandipan.das@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/events/amd/brs.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/events/amd/brs.c
++++ b/arch/x86/events/amd/brs.c
+@@ -259,13 +259,13 @@ void amd_brs_disable_all(void)
+ amd_brs_disable();
+ }
+
+-static bool amd_brs_match_plm(struct perf_event *event, u64 to)
++static bool amd_brs_match_plm(struct perf_event *event, u64 from, u64 to)
+ {
+ int type = event->attr.branch_sample_type;
+ int plm_k = PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV;
+ int plm_u = PERF_SAMPLE_BRANCH_USER;
+
+- if (!(type & plm_k) && kernel_ip(to))
++ if (!(type & plm_k) && (kernel_ip(to) || kernel_ip(from)))
+ return 0;
+
+ if (!(type & plm_u) && !kernel_ip(to))
+@@ -338,11 +338,11 @@ void amd_brs_drain(void)
+ */
+ to = (u64)(((s64)to << shift) >> shift);
+
+- if (!amd_brs_match_plm(event, to))
+- continue;
+-
+ rdmsrl(brs_from(brs_idx), from);
+
++ if (!amd_brs_match_plm(event, from, to))
++ continue;
++
+ perf_clear_branch_entry_bitfields(br+nr);
+
+ br[nr].from = from;
--- /dev/null
+From b13fb4ee46472d7f7fc3e2172c08c06ed8b3f31c Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Fri, 9 May 2025 15:32:34 +0200
+Subject: selftests/fs/statmount: build with tools include dir
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+commit b13fb4ee46472d7f7fc3e2172c08c06ed8b3f31c upstream.
+
+Copy the required headers files (mount.h, nsfs.h) to the tools
+include dir and define the statmount/listmount syscall numbers
+to decouple dependency with headers_install for the common cases.
+
+Reviewed-by: John Hubbard <jhubbard@nvidia.com>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Link: https://lore.kernel.org/20250509133240.529330-3-amir73il@gmail.com
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+[florian: resolved conflict in statmount/Makefile]
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/include/uapi/linux/mount.h | 235 ++++++++++++++
+ tools/include/uapi/linux/nsfs.h | 45 ++
+ tools/testing/selftests/filesystems/statmount/Makefile | 3
+ tools/testing/selftests/filesystems/statmount/statmount.h | 36 ++
+ 4 files changed, 318 insertions(+), 1 deletion(-)
+ create mode 100644 tools/include/uapi/linux/mount.h
+ create mode 100644 tools/include/uapi/linux/nsfs.h
+
+--- /dev/null
++++ b/tools/include/uapi/linux/mount.h
+@@ -0,0 +1,235 @@
++#ifndef _UAPI_LINUX_MOUNT_H
++#define _UAPI_LINUX_MOUNT_H
++
++#include <linux/types.h>
++
++/*
++ * These are the fs-independent mount-flags: up to 32 flags are supported
++ *
++ * Usage of these is restricted within the kernel to core mount(2) code and
++ * callers of sys_mount() only. Filesystems should be using the SB_*
++ * equivalent instead.
++ */
++#define MS_RDONLY 1 /* Mount read-only */
++#define MS_NOSUID 2 /* Ignore suid and sgid bits */
++#define MS_NODEV 4 /* Disallow access to device special files */
++#define MS_NOEXEC 8 /* Disallow program execution */
++#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
++#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
++#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
++#define MS_DIRSYNC 128 /* Directory modifications are synchronous */
++#define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */
++#define MS_NOATIME 1024 /* Do not update access times. */
++#define MS_NODIRATIME 2048 /* Do not update directory access times */
++#define MS_BIND 4096
++#define MS_MOVE 8192
++#define MS_REC 16384
++#define MS_VERBOSE 32768 /* War is peace. Verbosity is silence.
++ MS_VERBOSE is deprecated. */
++#define MS_SILENT 32768
++#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
++#define MS_UNBINDABLE (1<<17) /* change to unbindable */
++#define MS_PRIVATE (1<<18) /* change to private */
++#define MS_SLAVE (1<<19) /* change to slave */
++#define MS_SHARED (1<<20) /* change to shared */
++#define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */
++#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
++#define MS_I_VERSION (1<<23) /* Update inode I_version field */
++#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
++#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
++
++/* These sb flags are internal to the kernel */
++#define MS_SUBMOUNT (1<<26)
++#define MS_NOREMOTELOCK (1<<27)
++#define MS_NOSEC (1<<28)
++#define MS_BORN (1<<29)
++#define MS_ACTIVE (1<<30)
++#define MS_NOUSER (1<<31)
++
++/*
++ * Superblock flags that can be altered by MS_REMOUNT
++ */
++#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
++ MS_LAZYTIME)
++
++/*
++ * Old magic mount flag and mask
++ */
++#define MS_MGC_VAL 0xC0ED0000
++#define MS_MGC_MSK 0xffff0000
++
++/*
++ * open_tree() flags.
++ */
++#define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */
++#define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */
++
++/*
++ * move_mount() flags.
++ */
++#define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */
++#define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */
++#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
++#define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */
++#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */
++#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */
++#define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */
++#define MOVE_MOUNT_BENEATH 0x00000200 /* Mount beneath top mount */
++#define MOVE_MOUNT__MASK 0x00000377
++
++/*
++ * fsopen() flags.
++ */
++#define FSOPEN_CLOEXEC 0x00000001
++
++/*
++ * fspick() flags.
++ */
++#define FSPICK_CLOEXEC 0x00000001
++#define FSPICK_SYMLINK_NOFOLLOW 0x00000002
++#define FSPICK_NO_AUTOMOUNT 0x00000004
++#define FSPICK_EMPTY_PATH 0x00000008
++
++/*
++ * The type of fsconfig() call made.
++ */
++enum fsconfig_command {
++ FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
++ FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
++ FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
++ FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
++ FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
++ FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */
++ FSCONFIG_CMD_CREATE = 6, /* Create new or reuse existing superblock */
++ FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
++ FSCONFIG_CMD_CREATE_EXCL = 8, /* Create new superblock, fail if reusing existing superblock */
++};
++
++/*
++ * fsmount() flags.
++ */
++#define FSMOUNT_CLOEXEC 0x00000001
++
++/*
++ * Mount attributes.
++ */
++#define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
++#define MOUNT_ATTR_NOSUID 0x00000002 /* Ignore suid and sgid bits */
++#define MOUNT_ATTR_NODEV 0x00000004 /* Disallow access to device special files */
++#define MOUNT_ATTR_NOEXEC 0x00000008 /* Disallow program execution */
++#define MOUNT_ATTR__ATIME 0x00000070 /* Setting on how atime should be updated */
++#define MOUNT_ATTR_RELATIME 0x00000000 /* - Update atime relative to mtime/ctime. */
++#define MOUNT_ATTR_NOATIME 0x00000010 /* - Do not update access times. */
++#define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */
++#define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */
++#define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
++#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */
++
++/*
++ * mount_setattr()
++ */
++struct mount_attr {
++ __u64 attr_set;
++ __u64 attr_clr;
++ __u64 propagation;
++ __u64 userns_fd;
++};
++
++/* List of all mount_attr versions. */
++#define MOUNT_ATTR_SIZE_VER0 32 /* sizeof first published struct */
++
++
++/*
++ * Structure for getting mount/superblock/filesystem info with statmount(2).
++ *
++ * The interface is similar to statx(2): individual fields or groups can be
++ * selected with the @mask argument of statmount(). Kernel will set the @mask
++ * field according to the supported fields.
++ *
++ * If string fields are selected, then the caller needs to pass a buffer that
++ * has space after the fixed part of the structure. Nul terminated strings are
++ * copied there and offsets relative to @str are stored in the relevant fields.
++ * If the buffer is too small, then EOVERFLOW is returned. The actually used
++ * size is returned in @size.
++ */
++struct statmount {
++ __u32 size; /* Total size, including strings */
++ __u32 mnt_opts; /* [str] Options (comma separated, escaped) */
++ __u64 mask; /* What results were written */
++ __u32 sb_dev_major; /* Device ID */
++ __u32 sb_dev_minor;
++ __u64 sb_magic; /* ..._SUPER_MAGIC */
++ __u32 sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */
++ __u32 fs_type; /* [str] Filesystem type */
++ __u64 mnt_id; /* Unique ID of mount */
++ __u64 mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */
++ __u32 mnt_id_old; /* Reused IDs used in proc/.../mountinfo */
++ __u32 mnt_parent_id_old;
++ __u64 mnt_attr; /* MOUNT_ATTR_... */
++ __u64 mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */
++ __u64 mnt_peer_group; /* ID of shared peer group */
++ __u64 mnt_master; /* Mount receives propagation from this ID */
++ __u64 propagate_from; /* Propagation from in current namespace */
++ __u32 mnt_root; /* [str] Root of mount relative to root of fs */
++ __u32 mnt_point; /* [str] Mountpoint relative to current root */
++ __u64 mnt_ns_id; /* ID of the mount namespace */
++ __u32 fs_subtype; /* [str] Subtype of fs_type (if any) */
++ __u32 sb_source; /* [str] Source string of the mount */
++ __u32 opt_num; /* Number of fs options */
++ __u32 opt_array; /* [str] Array of nul terminated fs options */
++ __u32 opt_sec_num; /* Number of security options */
++ __u32 opt_sec_array; /* [str] Array of nul terminated security options */
++ __u64 supported_mask; /* Mask flags that this kernel supports */
++ __u32 mnt_uidmap_num; /* Number of uid mappings */
++ __u32 mnt_uidmap; /* [str] Array of uid mappings (as seen from callers namespace) */
++ __u32 mnt_gidmap_num; /* Number of gid mappings */
++ __u32 mnt_gidmap; /* [str] Array of gid mappings (as seen from callers namespace) */
++ __u64 __spare2[43];
++ char str[]; /* Variable size part containing strings */
++};
++
++/*
++ * Structure for passing mount ID and miscellaneous parameters to statmount(2)
++ * and listmount(2).
++ *
++ * For statmount(2) @param represents the request mask.
++ * For listmount(2) @param represents the last listed mount id (or zero).
++ */
++struct mnt_id_req {
++ __u32 size;
++ __u32 spare;
++ __u64 mnt_id;
++ __u64 param;
++ __u64 mnt_ns_id;
++};
++
++/* List of all mnt_id_req versions. */
++#define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */
++#define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */
++
++/*
++ * @mask bits for statmount(2)
++ */
++#define STATMOUNT_SB_BASIC 0x00000001U /* Want/got sb_... */
++#define STATMOUNT_MNT_BASIC 0x00000002U /* Want/got mnt_... */
++#define STATMOUNT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */
++#define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */
++#define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */
++#define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
++#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
++#define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
++#define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */
++#define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
++#define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
++#define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */
++#define STATMOUNT_SUPPORTED_MASK 0x00001000U /* Want/got supported mask flags */
++#define STATMOUNT_MNT_UIDMAP 0x00002000U /* Want/got uidmap... */
++#define STATMOUNT_MNT_GIDMAP 0x00004000U /* Want/got gidmap... */
++
++/*
++ * Special @mnt_id values that can be passed to listmount
++ */
++#define LSMT_ROOT 0xffffffffffffffff /* root mount */
++#define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */
++
++#endif /* _UAPI_LINUX_MOUNT_H */
+--- /dev/null
++++ b/tools/include/uapi/linux/nsfs.h
+@@ -0,0 +1,45 @@
++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
++#ifndef __LINUX_NSFS_H
++#define __LINUX_NSFS_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++#define NSIO 0xb7
++
++/* Returns a file descriptor that refers to an owning user namespace */
++#define NS_GET_USERNS _IO(NSIO, 0x1)
++/* Returns a file descriptor that refers to a parent namespace */
++#define NS_GET_PARENT _IO(NSIO, 0x2)
++/* Returns the type of namespace (CLONE_NEW* value) referred to by
++ file descriptor */
++#define NS_GET_NSTYPE _IO(NSIO, 0x3)
++/* Get owner UID (in the caller's user namespace) for a user namespace */
++#define NS_GET_OWNER_UID _IO(NSIO, 0x4)
++/* Get the id for a mount namespace */
++#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, __u64)
++/* Translate pid from target pid namespace into the caller's pid namespace. */
++#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int)
++/* Return thread-group leader id of pid in the callers pid namespace. */
++#define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int)
++/* Translate pid from caller's pid namespace into a target pid namespace. */
++#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int)
++/* Return thread-group leader id of pid in the target pid namespace. */
++#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int)
++
++struct mnt_ns_info {
++ __u32 size;
++ __u32 nr_mounts;
++ __u64 mnt_ns_id;
++};
++
++#define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */
++
++/* Get information about namespace. */
++#define NS_MNT_GET_INFO _IOR(NSIO, 10, struct mnt_ns_info)
++/* Get next namespace. */
++#define NS_MNT_GET_NEXT _IOR(NSIO, 11, struct mnt_ns_info)
++/* Get previous namespace. */
++#define NS_MNT_GET_PREV _IOR(NSIO, 12, struct mnt_ns_info)
++
++#endif /* __LINUX_NSFS_H */
+--- a/tools/testing/selftests/filesystems/statmount/Makefile
++++ b/tools/testing/selftests/filesystems/statmount/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+-CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
++CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES)
++
+ TEST_GEN_PROGS := statmount_test statmount_test_ns
+
+ include ../../lib.mk
+--- a/tools/testing/selftests/filesystems/statmount/statmount.h
++++ b/tools/testing/selftests/filesystems/statmount/statmount.h
+@@ -7,6 +7,42 @@
+ #include <linux/mount.h>
+ #include <asm/unistd.h>
+
++#ifndef __NR_statmount
++ #if defined __alpha__
++ #define __NR_statmount 567
++ #elif defined _MIPS_SIM
++ #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
++ #define __NR_statmount 4457
++ #endif
++ #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
++ #define __NR_statmount 6457
++ #endif
++ #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
++ #define __NR_statmount 5457
++ #endif
++ #else
++ #define __NR_statmount 457
++ #endif
++#endif
++
++#ifndef __NR_listmount
++ #if defined __alpha__
++ #define __NR_listmount 568
++ #elif defined _MIPS_SIM
++ #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
++ #define __NR_listmount 4458
++ #endif
++ #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
++ #define __NR_listmount 6458
++ #endif
++ #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
++ #define __NR_listmount 5458
++ #endif
++ #else
++ #define __NR_listmount 458
++ #endif
++#endif
++
+ static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask,
+ struct statmount *buf, size_t bufsize,
+ unsigned int flags)
exfat-preserve-benign-secondary-entries-during-rename-and-move.patch
btrfs-fix-false-io-failure-after-falling-back-to-buffered-write.patch
btrfs-fix-incorrect-buffered-io-fallback-for-append-direct-writes.patch
+slab-introduce-kmalloc_obj-and-family.patch
+slab-introduce-kmalloc_flex-and-family.patch
+add-default_gfp-helper-macro-and-use-it-in-the-new-alloc_obj-helpers.patch
+default_gfp-avoid-using-the-newfangled-__va_opt__-trick.patch
+slab-recognize-gfp-parameter-as-optional-in-kernel-doc.patch
+fscrypt-fix-key-setup-in-edge-case-with-multiple-data-unit-sizes.patch
+fscrypt-replace-mk_users-keyring-with-simple-list.patch
+selftests-fs-statmount-build-with-tools-include-dir.patch
+mm-damon-core-always-put-unsuccessfully-committed-target-pids.patch
+kvm-move-kvm_io_bus_get_dev-locking-responsibilities-to-callers.patch
+kvm-arm64-ensure-level-is-always-initialized-when-relaxing-perms.patch
+kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch
+bpf-reject-bpf_map_type_inode_storage-creation-if-bpf-lsm-is-uninitialized.patch
+perf-x86-amd-brs-fix-kernel-address-leakage.patch
--- /dev/null
+From stable+bounces-276925-greg=kroah.com@vger.kernel.org Fri Jul 17 06:47:13 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:42:58 -0700
+Subject: slab: Introduce kmalloc_flex() and family
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Kees Cook <kees@kernel.org>, Vlastimil Babka <vbabka@suse.cz>, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-3-ebiggers@kernel.org>
+
+From: Kees Cook <kees@kernel.org>
+
+commit e4c8b46b924eb8de66c6f0accc9cdd0c2e8fa23b upstream.
+
+As done for kmalloc_obj*(), introduce a type-aware allocator for flexible
+arrays, which may also have "counted_by" annotations:
+
+ ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
+
+becomes:
+
+ ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
+
+The internal use of __flex_counter() allows for automatically setting
+the counter member of a struct's flexible array member when it has
+been annotated with __counted_by(), avoiding any missed early size
+initializations while __counted_by() annotations are added to the
+kernel. Additionally, this also checks for "too large" allocations based
+on the type size of the counter variable. For example:
+
+ if (count > type_max(ptr->flex_counter))
+ fail...;
+ size = struct_size(ptr, flex_member, count);
+ ptr = kmalloc(size, gfp);
+ if (!ptr)
+ fail...;
+ ptr->flex_counter = count;
+
+becomes (n.b. unchanged from earlier example):
+
+ ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
+ if (!ptr)
+ fail...;
+ ptr->flex_counter = count;
+
+Note that manual initialization of the flexible array counter is still
+required (at some point) after allocation as not all compiler versions
+support the __counted_by annotation yet. But doing it internally makes
+sure they cannot be missed when __counted_by _is_ available, meaning
+that the bounds checker will not trip due to the lack of "early enough"
+initializations that used to work before enabling the stricter bounds
+checking. For example:
+
+ ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
+ fill(ptr->flex, count);
+ ptr->flex_count = count;
+
+This works correctly before adding a __counted_by annotation (since
+nothing is checking ptr->flex accesses against ptr->flex_count). After
+adding the annotation, the bounds sanitizer would trip during fill()
+because ptr->flex_count wasn't set yet. But with kmalloc_flex() setting
+ptr->flex_count internally at allocation time, the existing code works
+without needing to move the ptr->flex_count assignment before the call
+to fill(). (This has been a stumbling block for __counted_by adoption.)
+
+Link: https://patch.msgid.link/20251203233036.3212363-4-kees@kernel.org
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Kees Cook <kees@kernel.org>
+[Backport-notes: Removed the actual flex counter handling. That's a new
+ feature, which isn't necessary for just adding the new allocation APIs
+ to get backports to apply cleanly. Also, the allocation-time overflow
+ check in the upstream commit was reverted upstream.]
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/process/deprecated.rst | 7 +++++
+ include/linux/slab.h | 42 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 49 insertions(+)
+
+--- a/Documentation/process/deprecated.rst
++++ b/Documentation/process/deprecated.rst
+@@ -387,6 +387,7 @@ allocations. For example, these open cod
+ ptr = kzalloc(sizeof(*ptr), gfp);
+ ptr = kmalloc_array(count, sizeof(*ptr), gfp);
+ ptr = kcalloc(count, sizeof(*ptr), gfp);
++ ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
+ ptr = kmalloc(sizeof(struct foo, gfp);
+
+ become, respectively::
+@@ -395,4 +396,10 @@ become, respectively::
+ ptr = kzalloc_obj(*ptr, gfp);
+ ptr = kmalloc_objs(*ptr, count, gfp);
+ ptr = kzalloc_objs(*ptr, count, gfp);
++ ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
+ __auto_type ptr = kmalloc_obj(struct foo, gfp);
++
++If `ptr->flex_member` is annotated with __counted_by(), the allocation
++will automatically fail if `count` is larger than the maximum
++representable value that can be stored in the counter member associated
++with `flex_member`.
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -901,6 +901,27 @@ static __always_inline __alloc_size(1) v
+ })
+
+ /**
++ * __alloc_flex - Allocate an object that has a trailing flexible array
++ * @KMALLOC: kmalloc wrapper function to use for allocation.
++ * @GFP: GFP flags for the allocation.
++ * @TYPE: type of structure to allocate space for.
++ * @FAM: The name of the flexible array member of @TYPE structure.
++ * @COUNT: how many @FAM elements to allocate space for.
++ *
++ * Returns: Newly allocated pointer to @TYPE with @COUNT-many trailing
++ * @FAM elements, or NULL on failure or if @COUNT cannot be represented
++ * by the member of @TYPE that counts the @FAM elements (annotated via
++ * __counted_by()).
++ */
++#define __alloc_flex(KMALLOC, GFP, TYPE, FAM, COUNT) \
++({ \
++ const size_t __count = (COUNT); \
++ const size_t __obj_size = struct_size_t(TYPE, FAM, __count); \
++ TYPE *__obj_ptr = KMALLOC(__obj_size, GFP); \
++ __obj_ptr; \
++})
++
++/**
+ * kmalloc_obj - Allocate a single instance of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate.
+ * @GFP: GFP flags for the allocation.
+@@ -923,23 +944,44 @@ static __always_inline __alloc_size(1) v
+ #define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \
+ __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT)
+
++/**
++ * kmalloc_flex - Allocate a single instance of the given flexible structure
++ * @VAR_OR_TYPE: Variable or type to allocate (with its flex array).
++ * @FAM: The name of the flexible array member of the structure.
++ * @COUNT: How many flexible array member elements are desired.
++ * @GFP: GFP flags for the allocation.
++ *
++ * Returns: newly allocated pointer to @VAR_OR_TYPE on success, NULL on
++ * failure. If @FAM has been annotated with __counted_by(), the allocation
++ * will immediately fail if @COUNT is larger than what the type of the
++ * struct's counter variable can represent.
++ */
++#define kmalloc_flex(VAR_OR_TYPE, FAM, COUNT, GFP) \
++ __alloc_flex(kmalloc, GFP, typeof(VAR_OR_TYPE), FAM, COUNT)
++
+ /* All kzalloc aliases for kmalloc_(obj|objs|flex). */
+ #define kzalloc_obj(P, GFP) \
+ __alloc_objs(kzalloc, GFP, typeof(P), 1)
+ #define kzalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kzalloc, GFP, typeof(P), COUNT)
++#define kzalloc_flex(P, FAM, COUNT, GFP) \
++ __alloc_flex(kzalloc, GFP, typeof(P), FAM, COUNT)
+
+ /* All kvmalloc aliases for kmalloc_(obj|objs|flex). */
+ #define kvmalloc_obj(P, GFP) \
+ __alloc_objs(kvmalloc, GFP, typeof(P), 1)
+ #define kvmalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kvmalloc, GFP, typeof(P), COUNT)
++#define kvmalloc_flex(P, FAM, COUNT, GFP) \
++ __alloc_flex(kvmalloc, GFP, typeof(P), FAM, COUNT)
+
+ /* All kvzalloc aliases for kmalloc_(obj|objs|flex). */
+ #define kvzalloc_obj(P, GFP) \
+ __alloc_objs(kvzalloc, GFP, typeof(P), 1)
+ #define kvzalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kvzalloc, GFP, typeof(P), COUNT)
++#define kvzalloc_flex(P, FAM, COUNT, GFP) \
++ __alloc_flex(kvzalloc, GFP, typeof(P), FAM, COUNT)
+
+ #define kmem_buckets_alloc(_b, _size, _flags) \
+ alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))
--- /dev/null
+From stable+bounces-276924-greg=kroah.com@vger.kernel.org Fri Jul 17 06:47:09 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:42:57 -0700
+Subject: slab: Introduce kmalloc_obj() and family
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Kees Cook <kees@kernel.org>, Vlastimil Babka <vbabka@suse.cz>, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-2-ebiggers@kernel.org>
+
+From: Kees Cook <kees@kernel.org>
+
+commit 2932ba8d9c99875b98c951d9d3fd6d651d35df3a upstream.
+
+Introduce type-aware kmalloc-family helpers to replace the common
+idioms for single object and arrays of objects allocation:
+
+ ptr = kmalloc(sizeof(*ptr), gfp);
+ ptr = kmalloc(sizeof(struct some_obj_name), gfp);
+ ptr = kzalloc(sizeof(*ptr), gfp);
+ ptr = kmalloc_array(count, sizeof(*ptr), gfp);
+ ptr = kcalloc(count, sizeof(*ptr), gfp);
+
+These become, respectively:
+
+ ptr = kmalloc_obj(*ptr, gfp);
+ ptr = kmalloc_obj(*ptr, gfp);
+ ptr = kzalloc_obj(*ptr, gfp);
+ ptr = kmalloc_objs(*ptr, count, gfp);
+ ptr = kzalloc_objs(*ptr, count, gfp);
+
+Beyond the other benefits outlined below, the primary ergonomic benefit
+is the elimination of needing "sizeof" nor the type name, and the
+enforcement of assignment types (they do not return "void *", but rather
+a pointer to the type of the first argument). The type name _can_ be
+used, though, in the case where an assignment is indirect (e.g. via
+"return"). This additionally allows[1] variables to be declared via
+__auto_type:
+
+ __auto_type ptr = kmalloc_obj(struct foo, gfp);
+
+Internal introspection of the allocated type now becomes possible,
+allowing for future alignment-aware choices to be made by the allocator
+and future hardening work that can be type sensitive. For example,
+adding __alignof(*ptr) as an argument to the internal allocators so that
+appropriate/efficient alignment choices can be made, or being able to
+correctly choose per-allocation offset randomization within a bucket
+that does not break alignment requirements.
+
+Link: https://lore.kernel.org/all/CAHk-=wiCOTW5UftUrAnvJkr6769D29tF7Of79gUjdQHS_TkF5A@mail.gmail.com/ [1]
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Link: https://patch.msgid.link/20251203233036.3212363-1-kees@kernel.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/process/deprecated.rst | 24 ++++++++++++++
+ include/linux/slab.h | 58 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+
+--- a/Documentation/process/deprecated.rst
++++ b/Documentation/process/deprecated.rst
+@@ -372,3 +372,27 @@ The helper must be used::
+ DECLARE_FLEX_ARRAY(struct type2, two);
+ };
+ };
++
++Open-coded kmalloc assignments for struct objects
++-------------------------------------------------
++Performing open-coded kmalloc()-family allocation assignments prevents
++the kernel (and compiler) from being able to examine the type of the
++variable being assigned, which limits any related introspection that
++may help with alignment, wrap-around, or additional hardening. The
++kmalloc_obj()-family of macros provide this introspection, which can be
++used for the common code patterns for single, array, and flexible object
++allocations. For example, these open coded assignments::
++
++ ptr = kmalloc(sizeof(*ptr), gfp);
++ ptr = kzalloc(sizeof(*ptr), gfp);
++ ptr = kmalloc_array(count, sizeof(*ptr), gfp);
++ ptr = kcalloc(count, sizeof(*ptr), gfp);
++ ptr = kmalloc(sizeof(struct foo, gfp);
++
++become, respectively::
++
++ ptr = kmalloc_obj(*ptr, gfp);
++ ptr = kzalloc_obj(*ptr, gfp);
++ ptr = kmalloc_objs(*ptr, count, gfp);
++ ptr = kzalloc_objs(*ptr, count, gfp);
++ __auto_type ptr = kmalloc_obj(struct foo, gfp);
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -12,6 +12,7 @@
+ #ifndef _LINUX_SLAB_H
+ #define _LINUX_SLAB_H
+
++#include <linux/bug.h>
+ #include <linux/cache.h>
+ #include <linux/gfp.h>
+ #include <linux/overflow.h>
+@@ -883,6 +884,63 @@ static __always_inline __alloc_size(1) v
+ }
+ #define kmalloc(...) alloc_hooks(kmalloc_noprof(__VA_ARGS__))
+
++/**
++ * __alloc_objs - Allocate objects of a given type using
++ * @KMALLOC: which size-based kmalloc wrapper to allocate with.
++ * @GFP: GFP flags for the allocation.
++ * @TYPE: type to allocate space for.
++ * @COUNT: how many @TYPE objects to allocate.
++ *
++ * Returns: Newly allocated pointer to (first) @TYPE of @COUNT-many
++ * allocated @TYPE objects, or NULL on failure.
++ */
++#define __alloc_objs(KMALLOC, GFP, TYPE, COUNT) \
++({ \
++ const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \
++ (TYPE *)KMALLOC(__obj_size, GFP); \
++})
++
++/**
++ * kmalloc_obj - Allocate a single instance of the given type
++ * @VAR_OR_TYPE: Variable or type to allocate.
++ * @GFP: GFP flags for the allocation.
++ *
++ * Returns: newly allocated pointer to a @VAR_OR_TYPE on success, or NULL
++ * on failure.
++ */
++#define kmalloc_obj(VAR_OR_TYPE, GFP) \
++ __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), 1)
++
++/**
++ * kmalloc_objs - Allocate an array of the given type
++ * @VAR_OR_TYPE: Variable or type to allocate an array of.
++ * @COUNT: How many elements in the array.
++ * @GFP: GFP flags for the allocation.
++ *
++ * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success,
++ * or NULL on failure.
++ */
++#define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \
++ __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT)
++
++/* All kzalloc aliases for kmalloc_(obj|objs|flex). */
++#define kzalloc_obj(P, GFP) \
++ __alloc_objs(kzalloc, GFP, typeof(P), 1)
++#define kzalloc_objs(P, COUNT, GFP) \
++ __alloc_objs(kzalloc, GFP, typeof(P), COUNT)
++
++/* All kvmalloc aliases for kmalloc_(obj|objs|flex). */
++#define kvmalloc_obj(P, GFP) \
++ __alloc_objs(kvmalloc, GFP, typeof(P), 1)
++#define kvmalloc_objs(P, COUNT, GFP) \
++ __alloc_objs(kvmalloc, GFP, typeof(P), COUNT)
++
++/* All kvzalloc aliases for kmalloc_(obj|objs|flex). */
++#define kvzalloc_obj(P, GFP) \
++ __alloc_objs(kvzalloc, GFP, typeof(P), 1)
++#define kvzalloc_objs(P, COUNT, GFP) \
++ __alloc_objs(kvzalloc, GFP, typeof(P), COUNT)
++
+ #define kmem_buckets_alloc(_b, _size, _flags) \
+ alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))
+
--- /dev/null
+From stable+bounces-276928-greg=kroah.com@vger.kernel.org Fri Jul 17 06:48:15 2026
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Thu, 16 Jul 2026 21:43:01 -0700
+Subject: slab: recognize @GFP parameter as optional in kernel-doc
+To: stable@vger.kernel.org
+Cc: linux-hardening@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-kernel@vger.kernel.org, Randy Dunlap <rdunlap@infradead.org>, "Harry Yoo (Oracle)" <harry@kernel.org>, "Vlastimil Babka (SUSE)" <vbabka@kernel.org>, Eric Biggers <ebiggers@kernel.org>
+Message-ID: <20260717044303.425265-6-ebiggers@kernel.org>
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+commit 7b5f5865fb11e60edd03c5e063e2d228b7062317 upstream.
+
+Since the @GFP parameter in kmalloc_obj() etc. is now optional, change
+the kernel-doc to indicate that it is optional. This avoids kernel-doc
+warnings:
+
+WARNING: include/linux/slab.h:1101 Excess function parameter 'GFP' description in 'kmalloc_obj'
+WARNING: include/linux/slab.h:1113 Excess function parameter 'GFP' description in 'kmalloc_objs'
+WARNING: include/linux/slab.h:1128 Excess function parameter 'GFP' description in 'kmalloc_flex'
+
+Fixes: e19e1b480ac7 ("add default_gfp() helper macro and use it in the new *alloc_obj() helpers")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Acked-by: Harry Yoo (Oracle) <harry@kernel.org>
+Link: https://patch.msgid.link/20260617163125.2716279-1-rdunlap@infradead.org
+Signed-off-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/slab.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -924,7 +924,7 @@ static __always_inline __alloc_size(1) v
+ /**
+ * kmalloc_obj - Allocate a single instance of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate.
+- * @GFP: GFP flags for the allocation.
++ * @...: optional GFP flags for the allocation (GFP_KERNEL when not specified).
+ *
+ * Returns: newly allocated pointer to a @VAR_OR_TYPE on success, or NULL
+ * on failure.
+@@ -936,7 +936,7 @@ static __always_inline __alloc_size(1) v
+ * kmalloc_objs - Allocate an array of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate an array of.
+ * @COUNT: How many elements in the array.
+- * @GFP: GFP flags for the allocation.
++ * @...: optional GFP flags for the allocation (GFP_KERNEL when not specified).
+ *
+ * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success,
+ * or NULL on failure.
+@@ -949,7 +949,7 @@ static __always_inline __alloc_size(1) v
+ * @VAR_OR_TYPE: Variable or type to allocate (with its flex array).
+ * @FAM: The name of the flexible array member of the structure.
+ * @COUNT: How many flexible array member elements are desired.
+- * @GFP: GFP flags for the allocation.
++ * @...: optional GFP flags for the allocation (GFP_KERNEL when not specified).
+ *
+ * Returns: newly allocated pointer to @VAR_OR_TYPE on success, NULL on
+ * failure. If @FAM has been annotated with __counted_by(), the allocation