From: Xiaoguang Wang Date: Fri, 11 Mar 2022 13:22:05 +0000 (+0800) Subject: scsi: target: tcmu: Fix possible page UAF X-Git-Tag: v4.14.276~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7c5d79e50be6e06b669141e3db1f977a0dd4e8e;p=thirdparty%2Fkernel%2Fstable.git scsi: target: tcmu: Fix possible page UAF [ Upstream commit a6968f7a367f128d120447360734344d5a3d5336 ] tcmu_try_get_data_page() looks up pages under cmdr_lock, but it does not take refcount properly and just returns page pointer. When tcmu_try_get_data_page() returns, the returned page may have been freed by tcmu_blocks_release(). We need to get_page() under cmdr_lock to avoid concurrent tcmu_blocks_release(). Link: https://lore.kernel.org/r/20220311132206.24515-1-xiaoguang.wang@linux.alibaba.com Reviewed-by: Bodo Stroesser Signed-off-by: Xiaoguang Wang Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 96601fda47b18..f687481ccfdc7 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -1165,6 +1165,7 @@ static struct page *tcmu_try_get_block_page(struct tcmu_dev *udev, uint32_t dbi) mutex_lock(&udev->cmdr_lock); page = tcmu_get_block_page(udev, dbi); if (likely(page)) { + get_page(page); mutex_unlock(&udev->cmdr_lock); return page; } @@ -1233,6 +1234,7 @@ static int tcmu_vma_fault(struct vm_fault *vmf) /* For the vmalloc()ed cmd area pages */ addr = (void *)(unsigned long)info->mem[mi].addr + offset; page = vmalloc_to_page(addr); + get_page(page); } else { uint32_t dbi; @@ -1243,7 +1245,6 @@ static int tcmu_vma_fault(struct vm_fault *vmf) return VM_FAULT_NOPAGE; } - get_page(page); vmf->page = page; return 0; }