@@ -226,3 +226,19 @@ This section introduces the interfaces in
``<securityfs>/integrity/diglim`` necessary to interact with DIGLIM.
.. kernel-doc:: security/integrity/diglim/fs.c
+
+
+Loader
+------
+
+Digest lists should be loaded as soon as possible, before files are
+accessed, so that services like IMA can perform their queries.
+
+The kernel loader implements two methods for loading digest lists at kernel
+initialization time. The first method takes a directory from
+CONFIG_DIGLIM_DIGEST_LISTS_DIR and executes digest_list_read() for each
+file in that directory. The second method, invoked sequentially after the
+first, executes a digest list uploader at CONFIG_DIGLIM_UPLOADER_PATH with
+the following syntax:
+
+<CONFIG_DIGLIM_UPLOADER_PATH> add <CONFIG_DIGLIM_DIGEST_LISTS_DIR>
@@ -5518,6 +5518,7 @@ F: include/uapi/linux/diglim.h
F: security/integrity/diglim/diglim.h
F: security/integrity/diglim/fs.c
F: security/integrity/diglim/ima.c
+F: security/integrity/diglim/loader.c
F: security/integrity/diglim/methods.c
F: security/integrity/diglim/parser.c
F: tools/testing/selftests/diglim/
@@ -9,3 +9,17 @@ config DIGLIM
help
DIGLIM provides reference values for file content and metadata,
that can be used for measurement and appraisal with IMA.
+
+config DIGLIM_DIGEST_LISTS_DIR
+ string "Path of the directory containing digest lists"
+ depends on DIGLIM
+ default "/etc/digest_lists"
+ help
+ This option defines the path of the directory containing digest lists.
+
+config DIGLIM_UPLOADER_PATH
+ string "Path of the user space digest list uploader"
+ depends on DIGLIM
+ default "/usr/libexec/diglim/upload_digest_lists"
+ help
+ This option defines the path of the user space digest list uploader.
@@ -5,4 +5,4 @@
obj-$(CONFIG_DIGLIM) += diglim.o
-diglim-y := methods.o parser.o ima.o fs.o
+diglim-y := methods.o parser.o ima.o fs.o loader.o
new file mode 100644
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017-2021 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Functions to load digest lists.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/namei.h>
+#include <linux/ima.h>
+
+#include "diglim.h"
+
+struct readdir_callback {
+ struct dir_context ctx;
+ struct path *path;
+};
+
+static bool digest_list_supported_by_kernel(const char *filename)
+{
+ char *type_start, *format_start, *format_end;
+
+ type_start = strchr(filename, '-');
+ if (!type_start++)
+ return false;
+
+ format_start = strchr(type_start, '-');
+ if (!format_start++)
+ return false;
+
+ format_end = strchr(format_start, '-');
+ if (!format_end)
+ return false;
+
+ if (format_end - format_start != strlen("compact") ||
+ strncmp(format_start, "compact", format_end - format_start))
+ return false;
+
+ return true;
+}
+
+static int __init digest_list_load(struct dir_context *__ctx, const char *name,
+ int namelen, loff_t offset, u64 ino,
+ unsigned int d_type)
+{
+ struct readdir_callback *ctx = container_of(__ctx, typeof(*ctx), ctx);
+ int ret;
+
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ return 0;
+
+ if (!digest_list_supported_by_kernel(name))
+ return 0;
+
+ ret = digest_list_read(ctx->path, (char *)name, DIGEST_LIST_ADD);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void digest_list_exec_parser(void)
+{
+ char *argv[4] = {NULL}, *envp[1] = {NULL};
+
+ argv[0] = (char *)CONFIG_DIGLIM_UPLOADER_PATH;
+ argv[1] = "add";
+ argv[2] = CONFIG_DIGLIM_DIGEST_LISTS_DIR;
+
+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+}
+
+void __init digest_lists_load(void)
+{
+ struct file *file;
+ struct readdir_callback buf = {
+ .ctx.actor = digest_list_load,
+ };
+
+ file = filp_open(CONFIG_DIGLIM_DIGEST_LISTS_DIR, O_RDONLY, 0);
+ if (IS_ERR(file))
+ return;
+
+ buf.path = &file->f_path;
+ iterate_dir(file, &buf.ctx);
+ fput(file);
+
+ digest_list_exec_parser();
+}
@@ -211,6 +211,7 @@ void __init integrity_load_keys(void)
if (!IS_ENABLED(CONFIG_IMA_LOAD_X509))
evm_load_x509();
+ digest_lists_load();
}
static int __init integrity_fs_init(void)
@@ -288,4 +288,12 @@ static inline void __init add_to_platform_keyring(const char *source,
{
}
#endif
+
+#ifdef CONFIG_DIGLIM
+void __init digest_lists_load(void);
+#else
+static inline void __init digest_lists_load(void)
+{
+}
+#endif
#endif /*__INTEGRITY_H*/
Digest lists should be loaded as soon as possible, before files are accessed, so that services like IMA can perform their queries. Implement two methods for loading digest lists at kernel initialization time. Take a directory from CONFIG_DIGLIM_DIGEST_LISTS_DIR and execute digest_list_read() for each file in that directory. Afterwards, execute a digest list uploader at CONFIG_DIGLIM_UPLOADER_PATH with the following syntax: <CONFIG_DIGLIM_UPLOADER_PATH> add <CONFIG_DIGLIM_DIGEST_LISTS_DIR> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> --- .../security/diglim/implementation.rst | 16 ++++ MAINTAINERS | 1 + security/integrity/diglim/Kconfig | 14 +++ security/integrity/diglim/Makefile | 2 +- security/integrity/diglim/loader.c | 92 +++++++++++++++++++ security/integrity/iint.c | 1 + security/integrity/integrity.h | 8 ++ 7 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 security/integrity/diglim/loader.c