In 64-bit lo_ioctl(), commit 7035b5df3c07 ("loop: cleanup set_status interface") added a check requiring (mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN) (now BLK_OPEN_WRITE) before allowing LOOP_SET_STATUS or LOOP_SET_STATUS64, but the corresponding check was omitted from 32-bit lo_compat_ioctl(). As a result, on kernels with CONFIG_COMPAT=y, an unprivileged process holding a read-only (O_RDONLY) file descriptor to an active /dev/loopN device can issue a 32-bit compat LOOP_SET_STATUS ioctl to modify lo_offset, clear lo_sizelimit to 0 (exposing backing-file data past the configured limit), or alter lo_flags. Enforce the same (mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN) check on LOOP_SET_STATUS in lo_compat_ioctl(). Fixes: 7035b5df3c07 ("loop: cleanup set_status interface") Assisted-by: ARTIST LLM Signed-off-by: Dominik Maier --- drivers/block/loop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 758c20678bf6..f15a5cae5c63 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1708,8 +1708,10 @@ static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode, switch(cmd) { case LOOP_SET_STATUS: - err = loop_set_status_compat(lo, - (const struct compat_loop_info __user *)arg); + err = -EPERM; + if ((mode & BLK_OPEN_WRITE) || capable(CAP_SYS_ADMIN)) + err = loop_set_status_compat(lo, + (const struct compat_loop_info __user *)arg); break; case LOOP_GET_STATUS: err = loop_get_status_compat(lo, -- 2.56.0.218.g1ec904b173-goog