From: Zhang Tianxing zhangtianxing3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I409K9 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 | 4 +++ security/integrity/ima/ima_digest_list.c | 23 ++++++++++++++++ security/integrity/ima/ima_fs.c | 11 ++++++++ 7 files changed, 79 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index e92e899ae964..4a0261de0ed8 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1975,6 +1975,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 1cb5960fa52f..168a101cb64a 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -7005,6 +7005,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 fac5531742a4..599b8fac2c4b 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -8251,6 +8251,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 aa6a06f3e8b1..eab73b839c2a 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 124b4e78a784..d19d322309fb 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -60,6 +60,10 @@ extern int ima_digest_list_pcr; extern bool ima_plus_standard_pcr; extern const char boot_aggregate_name[]; extern int ima_digest_list_actions; +#ifdef CONFIG_IMA_DIGEST_LIST +extern size_t ima_digest_db_max_size __ro_after_init; +extern size_t ima_digest_db_size; +#endif
/* IMA event related data */ struct ima_event_data { diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 5aaea24571d9..021ffda4a6f9 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 7310683a7af7..66574a79ac97 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -319,6 +319,12 @@ static ssize_t ima_read_file(char *path, struct dentry *dentry) 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. @@ -334,6 +340,11 @@ static ssize_t ima_read_file(char *path, struct dentry *dentry) if (rc < 0) break; size -= rc; + + if (dentry == digest_list_data) + ima_digest_db_size += rc; + if (dentry == digest_list_data_del) + ima_digest_db_size -= rc; }
vfree(data);