rdma-core/0038-libhns-Fix-out-of-bounds-write-when-filling-inline-d.patch
zhengfeng luo 123f94ea3f Backport batch of bugfix and refactor patches for hns from rdma-core v39
These patches are mainly related to IO operations.

Signed-off-by: zhengfeng luo <luozhengfeng@h-partners.com>
Signed-off-by: Chengchang Tang <tangchengchang@huawei.com>
2022-08-29 21:05:49 +08:00

116 lines
3.8 KiB
Diff

From 203675526b14d9556eeb4212536ebcfc81691c1b Mon Sep 17 00:00:00 2001
From: Wenpeng Liang <liangwenpeng@huawei.com>
Date: Mon, 17 Jan 2022 20:43:38 +0800
Subject: libhns: Fix out-of-bounds write when filling inline data into
extended sge space
If the buf to store inline data is in the last page of the extended sge
space, filling the entire inline data into the extended sge space at one
time may result in out-of-bounds writing.
When the remaining space at the end of the extended sge is not enough to
accommodate the entire inline data, the inline data needs to be filled
into the extended sge space in two steps:
(1) The front part of the inline data is filled into the remaining space
at the end of the extended sge.
(2) The remaining inline data is filled into the header space of the
extended sge.
Fixes: b7814b7b9715("libhns: Support inline data in extented sge space for RC")
Signed-off-by: Wenpeng Liang <liangwenpeng@huawei.com>
---
providers/hns/hns_roce_u_hw_v2.c | 40 ++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/providers/hns/hns_roce_u_hw_v2.c b/providers/hns/hns_roce_u_hw_v2.c
index e39ee7f..20745dc 100644
--- a/providers/hns/hns_roce_u_hw_v2.c
+++ b/providers/hns/hns_roce_u_hw_v2.c
@@ -772,21 +772,43 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp,
struct hns_roce_sge_info *sge_info)
{
unsigned int sge_sz = sizeof(struct hns_roce_v2_wqe_data_seg);
- void *dseg;
+ unsigned int sge_mask = qp->ex_sge.sge_cnt - 1;
+ void *dst_addr, *src_addr, *tail_bound_addr;
+ uint32_t src_len, tail_len;
int i;
+
if (sge_info->total_len > qp->sq.max_gs * sge_sz)
return EINVAL;
- dseg = get_send_sge_ex(qp, sge_info->start_idx);
+ dst_addr = get_send_sge_ex(qp, sge_info->start_idx & sge_mask);
+ tail_bound_addr = get_send_sge_ex(qp, qp->ex_sge.sge_cnt & sge_mask);
for (i = 0; i < wr->num_sge; i++) {
- memcpy(dseg, (void *)(uintptr_t)wr->sg_list[i].addr,
- wr->sg_list[i].length);
- dseg += wr->sg_list[i].length;
+ tail_len = (uintptr_t)tail_bound_addr - (uintptr_t)dst_addr;
+
+ src_addr = (void *)(uintptr_t)wr->sg_list[i].addr;
+ src_len = wr->sg_list[i].length;
+
+ if (src_len < tail_len) {
+ memcpy(dst_addr, src_addr, src_len);
+ dst_addr += src_len;
+ } else if (src_len == tail_len) {
+ memcpy(dst_addr, src_addr, src_len);
+ dst_addr = get_send_sge_ex(qp, 0);
+ } else {
+ memcpy(dst_addr, src_addr, tail_len);
+ dst_addr = get_send_sge_ex(qp, 0);
+ src_addr += tail_len;
+ src_len -= tail_len;
+
+ memcpy(dst_addr, src_addr, src_len);
+ dst_addr += src_len;
+ }
}
- sge_info->start_idx += DIV_ROUND_UP(sge_info->total_len, sge_sz);
+ sge_info->valid_num = DIV_ROUND_UP(sge_info->total_len, sge_sz);
+ sge_info->start_idx += sge_info->valid_num;
return 0;
}
@@ -828,7 +850,6 @@ static int set_ud_inl(struct hns_roce_qp *qp, const struct ibv_send_wr *wr,
struct hns_roce_ud_sq_wqe *ud_sq_wqe,
struct hns_roce_sge_info *sge_info)
{
- unsigned int sge_idx = sge_info->start_idx;
int ret;
if (!check_inl_data_len(qp, sge_info->total_len))
@@ -845,8 +866,6 @@ static int set_ud_inl(struct hns_roce_qp *qp, const struct ibv_send_wr *wr,
if (ret)
return ret;
- sge_info->valid_num = sge_info->start_idx - sge_idx;
-
hr_reg_write(ud_sq_wqe, UDWQE_SGE_NUM, sge_info->valid_num);
}
@@ -969,7 +988,6 @@ static int set_rc_inl(struct hns_roce_qp *qp, const struct ibv_send_wr *wr,
struct hns_roce_rc_sq_wqe *rc_sq_wqe,
struct hns_roce_sge_info *sge_info)
{
- unsigned int sge_idx = sge_info->start_idx;
void *dseg = rc_sq_wqe;
int ret;
int i;
@@ -997,8 +1015,6 @@ static int set_rc_inl(struct hns_roce_qp *qp, const struct ibv_send_wr *wr,
if (ret)
return ret;
- sge_info->valid_num = sge_info->start_idx - sge_idx;
-
hr_reg_write(rc_sq_wqe, RCWQE_SGE_NUM, sge_info->valid_num);
}
--
2.27.0