[PATCH v5 3/3] ima: Use kstat.ctime as a fallback change detection for stacked fs

Roberto Sassu roberto.sassu at huaweicloud.com
Wed Feb 4 12:36:09 UTC 2026


On Fri, 2026-01-30 at 16:39 -0600, Frederick Lawler wrote:
> IMA performs unnecessary measurements on files in stacked file systems
> that do not set kstat.change_cookie to an inode's i_version.
> 
> For example: TMPFS (upper) is stacked onto XFS (lower).
> Actions files result in re-measurement because commit 1cf7e834a6fb
> ("xfs: switch to multigrain timestamps") introduced multigrain
> timestamps into XFS which changed the kstat.change_cookie semantics
> to no longer supply an i_version to compare against in
> integrity_inode_attributes_changed(). Once the inode is in TMPFS,
> the change detection behavior operates as normal because TMPFS updates
> kstat.change_cookie to the i_version.
> 
> Instead, fall back onto a ctime comparison. This also gives file systems
> that do not support i_version an opportunity avoid the same behavior,
> as they're more likely to have ctime support.
> 
> timespec64_to_ns() is chosen to avoid adding extra storage to
> integrity_inode_attributes by leveraging the existing version field.

Correct me if I'm wrong, but this issue seems to me xfs-specific. In
that case, maybe it is better to remove the stacked filesystem part,
which might be misleading.

Thanks

Roberto

> Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> Fixes: 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> Suggested-by: Jeff Layton <jlayton at kernel.org>
> Signed-off-by: Frederick Lawler <fred at cloudflare.com>
> ---
>  include/linux/integrity.h         |  6 +++++-
>  security/integrity/ima/ima_api.c  | 11 ++++++++---
>  security/integrity/ima/ima_main.c |  2 +-
>  3 files changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index 382c783f0fa3ae4a938cdf9559291ba1903a378e..ec2c94907f417c4a71ecce29ac79edac9bc2c6f8 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -10,6 +10,7 @@
>  #include <linux/fs.h>
>  #include <linux/iversion.h>
>  #include <linux/kernel.h>
> +#include <linux/time64.h>
>  
>  enum integrity_status {
>  	INTEGRITY_PASS = 0,
> @@ -58,6 +59,9 @@ integrity_inode_attrs_stat_changed
>  	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;
>  }
>  
> @@ -84,7 +88,7 @@ integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
>  	 * only for IMA if vfs_getattr_nosec() fails.
>  	 */
>  	if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> -				       STATX_CHANGE_COOKIE,
> +				       STATX_CHANGE_COOKIE | STATX_CTIME,
>  				       AT_STATX_SYNC_AS_STAT))
>  		return !IS_I_VERSION(inode) ||
>  		       !inode_eq_iversion(inode, attrs->version);
> 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 8cb17c9d446caaa5a98f5ec8f027c17ba7babca8..776db158b0bd8a0d053729ac0cc15af8b6020a98 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -199,7 +199,7 @@ 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,
> +				      STATX_CHANGE_COOKIE | STATX_CTIME,
>  				      AT_STATX_SYNC_AS_STAT) ||
>  		    integrity_inode_attrs_stat_changed(&iint->real_inode,
>  						       &stat)) {
> 




More information about the Linux-security-module-archive mailing list