net: hns3: remediate a potential overflow risk of bd_num_list
authorGuangbin Huang <huangguangbin2@huawei.com>
Mon, 29 Mar 2021 03:57:47 +0000 (11:57 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 May 2021 08:12:54 +0000 (10:12 +0200)
[ Upstream commit a2ee6fd28a190588e142ad8ea9d40069cd3c9f98 ]

The array size of bd_num_list is a fixed value, it may have potential
overflow risk when array size of hclge_dfx_bd_offset_list is greater
than that fixed value. So modify bd_num_list as a pointer and allocate
memory for it according to array size of hclge_dfx_bd_offset_list.

Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

index b856dbe..98190aa 100644 (file)
@@ -10845,7 +10845,6 @@ static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
 #define REG_LEN_PER_LINE       (REG_NUM_PER_LINE * sizeof(u32))
 #define REG_SEPARATOR_LINE     1
 #define REG_NUM_REMAIN_MASK    3
-#define BD_LIST_MAX_NUM                30
 
 int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc)
 {
@@ -10939,15 +10938,19 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
 {
        u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
        int data_len_per_desc, bd_num, i;
-       int bd_num_list[BD_LIST_MAX_NUM];
+       int *bd_num_list;
        u32 data_len;
        int ret;
 
+       bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
+       if (!bd_num_list)
+               return -ENOMEM;
+
        ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
        if (ret) {
                dev_err(&hdev->pdev->dev,
                        "Get dfx reg bd num fail, status is %d.\n", ret);
-               return ret;
+               goto out;
        }
 
        data_len_per_desc = sizeof_field(struct hclge_desc, data);
@@ -10958,6 +10961,8 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
                *len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE;
        }
 
+out:
+       kfree(bd_num_list);
        return ret;
 }
 
@@ -10965,16 +10970,20 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
 {
        u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
        int bd_num, bd_num_max, buf_len, i;
-       int bd_num_list[BD_LIST_MAX_NUM];
        struct hclge_desc *desc_src;
+       int *bd_num_list;
        u32 *reg = data;
        int ret;
 
+       bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
+       if (!bd_num_list)
+               return -ENOMEM;
+
        ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
        if (ret) {
                dev_err(&hdev->pdev->dev,
                        "Get dfx reg bd num fail, status is %d.\n", ret);
-               return ret;
+               goto out;
        }
 
        bd_num_max = bd_num_list[0];
@@ -10983,8 +10992,10 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
 
        buf_len = sizeof(*desc_src) * bd_num_max;
        desc_src = kzalloc(buf_len, GFP_KERNEL);
-       if (!desc_src)
-               return -ENOMEM;
+       if (!desc_src) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        for (i = 0; i < dfx_reg_type_num; i++) {
                bd_num = bd_num_list[i];
@@ -11000,6 +11011,8 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
        }
 
        kfree(desc_src);
+out:
+       kfree(bd_num_list);
        return ret;
 }