From b27bee6f53bf6ca7eea08dadc5bd053d52807ff4 Mon Sep 17 00:00:00 2001 From: fengsheng Date: Tue, 17 Dec 2019 18:45:40 +0800 Subject: [PATCH] drivers : sysctl fixup memory usage issues driver inclusion category: Bugfix bugzilla: NA CVE: NA 1. fixup Memory use after free issue when driver uninstall 2. ut_hisi_sysctl_get_hllc_crc_ecc add input parameter judgment Signed-off-by: fengsheng Reviewed-by: zhangmu Signed-off-by: Yang Yingliang --- drivers/soc/hisilicon/sysctl/sysctl_drv.c | 6 ++- .../soc/hisilicon/sysctl/sysctl_local_ras.c | 42 +++++++++++-------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/soc/hisilicon/sysctl/sysctl_drv.c b/drivers/soc/hisilicon/sysctl/sysctl_drv.c index b07cab02a423..75d75228ce1f 100644 --- a/drivers/soc/hisilicon/sysctl/sysctl_drv.c +++ b/drivers/soc/hisilicon/sysctl/sysctl_drv.c @@ -48,9 +48,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define DEBUG -#define SYSCTL_DRIVER_VERSION "1.8.15.0" +#define SYSCTL_DRIVER_VERSION "1.8.15.2" -/* debug���� */ unsigned int g_sysctrl_debug; /* sysctrl reg base address */ @@ -668,6 +667,9 @@ unsigned long ut_hisi_sysctl_get_hllc_crc_ecc(u8 chip_id, u32 hllc_id) unsigned int ret; hllc_crc_ecc_info hllc_crc_ecc; + if (hllc_id >= HLLC_NUM_MAX) + return SYSCTL_ERR_PARAM; /* the upper 32 bits. */ + memset(&hllc_crc_ecc, 0, sizeof(hllc_crc_ecc_info)); ret = hisi_sysctl_get_hllc_crc_ecc(chip_id, &hllc_crc_ecc); pr_info("hllc_crc_ecc.hllc_crc_ecc[%d]:0x%x.\n", hllc_id, hllc_crc_ecc.hllc_crc_ecc[hllc_id]); diff --git a/drivers/soc/hisilicon/sysctl/sysctl_local_ras.c b/drivers/soc/hisilicon/sysctl/sysctl_local_ras.c index 81926f166b40..0e38e82d2a34 100644 --- a/drivers/soc/hisilicon/sysctl/sysctl_local_ras.c +++ b/drivers/soc/hisilicon/sysctl/sysctl_local_ras.c @@ -126,17 +126,17 @@ static int sysctl_tdh_mem_access_open(u8 chip_id) static inline bool sysctl_is_hest_type_generic_v2(struct ghes *ghes) { - return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2; + return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2; } static int sysctl_map_gen_v2(const struct ghes *ghes) { - return apei_map_generic_address(&ghes->generic_v2->read_ack_register); + return apei_map_generic_address(&ghes->generic_v2->read_ack_register); } static void sysctl_unmap_gen_v2(const struct ghes *ghes) { - apei_unmap_generic_address(&ghes->generic_v2->read_ack_register); + apei_unmap_generic_address(&ghes->generic_v2->read_ack_register); } static int sysctl_correlation_reg_report(const struct hisi_oem_type1_err_sec *ras_cper) { @@ -381,15 +381,6 @@ static int sysctl_ghes_read_estatus(struct ghes *sysctl_ghes, int silent) goto error_read_block; } - pr_info("[INFO] SYSCTL RAS HISILICON Error : ghes source id is %d.\n", - sysctl_ghes->generic->header.source_id); - pr_info("[INFO] SYSCTL RAS HISILICON Error : error status addr is 0x%llx.\n", - sysctl_ghes->buffer_paddr); - pr_info("[INFO] SYSCTL RAS HISILICON Error : data_length is %d.\n", - sysctl_ghes->estatus->data_length); - pr_info("[INFO] SYSCTL RAS HISILICON Error : severity is %d.\n", - sysctl_ghes->estatus->error_severity); - if (cper_estatus_check(sysctl_ghes->estatus)) { pr_err("[ERROR] SYSCTL RAS cper_estatus_check fail.\n"); goto error_read_block; @@ -467,8 +458,6 @@ static int sysctl_hisi_error_handler(struct work_struct *work) struct ghes *sysctl_ghes = NULL; (void)work; - pr_info("[INFO] SYSCTL RAS %s start.\n", __func__); - rcu_read_lock(); list_for_each_entry_rcu(sysctl_ghes, &hisi_ghes_list, list) { if (!sysctl_ghes_proc(sysctl_ghes)) @@ -476,9 +465,6 @@ static int sysctl_hisi_error_handler(struct work_struct *work) } rcu_read_unlock(); - pr_info("[INFO] SYSCTL RAS sysctl_ghes_proc ret: %d.\n", ret); - pr_info("[INFO] SYSCTL RAS %s end.\n", __func__); - return ret; } @@ -559,6 +545,7 @@ int hip_sysctl_local_ras_init(void) static void his_ghes_list_free(void) { struct ghes *node = NULL; + struct ghes *tmp_node = NULL; rcu_read_lock(); list_for_each_entry_rcu(node, &hisi_ghes_list, list) { @@ -574,8 +561,27 @@ static void his_ghes_list_free(void) if (sysctl_is_hest_type_generic_v2(node)) sysctl_unmap_gen_v2(node); - kfree(node); + /* Release the node of the previous loop. */ + if (tmp_node != NULL) { + kfree(tmp_node); + tmp_node = NULL; + } + + /* Record the node of the current loop. */ + tmp_node = node; + + /* hisi_ghes_list isn't a member of node. */ + if (node->list.next == &hisi_ghes_list) { + node = NULL; + break; + } } + + if (tmp_node != NULL) { + kfree(tmp_node); + tmp_node = NULL; + } + rcu_read_unlock(); } -- GitLab