From: Paul Moore <p...@paul-moore.com>

This patch converts IMA and EVM to use the LSM frameworks's initcall
mechanism. It moved the integrity_fs_init() call to ima_fs_init() and
evm_init_secfs(), to work around the fact that there is no "integrity" LSM,
and introduced integrity_fs_fini() to remove the integrity directory, if
empty. Both integrity_fs_init() and integrity_fs_fini() support the
scenario of being called by both the IMA and EVM LSMs.

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: Roberto Sassu <roberto.sa...@huawei.com>
---
 security/integrity/evm/evm_main.c  |  3 +--
 security/integrity/evm/evm_secfs.c | 11 +++++++++--
 security/integrity/iint.c          | 14 ++++++++++++--
 security/integrity/ima/ima_fs.c    | 11 +++++++++--
 security/integrity/ima/ima_main.c  |  4 ++--
 security/integrity/integrity.h     |  2 ++
 6 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/security/integrity/evm/evm_main.c 
b/security/integrity/evm/evm_main.c
index db8e324ed4e6..73d500a375cb 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -1179,6 +1179,5 @@ DEFINE_LSM(evm) = {
        .init = init_evm_lsm,
        .order = LSM_ORDER_LAST,
        .blobs = &evm_blob_sizes,
+       .initcall_late = init_evm,
 };
-
-late_initcall(init_evm);
diff --git a/security/integrity/evm/evm_secfs.c 
b/security/integrity/evm/evm_secfs.c
index b0d2aad27850..c26724690cec 100644
--- a/security/integrity/evm/evm_secfs.c
+++ b/security/integrity/evm/evm_secfs.c
@@ -302,10 +302,16 @@ int __init evm_init_secfs(void)
        int error = 0;
        struct dentry *dentry;
 
-       evm_dir = securityfs_create_dir("evm", integrity_dir);
-       if (IS_ERR(evm_dir))
+       error = integrity_fs_init();
+       if (error < 0)
                return -EFAULT;
 
+       evm_dir = securityfs_create_dir("evm", integrity_dir);
+       if (IS_ERR(evm_dir)) {
+               error = -EFAULT;
+               goto out;
+       }
+
        dentry = securityfs_create_file("evm", 0660,
                                      evm_dir, NULL, &evm_key_ops);
        if (IS_ERR(dentry)) {
@@ -329,5 +335,6 @@ int __init evm_init_secfs(void)
 out:
        securityfs_remove(evm_symlink);
        securityfs_remove(evm_dir);
+       integrity_fs_fini();
        return error;
 }
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 068ac6c2ae1e..8ec1a3436a71 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -42,8 +42,11 @@ void __init integrity_load_keys(void)
                evm_load_x509();
 }
 
-static int __init integrity_fs_init(void)
+int __init integrity_fs_init(void)
 {
+       if (integrity_dir)
+               return 0;
+
        integrity_dir = securityfs_create_dir("integrity", NULL);
        if (IS_ERR(integrity_dir)) {
                int ret = PTR_ERR(integrity_dir);
@@ -58,4 +61,11 @@ static int __init integrity_fs_init(void)
        return 0;
 }
 
-late_initcall(integrity_fs_init)
+void __init integrity_fs_fini(void)
+{
+       if (!integrity_dir || !simple_empty(integrity_dir))
+               return;
+
+       securityfs_remove(integrity_dir);
+       integrity_dir = NULL;
+}
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 87045b09f120..012a58959ff0 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -499,9 +499,15 @@ int __init ima_fs_init(void)
        struct dentry *dentry;
        int ret;
 
+       ret = integrity_fs_init();
+       if (ret < 0)
+               return ret;
+
        ima_dir = securityfs_create_dir("ima", integrity_dir);
-       if (IS_ERR(ima_dir))
-               return PTR_ERR(ima_dir);
+       if (IS_ERR(ima_dir)) {
+               ret = PTR_ERR(ima_dir);
+               goto out;
+       }
 
        ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima",
                                                NULL);
@@ -555,6 +561,7 @@ int __init ima_fs_init(void)
 out:
        securityfs_remove(ima_symlink);
        securityfs_remove(ima_dir);
+       integrity_fs_fini();
 
        return ret;
 }
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index eade8e1e3cb1..b703bfc2f470 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1283,6 +1283,6 @@ DEFINE_LSM(ima) = {
        .init = init_ima_lsm,
        .order = LSM_ORDER_LAST,
        .blobs = &ima_blob_sizes,
+       /* Start IMA after the TPM is available */
+       .initcall_late = init_ima,
 };
-
-late_initcall(init_ima);       /* Start IMA after the TPM is available */
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c2c2da691123..7b388b66cf80 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -114,6 +114,8 @@ struct ima_file_id {
 
 int integrity_kernel_read(struct file *file, loff_t offset,
                          void *addr, unsigned long count);
+int __init integrity_fs_init(void);
+void __init integrity_fs_fini(void);
 
 #define INTEGRITY_KEYRING_EVM          0
 #define INTEGRITY_KEYRING_IMA          1
-- 
2.43.0


Reply via email to