Commit 987b4ae7 authored by Weihang Li's avatar Weihang Li Committed by David S. Miller

net: hns3: add check to number of buffer descriptors

This patch adds check to number of bds before we allocate memory for
them. If we get an invalid bd num in some cases, it will cause a memory
overflow.
Signed-off-by: default avatarWeihang Li <liweihang@hisilicon.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9d5e67d1
...@@ -1060,6 +1060,52 @@ static int hclge_config_ssu_hw_err_int(struct hclge_dev *hdev, bool en) ...@@ -1060,6 +1060,52 @@ static int hclge_config_ssu_hw_err_int(struct hclge_dev *hdev, bool en)
return ret; return ret;
} }
/* hclge_query_bd_num: query number of buffer descriptors
* @hdev: pointer to struct hclge_dev
* @is_ras: true for ras, false for msix
* @mpf_bd_num: number of main PF interrupt buffer descriptors
* @pf_bd_num: number of not main PF interrupt buffer descriptors
*
* This function querys number of mpf and pf buffer descriptors.
*/
static int hclge_query_bd_num(struct hclge_dev *hdev, bool is_ras,
int *mpf_bd_num, int *pf_bd_num)
{
struct device *dev = &hdev->pdev->dev;
u32 mpf_min_bd_num, pf_min_bd_num;
enum hclge_opcode_type opcode;
struct hclge_desc desc_bd;
int ret;
if (is_ras) {
opcode = HCLGE_QUERY_RAS_INT_STS_BD_NUM;
mpf_min_bd_num = HCLGE_MPF_RAS_INT_MIN_BD_NUM;
pf_min_bd_num = HCLGE_PF_RAS_INT_MIN_BD_NUM;
} else {
opcode = HCLGE_QUERY_MSIX_INT_STS_BD_NUM;
mpf_min_bd_num = HCLGE_MPF_MSIX_INT_MIN_BD_NUM;
pf_min_bd_num = HCLGE_PF_MSIX_INT_MIN_BD_NUM;
}
hclge_cmd_setup_basic_desc(&desc_bd, opcode, true);
ret = hclge_cmd_send(&hdev->hw, &desc_bd, 1);
if (ret) {
dev_err(dev, "fail(%d) to query msix int status bd num\n",
ret);
return ret;
}
*mpf_bd_num = le32_to_cpu(desc_bd.data[0]);
*pf_bd_num = le32_to_cpu(desc_bd.data[1]);
if (*mpf_bd_num < mpf_min_bd_num || *pf_bd_num < pf_min_bd_num) {
dev_err(dev, "Invalid bd num: mpf(%d), pf(%d)\n",
*mpf_bd_num, *pf_bd_num);
return -EINVAL;
}
return 0;
}
/* hclge_handle_mpf_ras_error: handle all main PF RAS errors /* hclge_handle_mpf_ras_error: handle all main PF RAS errors
* @hdev: pointer to struct hclge_dev * @hdev: pointer to struct hclge_dev
* @desc: descriptor for describing the command * @desc: descriptor for describing the command
...@@ -1291,24 +1337,16 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev, ...@@ -1291,24 +1337,16 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev,
static int hclge_handle_all_ras_errors(struct hclge_dev *hdev) static int hclge_handle_all_ras_errors(struct hclge_dev *hdev)
{ {
struct device *dev = &hdev->pdev->dev;
u32 mpf_bd_num, pf_bd_num, bd_num; u32 mpf_bd_num, pf_bd_num, bd_num;
struct hclge_desc desc_bd;
struct hclge_desc *desc; struct hclge_desc *desc;
int ret; int ret;
/* query the number of registers in the RAS int status */ /* query the number of registers in the RAS int status */
hclge_cmd_setup_basic_desc(&desc_bd, HCLGE_QUERY_RAS_INT_STS_BD_NUM, ret = hclge_query_bd_num(hdev, true, &mpf_bd_num, &pf_bd_num);
true); if (ret)
ret = hclge_cmd_send(&hdev->hw, &desc_bd, 1);
if (ret) {
dev_err(dev, "fail(%d) to query ras int status bd num\n", ret);
return ret; return ret;
}
mpf_bd_num = le32_to_cpu(desc_bd.data[0]);
pf_bd_num = le32_to_cpu(desc_bd.data[1]);
bd_num = max_t(u32, mpf_bd_num, pf_bd_num);
bd_num = max_t(u32, mpf_bd_num, pf_bd_num);
desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc) if (!desc)
return -ENOMEM; return -ENOMEM;
...@@ -1844,25 +1882,16 @@ static int hclge_handle_all_hw_msix_error(struct hclge_dev *hdev, ...@@ -1844,25 +1882,16 @@ static int hclge_handle_all_hw_msix_error(struct hclge_dev *hdev,
struct hclge_mac_tnl_stats mac_tnl_stats; struct hclge_mac_tnl_stats mac_tnl_stats;
struct device *dev = &hdev->pdev->dev; struct device *dev = &hdev->pdev->dev;
u32 mpf_bd_num, pf_bd_num, bd_num; u32 mpf_bd_num, pf_bd_num, bd_num;
struct hclge_desc desc_bd;
struct hclge_desc *desc; struct hclge_desc *desc;
u32 status; u32 status;
int ret; int ret;
/* query the number of bds for the MSIx int status */ /* query the number of bds for the MSIx int status */
hclge_cmd_setup_basic_desc(&desc_bd, HCLGE_QUERY_MSIX_INT_STS_BD_NUM, ret = hclge_query_bd_num(hdev, false, &mpf_bd_num, &pf_bd_num);
true); if (ret)
ret = hclge_cmd_send(&hdev->hw, &desc_bd, 1);
if (ret) {
dev_err(dev, "fail(%d) to query msix int status bd num\n",
ret);
goto out; goto out;
}
mpf_bd_num = le32_to_cpu(desc_bd.data[0]);
pf_bd_num = le32_to_cpu(desc_bd.data[1]);
bd_num = max_t(u32, mpf_bd_num, pf_bd_num); bd_num = max_t(u32, mpf_bd_num, pf_bd_num);
desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc) { if (!desc) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1930,7 +1959,6 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) ...@@ -1930,7 +1959,6 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev)
struct hclge_dev *hdev = ae_dev->priv; struct hclge_dev *hdev = ae_dev->priv;
struct device *dev = &hdev->pdev->dev; struct device *dev = &hdev->pdev->dev;
u32 mpf_bd_num, pf_bd_num, bd_num; u32 mpf_bd_num, pf_bd_num, bd_num;
struct hclge_desc desc_bd;
struct hclge_desc *desc; struct hclge_desc *desc;
u32 status; u32 status;
int ret; int ret;
...@@ -1939,19 +1967,11 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev) ...@@ -1939,19 +1967,11 @@ void hclge_handle_all_hns_hw_errors(struct hnae3_ae_dev *ae_dev)
status = hclge_read_dev(&hdev->hw, HCLGE_RAS_PF_OTHER_INT_STS_REG); status = hclge_read_dev(&hdev->hw, HCLGE_RAS_PF_OTHER_INT_STS_REG);
/* query the number of bds for the MSIx int status */ /* query the number of bds for the MSIx int status */
hclge_cmd_setup_basic_desc(&desc_bd, HCLGE_QUERY_MSIX_INT_STS_BD_NUM, ret = hclge_query_bd_num(hdev, false, &mpf_bd_num, &pf_bd_num);
true); if (ret)
ret = hclge_cmd_send(&hdev->hw, &desc_bd, 1);
if (ret) {
dev_err(dev, "fail(%d) to query msix int status bd num\n",
ret);
return; return;
}
mpf_bd_num = le32_to_cpu(desc_bd.data[0]);
pf_bd_num = le32_to_cpu(desc_bd.data[1]);
bd_num = max_t(u32, mpf_bd_num, pf_bd_num); bd_num = max_t(u32, mpf_bd_num, pf_bd_num);
desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL); desc = kcalloc(bd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc) if (!desc)
return; return;
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
#include "hclge_main.h" #include "hclge_main.h"
#define HCLGE_MPF_RAS_INT_MIN_BD_NUM 10
#define HCLGE_PF_RAS_INT_MIN_BD_NUM 4
#define HCLGE_MPF_MSIX_INT_MIN_BD_NUM 10
#define HCLGE_PF_MSIX_INT_MIN_BD_NUM 4
#define HCLGE_RAS_PF_OTHER_INT_STS_REG 0x20B00 #define HCLGE_RAS_PF_OTHER_INT_STS_REG 0x20B00
#define HCLGE_RAS_REG_NFE_MASK 0xFF00 #define HCLGE_RAS_REG_NFE_MASK 0xFF00
#define HCLGE_RAS_REG_ROCEE_ERR_MASK 0x3000000 #define HCLGE_RAS_REG_ROCEE_ERR_MASK 0x3000000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment