VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2025-71306

CVE-2025-71306

Description

In the Linux kernel, the following vulnerability has been resolved:

ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

KASAN reported a stack-out-of-bounds access in ima_appraise_measurement from is_bprm_creds_for_exec:

BUG: KASAN: stack-out-of-bounds in ima_appraise_measurement+0x12dc/0x16a0 Read of size 1 at addr ffffc9000160f940 by task sudo/550 The buggy address belongs to stack of task sudo/550 and is located at offset 24 in frame: ima_appraise_measurement+0x0/0x16a0 This frame has 2 objects: [48, 56) 'file' [80, 148) 'hash'

This is caused by using container_of on the *file pointer. This offset calculation is what triggers the stack-out-of-bounds error.

In order to fix this, pass in a bprm_is_check boolean which can be set depending on how process_measurement is called. If the caller has a linux_binprm pointer and the function is BPRM_CHECK we can determine is_check and set it then. Otherwise set it to false.

Affected products

1

Patches

4
ab3d16da982a

ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitChris J ArgesDec 28, 2025Fixed in 6.19.4via kernel-cna
3 files changed · +20 25
  • security/integrity/ima/ima_appraise.c+3 13 modified
    diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
    index 5149ff4fd50d24..16c20c578ea878 100644
    --- a/security/integrity/ima/ima_appraise.c
    +++ b/security/integrity/ima/ima_appraise.c
    @@ -470,17 +470,6 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     	return rc;
     }
     
    -static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
    -{
    -	struct linux_binprm *bprm;
    -
    -	if (func == BPRM_CHECK) {
    -		bprm = container_of(&file, struct linux_binprm, file);
    -		return bprm->is_check;
    -	}
    -	return false;
    -}
    -
     /*
      * ima_appraise_measurement - appraise file measurement
      *
    @@ -492,7 +481,8 @@ static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig)
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check)
     {
     	static const char op[] = "appraise_data";
     	int audit_msgno = AUDIT_INTEGRITY_DATA;
    @@ -514,7 +504,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     	 * of the script interpreter(userspace). Differentiate kernel and
     	 * userspace enforced integrity audit messages.
     	 */
    -	if (is_bprm_creds_for_exec(func, file))
    +	if (bprm_is_check)
     		audit_msgno = AUDIT_INTEGRITY_USERSPACE;
     
     	/* If reading the xattr failed and there's no modsig, error out. */
    
  • security/integrity/ima/ima.h+4 2 modified
    diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
    index e3d71d8d56e38c..89ebe98ffc5e57 100644
    --- a/security/integrity/ima/ima.h
    +++ b/security/integrity/ima/ima.h
    @@ -441,7 +441,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig);
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check);
     int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
     		      int mask, enum ima_hooks func);
     void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
    @@ -466,7 +467,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
     					   const unsigned char *filename,
     					   struct evm_ima_xattr_data *xattr_value,
     					   int xattr_len,
    -					   const struct modsig *modsig)
    +					   const struct modsig *modsig,
    +					   bool bprm_is_check)
     {
     	return INTEGRITY_UNKNOWN;
     }
    
  • security/integrity/ima/ima_main.c+13 10 modified
    diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
    index 5770cf691912aa..1d6229b156fb17 100644
    --- a/security/integrity/ima/ima_main.c
    +++ b/security/integrity/ima/ima_main.c
    @@ -236,7 +236,8 @@ static void ima_file_free(struct file *file)
     static int process_measurement(struct file *file, const struct cred *cred,
     			       struct lsm_prop *prop, char *buf, loff_t size,
     			       int mask, enum ima_hooks func,
    -			       enum kernel_read_file_id read_id)
    +			       enum kernel_read_file_id read_id,
    +			       bool bprm_is_check)
     {
     	struct inode *real_inode, *inode = file_inode(file);
     	struct ima_iint_cache *iint = NULL;
    @@ -426,7 +427,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
     			inode_lock(inode);
     			rc = ima_appraise_measurement(func, iint, file,
     						      pathname, xattr_value,
    -						      xattr_len, modsig);
    +						      xattr_len, modsig,
    +						      bprm_is_check);
     			inode_unlock(inode);
     		}
     		if (!rc)
    @@ -493,14 +495,15 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
     
     	if (reqprot & PROT_EXEC) {
     		ret = process_measurement(file, current_cred(), &prop, NULL,
    -					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
    +					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0,
    +					  false);
     		if (ret)
     			return ret;
     	}
     
     	if (prot & PROT_EXEC)
     		return process_measurement(file, current_cred(), &prop, NULL,
    -					   0, MAY_EXEC, MMAP_CHECK, 0);
    +					   0, MAY_EXEC, MMAP_CHECK, 0, false);
     
     	return 0;
     }
    @@ -584,7 +587,8 @@ static int ima_bprm_check(struct linux_binprm *bprm)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(bprm->file, current_cred(),
    -				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
    +				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0,
    +				   bprm->is_check);
     }
     
     /**
    @@ -614,7 +618,7 @@ static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
    -				   0, MAY_EXEC, CREDS_CHECK, 0);
    +				   0, MAY_EXEC, CREDS_CHECK, 0, false);
     }
     
     /**
    @@ -662,7 +666,7 @@ static int ima_file_check(struct file *file, int mask)
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
     				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
    -					   MAY_APPEND), FILE_CHECK, 0);
    +					   MAY_APPEND), FILE_CHECK, 0, false);
     }
     
     static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
    @@ -881,7 +885,7 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
    -				   MAY_READ, func, 0);
    +				   MAY_READ, func, 0, false);
     }
     
     const int read_idmap[READING_MAX_ID] = {
    @@ -925,7 +929,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, buf, size,
    -				   MAY_READ, func, read_id);
    +				   MAY_READ, func, read_id, false);
     }
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
377cae9851e8

ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitChris J ArgesDec 28, 2025Fixed in 7.0via kernel-cna
3 files changed · +20 25
  • security/integrity/ima/ima_appraise.c+3 13 modified
    diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
    index 5149ff4fd50d24..16c20c578ea878 100644
    --- a/security/integrity/ima/ima_appraise.c
    +++ b/security/integrity/ima/ima_appraise.c
    @@ -470,17 +470,6 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     	return rc;
     }
     
    -static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
    -{
    -	struct linux_binprm *bprm;
    -
    -	if (func == BPRM_CHECK) {
    -		bprm = container_of(&file, struct linux_binprm, file);
    -		return bprm->is_check;
    -	}
    -	return false;
    -}
    -
     /*
      * ima_appraise_measurement - appraise file measurement
      *
    @@ -492,7 +481,8 @@ static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig)
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check)
     {
     	static const char op[] = "appraise_data";
     	int audit_msgno = AUDIT_INTEGRITY_DATA;
    @@ -514,7 +504,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     	 * of the script interpreter(userspace). Differentiate kernel and
     	 * userspace enforced integrity audit messages.
     	 */
    -	if (is_bprm_creds_for_exec(func, file))
    +	if (bprm_is_check)
     		audit_msgno = AUDIT_INTEGRITY_USERSPACE;
     
     	/* If reading the xattr failed and there's no modsig, error out. */
    
  • security/integrity/ima/ima.h+4 2 modified
    diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
    index e3d71d8d56e38c..89ebe98ffc5e57 100644
    --- a/security/integrity/ima/ima.h
    +++ b/security/integrity/ima/ima.h
    @@ -441,7 +441,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig);
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check);
     int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
     		      int mask, enum ima_hooks func);
     void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
    @@ -466,7 +467,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
     					   const unsigned char *filename,
     					   struct evm_ima_xattr_data *xattr_value,
     					   int xattr_len,
    -					   const struct modsig *modsig)
    +					   const struct modsig *modsig,
    +					   bool bprm_is_check)
     {
     	return INTEGRITY_UNKNOWN;
     }
    
  • security/integrity/ima/ima_main.c+13 10 modified
    diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
    index 5770cf691912aa..1d6229b156fb17 100644
    --- a/security/integrity/ima/ima_main.c
    +++ b/security/integrity/ima/ima_main.c
    @@ -236,7 +236,8 @@ static void ima_file_free(struct file *file)
     static int process_measurement(struct file *file, const struct cred *cred,
     			       struct lsm_prop *prop, char *buf, loff_t size,
     			       int mask, enum ima_hooks func,
    -			       enum kernel_read_file_id read_id)
    +			       enum kernel_read_file_id read_id,
    +			       bool bprm_is_check)
     {
     	struct inode *real_inode, *inode = file_inode(file);
     	struct ima_iint_cache *iint = NULL;
    @@ -426,7 +427,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
     			inode_lock(inode);
     			rc = ima_appraise_measurement(func, iint, file,
     						      pathname, xattr_value,
    -						      xattr_len, modsig);
    +						      xattr_len, modsig,
    +						      bprm_is_check);
     			inode_unlock(inode);
     		}
     		if (!rc)
    @@ -493,14 +495,15 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
     
     	if (reqprot & PROT_EXEC) {
     		ret = process_measurement(file, current_cred(), &prop, NULL,
    -					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
    +					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0,
    +					  false);
     		if (ret)
     			return ret;
     	}
     
     	if (prot & PROT_EXEC)
     		return process_measurement(file, current_cred(), &prop, NULL,
    -					   0, MAY_EXEC, MMAP_CHECK, 0);
    +					   0, MAY_EXEC, MMAP_CHECK, 0, false);
     
     	return 0;
     }
    @@ -584,7 +587,8 @@ static int ima_bprm_check(struct linux_binprm *bprm)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(bprm->file, current_cred(),
    -				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
    +				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0,
    +				   bprm->is_check);
     }
     
     /**
    @@ -614,7 +618,7 @@ static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
    -				   0, MAY_EXEC, CREDS_CHECK, 0);
    +				   0, MAY_EXEC, CREDS_CHECK, 0, false);
     }
     
     /**
    @@ -662,7 +666,7 @@ static int ima_file_check(struct file *file, int mask)
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
     				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
    -					   MAY_APPEND), FILE_CHECK, 0);
    +					   MAY_APPEND), FILE_CHECK, 0, false);
     }
     
     static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
    @@ -881,7 +885,7 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
    -				   MAY_READ, func, 0);
    +				   MAY_READ, func, 0, false);
     }
     
     const int read_idmap[READING_MAX_ID] = {
    @@ -925,7 +929,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, buf, size,
    -				   MAY_READ, func, read_id);
    +				   MAY_READ, func, read_id, false);
     }
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
377cae9851e8

ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

3 files changed · +20 25
  • security/integrity/ima/ima_appraise.c+3 13 modified
    diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
    index 5149ff4fd50d24..16c20c578ea878 100644
    --- a/security/integrity/ima/ima_appraise.c
    +++ b/security/integrity/ima/ima_appraise.c
    @@ -470,17 +470,6 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     	return rc;
     }
     
    -static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
    -{
    -	struct linux_binprm *bprm;
    -
    -	if (func == BPRM_CHECK) {
    -		bprm = container_of(&file, struct linux_binprm, file);
    -		return bprm->is_check;
    -	}
    -	return false;
    -}
    -
     /*
      * ima_appraise_measurement - appraise file measurement
      *
    @@ -492,7 +481,8 @@ static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig)
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check)
     {
     	static const char op[] = "appraise_data";
     	int audit_msgno = AUDIT_INTEGRITY_DATA;
    @@ -514,7 +504,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     	 * of the script interpreter(userspace). Differentiate kernel and
     	 * userspace enforced integrity audit messages.
     	 */
    -	if (is_bprm_creds_for_exec(func, file))
    +	if (bprm_is_check)
     		audit_msgno = AUDIT_INTEGRITY_USERSPACE;
     
     	/* If reading the xattr failed and there's no modsig, error out. */
    
  • security/integrity/ima/ima.h+4 2 modified
    diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
    index e3d71d8d56e38c..89ebe98ffc5e57 100644
    --- a/security/integrity/ima/ima.h
    +++ b/security/integrity/ima/ima.h
    @@ -441,7 +441,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig);
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check);
     int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
     		      int mask, enum ima_hooks func);
     void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
    @@ -466,7 +467,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
     					   const unsigned char *filename,
     					   struct evm_ima_xattr_data *xattr_value,
     					   int xattr_len,
    -					   const struct modsig *modsig)
    +					   const struct modsig *modsig,
    +					   bool bprm_is_check)
     {
     	return INTEGRITY_UNKNOWN;
     }
    
  • security/integrity/ima/ima_main.c+13 10 modified
    diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
    index 5770cf691912aa..1d6229b156fb17 100644
    --- a/security/integrity/ima/ima_main.c
    +++ b/security/integrity/ima/ima_main.c
    @@ -236,7 +236,8 @@ static void ima_file_free(struct file *file)
     static int process_measurement(struct file *file, const struct cred *cred,
     			       struct lsm_prop *prop, char *buf, loff_t size,
     			       int mask, enum ima_hooks func,
    -			       enum kernel_read_file_id read_id)
    +			       enum kernel_read_file_id read_id,
    +			       bool bprm_is_check)
     {
     	struct inode *real_inode, *inode = file_inode(file);
     	struct ima_iint_cache *iint = NULL;
    @@ -426,7 +427,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
     			inode_lock(inode);
     			rc = ima_appraise_measurement(func, iint, file,
     						      pathname, xattr_value,
    -						      xattr_len, modsig);
    +						      xattr_len, modsig,
    +						      bprm_is_check);
     			inode_unlock(inode);
     		}
     		if (!rc)
    @@ -493,14 +495,15 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
     
     	if (reqprot & PROT_EXEC) {
     		ret = process_measurement(file, current_cred(), &prop, NULL,
    -					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
    +					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0,
    +					  false);
     		if (ret)
     			return ret;
     	}
     
     	if (prot & PROT_EXEC)
     		return process_measurement(file, current_cred(), &prop, NULL,
    -					   0, MAY_EXEC, MMAP_CHECK, 0);
    +					   0, MAY_EXEC, MMAP_CHECK, 0, false);
     
     	return 0;
     }
    @@ -584,7 +587,8 @@ static int ima_bprm_check(struct linux_binprm *bprm)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(bprm->file, current_cred(),
    -				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
    +				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0,
    +				   bprm->is_check);
     }
     
     /**
    @@ -614,7 +618,7 @@ static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
    -				   0, MAY_EXEC, CREDS_CHECK, 0);
    +				   0, MAY_EXEC, CREDS_CHECK, 0, false);
     }
     
     /**
    @@ -662,7 +666,7 @@ static int ima_file_check(struct file *file, int mask)
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
     				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
    -					   MAY_APPEND), FILE_CHECK, 0);
    +					   MAY_APPEND), FILE_CHECK, 0, false);
     }
     
     static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
    @@ -881,7 +885,7 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
    -				   MAY_READ, func, 0);
    +				   MAY_READ, func, 0, false);
     }
     
     const int read_idmap[READING_MAX_ID] = {
    @@ -925,7 +929,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, buf, size,
    -				   MAY_READ, func, read_id);
    +				   MAY_READ, func, read_id, false);
     }
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
ab3d16da982a

ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()

3 files changed · +20 25
  • security/integrity/ima/ima_appraise.c+3 13 modified
    diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
    index 5149ff4fd50d24..16c20c578ea878 100644
    --- a/security/integrity/ima/ima_appraise.c
    +++ b/security/integrity/ima/ima_appraise.c
    @@ -470,17 +470,6 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     	return rc;
     }
     
    -static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
    -{
    -	struct linux_binprm *bprm;
    -
    -	if (func == BPRM_CHECK) {
    -		bprm = container_of(&file, struct linux_binprm, file);
    -		return bprm->is_check;
    -	}
    -	return false;
    -}
    -
     /*
      * ima_appraise_measurement - appraise file measurement
      *
    @@ -492,7 +481,8 @@ static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig)
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check)
     {
     	static const char op[] = "appraise_data";
     	int audit_msgno = AUDIT_INTEGRITY_DATA;
    @@ -514,7 +504,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     	 * of the script interpreter(userspace). Differentiate kernel and
     	 * userspace enforced integrity audit messages.
     	 */
    -	if (is_bprm_creds_for_exec(func, file))
    +	if (bprm_is_check)
     		audit_msgno = AUDIT_INTEGRITY_USERSPACE;
     
     	/* If reading the xattr failed and there's no modsig, error out. */
    
  • security/integrity/ima/ima.h+4 2 modified
    diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
    index e3d71d8d56e38c..89ebe98ffc5e57 100644
    --- a/security/integrity/ima/ima.h
    +++ b/security/integrity/ima/ima.h
    @@ -441,7 +441,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
     int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
     			     struct file *file, const unsigned char *filename,
     			     struct evm_ima_xattr_data *xattr_value,
    -			     int xattr_len, const struct modsig *modsig);
    +			     int xattr_len, const struct modsig *modsig,
    +			     bool bprm_is_check);
     int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
     		      int mask, enum ima_hooks func);
     void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
    @@ -466,7 +467,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
     					   const unsigned char *filename,
     					   struct evm_ima_xattr_data *xattr_value,
     					   int xattr_len,
    -					   const struct modsig *modsig)
    +					   const struct modsig *modsig,
    +					   bool bprm_is_check)
     {
     	return INTEGRITY_UNKNOWN;
     }
    
  • security/integrity/ima/ima_main.c+13 10 modified
    diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
    index 5770cf691912aa..1d6229b156fb17 100644
    --- a/security/integrity/ima/ima_main.c
    +++ b/security/integrity/ima/ima_main.c
    @@ -236,7 +236,8 @@ static void ima_file_free(struct file *file)
     static int process_measurement(struct file *file, const struct cred *cred,
     			       struct lsm_prop *prop, char *buf, loff_t size,
     			       int mask, enum ima_hooks func,
    -			       enum kernel_read_file_id read_id)
    +			       enum kernel_read_file_id read_id,
    +			       bool bprm_is_check)
     {
     	struct inode *real_inode, *inode = file_inode(file);
     	struct ima_iint_cache *iint = NULL;
    @@ -426,7 +427,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
     			inode_lock(inode);
     			rc = ima_appraise_measurement(func, iint, file,
     						      pathname, xattr_value,
    -						      xattr_len, modsig);
    +						      xattr_len, modsig,
    +						      bprm_is_check);
     			inode_unlock(inode);
     		}
     		if (!rc)
    @@ -493,14 +495,15 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
     
     	if (reqprot & PROT_EXEC) {
     		ret = process_measurement(file, current_cred(), &prop, NULL,
    -					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
    +					  0, MAY_EXEC, MMAP_CHECK_REQPROT, 0,
    +					  false);
     		if (ret)
     			return ret;
     	}
     
     	if (prot & PROT_EXEC)
     		return process_measurement(file, current_cred(), &prop, NULL,
    -					   0, MAY_EXEC, MMAP_CHECK, 0);
    +					   0, MAY_EXEC, MMAP_CHECK, 0, false);
     
     	return 0;
     }
    @@ -584,7 +587,8 @@ static int ima_bprm_check(struct linux_binprm *bprm)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(bprm->file, current_cred(),
    -				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
    +				   &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0,
    +				   bprm->is_check);
     }
     
     /**
    @@ -614,7 +618,7 @@ static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
     
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
    -				   0, MAY_EXEC, CREDS_CHECK, 0);
    +				   0, MAY_EXEC, CREDS_CHECK, 0, false);
     }
     
     /**
    @@ -662,7 +666,7 @@ static int ima_file_check(struct file *file, int mask)
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
     				   mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
    -					   MAY_APPEND), FILE_CHECK, 0);
    +					   MAY_APPEND), FILE_CHECK, 0, false);
     }
     
     static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
    @@ -881,7 +885,7 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, NULL, 0,
    -				   MAY_READ, func, 0);
    +				   MAY_READ, func, 0, false);
     }
     
     const int read_idmap[READING_MAX_ID] = {
    @@ -925,7 +929,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
     	func = read_idmap[read_id] ?: FILE_CHECK;
     	security_current_getlsmprop_subj(&prop);
     	return process_measurement(file, current_cred(), &prop, buf, size,
    -				   MAY_READ, func, read_id);
    +				   MAY_READ, func, read_id, false);
     }
     
     /**
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"The `is_bprm_creds_for_exec()` function used `container_of(&file, struct linux_binprm, file)` on a stack-local `struct file *` pointer, causing an out-of-bounds read when the pointer is not actually embedded inside a `struct linux_binprm`."

Attack vector

An attacker can trigger this bug by executing a binary (e.g., via `sudo`) on a system where IMA appraisal is enabled. The call path goes from `ima_bprm_check()` → `process_measurement()` → `ima_appraise_measurement()`. Inside `ima_appraise_measurement`, the removed helper `is_bprm_creds_for_exec()` performed `container_of` on the `file` pointer to recover a `struct linux_binprm`, but the `file` pointer passed in is a stack-local copy, not a member of a `linux_binprm`. This causes KASAN to report a stack-out-of-bounds read of size 1 at a stack offset of 24 bytes [patch_id=2662189]. No special privileges beyond the ability to execute a file are required; the bug manifests during normal binary execution with IMA appraisal active.

Affected code

The vulnerable code was in `security/integrity/ima/ima_appraise.c` in the `is_bprm_creds_for_exec()` function, which called `container_of(&file, struct linux_binprm, file)`. The fix touches three files: `security/integrity/ima/ima_appraise.c` (removes the helper and updates `ima_appraise_measurement` signature), `security/integrity/ima/ima_main.c` (adds `bprm_is_check` parameter to `process_measurement` and all its callers), and `security/integrity/ima/ima.h` (updates the declaration and stub) [patch_id=2662189].

What the fix does

The patch removes the `is_bprm_creds_for_exec()` function entirely and instead passes a `bool bprm_is_check` parameter through `process_measurement()` into `ima_appraise_measurement()` [patch_id=2662189]. In `ima_bprm_check()`, the caller already has access to the `linux_binprm` structure via the `bprm` parameter, so it can directly read `bprm->is_check` and pass that boolean. All other callers of `process_measurement()` pass `false` for this parameter. This eliminates the unsafe `container_of` arithmetic that caused the stack-out-of-bounds access.

Preconditions

  • configThe kernel must be built with CONFIG_IMA_APPRAISE enabled and IMA appraisal must be active at runtime.
  • inputAn attacker must be able to execute a binary on the system (e.g., via sudo or normal execve).

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.