@@ -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
@@ -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,6 @@ DEFINE_LSM(evm) = {
.init = init_evm_lsm,
.order = LSM_ORDER_LAST,
.blobs = &evm_blob_sizes,
+ .initcall_device = integrity_device_init,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_evm);
@@ -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)
@@ -27,6 +27,7 @@
#include <linux/fs.h>
#include <linux/iversion.h>
#include <linux/evm.h>
+#include "../initcalls.h"
#include "ima.h"
@@ -1180,7 +1181,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;
@@ -1255,6 +1256,6 @@ DEFINE_LSM(ima) = {
.init = init_ima_lsm,
.order = LSM_ORDER_LAST,
.blobs = &ima_blob_sizes,
+ .initcall_device = integrity_device_init,
+ .initcall_late = integrity_late_init,
};
-
-late_initcall(init_ima); /* Start IMA after the TPM is available */
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <keys/system_keyring.h>
+#include "../initcalls.h"
struct key *ima_blacklist_keyring;
@@ -21,7 +22,7 @@ struct key *ima_blacklist_keyring;
/*
* Allocate the IMA blacklist keyring
*/
-static __init int ima_mok_init(void)
+int __init ima_mok_init(void)
{
struct key_restriction *restriction;
@@ -46,4 +47,3 @@ static __init int ima_mok_init(void)
panic("Can't allocate IMA blacklist keyring.");
return 0;
}
-device_initcall(ima_mok_init);
new file mode 100644
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Platform certificate / keyring initcalls
+ *
+ */
+
+#include <linux/init.h>
+
+#include "initcalls.h"
+
+/**
+ * integrity_device_init - device_initcalls for IMA/EVM
+ *
+ * This helper function wraps all of the device_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_device_init(void)
+{
+ int rc = 0, rc_tmp;
+ static bool setup = false;
+
+ if (setup)
+ return 0;
+ setup = true;
+
+#if defined(CONFIG_INTEGRITY_PLATFORM_KEYRING)
+ rc_tmp = platform_keyring_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+#if defined(CONFIG_INTEGRITY_MACHINE_KEYRING)
+ rc_tmp = machine_keyring_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+#if defined(CONFIG_IMA_BLACKLIST_KEYRING)
+ rc_tmp = ima_mok_init();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+ return rc;
+}
+
+/**
+ * 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;
+
+#if defined(CONFIG_LOAD_UEFI_KEYS)
+ rc_tmp = load_uefi_certs();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+#if defined(CONFIG_LOAD_IPL_KEYS)
+ rc_tmp = load_ipl_certs();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+#if defined(CONFIG_LOAD_PPC_KEYS)
+ rc_tmp = load_powerpc_certs();
+ if (!rc && rc_tmp)
+ rc = rc_tmp;
+#endif
+
+ 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;
+}
new file mode 100644
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef PLATFORM_CERTS_INITCALLS_H
+#define PLATFORM_CERTS_INITCALLS_H
+
+int machine_keyring_init(void);
+int platform_keyring_init(void);
+
+int load_uefi_certs(void);
+int load_ipl_certs(void);
+int load_powerpc_certs(void);
+
+int integrity_fs_init(void);
+
+int init_ima(void);
+int init_evm(void);
+
+int ima_mok_init(void);
+
+int integrity_device_init(void);
+int integrity_late_init(void);
+
+#endif
@@ -10,12 +10,13 @@
#include <keys/system_keyring.h>
#include <asm/boot_data.h>
#include "../integrity.h"
+#include "../initcalls.h"
/*
* Load the certs contained in the IPL report created by the machine loader
* into the platform trusted keyring.
*/
-static int __init load_ipl_certs(void)
+int __init load_ipl_certs(void)
{
void *ptr, *end;
unsigned int len;
@@ -33,4 +34,3 @@ static int __init load_ipl_certs(void)
}
return 0;
}
-late_initcall(load_ipl_certs);
@@ -14,6 +14,7 @@
#include <asm/secvar.h>
#include "keyring_handler.h"
#include "../integrity.h"
+#include "../initcalls.h"
#define extract_esl(db, data, size, offset) \
do { db = data + offset; size = size - offset; } while (0)
@@ -56,7 +57,7 @@ static __init void *get_cert_list(u8 *key, unsigned long keylen, u64 *size)
* keyring and the blacklisted X.509 cert SHA256 hashes into the blacklist
* keyring.
*/
-static int __init load_powerpc_certs(void)
+int __init load_powerpc_certs(void)
{
void *db = NULL, *dbx = NULL, *data = NULL;
void *trustedca;
@@ -156,4 +157,3 @@ static int __init load_powerpc_certs(void)
return rc;
}
-late_initcall(load_powerpc_certs);
@@ -12,6 +12,7 @@
#include <keys/system_keyring.h>
#include "../integrity.h"
#include "keyring_handler.h"
+#include "../initcalls.h"
/*
* On T2 Macs reading the db and dbx efi variables to load UEFI Secure Boot
@@ -157,7 +158,7 @@ static int __init load_moklist_certs(void)
* keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
* keyring.
*/
-static int __init load_uefi_certs(void)
+int __init load_uefi_certs(void)
{
efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
@@ -235,4 +236,3 @@ static int __init load_uefi_certs(void)
return rc;
}
-late_initcall(load_uefi_certs);
@@ -7,8 +7,9 @@
#include <linux/efi.h>
#include "../integrity.h"
+#include "../initcalls.h"
-static __init int machine_keyring_init(void)
+int __init machine_keyring_init(void)
{
int rc;
@@ -19,7 +20,6 @@ static __init int machine_keyring_init(void)
pr_notice("Machine keyring initialized\n");
return 0;
}
-device_initcall(machine_keyring_init);
void __init add_to_machine_keyring(const char *source, const void *data, size_t len)
{
@@ -13,6 +13,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include "../integrity.h"
+#include "../initcalls.h"
/**
* add_to_platform_keyring - Add to platform keyring without validation.
@@ -37,10 +38,12 @@ void __init add_to_platform_keyring(const char *source, const void *data,
pr_info("Error adding keys to platform keyring %s\n", source);
}
-/*
- * Create the trusted keyrings.
+/**
+ * platform_keyring_init - Create the trusted keyrings.
+ *
+ * Must be initialised before we try and load the keys into the keyring.
*/
-static __init int platform_keyring_init(void)
+int __init platform_keyring_init(void)
{
int rc;
@@ -51,8 +54,3 @@ static __init int platform_keyring_init(void)
pr_notice("Platform Keyring initialized\n");
return 0;
}
-
-/*
- * Must be initialised before we try and load the keys into the keyring.
- */
-device_initcall(platform_keyring_init);
This patch converts IMA and EVM to use the LSM frameworks's initcall mechanism. There were two challenges to doing this conversion: the first simply being the number of initcalls across IMA and EVM, and the second was the number of resources shared between the two related, yet independent LSMs. The first problem was resolved by the creation of two new functions, integrity_device_init() and integrity_late_init(), with each focused on calling all of the various IMA/EVM initcalls for a single initcall type. The second problem was resolved by registering both of these new functions as initcalls for each LSM and including code in each registered initcall to ensure it only executes once. Signed-off-by: Paul Moore <paul@paul-moore.com> --- security/integrity/Makefile | 2 +- security/integrity/evm/evm_main.c | 7 +- security/integrity/iint.c | 4 +- security/integrity/ima/ima_main.c | 7 +- security/integrity/ima/ima_mok.c | 4 +- security/integrity/initcalls.c | 97 +++++++++++++++++++ security/integrity/initcalls.h | 23 +++++ .../integrity/platform_certs/load_ipl_s390.c | 4 +- .../integrity/platform_certs/load_powerpc.c | 4 +- security/integrity/platform_certs/load_uefi.c | 4 +- .../platform_certs/machine_keyring.c | 4 +- .../platform_certs/platform_keyring.c | 14 ++- 12 files changed, 147 insertions(+), 27 deletions(-) create mode 100644 security/integrity/initcalls.c create mode 100644 security/integrity/initcalls.h