[PATCH v15 10/26] ima: Switch to lazy lsm policy updates for better performance
From: Stefan Berger <stefanb@linux.ibm.com>
Date: 2023-02-06 14:04:12
Also in:
linux-integrity, lkml
Subsystem:
extended verification module (evm), integrity measurement architecture (ima), security subsystem, the rest · Maintainers:
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Paul Moore, James Morris, "Serge E. Hallyn", Linus Torvalds
Instead of calling ima_lsm_update_rules() for every namespace upon invocation of the ima_lsm_policy_change() notification function, only set a flag in a namespace and defer the call to ima_lsm_update_rules() to before the policy is accessed the next time, which is either in ima_policy_start(), when displaying the policy via the policy file in securityfs, or when calling ima_match_policy(). The performance numbers before this change for a test enabling and disabling an SELinux module was as follows with a given number of IMA namespaces that each have a policy containing 2 rules with SELinux labels: 2: ~9s 192: ~11s 1920: ~80s With this change: 2: ~6.5s 192: ~7s 1920: ~8.3s Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> Acked-by: Serge Hallyn <serge@hallyn.com> --- security/integrity/ima/ima.h | 4 ++++ security/integrity/ima/ima_policy.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index db28d6d222a6..4de8ec776611 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h@@ -123,6 +123,10 @@ struct ima_h_table { }; struct ima_namespace { + unsigned long ima_ns_flags; +/* Bit numbers for above flags; use BIT() to get flag */ +#define IMA_NS_LSM_UPDATE_RULES 0 + /* policy rules */ struct list_head ima_default_rules; /* Kconfig, builtin & arch rules */ struct list_head ima_policy_rules; /* arch & custom rules */
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 8e71b28855a4..19aca18db323 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c@@ -252,6 +252,14 @@ static struct ima_rule_entry critical_data_rules[] __ro_after_init = { {.action = MEASURE, .func = CRITICAL_DATA, .flags = IMA_FUNC}, }; +static void ima_lsm_update_rules(struct ima_namespace *ns); + +static inline void ima_lazy_lsm_update_rules(struct ima_namespace *ns) +{ + if (test_and_clear_bit(IMA_NS_LSM_UPDATE_RULES, &ns->ima_ns_flags)) + ima_lsm_update_rules(ns); +} + static int ima_policy __initdata; static int __init default_measure_policy_setup(char *str)
@@ -498,7 +506,8 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, return NOTIFY_DONE; ns = container_of(nb, struct ima_namespace, ima_lsm_policy_notifier); - ima_lsm_update_rules(ns); + + set_bit(IMA_NS_LSM_UPDATE_RULES, &ns->ima_ns_flags); return NOTIFY_OK; }
@@ -752,6 +761,8 @@ int ima_match_policy(struct ima_namespace *ns, if (template_desc && !*template_desc) *template_desc = ima_template_desc_current(); + ima_lazy_lsm_update_rules(ns); + rcu_read_lock(); ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
@@ -2016,6 +2027,8 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) struct ima_rule_entry *entry; struct list_head *ima_rules_tmp; + ima_lazy_lsm_update_rules(ns); + rcu_read_lock(); ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
--
2.37.3