Linux Security Modules development
 help / color / mirror / Atom feed
* Re: [LSF/MM/BPF TOPIC] Refactor LSM hooks for VFS mount operations
From: Song Liu @ 2026-01-22 23:01 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Paul Moore, bpf, Linux-Fsdevel, lsf-pc, linux-security-module,
	Christian Brauner, Al Viro
In-Reply-To: <94bf50cb-cea7-48c1-9f88-073c969eb211@schaufler-ca.com>

Hi Casey,

Thanks for your comments!

On Thu, Jan 22, 2026 at 9:16 AM Casey Schaufler <casey@schaufler-ca.com> wrote:
>
> On 1/21/2026 7:00 PM, Song Liu wrote:
> > Hi Paul,
> >
> > On Wed, Jan 21, 2026 at 4:14 PM Paul Moore <paul@paul-moore.com> wrote:
> >> On Wed, Jan 21, 2026 at 4:18 PM Song Liu <song@kernel.org> wrote:
> >>> Current LSM hooks do not have good coverage for VFS mount operations.
> >>> Specifically, there are the following issues (and maybe more..):
> >> I don't recall LSM folks normally being invited to LSFMMBPF so it
> >> seems like this would be a poor forum to discuss LSM hooks.
> > Agreed this might not be the best forum to discuss LSM hooks.
> > However, I am not aware of a better forum for in person discussions.
> >
> > AFAICT, in-tree LSMs have straightforward logics around mount
> > monitoring. As long as we get these logic translated properly, I
> > don't expect much controversy with in-tree LSMs.
>
> The existing mount hooks can't handle multiple LSMs that provide
> mount options. Fixing this has proven non-trivial.

Could you please share more information about this issue?

> Changes to LSM
> hooks have to be discussed on the LSM email list, regardless of how
> little impact it seems they might have.

I don't think we're gonna ship anything without thorough discussions in
the mailing list.

Thanks,
Song

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC] Refactor LSM hooks for VFS mount operations
From: Song Liu @ 2026-01-22 23:15 UTC (permalink / raw)
  To: Paul Moore
  Cc: bpf, Linux-Fsdevel, lsf-pc, linux-security-module,
	Christian Brauner, Al Viro
In-Reply-To: <CAHC9VhSSmoUKPRZKr8vbaK1222ZAWQo51G5e3h65g135Q3p8jw@mail.gmail.com>

Hi Paul,

On Thu, Jan 22, 2026 at 9:27 AM Paul Moore <paul@paul-moore.com> wrote:
[...]
> The Linux Security Summit (LSS), held both in North America and Europe
> each year, typically has a large number of LSM developers and
> maintainers in attendance.  The CfP for LSS North America just
> recently opened (link below), and it closes on March 15th with LSS-NA
> taking place May 21st and 22nd; reworking the LSM mount APIs would
> definitely be on-topic for LSS.  While there is a modest conference
> fee to cover recordings (waived for presenters), anyone may attend LSS
> as no invitation is required.
>
> https://sessionize.com/linux-security-summit-north-america-2026
>
> The CfP for Linux Security Summit Europe will open later this year,
> you can expect a similar CfP as LSS North America.
>
> https://events.linuxfoundation.org/linux-security-summit-europe

Thanks for the suggestions! I will double check my schedule and
see whether I can make LSS. LSS Europe is right after LPC, so
there is a good chance I can make it in person.

> > AFAICT, in-tree LSMs have straightforward logics around mount
> > monitoring. As long as we get these logic translated properly, I
> > don't expect much controversy with in-tree LSMs.
>
> It seems very odd, and potentially a waste of time/energy, to discuss
> a redesign of an API without the people needed to sign-off on and
> maintain the design, but what do I know ...

Unfortunately, I often did some work that turned out to be a waste of
time and energy. Well, that's a different story.

This issue has been bothering us for quite some time. Therefore, I
don't mind spending more than necessary effort to get it fixed
sooner. Again, I don't think offline discussions can replace formal
review in the mailing list, so nothing gonna land without the
agreement in the LSM community.

Thanks,
Song

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC] Refactor LSM hooks for VFS mount operations
From: Casey Schaufler @ 2026-01-23  2:29 UTC (permalink / raw)
  To: Song Liu
  Cc: Paul Moore, bpf, Linux-Fsdevel, lsf-pc, linux-security-module,
	Christian Brauner, Al Viro, Casey Schaufler
In-Reply-To: <CAPhsuW7xi+PP9OnkpBoh96aQyf3C82S1cZY4NJro-FKp0i719Q@mail.gmail.com>

On 1/22/2026 3:01 PM, Song Liu wrote:
> Hi Casey,
>
> Thanks for your comments!
>
> On Thu, Jan 22, 2026 at 9:16 AM Casey Schaufler <casey@schaufler-ca.com> wrote:
>> On 1/21/2026 7:00 PM, Song Liu wrote:
>>> Hi Paul,
>>>
>>> On Wed, Jan 21, 2026 at 4:14 PM Paul Moore <paul@paul-moore.com> wrote:
>>>> On Wed, Jan 21, 2026 at 4:18 PM Song Liu <song@kernel.org> wrote:
>>>>> Current LSM hooks do not have good coverage for VFS mount operations.
>>>>> Specifically, there are the following issues (and maybe more..):
>>>> I don't recall LSM folks normally being invited to LSFMMBPF so it
>>>> seems like this would be a poor forum to discuss LSM hooks.
>>> Agreed this might not be the best forum to discuss LSM hooks.
>>> However, I am not aware of a better forum for in person discussions.
>>>
>>> AFAICT, in-tree LSMs have straightforward logics around mount
>>> monitoring. As long as we get these logic translated properly, I
>>> don't expect much controversy with in-tree LSMs.
>> The existing mount hooks can't handle multiple LSMs that provide
>> mount options. Fixing this has proven non-trivial.
> Could you please share more information about this issue?

LSMs assume that any mount options passed to them are options
they provide. If an option isn't recognized, it's an error. If
two LSMs provide mount options the first will report an error for
a mount option recognized by the second. Since hook processing
uses a "bail on fail" model, the second LSM will never be called
to process its options and the mount operation will fail.

The option processing needs to change to allow option processing
in an LSM to differentiate between a failure in processing its
options from finding an unrecognized option. The infrastructure
needs to be changed to allow for multiple LSMs to look at the
options and only fail if none of them handle the options.

>
>> Changes to LSM
>> hooks have to be discussed on the LSM email list, regardless of how
>> little impact it seems they might have.
> I don't think we're gonna ship anything without thorough discussions in
> the mailing list.
>
> Thanks,
> Song

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC] Refactor LSM hooks for VFS mount operations
From: Paul Moore @ 2026-01-23  2:39 UTC (permalink / raw)
  To: Song Liu
  Cc: bpf, Linux-Fsdevel, lsf-pc, linux-security-module,
	Christian Brauner, Al Viro
In-Reply-To: <CAPhsuW6TMNTGs9miKmQ_YFdm-NnCfLViCjQjMkWUYnuj9bB-qA@mail.gmail.com>

On Thu, Jan 22, 2026 at 6:15 PM Song Liu <song@kernel.org> wrote:
> On Thu, Jan 22, 2026 at 9:27 AM Paul Moore <paul@paul-moore.com> wrote:

...

> This issue has been bothering us for quite some time. Therefore, I
> don't mind spending more than necessary effort to get it fixed
> sooner.

Help on identifying and correcting any deficiencies in the LSM mount
hooks is definitely welcome.

-- 
paul-moore.com

^ permalink raw reply

* [PATCH] landlock: fix struct layer_access_masks kernel-doc
From: Randy Dunlap @ 2026-01-23  2:51 UTC (permalink / raw)
  To: linux-kernel
  Cc: Randy Dunlap, Günther Noack, Mickaël Salaün,
	linux-security-module, Paul Moore, James Morris, Serge E. Hallyn

Use the correct struct name and describe the struct member in
kernel-doc notation to prevent kernel-doc warnings.

WARNING: ../security/landlock/ruleset.h:313 expecting prototype for
  struct layer_accesses. Prototype was for struct layer_access_masks instead

Fixes: 1ebf8e8d3245 ("landlock: Transpose the layer masks data structure")
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
---
Something like this is needed. Feel free to massage/correct it some.

Cc: Günther Noack <gnoack3000@gmail.com>
Cc: Mickaël Salaün <mic@digikod.net>
Cc: linux-security-module@vger.kernel.org
Cc: Paul Moore <paul@paul-moore.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>

 security/landlock/ruleset.h |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- linux-next-20260121.orig/security/landlock/ruleset.h
+++ linux-next-20260121/security/landlock/ruleset.h
@@ -302,9 +302,9 @@ landlock_get_scope_mask(const struct lan
 }
 
 /**
- * struct layer_accesses - A boolean matrix of layers and access rights
- *
- * This has a bit for each combination of layer numbers and access rights.
+ * struct layer_access_masks - A boolean matrix of layers and access rights
+ * @access: This has a bit for each combination of layer numbers and access
+ * rights.
  * During access checks, it is used to represent the access rights for each
  * layer which still need to be fulfilled.  When all bits are 0, the access
  * request is considered to be fulfilled.

^ permalink raw reply

* Re: [PATCH v2 08/13] mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
From: Baolin Wang @ 2026-01-23  6:20 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: x86, linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel,
	intel-gfx, linux-fsdevel, linux-aio, linux-erofs, linux-ext4,
	linux-mm, ntfs3, devel, linux-xfs, keyrings,
	linux-security-module
In-Reply-To: <736febd280eb484d79cef5cf55b8a6f79ad832d2.1769097829.git.lorenzo.stoakes@oracle.com>



On 1/23/26 12:06 AM, Lorenzo Stoakes wrote:
> In order to be able to use only vma_flags_t in vm_area_desc we must adjust
> shmem file setup functions to operate in terms of vma_flags_t rather than
> vm_flags_t.
> 
> This patch makes this change and updates all callers to use the new
> functions.
> 
> No functional changes intended.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>

(reduced distribution list too)

Thanks. The shmem part looks good to me with some nits below.

Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>

> ---
>   arch/x86/kernel/cpu/sgx/ioctl.c           |  2 +-
>   drivers/gpu/drm/drm_gem.c                 |  5 +-
>   drivers/gpu/drm/i915/gem/i915_gem_shmem.c |  2 +-
>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c   |  3 +-
>   drivers/gpu/drm/i915/gt/shmem_utils.c     |  3 +-
>   drivers/gpu/drm/ttm/tests/ttm_tt_test.c   |  2 +-
>   drivers/gpu/drm/ttm/ttm_backup.c          |  3 +-
>   drivers/gpu/drm/ttm/ttm_tt.c              |  2 +-
>   fs/xfs/scrub/xfile.c                      |  3 +-
>   fs/xfs/xfs_buf_mem.c                      |  2 +-
>   include/linux/shmem_fs.h                  |  8 ++-
>   ipc/shm.c                                 |  6 +--
>   mm/memfd.c                                |  2 +-
>   mm/memfd_luo.c                            |  2 +-
>   mm/shmem.c                                | 59 +++++++++++++----------
>   security/keys/big_key.c                   |  2 +-
>   16 files changed, 57 insertions(+), 49 deletions(-)

[snip]

>   	inode->i_flags |= i_flags;
> @@ -5864,9 +5869,10 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name,
>    *	checks are provided at the key or shm level rather than the inode.
>    * @name: name for dentry (to be seen in /proc/<pid>/maps)
>    * @size: size to be set for the file
> - * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
> + * @vma_flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size

nit: s/vma_flags/flags

>    */
> -struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
> +struct file *shmem_kernel_file_setup(const char *name, loff_t size,
> +				     vma_flags_t flags)
>   {
>   	return __shmem_file_setup(shm_mnt, name, size, flags, S_PRIVATE);
>   }
> @@ -5878,7 +5884,7 @@ EXPORT_SYMBOL_GPL(shmem_kernel_file_setup);
>    * @size: size to be set for the file
>    * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size

nit: s/VM_NORESERVE/VMA_NORESERVE_BIT

