[RFC][PATCH v2 9/9] ima: Register to the digest_cache LSM notifier and process events
Roberto Sassu
roberto.sassu at huaweicloud.com
Mon Apr 15 16:10:44 UTC 2024
From: Roberto Sassu <roberto.sassu at huawei.com>
A digest cache used for measurement/appraisal might change over the time
(due to file modification, directory changes). When that happens, IMA
should invalidate the cached integrity result for affected inodes and
evaluate those inodes again.
Implement ima_digest_cache_change(), to be invoked at every notification by
the digest_cache LSM, and register it as a callback with
digest_cache_register_notifier().
For every notification, and if the type of event is DIGEST_CACHE_RESET,
retrieve the inode integrity metadata (if any), and set the
IMA_CHANGE_XATTR atomic flag, so that IMA fully reevaluates the inode in
process_measurement().
Signed-off-by: Roberto Sassu <roberto.sassu at huawei.com>
---
security/integrity/ima/ima_digest_cache.c | 31 +++++++++++++++++++++++
security/integrity/ima/ima_digest_cache.h | 6 +++++
security/integrity/ima/ima_main.c | 11 +++++++-
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/security/integrity/ima/ima_digest_cache.c b/security/integrity/ima/ima_digest_cache.c
index 013c69f265d8..0ab35575ff7c 100644
--- a/security/integrity/ima/ima_digest_cache.c
+++ b/security/integrity/ima/ima_digest_cache.c
@@ -90,3 +90,34 @@ void ima_digest_cache_update_allowed_usage(struct file *file,
out:
digest_cache_put(digest_cache);
}
+
+static int ima_digest_cache_change(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct ima_iint_cache *iint;
+ struct digest_cache_event_data *event_data = data;
+
+ if (event != DIGEST_CACHE_RESET)
+ return NOTIFY_DONE;
+
+ iint = ima_iint_find(event_data->inode);
+ if (!iint) {
+ pr_debug("Integrity metadata not found for inode %lu\n",
+ event_data->inode->i_ino);
+ return NOTIFY_OK;
+ }
+
+ set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags);
+ pr_debug("Integrity metadata of inode %lu successfully reset\n",
+ event_data->inode->i_ino);
+ return NOTIFY_OK;
+}
+
+static struct notifier_block digest_cache_notifier = {
+ .notifier_call = ima_digest_cache_change,
+};
+
+int ima_digest_cache_register_notifier(void)
+{
+ return digest_cache_register_notifier(&digest_cache_notifier);
+}
diff --git a/security/integrity/ima/ima_digest_cache.h b/security/integrity/ima/ima_digest_cache.h
index cb47c15e975d..44c188c2fb93 100644
--- a/security/integrity/ima/ima_digest_cache.h
+++ b/security/integrity/ima/ima_digest_cache.h
@@ -15,6 +15,7 @@ void ima_digest_cache_store_allowed_usage(struct file *file,
void ima_digest_cache_update_allowed_usage(struct file *file,
struct ima_iint_cache *iint,
u64 *allowed_usage);
+int ima_digest_cache_register_notifier(void);
#else
static inline void
ima_digest_cache_store_allowed_usage(struct file *file,
@@ -27,4 +28,9 @@ ima_digest_cache_update_allowed_usage(struct file *file,
u64 *allowed_usage)
{ }
+static inline int ima_digest_cache_register_notifier(void)
+{
+ return 0;
+}
+
#endif /* CONFIG_SECURITY_DIGEST_CACHE */
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 7ae2bd888d41..fe826755acd1 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1159,8 +1159,17 @@ static int __init init_ima(void)
return error;
error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
- if (error)
+ if (error) {
pr_warn("Couldn't register LSM notifier, error %d\n", error);
+ return error;
+ }
+
+ error = ima_digest_cache_register_notifier();
+ if (error) {
+ pr_warn("Couldn't register digest cache notifier, error %d\n",
+ error);
+ unregister_blocking_lsm_notifier(&ima_lsm_policy_notifier);
+ }
if (!error)
ima_update_policy_flags();
--
2.34.1
More information about the Linux-security-module-archive
mailing list