From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I4XF98 CVE: NA
-----------------------------------------------------------------------
The hinic driver currently generates a NULL pointer dereference when performing the hinicadm tool command during device probe. This is because the hinicadm process accesses the NULL hwif pointer in the hwdev which have not been allocated in probe.
Fix this by checking the initialization state of device before accessing it.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Wangxiaoyun cloud.wangxiaoyun@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_lld.c | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index bea0c7ef51e8..9d39da0c76d4 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -801,8 +801,7 @@ static bool __is_pcidev_match_chip_name(const char *ifname, if (dev->init_state < HINIC_INIT_STATE_HW_PART_INITED) return false; } else { - if (dev->init_state >= - HINIC_INIT_STATE_HW_PART_INITED && + if (dev->init_state < HINIC_INIT_STATE_HW_PART_INITED || hinic_func_type(dev->hwdev) != type) return false; } @@ -1153,6 +1152,10 @@ void *hinic_get_ppf_hwdev_by_pdev(struct pci_dev *pdev) chip_node = pci_adapter->chip_node; lld_dev_hold(); list_for_each_entry(dev, &chip_node->func_list, node) { + if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag) || + dev->init_state < HINIC_INIT_STATE_HW_IF_INITED) + continue; + if (dev->hwdev && hinic_func_type(dev->hwdev) == TYPE_PPF) { lld_dev_put(); return dev->hwdev; @@ -1365,6 +1368,10 @@ int hinic_get_pf_id(void *hwdev, u32 port_id, u32 *pf_id, u32 *isvalid)
lld_dev_hold(); list_for_each_entry(dev, &chip_node->func_list, node) { + if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag) || + dev->init_state < HINIC_INIT_STATE_HWDEV_INITED) + continue; + if (hinic_physical_port_id(dev->hwdev) == port_id) { *pf_id = hinic_global_func_id(dev->hwdev); *isvalid = 1; @@ -1852,7 +1859,8 @@ static void send_event_to_all_pf(struct hinic_pcidev *dev,
lld_dev_hold(); list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { - if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag)) + if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag) || + des_dev->init_state < HINIC_INIT_STATE_HW_IF_INITED) continue;
if (hinic_func_type(des_dev->hwdev) == TYPE_VF) @@ -1870,7 +1878,8 @@ static void send_event_to_dst_pf(struct hinic_pcidev *dev, u16 func_id,
lld_dev_hold(); list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { - if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag)) + if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag) || + des_dev->init_state < HINIC_INIT_STATE_HW_IF_INITED) continue;
if (hinic_func_type(des_dev->hwdev) == TYPE_VF) @@ -2637,8 +2646,11 @@ static void slave_host_init_delay_work(struct work_struct *work) /* Make sure the PPF must be the first one */ lld_dev_hold(); list_for_each_entry(ppf_pcidev, &chip_node->func_list, node) { - if (ppf_pcidev && - hinic_func_type(ppf_pcidev->hwdev) == TYPE_PPF) { + if (test_bit(HINIC_FUNC_IN_REMOVE, &ppf_pcidev->flag) || + ppf_pcidev->init_state < HINIC_INIT_STATE_HW_IF_INITED) + continue; + + if (hinic_func_type(ppf_pcidev->hwdev) == TYPE_PPF) { found = 1; break; } @@ -2872,7 +2884,8 @@ int hinic_register_micro_log(struct hinic_micro_log_info *micro_log_info) 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 (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag)) + if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag) || + dev->init_state < HINIC_INIT_STATE_HW_IF_INITED) continue;
if (hinic_func_type(dev->hwdev) == TYPE_PPF) { @@ -2902,7 +2915,8 @@ void hinic_unregister_micro_log(struct hinic_micro_log_info *micro_log_info) 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 (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag)) + if (test_bit(HINIC_FUNC_IN_REMOVE, &dev->flag) || + dev->init_state < HINIC_INIT_STATE_HW_IF_INITED) continue;
if (hinic_func_type(dev->hwdev) == TYPE_PPF)