From: Zhang Tianxing zhangtianxing3@huawei.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7QZ2M CVE: NA
-----------------------------------------------------------------
This patch sets max size for IMA digest database to prevent OOM.
A __ro_after_init global variable ima_digest_db_max_size is used to set the maximum data uploaded to digest database.
Another global variable ima_digest_db_size records the data uploaded to kernel digest database and increments when uploading digest lists.
Signed-off-by: Zhang Tianxing zhangtianxing3@huawei.com Reviewed-by: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Signed-off-by: zhoushuiqing zhoushuiqing2@huawei.com --- .../admin-guide/kernel-parameters.txt | 4 +++ arch/arm64/configs/openeuler_defconfig | 5 ++++ arch/x86/configs/openeuler_defconfig | 5 ++++ security/integrity/ima/Kconfig | 27 +++++++++++++++++++ security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_digest_list.c | 23 ++++++++++++++++ security/integrity/ima/ima_fs.c | 13 +++++++++ 7 files changed, 79 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 84fe3bc6c..eefb460d3 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1984,6 +1984,10 @@ with PCR 10, according to the existing behavior. Format: { [+]<unsigned int> }
+ ima_digest_db_size=nn[M] + [IMA] + Sets the maximum data uploaded to IMA digest database. + ima_hash= [IMA] Format: { md5 | sha1 | rmd160 | sha256 | sha384 | sha512 | ... } diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 447b264a2..1c42b5fea 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -7017,6 +7017,11 @@ 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 +CONFIG_IMA_DIGEST_DB_SIZE=16 CONFIG_IMA_PARSER_BINARY_PATH="/usr/bin/upload_digest_lists" CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index afbf7a850..e3695853a 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -8264,6 +8264,11 @@ 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 +CONFIG_IMA_DIGEST_DB_SIZE=16 CONFIG_IMA_PARSER_BINARY_PATH="/usr/bin/upload_digest_lists" CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index aa6a06f3e..eab73b839 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -357,6 +357,33 @@ config IMA_DIGEST_LISTS_DIR This option defines the path of the directory containing digest lists.
+choice + prompt "Defalut maximum data uploaded to the IMA digest database" + default IMA_STANDARD_DIGEST_DB_SIZE + depends on IMA_DIGEST_LIST + help + This option defines the maximum data uploaded to the IMA digest + 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 + bool "maximum" + config IMA_CUSTOM_DIGEST_DB_SIZE + bool "custom" +endchoice + +config IMA_DIGEST_DB_MEGABYTES + int + depends on IMA_DIGEST_LIST + range 8 64 + default 8 if IMA_MIN_DIGEST_DB_SIZE + default 16 if IMA_STANDARD_DIGEST_DB_SIZE + default 64 if IMA_MAX_DIGEST_DB_SIZE + config IMA_PARSER_BINARY_PATH string "Path of the parser binary" depends on IMA_DIGEST_LIST diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9ba7bff50..3d75acdc3 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -61,6 +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; #endif
/* IMA event related data */ diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 5aaea2457..021ffda4a 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -14,6 +14,9 @@ */
#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)
#include <linux/vmalloc.h> #include <linux/module.h> @@ -26,11 +29,31 @@ #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; + struct ima_h_table ima_digests_htable = { .len = ATOMIC_LONG_INIT(0), .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT };
+static int __init digest_db_max_size_setup(char *str) +{ + int size; + 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"); + return 0; + } + + ima_digest_db_max_size = size; + + return 1; +} +__setup("ima_digest_db_size=", digest_db_max_size_setup); + static int __init digest_list_pcr_setup(char *str) { int pcr, ret; diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 2b8291351..7a20c567f 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -369,6 +369,12 @@ static ssize_t ima_read_policy(char *path) rc = ima_parse_add_rule(p); } else if (dentry == digest_list_data || dentry == digest_list_data_del) { + /* Only check size when adding digest lists */ + if (dentry == digest_list_data && + size > ima_digest_db_max_size - ima_digest_db_size) { + rc = -ENOMEM; + break; + } /* * Disable usage of digest lists if not measured * or appraised. @@ -388,6 +394,13 @@ static ssize_t ima_read_policy(char *path) 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; +#endif }
vfree(data);