hulk inclusion category: feature feature: digest-lists
---------------------------
This patch limits the digest lists processed by the kernel. It excludes digest lists not in the compact format, and those without security.evm or without IMA signature.
ima_check_measured_appraised() is called at the end of ima_file_check() to verify that everything accessed by the user space parser (except for directories and securityfs) has been processed by IMA. If a digest list was not processed by an IMA submodule, digest list lookup is disabled for that submodule.
Signed-off-by: Roberto Sassu roberto.sassu@huawei.com --- security/integrity/ima/Kconfig | 7 ++++ security/integrity/ima/ima_digest_list.c | 41 ++++++++++++++++++++++++ security/integrity/ima/ima_main.c | 10 ++++-- 3 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 5fe5f67b2e18..00486c2d7090 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -305,3 +305,10 @@ config IMA_DIGEST_LISTS_DIR help This option defines the path of the directory containing digest lists. + +config IMA_PARSER_BINARY_PATH + string "Path of the parser binary" + depends on IMA_DIGEST_LIST + default "/usr/bin/upload_digest_lists" + help + This option defines the path of the parser binary. diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 11d00fe63ffb..cbb55d58cdb2 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/file.h> #include <linux/namei.h> +#include <linux/xattr.h> #include <linux/sched/mm.h> #include <linux/magic.h>
@@ -271,6 +272,8 @@ static int __init load_digest_list(struct dir_context *__ctx, const char *name, struct readdir_callback *ctx = container_of(__ctx, typeof(*ctx), ctx); struct path *dir = ctx->path; struct file *file; + u8 *xattr_value = NULL; + char *type_start, *format_start, *format_end; void *datap; loff_t size; int ret; @@ -278,12 +281,36 @@ static int __init load_digest_list(struct dir_context *__ctx, const char *name, if (!strcmp(name, ".") || !strcmp(name, "..")) return 0;
+ type_start = strchr(name, '-'); + if (!type_start) + return 0; + + format_start = strchr(type_start + 1, '-'); + if (!format_start) + return 0; + + format_end = strchr(format_start + 1, '-'); + if (!format_end) + return 0; + + if (format_end - format_start - 1 != strlen("compact") || + strncmp(format_start + 1, "compact", format_end - format_start - 1)) + return 0; + file = file_open_root(dir->dentry, dir->mnt, name, O_RDONLY, 0); if (IS_ERR(file)) { pr_err("Unable to open file: %s (%ld)", name, PTR_ERR(file)); return 0; }
+ size = vfs_getxattr(file_dentry(file), XATTR_NAME_EVM, NULL, 0); + if (size < 0) { + size = vfs_getxattr_alloc(file_dentry(file), XATTR_NAME_IMA, + (char **)&xattr_value, 0, GFP_NOFS); + if (size < 0 || xattr_value[0] != EVM_IMA_XATTR_DIGSIG) + goto out; + } + ret = kernel_read_file(file, &datap, &size, 0, READING_DIGEST_LIST); if (ret < 0) { pr_err("Unable to read file: %s (%d)", name, ret); @@ -299,9 +326,21 @@ static int __init load_digest_list(struct dir_context *__ctx, const char *name, vfree(datap); out: fput(file); + kfree(xattr_value); return 0; }
+static void ima_exec_parser(void) +{ + char *argv[4] = {NULL}, *envp[1] = {NULL}; + + argv[0] = (char *)CONFIG_IMA_PARSER_BINARY_PATH; + argv[1] = "add"; + argv[2] = (char *)CONFIG_IMA_DIGEST_LISTS_DIR; + + call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); +} + void __init ima_load_digest_lists(void) { struct path path; @@ -327,6 +366,8 @@ void __init ima_load_digest_lists(void) fput(file); out: path_put(&path); + + ima_exec_parser(); }
/**************** diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index a386a5bf1ed9..4875c6db7793 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -460,11 +460,15 @@ int ima_bprm_check(struct linux_binprm *bprm) int ima_file_check(struct file *file, int mask) { u32 secid; + int rc;
security_task_getsecid(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, 0, - mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK); + rc = process_measurement(file, current_cred(), secid, NULL, 0, + mask & (MAY_READ | MAY_WRITE | MAY_EXEC | + MAY_APPEND), FILE_CHECK); + if (ima_current_is_parser() && !rc) + ima_check_measured_appraised(file); + return rc; } EXPORT_SYMBOL_GPL(ima_file_check);