[RFC PATCH 25/29] ima,evm: move initcalls to the LSM framework
John Johansen
john.johansen at canonical.com
Wed May 14 13:06:30 UTC 2025
On 4/9/25 11:50, Paul Moore wrote:
> 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 at 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
>
> 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..770d0411da2b 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,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);
> 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 55a4f08a2565..1687badafb48 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"
>
> @@ -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 */
> diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c
> index 95cc31525c57..4374fb6cc66d 100644
> --- a/security/integrity/ima/ima_mok.c
> +++ b/security/integrity/ima/ima_mok.c
> @@ -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);
> diff --git a/security/integrity/initcalls.c b/security/integrity/initcalls.c
> new file mode 100644
> index 000000000000..de39754a1c2c
> --- /dev/null
> +++ b/security/integrity/initcalls.c
> @@ -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;
if none of the below config options are defined then rc_tmp is unused and the build can kick out with
../security/integrity/initcalls.c:21:21: error: unused variable ‘rc_tmp’ [-Werror=unused-variable]
> + 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;
> +}
> diff --git a/security/integrity/initcalls.h b/security/integrity/initcalls.h
> new file mode 100644
> index 000000000000..dce16abb3b8a
> --- /dev/null
> +++ b/security/integrity/initcalls.h
> @@ -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
> diff --git a/security/integrity/platform_certs/load_ipl_s390.c b/security/integrity/platform_certs/load_ipl_s390.c
> index c7c381a9ddaa..3bf91d925614 100644
> --- a/security/integrity/platform_certs/load_ipl_s390.c
> +++ b/security/integrity/platform_certs/load_ipl_s390.c
> @@ -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);
> diff --git a/security/integrity/platform_certs/load_powerpc.c b/security/integrity/platform_certs/load_powerpc.c
> index c85febca3343..2904559e485b 100644
> --- a/security/integrity/platform_certs/load_powerpc.c
> +++ b/security/integrity/platform_certs/load_powerpc.c
> @@ -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);
> diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
> index d1fdd113450a..52c180704674 100644
> --- a/security/integrity/platform_certs/load_uefi.c
> +++ b/security/integrity/platform_certs/load_uefi.c
> @@ -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);
> diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
> index a401640a63cd..b49eb2bab7a2 100644
> --- a/security/integrity/platform_certs/machine_keyring.c
> +++ b/security/integrity/platform_certs/machine_keyring.c
> @@ -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)
> {
> diff --git a/security/integrity/platform_certs/platform_keyring.c b/security/integrity/platform_certs/platform_keyring.c
> index bcafd7387729..84a8e4309f06 100644
> --- a/security/integrity/platform_certs/platform_keyring.c
> +++ b/security/integrity/platform_certs/platform_keyring.c
> @@ -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);
More information about the Linux-security-module-archive
mailing list