diff mbox series

[v9,11/23] ima: Move ima_lsm_policy_notifier into ima_namespace

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

Commit Message

Stefan Berger Jan. 25, 2022, 10:46 p.m. UTC
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>
---
 security/integrity/ima/ima.h             |  2 ++
 security/integrity/ima/ima_init_ima_ns.c | 14 ++++++++++++++
 security/integrity/ima/ima_main.c        |  6 +-----
 security/integrity/ima/ima_policy.c      |  4 +++-
 4 files changed, 20 insertions(+), 6 deletions(-)

Comments

Christian Brauner Jan. 26, 2022, 1:05 p.m. UTC | #1
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.
Stefan Berger Jan. 26, 2022, 9:54 p.m. UTC | #2
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 mbox series

Patch

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;
 }