[RFC PATCH v2 31/34] ima,evm: move initcalls to the LSM framework
Paul Moore
paul at paul-moore.com
Mon Jul 21 23:21:34 UTC 2025
This patch converts IMA and EVM to use the LSM frameworks's initcall
mechanism. There was a minor challenge in this conversion that wasn't
seen when converting the other LSMs brought about by the resource
sharing between the two related, yes independent IMA and EVM LSMs.
This was resolved by registering the same initcalls for each LSM and
including code in each registered initcall to ensure it only executes
once during each boot.
It is worth mentioning that this patch does not touch any of the
"platform certs" code that lives in the security/integrity/platform_certs
directory as the IMA/EVM maintainers have assured me that this code is
unrelated to IMA/EVM, despite the location, and will be moved to a more
relevant subsystem in the future.
Signed-off-by: Paul Moore <paul at paul-moore.com>
---
security/integrity/Makefile | 2 +-
security/integrity/evm/evm_main.c | 6 ++---
security/integrity/iint.c | 4 +--
security/integrity/ima/ima_main.c | 6 ++---
security/integrity/initcalls.c | 41 +++++++++++++++++++++++++++++++
security/integrity/initcalls.h | 13 ++++++++++
6 files changed, 63 insertions(+), 9 deletions(-)
create mode 100644 security/integrity/initcalls.c
create mode 100644 security/integrity/initcalls.h
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 92b63039c654..6ea330ea88b1 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -5,7 +5,7 @@
obj-$(CONFIG_INTEGRITY) += integrity.o
-integrity-y := iint.o
+integrity-y := iint.o initcalls.o
integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index db8e324ed4e6..823573bcaa27 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
#include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/utils.h>
+#include "../initcalls.h"
#include "evm.h"
int evm_initialized;
@@ -1112,7 +1113,7 @@ void __init evm_load_x509(void)
}
#endif
-static int __init init_evm(void)
+int __init init_evm(void)
{
int error;
struct list_head *pos, *q;
@@ -1179,6 +1180,5 @@ DEFINE_LSM(evm) = {
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
.blobs = &evm_blob_sizes,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_evm);
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 068ac6c2ae1e..a4b88d67ff43 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -11,6 +11,7 @@
*/
#include <linux/security.h>
#include "integrity.h"
+#include "initcalls.h"
struct dentry *integrity_dir;
@@ -42,7 +43,7 @@ void __init integrity_load_keys(void)
evm_load_x509();
}
-static int __init integrity_fs_init(void)
+int __init integrity_fs_init(void)
{
integrity_dir = securityfs_create_dir("integrity", NULL);
if (IS_ERR(integrity_dir)) {
@@ -58,4 +59,3 @@ static int __init integrity_fs_init(void)
return 0;
}
-late_initcall(integrity_fs_init)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index ded971bdeaae..ea9c0ed12e06 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -27,6 +27,7 @@
#include <linux/fs.h>
#include <linux/iversion.h>
#include <linux/evm.h>
+#include "../initcalls.h"
#include "ima.h"
@@ -1182,7 +1183,7 @@ static int ima_kernel_module_request(char *kmod_name)
#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
-static int __init init_ima(void)
+int __init init_ima(void)
{
int error;
@@ -1257,6 +1258,5 @@ DEFINE_LSM(ima) = {
.init = init_ima_lsm,
.order = LSM_ORDER_LAST,
.blobs = &ima_blob_sizes,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_ima); /* Start IMA after the TPM is available */
diff --git a/security/integrity/initcalls.c b/security/integrity/initcalls.c
new file mode 100644
index 000000000000..92ec9f0aa2a7
--- /dev/null
+++ b/security/integrity/initcalls.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Platform certificate / keyring initcalls
+ *
+ */
+
+#include <linux/init.h>
+
+#include "initcalls.h"
+
+/**
+ * integrity_late_init - late_initcalls for IMA/EVM
+ *
+ * This helper function wraps all of the late_initcalls for both IMA and EVM.
+ * It can be called multiple times, e.g. once from IMA and once from EVM,
+ * without problem as it maintains an internal static state variable which
+ * ensures that any setup/initialization is only done once.
+ */
+int __init integrity_late_init(void)
+{
+ int rc = 0, rc_tmp;
+ static bool setup = false;
+
+ if (setup)
+ return 0;
+ setup = true;
+
+ rc_tmp = integrity_fs_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = init_ima();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ rc_tmp = init_evm();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+
+ return rc;
+}
diff --git a/security/integrity/initcalls.h b/security/integrity/initcalls.h
new file mode 100644
index 000000000000..5511c62f8166
--- /dev/null
+++ b/security/integrity/initcalls.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef PLATFORM_CERTS_INITCALLS_H
+#define PLATFORM_CERTS_INITCALLS_H
+
+int integrity_fs_init(void);
+
+int init_ima(void);
+int init_evm(void);
+
+int integrity_late_init(void);
+
+#endif
--
2.50.1
More information about the Linux-security-module-archive
mailing list