>    */
> -struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
> +struct file *shmem_file_setup(const char *name, loff_t size, vma_flags_t flags)
>   {
>   	return __shmem_file_setup(shm_mnt, name, size, flags, 0);
>   }
> @@ -5889,16 +5895,17 @@ EXPORT_SYMBOL_GPL(shmem_file_setup);
>    * @mnt: the tmpfs mount where the file will be created
>    * @name: name for dentry (to be seen in /proc/<pid>/maps)
>    * @size: size to be set for the file
> - * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
> + * @flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size
>    */
>   struct file *shmem_file_setup_with_mnt(struct vfsmount *mnt, const char *name,
> -				       loff_t size, unsigned long flags)
> +				       loff_t size, vma_flags_t flags)
>   {
>   	return __shmem_file_setup(mnt, name, size, flags, 0);
>   }
>   EXPORT_SYMBOL_GPL(shmem_file_setup_with_mnt);
>   
> -static struct file *__shmem_zero_setup(unsigned long start, unsigned long end, vm_flags_t vm_flags)
> +static struct file *__shmem_zero_setup(unsigned long start, unsigned long end,
> +		vma_flags_t flags)
>   {
>   	loff_t size = end - start;
>   
> @@ -5908,7 +5915,7 @@ static struct file *__shmem_zero_setup(unsigned long start, unsigned long end, v
>   	 * accessible to the user through its mapping, use S_PRIVATE flag to
>   	 * bypass file security, in the same way as shmem_kernel_file_setup().
>   	 */
> -	return shmem_kernel_file_setup("dev/zero", size, vm_flags);
> +	return shmem_kernel_file_setup("dev/zero", size, flags);
>   }
>   
>   /**
> @@ -5918,7 +5925,7 @@ static struct file *__shmem_zero_setup(unsigned long start, unsigned long end, v
>    */
>   int shmem_zero_setup(struct vm_area_struct *vma)
>   {
> -	struct file *file = __shmem_zero_setup(vma->vm_start, vma->vm_end, vma->vm_flags);
> +	struct file *file = __shmem_zero_setup(vma->vm_start, vma->vm_end, vma->flags);
>   
>   	if (IS_ERR(file))
>   		return PTR_ERR(file);
> @@ -5939,7 +5946,7 @@ int shmem_zero_setup(struct vm_area_struct *vma)
>    */
>   int shmem_zero_setup_desc(struct vm_area_desc *desc)
>   {
> -	struct file *file = __shmem_zero_setup(desc->start, desc->end, desc->vm_flags);
> +	struct file *file = __shmem_zero_setup(desc->start, desc->end, desc->vma_flags);
>   
>   	if (IS_ERR(file))
>   		return PTR_ERR(file);
> diff --git a/security/keys/big_key.c b/security/keys/big_key.c
> index d46862ab90d6..268f702df380 100644
> --- a/security/keys/big_key.c
> +++ b/security/keys/big_key.c
> @@ -103,7 +103,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>   					 0, enckey);
>   
>   		/* save aligned data to file */
> -		file = shmem_kernel_file_setup("", enclen, 0);
> +		file = shmem_kernel_file_setup("", enclen, EMPTY_VMA_FLAGS);
>   		if (IS_ERR(file)) {
>   			ret = PTR_ERR(file);
>   			goto err_enckey;


^ permalink raw reply

* Re: [PATCH v2 08/13] mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
From: Darrick J. Wong @ 2026-01-23  7:46 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, Jarkko Sakkinen, Dave Hansen, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
	Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
	Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
	Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
	Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
	Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
	Reinette Chatre, Dave Martin, James Morse, Babu Moger,
	Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
	Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
	Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
	James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
	linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
	linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
	ntfs3, devel, linux-xfs, keyrings, linux-security-module,
	Jason Gunthorpe
In-Reply-To: <736febd280eb484d79cef5cf55b8a6f79ad832d2.1769097829.git.lorenzo.stoakes@oracle.com>

On Thu, Jan 22, 2026 at 04:06:17PM +0000, Lorenzo Stoakes wrote:
> In order to be able to use only vma_flags_t in vm_area_desc we must adjust
> shmem file setup functions to operate in terms of vma_flags_t rather than
> vm_flags_t.
> 
> This patch makes this change and updates all callers to use the new
> functions.
> 
> No functional changes intended.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
>  arch/x86/kernel/cpu/sgx/ioctl.c           |  2 +-
>  drivers/gpu/drm/drm_gem.c                 |  5 +-
>  drivers/gpu/drm/i915/gem/i915_gem_shmem.c |  2 +-
>  drivers/gpu/drm/i915/gem/i915_gem_ttm.c   |  3 +-
>  drivers/gpu/drm/i915/gt/shmem_utils.c     |  3 +-
>  drivers/gpu/drm/ttm/tests/ttm_tt_test.c   |  2 +-
>  drivers/gpu/drm/ttm/ttm_backup.c          |  3 +-
>  drivers/gpu/drm/ttm/ttm_tt.c              |  2 +-
>  fs/xfs/scrub/xfile.c                      |  3 +-
>  fs/xfs/xfs_buf_mem.c                      |  2 +-
>  include/linux/shmem_fs.h                  |  8 ++-
>  ipc/shm.c                                 |  6 +--
>  mm/memfd.c                                |  2 +-
>  mm/memfd_luo.c                            |  2 +-
>  mm/shmem.c                                | 59 +++++++++++++----------
>  security/keys/big_key.c                   |  2 +-
>  16 files changed, 57 insertions(+), 49 deletions(-)
> 

<snip to xfs>

> diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> index c753c79df203..fe0584a39f16 100644
> --- a/fs/xfs/scrub/xfile.c
> +++ b/fs/xfs/scrub/xfile.c
> @@ -61,7 +61,8 @@ xfile_create(
>  	if (!xf)
>  		return -ENOMEM;
>  
> -	xf->file = shmem_kernel_file_setup(description, isize, VM_NORESERVE);
> +	xf->file = shmem_kernel_file_setup(description, isize,
> +					   mk_vma_flags(VMA_NORESERVE_BIT));

Seems fine, macro sorcery aside...

>  	if (IS_ERR(xf->file)) {
>  		error = PTR_ERR(xf->file);
>  		goto out_xfile;
> diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
> index dcbfa274e06d..fd6f0a5bc0ea 100644
> --- a/fs/xfs/xfs_buf_mem.c
> +++ b/fs/xfs/xfs_buf_mem.c
> @@ -62,7 +62,7 @@ xmbuf_alloc(
>  	if (!btp)
>  		return -ENOMEM;
>  
> -	file = shmem_kernel_file_setup(descr, 0, 0);
> +	file = shmem_kernel_file_setup(descr, 0, EMPTY_VMA_FLAGS);

...but does mk_vma_flags() produce the same result?

--D

>  	if (IS_ERR(file)) {
>  		error = PTR_ERR(file);
>  		goto out_free_btp;

^ permalink raw reply

* Re: [PATCH v2 09/13] mm: update all remaining mmap_prepare users to use vma_flags_t
From: Darrick J. Wong @ 2026-01-23  7:47 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, Jarkko Sakkinen, Dave Hansen, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
	Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
	Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
	Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
	Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
	Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
	Reinette Chatre, Dave Martin, James Morse, Babu Moger,
	Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
	Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
	Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
	James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
	linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
	linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
	ntfs3, devel, linux-xfs, keyrings, linux-security-module,
	Jason Gunthorpe
In-Reply-To: <fb1f55323799f09fe6a36865b31550c9ec67c225.1769097829.git.lorenzo.stoakes@oracle.com>

On Thu, Jan 22, 2026 at 04:06:18PM +0000, Lorenzo Stoakes wrote:
> We will be shortly removing the vm_flags_t field from vm_area_desc so we
> need to update all mmap_prepare users to only use the dessc->vma_flags
> field.
> 
> This patch achieves that and makes all ancillary changes required to make
> this possible.
> 
> This lays the groundwork for future work to eliminate the use of vm_flags_t
> in vm_area_desc altogether and more broadly throughout the kernel.
> 
> While we're here, we take the opportunity to replace VM_REMAP_FLAGS with
> VMA_REMAP_FLAGS, the vma_flags_t equivalent.
> 
> No functional changes intended.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> ---
>  drivers/char/mem.c       |  6 +++---
>  drivers/dax/device.c     | 10 +++++-----
>  fs/aio.c                 |  2 +-
>  fs/erofs/data.c          |  5 +++--
>  fs/ext4/file.c           |  4 ++--
>  fs/ntfs3/file.c          |  2 +-
>  fs/orangefs/file.c       |  4 ++--
>  fs/ramfs/file-nommu.c    |  2 +-
>  fs/resctrl/pseudo_lock.c |  2 +-
>  fs/romfs/mmap-nommu.c    |  2 +-
>  fs/xfs/xfs_file.c        |  4 ++--
>  fs/zonefs/file.c         |  3 ++-
>  include/linux/dax.h      |  8 ++++----
>  include/linux/mm.h       | 24 +++++++++++++++++++-----
>  kernel/relay.c           |  2 +-
>  mm/memory.c              | 17 ++++++++---------
>  16 files changed, 56 insertions(+), 41 deletions(-)
> 

<snip to xfs>

> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 7874cf745af3..1238ec018bc7 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1974,14 +1974,14 @@ xfs_file_mmap_prepare(
>  	 * We don't support synchronous mappings for non-DAX files and
>  	 * for DAX files if underneath dax_device is not synchronous.
>  	 */
> -	if (!daxdev_mapping_supported(desc->vm_flags, file_inode(file),
> +	if (!daxdev_mapping_supported(desc, file_inode(file),
>  				      target->bt_daxdev))
>  		return -EOPNOTSUPP;
>  
>  	file_accessed(file);
>  	desc->vm_ops = &xfs_file_vm_ops;
>  	if (IS_DAX(inode))
> -		desc->vm_flags |= VM_HUGEPAGE;
> +		vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT);

Looks good to me,
Acked-by: "Darrick J. Wong" <djwong@kernel.org>

--D

>  	return 0;
>  }
>  

^ permalink raw reply

* Re: [PATCH tip/locking/core 0/6] compiler-context-analysis: Scoped init guards
From: Peter Zijlstra @ 2026-01-23  8:44 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Marco Elver, Ingo Molnar, Thomas Gleixner, Will Deacon,
	Boqun Feng, Waiman Long, Steven Rostedt, Bart Van Assche,
	kasan-dev, llvm, linux-crypto, linux-doc, linux-security-module,
	linux-kernel
In-Reply-To: <20260122063042.GA24452@lst.de>

On Thu, Jan 22, 2026 at 07:30:42AM +0100, Christoph Hellwig wrote:

> That's better.  What would be even better for everyone would be:
> 
> 	mutex_prepare(&obj->mutex); /* acquire, but with a nice name */
> 	obj->data = FOO;
> 	mutex_init_prepared(&obj->mutex); /* release, barrier, actual init */
> 
> 	mutex_lock(&obj->mutex); /* IFF needed only */
> 

This is cannot work. There is no such thing is a release-barrier.
Furthermore, store-release, load-acquire needs an address dependency to
work.

When publishing an object, which is what we're talking about, we have
two common patterns:

 1) a locked data-structure

 2) RCU


The way 1) works is:

	Publish				Use

	lock(&structure_lock);
	insert(&structure, obj);
	unlock(&structure_lock);

					lock(&structure_lock)
					obj = find(&structure, key);
					...
					unlock(&structure_lock);

And here the Publish-unlock is a release which pairs with the Use-lock's
acquire and guarantees that Use sees both 'structure' in a coherent
state and obj as it was at the time of insertion. IOW we have
release-acquire through the &structure_lock pointer.

The way 2) works is:

	Publish				Use

	lock(&structure_lock);
	insert(&structure, obj)
	   rcu_assign_pointer(ptr, obj);
	unlock(&structure_lock);
	  	
					rcu_read_lock();
					obj = find_rcu(&structure, key);
					...
					rcu_read_unlock();


And here rcu_assign_pointer() is a store-release that pairs with an
rcu_dereference() inside find_rcu() on the same pointer.

There is no alternative way to order things, there must be a
release-acquire through a common address.

In both cases it is imperative the obj is fully (or full enough)
initialized before publication, because the consumer is only guaranteed
to see the state of the object it was in at publish time.

^ permalink raw reply

* [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Tetsuo Handa @ 2026-01-23 10:08 UTC (permalink / raw)
  To: linux-security-module, SELinux
  Cc: Steffen Klassert, Herbert Xu, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Network Development

Since xfrm_dev_{state,policy}_flush() are called from only NETDEV_DOWN and
NETDEV_UNREGISTER events, making xfrm_dev_{state,policy}_flush() no-op by
returning an error value from xfrm_dev_{state,policy}_flush_secctx_check()
is pointless. Especially, if xfrm_dev_{state,policy}_flush_secctx_check()
returned an error value upon NETDEV_UNREGISTER event, the system will hung
up with

  unregister_netdevice: waiting for $dev to become free. Usage count = $count

message because the reference to $dev acquired by
xfrm_dev_{state,policy}_add() cannot be released.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 net/xfrm/xfrm_policy.c | 35 -----------------------------------
 net/xfrm/xfrm_state.c  | 33 ---------------------------------
 2 files changed, 68 deletions(-)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 62486f866975..f4df6491095f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1778,41 +1778,12 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid)
 	}
 	return err;
 }
-
-static inline int xfrm_dev_policy_flush_secctx_check(struct net *net,
-						     struct net_device *dev,
-						     bool task_valid)
-{
-	struct xfrm_policy *pol;
-	int err = 0;
-
-	list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
-		if (pol->walk.dead ||
-		    xfrm_policy_id2dir(pol->index) >= XFRM_POLICY_MAX ||
-		    pol->xdo.dev != dev)
-			continue;
-
-		err = security_xfrm_policy_delete(pol->security);
-		if (err) {
-			xfrm_audit_policy_delete(pol, 0, task_valid);
-			return err;
-		}
-	}
-	return err;
-}
 #else
 static inline int
 xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid)
 {
 	return 0;
 }
-
-static inline int xfrm_dev_policy_flush_secctx_check(struct net *net,
-						     struct net_device *dev,
-						     bool task_valid)
-{
-	return 0;
-}
 #endif
 
 int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
@@ -1861,11 +1832,6 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
 	struct xfrm_policy *pol;
 
 	spin_lock_bh(&net->xfrm.xfrm_policy_lock);
-
-	err = xfrm_dev_policy_flush_secctx_check(net, dev, task_valid);
-	if (err)
-		goto out;
-
 again:
 	list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
 		if (pol->walk.dead)
@@ -1888,7 +1854,6 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
 		__xfrm_policy_inexact_flush(net);
 	else
 		err = -ESRCH;
-out:
 	spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
 	return err;
 }
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 98b362d51836..855778177558 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -881,41 +881,12 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
 
 	return err;
 }
