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>
116 lines
3.8 KiB
Diff
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
|
|
|