From: Zhang Tianxing zhangtianxing3@huawei.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7QZ2M CVE: NA
-----------------------------------------------------------------
This patch fixes some issues involved with IMA digest db size patches: - use CONFIG_IMA_DIGEST_LIST to seperate db size check in ima_fs.c - remove minimum digest db size limit in Kconfig - change ima_digest_db_size data type from size_t to int, to avoid overflow - change ima_digest_db_size in ima_add_digest_data_entry and ima_del_digest_data_entry - add some debug messages
Fixes: 7c9d18bcaa ("ima: Add max size for IMA digest database") Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Reviewed-by: zhujianwei zhujianwei7@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: zhoushuiqing zhoushuiqing2@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 - arch/x86/configs/openeuler_defconfig | 1 - security/integrity/ima/Kconfig | 5 +---- security/integrity/ima/ima.h | 4 ++-- security/integrity/ima/ima_digest_list.c | 21 ++++++++++++++++----- security/integrity/ima/ima_fs.c | 12 ++++++------ 6 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 8c780d7812d5e..08ac586c81f8a 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -9556,7 +9556,6 @@ CONFIG_IMA_X509_PATH="/etc/keys/x509_ima.der" # CONFIG_IMA_APPRAISE_SIGNED_INIT is not set CONFIG_IMA_DIGEST_LIST=y CONFIG_IMA_DIGEST_LISTS_DIR="/etc/ima/digest_lists" -# CONFIG_IMA_MIN_DIGEST_DB_SIZE is not set CONFIG_IMA_STANDARD_DIGEST_DB_SIZE=y # CONFIG_IMA_MAX_DIGEST_DB_SIZE is not set # CONFIG_IMA_CUSTOM_DIGEST_DB_SIZE is not set diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index bd3bb01924f07..5f4d70de32f99 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -9682,7 +9682,6 @@ CONFIG_IMA_X509_PATH="/etc/keys/x509_ima.der" # CONFIG_IMA_APPRAISE_SIGNED_INIT is not set CONFIG_IMA_DIGEST_LIST=y CONFIG_IMA_DIGEST_LISTS_DIR="/etc/ima/digest_lists" -# CONFIG_IMA_MIN_DIGEST_DB_SIZE is not set CONFIG_IMA_STANDARD_DIGEST_DB_SIZE=y # CONFIG_IMA_MAX_DIGEST_DB_SIZE is not set # CONFIG_IMA_CUSTOM_DIGEST_DB_SIZE is not set diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index eab73b839c2af..d0d45a521083c 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -366,8 +366,6 @@ choice database. The compiled default limit can be overwritten using the kernel command line "ima_digest_db_size".
- config IMA_MIN_DIGEST_DB_SIZE - bool "minimum" config IMA_STANDARD_DIGEST_DB_SIZE bool "standard (default)" config IMA_MAX_DIGEST_DB_SIZE @@ -379,8 +377,7 @@ endchoice config IMA_DIGEST_DB_MEGABYTES int depends on IMA_DIGEST_LIST - range 8 64 - default 8 if IMA_MIN_DIGEST_DB_SIZE + range 0 64 default 16 if IMA_STANDARD_DIGEST_DB_SIZE default 64 if IMA_MAX_DIGEST_DB_SIZE
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 3d75acdc3db77..1edd7087354c0 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -61,8 +61,8 @@ extern const char boot_aggregate_name[]; extern int ima_digest_list_pcr; extern bool ima_plus_standard_pcr; extern int ima_digest_list_actions; -extern size_t ima_digest_db_max_size __ro_after_init; -extern size_t ima_digest_db_size; +extern int ima_digest_db_max_size __ro_after_init; +extern int ima_digest_db_size; #endif
/* IMA event related data */ diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 021ffda4a6f91..067f79d8799f8 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -14,7 +14,6 @@ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define MIN_DB_SIZE (8 * 1024 * 1024) #define MAX_DB_SIZE (64 * 1024 * 1024) #define DEFAULT_DB_SIZE (CONFIG_IMA_DIGEST_DB_MEGABYTES * 1024 * 1024)
@@ -29,8 +28,8 @@ #include "ima.h" #include "ima_digest_list.h"
-size_t ima_digest_db_max_size __ro_after_init = DEFAULT_DB_SIZE; -size_t ima_digest_db_size; +int ima_digest_db_max_size __ro_after_init = DEFAULT_DB_SIZE; +int ima_digest_db_size;
struct ima_h_table ima_digests_htable = { .len = ATOMIC_LONG_INIT(0), @@ -43,12 +42,13 @@ static int __init digest_db_max_size_setup(char *str) char *retptr;
size = memparse(str, &retptr); - if (size < MIN_DB_SIZE || size > MAX_DB_SIZE || *retptr != '\0') { - pr_err("DB size should range from 8M to 64M\n"); + if (size < 0 || size > MAX_DB_SIZE || *retptr != '\0') { + pr_err("digest DB size should range from 0M to 64M\n"); return 0; }
ima_digest_db_max_size = size; + pr_info_once("parse reserve digest DB memory: %s\n", str);
return 1; } @@ -118,6 +118,9 @@ static int ima_add_digest_data_entry(u8 *digest, enum hash_algo algo, if (d == NULL) return -ENOMEM;
+ ima_digest_db_size += sizeof(struct ima_digest); + ima_digest_db_size += digest_len; + d->algo = algo; d->type = type; d->modifiers = modifiers; @@ -141,6 +144,9 @@ static void ima_del_digest_data_entry(u8 *digest, enum hash_algo algo, if (--d->count > 0) return;
+ ima_digest_db_size -= sizeof(struct ima_digest); + ima_digest_db_size -= hash_digest_size[algo]; + hlist_del_rcu(&d->hnext); atomic_long_dec(&ima_digests_htable.len); kfree(d); @@ -349,6 +355,11 @@ static bool __init load_digest_list(struct dir_context *__ctx, const char *name,
size = ret;
+ if (size > ima_digest_db_max_size - ima_digest_db_size) { + pr_err_once("digest DB is full: %d\n", ima_digest_db_size); + goto out_fput; + } + ima_check_measured_appraised(file);
ret = ima_parse_compact_list(size, datap, DIGEST_LIST_OP_ADD); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index e531ee4838d4e..237628466eb38 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -373,6 +373,7 @@ static ssize_t ima_read_policy(char *path) /* Only check size when adding digest lists */ if (dentry == digest_list_data && size > ima_digest_db_max_size - ima_digest_db_size) { + pr_err("digest DB is full: %d\n", ima_digest_db_size); rc = -ENOMEM; break; } @@ -394,14 +395,13 @@ static ssize_t ima_read_policy(char *path) #endif if (rc < 0) break; - size -= rc; - #ifdef CONFIG_IMA_DIGEST_LIST - if (dentry == digest_list_data) - ima_digest_db_size += rc; - if (dentry == digest_list_data_del) - ima_digest_db_size -= rc; + else if (dentry == digest_list_data) + pr_debug("digest imported, current DB size: %d\n", ima_digest_db_size); + else if (dentry == digest_list_data_del) + pr_debug("digest deleted, current DB size: %d\n", ima_digest_db_size); #endif + size -= rc; }
vfree(data);