From 922a4aced7967cbdee8b7716f188de008e75f9f9 Mon Sep 17 00:00:00 2001
From: Xue <xuechaojing@huawei.com>
Date: Tue, 14 May 2019 21:01:39 +0800
Subject: [PATCH 2765/2944] openeuler: net: hinic:fix bug in dbgtool

commit 4a7812da7d7d228896f51502b0a0b92ddc5e820 openEuler-1.0

driver inclusion
category:bugfix
bugzilla:4472
CVE:NA

------------------------------------------------------------------------

1.fix bug in dbgtool init
2.add address security check in hinic_mem_mmap.

Reviewed-by: chiqijun <chiqijun@huawei.com>
Signed-off-by: Xue <xuechaojing@huawei.com>
Reviewed-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Signed-off-by: Xin Hao <haoxing990@gmail.com>
Reviewed-by: Baolin Wang <baolin.wang@openanolis.org>
---
 .../net/ethernet/huawei/hinic/hinic_dbgtool_knl.c  | 33 +++++++++++++++++-----
 drivers/net/ethernet/huawei/hinic/hinic_lld.c      | 25 ++++++++++++++++
 drivers/net/ethernet/huawei/hinic/hinic_lld.h      |  1 +
 drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h  |  2 +-
 4 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
index ff43c04..027fb01 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dbgtool_knl.c
@@ -33,6 +33,7 @@
 #include "hinic_hwdev.h"
 #include "hinic_hw_mgmt.h"
 #include "hinic_nic_dev.h"
+#include "hinic_lld.h"
 #include "hinic_dbgtool_knl.h"
 
 struct ffm_intr_info {
@@ -104,6 +105,18 @@ static ssize_t dbgtool_knl_write(struct file *pfile,
 	return 0;
 }
 
+static bool is_valid_phy_addr(u64 offset)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_CARD_NUM; i++) {
+		if (offset == g_card_phy_addr[i])
+			return true;
+	}
+
+	return false;
+}
+
 int hinic_mem_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	unsigned long vmsize = vma->vm_end - vma->vm_start;
@@ -115,10 +128,12 @@ int hinic_mem_mmap(struct file *filp, struct vm_area_struct *vma)
 		return -EAGAIN;
 	}
 