-
-static inline int
-xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid)
-{
-	int i, err = 0;
-
-	for (i = 0; i <= net->xfrm.state_hmask; i++) {
-		struct xfrm_state *x;
-		struct xfrm_dev_offload *xso;
-
-		hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) {
-			xso = &x->xso;
-
-			if (xso->dev == dev &&
-			   (err = security_xfrm_state_delete(x)) != 0) {
-				xfrm_audit_state_delete(x, 0, task_valid);
-				return err;
-			}
-		}
-	}
-
-	return err;
-}
 #else
 static inline int
 xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid)
 {
 	return 0;
 }
-
-static inline int
-xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid)
-{
-	return 0;
-}
 #endif
 
 int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
@@ -966,9 +937,6 @@ int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_vali
 	int i, err = 0, cnt = 0;
 
 	spin_lock_bh(&net->xfrm.xfrm_state_lock);
-	err = xfrm_dev_state_flush_secctx_check(net, dev, task_valid);
-	if (err)
-		goto out;
 
 	err = -ESRCH;
 	for (i = 0; i <= net->xfrm.state_hmask; i++) {
@@ -997,7 +965,6 @@ int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_vali
 	if (cnt)
 		err = 0;
 
-out:
 	spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
 	spin_lock_bh(&xfrm_state_dev_gc_lock);
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH v2 08/13] mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
From: Lorenzo Stoakes @ 2026-01-23 12:26 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: Andrew Morton, Jarkko Sakkinen, Dave Hansen, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
	Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
	Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
	Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
	Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
	Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
	Reinette Chatre, Dave Martin, James Morse, Babu Moger,
	Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
	Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
	Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
	James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
	linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
	linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
	ntfs3, devel, linux-xfs, keyrings, linux-security-module,
	Jason Gunthorpe
In-Reply-To: <20260123074652.GW5945@frogsfrogsfrogs>

