From: Luoyouming luoyouming@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8HYV0
--------------------------------------------------------------------------
After the user sets the sl value, the driver does not verify the sl value, which may result in the user's configuration value exceeding the system configuration specifications. This patch adds validation for the validity of the user-configured sl value.
Fixes: 11ef2ec6aa7c ("RDMA/hns: Support DSCP of userspace") Signed-off-by: Luoyouming luoyouming@huawei.com --- drivers/infiniband/hw/hns/hns_roce_ah.c | 9 +++++++++ drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 10 ++++++---- 2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c index f4ceaeba5601..03a714243c57 100644 --- a/drivers/infiniband/hw/hns/hns_roce_ah.c +++ b/drivers/infiniband/hw/hns/hns_roce_ah.c @@ -62,6 +62,7 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, struct hns_roce_ah *ah = to_hr_ah(ibah); u8 priority = 0; u8 tc_mode = 0; + u32 sl_num; int ret;
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata) @@ -92,6 +93,14 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, else ah->av.sl = rdma_ah_get_sl(ah_attr);
+ sl_num = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1); + if (unlikely(ah->av.sl > sl_num)) { + ibdev_err_ratelimited(&hr_dev->ib_dev, + "failed to set sl, sl (%u) shouldn't be larger than %u.\n", + ah->av.sl, sl_num); + return -EINVAL; + } + memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE); memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 350b824431e6..c84d44707a35 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -5245,6 +5245,7 @@ static int hns_roce_set_sl(struct ib_qp *ibqp, struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); struct ib_device *ibdev = &hr_dev->ib_dev; + u32 sl_num; int ret;
ret = hns_roce_hw_v2_get_dscp(hr_dev, get_tclass(&attr->ah_attr.grh), @@ -5261,10 +5262,11 @@ static int hns_roce_set_sl(struct ib_qp *ibqp, else hr_qp->sl = rdma_ah_get_sl(&attr->ah_attr);
- if (unlikely(hr_qp->sl > MAX_SERVICE_LEVEL)) { - ibdev_err(ibdev, - "failed to fill QPC, sl (%u) shouldn't be larger than %d.\n", - hr_qp->sl, MAX_SERVICE_LEVEL); + sl_num = min_t(u32, MAX_SERVICE_LEVEL, hr_dev->caps.sl_num - 1); + if (unlikely(hr_qp->sl > sl_num)) { + ibdev_err_ratelimited(ibdev, + "failed to fill QPC, sl (%u) shouldn't be larger than %u.\n", + hr_qp->sl, sl_num); return -EINVAL; }