driver inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/rdma-core/issues/I83L7U
----------------------------------------------------------
Currently, the mapping relationship of reset page between kernel mode and user mode is maintained by driver. If the driver is hot-plugged (e.g. reset), the memory of the reset page is released by kernel driver, but the reset page in user mode still points to this released address which would lead to a UAF.
This patch use the helper rdma_user_mmap_io() to maintain the vma mapping, rather than driver itself, which remmaps the userspace reset page to an safe zero page if driver was hot-plugged.
Fixes: e8b1fec497a0 ("RDMA/hns: Kernel notify usr space to stop ring db") Signed-off-by: Chengchang Tang tangchengchang@huawei.com --- drivers/infiniband/hw/hns/hns_roce_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 4a16200ab950..2f0a5b2bbc50 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -675,10 +675,9 @@ static int hns_roce_mmap(struct ib_ucontext *uctx, struct vm_area_struct *vma) goto out; }
- ret = remap_pfn_range(vma, vma->vm_start, - page_to_pfn(hr_dev->reset_page), - PAGE_SIZE, vma->vm_page_prot); - goto out; + prot = vma->vm_page_prot; + pfn = page_to_pfn(hr_dev->reset_page); + break; default: ret = -EINVAL; goto out;
driver inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/rdma-core/issues/I83L7U
----------------------------------------------------------
Currently, the driver notifies user mode whether a reset has occurred through setting a shared variable to non-zero value. However, if the user fails to obtain this variable in time, the notification will be lost because this variable will be clear after completes the reset.
This patch adds a new reset variable to ensure that the user mode can obtain whether the driver has been reset at any time. A non-zero value will be assigned to this variable, which will permanently become 0 once a reset occurs. During reset, the driver will assign 0 to this variable. After reset, this variable will be remapped to a page of all zeros. The userspace driver can judge whether the driver has been reset by whether this variable is 0.
Fixes: e8b1fec497a0 ("RDMA/hns: Kernel notify usr space to stop ring db") Signed-off-by: Chengchang Tang tangchengchang@huawei.com --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 ++++++ drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index e905d26bb3e5..63715443bd7d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -2740,6 +2740,8 @@ static void free_dip_list(struct hns_roce_dev *hr_dev)
static int hns_roce_v2_get_reset_page(struct hns_roce_dev *hr_dev) { + struct hns_roce_v2_reset_state *state; + hr_dev->reset_page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (!hr_dev->reset_page) return -ENOMEM; @@ -2748,6 +2750,9 @@ static int hns_roce_v2_get_reset_page(struct hns_roce_dev *hr_dev) if (!hr_dev->reset_kaddr) goto err_with_vmap;
+ state = hr_dev->reset_kaddr; + state->hw_ready = ~state->hw_ready; + return 0;
err_with_vmap: @@ -7425,6 +7430,7 @@ static void hns_roce_v2_reset_notify_user(struct hns_roce_dev *hr_dev) state = (struct hns_roce_v2_reset_state *)hr_dev->reset_kaddr;
state->reset_state = HNS_ROCE_IS_RESETTING; + state->hw_ready = 0; /* Ensure reset state was flushed in memory */ wmb(); } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index ad1f5771974f..6db94c0a5f1c 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -1313,6 +1313,7 @@ struct hns_roce_link_table {
struct hns_roce_v2_reset_state { u32 reset_state; /* stored to use in user space */ + u32 hw_ready; };
struct hns_roce_v2_free_mr {