Commit 991fd7d3 authored by Junxian Huang's avatar Junxian Huang Committed by Juan Zhou
Browse files

RDMA/hns: Fix several memory issues in roce bonding

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: e62a2027 ("RDMA/hns: support RoCE bonding")
Fixes: 82ee5d30 ("RDMA/hns: Apply XArray for Bond ID allocation")
Fixes: b927e306 ("RDMA/hns: Fix the concurrency error between bond and reset.")
Signed-off-by: default avatarJunxian Huang <huangjunxian6@hisilicon.com>
parent b133b21f
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -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;
}
+11 −1
Original line number Diff line number Diff line
@@ -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);