From 067d563e142500386de1dceff3a8cb9773daf48f Mon Sep 17 00:00:00 2001
From: Anders Roxell <anders.roxell@linaro.org>
Date: Wed, 9 Jul 2025 19:06:33 +0200
Subject: [PATCH] block: fix ioctl collision between FS_IOC_GETLBMD_CAP and
 LOOP_SET_STATUS

Commit 9eb22f7fedfc ("fs: add ioctl to query metadata and protection
info capabilities") introduced a check in blkdev_common_ioctl() that
incorrectly intercepts other ioctls:

    if (_IOC_NR(cmd) == _IOC_NR(FS_IOC_GETLBMD_CAP))
        return blk_get_meta_cap(bdev, cmd, argp);

This check only compares the command number (_IOC_NR), not the full
ioctl command. Since both FS_IOC_GETLBMD_CAP (0x1502) and
LOOP_SET_STATUS (0x4C02) have command number 2, the check incorrectly
intercepts LOOP_SET_STATUS and routes it to blk_get_meta_cap(), which
returns -EINVAL.

This caused LTP tests like chdir01 to fail with:
    ioctl(/dev/loop0, LOOP_SET_STATUS, ...) failed: EINVAL (22)

Fix by properly handling FS_IOC_GETLBMD_CAP in the switch statement
instead of using a separate _IOC_NR comparison that matches unrelated
ioctls.

Fixes: 9eb22f7fedfc ("fs: add ioctl to query metadata and protection info capabilities")
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
---
 block/ioctl.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index 9ad403733e19..11dc842cff04 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -567,9 +567,6 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
 {
 	unsigned int max_sectors;
 
-	if (_IOC_NR(cmd) == _IOC_NR(FS_IOC_GETLBMD_CAP))
-		return blk_get_meta_cap(bdev, cmd, argp);
-
 	switch (cmd) {
 	case BLKFLSBUF:
 		return blkdev_flushbuf(bdev, cmd, arg);
@@ -635,6 +632,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
 	case BLKCRYPTOGENERATEKEY:
 	case BLKCRYPTOPREPAREKEY:
 		return blk_crypto_ioctl(bdev, cmd, argp);
+	case FS_IOC_GETLBMD_CAP:
+		return blk_get_meta_cap(bdev, cmd, argp);
 	case IOC_PR_REGISTER:
 		return blkdev_pr_register(bdev, mode, argp);
 	case IOC_PR_RESERVE:
-- 
2.47.2

