From: Junxian Huang huangjunxian6@hisilicon.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6GT7F
--------------------------------------------------------------------------
Fix several memory issues in roce bonding: 1. When bond init failed, an error code is returned without device being unregistered. 2. In the abnormal situation where hr_dev may be NULL, the printing in hns_roce_clear_bond() will cause a kernel panic. 3. Though unlikely, there is a time gap between free(die_info) and xa_erase(). This may lead to a potential UAF.
Fixes: e62a20278f18 ("RDMA/hns: support RoCE bonding") Fixes: 82ee5d30a22d ("RDMA/hns: Apply XArray for Bond ID allocation") Fixes: b927e3066992 ("RDMA/hns: Fix the concurrency error between bond and reset.") Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com --- drivers/infiniband/hw/hns/hns_roce_bond.c | 15 ++++++++++----- drivers/infiniband/hw/hns/hns_roce_main.c | 12 +++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c index f97166031a30..849e2388d181 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.c +++ b/drivers/infiniband/hw/hns/hns_roce_bond.c @@ -284,7 +284,8 @@ static void hns_roce_clear_bond(struct hns_roce_bond_group *bond_grp) out: ret = hns_roce_cleanup_bond(bond_grp); if (!ret) - ibdev_info(&hr_dev->ib_dev, "RoCE clear bond finished!\n"); + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE clear bond finished!\n"); }
static void hns_roce_slave_changestate(struct hns_roce_bond_group *bond_grp) @@ -558,6 +559,12 @@ static struct hns_roce_die_info *alloc_die_info(int bus_num) return die_info; }
+static void dealloc_die_info(struct hns_roce_die_info *die_info, u8 bus_num) +{ + xa_erase(&roce_bond_xa, bus_num); + kvfree(die_info); +} + static int alloc_bond_id(struct hns_roce_bond_group *bond_grp) { u8 bus_num = bond_grp->bus_num; @@ -599,10 +606,8 @@ static int remove_bond_id(int bus_num, u8 bond_id)
die_info->bond_id_mask &= ~BOND_ID(bond_id); die_info->bgrps[bond_id] = NULL; - if (!die_info->bond_id_mask) { - kfree(die_info); - xa_erase(&roce_bond_xa, bus_num); - } + if (!die_info->bond_id_mask) + dealloc_die_info(die_info, bus_num);
return 0; } diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 4eb18fb31726..9881e84782bd 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -1114,14 +1114,24 @@ static int hns_roce_register_device(struct hns_roce_dev *hr_dev)
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { ret = hr_dev->hw->bond_init(hr_dev); - if (ret) + if (ret) { dev_err(dev, "roce bond init failed, ret = %d\n", ret); + /* For non-bond devices, the failure of bond_init does + * not affect other functions. + */ + if (hr_dev->hw->bond_is_active(hr_dev)) + goto error_bond_init; + else + ret = 0; + } }
hr_dev->active = true;
return ret;
+error_bond_init: + unregister_netdevice_notifier(&iboe->nb); error_failed_setup_mtu_mac: ib_unregister_device(ib_dev);