ima_collect_measurement() discards a modsig when detached data cannot be supplied, but the reason is lost.
Return the pkcs7_supply_detached_data() error from ima_collect_modsig() and emit a separate failed-modsig audit record. Keep ordinary collection errors on their existing audit path so both causes are reported when they happen together. Signed-off-by: Jérémy Jean <[email protected]> --- security/integrity/ima/ima.h | 8 ++++---- security/integrity/ima/ima_api.c | 25 +++++++++++++++++-------- security/integrity/ima/ima_modsig.c | 8 ++++---- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 6280d7ec23326..a3670a479d095 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -559,7 +559,7 @@ static inline void __init init_ima_appraise_lsm(const struct lsm_id *lsmid) #ifdef CONFIG_IMA_APPRAISE_MODSIG int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, struct modsig **modsig); -bool ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size); +int ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size); int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, const u8 **digest, u32 *digest_size); int ima_get_raw_modsig(const struct modsig *modsig, const void **data, @@ -572,10 +572,10 @@ static inline int ima_read_modsig(enum ima_hooks func, const void *buf, return -EOPNOTSUPP; } -static inline bool ima_collect_modsig(struct modsig *modsig, const void *buf, - loff_t size) +static inline int ima_collect_modsig(struct modsig *modsig, const void *buf, + loff_t size) { - return false; + return -EOPNOTSUPP; } static inline int ima_get_modsig_digest(const struct modsig *modsig, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 7859c9d1a27f5..5f6178948eb3e 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -254,7 +254,7 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, struct ima_digest_data, hdr); struct name_snapshot filename; struct kstat stat; - int result = 0; + int result = 0, modsig_result = 0; int length; void *tmpbuf; u64 i_version = 0; @@ -264,9 +264,12 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, * the file digest without collecting the modsig in a previous * measurement rule. */ - if (modsig && *modsig && !ima_collect_modsig(*modsig, buf, size)) { - ima_free_modsig(*modsig); - *modsig = NULL; + if (modsig && *modsig) { + modsig_result = ima_collect_modsig(*modsig, buf, size); + if (modsig_result) { + ima_free_modsig(*modsig); + *modsig = NULL; + } } if (iint->flags & IMA_COLLECTED) @@ -326,15 +329,21 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file, if (!result) iint->flags |= IMA_COLLECTED; out: - if (result) { + if (result || modsig_result) { if (file->f_flags & O_DIRECT) audit_cause = "failed(directio)"; take_dentry_name_snapshot(&filename, file->f_path.dentry); - integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, - filename.name.name, "collect_data", - audit_cause, result, 0, result); + if (modsig_result) + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, + filename.name.name, "collect_data", + "failed-modsig", modsig_result, 0, + modsig_result); + if (result) + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, + filename.name.name, "collect_data", + audit_cause, result, 0, result); release_dentry_name_snapshot(&filename); } diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c index e640a9a53508e..c5bd4770298a1 100644 --- a/security/integrity/ima/ima_modsig.c +++ b/security/integrity/ima/ima_modsig.c @@ -99,9 +99,9 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, * * Digest export is best-effort; not all signatures expose a single digest. * - * Return: true if the file data was supplied, false otherwise. + * Return: 0 if the file data was supplied, error code otherwise. */ -bool ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) +int ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) { int rc; @@ -113,13 +113,13 @@ bool ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) sizeof(struct module_signature); rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); if (rc) - return false; + return rc; /* Ask the PKCS7 code to calculate the file hash. */ rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, &modsig->digest_size, &modsig->hash_algo); - return true; + return 0; } int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) -- 2.47.3
