Message ID | 20220125224645.79319-12-stefanb@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ima: Namespace IMA with audit support in IMA-ns | expand |
On Tue, Jan 25, 2022 at 05:46:33PM -0500, Stefan Berger wrote: > From: Stefan Berger <stefanb@linux.ibm.com> > > Move the ima_lsm_policy_notifier into the ima_namespace. Each IMA > namespace can now register its own LSM policy change notifier callback. > The policy change notifier for the init_ima_ns still remains in init_ima() > and therefore handle the registration of the callback for all other > namespaces in init_ima_namespace(). > > Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> > --- I'd double-check that this cannot be used to cause rcu stalls when a lot of ima namespace with a lot of rules are used leading to a dos situation during LSM policy update. The good thing at least is that an LSM policy update can only be triggered for selinux for the whole system.
On 1/26/22 08:05, Christian Brauner wrote: > On Tue, Jan 25, 2022 at 05:46:33PM -0500, Stefan Berger wrote: >> From: Stefan Berger <stefanb@linux.ibm.com> >> >> Move the ima_lsm_policy_notifier into the ima_namespace. Each IMA >> namespace can now register its own LSM policy change notifier callback. >> The policy change notifier for the init_ima_ns still remains in init_ima() >> and therefore handle the registration of the callback for all other >> namespaces in init_ima_namespace(). >> >> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> >> --- > I'd double-check that this cannot be used to cause rcu stalls when a lot > of ima namespace with a lot of rules are used leading to a dos situation > during LSM policy update. The good thing at least is that an LSM policy > update can only be triggered for selinux for the whole system. I just ran a test with up to 1920 IMA-namespaces each with 2 audit rules with the vmtools_exec_t label. Disabling of the vmtools SELinux module caused the rules to disappear in all IMA namespaces, as expected. However, it also added many kernel log lines 'ima: rule for LSM 'vmtools_exec_t' is undefined' to the kernel log that should probably be suppressed for ns != &init_ima_ns. Nothing bad happened otherwise. Also re-enabling the vmtools module didn't cause any kernel errors. So I think we should be fine. https://github.com/stefanberger/ima-namespaces-tests/tree/master/audit-many-2
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 94c6e3a4d666..fb6bd054d899 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -144,6 +144,8 @@ struct ima_namespace { int valid_policy; struct dentry *ima_policy; + + struct notifier_block ima_lsm_policy_notifier; } __randomize_layout; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index 425eed1c6838..1cba545ae477 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -10,6 +10,8 @@ static int ima_init_namespace(struct ima_namespace *ns) { + int rc; + INIT_LIST_HEAD(&ns->ima_default_rules); INIT_LIST_HEAD(&ns->ima_policy_rules); INIT_LIST_HEAD(&ns->ima_temp_rules); @@ -30,6 +32,15 @@ static int ima_init_namespace(struct ima_namespace *ns) ns->valid_policy = 1; ns->ima_fs_flags = 0; + if (ns != &init_ima_ns) { + ns->ima_lsm_policy_notifier.notifier_call = + ima_lsm_policy_change; + rc = register_blocking_lsm_notifier + (&ns->ima_lsm_policy_notifier); + if (rc) + return rc; + } + return 0; } @@ -39,5 +50,8 @@ int __init ima_ns_init(void) } struct ima_namespace init_ima_ns = { + .ima_lsm_policy_notifier = { + .notifier_call = ima_lsm_policy_change, + }, }; EXPORT_SYMBOL(init_ima_ns); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2cd5cc90ab79..ae0e9b14554a 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -38,10 +38,6 @@ int ima_appraise; int __ro_after_init ima_hash_algo = HASH_ALGO_SHA1; static int hash_setup_done; -static struct notifier_block ima_lsm_policy_notifier = { - .notifier_call = ima_lsm_policy_change, -}; - static int __init hash_setup(char *str) { struct ima_template_desc *template_desc = ima_template_desc_current(); @@ -1072,7 +1068,7 @@ static int __init init_ima(void) if (error) return error; - error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier); + error = register_blocking_lsm_notifier(&ns->ima_lsm_policy_notifier); if (error) pr_warn("Couldn't register LSM notifier, error %d\n", error); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 05b2bc06ab0c..3b754b9f5ef7 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -465,12 +465,14 @@ static void ima_lsm_update_rules(struct ima_namespace *ns) int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, void *lsm_data) { - struct ima_namespace *ns = &init_ima_ns; + struct ima_namespace *ns; if (event != LSM_POLICY_CHANGE) return NOTIFY_DONE; + ns = container_of(nb, struct ima_namespace, ima_lsm_policy_notifier); ima_lsm_update_rules(ns); + return NOTIFY_OK; }