On Thu, Jan 22, 2026 at 11:46:52PM -0800, Darrick J. Wong wrote:
> On Thu, Jan 22, 2026 at 04:06:17PM +0000, Lorenzo Stoakes wrote:
> > In order to be able to use only vma_flags_t in vm_area_desc we must adjust
> > shmem file setup functions to operate in terms of vma_flags_t rather than
> > vm_flags_t.
> >
> > This patch makes this change and updates all callers to use the new
> > functions.
> >
> > No functional changes intended.
> >
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > ---
> >  arch/x86/kernel/cpu/sgx/ioctl.c           |  2 +-
> >  drivers/gpu/drm/drm_gem.c                 |  5 +-
> >  drivers/gpu/drm/i915/gem/i915_gem_shmem.c |  2 +-
> >  drivers/gpu/drm/i915/gem/i915_gem_ttm.c   |  3 +-
> >  drivers/gpu/drm/i915/gt/shmem_utils.c     |  3 +-
> >  drivers/gpu/drm/ttm/tests/ttm_tt_test.c   |  2 +-
> >  drivers/gpu/drm/ttm/ttm_backup.c          |  3 +-
> >  drivers/gpu/drm/ttm/ttm_tt.c              |  2 +-
> >  fs/xfs/scrub/xfile.c                      |  3 +-
> >  fs/xfs/xfs_buf_mem.c                      |  2 +-
> >  include/linux/shmem_fs.h                  |  8 ++-
> >  ipc/shm.c                                 |  6 +--
> >  mm/memfd.c                                |  2 +-
> >  mm/memfd_luo.c                            |  2 +-
> >  mm/shmem.c                                | 59 +++++++++++++----------
> >  security/keys/big_key.c                   |  2 +-
> >  16 files changed, 57 insertions(+), 49 deletions(-)
> >
>
> <snip to xfs>
>
> > diff --git a/fs/xfs/scrub/xfile.c b/fs/xfs/scrub/xfile.c
> > index c753c79df203..fe0584a39f16 100644
> > --- a/fs/xfs/scrub/xfile.c
> > +++ b/fs/xfs/scrub/xfile.c
> > @@ -61,7 +61,8 @@ xfile_create(
> >  	if (!xf)
> >  		return -ENOMEM;
> >
> > -	xf->file = shmem_kernel_file_setup(description, isize, VM_NORESERVE);
> > +	xf->file = shmem_kernel_file_setup(description, isize,
> > +					   mk_vma_flags(VMA_NORESERVE_BIT));
>
> Seems fine, macro sorcery aside...

Thanks.

>
> >  	if (IS_ERR(xf->file)) {
> >  		error = PTR_ERR(xf->file);
> >  		goto out_xfile;
> > diff --git a/fs/xfs/xfs_buf_mem.c b/fs/xfs/xfs_buf_mem.c
> > index dcbfa274e06d..fd6f0a5bc0ea 100644
> > --- a/fs/xfs/xfs_buf_mem.c
> > +++ b/fs/xfs/xfs_buf_mem.c
> > @@ -62,7 +62,7 @@ xmbuf_alloc(
> >  	if (!btp)
> >  		return -ENOMEM;
> >
> > -	file = shmem_kernel_file_setup(descr, 0, 0);
> > +	file = shmem_kernel_file_setup(descr, 0, EMPTY_VMA_FLAGS);
>
> ...but does mk_vma_flags() produce the same result?

Doing a quick fs/xfs/xfs_buf_mem.s build suggests so:

Before:

	movq	%rax, %rbx
	movq	%r15, %rdi
	xorl	%esi, %esi
	xorl	%edx, %edx
	callq	shmem_kernel_file_setup

After:

	movq	%rax, %rbx
	movq	%r15, %rdi
	xorl	%esi, %esi
	xorl	%edx, %edx
	callq	shmem_kernel_file_setup

Quick google to remind myself of x86-64 sysv calling convention and RDI, RSI,
RDX = param 1,2,3, presumably top 32-bits of registers already cleared and so
params 2, 3 being 0 is correct.

So yeah mk_vma_flags() would work too, I guess EMPTY_VMA_FLAGS is more
semantically nice.

But actually could be nice to define EMPTY_VMA_FLAGS that way rather than the
empty initialiser I use now... :) Still no delta anyway afaict.

>
> --D
>
> >  	if (IS_ERR(file)) {
> >  		error = PTR_ERR(file);
> >  		goto out_free_btp;

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH v2 08/13] mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
From: Lorenzo Stoakes @ 2026-01-23 12:30 UTC (permalink / raw)
  To: Baolin Wang
  Cc: Andrew Morton, x86, linux-sgx, linux-kernel, nvdimm, linux-cxl,
	dri-devel, intel-gfx, linux-fsdevel, linux-aio, linux-erofs,
	linux-ext4, linux-mm, ntfs3, devel, linux-xfs, keyrings,
	linux-security-module
In-Reply-To: <7ccc3447-3a39-4206-95c5-a6cd00e2bda6@linux.alibaba.com>

On Fri, Jan 23, 2026 at 02:20:51PM +0800, Baolin Wang wrote:
>
>
> On 1/23/26 12:06 AM, Lorenzo Stoakes wrote:
> > In order to be able to use only vma_flags_t in vm_area_desc we must adjust
> > shmem file setup functions to operate in terms of vma_flags_t rather than
> > vm_flags_t.
> >
> > This patch makes this change and updates all callers to use the new
> > functions.
> >
> > No functional changes intended.
> >
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
>
> (reduced distribution list too)
>
> Thanks. The shmem part looks good to me with some nits below.
>
> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>

Thanks!

>
> > ---
> >   arch/x86/kernel/cpu/sgx/ioctl.c           |  2 +-
> >   drivers/gpu/drm/drm_gem.c                 |  5 +-
> >   drivers/gpu/drm/i915/gem/i915_gem_shmem.c |  2 +-
> >   drivers/gpu/drm/i915/gem/i915_gem_ttm.c   |  3 +-
> >   drivers/gpu/drm/i915/gt/shmem_utils.c     |  3 +-
> >   drivers/gpu/drm/ttm/tests/ttm_tt_test.c   |  2 +-
> >   drivers/gpu/drm/ttm/ttm_backup.c          |  3 +-
> >   drivers/gpu/drm/ttm/ttm_tt.c              |  2 +-
> >   fs/xfs/scrub/xfile.c                      |  3 +-
> >   fs/xfs/xfs_buf_mem.c                      |  2 +-
> >   include/linux/shmem_fs.h                  |  8 ++-
> >   ipc/shm.c                                 |  6 +--
> >   mm/memfd.c                                |  2 +-
> >   mm/memfd_luo.c                            |  2 +-
> >   mm/shmem.c                                | 59 +++++++++++++----------
> >   security/keys/big_key.c                   |  2 +-
> >   16 files changed, 57 insertions(+), 49 deletions(-)
>
> [snip]
>
> >   	inode->i_flags |= i_flags;
> > @@ -5864,9 +5869,10 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name,
> >    *	checks are provided at the key or shm level rather than the inode.
> >    * @name: name for dentry (to be seen in /proc/<pid>/maps)
> >    * @size: size to be set for the file
> > - * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
> > + * @vma_flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size
>
> nit: s/vma_flags/flags
>
> >    */
> > -struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
> > +struct file *shmem_kernel_file_setup(const char *name, loff_t size,
> > +				     vma_flags_t flags)
> >   {
> >   	return __shmem_file_setup(shm_mnt, name, size, flags, S_PRIVATE);
> >   }
> > @@ -5878,7 +5884,7 @@ EXPORT_SYMBOL_GPL(shmem_kernel_file_setup);
> >    * @size: size to be set for the file
> >    * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
>
> nit: s/VM_NORESERVE/VMA_NORESERVE_BIT

Good spots, will send fix-patch.

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH v2 08/13] mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
From: Lorenzo Stoakes @ 2026-01-23 12:33 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
	Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
	Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
	Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
	Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
	Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
	Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
	Reinette Chatre, Dave Martin, James Morse, Babu Moger,
	Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
	Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
	Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
	James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
	linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
	linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
	ntfs3, linux-xfs, keyrings, linux-security-module,
	Jason Gunthorpe
In-Reply-To: <736febd280eb484d79cef5cf55b8a6f79ad832d2.1769097829.git.lorenzo.stoakes@oracle.com>

Hi Andrew,

Please apply this fix-patch which addresses some minor issues in the kdoc
comments for this patch.

Thanks, Lorenzo

----8<----
From 0283ddb073248f00bfa9694901fcba25362bdc58 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Date: Fri, 23 Jan 2026 12:30:34 +0000
Subject: [PATCH] fix

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
 mm/shmem.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 97a8f55c7296..b9ddd38621a0 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -5869,7 +5869,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name,
  *	checks are provided at the key or shm level rather than the inode.
  * @name: name for dentry (to be seen in /proc/<pid>/maps)
  * @size: size to be set for the file
- * @vma_flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size
+ * @flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size
  */
 struct file *shmem_kernel_file_setup(const char *name, loff_t size,
 				    vma_flags_t flags)
@@ -5882,7 +5882,7 @@ EXPORT_SYMBOL_GPL(shmem_kernel_file_setup);
  * shmem_file_setup - get an unlinked file living in tmpfs
  * @name: name for dentry (to be seen in /proc/<pid>/maps)
  * @size: size to be set for the file
- * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ * @flags: VMA_NORESERVE_BIT suppresses pre-accounting of the entire object size
  */
 struct file *shmem_file_setup(const char *name, loff_t size, vma_flags_t flags)
 {
--
2.52.0

^ permalink raw reply related

* Re: [PATCH v3] ima: Fallback to ctime check for FS without kstat.change_cookie
From: Jeff Layton @ 2026-01-23 13:48 UTC (permalink / raw)
  To: Frederick Lawler, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
	Darrick J. Wong, Christian Brauner, Josef Bacik
  Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <20260122-xfs-ima-fixup-v3-1-20335a8aa836@cloudflare.com>

On Thu, 2026-01-22 at 10:49 -0600, Frederick Lawler wrote:
> Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> introduced a means to track change detection for an inode
> via ctime updates, opposed to setting kstat.change_cookie to
> an i_version when calling into xfs_vn_getattr().
> 
> This introduced a regression for IMA such that an action
> performed on a LOWER inode on a stacked file systems always
> requires a re-evaluation if the LOWER file system does not
> leverage kstat.change_cookie to track inode i_version or lacks
> i_version support all together.
> 
> In the case of stacking XFS on XFS, an action on either the LOWER or UPPER
> will require re-evaluation. Stacking TMPFS on XFS for instance, once the
> inode is UPPER is mutated, IMA resumes normal behavior because TMPFS
> leverages generic_fillattr() to update the change cookie.
> 
> This is because IMA caches kstat.change_cookie to compare against an
> inode's i_version directly in integrity_inode_attrs_changed(), and thus
> could be out of date depending on how file systems set
> kstat.change_cookie.
> 
> To address this, require integrity_inode_attrs_changed() to query
> vfs_getattr_nosec() to compare the cached version against
> kstat.change_cookie directly. This ensures that when updates occur,
> we're accessing the same changed inode version on changes, and fallback
> to compare against kstat.ctime when STATX_CHANGE_COOKIE is missing from
> result mask.
> 
> Lastly, because EVM still relies on querying and caching a inode's
> i_version directly, the integrity_inode_attrs_changed() falls back to the
> original inode.i_version != cached comparison.
> 

It would be good to add:

Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")

That will help the stable kernel automation pick this up too.

> Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> Suggested-by: Jeff Layton <jlayton@kernel.org>
> Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> ---
> We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> using multigrain ctime (as well as other file systems) for
> change detection in commit 1cf7e834a6fb ("xfs: switch to
> multigrain timestamps").
> 
> Because file systems may implement i_version as they see fit, IMA
> caching may be behind as well as file systems that don't support/export
> i_version. Thus we're proposing to compare against the kstat.change_cookie
> directly to the cached version, and fall back to a ctime guard when
> that's not updated.
> 
> EVM is largely left alone since there's no trivial way to query a file
> directly in the LSM call paths to obtain kstat.change_cookie &
> kstat.ctime to cache. Thus retains accessing i_version directly.
> 
> Regression tests will be added to the Linux Test Project instead of
> selftest to help catch future file system changes that may impact
> future evaluation of IMA.
> 
> I'd like this to be backported to at least 6.18 if possible.
> 
> Below is a simplified test that demonstrates the issue:
> 
> _fragment.config_
> CONFIG_XFS_FS=y
> CONFIG_OVERLAY_FS=y
> CONFIG_IMA=y
> CONFIG_IMA_WRITE_POLICY=y
> CONFIG_IMA_READ_POLICY=y
> 
> _./test.sh_
> 
> IMA_POLICY="/sys/kernel/security/ima/policy"
> TEST_BIN="/bin/date"
> MNT_BASE="/tmp/ima_test_root"
> 
> mkdir -p "$MNT_BASE"
> mount -t tmpfs tmpfs "$MNT_BASE"
> mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
> 
> dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
> mkfs.xfs -q "$MNT_BASE/xfs.img"
> mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
> cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
> 
> mount -t overlay overlay -o \
> "lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
> "$MNT_BASE/ovl"
> 
> echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
> 
> target_prog="$MNT_BASE/ovl/test_prog"
> setpriv --reuid nobody "$target_prog"
> setpriv --reuid nobody "$target_prog"
> setpriv --reuid nobody "$target_prog"
> 
> audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
> 
> if [[ "$audit_count" -eq 1 ]]; then
>         echo "PASS: Found exactly 1 audit event."
> else
>         echo "FAIL: Expected 1 audit event, but found $audit_count."
>         exit 1
> fi
> ---
> Changes in v3:
> - Prefer timespec64_to_ns() to leverage attr.version. [Roberto]
> - s/TPMFS/TMPFS/ in description.
> - Link to v2: https://lore.kernel.org/r/20260120-xfs-ima-fixup-v2-1-f332ead8b043@cloudflare.com
> 
> Changes in v2:
> - Updated commit description + message to clarify the problem.
> - compare struct timespec64 to avoid collision possibility [Roberto].
> - Don't check inode_attr_changed() in ima_check_last_writer()
> - Link to v1: https://lore.kernel.org/r/20260112-xfs-ima-fixup-v1-1-8d13b6001312@cloudflare.com
> 
> Changes since RFC:
> - Remove calls to I_IS_VERSION()
> - Function documentation/comments
> - Abide IMA/EVM change detection fallback invariants
> - Combined ctime guard into version for attributes struct
> - Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
> ---
>  include/linux/integrity.h         | 35 +++++++++++++++++++++++++++++++----
>  security/integrity/evm/evm_main.c |  5 ++---
>  security/integrity/ima/ima_api.c  | 11 ++++++++---
>  security/integrity/ima/ima_main.c | 17 ++++++++++-------
>  4 files changed, 51 insertions(+), 17 deletions(-)
> 
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index f5842372359be5341b6870a43b92e695e8fc78af..034f0a1ed48ca8c19c764e302bbfc555dad92cde 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -9,6 +9,8 @@
>  
>  #include <linux/fs.h>
>  #include <linux/iversion.h>
> +#include <linux/kernel.h>
> +#include <linux/time64.h>
>  
>  enum integrity_status {
>  	INTEGRITY_PASS = 0,
> @@ -51,14 +53,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
>  
>  /*
>   * On stacked filesystems detect whether the inode or its content has changed.
> + *
> + * Must be called in process context.
>   */
>  static inline bool
>  integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> -			      const struct inode *inode)
> +			      struct file *file, struct inode *inode)
>  {
> -	return (inode->i_sb->s_dev != attrs->dev ||
> -		inode->i_ino != attrs->ino ||
> -		!inode_eq_iversion(inode, attrs->version));
> +	struct kstat stat;
> +
> +	might_sleep();
> +
> +	if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> +		return true;
> +
> +	/*
> +	 * EVM currently relies on backing inode i_version. While IS_I_VERSION
> +	 * is not a good indicator of i_version support, this still retains
> +	 * the logic such that a re-evaluation should still occur for EVM, and
> +	 * only for IMA if vfs_getattr_nosec() fails.
> +	 */
> +	if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> +				       STATX_CHANGE_COOKIE | STATX_CTIME,
> +				       AT_STATX_SYNC_AS_STAT))
> +		return !IS_I_VERSION(inode) ||
> +			!inode_eq_iversion(inode, attrs->version);
> +
> +	if (stat.result_mask & STATX_CHANGE_COOKIE)
> +		return stat.change_cookie != attrs->version;
> +
> +	if (stat.result_mask & STATX_CTIME)
> +		return timespec64_to_ns(&stat.ctime) != (s64)attrs->version;
> +
> +	return true;
>  }
>  
>  
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
>  	bool ret = false;
>  
>  	if (iint) {
> -		ret = (!IS_I_VERSION(metadata_inode) ||
> -		       integrity_inode_attrs_changed(&iint->metadata_inode,
> -						     metadata_inode));
> +		ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> +						    NULL, metadata_inode);
>  		if (ret)
>  			iint->evm_status = INTEGRITY_UNKNOWN;
>  	}
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index c35ea613c9f8d404ba4886e3b736c3bab29d1668..e47d6281febc15a0ac1bd2ea1d28fea4d0cd5c58 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -272,10 +272,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
>  	 * to an initial measurement/appraisal/audit, but was modified to
>  	 * assume the file changed.
>  	 */
> -	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> +	result = vfs_getattr_nosec(&file->f_path, &stat,
> +				   STATX_CHANGE_COOKIE | STATX_CTIME,
>  				   AT_STATX_SYNC_AS_STAT);
> -	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> -		i_version = stat.change_cookie;
> +	if (!result) {
> +		if (stat.result_mask & STATX_CHANGE_COOKIE)
> +			i_version = stat.change_cookie;
> +		else if (stat.result_mask & STATX_CTIME)
> +			i_version = timespec64_to_ns(&stat.ctime);
> +	}
>  	hash.hdr.algo = algo;
>  	hash.hdr.length = hash_digest_size[algo];
>  
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 5770cf691912aa912fc65280c59f5baac35dd725..8ac42b03740eb93bf23b15cb9039af6cd32aa999 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -28,6 +28,7 @@
>  #include <linux/iversion.h>
>  #include <linux/evm.h>
>  #include <linux/crash_dump.h>
> +#include <linux/time64.h>
>  
>  #include "ima.h"
>  
> @@ -199,10 +200,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
>  					    &iint->atomic_flags);
>  		if ((iint->flags & IMA_NEW_FILE) ||
>  		    vfs_getattr_nosec(&file->f_path, &stat,
> -				      STATX_CHANGE_COOKIE,
> -				      AT_STATX_SYNC_AS_STAT) ||
> -		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> -		    stat.change_cookie != iint->real_inode.version) {
> +			    STATX_CHANGE_COOKIE | STATX_CTIME,
> +			    AT_STATX_SYNC_AS_STAT) ||
> +		    ((stat.result_mask & STATX_CHANGE_COOKIE) ?
> +		      stat.change_cookie != iint->real_inode.version :
> +		      (!(stat.result_mask & STATX_CTIME) ||
> +			timespec64_to_ns(&stat.ctime) !=
> +			(s64)iint->real_inode.version))) {
>  			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
>  			iint->measured_pcrs = 0;
>  			if (update)
> @@ -328,9 +332,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
>  	real_inode = d_real_inode(file_dentry(file));
>  	if (real_inode != inode &&
>  	    (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> -		if (!IS_I_VERSION(real_inode) ||
> -		    integrity_inode_attrs_changed(&iint->real_inode,
> -						  real_inode)) {
> +		if (integrity_inode_attrs_changed(&iint->real_inode,
> +						  file, real_inode)) {
>  			iint->flags &= ~IMA_DONE_MASK;
>  			iint->measured_pcrs = 0;
>  		}
> 
> ---
> base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> change-id: 20251212-xfs-ima-fixup-931780a62c2c
> 
> Best regards,

I gave the IMA code a closer look this time. You can add:

Reviewed-by: Jeff Layton <jlayton@kernel.org>

^ permalink raw reply

* Re: [PATCH] ima: Detect changes to files via kstat changes rather than i_version
From: Jeff Layton @ 2026-01-23 14:06 UTC (permalink / raw)
  To: Roberto Sassu, Frederick Lawler, Mimi Zohar, Roberto Sassu,
	Dmitry Kasatkin, Eric Snowberg, Paul Moore, James Morris,
	Serge E. Hallyn, Darrick J. Wong, Christian Brauner, Josef Bacik
  Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <c825efc60cace922b45d0824f11cdaf44be9c0d3.camel@huaweicloud.com>

On Thu, 2026-01-15 at 12:46 +0100, Roberto Sassu wrote:
> On Mon, 2026-01-12 at 16:32 -0600, Frederick Lawler wrote:
> > Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> > introduced a means to track change detection for an inode
> > via ctime updates, opposed to setting kstat.change_cookie when
> > calling into xfs_vn_getattr().
> > 
> > This introduced a regression because IMA caches kstat.change_cookie
> > to compare against an inode's i_version directly in
> > integrity_inode_attrs_changed(), and thus could be out of date
> > depending on how file systems increment i_version.
> > 
> > To address this, require integrity_inode_attrs_changed() to query
> > vfs_getattr_nosec() to compare the cached version against
> > kstat.change_cookie directly. This ensures that when updates occur,
> > we're accessing the same changed inode version on changes, and fallback
> > to compare against an artificial version generated from kstat.ctime
> > via integrity_ctime_guard() when there's no detected change
> > to the kstat.change_cookie.
> > 
> > This ensures that in the absence of i_version support for file systems,
> > and in the absence of a kstat.change_cookie update, we ultimately have a
> > unique-enough version to compare against.
> > 
> > The exact implementation for integrity_ctime_guard() is to ensure that
> > if tv_sec or tv_nsec are zero, there's some value to store back into
> > struct integrity_inode_attributes.version. This also avoids the need to
> > add additional storage and comparisons.
> > 
> > Lastly, because EVM still relies on querying and caching a backing inode's
> > i_version, the integrity_inode_attrs_changed() falls back to the
> > original inode.i_version != cached comparison. This maintains the
> > invariant that a re-evaluation in unknown change detection circumstances
> > is required.
> > 
> > Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> > Suggested-by: Jeff Layton <jlayton@kernel.org>
> > Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> > ---
> > We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> > struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> > using multigrain ctime (as well as other file systems) for
> > change detection in commit 1cf7e834a6fb ("xfs: switch to
> > multigrain timestamps").
> > 
> > Because file systems may implement i_version as they see fit, IMA
> > caching may be behind as well as file systems that don't support/export
> > i_version. Thus we're proposing to compare against the kstat.change_cookie
> > directly to the cached version, and fall back to a ctime guard when
> > that's not updated.
> > 
> > EVM is largely left alone since there's no trivial way to query a file
> > directly in the LSM call paths to obtain kstat.change_cookie &
> > kstat.ctime to cache. Thus retains accessing i_version directly.
> > 
> > Regression tests will be added to the Linux Test Project instead of
> > selftest to help catch future file system changes that may impact
> > future evaluation of IMA.
> > 
> > I'd like this to be backported to at least 6.18 if possible.
> > 
> > Below is a simplified test that demonstrates the issue:
> > 
> > _fragment.config_
> > CONFIG_XFS_FS=y
> > CONFIG_OVERLAY_FS=y
> > CONFIG_IMA=y
> > CONFIG_IMA_WRITE_POLICY=y
> > CONFIG_IMA_READ_POLICY=y
> > 
> > _./test.sh_
> > 
> > IMA_POLICY="/sys/kernel/security/ima/policy"
> > TEST_BIN="/bin/date"
> > MNT_BASE="/tmp/ima_test_root"
> > 
> > mkdir -p "$MNT_BASE"
> > mount -t tmpfs tmpfs "$MNT_BASE"
> > mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
> > 
> > dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
> > mkfs.xfs -q "$MNT_BASE/xfs.img"
> > mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
> > cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
> > 
> > mount -t overlay overlay -o \
> > "lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
> > "$MNT_BASE/ovl"
> > 
> > echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
> > 
> > target_prog="$MNT_BASE/ovl/test_prog"
> > setpriv --reuid nobody "$target_prog"
> > setpriv --reuid nobody "$target_prog"
> > setpriv --reuid nobody "$target_prog"
> > 
> > audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
> > 
> > if [[ "$audit_count" -eq 1 ]]; then
> >         echo "PASS: Found exactly 1 audit event."
> > else
> >         echo "FAIL: Expected 1 audit event, but found $audit_count."
> >         exit 1
> > fi
> > ---
> > Changes since RFC:
> > - Remove calls to I_IS_VERSION()
> > - Function documentation/comments
> > - Abide IMA/EVM change detection fallback invariants
> > - Combined ctime guard into version for attributes struct
> > - Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
> > ---
> >  include/linux/integrity.h         | 42 +++++++++++++++++++++++++++++++++++----
> >  security/integrity/evm/evm_main.c |  5 ++---
> >  security/integrity/ima/ima_api.c  | 11 +++++++---
> >  security/integrity/ima/ima_main.c | 15 +++++---------
> >  4 files changed, 53 insertions(+), 20 deletions(-)
> > 
> > diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> > index f5842372359be5341b6870a43b92e695e8fc78af..5eca8aa2769f9238c68bb40885ecc46910524f11 100644
> > --- a/include/linux/integrity.h
> > +++ b/include/linux/integrity.h
> > @@ -9,6 +9,7 @@
> >  
> >  #include <linux/fs.h>
> >  #include <linux/iversion.h>
> > +#include <linux/kernel.h>
> >  
> >  enum integrity_status {
> >  	INTEGRITY_PASS = 0,
> > @@ -36,6 +37,14 @@ struct integrity_inode_attributes {
> >  	dev_t dev;
> >  };
> >  
> > +/*
> > + * Wrapper to generate an artificial version for a file.
> > + */
> > +static inline u64 integrity_ctime_guard(struct kstat stat)
> > +{
> > +	return stat.ctime.tv_sec ^ stat.ctime.tv_nsec;
> 
> Unfortunately, we cannot take the risk of a collision. Better use all
> or a packed version.
> 
> > +}
> > +
> >  /*
> >   * On stacked filesystems the i_version alone is not enough to detect file data
> >   * or metadata change. Additional metadata is required.
> > @@ -51,14 +60,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> >  
> >  /*
> >   * On stacked filesystems detect whether the inode or its content has changed.
> > + *
> > + * Must be called in process context.
> >   */
> >  static inline bool
> >  integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> > -			      const struct inode *inode)
> > +			      struct file *file, struct inode *inode)
> >  {
> > -	return (inode->i_sb->s_dev != attrs->dev ||
> > -		inode->i_ino != attrs->ino ||
> > -		!inode_eq_iversion(inode, attrs->version));
> > +	struct kstat stat;
> > +
> > +	might_sleep();
> > +
> > +	if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> > +		return true;
> > +
> > +	/*
> > +	 * EVM currently relies on backing inode i_version. While IS_I_VERSION
> > +	 * is not a good indicator of i_version support, this still retains
> > +	 * the logic such that a re-evaluation should still occur for EVM, and
> > +	 * only for IMA if vfs_getattr_nosec() fails.
> > +	 */
> > +	if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> > +				       STATX_CHANGE_COOKIE | STATX_CTIME,
> > +				       AT_STATX_SYNC_AS_STAT))
> > +		return !IS_I_VERSION(inode) ||
> > +			!inode_eq_iversion(inode, attrs->version);
> > +
> > +	if (stat.result_mask & STATX_CHANGE_COOKIE)
> > +		return stat.change_cookie != attrs->version;
> > +
> > +	if (stat.result_mask & STATX_CTIME)
> > +		return integrity_ctime_guard(stat) != attrs->version;
> 
> Yes, switching to the new field I guess it works, but I'm wondering if
> we could have more uniformity across the filesystems, otherwise one has
> to use one source for filesystem X, another source for filesystem Y.
> 

That would be wonderful, but we have >50 filesystems in the kernel. A
few filesystems have a real change cookie, but most don't. XFS has a
change cookie, but it doesn't conform to expectations (it changes on
atime changes). Adding a proper change attribute isn't simple since it
usually requires revving an on-disk format.

Most do provide a ctime, however. Traditionally, that hasn't been
granular enough to reliably detect changes that occur over short
intervals, but that changed with the advent of multigrain timestamps.

I'm hoping more filesystems can be converted to use those in the
future, which gives us just as good a granularity to changes as a
change cookie, without having to worry about storing a separate field
on disk. It should be a fairly straightforward conversion for most
disk-based filesystems.

This scheme where we use the CHANGE_COOKIE if it exists and fall back
to the CTIME if it doesn't is really the "gold standard" for detecting
changes for the forseeable future.

> 
> > +
> > +	return true;
> >  }
> >  
> >  
> > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> > index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> > --- a/security/integrity/evm/evm_main.c
> > +++ b/security/integrity/evm/evm_main.c
> > @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
> >  	bool ret = false;
> >  
> >  	if (iint) {
> > -		ret = (!IS_I_VERSION(metadata_inode) ||
> > -		       integrity_inode_attrs_changed(&iint->metadata_inode,
> > -						     metadata_inode));
> > +		ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> > +						    NULL, metadata_inode);
> >  		if (ret)
> >  			iint->evm_status = INTEGRITY_UNKNOWN;
> >  	}
> > diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> > index c35ea613c9f8d404ba4886e3b736c3bab29d1668..8096986f3689781d3cdf6595f330033782f9cc45 100644
> > --- a/security/integrity/ima/ima_api.c
> > +++ b/security/integrity/ima/ima_api.c
> > @@ -272,10 +272,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> >  	 * to an initial measurement/appraisal/audit, but was modified to
> >  	 * assume the file changed.
> >  	 */
> > -	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> > +	result = vfs_getattr_nosec(&file->f_path, &stat,
> > +				   STATX_CHANGE_COOKIE | STATX_CTIME,
> >  				   AT_STATX_SYNC_AS_STAT);
> > -	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> > -		i_version = stat.change_cookie;
> > +	if (!result) {
> > +		if (stat.result_mask & STATX_CHANGE_COOKIE)
> > +			i_version = stat.change_cookie;
> > +		else if (stat.result_mask & STATX_CTIME)
> > +			i_version = integrity_ctime_guard(stat);
> > +	}
> >  	hash.hdr.algo = algo;
> >  	hash.hdr.length = hash_digest_size[algo];
> >  
> > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > index 5770cf691912aa912fc65280c59f5baac35dd725..3a4c32e254f925bba85cb91b63744ac142b3b049 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -22,6 +22,7 @@
> >  #include <linux/mount.h>
> >  #include <linux/mman.h>
> >  #include <linux/slab.h>
> > +#include <linux/stat.h>
> >  #include <linux/xattr.h>
> >  #include <linux/ima.h>
> >  #include <linux/fs.h>
> > @@ -191,18 +192,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
> >  
> >  	mutex_lock(&iint->mutex);
> >  	if (atomic_read(&inode->i_writecount) == 1) {
> > -		struct kstat stat;
> > -
> >  		clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags);
> >  
> >  		update = test_and_clear_bit(IMA_UPDATE_XATTR,
> >  					    &iint->atomic_flags);
> >  		if ((iint->flags & IMA_NEW_FILE) ||
> > -		    vfs_getattr_nosec(&file->f_path, &stat,
> > -				      STATX_CHANGE_COOKIE,
> > -				      AT_STATX_SYNC_AS_STAT) ||
> > -		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> > -		    stat.change_cookie != iint->real_inode.version) {
> > +		    integrity_inode_attrs_changed(&iint->real_inode, file,
> > +						  inode)) {
> >  			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
> >  			iint->measured_pcrs = 0;
> >  			if (update)
> > @@ -328,9 +324,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
> >  	real_inode = d_real_inode(file_dentry(file));
> >  	if (real_inode != inode &&
> >  	    (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> > -		if (!IS_I_VERSION(real_inode) ||
> > -		    integrity_inode_attrs_changed(&iint->real_inode,
> > -						  real_inode)) {
> > +		if (integrity_inode_attrs_changed(&iint->real_inode,
> > +						  file, real_inode)) {
> >  			iint->flags &= ~IMA_DONE_MASK;
> >  			iint->measured_pcrs = 0;
> >  		}
> > 
> > ---
> > base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> > change-id: 20251212-xfs-ima-fixup-931780a62c2c
> > 
> > Best regards,

-- 
Jeff Layton <jlayton@kernel.org>

^ permalink raw reply

* [PATCH 1/2] keys/trusted_keys: fix handle passed to tpm_buf_append_name during unseal
From: Srish Srinivasan @ 2026-01-23 16:55 UTC (permalink / raw)
  To: linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	zohar, nayna, stefanb, rnsastry, linux-kernel,
	linux-security-module, ssrish
In-Reply-To: <20260123165504.461607-1-ssrish@linux.ibm.com>

TPM2_Unseal[1] expects the handle of a loaded data object, and not the
handle of the parent key. But the tpm2_unseal_cmd provides the parent
keyhandle instead of blob_handle for the session HMAC calculation. This
causes unseal to fail.

Fix this by passing blob_handle to tpm_buf_append_name().

Fixes: 6e9722e9a7bf ("tpm2-sessions: Fix out of range indexing in name_size")

References:
[1] trustedcomputinggroup.org/wp-content/uploads/
    Trusted-Platform-Module-2.0-Library-Part-3-Version-184_pub.pdf

Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
 security/keys/trusted-keys/trusted_tpm2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index a7ea4a1c3bed..6340823f8b53 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -465,7 +465,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 }
 
 /**
- * tpm2_unseal_cmd() - execute a TPM2_Unload command
+ * tpm2_unseal_cmd() - execute a TPM2_Unseal command
  *
  * @chip: TPM chip to use
  * @payload: the key data in clear and encrypted form
@@ -498,7 +498,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 		return rc;
 	}
 
-	rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
+	rc = tpm_buf_append_name(chip, &buf, blob_handle, NULL);
 	if (rc)
 		goto out;
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/2] move TPM-specific fields into trusted_tpm_options
From: Srish Srinivasan @ 2026-01-23 16:55 UTC (permalink / raw)
  To: linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	zohar, nayna, stefanb, rnsastry, linux-kernel,
	linux-security-module, ssrish

A recently posted patch series titled 'Extend "trusted" keys to support
a new trust source named the PowerVM Key Wrapping Module (PKWM)'
introduced a change in the handling of backend-specific fields in the
backend agnostic trusted_key_options structure. However, there are a
number of TPM-specific fields that are residing in trusted_key_options
and they have not been migrated yet.

This patch series intends to move all TPM-spcific fields out of
trusted_key_options into a newly defined trusted_tpm_options structure.
A pointer to the trusted_tpm_options struct is stored in
trusted_key_option's private.

Along with the migration of TPM-specific fields, this patch series includes
a preparatory bug-fix patch: passing the blob_handle to tpm_buf_append_name
during TPM2_Unseal instead of the keyhandle.

This patch series has been validated against both TPM 1.2 and TPM 2.0
trusted-key backends using a vTPM environment, on x86_64 and ppc64le.
Testing included key creation, loading, resealing (TPM 2.0), key revocation
, unlinking, invalidation, and reloading trusted keys from encrypted blobs.
I would welcome any additional testing from upstream to further strengthen
the validation.

This patch series is intended to be applied on top of the PKWM trusted-keys
series posted earlier [1], which introduces a pointer named private in the
trusted_key_options structure to handle backend-specific fields.

Srish Srinivasan (2):
  keys/trusted_keys: fix handle passed to tpm_buf_append_name during
    unseal
  keys/trusted_keys: move TPM-specific fields into trusted_tpm_options

[1]
lore.kernel.org/linuxppc-dev/20260115100504.488665-1-ssrish@linux.ibm.com/T

 include/keys/trusted-type.h               |  11 ---
 include/keys/trusted_tpm.h                |  14 +++
 security/keys/trusted-keys/trusted_tpm1.c | 103 ++++++++++++++--------
 security/keys/trusted-keys/trusted_tpm2.c |  66 +++++++++-----
 4 files changed, 123 insertions(+), 71 deletions(-)

-- 
2.43.0


^ permalink raw reply

* [PATCH 2/2] keys/trusted_keys: move TPM-specific fields into trusted_tpm_options
From: Srish Srinivasan @ 2026-01-23 16:55 UTC (permalink / raw)
  To: linux-integrity, keyrings, linuxppc-dev
  Cc: maddy, mpe, npiggin, christophe.leroy, James.Bottomley, jarkko,
	zohar, nayna, stefanb, rnsastry, linux-kernel,
	linux-security-module, ssrish
In-Reply-To: <20260123165504.461607-1-ssrish@linux.ibm.com>

The trusted_key_options struct contains TPM-specific fields (keyhandle,
keyauth, blobauth_len, blobauth, pcrinfo_len, pcrinfo, pcrlock, hash,
policydigest_len, policydigest, and policyhandle). This leads to the
accumulation of backend-specific fields in the generic options structure.

Define trusted_tpm_options structure and move the TPM-specific fields
there. Store a pointer to trusted_tpm_options in trusted_key_options's
private.

No functional change intended.

Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
 include/keys/trusted-type.h               |  11 ---
 include/keys/trusted_tpm.h                |  14 +++
 security/keys/trusted-keys/trusted_tpm1.c | 103 ++++++++++++++--------
 security/keys/trusted-keys/trusted_tpm2.c |  62 ++++++++-----
 4 files changed, 121 insertions(+), 69 deletions(-)

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index 03527162613f..b80f250305b8 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -39,17 +39,6 @@ struct trusted_key_payload {
 
 struct trusted_key_options {
 	uint16_t keytype;
-	uint32_t keyhandle;
-	unsigned char keyauth[TPM_DIGEST_SIZE];
-	uint32_t blobauth_len;
-	unsigned char blobauth[TPM_DIGEST_SIZE];
-	uint32_t pcrinfo_len;
-	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
-	int pcrlock;
-	uint32_t hash;
-	uint32_t policydigest_len;
-	unsigned char policydigest[MAX_DIGEST_SIZE];
-	uint32_t policyhandle;
 	void *private;
 };
 
diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h
index 0fadc6a4f166..355ebd36cbfd 100644
--- a/include/keys/trusted_tpm.h
+++ b/include/keys/trusted_tpm.h
@@ -7,6 +7,20 @@
 
 extern struct trusted_key_ops trusted_key_tpm_ops;
 
+struct trusted_tpm_options {
+	uint32_t keyhandle;
+	unsigned char keyauth[TPM_DIGEST_SIZE];
+	uint32_t blobauth_len;
+	unsigned char blobauth[TPM_DIGEST_SIZE];
+	uint32_t pcrinfo_len;
+	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+	int pcrlock;
+	uint32_t hash;
+	uint32_t policydigest_len;
+	unsigned char policydigest[MAX_DIGEST_SIZE];
+	uint32_t policyhandle;
+};
+
 int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options);
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index 636acb66a4f6..0ab0234ebe37 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -50,12 +50,14 @@ enum {
 #if TPM_DEBUG
 static inline void dump_options(struct trusted_key_options *o)
 {
+	struct trusted_tpm_options *tpm_opts = o->private;
+
 	pr_info("sealing key type %d\n", o->keytype);
-	pr_info("sealing key handle %0X\n", o->keyhandle);
-	pr_info("pcrlock %d\n", o->pcrlock);
-	pr_info("pcrinfo %d\n", o->pcrinfo_len);
+	pr_info("sealing key handle %0X\n", tpm_opts->keyhandle);
+	pr_info("pcrlock %d\n", tpm_opts->pcrlock);
+	pr_info("pcrinfo %d\n", tpm_opts->pcrinfo_len);
 	print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
-		       16, 1, o->pcrinfo, o->pcrinfo_len, 0);
+		       16, 1, tpm_opts->pcrinfo, tpm_opts->pcrinfo_len, 0);
 }
 
 static inline void dump_sess(struct osapsess *s)
@@ -624,6 +626,7 @@ static int tpm_unseal(struct tpm_buf *tb,
 static int key_seal(struct trusted_key_payload *p,
 		    struct trusted_key_options *o)
 {
+	struct trusted_tpm_options *tpm_opts;
 	struct tpm_buf tb;
 	int ret;
 
@@ -634,9 +637,12 @@ static int key_seal(struct trusted_key_payload *p,
 	/* include migratable flag at end of sealed key */
 	p->key[p->key_len] = p->migratable;
 
-	ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,
+	tpm_opts = o->private;
+
+	ret = tpm_seal(&tb, o->keytype, tpm_opts->keyhandle, tpm_opts->keyauth,
 		       p->key, p->key_len + 1, p->blob, &p->blob_len,
-		       o->blobauth, o->pcrinfo, o->pcrinfo_len);
+		       tpm_opts->blobauth, tpm_opts->pcrinfo,
+		       tpm_opts->pcrinfo_len);
 	if (ret < 0)
 		pr_info("srkseal failed (%d)\n", ret);
 
@@ -650,6 +656,7 @@ static int key_seal(struct trusted_key_payload *p,
 static int key_unseal(struct trusted_key_payload *p,
 		      struct trusted_key_options *o)
 {
+	struct trusted_tpm_options *tpm_opts;
 	struct tpm_buf tb;
 	int ret;
 
@@ -657,8 +664,10 @@ static int key_unseal(struct trusted_key_payload *p,
 	if (ret)
 		return ret;
 
-	ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
-			 o->blobauth, p->key, &p->key_len);
+	tpm_opts = o->private;
+
+	ret = tpm_unseal(&tb, tpm_opts->keyhandle, tpm_opts->keyauth, p->blob,
+			 p->blob_len, tpm_opts->blobauth, p->key, &p->key_len);
 	if (ret < 0)
 		pr_info("srkunseal failed (%d)\n", ret);
 	else
@@ -695,6 +704,7 @@ static const match_table_t key_tokens = {
 static int getoptions(char *c, struct trusted_key_payload *pay,
 		      struct trusted_key_options *opt)
 {
+	struct trusted_tpm_options *tpm_opts;
 	substring_t args[MAX_OPT_ARGS];
 	char *p = c;
 	int token;
@@ -710,7 +720,9 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 	if (tpm2 < 0)
 		return tpm2;
 
-	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
+	tpm_opts = opt->private;
+
+	tpm_opts->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
 
 	if (!c)
 		return 0;
@@ -724,11 +736,11 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 
 		switch (token) {
 		case Opt_pcrinfo:
-			opt->pcrinfo_len = strlen(args[0].from) / 2;
-			if (opt->pcrinfo_len > MAX_PCRINFO_SIZE)
+			tpm_opts->pcrinfo_len = strlen(args[0].from) / 2;
+			if (tpm_opts->pcrinfo_len > MAX_PCRINFO_SIZE)
 				return -EINVAL;
-			res = hex2bin(opt->pcrinfo, args[0].from,
-				      opt->pcrinfo_len);
+			res = hex2bin(tpm_opts->pcrinfo, args[0].from,
+				      tpm_opts->pcrinfo_len);
 			if (res < 0)
 				return -EINVAL;
 			break;
@@ -737,12 +749,12 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			if (res < 0)
 				return -EINVAL;
 			opt->keytype = SEAL_keytype;
-			opt->keyhandle = handle;
+			tpm_opts->keyhandle = handle;
 			break;
 		case Opt_keyauth:
 			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
 				return -EINVAL;
-			res = hex2bin(opt->keyauth, args[0].from,
+			res = hex2bin(tpm_opts->keyauth, args[0].from,
 				      SHA1_DIGEST_SIZE);
 			if (res < 0)
 				return -EINVAL;
@@ -753,21 +765,23 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			 * hex strings.  TPM 2.0 authorizations are simple
 			 * passwords (although it can take a hash as well)
 			 */
-			opt->blobauth_len = strlen(args[0].from);
+			tpm_opts->blobauth_len = strlen(args[0].from);
 
-			if (opt->blobauth_len == 2 * TPM_DIGEST_SIZE) {
-				res = hex2bin(opt->blobauth, args[0].from,
+			if (tpm_opts->blobauth_len == 2 * TPM_DIGEST_SIZE) {
+				res = hex2bin(tpm_opts->blobauth, args[0].from,
 					      TPM_DIGEST_SIZE);
 				if (res < 0)
 					return -EINVAL;
 
-				opt->blobauth_len = TPM_DIGEST_SIZE;
+				tpm_opts->blobauth_len = TPM_DIGEST_SIZE;
 				break;
 			}
 
-			if (tpm2 && opt->blobauth_len <= sizeof(opt->blobauth)) {
-				memcpy(opt->blobauth, args[0].from,
-				       opt->blobauth_len);
+			if (tpm2 &&
+			    tpm_opts->blobauth_len <=
+				sizeof(tpm_opts->blobauth)) {
+				memcpy(tpm_opts->blobauth, args[0].from,
+				       tpm_opts->blobauth_len);
 				break;
 			}
 
@@ -785,14 +799,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			res = kstrtoul(args[0].from, 10, &lock);
 			if (res < 0)
 				return -EINVAL;
-			opt->pcrlock = lock;
+			tpm_opts->pcrlock = lock;
 			break;
 		case Opt_hash:
 			if (test_bit(Opt_policydigest, &token_mask))
 				return -EINVAL;
 			for (i = 0; i < HASH_ALGO__LAST; i++) {
 				if (!strcmp(args[0].from, hash_algo_name[i])) {
-					opt->hash = i;
+					tpm_opts->hash = i;
 					break;
 				}
 			}
@@ -804,14 +818,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			}
 			break;
 		case Opt_policydigest:
-			digest_len = hash_digest_size[opt->hash];
+			digest_len = hash_digest_size[tpm_opts->hash];
 			if (!tpm2 || strlen(args[0].from) != (2 * digest_len))
 				return -EINVAL;
-			res = hex2bin(opt->policydigest, args[0].from,
+			res = hex2bin(tpm_opts->policydigest, args[0].from,
 				      digest_len);
 			if (res < 0)
 				return -EINVAL;
-			opt->policydigest_len = digest_len;
+			tpm_opts->policydigest_len = digest_len;
 			break;
 		case Opt_policyhandle:
 			if (!tpm2)
@@ -819,7 +833,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			res = kstrtoul(args[0].from, 16, &handle);
 			if (res < 0)
 				return -EINVAL;
-			opt->policyhandle = handle;
+			tpm_opts->policyhandle = handle;
 			break;
 		default:
 			return -EINVAL;
@@ -830,6 +844,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 
 static struct trusted_key_options *trusted_options_alloc(void)
 {
+	struct trusted_tpm_options *tpm_opts;
 	struct trusted_key_options *options;
 	int tpm2;
 
@@ -842,14 +857,23 @@ static struct trusted_key_options *trusted_options_alloc(void)
 		/* set any non-zero defaults */
 		options->keytype = SRK_keytype;
 
-		if (!tpm2)
-			options->keyhandle = SRKHANDLE;
+		tpm_opts = kzalloc(sizeof(*tpm_opts), GFP_KERNEL);
+		if (!tpm_opts) {
+			kfree_sensitive(options);
+			options = NULL;
+		} else {
+			if (!tpm2)
+				tpm_opts->keyhandle = SRKHANDLE;
+
+			options->private = tpm_opts;
+		}
 	}
 	return options;
 }
 
 static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
 {
+	struct trusted_tpm_options *tpm_opts = NULL;
 	struct trusted_key_options *options = NULL;
 	int ret = 0;
 	int tpm2;
@@ -867,7 +891,9 @@ static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
 		goto out;
 	dump_options(options);
 
-	if (!options->keyhandle && !tpm2) {
+	tpm_opts = options->private;
+
+	if (!tpm_opts->keyhandle && !tpm2) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -881,20 +907,22 @@ static int trusted_tpm_seal(struct trusted_key_payload *p, char *datablob)
 		goto out;
 	}
 
-	if (options->pcrlock) {
-		ret = pcrlock(options->pcrlock);
+	if (tpm_opts->pcrlock) {
+		ret = pcrlock(tpm_opts->pcrlock);
 		if (ret < 0) {
 			pr_info("pcrlock failed (%d)\n", ret);
 			goto out;
 		}
 	}
 out:
+	kfree_sensitive(options->private);
 	kfree_sensitive(options);
 	return ret;
 }
 
 static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
 {
+	struct trusted_tpm_options *tpm_opts = NULL;
 	struct trusted_key_options *options = NULL;
 	int ret = 0;
 	int tpm2;
@@ -912,7 +940,9 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
 		goto out;
 	dump_options(options);
 
-	if (!options->keyhandle && !tpm2) {
+	tpm_opts = options->private;
+
+	if (!tpm_opts->keyhandle && !tpm2) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -924,14 +954,15 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob)
 	if (ret < 0)
 		pr_info("key_unseal failed (%d)\n", ret);
 
-	if (options->pcrlock) {
-		ret = pcrlock(options->pcrlock);
+	if (tpm_opts->pcrlock) {
+		ret = pcrlock(tpm_opts->pcrlock);
 		if (ret < 0) {
 			pr_info("pcrlock failed (%d)\n", ret);
 			goto out;
 		}
 	}
 out:
+	kfree_sensitive(options->private);
 	kfree_sensitive(options);
 	return ret;
 }
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 6340823f8b53..568c4af9010c 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -24,6 +24,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
 			   struct trusted_key_options *options,
 			   u8 *src, u32 len)
 {
+	struct trusted_tpm_options *tpm_opts;
 	const int SCRATCH_SIZE = PAGE_SIZE;
 	u8 *scratch = kmalloc(SCRATCH_SIZE, GFP_KERNEL);
 	u8 *work = scratch, *work1;
@@ -46,7 +47,9 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
 	work = asn1_encode_oid(work, end_work, tpm2key_oid,
 			       asn1_oid_len(tpm2key_oid));
 
-	if (options->blobauth_len == 0) {
+	tpm_opts = options->private;
+
+	if (tpm_opts->blobauth_len == 0) {
 		unsigned char bool[3], *w = bool;
 		/* tag 0 is emptyAuth */
 		w = asn1_encode_boolean(w, w + sizeof(bool), true);
@@ -69,7 +72,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
 		goto err;
 	}
 
-	work = asn1_encode_integer(work, end_work, options->keyhandle);
+	work = asn1_encode_integer(work, end_work, tpm_opts->keyhandle);
 	work = asn1_encode_octet_string(work, end_work, pub, pub_len);
 	work = asn1_encode_octet_string(work, end_work, priv, priv_len);
 
@@ -102,6 +105,7 @@ static int tpm2_key_decode(struct trusted_key_payload *payload,
 			   struct trusted_key_options *options,
 			   u8 **buf)
 {
+	struct trusted_tpm_options *tpm_opts;
 	int ret;
 	struct tpm2_key_context ctx;
 	u8 *blob;
@@ -120,8 +124,10 @@ static int tpm2_key_decode(struct trusted_key_payload *payload,
 	if (!blob)
 		return -ENOMEM;
 
+	tpm_opts = options->private;
+
 	*buf = blob;
-	options->keyhandle = ctx.parent;
+	tpm_opts->keyhandle = ctx.parent;
 
 	memcpy(blob, ctx.priv, ctx.priv_len);
 	blob += ctx.priv_len;
@@ -233,6 +239,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options)
 {
+	struct trusted_tpm_options *tpm_opts;
 	off_t offset = TPM_HEADER_SIZE;
 	struct tpm_buf buf, sized;
 	int blob_len = 0;
@@ -240,11 +247,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	u32 flags;
 	int rc;
 
-	hash = tpm2_find_hash_alg(options->hash);
+	tpm_opts = options->private;
+
+	hash = tpm2_find_hash_alg(tpm_opts->hash);
 	if (hash < 0)
 		return hash;
 
-	if (!options->keyhandle)
+	if (!tpm_opts->keyhandle)
 		return -EINVAL;
 
 	rc = tpm_try_get_ops(chip);
@@ -268,18 +277,19 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		goto out_put;
 	}
 
-	rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
+	rc = tpm_buf_append_name(chip, &buf, tpm_opts->keyhandle, NULL);
 	if (rc)
 		goto out;
 
 	tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
-				    options->keyauth, TPM_DIGEST_SIZE);
+				    tpm_opts->keyauth, TPM_DIGEST_SIZE);
 
 	/* sensitive */
-	tpm_buf_append_u16(&sized, options->blobauth_len);
+	tpm_buf_append_u16(&sized, tpm_opts->blobauth_len);
 
-	if (options->blobauth_len)
-		tpm_buf_append(&sized, options->blobauth, options->blobauth_len);
+	if (tpm_opts->blobauth_len)
+		tpm_buf_append(&sized, tpm_opts->blobauth,
+			       tpm_opts->blobauth_len);
 
 	tpm_buf_append_u16(&sized, payload->key_len);
 	tpm_buf_append(&sized, payload->key, payload->key_len);
@@ -292,14 +302,15 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 
 	/* key properties */
 	flags = 0;
-	flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
+	flags |= tpm_opts->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
 	flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT);
 	tpm_buf_append_u32(&sized, flags);
 
 	/* policy */
-	tpm_buf_append_u16(&sized, options->policydigest_len);
-	if (options->policydigest_len)
-		tpm_buf_append(&sized, options->policydigest, options->policydigest_len);
+	tpm_buf_append_u16(&sized, tpm_opts->policydigest_len);
+	if (tpm_opts->policydigest_len)
+		tpm_buf_append(&sized, tpm_opts->policydigest,
+			       tpm_opts->policydigest_len);
 
 	/* public parameters */
 	tpm_buf_append_u16(&sized, TPM_ALG_NULL);
@@ -373,6 +384,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 			 u32 *blob_handle)
 {
 	u8 *blob_ref __free(kfree) = NULL;
+	struct trusted_tpm_options *tpm_opts;
 	struct tpm_buf buf;
 	unsigned int private_len;
 	unsigned int public_len;
@@ -391,8 +403,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 		blob_ref = blob;
 	}
 
+	tpm_opts = options->private;
+
 	/* new format carries keyhandle but old format doesn't */
-	if (!options->keyhandle)
+	if (!tpm_opts->keyhandle)
 		return -EINVAL;
 
 	/* must be big enough for at least the two be16 size counts */
@@ -433,11 +447,11 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
 		return rc;
 	}
 
-	rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
+	rc = tpm_buf_append_name(chip, &buf, tpm_opts->keyhandle, NULL);
 	if (rc)
 		goto out;
 
-	tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
+	tpm_buf_append_hmac_session(chip, &buf, 0, tpm_opts->keyauth,
 				    TPM_DIGEST_SIZE);
 
 	tpm_buf_append(&buf, blob, blob_len);
@@ -481,6 +495,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 			   struct trusted_key_options *options,
 			   u32 blob_handle)
 {
+	struct trusted_tpm_options *tpm_opts;
 	struct tpm_header *head;
 	struct tpm_buf buf;
 	u16 data_len;
@@ -502,10 +517,12 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 	if (rc)
 		goto out;
 
-	if (!options->policyhandle) {
+	tpm_opts = options->private;
+
+	if (!tpm_opts->policyhandle) {
 		tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
-					    options->blobauth,
-					    options->blobauth_len);
+					    tpm_opts->blobauth,
+					    tpm_opts->blobauth_len);
 	} else {
 		/*
 		 * FIXME: The policy session was generated outside the
@@ -518,9 +535,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 		 * could repeat our actions with the exfiltrated
 		 * password.
 		 */
-		tpm2_buf_append_auth(&buf, options->policyhandle,
+		tpm2_buf_append_auth(&buf, tpm_opts->policyhandle,
 				     NULL /* nonce */, 0, 0,
-				     options->blobauth, options->blobauth_len);
+				     tpm_opts->blobauth,
+				     tpm_opts->blobauth_len);
 		if (tpm2_chip_auth(chip)) {
 			tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0);
 		} else  {
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] evm: Use ordered xattrs list to calculate HMAC in evm_init_hmac()
From: Mimi Zohar @ 2026-01-23 19:33 UTC (permalink / raw)
  To: Roberto Sassu, paul, Casey Schaufler
  Cc: linux-integrity, linux-security-module, linux-kernel,
	Roberto Sassu
In-Reply-To: <20260122080717.1772063-1-roberto.sassu@huaweicloud.com>

On Thu, 2026-01-22 at 09:07 +0100, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Commit 8e5d9f916a96 ("smack: deduplicate xattr setting in
> smack_inode_init_security()") introduced xattr_dupval() to simplify setting
> the xattrs to be provided by the SMACK LSM on inode creation, in the
> smack_inode_init_security().
> 
> Unfortunately, moving lsm_get_xattr_slot() caused the SMACK64TRANSMUTE
> xattr be added in the array of new xattrs before SMACK64. This causes the
> HMAC of xattrs calculated by evm_init_hmac() for new files to diverge from
> the one calculated by both evm_calc_hmac_or_hash() and evmctl.
> 
> evm_init_hmac() calculates the HMAC of the xattrs of new files based on the
> order LSMs provide them, while evm_calc_hmac_or_hash() and evmctl calculate
> the HMAC based on an ordered xattrs list.
> 
> Fix the issue by making evm_init_hmac() calculate the HMAC of new files
> based on the ordered xattrs list too.
> 
> Fixes: 8e5d9f916a96 ("smack: deduplicate xattr setting in smack_inode_init_security()")
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>

Thanks, Roberto.  The patch is now queued in next-integrity.

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC] Refactor LSM hooks for VFS mount operations
From: Song Liu @ 2026-01-23 20:23 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Paul Moore, bpf, Linux-Fsdevel, lsf-pc, linux-security-module,
	Christian Brauner, Al Viro
In-Reply-To: <633aa038-4356-4db3-b61f-191cf56c73b4@schaufler-ca.com>

Hi Casey,

On Thu, Jan 22, 2026 at 6:38 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
[...]
> > Could you please share more information about this issue?
>
> LSMs assume that any mount options passed to them are options
> they provide. If an option isn't recognized, it's an error. If
> two LSMs provide mount options the first will report an error for
> a mount option recognized by the second. Since hook processing
> uses a "bail on fail" model, the second LSM will never be called
> to process its options and the mount operation will fail.
>
> The option processing needs to change to allow option processing
> in an LSM to differentiate between a failure in processing its
> options from finding an unrecognized option. The infrastructure
> needs to be changed to allow for multiple LSMs to look at the
> options and only fail if none of them handle the options.

Thanks for the explanation!

This issue is indeed tricky. Since we are talking about to major
refactoring of LSM hooks around mount operations, it is good
timing to also solve this issue. I will look more into this.

Song

^ permalink raw reply

* Re: [RFC PATCH 2/2] landlock: transpose the layer masks data structure
From: Günther Noack @ 2026-01-23 22:11 UTC (permalink / raw)
  To: Tingmao Wang
  Cc: Mickaël Salaün, Justin Suess, linux-security-module,
	Samasth Norway Ananda, Matthieu Buffet, Mikhail Ivanov,
	konstantin.meskhidze
In-Reply-To: <6a789aa9-c479-43f9-ac24-bc227f8388c6@maowtm.org>

On Wed, Jan 21, 2026 at 12:26:52AM +0000, Tingmao Wang wrote:
> On 12/30/25 10:39, Günther Noack wrote:
> > The layer masks data structure tracks the requested but unfulfilled
> > access rights during an operations security check.  It stores one bit
> > for each combination of access right and layer index.  If the bit is
> > set, that access right is not granted (yet) in the given layer and we
> > have to traverse the path further upwards to grant it.
> > 
> > Previously, the layer masks were stored as arrays mapping from access
> > right indices to layer_mask_t.  The layer_mask_t value then indicates
> > all layers in which the given access right is still (tentatively)
> > denied.
> > 
> > This patch introduces struct layer_access_masks instead: This struct
> > contains an array with the access_mask_t of each (tentatively) denied
> > access right in that layer.
> > 
> > The hypothesis of this patch is that this simplifies the code enough
> > so that the resulting code will run faster:
> > 
> > * We can use bitwise operations in multiple places where we previously
> >   looped over bits individually with macros.  (Should require less
> >   branch speculation)
> > 
> > * Code is ~160 lines smaller.
> > 
> > Other noteworthy changes:
> > 
> > * Clarify deny_mask_t and the code assembling it.
> >   * Document what that value looks like
> >   * Make writing and reading functions specific to file system rules.
> >     (It only worked for FS rules before as well, but going all the way
> >     simplifies the code logic more.)
> 
> In the original commit message that added this type [1] there was this
> statement:
> 
> > Implementing deny_masks_t with a bitfield instead of a struct enables a
> > generic implementation to store and extract layer levels.
> 
> At some point when looking at this I was wondering why this wasn't a
> struct with 2 u8:4 fields, but rather, a u8 with bit manipulation code.
> While it is possible that I might have just misunderstood it, reading the
> above statement my take-away was that a struct would have forced us to
> address the indices with specific names, e.g. it would need to be defined
> like
> 
> struct deny_masks_t {
>     u8 ioctl:4;
>     u8 truncate:4;
> }
> 
> And it would thus not be possible to manipulate the indices in a generic
> way (e.g. the way it was implemented before, given
> all_existing_optional_access and access_bit, read and write the right
> bits).
> 
> However, since we're now removing that generic-ability, should we consider
> turning it into a struct?  (If later on we have different access types
> that also have optional accesses, we could use a union of structs)

I could not agree more, I also think a struct would be better, and
also rolling it out per access right type is not something I am afraid
of.  I remarked on it in
https://lore.kernel.org/all/20260111.11c57c607174@gnoack.org/

But as Mickaël pointed out in
https://lore.kernel.org/all/20260120.haeCh4li9Vae@digikod.net/, my
endeavors to change the deny masks data type are a bit too intertwined
with the refactoring of transposing the layer masks.  I'll try to
decouple these two changes from each other and send the deny masks
change as a follow-up.


> btw, since this causes conflicts with the quiet flag series and Mickaël
> has indicated that this should be merged first, I will probably have to
> make my series based on top of this.  Will watch this series to see if
> there are more changes.
> 
> Also, this transpose and code simplification should also simplify the
> mutable domains work so thanks for the refactor!

Thanks, I am glad it helps and does not only cause merge conflicts! :)


> A while ago I also made some benchmarking script which I sent a PR to
> landlock-test-tools [2], and earlier I tested this patch with it, and saw
> some improvement (but it was much less in terms of percentage, which may
> be due to the lower directory depth, or may be due to other unknown
> reason):
> 
> TestDescription(landlock=True, dir_depth=10, nb_extra_rules=10)
>   base.2:
>     c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=1718.15, min=1663.00, max=275949.00, median=1696.46, stddev=437.52
>     95% confidence interval: [1718.03 .. 1718.28]
>   Estimated landlock overhead (vs no-landlock): 226.5%
>   48bd90e91fe6.2:
>     c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=1709.60, min=1633.00, max=280608.00, median=1688.83, stddev=441.83
>     95% confidence interval: [1709.48 .. 1709.73]
>     ** Improved 0.5% **
>          ...
>       [1660 .. 1669]:                                             [1660 .. 1669]: ###                                     
>       [1670 .. 1679]: ##                                          [1670 .. 1679]: ###############                         
>       [1680 .. 1689]: ######################                      [1680 .. 1689]: #################################       
>       [1690 .. 1699]: ########################################    [1690 .. 1699]: ##################################      
>       [1700 .. 1709]: ############################                [1700 .. 1709]: #############                           
>       [1710 .. 1719]: #########                                   [1710 .. 1719]: ##                                      
>       [1720 .. 1729]: ##                                          [1720 .. 1729]:                                         
>          ...
>     Estimated landlock overhead (vs no-landlock): 223.0%
> 
> TestDescription(landlock=True, dir_depth=29, nb_extra_rules=10)
>   base.2:
>     c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=3869.66, min=3727.00, max=272563.00, median=3813.42, stddev=666.18
>     95% confidence interval: [3869.47 .. 3869.86]
>   Estimated landlock overhead (vs no-landlock): 427.3%
>   48bd90e91fe6.2:
>     c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=3855.61, min=3697.00, max=271690.00, median=3804.82, stddev=682.74
>     95% confidence interval: [3855.41 .. 3855.81]
>     ** Improved 0.4% **
>          ...
>       [3750 ..   3759]:                                             [3750 ..   3759]: #                                       
>       [3760 ..   3769]:                                             [3760 ..   3769]: #######                                 
>       [3770 ..   3779]:                                             [3770 ..   3779]: ###############                         
>       [3780 ..   3789]: ####                                        [3780 ..   3789]: ###################                     
>       [3790 ..   3799]: ###################                         [3790 ..   3799]: ###################                     
>       [3800 ..   3809]: ######################################      [3800 ..   3809]: ########################                
>       [3810 ..   3819]: ########################################    [3810 ..   3819]: ############################            
>       [3820 ..   3829]: ##########################                  [3820 ..   3829]: #####################                   
>       [3830 ..   3839]: #############                               [3830 ..   3839]: #########                               
>       [3840 ..   3849]: ######                                      [3840 ..   3849]: ##                                      
>       [3850 ..   3859]: ##                                          [3850 ..   3859]:                                         
>       [3860 ..   3869]:                                             [3860 ..   3869]:                                         
>       [3870 ..   3879]:                                             [3870 ..   3879]:                                         
>       ...
>       [4980 ..   4989]:                                             [4980 ..   4989]:                                         
>       [4990 ..   4999]:                                             [4990 ..   4999]:                                         
>       [5000 .. 272563]: #                                           [5000 .. 271690]: #                                       
>     Estimated landlock overhead (vs no-landlock): 424.2%
> 
> Full data including test with 0 depth, or 1000 rules:
> https://fileshare.maowtm.org/landlock-20251230/index.html

Ooh, awesome, thanks for the measurements! :)

The tool I used to benchmark myself [1] is much more crude.  It
purposefully constructs an uncharacteristically bad scenario, to
amplify the performance difference and to make it more measurable.

It creates 10000 nested subdirectories, with a rule for each, so that
landlock_unmask_layers() gets called 10000 times per attempted access
in the innermost directory.

[1] https://lore.kernel.org/all/20251230.d4bf391b98c5@gnoack.org/

–Günther

^ permalink raw reply

* Re: [PATCH] landlock: fix struct layer_access_masks kernel-doc
From: Günther Noack @ 2026-01-23 22:29 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: linux-kernel, Mickaël Salaün, linux-security-module,
	Paul Moore, James Morris, Serge E. Hallyn
In-Reply-To: <20260123025121.3713403-1-rdunlap@infradead.org>

On Thu, Jan 22, 2026 at 06:51:19PM -0800, Randy Dunlap wrote:
> Use the correct struct name and describe the struct member in
> kernel-doc notation to prevent kernel-doc warnings.
> 
> WARNING: ../security/landlock/ruleset.h:313 expecting prototype for
>   struct layer_accesses. Prototype was for struct layer_access_masks instead
> 
> Fixes: 1ebf8e8d3245 ("landlock: Transpose the layer masks data structure")
> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
> ---
> Something like this is needed. Feel free to massage/correct it some.

The code that ended up in linux-next is an ongoing patch set and was
not the final version yet, so I'll take the liberty to include a
rewritten and fixed documentation in that place in the next patch set
version (I'll CC you).
https://lore.kernel.org/all/20251230103917.10549-3-gnoack3000@gmail.com/

Thank you for spotting this so quickly! We had actually overlooked it
in the code review so far.

–Günther

^ permalink raw reply

* Re: [PATCH 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Coiby Xu @ 2026-01-24  0:18 UTC (permalink / raw)
  To: Ard Biesheuvel, Mimi Zohar
  Cc: Dave Hansen, linux-integrity, Heiko Carstens, Roberto Sassu,
	Catalin Marinas, Will Deacon, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
	Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
	H. Peter Anvin, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	Paul Moore, James Morris, Serge E. Hallyn, Jarkko Sakkinen,
	moderated list:ARM64 PORT (AARCH64 ARCHITECTURE), open list,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	open list:S390 ARCHITECTURE,
	open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
	open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <CAMj1kXFBMSEdRL8FotASbQO3dcfNG0bpp9Vnm5JPn-yjyDr=GA@mail.gmail.com>

On Wed, Jan 21, 2026 at 05:25:39PM +0100, Ard Biesheuvel wrote:
>On Wed, 21 Jan 2026 at 16:41, Mimi Zohar <zohar@linux.ibm.com> wrote:
>>
>> On Mon, 2026-01-19 at 12:04 +0800, Coiby Xu wrote:
>>
>> > diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
>> > index 976e75f9b9ba..5dce572192d6 100644
>> > --- a/security/integrity/ima/Kconfig
>> > +++ b/security/integrity/ima/Kconfig
>> > @@ -311,6 +311,7 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
>> >   config IMA_SECURE_AND_OR_TRUSTED_BOOT
>> >          bool
>> >          depends on IMA_ARCH_POLICY
>> > +       depends on INTEGRITY_SECURE_BOOT
>> >
>> >
>> > Another idea is make a tree-wide arch_get_secureboot i.e. to move
>> > current arch_ima_get_secureboot code to arch-specific secure boot
>> > implementation. By this way, there will no need for a new Kconfig option
>> > INTEGRITY_SECURE_BOOT. But I'm not sure if there is any unforeseen
>> > concern.
>>
>> Originally basing IMA policy on the secure boot mode was an exception.  As long
>> as making it public isn't an issue any longer, this sounds to me.  Ard, Dave, do
>> you have any issues with replacing arch_ima_get_secureboot() with
>> arch_get_secureboot()?
>
>I don't see an issue with that. If there is a legitimate need to
>determine this even if IMA is not enabled, then this makes sense.

Thanks for the confirmation! Here's the updated patch
https://github.com/coiby/linux/commit/c222c1d08d90ef1ec85ef81ece90afc9efde7937.patch

If there is no objection, I'll send v2.

-- 
Best regards,
Coiby


^ permalink raw reply

* [syzbot] [lsm?] [input?] [usb?] memory leak in prepare_creds (6)
From: syzbot @ 2026-01-24  4:11 UTC (permalink / raw)
  To: linux-input, linux-kernel, linux-security-module, linux-usb, paul,
	sergeh, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    6c790212c588 Merge tag 'devicetree-fixes-for-6.19-3' of gi..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=16019d22580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=9d7d0fbecb37bff8
dashboard link: https://syzkaller.appspot.com/bug?extid=dd3b43aa0204089217ee
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=117a579a580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=118ef852580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/1ceba1c1c7bd/disk-6c790212.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d83b71fd8384/vmlinux-6c790212.xz
kernel image: https://storage.googleapis.com/syzbot-assets/07ef6040f444/bzImage-6c790212.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+dd3b43aa0204089217ee@syzkaller.appspotmail.com

BUG: memory leak
unreferenced object 0xffff888108b89480 (size 184):
  comm "syz-executor", pid 5994, jiffies 4294943386
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  backtrace (crc 369454a7):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    kmem_cache_alloc_noprof+0x412/0x580 mm/slub.c:5270
    prepare_creds+0x22/0x600 kernel/cred.c:185
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

BUG: memory leak
unreferenced object 0xffff8881032ee1a0 (size 32):
  comm "syz-executor", pid 5994, jiffies 4294943386
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    f8 52 86 00 81 88 ff ff 00 00 00 00 00 00 00 00  .R..............
  backtrace (crc 336e1c5f):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    __do_kmalloc_node mm/slub.c:5656 [inline]
    __kmalloc_noprof+0x465/0x680 mm/slub.c:5669
    kmalloc_noprof include/linux/slab.h:961 [inline]
    kzalloc_noprof include/linux/slab.h:1094 [inline]
    lsm_blob_alloc+0x4d/0x80 security/security.c:192
    lsm_cred_alloc security/security.c:209 [inline]
    security_prepare_creds+0x2d/0x290 security/security.c:2763
    prepare_creds+0x395/0x600 kernel/cred.c:215
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

BUG: memory leak
unreferenced object 0xffff888108b89540 (size 184):
  comm "syz-executor", pid 5994, jiffies 4294943447
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  backtrace (crc 17b2a574):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    kmem_cache_alloc_noprof+0x412/0x580 mm/slub.c:5270
    prepare_creds+0x22/0x600 kernel/cred.c:185
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

BUG: memory leak
unreferenced object 0xffff8881032eee80 (size 32):
  comm "syz-executor", pid 5994, jiffies 4294943447
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    f8 52 86 00 81 88 ff ff 00 00 00 00 00 00 00 00  .R..............
  backtrace (crc 336e1c5f):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    __do_kmalloc_node mm/slub.c:5656 [inline]
    __kmalloc_noprof+0x465/0x680 mm/slub.c:5669
    kmalloc_noprof include/linux/slab.h:961 [inline]
    kzalloc_noprof include/linux/slab.h:1094 [inline]
    lsm_blob_alloc+0x4d/0x80 security/security.c:192
    lsm_cred_alloc security/security.c:209 [inline]
    security_prepare_creds+0x2d/0x290 security/security.c:2763
    prepare_creds+0x395/0x600 kernel/cred.c:215
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

BUG: memory leak
unreferenced object 0xffff888109bf16c0 (size 184):
  comm "syz-executor", pid 5994, jiffies 4294943507
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  backtrace (crc a1f2f9ed):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    kmem_cache_alloc_noprof+0x412/0x580 mm/slub.c:5270
    prepare_creds+0x22/0x600 kernel/cred.c:185
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

BUG: memory leak
unreferenced object 0xffff888109151e00 (size 32):
  comm "syz-executor", pid 5994, jiffies 4294943507
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    f8 52 86 00 81 88 ff ff 00 00 00 00 00 00 00 00  .R..............
  backtrace (crc 336e1c5f):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4958 [inline]
    slab_alloc_node mm/slub.c:5263 [inline]
    __do_kmalloc_node mm/slub.c:5656 [inline]
    __kmalloc_noprof+0x465/0x680 mm/slub.c:5669
    kmalloc_noprof include/linux/slab.h:961 [inline]
    kzalloc_noprof include/linux/slab.h:1094 [inline]
    lsm_blob_alloc+0x4d/0x80 security/security.c:192
    lsm_cred_alloc security/security.c:209 [inline]
    security_prepare_creds+0x2d/0x290 security/security.c:2763
    prepare_creds+0x395/0x600 kernel/cred.c:215
    copy_creds+0x44/0x290 kernel/cred.c:286
    copy_process+0x7a7/0x2870 kernel/fork.c:2086
    kernel_clone+0xac/0x6e0 kernel/fork.c:2651
    __do_sys_clone+0x7f/0xb0 kernel/fork.c:2792
    do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
    do_syscall_64+0xa4/0xf80 arch/x86/entry/syscall_64.c:94
    entry_SYSCALL_64_after_hwframe+0x77/0x7f

connection error: failed to recv *flatrpc.ExecutorMessageRawT: EOF


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* Re: [PATCH v4 4/6] pseries/plpks: add HCALLs for PowerVM Key Wrapping Module
From: Christophe Leroy (CS GROUP) @ 2026-01-24 10:03 UTC (permalink / raw)
  To: Nayna Jain, Srish Srinivasan, linux-integrity, keyrings,
	linuxppc-dev
  Cc: maddy, mpe, npiggin, James.Bottomley, jarkko, zohar, rnsastry,
	linux-kernel, linux-security-module
In-Reply-To: <5b29327e-9175-416f-b34b-da4f6ac03a96@linux.ibm.com>



Le 15/01/2026 à 21:45, Nayna Jain a écrit :
> 
> On 1/15/26 5:05 AM, Srish Srinivasan wrote:
>> The hypervisor generated wrapping key is an AES-GCM-256 symmetric key 
>> which
>> is stored in a non-volatile, secure, and encrypted storage called the 
>> Power
>> LPAR Platform KeyStore. It has policy based protections that prevent it
>> from being read out or exposed to the user.
>>
>> Implement H_PKS_GEN_KEY, H_PKS_WRAP_OBJECT, and H_PKS_UNWRAP_OBJECT 
>> HCALLs
>> to enable using the PowerVM Key Wrapping Module (PKWM) as a new trust
>> source for trusted keys. Disallow H_PKS_READ_OBJECT, H_PKS_SIGNED_UPDATE,
>> and H_PKS_WRITE_OBJECT for objects with the 'wrapping key' policy set.
>> Capture the availability status for the H_PKS_WRAP_OBJECT interface.
> 
> Reviewed-by: Nayna Jain <nayna@linux.ibm.com>
>>
>> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
>> ---
>>   Documentation/arch/powerpc/papr_hcalls.rst |  43 +++
>>   arch/powerpc/include/asm/plpks.h           |  10 +
>>   arch/powerpc/platforms/pseries/plpks.c     | 342 ++++++++++++++++++++-
>>   3 files changed, 393 insertions(+), 2 deletions(-)

[...]

>> diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/ 
>> platforms/pseries/plpks.c
>> index 4a08f51537c8..b97b7750f6a8 100644
>> --- a/arch/powerpc/platforms/pseries/plpks.c
>> +++ b/arch/powerpc/platforms/pseries/plpks.c
>> @@ -9,6 +9,32 @@
>>   #define pr_fmt(fmt) "plpks: " fmt
>> +#define PLPKS_WRAPKEY_COMPONENT    "PLPKSWR"
>> +#define PLPKS_WRAPKEY_NAME    "default-wrapping-key"
>> +
>> +/*
>> + * To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
>> + */
>> +#define PLPKS_WRAPPING_BUF_ALIGN    4096
>> +
>> +/*
>> + * To ensure the output buffer's length is at least 1024 bytes greater
>> + * than the input buffer's length during the WRAP H_CALL
>> + */
>> +#define PLPKS_WRAPPING_BUF_DIFF    1024
>> +
>> +#define PLPKS_WRAP_INTERFACE_BIT    3
>> +#define PLPKS_WRAPPING_KEY_LENGTH    32
>> +
>> +#define WRAPFLAG_BE_BIT_SET(be_bit) \
>> +    BIT_ULL(63 - (be_bit))
>> +
>> +#define WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo) \
>> +    GENMASK_ULL(63 - (be_bit_hi), 63 - (be_bit_lo))
>> +
>> +#define WRAPFLAG_BE_FIELD_PREP(be_bit_hi, be_bit_lo, val) \
>> +    FIELD_PREP(WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo), (val))

I get following build failure:

   CC      arch/powerpc/platforms/pseries/plpks.o
arch/powerpc/platforms/pseries/plpks.c: In function 'plpks_wrap_object':
arch/powerpc/platforms/pseries/plpks.c:36:9: error: implicit declaration 
of function 'FIELD_PREP' [-Werror=implicit-function-declaration]
    36 |         FIELD_PREP(WRAPFLAG_BE_GENMASK(be_bit_hi, be_bit_lo), 
(val))
       |         ^~~~~~~~~~
arch/powerpc/platforms/pseries/plpks.c:1049:25: note: in expansion of 
macro 'WRAPFLAG_BE_FIELD_PREP'
  1049 |         objwrapflags |= WRAPFLAG_BE_FIELD_PREP(60, 63, 0x1);
       |                         ^~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors


>> +
>>   #include <linux/delay.h>
>>   #include <linux/errno.h>
>>   #include <linux/io.h>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox