From a5d265667ad84155eba7a6c965decd83bc18d5b9 Mon Sep 17 00:00:00 2001 From: James Morse Date: Thu, 16 Apr 2020 11:05:05 +0800 Subject: [PATCH 2870/2944] openEuler: ACPI / PPTT: Add helper to validate cache nodes from an offset [dead] commit 3ec28b81de7f3d17f0f253d4ec0f7e6c068cc0c8 openEuler-1.0 hulk inclusion category: feature bugzilla: 28055 CVE: NA ------------------------------ The MPAM table holds a PPTT-offset that describes a cache. Add a helper acpi_pptt_validate_cache_node(), which checks this offset really is in the PPTT, on a node boundary, and that node really is a cache. With this the MPAM probe code can go poking through struct cacheinfo looking for a level with a matching firmware_node. Signed-off-by: James Morse Signed-off-by: Wang ShaoBo Reviewed-By: Xie XiuQi Signed-off-by: Yang Yingliang Signed-off-by: Xin Hao Reviewed-by: Baolin Wang --- drivers/acpi/pptt.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 4 ++++ 2 files changed, 42 insertions(+) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 750295c..f0aa0b4 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -280,6 +280,44 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he return NULL; } +/** + * acpi_validate_cache_node() - Given an offset in the table, check this is + * a cache node. + * Used for cross-table pointers. + * + * Return the cache pointer for a valid cache, or NULL. + */ +struct acpi_pptt_cache * +acpi_pptt_validate_cache_node(struct acpi_table_header *table_hdr, u32 offset) +{ + struct acpi_subtable_header *entry, *cache; + unsigned long table_end; + + if ((offset < sizeof(*table_hdr)) || (offset >= table_hdr->length)) + return NULL; + + table_end = (unsigned long)table_hdr + table_hdr->length; + entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, + sizeof(struct acpi_table_pptt)); + + cache = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, offset); + + /* Walk every node to check offset is on a node boundary */ + while ((unsigned long)(entry + 1) < table_end) { + if (entry->length == 0) { + pr_err("Invalid zero length subtable\n"); + break; + } + if ((entry->type == ACPI_PPTT_TYPE_CACHE) && (entry == cache)) + return (struct acpi_pptt_cache *)entry; + + entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, + entry->length); + } + + return NULL; +} + static int acpi_find_cache_levels(struct acpi_table_header *table_hdr, u32 acpi_cpu_id) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 2ed8bbe..63fb5bc 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -664,6 +664,10 @@ static inline u64 acpi_arch_get_root_pointer(void) } #endif +struct acpi_pptt_cache * +acpi_pptt_validate_cache_node(struct acpi_table_header *table_hdr, + u32 offset); + #else /* !CONFIG_ACPI */ #define acpi_disabled 1 -- 1.8.3.1