-	if (offset && offset != g_card_phy_addr[card_id]) {
+	if (offset && !is_valid_phy_addr((u64)offset) &&
+	    !hinic_is_valid_bar_addr((u64)offset)) {
 		pr_err("offset is invalid\n");
 		return -EAGAIN;
 	}
+
 	/* old version of tool set vma->vm_pgoff to 0 */
 	phy_addr = offset ? offset : g_card_phy_addr[card_id];
 
@@ -143,7 +158,7 @@ int hinic_mem_mmap(struct file *filp, struct vm_area_struct *vma)
 long dbgtool_knl_api_cmd_read(struct dbgtool_param *para,
 			      void **g_func_handle_array)
 {
-	long ret;
+	long ret = 0;
 	u8 *cmd;
 	u16 size;
 	void *ack;
@@ -224,7 +239,7 @@ long dbgtool_knl_api_cmd_read(struct dbgtool_param *para,
 long dbgtool_knl_api_cmd_write(struct dbgtool_param *para,
 			       void **g_func_handle_array)
 {
-	long ret;
+	long ret = 0;
 	u8 *cmd;
 	u16 size;
 	u32 pf_id;
@@ -410,7 +425,7 @@ long dbgtool_knl_ffm_info_clr(struct dbgtool_param *para,
 long dbgtool_knl_msg_to_up(struct dbgtool_param *para,
 			   void **g_func_handle_array)
 {
-	long ret;
+	long ret = 0;
 	void *buf_in;
 	void *buf_out;
 	u16 out_size;
@@ -525,7 +540,7 @@ long dbgtool_knl_unlocked_ioctl(struct file *pfile,
 				unsigned int cmd,
 				unsigned long arg)
 {
-	long ret;
+	long ret = 0;
 	unsigned int real_cmd;
 	struct dbgtool_param param;
 	struct dbgtool_k_glb_info *dbgtool_info;
@@ -723,6 +738,7 @@ int dbgtool_knl_init(void *vhwdev, void *chip_node)
 			kzalloc(sizeof(struct dbgtool_k_glb_info), GFP_KERNEL);
 	if (!dbgtool_info) {
 		pr_err("Failed to allocate dbgtool_info\n");
+		ret = -EFAULT;
 		goto dbgtool_info_fail;
 	}
 	chip_info->dbgtool_info = dbgtool_info;
@@ -733,15 +749,17 @@ int dbgtool_knl_init(void *vhwdev, void *chip_node)
 					GFP_KERNEL);
 	if (!dbgtool_info->ffm) {
 		pr_err("Failed to allocate cell contexts for a chain\n");
+		ret = -EFAULT;
 		goto dbgtool_info_ffm_fail;
 	}
 
 	sema_init(&dbgtool_info->dbgtool_sem, 1);
 
 	ret = sscanf(chip_info->chip_name, HINIC_CHIP_NAME "%d", &id);
-	if (ret < 0)
+	if (ret < 0) {
 		pr_err("Failed to get hinic id\n");
-
+		goto sscanf_chdev_fail;
+	}
 	g_card_node_array[id] = chip_info;
 	chip_info->func_num++;
 
@@ -801,6 +819,7 @@ int dbgtool_knl_init(void *vhwdev, void *chip_node)
 	unregister_chrdev_region(dbgtool_dev_id, 1);
 alloc_chdev_fail:
 	g_card_node_array[id] = NULL;
+sscanf_chdev_fail:
 	kfree(dbgtool_info->ffm);
 dbgtool_info_ffm_fail:
 	kfree(dbgtool_info);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c
index 1f04615..86e499d 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c
@@ -1329,6 +1329,31 @@ static bool __is_func_valid(struct hinic_pcidev *dev)
 	return true;
 }
 
+bool hinic_is_valid_bar_addr(u64 offset)
+{
+	struct card_node *chip_node = NULL;
+	struct hinic_pcidev *dev;
+
+	lld_dev_hold();
+	list_for_each_entry(chip_node, &g_hinic_chip_list, node) {
+		list_for_each_entry(dev, &chip_node->func_list, node) {
+			if (hinic_func_type(dev->hwdev) == TYPE_VF)
+				continue;
+
+			if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag))
+				continue;
+
+			if (offset == pci_resource_start(dev->pcidev, 0)) {
+				lld_dev_put();
+				return true;
+			}
+		}
+	}
+	lld_dev_put();
+
+	return false;
+}
+
 void hinic_get_card_info(void *hwdev, void *bufin)
 {
 	struct card_node *chip_node = NULL;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.h b/drivers/net/ethernet/huawei/hinic/hinic_lld.h
index 004e96f..deaeb95 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_lld.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.h
@@ -117,4 +117,5 @@ int hinic_get_chip_cos_up_map(struct pci_dev *pdev, bool *is_setted,
 
 struct pci_device_id *hinic_get_pci_device_id(struct pci_dev *pdev);
 bool hinic_is_in_host(void);
+bool hinic_is_valid_bar_addr(u64 offset);
 #endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
index fc34ecf..8524c45 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h
@@ -30,7 +30,7 @@
 #define HINIC_DRV_NAME		"hinic"
 #define HINIC_CHIP_NAME		"hinic"
 
-#define HINIC_DRV_VERSION	"1.8.2.8"
+#define HINIC_DRV_VERSION	"1.8.3.1"
 struct vf_data_storage;
 
 #define HINIC_FUNC_IS_VF(hwdev)	(hinic_func_type(hwdev) == TYPE_VF)
-- 
1.8.3.1

