Skip to content

Commit 2ed3814

Browse files
shirazsaleemjgunthorpe
authored andcommitted
RDMA/i40iw: Address an mmap handler exploit in i40iw
i40iw_mmap manipulates the vma->vm_pgoff to differentiate a push page mmap vs a doorbell mmap, and uses it to compute the pfn in remap_pfn_range without any validation. This is vulnerable to an mmap exploit as described in: https://lore.kernel.org/r/20201119093523.7588-1-zhudi21@huawei.com The push feature is disabled in the driver currently and therefore no push mmaps are issued from user-space. The feature does not work as expected in the x722 product. Remove the push module parameter and all VMA attribute manipulations for this feature in i40iw_mmap. Update i40iw_mmap to only allow DB user mmapings at offset = 0. Check vm_pgoff for zero and if the mmaps are bound to a single page. Cc: <stable@kernel.org> Fixes: d374984 ("i40iw: add files for iwarp interface") Link: https://lore.kernel.org/r/20201125005616.1800-2-shiraz.saleem@intel.com Reported-by: Di Zhu <zhudi21@huawei.com> Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 6830ff8 commit 2ed3814

2 files changed

Lines changed: 7 additions & 35 deletions

File tree

drivers/infiniband/hw/i40iw/i40iw_main.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@
5454
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
5555
__stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD)
5656

57-
static int push_mode;
58-
module_param(push_mode, int, 0644);
59-
MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)");
60-
6157
static int debug;
6258
module_param(debug, int, 0644);
6359
MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all");
@@ -1580,7 +1576,6 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl,
15801576
if (status)
15811577
goto exit;
15821578
iwdev->obj_next = iwdev->obj_mem;
1583-
iwdev->push_mode = push_mode;
15841579

15851580
init_waitqueue_head(&iwdev->vchnl_waitq);
15861581
init_waitqueue_head(&dev->vf_reqs);

drivers/infiniband/hw/i40iw/i40iw_verbs.c

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -167,39 +167,16 @@ static void i40iw_dealloc_ucontext(struct ib_ucontext *context)
167167
*/
168168
static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
169169
{
170-
struct i40iw_ucontext *ucontext;
171-
u64 db_addr_offset, push_offset, pfn;
172-
173-
ucontext = to_ucontext(context);
174-
if (ucontext->iwdev->sc_dev.is_pf) {
175-
db_addr_offset = I40IW_DB_ADDR_OFFSET;
176-
push_offset = I40IW_PUSH_OFFSET;
177-
if (vma->vm_pgoff)
178-
vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1;
179-
} else {
180-
db_addr_offset = I40IW_VF_DB_ADDR_OFFSET;
181-
push_offset = I40IW_VF_PUSH_OFFSET;
182-
if (vma->vm_pgoff)
183-
vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1;
184-
}
170+
struct i40iw_ucontext *ucontext = to_ucontext(context);
171+
u64 dbaddr;
185172

186-
vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT;
187-
188-
if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) {
189-
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
190-
} else {
191-
if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2)
192-
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
193-
else
194-
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
195-
}
173+
if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE)
174+
return -EINVAL;
196175

197-
pfn = vma->vm_pgoff +
198-
(pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >>
199-
PAGE_SHIFT);
176+
dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0);
200177

201-
return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
202-
vma->vm_page_prot, NULL);
178+
return rdma_user_mmap_io(context, vma, dbaddr >> PAGE_SHIFT, PAGE_SIZE,
179+
pgprot_noncached(vma->vm_page_prot), NULL);
203180
}
204181

205182
/**

0 commit comments

Comments
 (0)