From: Roberto Sassu <roberto.sassu@xxxxxxxxxx> If the digest of the accessed file is found in the digest cache, pass the ANDed masks from the IMA policy and from the digest cache to ima_appraise_measurement(). If the DIGEST_CACHE_APPRAISE_CONTENT flag is set in the mask, security.ima is not available, and the modsig method is disabled, grant access in read-only mode (except for new files). Since xattrs were not verified with EVM, writes need to be prevented to avoid the HMAC to be updated from an unverified one. Signed-off-by: Roberto Sassu <roberto.sassu@xxxxxxxxxx> --- security/integrity/ima/ima.h | 6 ++++-- security/integrity/ima/ima_appraise.c | 14 +++++++++++++- security/integrity/ima/ima_main.c | 3 ++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 4f40e07954d..385aaede15b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -322,7 +322,8 @@ int ima_appraise_measurement(enum ima_hooks func, struct integrity_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, + u8 digest_cache_mask); int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); @@ -346,7 +347,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, + u8 digest_cache_mask) { return INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 10dbafdae3d..e6e0ac5e26a 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -479,7 +479,8 @@ int ima_appraise_measurement(enum ima_hooks func, struct integrity_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, + u8 digest_cache_mask) { static const char op[] = "appraise_data"; const char *cause = "unknown"; @@ -514,6 +515,17 @@ int ima_appraise_measurement(enum ima_hooks func, (!(iint->flags & IMA_DIGSIG_REQUIRED) || (inode->i_size == 0))) status = INTEGRITY_PASS; + /* + * Except for new files, use the digest cache to appraise the + * file content and, at the same time, mark the file as + * immutable to prevent file updates and transitioning from an + * unverified HMAC to a valid HMAC. + */ + if (status != INTEGRITY_PASS && + (digest_cache_mask & DIGEST_CACHE_APPRAISE_CONTENT)) { + set_bit(IMA_DIGSIG, &iint->atomic_flags); + status = INTEGRITY_PASS; + } goto out; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7a5148ac3af..9f745b473bc 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -381,7 +381,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, + digest_cache_mask); inode_unlock(inode); } if (!rc) -- 2.34.1