summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKanishka De Silva <kpskanna1915@gmail.com>2026-08-30 12:31:33 +0530
committerJens Axboe <axboe@kernel.dk>2026-09-01 08:44:03 -0600
commit6e2b571b0a54755b06e092501913e1dfefe75d6c (patch)
tree1cdb52413ccb52334f57c8654d01ff17157fee42
parente52349a5ea6a74d46dfb703fcb64e08b5af28e8c (diff)
downloadlinux-6e2b571b0a54755b06e092501913e1dfefe75d6c.tar.gz
linux-6e2b571b0a54755b06e092501913e1dfefe75d6c.zip
ublk: clear VM_MAYWRITE on read-only ublk char device mmap
ublk_ch_mmap() rejects mmap requests with VM_WRITE set, but never clears VM_MAYWRITE on the resulting read-only mapping. This allows a userspace daemon to mmap the per-queue command buffer PROT_READ, then upgrade it to PROT_WRITE via mprotect(), since VM_MAYWRITE was never cleared. The command buffer holds struct ublksrv_io_desc entries that are kernel-written ABI; a writable mapping lets an unprivileged daemon process corrupt fields such as addr, op_flags, nr_sectors, and start_sector. Same bug class as the drm/panthor and drm/vc4 VM_MAYWRITE fixes, and the 2026-08-13 ptp/vmclock fix (a5edadbae57e). Verified via mprotect() PoC: before the fix, a PROT_READ mapping can be upgraded to PROT_READ|PROT_WRITE and a write into the command buffer corrupts io_desc fields (confirmed under KASAN). After the fix, mprotect() returns -EACCES. Fixes: 3fee8d7599e1 ("ublk_drv: add io_uring based userspace block driver") Cc: stable@vger.kernel.org Signed-off-by: Kanishka De Silva <kpskanna1915@gmail.com> Reviewed-by: Ming Lei <tom.leiming@gmail.com> Link: https://patch.msgid.link/20260830070133.559-1-kpskanna1915@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/ublk_drv.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 6c5bec7da97c..e5ba07d8d281 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -2653,6 +2653,12 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
if (vma->vm_flags & VM_WRITE)
return -EPERM;
+ /*
+ * The per-queue command buffer is kernel-written ABI; prevent
+ * the daemon from upgrading to writable via mprotect().
+ */
+ vm_flags_clear(vma, VM_MAYWRITE);
+
end = UBLKSRV_CMD_BUF_OFFSET + ub->dev_info.nr_hw_queues * max_sz;
if (phys_off < UBLKSRV_CMD_BUF_OFFSET || phys_off >= end)
return -EINVAL;